예제 #1
0
        /// <summary>
        ///
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="items"></param>
        /// <param name="getPosition"></param>
        /// <param name="grid"></param>
        /// <param name="indexMap"></param>
        /// <param name="tolerance"></param>
        /// <returns></returns>
        public static List <T> RemoveCoincident <T>(IReadOnlyList <T> items, Func <T, Vec3d> getPosition, HashGrid3d <int> grid, out int[] indexMap, double tolerance = SlurMath.ZeroTolerance)
        {
            var result = new List <T>();
            var map    = new int[items.Count];

            grid.Scale = tolerance * RadiusToHashScale;

            // add points to result if no duplicates are found
            for (int i = 0; i < items.Count; i++)
            {
                var p0 = getPosition(items[i]);

                // search for concident in result
                foreach (int j in grid.Search(new Interval3d(p0, tolerance)))
                {
                    if (p0.ApproxEquals(getPosition(result[j]), tolerance))
                    {
                        map[i] = j;
                        goto EndFor;
                    }
                }

                // no coincident item found, add i to result
                grid.Insert(p0, result.Count);
                map[i] = result.Count;
                result.Add(items[i]);

                EndFor :;
            }

            indexMap = map;
            return(result);
        }
예제 #2
0
        /// <summary>
        /// For each item in A, returns the index of the first coincident item in B. If no coincident point is found, -1 is returned.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="U"></typeparam>
        /// <param name="itemsA"></param>
        /// <param name="getPositionA"></param>
        /// <param name="itemsB"></param>
        /// <param name="getPositionB"></param>
        /// <param name="grid"></param>
        /// <param name="tolerance"></param>
        /// <returns></returns>
        public static IEnumerable <int> GetFirstCoincident <T, U>(IReadOnlyList <T> itemsA, Func <T, Vec3d> getPositionA, IReadOnlyList <U> itemsB, Func <U, Vec3d> getPositionB, HashGrid3d <int> grid, double tolerance = SlurMath.ZeroTolerance)
        {
            grid.Scale = tolerance * RadiusToHashScale;

            // insert B
            for (int i = 0; i < itemsB.Count; i++)
            {
                grid.Insert(getPositionB(itemsB[i]), i);
            }

            // search from A
            for (int i = 0; i < itemsA.Count; i++)
            {
                var p0 = getPositionA(itemsA[i]);

                foreach (var j in grid.Search(new Interval3d(p0, tolerance)))
                {
                    if (p0.ApproxEquals(getPositionB(itemsB[j]), tolerance))
                    {
                        yield return(j);

                        goto EndFor;
                    }
                }

                yield return(-1);

                EndFor :;
            }
        }
예제 #3
0
        /// <summary>
        /// For each item, returns the index of the first coincident item within the same list. If no coincident point is found, -1 is returned.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="items"></param>
        /// <param name="grid"></param>
        /// <param name="getPosition"></param>
        /// <param name="tolerance"></param>
        /// <returns></returns>
        public static IEnumerable <int> GetFirstCoincident <T>(IReadOnlyList <T> items, Func <T, Vec3d> getPosition, HashGrid3d <int> grid, double tolerance = 1.0e-8)
        {
            grid.BinScale = tolerance * RadiusToBinScale;

            // insert
            for (int i = 0; i < items.Count; i++)
            {
                grid.Insert(getPosition(items[i]), i);
            }

            // search
            for (int i = 0; i < items.Count; i++)
            {
                var p0 = getPosition(items[i]);

                foreach (var j in grid.Search(new Interval3d(p0, tolerance)))
                {
                    if (i != j && p0.ApproxEquals(getPosition(items[j]), tolerance))
                    {
                        yield return(j);

                        goto EndFor;
                    }
                }

                yield return(-1);

                EndFor :;
            }
        }
예제 #4
0
        /// <summary>
        /// For each item in A, returns the index of each coincident items in B.
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="U"></typeparam>
        /// <param name="itemsA"></param>
        /// <param name="getPositionA"></param>
        /// <param name="itemsB"></param>
        /// <param name="getPositionB"></param>
        /// <param name="grid"></param>
        /// <param name="tolerance"></param>
        /// <returns></returns>
        public static IEnumerable <IEnumerable <int> > GetAllCoincident <T, U>(IReadOnlyList <T> itemsA, Func <T, Vec3d> getPositionA, IReadOnlyList <U> itemsB, Func <U, Vec3d> getPositionB, HashGrid3d <int> grid, double tolerance = SlurMath.ZeroTolerance)
        {
            grid.Scale = tolerance * RadiusToHashScale;

            // insert B
            for (int i = 0; i < itemsB.Count; i++)
            {
                grid.Insert(getPositionB(itemsB[i]), i);
            }

            // search from A
            for (int i = 0; i < itemsA.Count; i++)
            {
                var p0 = getPositionA(itemsA[i]);

                yield return(grid.Search(new Interval3d(p0, tolerance))
                             .Where(j => p0.ApproxEquals(getPositionB(itemsB[j]), tolerance)));
            }
        }
예제 #5
0
        /// <summary>
        /// Consolidates points within a given search radius.
        /// Returns true if the solution converged within the given maximum number of steps.
        /// </summary>
        /// <param name="points"></param>
        /// <param name="radius"></param>
        /// <param name="tolerance"></param>
        /// <param name="maxSteps"></param>
        /// <returns></returns>
        public static bool ConsolidatePoints(IList <Vec3d> points, double radius, double tolerance = SlurMath.ZeroTolerance, int maxSteps = 4)
        {
            var grid = new HashGrid3d <Vec3d>(radius * RadiusToHashScale, points.Count);

            var radSqr    = radius * radius;
            var tolSqr    = tolerance * tolerance;
            var converged = false;

            while (!converged && maxSteps-- > 0)
            {
                converged = true;

                // insert into grid
                for (int i = 0; i < points.Count; i++)
                {
                    var p = points[i];
                    grid.Insert(p, p);
                }

                // search grid
                for (int i = 0; i < points.Count; i++)
                {
                    var p0 = points[i];
                    var p1 = grid.Search(new Interval3d(p0, radius))
                             .Where(p => p0.SquareDistanceTo(p) < radSqr)
                             .Mean();

                    points[i] = p1;

                    if (p0.SquareDistanceTo(p1) > tolSqr)
                    {
                        converged = false;
                    }
                }

                grid.Clear();
            }

            return(maxSteps > 0);
        }