I have this:
#region IEquatable<Points> Members public bool Equals(Points other) { if (Object.ReferenceEquals(other, null)) return false; if (Object.ReferenceEquals(this, other)) return true; return this.PointNumber.Equals(other.PointNumber); } public override int GetHashCode() { int hashDescription = this.PointNumber == null ? 0 : this.PointNumber.GetHashCode(); return hashDescription; } #endregion
to distinct repeat cogo points(civil 3d) about its PointNumber.
Now, I want the same but Point2d Collection, however it doesn´t work:
namespace toolsC3D { public class Vertex : IEquatable<Vertex> { #region IEquatable<Vertex> Members public bool Equals(Vertex other) { if (Object.ReferenceEquals(other, null)) return false; if (Object.ReferenceEquals(this, other)) return true; return this.punto2d.Equals(other.punto2d); } public override int GetHashCode() { int hashDescription = this.punto2d == null ? 0 : this.punto2d.GetHashCode(); return hashDescription; } #endregion private Autodesk.AutoCAD.Geometry.Point2d mipunto2d = new Autodesk.AutoCAD.Geometry.Point2d(0,0); public Autodesk.AutoCAD.Geometry.Point2d punto2d { get { return mipunto2d; } set { mipunto2d = value; } } } }
How can I delete all repeated location of point2D in a point2d Collection?
Can I do distinct with both conditions? point2d.X and point2d.Y?
I have seen that Point2dCollection has IsEqual() method but I don´t know how I could use it.
Solved! Go to Solution.
Solved by zrobert. Go to Solution.
Hi;
Try something like this. (I'm not tested this code):
public Point2dCollection RemoveDuplicates(Point2dCollection coll) { var distinctItems = coll.ToArray().Distinct(new Point2DComparer()); var c = distinctItems.ToArray(); return new Point2dCollection(c); } class Point2DComparer : IEqualityComparer<Point2d> { public bool Equals(Point2d pt1, Point2d pt2) { return System.Math.Abs(pt1.X - pt2.X) < 0.0001 && System.Math.Abs(pt1.Y - pt2.Y) < 0.0001; } public int GetHashCode(Point2d pt) { return pt.GetHashCode(); } }
Yes, but I have points in the same collection. Perhaps I have to clone or copy collection and compare them to each other with IsEqual().
You can use one of these overloaded RemoveDuplicates() extension methods.
They return a Point2d lazy sequence (IEnumerable<Point2d>) which can be iterated with foreach or converted into a Point2d array or list.
They can be called as a Point2dCollection instance method, a Point2d[] instance method or a List<Point2d> instance method.
A Tolerance can be passed as argument to be used for equality comparison, if none argument is passed the Tolerence.Global is used.
public static class Point2dExtensions { private static Tolerance tolerance; public static IEnumerable<Point2d> RemoveDuplicates(this Point2dCollection source) { return source.Cast<Point2d>().RemoveDuplicates(Tolerance.Global); } public static IEnumerable<Point2d> RemoveDuplicates(this Point2dCollection source, Tolerance tolerance) { return source.Cast<Point2d>().RemoveDuplicates(tolerance); } public static IEnumerable<Point2d> RemoveDuplicates(this IEnumerable<Point2d> source) { return source.RemoveDuplicates(Tolerance.Global); } public static IEnumerable<Point2d> RemoveDuplicates(this IEnumerable<Point2d> source, Tolerance tolerance) { if (source == null) throw new ArgumentNullException("source");
Point2dExtensions.tolerance = tolerance; return source.Distinct(new Point2dComparer()); } class Point2dComparer : IEqualityComparer<Point2d> { public bool Equals(Point2d a, Point2d b) { return a.IsEqualTo(b, Point2dExtensions.tolerance); } public int GetHashCode(Point2d pt) { return 0; } } }
If you want to use the HashCode in the equality comparison, you can replace the Point2dequalityComparer with this one (but I'm not sure it's more efficient).
class Point2dComparer : IEqualityComparer<Point2d> { public bool Equals(Point2d a, Point2d b) { return a.IsEqualTo(b, Point2dExtensions.tolerance); } public int GetHashCode(Point2d pt) { return new Point2d(Round(pt.X), Round(pt.Y)).GetHashCode(); } private double prec = Point2dExtensions.tolerance.EqualPoint * 10.0; private double Round(double num) { if (prec == 0.0) return num; else return Math.Floor(num / prec + 0.5) * prec; } }
gile, I have already tried both code amb both doesn´t work.
I have 12 vertex and 2 repited vertex and returns equally 12.
I use this, but I think that it shoud be something more efficient;
public static void RemoveDuplicates(this Point2dCollection source) { for (int i = 0; i <= source.Count - 1; i++) { for (int k = 0; k <= source.Count - 1; k++) { if (k > i) { if(source[i].IsEqualTo(source[k])) { source.RemoveAt(k); k--; } } } } }
Hi;
For Point3DCollection, do this changes:
public Point3dCollection RemoveDuplicates(Point3dCollection collection) { var a = collection.Cast<Point3d>(); var distinctItems = a.Distinct(new Point3DComparer()); var c = distinctItems.ToArray(); return new Point3dCollection(c); }
private class Point3DComparer : IEqualityComparer<Point3d> { public bool Equals(Point3d pt1, Point3d pt2) { return System.Math.Abs(pt1.X - pt2.X) < 0.0001 && System.Math.Abs(pt1.Y - pt2.Y) < 0.0001 && System.Math.Abs(pt1.Z - pt2.Z) < 0.0001; } public int GetHashCode(Point3d point) { return point.GetHashCode(); } }
Chears...
For ObjectIdCollection, try the same thing. ObjectIdCollection implements IList interface just
like Point3DCollection. Dont forget to change comparation logic in "SomeObject"Comparer class.
But, I think that you can avoid collection of duplicate ObjectId members...