J'ai besoin de trouver la direction de distance la plus courte d'un point dans mon monde 2D à un autre point où les bords sont enveloppés (comme des astéroïdes, etc.). Je sais comment trouver la distance la plus courte, mais j'ai du mal à trouver la direction dans laquelle elle se trouve.
La distance la plus courte est donnée par:
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));
Exemple du monde
:
: T
:
:--------------:---------
: :
: S :
: :
: :
: T :
: :
:--------------:
Dans le diagramme, les bords sont représentés par: et -. J'ai également montré une répétition enveloppée du monde en haut à droite. Je veux trouver la direction en degrés de S à T. Donc, la distance la plus courte est vers la répétition en haut à droite de T. mais comment puis-je calculer la direction en degrés de S vers le T répété en haut à droite?
Je connais les positions de S et de T mais je suppose que je dois trouver la position du T répété mais il y en a plus de 1.
Le système de coordonnées des mondes commence à 0,0 en haut à gauche et 0 degrés pour la direction pourrait commencer à l'ouest.
Il semble que cela ne devrait pas être trop difficile, mais je n'ai pas pu trouver de solution. J'espère que quelqu'un peut aider? Tous les sites Web seraient appréciés.
Réponses:
Vous devrez modifier un peu votre algorithme pour calculer l'angle - actuellement, vous enregistrez uniquement la différence absolue de position, mais vous avez besoin de la différence relative (c'est-à-dire qu'elle peut être positive ou négative selon le positionnement).
la source
MapX
100,T.X
90 etS.X
10.dx
soient clairement 20, mais cet algorithme renverra 30!Dans un tel monde, il existe un nombre infini de chemins de S à T. Notons les coordonnées de T par
(Tx, Ty)
, les coordonnées de S par(Sx, Sy)
et la taille du monde par(Wx, Wy)
. Les coordonnées enveloppées de T sont(Tx + i * Wx, Ty + j * Wy)
, oùi
etj
sont des entiers, c'est-à-dire des éléments de l'ensemble{..., -2, -1, 0, 1, 2, ...}
. Les vecteurs reliant S à T le sont(Dx, Dy) := (Tx + i * Wx - Sx, Ty + j * Wy - Sy)
. Pour une(i, j)
paire donnée , la distance est la longueur du vecteursqrt(Dx * Dx + Dy * Dy)
, et la direction en radians estatan(Dy / Dx)
. Le chemin le plus court est l' un des 9 chemins, oùi
etj
sont{-1, 0, 1}
:Les valeurs
i
etj
pour le chemin le plus court peuvent être déterminées directement:Merci, @IlmariKaronen, @SamHocevar et @romkyns pour votre aide!
la source
abs(Tx-Sx) < Wx/2
, alorsi=0
est optimal; sinon le choix optimal esti=-1
oui=1
, selon le signe deTx-Sx
. Il en va de même pourTy-Sy
etj
.Calculez un vecteur de direction possible, même s'il n'est pas le plus court, puis enveloppez sa coordonnée X pour qu'elle soit dans la
[-MapX/2,MapX/2]
plage, et même pour Y:C'est ça! Vous obtenez également la distance sans autres calculs:
la source
vec2 toroidalNearestWay (vec2 from, vec2 to, vec2 mapSize) { return (mod((to - from + 3.0 * mapSize / 2.0), mapSize)) - mapSize / 2.0; }
Je suppose qu'il y a plusieurs façons de procéder. Voici 2 que je peux penser du haut de ma tête:
# 1: Gérer les étuis manuellement
Il y a exactement 10 cas qui peuvent se produire:
S
Pour chacune des tuiles environnantes, ce sont des permutations de différents calculs pour la composante de distance X ou Y. Comme il s'agit d'un nombre fini de cas, vous pouvez simplement coder en dur comment les calculer et trouver la distance la plus courte entre tous.
Voici une illustration de 2 cas à trouver
dx
. Cas 1, oùT
est dans la même tuile queS
, dx est justeS.x - T.x
. Pour les tuiles à droite,dx
sera calculé commeTileWidth - S.x + T.x
.Pour une petite optimisation, trouvez la distance minimale avant de prendre une racine carrée. Ensuite, vous vous enregistrez jusqu'à 7
sqrt
appels.# 2: Résumé des coordonnées
Si vous avez besoin de faire quelque chose de plus fluide "spatialement", comme un algorithme de recherche de chemin, il suffit d'abstraire les coordonnées pour que votre algorithme de recherche de chemin ne réalise même pas que le monde est fait de tuiles répétitives. Théoriquement, l'algorithme de recherche de chemin peut aller à l'infini dans n'importe quelle direction (bon, vous serez limité par des limites numériques, mais vous obtenez le point).
Pour un calcul de distance simple, ne vous embêtez pas à le faire.
la source
Ne vous embêtez pas avec les "9 directions". La raison en est qu'il y a 5 cas dégénérés parmi ces 9: "nord droit", "ouest droit", "sud droit", "est est" et "identique". Par exemple, le nord droit est dégénéré car il représente le cas où le nord-ouest et le nord-est se rejoignent et produisent le même résultat.
Ainsi, vous avez 4 directions à calculer et vous pouvez simplement choisir le minimum.
la source
Merci pour toutes les réponses à la fin, j'ai utilisé Toomai édité par Scott Chamberlain. J'ai également dû faire quelques changements car mon système de coordonnées commence par y en haut à gauche et augmente à mesure que vous descendez (essentiellement inversé par rapport aux coordonnées normales du graphique pour y).
J'ai posté au cas où quelqu'un d'autre trouverait cette page et aurait le même système y inversé.
la source
y
en haut. C'est parce que le comportement souhaité est censé envelopper les coordonnées à la limite du monde, tandis que le code que vous avez réutilisé reflétait les coordonnées à chaque frontière.