Jak określić długość ścieżki?


11

Mam grę, która wymaga, aby każdy gracz poruszał się jedną określoną ścieżką. Rysuję ścieżkę za pomocą krzywych Béziera. Jak mogę określić całkowitą rzeczywistą (nieliniową) długość ścieżki i odległość, jaką pokonał każdy gracz? (Odległość między punktem początkowym a określonym punktem na ścieżce).

AKTUALIZACJA:

Ścieżka jest reprezentowana w płaszczyźnie kartezjańskiej (2D).


Odpowiedź na twoje pytanie znajduje się u dołu tej odpowiedzi
BlueRaja - Danny Pflughoeft

Odpowiedzi:


7

Jak powiedzieli poprzednie odpowiedzi, obliczenie długości krzywej Beziera jest trudne ( niemożliwe ?). Powiedziałbym, że 100% gier wykorzystuje przybliżoną długość, która jest prawie zawsze wystarczająco dokładna.

Kilka miesięcy temu wdrożyłem go, stosując proponowane podejście polegające na podzieleniu krzywej na „małe” segmenty i dodaniu ich długości. Jest przykładem realizacji C ++ tutaj .


11

Pomiar długości krzywej Beziera jest trudny. Jeśli nie przeszkadza ci niewielka niedokładność, prostym rozwiązaniem byłoby przybliżenie krzywych Beziera liniami prostymi i obliczenie sumy długości linii. Im więcej segmentów utworzysz, tym lepsze zbliżenie.


Mogę to rozważyć, ale jak mogę określić, ile segmentów powinienem mieć i jak mogę mapować segmenty, aby ich punkt początkowy i końcowy znajdowały się na mojej ścieżce? Czy ta technika ma nazwę? (więc szukam go w Google)
Valentin Radu

Prostym podejściem byłoby po prostu użycie liniowego rozkładu punktów od B (0) do B (1) ... podobnie jak coś, czego użyłbyś do wykreślenia krzywej. Spójrz na kod źródłowy w odpowiedzi Dana.
bummzack

Byłbym wdzięczny za wyjaśnienie głosowania w dół, by wiedzieć, co mógłbym poprawić w swojej odpowiedzi ...
bummzack,

7

Parametryzacja długości splajnu wyższego rzędu (tj. Większego niż 1 rząd) musi być aproksymowana; nie można go przedstawić bezpośrednio, stąd fakt, że nie jest łatwo znaleźć bezpośrednie rozwiązanie tego problemu.

Niektóre istniejące implementacje (kod kopiuj-wklej):

Stosując przybliżenia Czebyszewa , według autorów, dokładność rośnie wraz ze wzrostem wielkości krzywej. Spójrz na pseudokod pp. 7-8, reszta to opis innych algorytmów, na których oparli swoje podejście, które możesz zignorować. Wiele odnośników online określa tę metodę jako dobrą.

Zobacz także te zwięzłe podejścia.


5

Zaczęło się to jako komentarz do komentarza do odpowiedzi @ bummzack, ale stało się zbyt długie.

jak mogę określić, ile segmentów powinienem mieć

Istnieją dwa podejścia. Pierwszy to tylko standardowy algorytm renderowania krzywej Béziera: punkty kontrolne tworzą obwiednię krzywej, więc jeśli wszystkie punkty kontrolne znajdują się w epsilon odcinka linii od punktu początkowego do punktu końcowego, przybliżamy go jako linię; w przeciwnym razie dzielisz za pomocą algorytmu de Casteljau. Epsilon jest wybierany zgodnie z błędem, jaki chcesz uzyskać w wyniku końcowym. (Do renderowania jest to zwykle 0,5 piksela).

Drugim podejściem jest udoskonalenie tego przy użyciu arytmetyki przedziałowej. Weź długość linii od początku do końca jako dolną granicę, a sumę długości linii przechodzących przez punkty kontrolne jako górną granicę. Ponownie podziel według wymagań ostatecznych błędów.

Zwykle dzieli się na t = 0,5, ale algorytm de Casteljau pozwala na podział w dowolnym punkcie, więc jeśli masz sześcienny Bézier z punktami kontrolnymi od C_0 do C_3, a C_2 jest znacznie bliżej segmentu linii między punktami końcowymi niż C_1, możesz zauważyć, że podział jeden z 1/3 lub 2/3 daje mocniejsze granice. Nie analizowałem algebry, aby uzasadnić, która opcja byłaby lepsza, ale możesz eksperymentować i składać raporty, jeśli chcesz. Jeśli nic więcej, chciałem zaznaczyć, że istnieje taka opcja.


3

Obliczenia długości sparametryzowanej krzywej można dokonać, biorąc całkę z sqrt ((dx / dt) ² + (dy / dt) ²), gdzie dx / dt jest pochodną składowej x krzywej i dy / dt jest pochodną składowej y krzywej. W przypadku splajnu Béziera te dwa są takie same, ponieważ równanie można rozszerzyć na dowolny wymiar.

Wzór na sześcienną splajn Béziera jest następujący: B (t) = (1 - t³) * P0 + 3 (1 - t) ²t * P1 + 3 (1 - t) t² * P2 + t³ P3 gdzie P0 do P3 to punkty kontrolne.

Według Wolfram | Alpha pochodna tego wzoru to: d (B (t)) / dt = 3 (t (t (P3 - P0) + P2 (2 - 3t) + P1 (3t² - 4t + 1))

Teraz możesz umieścić to z powrotem w równaniu długości krzywej i obliczyć całkę od t = 0 do t = 1. Niestety, Wolfram | Alpha przekroczył limit czasu, gdy próbuję to zrobić. Możesz jednak dokonać integracji numerycznej.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.