Author Topic: How to filter out points with the same coordinates in a List<Point3d>?  (Read 3171 times)

0 Members and 1 Guest are viewing this topic.

waterharbin

  • Guest
Hi.
I got a List<Points>, but it holds some points with the same coordinates. I want all the points only have their exclusive coordinates. Repeated points must be filtered out. I can define another List<Points>,and then use the Exists() and Find() method to do this. But I wonder is there any simple method somewhat like List.Filter() can get the job done? So I don't need to define another List<Point3d>.

gile

  • Gator
  • Posts: 2507
  • Marseille, France
Hi,

Look at the IEnumerable<T> extension methods.

The Distinct() method may be what you're looking for, you can define your own equality Comaparer if you need to use a Tolerance.
Speaking English as a French Frog

Gasty

  • Newt
  • Posts: 90
Hi,

There is  a lot of way to do that, LINQ Distinct would be the first, but a more conventional way is to conditional add the point to a list:


If Not MyList.Contains(testPoint) then
  MyList.Add(testPoint)
End If

Also check the Tolerance (equalpoint) property in order to avoid rounding issues.

Gaston Nunez

TheMaster

  • Guest
Hi,

There is  a lot of way to do that, LINQ Distinct would be the first, but a more conventional way is to conditional add the point to a list:


If Not MyList.Contains(testPoint) then
  MyList.Add(testPoint)
End If

Also check the Tolerance (equalpoint) property in order to avoid rounding issues.

Gaston Nunez

You probably wouldn't want to use List<T>.Contains() to do this, because it is much slower than using Distinct() or a HashSet<T>.  Distinct() also uses a hashing algorithm to check if the collection already contains a duplicate/equal item.

List<T>.Contains() does a simple, linear search of the list, which is far slower.
« Last Edit: June 02, 2012, 02:36:47 PM by TheMaster »

waterharbin

  • Guest
Hi.
I have tried the Exists(). I am not good at LINQ, this is all I got here.
Code: [Select]
        private void censorPoints(List<Point3d> sourceLst, List<Point3d> distinctLst)
        {
            foreach (Point3d sourcePt in sourceLst)
            {
                bool existed = distinctLst.Exists(pt =>
                    {
                        if (pt.DistanceTo(sourcePt) < 20)
                            return true;
                        return false;
                    });
                if (!existed)
                    distinctLst.Add(sourcePt);
            }
        }
I have my own problem of "the same" points. If two points are too close to each other, they are considered as "the same" points. One need to be filtered out. I don't know how to write the lambda expression for Distinct() and Contains() methods. I also don't which is the fastest.

TheMaster

  • Guest
Hi.
I have tried the Exists(). I am not good at LINQ, this is all I got here.
Code: [Select]
        private void censorPoints(List<Point3d> sourceLst, List<Point3d> distinctLst)
        {
            foreach (Point3d sourcePt in sourceLst)
            {
                bool existed = distinctLst.Exists(pt =>
                    {
                        if (pt.DistanceTo(sourcePt) < 20)
                            return true;
                        return false;
                    });
                if (!existed)
                    distinctLst.Add(sourcePt);
            }
        }
I have my own problem of "the same" points. If two points are too close to each other, they are considered as "the same" points. One need to be filtered out. I don't know how to write the lambda expression for Distinct() and Contains() methods. I also don't which is the fastest.

If fastest is important, then you should consider using spatial indexing (discussed in the thread about finding the nearest point).  You could do the filtering in the process of building the spatial index, since each point will have an index node, you can compare it to already-indexed points within the same index node. This would probably be the fastest way if you have a large number of coincident or 'equal' coordinates.

Doing this with the LINQ's Distinct() method is difficult when your comparison is 'fuzzy' because you would need to write a custom IEqualityComparer<Point3d>, and for Distinct() to take advantage of hashing, you would have to implement GetHashcode() and have it return the same hash value for all points that are equal. In other words if Equals( a, b ) returns true, then GetHashcode( a ) == GetHashcode( b ) must be true as well.

If you don't provide a hashcode (e.g., have GetHashcode() return 0 for all points), Distinct() will need to use Equals() to compare every point to every other point. Hence, while Distinct() will do the job, it will not perform well when the equality test is a 'fuzzy' comparison.


« Last Edit: June 17, 2012, 01:19:52 AM by TheMaster »