Necesito encontrar la dirección de la distancia más corta desde un punto en mi mundo 2D a otro punto donde se envuelven los bordes (como asteroides, etc.). Sé cómo encontrar la distancia más corta, pero estoy luchando por encontrar en qué dirección está.
La distancia más corta viene dada por:
int rows = MapY;
int cols = MapX;
int d1 = abs(S.Y - T.Y);
int d2 = abs(S.X - T.X);
int dr = min(d1, rows-d1);
int dc = min(d2, cols-d2);
double dist = sqrt((double)(dr*dr + dc*dc));
Ejemplo del mundo
:
: T
:
:--------------:---------
: :
: S :
: :
: :
: T :
: :
:--------------:
En el diagrama, los bordes se muestran con: y -. También he mostrado una repetición envuelta del mundo en la parte superior derecha. Quiero encontrar la dirección en grados de S a T. Entonces, la distancia más corta es a la repetición superior derecha de T. pero, ¿cómo calculo la dirección en grados de S a la repetida T en la parte superior derecha?
Conozco las posiciones de S y T, pero supongo que necesito encontrar la posición de la T repetida, sin embargo, hay más de 1.
El sistema de coordenadas del mundo comienza en 0,0 en la esquina superior izquierda y 0 grados para la dirección podría comenzar en el oeste.
Parece que esto no debería ser demasiado difícil, pero no he podido encontrar una solución. Espero que alguien pueda ayudar? Cualquier sitio web sería apreciado.
Respuestas:
Tendrá que ajustar un poco su algoritmo para calcular el ángulo: actualmente solo registra la diferencia absoluta en la posición, pero necesita la diferencia relativa (es decir, puede ser positiva o negativa dependiendo del posicionamiento).
fuente
MapX
es 100,T.X
es 90 yS.X
es 10.dx
claramente debería ser 20, ¡pero este algoritmo devolverá 30!En un mundo así, hay un número infinito de caminos de S a T. Denotemos las coordenadas de T por
(Tx, Ty)
, las coordenadas de S por(Sx, Sy)
y el tamaño del mundo por(Wx, Wy)
. Las coordenadas envueltas de T son(Tx + i * Wx, Ty + j * Wy)
, dondei
yj
son enteros, es decir, elementos del conjunto{..., -2, -1, 0, 1, 2, ...}
. Los vectores que conectan S a T son(Dx, Dy) := (Tx + i * Wx - Sx, Ty + j * Wy - Sy)
. Para un(i, j)
par dado , la distancia es la longitud del vectorsqrt(Dx * Dx + Dy * Dy)
, y la dirección en radianes esatan(Dy / Dx)
. El camino más corto es uno de los 9 caminos, dondei
yj
están en{-1, 0, 1}
:Los valores
i
yj
para la ruta más corta se pueden determinar directamente:¡Gracias, @IlmariKaronen, @SamHocevar y @romkyns por su ayuda!
fuente
abs(Tx-Sx) < Wx/2
, entoncesi=0
es óptimo; de lo contrario, la opción óptima esi=-1
oi=1
, dependiendo del signo deTx-Sx
. Lo mismo vale paraTy-Sy
yj
.Calcule un vector de dirección posible, incluso si no es el más corto, luego ajuste su coordenada X para que esté en el
[-MapX/2,MapX/2]
rango, y lo mismo para Y:¡Eso es! También obtienes la distancia sin más cálculos:
fuente
vec2 toroidalNearestWay (vec2 from, vec2 to, vec2 mapSize) { return (mod((to - from + 3.0 * mapSize / 2.0), mapSize)) - mapSize / 2.0; }
Supongo que hay varias maneras de hacer esto. Aquí hay 2 que puedo pensar en la parte superior de mi cabeza:
# 1: maneje los estuches manualmente
Hay exactamente 10 casos que pueden suceder:
S
Sin embargo, para cada uno de los mosaicos circundantes, son permutaciones de diferentes cálculos para el componente de distancia X o Y. Debido a que es un número finito de casos, puede simplemente codificar cómo calcularlos y encontrar la distancia más corta entre todos ellos.
Aquí hay una ilustración de 2 casos para encontrar
dx
. El caso 1, dondeT
está en el mismo mosaico queS
, dx es justoS.x - T.x
. Para los mosaicos a la derecha,dx
se calculará comoTileWidth - S.x + T.x
.Como una pequeña optimización, encuentre la distancia mínima antes de sacar una raíz cuadrada. Luego te ahorras hasta 7
sqrt
llamadas.# 2: Resumen las coordenadas
Si necesita hacer algo más espacialmente "fluido", como un algoritmo de búsqueda de ruta, simplemente abstraiga las coordenadas para que su algoritmo de búsqueda de ruta ni siquiera se dé cuenta de que el mundo está hecho de mosaicos repetitivos. El algoritmo de búsqueda de ruta podría ir infinitamente en cualquier dirección teóricamente (bueno, bueno, estarás limitado por límites numéricos, pero obtienes el punto).
Para el cálculo de distancia simple, no te molestes en hacer esto.
fuente
No te molestes con las "9 direcciones". La razón es que hay 5 casos degenerados entre esos 9: "recto norte", "recto oeste", "recto sur", "recto este" e "idéntico". Por ejemplo, el norte recto es degenerado porque representa el caso donde el noroeste y el noreste se unen y producen el mismo resultado.
Por lo tanto, tiene 4 direcciones para calcular y puede elegir el mínimo.
fuente
Gracias por todas las respuestas al final, utilicé Toomai editado por Scott Chamberlain. También tuve que hacer algunos cambios debido al hecho de que mi sistema de coordenadas comienza con y en la parte superior izquierda y aumenta a medida que avanza (básicamente invertido en comparación con las coordenadas de gráfico normales para y).
He publicado en caso de que alguien más encuentre esta página y tenga el mismo sistema invertido.
fuente
y
en la parte superior. Se debe a que el comportamiento deseado es supuestamente envolver las coordenadas en el borde mundial, mientras que el código que reutilizó reflejó las coordenadas en cada límite.