Search code examples
c#coordinatescluster-analysispoint

C# - creating groups of points


How to create something that accepts one point and list of all points and returns list of points that are close enough to the original point or to the point which is close enough.

If you still can't understand me here's a picture:

Point grouping

I've tried:

    int range = 6;
    public List<IntPoint> getClosePoints(ref Dictionary<IntPoint,bool> allPoints,IntPoint startingPoint) {
        List<IntPoint> closePoints = new List<IntPoint>();
        closePoints.Add(startingPoint);
        bool gotBigger = true;

        while (gotBigger) {
            gotBigger = false;
            foreach (IntPoint proven in closePoints.ToList()) {
                foreach (IntPoint possible in allPoints.Keys.ToList()) {
                    if (isInRange(proven,possible,range) && !allPoints[possible]) {
                        gotBigger = true;
                        closePoints.Add(possible);
                        allPoints[possible] = true;
                    }
                }
            }
        }
        return closePoints;
    }

    public bool isInRange(IntPoint A, IntPoint B, int range){
        if(A.DistanceTo(B) < range)
            return true;
        return false;
    }

(IntPoint is similiar to Point, it is from AForge, all points have bool value false) But this makes my program super-laggy considering that it is called thousand times a loop. :/ (And also it doesn't seem to work now)


Solution

  • try this:

    public IEnumerable<Point> GetPoints(Point origin, IEnumerable<Point> points, int distance)
    {
        var result = new HashSet<Point>();
        var found = new Queue<Point>();
        found.Enqueue(origin)
    
        while(found.Count > 0)
        {
            var current = found.Dequeue();
            var candidates = points
                .Where(p => !result.Contains(p) &&
                       p.Distance(current) <= distance);
    
            foreach(var p in candidates)
            {
                result.Add(p);
                found.Enqueue(p)
            }
        }
    
        return result;
    }
    

    i think this is straight forward enough, in any case the HashSet feature is that it can tell if it contains an item in near O(1).