Nearest neighbor zones visualized
Asked Answered
J

4

6

I'm writing an app that looks up points in two-dimensional space using a k-d tree. It would be nice, during development, to be able to "see" the nearest-neighbor zones surrounding each point.

In the attached image, the red points are points in the k-d tree, and the blue lines surrounding each point bound the zone where a nearest neighbor search will return the contained point.

The image was created thusly:

for each point in the space:
  da = distance to nearest neighbor
  db = distance to second-nearest neighbor
  if absolute_value(da - db) < 4:
    draw blue pixel

This algorithm has two problems:

  • (more important) It's slow on my (reasonably fast Core i7) computer.
  • (less important) It's sloppy, as you can see by the varying widths of the blue lines.

What is this "visualization" of a set of points called?

What are some good algorithms to create such a visualization?

partitions

Jeffryjeffy answered 15/2, 2012 at 6:32 Comment(0)
A
7

This is called a Voronoi Diagram and there are many excellent algorithms for generating them efficiently. The one I've heard about most is Fortune's algorithm, which runs in time O(n log n), though others algorithms exist for this problem.

Hope this helps!

Aldarcy answered 15/2, 2012 at 6:39 Comment(0)
P
4

Jacob,

hey, you found an interesting way of generating this Voronoi diagram, even though it is not so efficient.

The less important issue first: the varying thickness boundaries that you get, those butterfly shapes, are in fact the area between the two branches of an hyperbola. Precisely the hyperbola given by the equation |da - db| = 4. To get a thick line instead, you have to modify this criterion and replace it by the distance to the bisector of the two nearest neighbors, let A and B; using vector calculus, | PA.AB/||AB|| - ||AB||/2 | < 4.

The more important issue: there are two well known efficient solutions to the construction of the Voronoi diagram of a set of points: Fortune's sweep algorithm (as mentioned by templatetypedef) and Preparata & Shamos' Divide & Conquer solutions. Both run in optimal time O(N.Lg(N)) for N points, but aren't so easy to implement.

These algorithm will construct the Voronoi diagram as a set of line segments and half-lines. Check http://en.wikipedia.org/wiki/Voronoi_diagram.

This paper "Primitives for the manipulation of general subdivisions and the computation of Voronoi" describes both algorithms using a somewhat high-level framework, caring about all implementation details; the article is difficult but the algorithms are implementable.

You may also have a look at "A straightforward iterative algorithm for the planar Voronoi diagram", which I never tried.

A totally different approach is to directly build the distance map from the given points for example by means of Dijkstra's algorithm: starting from the given points, you grow the boundary of the area within a given distance from every point and you stop growing when two boundaries meet. [More explanations required.] See http://1.bp.blogspot.com/-O6rXggLa9fE/TnAwz4f9hXI/AAAAAAAAAPk/0vrqEKRPVIw/s1600/distmap-20-seed4-fin.jpg

Another good starting point (for efficiently computing the distance map) can be "A general algorithm for computing distance transforms in linear time".

Phoney answered 15/2, 2012 at 8:16 Comment(0)
E
2

From personal experience: Fortune's algorithm is a pain to implement. The divide and conquer algorithm presented by Guibas and Stolfi isn't too bad; they give detailed pseudocode that's easy to transcribe into a procedural programming language. Both will blow up if you have nearly degenerate inputs and use floating point, but since the primitives are quadratic, if you can represent coordinates as 32-bit integers, then you can use 64 bits to carry out the determinant computations.

Once you get it working, you might consider replacing your kd-tree algorithms, which have a Theta(√n) worst case, with algorithms that work on planar subdivisions.

Epicotyl answered 15/2, 2012 at 12:54 Comment(0)
G
1

You can find a great implementation for it at D3.js library: http://mbostock.github.com/d3/ex/voronoi.html

Gravelly answered 15/2, 2012 at 18:27 Comment(1)
thanks for the link. I ended up using the D3 implementation and it's been great.Jeffryjeffy

© 2022 - 2024 — McMap. All rights reserved.