Muszę znaleźć najkrótszą odległość od jednego punktu w moim świecie 2D do innego punktu, w którym krawędzie są owinięte (jak asteroidy itp.). Wiem, jak znaleźć najkrótszą odległość, ale staram się znaleźć kierunek.
Najkrótszą odległość podaje:
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));
Przykład świata
:
: T
:
:--------------:---------
: :
: S :
: :
: :
: T :
: :
:--------------:
Na schemacie krawędzie pokazano za pomocą: i -. W prawym górnym rogu pokazałem też zawinięte powtórzenie świata. Chcę znaleźć kierunek w stopniach od S do T. Więc najkrótsza odległość to powtórzenie T. w prawym górnym rogu, ale jak obliczyć kierunek w kierunku od S do powtarzanego T w prawym górnym rogu?
Znam pozycje zarówno S, jak i T, ale przypuszczam, że muszę znaleźć pozycję powtarzanej T, ale tam więcej niż 1.
Układ współrzędnych światów zaczyna się od 0,0 w lewym górnym rogu i 0 stopni, aby kierunek mógł zacząć się na Zachodzie.
Wygląda na to, że nie powinno to być zbyt trudne, ale nie byłem w stanie znaleźć rozwiązania. Mam nadzieję, że ktoś może pomóc? Wszelkie strony będą mile widziane.
Odpowiedzi:
Będziesz musiał nieco ulepszyć algorytm, aby obliczyć kąt - obecnie rejestrujesz tylko bezwzględną różnicę pozycji, ale potrzebujesz różnicy względnej (tzn. Może być dodatnia lub ujemna w zależności od pozycjonowania).
źródło
MapX
jest to 100,T.X
to 90 iS.X
to 10.dx
powinno być wyraźnie 20, ale ten algorytm zwróci 30!W takim świecie istnieje nieskończona liczba ścieżek od S do T. Oznaczmy współrzędne T przez
(Tx, Ty)
, współrzędne S przez(Sx, Sy)
i wielkość świata według(Wx, Wy)
. Zawinięte współrzędne T są(Tx + i * Wx, Ty + j * Wy)
, gdziei
ij
są liczbami całkowitymi, to znaczy elementami zestawu{..., -2, -1, 0, 1, 2, ...}
. Wektory łączące S z T to(Dx, Dy) := (Tx + i * Wx - Sx, Ty + j * Wy - Sy)
. Dla danej(i, j)
pary odległość jest długością wektorasqrt(Dx * Dx + Dy * Dy)
, a kierunek w radianach toatan(Dy / Dx)
. Najkrótszej ścieżki jest jednym z tych, w których ścieżki 9i
ij
są w{-1, 0, 1}
:Wartości
i
ij
dla najkrótszej ścieżki można określić bezpośrednio:Dziękuję, @IlmariKaronen, @SamHocevar i @romkyns za pomoc!
źródło
abs(Tx-Sx) < Wx/2
, toi=0
jest optymalne; w przeciwnym razie optymalnym wyborem jesti=-1
lubi=1
, w zależności od znakuTx-Sx
. To samo dotyczyTy-Sy
ij
.Oblicz jeden możliwy wektor kierunku, nawet jeśli nie jest on najkrótszy, a następnie zawiń jego współrzędną X, aby znajdowała się w
[-MapX/2,MapX/2]
zakresie, i to samo dla Y:To jest to! Otrzymujesz również odległość bez dalszych obliczeń:
źródło
vec2 toroidalNearestWay (vec2 from, vec2 to, vec2 mapSize) { return (mod((to - from + 3.0 * mapSize / 2.0), mapSize)) - mapSize / 2.0; }
Sądzę, że jest na to wiele sposobów. Oto 2, o których mogę myśleć z góry:
# 1: Obsługuj skrzynki ręcznie
Jest dokładnie 10 przypadków, które mogą się zdarzyć:
S
Jednak dla każdej z otaczających płytek są to kombinacje różnych obliczeń dla komponentu odległości X lub Y. Ponieważ jest to skończona liczba przypadków, możesz po prostu ustalić, jak je obliczyć i znaleźć najkrótszą odległość między nimi wszystkimi.
Oto ilustracja 2 przypadków do znalezienia
dx
. Przypadek 1, gdzieT
jest na tym samym kafelku coS
, dx jest po prostuS.x - T.x
. Dla płytek po prawejdx
stronie zostanie obliczony jakoTileWidth - S.x + T.x
.W ramach małej optymalizacji znajdź minimalną odległość przed pierwiastkiem kwadratowym. Następnie oszczędzasz do 7
sqrt
połączeń.# 2: Wyodrębnij współrzędne
Jeśli potrzebujesz zrobić coś bardziej „płynnego” przestrzennie, na przykład algorytm znajdowania ścieżki, po prostu wyodrębnij współrzędne, aby algorytm znajdujący ścieżkę nawet nie zdawał sobie sprawy, że świat składa się z powtarzających się kafelków. Algorytm znajdowania ścieżki może teoretycznie iść w dowolnym kierunku w dowolnym kierunku (no cóż, będziesz ograniczony limitami liczbowymi, ale dostaniesz sens).
Dla prostego obliczania odległości nie zawracaj sobie tym głowy.
źródło
Nie przejmuj się „9 kierunkami”. Powodem jest to, że wśród tych 9 jest 5 zdegenerowanych przypadków: „prosto na północ”, „prosto na zachód”, „prosto na południe”, „prosto na wschód” i „identycznie”. Na przykład prosta północ jest zdegenerowana, ponieważ reprezentuje przypadek, w którym północno-zachodni i północny wschód łączą się i dają ten sam wynik.
Zatem masz 4 kierunki do obliczenia i możesz po prostu wybrać minimum.
źródło
Dzięki za wszystkie odpowiedzi na końcu użyłem Toomai pod redakcją Scotta Chamberlaina. Miałem też kilka zmian ze względu na fakt, że mój układ współrzędnych zaczyna się od y w lewym górnym rogu i rośnie wraz z ruchem w dół (zasadniczo odwrócony w porównaniu do normalnych współrzędnych wykresu dla y).
Wysłałem na wypadek, gdyby ktokolwiek znalazł tę stronę i miał ten sam system.
źródło
y
na szczycie. Jest tak, ponieważ pożądane zachowanie ma zawijać współrzędne na krawędzi świata, podczas gdy ponownie użyty kod odzwierciedlał współrzędne na każdej granicy.