Monday, April 4, 2016

c++ - In 2D, how do I efficiently find the nearest object to a point?


I have a sizable game engine and I'd like a feature for finding the nearest of a list of points.


I could simply use the Pythagorean theorem to find each distance and choose the minimum one, but that requires iterating through all of them.


I also have a collision system, where essentially I turn objects into smaller objects on a smaller grid (kind of like a minimap) and only if objects exist in the same gridspace do I check for collisions. I could do that, only make the grid spacing larger to check for closeness. (Rather than checking every single object.) However, that would take additional setup in my base class and clutter up the already cluttered object. Is it worth it?


Is there something efficient and accurate I could use to detect which object is closest, based on a list of points and sizes?



Answer



The problem with a quad/octree in nearest-neighbor searches is that the closest object may be sitting right across the division between nodes. For collisions, this is okay, because if it's not in the node, we don't care about it. But consider this 2D example with a quadtree:


Quadtree example


Here, even though the black item and green item are in the same node, the black item is closest to the blue item. ultifinitus' answer can only guarantee the nearest-neighbor only every item in your tree is placed in the smallest possible node that could contain it, or in a unique node - this leads to more inefficient quadtrees. (Note that there are many different ways to implement a structure which could be called a quad/octree - more strict implementations may work better in this application.)



A better option would be a kd-tree. Kd-trees have a very efficient nearest-neighbor search algorithm you can implement, and can contain any number of dimensions (hence "k" dimensions.)


A great and informative animation from Wikipedia: kd-tree nearest-neighbor search


The biggest problem with using kd-trees, if I recall correctly, is that they are more difficult to insert/remove items from while maintaining balance. Therefore, I would recommend using one kd-tree for static objects such as houses and trees which is highly balanced, and another which contains players and vehicles, which needs balancing regularly. Find the nearest static object and the nearest mobile object, and compare those two.


Lastly, kd-trees are relatively simple to implement, and I'm sure you can find a multitude of C++ libraries with them. From what I remember, R-trees are much more complicated, and probably overkill if all you need is a simple nearest-neighbor search.


No comments:

Post a Comment

Simple past, Present perfect Past perfect

Can you tell me which form of the following sentences is the correct one please? Imagine two friends discussing the gym... I was in a good s...