Question

I would like to find a fast algorithm in order to find the x closest points to a given point on a plane.

We are actually dealing with not too many points (between 1,000 and 100,000), but I need the x closest points for every of these points. (where x usually will be between 5 and 20.)

I need to write it in C#.

A bit more context about the use case: These points are coordinates on a map. (I know, this means we are not exactly talking about a plane, but I hope to avoid dealing with projection issues.) In the end points that have many other points close to them should be displayed in red, points that have not too many points close to them should be displayed green. Between these two extremees the points are on a color gradient.

Was it helpful?

Solution

What you need is a data structure appropriate for organizing points in a plane. The K-D-Tree is often used in such situations. See k-d tree on Wikipedia.

Here, I found a general description of Geometric Algorithms


UPDATE

I ported a Java implementation of a KD-tree to C#. Please see User:Ojd/KD-Tree on RoboWiki. You can download the code there or you can download CySoft.Collections.zip directly from my homepage (only download, no docu).

OTHER TIPS

For a given point (not all of them) and as the number of points is not extreme, you could calculate the distance from each point:

var points = new List<Point>();
Point source = ...
....
var closestPoints = points.Where(point => point != source).
                           OrderBy(point => NotReallyDistanceButShouldDo(source, point)).
                           Take(20);

private double NotReallyDistanceButShouldDo(Point source, Point target)
{
   return Math.Pow(target.X - source.X, 2) + Math.Pow(target.Y - source.Y, 2);
}

(I've used x = 20)

The calculation are based on doubles so the fpu should be able to do a decent job here. Note that you might get better performance if Point is a class rather than a struct.

You need to create a distance function, then calculate distance for every point and sort the results, and take the first x.

If the results must be 100% accurate then you can use the standard distance function:

d = SQRT((x2 - x1)^2 + (y2 - y1)^2)

To make this more efficent. lets say the distance is k. Take all points with x coordinates between x-k and x+k. similarly take, y-k and y+k. So you have removed all excess coordinates. now make distance by (x-x1)^2 + (y-y1)^2. Make a min heap of k elements on them , and add them to the heap if new point < min(heap). You now have the k minimum elements in the heap.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top