/// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="items"></param> /// <param name="getPosition"></param> /// <param name="grid"></param> /// <param name="tolerance"></param> /// <returns></returns> public static IEnumerable <T> RemoveCoincident <T>(IEnumerable <T> items, Func <T, Vec2d> getPosition, HashGrid2d <Vec2d> grid = null, double tolerance = SlurMath.ZeroTolerance) { if (grid == null) { grid = new HashGrid2d <Vec2d>(); } grid.Scale = tolerance * _radiusToGridScale; // add points to result if no duplicates are found int i = 0; foreach (var item in items) { var p0 = getPosition(item); foreach (var p1 in grid.Search(new Interval3d(p0, tolerance))) { if (p0.ApproxEquals(p1, tolerance)) { goto EndFor; } } // no coincident items found grid.Insert(p0, p0); yield return(item); EndFor :; i++; } }
/// <summary> /// /// </summary> /// <typeparam name="T"></typeparam> /// <param name="items"></param> /// <param name="getPosition"></param> /// <param name="indexMap"></param> /// <param name="grid"></param> /// <param name="tolerance"></param> /// <returns></returns> public static List <T> RemoveCoincident <T>(IEnumerable <T> items, Func <T, Vec2d> getPosition, out List <int> indexMap, HashGrid2d <int> grid = null, double tolerance = SlurMath.ZeroTolerance) { if (grid == null) { grid = new HashGrid2d <int>(); } var result = new List <T>(); indexMap = new List <int>(); grid.Scale = tolerance * _radiusToGridScale; // add points to result if no duplicates are found foreach (var item in items) { var p0 = getPosition(item); // search for concident items in result foreach (int j in grid.Search(new Interval2d(p0, tolerance))) { if (p0.ApproxEquals(getPosition(result[j]), tolerance)) { indexMap.Add(j); goto EndFor; } } // no coincident items found grid.Insert(p0, result.Count); indexMap.Add(result.Count); result.Add(item); EndFor :; } return(result); }
/// <summary> /// For each item in A, returns the index of all 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="tolerance"></param> /// <returns></returns> public static IEnumerable <IEnumerable <int> > GetAllCoincident <T, U>(IReadOnlyList <T> itemsA, Func <T, Vec2d> getPositionA, IReadOnlyList <U> itemsB, Func <U, Vec2d> getPositionB, double tolerance = SlurMath.ZeroTolerance) { var grid = new HashGrid2d <int>(itemsB.Count); return(GetAllCoincident(itemsA, getPositionA, itemsB, getPositionB, grid, tolerance)); }
/// <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, Vec2d> getPositionA, IReadOnlyList <U> itemsB, Func <U, Vec2d> getPositionB, HashGrid2d <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 Interval2d(p0, tolerance)) .Where(j => p0.ApproxEquals(getPositionB(itemsB[j]), tolerance))); } }
/// <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, Vec2d> getPositionA, IReadOnlyList <U> itemsB, Func <U, Vec2d> getPositionB, HashGrid2d <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 :; } }
/// <summary> /// For each item in A, returns the index of each coincident items in B. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="itemsA"></param> /// <param name="itemsB"></param> /// <param name="getPosition"></param> /// <param name="grid"></param> /// <param name="tolerance"></param> /// <returns></returns> public static IEnumerable <IEnumerable <int> > GetAllCoincident <T>(IReadOnlyList <T> itemsA, IReadOnlyList <T> itemsB, Func <T, Vec2d> getPosition, HashGrid2d <int> grid, double tolerance = SlurMath.ZeroTolerance) { return(GetAllCoincident(itemsA, getPosition, itemsB, getPosition, grid, tolerance)); }
/// <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> /// <param name="items"></param> /// <param name="getPosition"></param> /// <param name="tolerance"></param> /// <returns></returns> public static IEnumerable <int> GetFirstCoincident <T>(IReadOnlyList <T> items, Func <T, Vec2d> getPosition, double tolerance = SlurMath.ZeroTolerance) { var grid = new HashGrid2d <int>(items.Count); return(GetFirstCoincident(items, getPosition, grid, tolerance)); }
/// <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, Vec2d> getPosition, HashGrid2d <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 Interval2d(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); }
/// <summary> /// Returns a new list with no coincident items. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="items"></param> /// <param name="getPosition"></param> /// <param name="indexMap"></param> /// <param name="tolerance"></param> /// <returns></returns> public static List <T> RemoveCoincident <T>(IReadOnlyList <T> items, Func <T, Vec2d> getPosition, out int[] indexMap, double tolerance = SlurMath.ZeroTolerance) { var grid = new HashGrid2d <int>(items.Count); return(RemoveCoincident(items, getPosition, grid, out indexMap, tolerance)); }
/// <summary> /// For each item in A, returns the index of all coincident items in B. /// </summary> /// <typeparam name="T"></typeparam> /// <param name="itemsA"></param> /// <param name="itemsB"></param> /// <param name="getPosition"></param> /// <param name="tolerance"></param> /// <returns></returns> public static IEnumerable <IEnumerable <int> > GetAllCoincident <T>(IReadOnlyList <T> itemsA, IReadOnlyList <T> itemsB, Func <T, Vec2d> getPosition, double tolerance = 1.0e-8) { var grid = new HashGrid2d <int>(itemsB.Count << 1); return(GetAllCoincident(itemsA, itemsB, getPosition, grid, tolerance)); }
/// <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, Vec2d> getPosition, HashGrid2d <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 Interval2d(p0, tolerance))) { if (i != j && p0.ApproxEquals(getPosition(items[j]), tolerance)) { yield return(j); goto EndFor; } } yield return(-1); EndFor :; } }