Tengo un motor de juego considerable y me gustaría tener una función para encontrar la lista de puntos más cercana.
Simplemente podría usar el teorema de Pitágoras para encontrar cada distancia y elegir la mínima, pero eso requiere iterar a través de todas ellas.
También tengo un sistema de colisión, donde esencialmente convierto objetos en objetos más pequeños en una cuadrícula más pequeña (algo así como un minimapa) y solo si los objetos existen en el mismo espacio de cuadrícula, verifico si hay colisiones. Podría hacer eso, solo agrandar el espacio de la cuadrícula para verificar la cercanía. (En lugar de verificar cada objeto). Sin embargo, eso requeriría una configuración adicional en mi clase base y desordenaría el objeto ya desordenado. ¿Vale la pena?
¿Hay algo eficiente y preciso que pueda usar para detectar qué objeto está más cerca, en base a una lista de puntos y tamaños?
Respuestas:
El problema con un quad / octree en las búsquedas de vecino más cercano es que el objeto más cercano puede estar sentado en la división entre nodos. Para colisiones, esto está bien, porque si no está en el nodo, no nos importa. Pero considere este ejemplo 2D con un quadtree:
Aquí, aunque el elemento negro y el elemento verde están en el mismo nodo, el elemento negro está más cerca del elemento azul. La respuesta de ultifinitus solo puede garantizar al vecino más cercano, solo cada elemento de su árbol se coloca en el nodo más pequeño posible que pueda contenerlo, o en un nodo único, lo que conduce a un cuadrilátero más ineficiente. (Tenga en cuenta que hay muchas formas diferentes de implementar una estructura que podría denominarse quad / octree; las implementaciones más estrictas pueden funcionar mejor en esta aplicación).
Una mejor opción sería un árbol kd . Los árboles Kd tienen un algoritmo de búsqueda de vecino más cercano muy eficiente que puede implementar, y puede contener cualquier cantidad de dimensiones (de ahí las dimensiones "k").
Una gran e informativa animación de Wikipedia:
El mayor problema con el uso de kd-trees, si no recuerdo mal, es que es más difícil insertar / eliminar elementos mientras se mantiene el equilibrio. Por lo tanto, recomendaría usar un árbol kd para objetos estáticos como casas y árboles que está altamente equilibrado, y otro que contenga jugadores y vehículos, que necesita equilibrarse regularmente. Encuentre el objeto estático más cercano y el objeto móvil más cercano, y compare esos dos.
Por último, los árboles kd son relativamente simples de implementar, y estoy seguro de que puedes encontrar una gran cantidad de bibliotecas C ++ con ellos. Por lo que recuerdo, los árboles R son mucho más complicados, y probablemente exageren si todo lo que necesitas es una simple búsqueda del vecino más cercano.
fuente
sqrt()
es monótono, o preservar el orden, para argumentos no negativos, entonces:Y viceversa.
Entonces, si solo desea comparar dos distancias pero no está interesado en sus valores reales, simplemente puede cortar el paso
sqrt()
de sus cosas de Pitágoras:No es tan eficiente como el oct-tree, pero es más fácil de implementar y aumenta la velocidad al menos un poco
fuente
Tiene que hacer una partición espacial, en este caso crea una estructura de datos eficiente (generalmente un octree). En este caso, cada objeto está dentro de uno o más espacios (cubos). Y si sabe en qué espacios se encuentra, puede buscar O (1) qué espacios son sus vecinos.
En este caso, se puede encontrar el objeto más cercano iterando primero sobre todos los objetos en su propio espacio mirando cuál es el más cercano allí. Si no hay nadie allí, puede verificar a sus primeros vecinos, si no hay nadie, puede verificar a sus vecinos, etc.
De esta manera, puede encontrar fácilmente el objeto más cercano sin tener que recorrer todos los objetos de su mundo. Como de costumbre, esta ganancia de velocidad requiere un poco de contabilidad, pero es realmente útil para todo tipo de cosas, por lo que si tienes un gran mundo definitivamente vale la pena implementar la partición espacial y un octree.
Como de costumbre, vea también el artículo de Wikipedia: http://en.wikipedia.org/wiki/Octree
fuente
Tal vez intente organizar sus datos espaciales en un RTree, que es como un btree para cosas en el espacio y permite consultas como "N vecinos más cercanos", etc ... http://en.wikipedia.org/wiki/Rtree
fuente
Aquí está mi implementación de Java para obtener la más cercana de un quadTree. Se trata del problema que dlras2 está describiendo:
Creo que la operación es realmente eficiente. Se basa en la distancia a un quad para evitar buscar en quads más allá del actual más cercano.
fuente