/// <summary> /// Removes redundant points. Two points are redundant if they occupy the same hash grid cell. /// </summary> /// <param name="points">List of points to prune.</param> /// <param name="cellSize">Size of cells to determine redundancy.</param> public static void RemoveRedundantPoints(ref QuickList<Vector3> points, double cellSize) { var set = new QuickSet<Int3>(BufferPools<Int3>.Locking, BufferPools<int>.Locking, BufferPool.GetPoolIndex(points.Count)); for (int i = points.Count - 1; i >= 0; --i) { var element = points.Elements[i]; var cell = new Int3 { X = (int)Math.Floor(element.X / cellSize), Y = (int)Math.Floor(element.Y / cellSize), Z = (int)Math.Floor(element.Z / cellSize) }; if (set.Contains(cell)) { points.FastRemoveAt(i); } else { set.Add(cell); //TODO: Consider adding adjacent cells to guarantee that a point on the border between two cells will still detect the presence //of a point on the opposite side of that border. } } set.Dispose(); }
/// <summary> /// Removes redundant points. Two points are redundant if they occupy the same hash grid cell. /// </summary> /// <param name="points">List of points to prune.</param> /// <param name="cellSize">Size of cells to determine redundancy.</param> public static void RemoveRedundantPoints(ref QuickList <Vector3> points, double cellSize) { var set = new QuickSet <Int3>(BufferPools <Int3> .Locking, BufferPools <int> .Locking, BufferPool.GetPoolIndex(points.Count)); for (int i = points.Count - 1; i >= 0; --i) { var element = points.Elements[i]; var cell = new Int3 { X = (int)Math.Floor(element.X / cellSize), Y = (int)Math.Floor(element.Y / cellSize), Z = (int)Math.Floor(element.Z / cellSize) }; if (set.Contains(cell)) { points.FastRemoveAt(i); } else { set.Add(cell); //TODO: Consider adding adjacent cells to guarantee that a point on the border between two cells will still detect the presence //of a point on the opposite side of that border. } } set.Dispose(); }
internal IEnumerable <TElement> ResolveEnumerable <TElement>(Func <Type, string, ImplicitRegistration, object> resolve, string name) { TElement value; var set = new QuickSet <Type>(); int hash = typeof(TElement).GetHashCode(); // Iterate over hierarchy for (var container = this; null != container; container = container._parent) { // Skip to parent if no data if (null == container._metadata) { continue; } // Hold on to registries var registry = container._registry; // Get indexes and iterate over them var length = container._metadata.GetEntries <TElement>(hash, out int[] data); for (var i = 1; i < length; i++) { var index = data[i]; if (set.Add(registry.Entries[index].HashCode, registry.Entries[index].Key.Type)) { try { var registration = (ExplicitRegistration)registry.Entries[index].Value; value = (TElement)resolve(typeof(TElement), registry.Entries[index].Key.Name, registration); } catch (ArgumentException ex) when(ex.InnerException is TypeLoadException) { continue; } yield return(value); } } } // If nothing registered attempt to resolve the type if (0 == set.Count) { try { var registration = GetRegistration(typeof(TElement), name); value = (TElement)resolve(typeof(TElement), name, registration); } catch { yield break; } yield return(value); } }
public static void RasterizeTriangle(ref Vector3 a, ref Vector3 b, ref Vector3 c, float cellSize, ref Vector3 gridOrigin, BufferPool pool, ref QuickSet <Cell, Buffer <Cell>, Buffer <int>, CellComparer> cells) { var gridA = a - gridOrigin; var gridB = b - gridOrigin; var gridC = c - gridOrigin; //Compute the bounding box of the triangle. var max = Vector3.Max(Vector3.Max(gridA, gridB), gridC); var min = Vector3.Min(Vector3.Min(gridA, gridB), gridC); var epsilon = new Vector3(1e-5f); min -= epsilon; max += epsilon; //Discretize the bounding box. //All indices are positive, so we can just truncate. int startX, endX, startY, endY, startZ, endZ; float inverseCellSize = 1f / cellSize; startX = (int)Math.Floor(min.X * inverseCellSize); endX = (int)Math.Floor(max.X * inverseCellSize); startY = (int)Math.Floor(min.Y * inverseCellSize); endY = (int)Math.Floor(max.Y * inverseCellSize); startZ = (int)Math.Floor(min.Z * inverseCellSize); endZ = (int)Math.Floor(max.Z * inverseCellSize); //Test the triangle against each cell. var halfExtents = new Vector3(cellSize * 0.5f); var cellPool = pool.SpecializeFor <Cell>(); var tablePool = pool.SpecializeFor <int>(); for (int i = startX; i <= endX; ++i) { for (int j = startY; j <= endY; ++j) { for (int k = startZ; k <= endZ; ++k) { var cellIndex = new Vector3(i, j, k); var cellOrigin = cellSize * cellIndex + halfExtents; var shiftedA = gridA - cellOrigin; var shiftedB = gridB - cellOrigin; var shiftedC = gridC - cellOrigin; if (BoxTriangleCollider.Intersecting(ref halfExtents, ref shiftedA, ref shiftedB, ref shiftedC)) { cells.Add(new Cell { X = i, Y = j, Z = k }, cellPool, tablePool); } } } } }
internal IEnumerable <TElement> ComplexArray <TElement>(Func <Type, IRegistration, object?> resolve, Type type) { object?value; var set = new QuickSet(); var key = new HashKey(typeof(TElement)); var typeKey = new HashKey(type); // Iterate over hierarchy for (UnityContainer?container = this; null != container; container = container._parent) { // Skip to parent if no data if (null == container._metadata) { continue; } // Hold on to registries Debug.Assert(null != container._registry); var registry = container._registry; // Get indexes and iterate over them var length = container._metadata.GetMeta(ref typeKey, out int[]? data); if (null != data) { for (var i = 1; i < length; i++) { var index = data[i]; var registration = (ExplicitRegistration)registry.Entries[index].Policies; if (null != registration.Name && set.Add(registration.Name)) { try { var itemKey = new HashKey(typeof(TElement), registration.Name); var item = container.GetOrAdd(ref itemKey, typeof(TElement), registration.Name, registration); value = resolve(typeof(TElement), item); } catch (ArgumentException ex) when(ex.InnerException is TypeLoadException) { continue; } #pragma warning disable CS8601 // Possible null reference assignment. yield return((TElement)value); #pragma warning restore CS8601 // Possible null reference assignment. } } } } }
/// <summary> /// Identifies the points on the surface of hull. /// </summary> /// <param name="points">List of points in the set.</param> /// <param name="outputTriangleIndices">List of indices into the input point set composing the triangulated surface of the convex hull. /// Each group of 3 indices represents a triangle on the surface of the hull.</param> /// <param name="outputSurfacePoints">Unique points on the surface of the convex hull.</param> public static void GetConvexHull(ref QuickList <Vector3> points, ref QuickList <int> outputTriangleIndices, IList <Vector3> outputSurfacePoints) { GetConvexHull(ref points, ref outputTriangleIndices); var alreadyContainedIndices = new QuickSet <int>(BufferPools <int> .Locking, BufferPools <int> .Locking); for (int i = outputTriangleIndices.Count - 1; i >= 0; i--) { int index = outputTriangleIndices[i]; if (alreadyContainedIndices.Add(index)) { outputSurfacePoints.Add(points[index]); } } alreadyContainedIndices.Dispose(); }
internal IEnumerable <TElement> ComplexArray <TElement>(Func <Type, string, ImplicitRegistration, object> resolve, Type type) { TElement value; var set = new QuickSet <Type>(); int hashCode = type.GetHashCode(); // Iterate over hierarchy for (var container = this; null != container; container = container._parent) { // Skip to parent if no data if (null == container._metadata) { continue; } // Hold on to registries var registry = container._registry; // Get indexes and iterate over them var length = container._metadata.GetEntries(hashCode, type, out int[] data); for (var i = 1; i < length; i++) { var index = data[i]; var name = registry.Entries[index].Key.Name; if (null == name) { continue; } if (set.Add(registry.Entries[index].HashCode, registry.Entries[index].Key.Type)) { try { int hash = NamedType.GetHashCode(typeof(TElement), name); var registration = container.GetOrAdd(hash, typeof(TElement), name, registry.Entries[index].Value); value = (TElement)resolve(typeof(TElement), name, registration); } catch (ArgumentException ex) when(ex.InnerException is TypeLoadException) { continue; } yield return(value); } } } }
public static void TestSetResizing(IUnmanagedMemoryPool pool) { Random random = new Random(5); var set = new QuickSet <int, PrimitiveComparer <int> >(4, pool); HashSet <int> controlSet = new HashSet <int>(); for (int iterationIndex = 0; iterationIndex < 100000; ++iterationIndex) { if (random.NextDouble() < 0.7) { set.Add(iterationIndex, pool); controlSet.Add(iterationIndex); } if (random.NextDouble() < 0.2) { var indexToRemove = random.Next(set.Count); var toRemove = set[indexToRemove]; set.FastRemove(toRemove); controlSet.Remove(toRemove); } if (iterationIndex % 1000 == 0) { set.EnsureCapacity(set.Count * 3, pool); } else if (iterationIndex % 7777 == 0) { set.Compact(pool); } } Debug.Assert(set.Count == controlSet.Count); for (int i = 0; i < set.Count; ++i) { Debug.Assert(controlSet.Contains(set[i])); } foreach (var element in controlSet) { Debug.Assert(set.Contains(element)); } set.Dispose(pool); }
public static void TestSetResizing() { Random random = new Random(5); UnsafeBufferPool <int> pool = new UnsafeBufferPool <int>(); QuickSet <int> set = new QuickSet <int>(pool, pool); HashSet <int> controlSet = new HashSet <int>(); for (int iterationIndex = 0; iterationIndex < 100000; ++iterationIndex) { if (random.NextDouble() < 0.7) { set.Add(iterationIndex); controlSet.Add(iterationIndex); } if (random.NextDouble() < 0.2) { var indexToRemove = random.Next(set.Count); var toRemove = set[indexToRemove]; set.FastRemove(toRemove); controlSet.Remove(toRemove); } if (iterationIndex % 1000 == 0) { set.EnsureCapacity(set.Count * 3); } else if (iterationIndex % 7777 == 0) { set.Compact(); } } Assert.IsTrue(set.Count == controlSet.Count); for (int i = 0; i < set.Count; ++i) { Assert.IsTrue(controlSet.Contains(set[i])); } foreach (var element in controlSet) { Assert.IsTrue(set.Contains(element)); } }
internal IEnumerable <TElement> ResolveEnumerable <TElement>(Func <Type, IRegistration, object?> resolve, Type typeDefinition, string?name) { object?value; var set = new QuickSet(); var key = new HashKey(typeof(TElement)); var keyGeneric = new HashKey(typeDefinition); // Iterate over hierarchy for (UnityContainer?container = this; null != container; container = container._parent) { // Skip to parent if no data if (null == container._metadata) { continue; } // Hold on to registries Debug.Assert(null != container._registry); var registry = container._registry; // Get indexes for bound types and iterate over them var length = container._metadata.GetMeta(ref key, out int[]? data); if (null != data) { for (var i = 1; i < length; i++) { var index = data[i]; var registration = (ExplicitRegistration)registry.Entries[index].Policies; if (!set.Add(registration.Name)) { continue; } try { value = resolve(typeof(TElement), registration); } catch (ArgumentException ex) when(ex.InnerException is TypeLoadException) { continue; } #pragma warning disable CS8601 // Possible null reference assignment. yield return((TElement)value); #pragma warning restore CS8601 // Possible null reference assignment. } } // Get indexes for unbound types and iterate over them length = container._metadata.GetMeta(ref keyGeneric, out data); if (null != data) { for (var i = 1; i < length; i++) { var index = data[i]; var registration = (ExplicitRegistration)registry.Entries[index].Policies; if (set.Add(registration.Name)) { try { var itemKey = new HashKey(typeof(TElement), registration.Name); var item = container.GetOrAdd(ref itemKey, typeof(TElement), registration.Name, registration); value = resolve(typeof(TElement), item); } catch (MakeGenericTypeFailedException) { continue; } catch (InvalidRegistrationException) { continue; } #pragma warning disable CS8601 // Possible null reference assignment. yield return((TElement)value); #pragma warning restore CS8601 // Possible null reference assignment. } } } } // If nothing registered attempt to resolve the type if (0 == set.Count) { try { var registration = GetRegistration(typeof(TElement), name); value = resolve(typeof(TElement), registration); } catch { yield break; } #pragma warning disable CS8601 // Possible null reference assignment. yield return((TElement)value); #pragma warning restore CS8601 // Possible null reference assignment. } }
internal IEnumerable <TElement> ResolveEnumerable <TElement>(Func <Type, string, ImplicitRegistration, object> resolve, Type typeDefinition, string name) { TElement value; var set = new QuickSet <Type>(); int hashCode = typeof(TElement).GetHashCode(); int hashGeneric = typeDefinition.GetHashCode(); // Iterate over hierarchy for (var container = this; null != container; container = container._parent) { // Skip to parent if no data if (null == container._metadata) { continue; } // Hold on to registries var registry = container._registry; // Get indexes for bound types and iterate over them var length = container._metadata.GetEntries <TElement>(hashCode, out int[] data); for (var i = 1; i < length; i++) { var index = data[i]; if (set.Add(registry.Entries[index].HashCode, registry.Entries[index].Key.Type)) { try { var registration = (ExplicitRegistration)registry.Entries[index].Value; value = (TElement)resolve(typeof(TElement), registry.Entries[index].Key.Name, registration); } catch (ArgumentException ex) when(ex.InnerException is TypeLoadException) { continue; } yield return(value); } } // Get indexes for unbound types and iterate over them length = container._metadata.GetEntries(hashGeneric, typeDefinition, out data); for (var i = 1; i < length; i++) { var index = data[i]; var key = registry.Entries[index].Key.Name; if (set.Add(registry.Entries[index].HashCode, registry.Entries[index].Key.Type)) { try { int hash = NamedType.GetHashCode(typeof(TElement), key); var registration = container.GetOrAdd(hash, typeof(TElement), key, registry.Entries[index].Value); value = (TElement)resolve(typeof(TElement), key, registration); } catch (MakeGenericTypeFailedException) { continue; } catch (InvalidOperationException ex) when(ex.InnerException is InvalidRegistrationException) { continue; } // TODO: Verify if required //catch (ArgumentException ex) when (ex.InnerException is TypeLoadException) //{ // continue; //} yield return(value); } } } // If nothing registered attempt to resolve the type if (0 == set.Count) { try { var registration = GetRegistration(typeof(TElement), name); value = (TElement)resolve(typeof(TElement), name, registration); } catch { yield break; } yield return(value); } }
/// <summary> /// Identifies the points on the surface of hull. /// </summary> /// <param name="points">List of points in the set.</param> /// <param name="outputTriangleIndices">List of indices into the input point set composing the triangulated surface of the convex hull. /// Each group of 3 indices represents a triangle on the surface of the hull.</param> /// <param name="outputSurfacePoints">Unique points on the surface of the convex hull.</param> public static void GetConvexHull(ref QuickList<Vector3> points, ref QuickList<int> outputTriangleIndices, IList<Vector3> outputSurfacePoints) { GetConvexHull(ref points, ref outputTriangleIndices); var alreadyContainedIndices = new QuickSet<int>(BufferPools<int>.Locking, BufferPools<int>.Locking); for (int i = outputTriangleIndices.Count - 1; i >= 0; i--) { int index = outputTriangleIndices[i]; if (alreadyContainedIndices.Add(index)) { outputSurfacePoints.Add(points[index]); } } alreadyContainedIndices.Dispose(); }
public static void TestSetResizing() { Random random = new Random(5); UnsafeBufferPool<int> pool = new UnsafeBufferPool<int>(); QuickSet<int> set = new QuickSet<int>(pool, pool); HashSet<int> controlSet = new HashSet<int>(); for (int iterationIndex = 0; iterationIndex < 100000; ++iterationIndex) { if (random.NextDouble() < 0.7) { set.Add(iterationIndex); controlSet.Add(iterationIndex); } if (random.NextDouble() < 0.2) { var indexToRemove = random.Next(set.Count); var toRemove = set[indexToRemove]; set.FastRemove(toRemove); controlSet.Remove(toRemove); } if (iterationIndex % 1000 == 0) { set.EnsureCapacity(set.Count * 3); } else if (iterationIndex % 7777 == 0) { set.Compact(); } } Assert.IsTrue(set.Count == controlSet.Count); for (int i = 0; i < set.Count; ++i) { Assert.IsTrue(controlSet.Contains(set[i])); } foreach (var element in controlSet) { Assert.IsTrue(set.Contains(element)); } }