Biorąc pod uwagę punkty linii i kwadratową krzywą Beziera, jak obliczyć ich najbliższy punkt? .... Podobnie, biorąc pod uwagę punkty 2 krzywych, jak uzyskać najbliższy punkt?
Oto moja próba. Poniższe algorytmy są dalekie od ideału , ale są proste i uważam, że powinieneś zacząć od tego, sprawdzić, czy działają w twojej sytuacji, i przejść na coś szybszego i / lub dokładniejszego później.
Pomysł jest następujący:
Próbkuj krzywą Béziera, znajdź najbliższy punkt na tej próbce
Próbkuj okolicę wokół znalezionego punktu, znajdź nowy najbliższy punkt
Kontynuuj, aż punkt nie zmieni się już wiele
Algorytm odległości od krzywej Béziera do linii
Krzywa Béziera jest parametryzowana przez funkcję F(t)wykorzystującą zestaw punktów kontrolnych i zmienny parametr t. Liczba punktów generujących jest nieistotna.
Linia jest parametryzowana dwoma punktami Ai B.
Niech SAMPLES = 10na przykład
Zacznij od t0 = 0it1 = 1
Pozwolić dt = (t1 - t0) / SAMPLES
Jeśli dt < 1e-10(lub jakikolwiek inny warunek dokładności, który uznasz za odpowiedni), algorytm jest zakończony i odpowiedź brzmiF(t0) .
Oblicz listę SAMPLES + 1punktów na krzywej Béziera:
L[0] = F(t0)
L[1] = F(t0 + dt)
L[2] = F(t0 + 2 * dt)
…
L[SAMPLES] = F(t0 + SAMPLES * dt)
Znajdź punkt Lz indeksem inajbliższy linii. Użyj dowolnej znanej metody odległości punkt / linia , na przykład odległości kwadratowej, ||AB^L[i]A||² / ||AB||²gdzie ^oznacza iloczyn krzyżowy i ||…||jest odległością.
Jeśli i == 0ustaw i = 1; jeśli i == SAMPLES, ustawi = SAMPLES - 1
Niech t1 = t0 + (i + 1) * dtit0 = t0 + (i - 1) * dt
Wróć do kroku 3.
Algorytm odległości od krzywej Béziera do krzywej Béziera
Tym razem mamy dwie krzywe Béziera, parametryzowane przez F(t)i G(t).
Niech SAMPLES = 10na przykład
Start z t0 = 0, t1 = 1, s0 = 0is1 = 1
Pozwolić dt = (t1 - t0) / SAMPLES
Pozwolić ds = (s1 - s0) / SAMPLES
Jeśli dt < 1e-10(lub jakikolwiek inny warunek dokładności, który uznasz za odpowiedni), algorytm jest zakończony i odpowiedź brzmiF(t0) .
JEŻELI jest to pierwszy przebieg pętli:
6.1 Oblicz listę SAMPLES + 1punktów na F( patrz wyżej ).
6.2 Oblicz listę SAMPLES + 1punktów na G.
6.3 Znajdź, która para punktów jest najbliżej siebie.
6.4 Aktualizacja t0, t1, s0, s1jak widać powyżej.
ELSE : alternatywnie obliczyć listę punktów na FOR listę punktów G, które następnie znaleźć punkt Fjest najbliżej G(s0)i aktualizacji t0oraz t1, LUB która punktu Gjest najbliżej F(t0)i aktualizacji s0oraz s1.
Wróć do kroku 3.
Problemy
Z założenia algorytmy te zawsze będą zbieżne do lokalnego minimum. Nie ma jednak gwarancji, że zostaną one dostosowane do najlepszego rozwiązania. W szczególności algorytm krzywej Béziera wcale nie jest zbyt dobry, aw przypadku, gdy dwie krzywe znajdują się blisko siebie w wielu miejscach, możesz niestety przegapić rozwiązanie z dużej odległości.
Ale jak powiedziałem, zanim zaczniesz myśleć o bardziej solidnych rozwiązaniach, powinieneś najpierw poeksperymentować z tymi prostymi.
1) Przetłumacz wszystko na jedną oś, więc zamiast obliczać długość jednego punktu do „linii”, „linią” jest, powiedzmy, oś Y.
Potem, biorąc pod uwagę krzywą Beziera, powiedziałbym, że zależy to od liczby punktów kontrolnych.
Jeśli są trzy, (początek, „kontrola” i koniec) zrobiłbym jakiś skan (powiedz każdy o kilka procent, a następnie dopracuj między najbliższymi (stosując powiedzmy podejście „binarne”).
Więcej punktów Wypróbuję parę, która była najbliżej (przetłumaczona oś Y).
Jestem pewien, że matematyk może dać ci dokładne rozwiązanie (w matematyce), ale jeśli chcesz znaleźć / rozwiązanie w grze wideo, może być lepiej z nieco ok rozwiązanie, ponieważ prawdziwe rozwiązanie może zawierać kilka odpowiedzi ( Nie mówię nawet o mocy obliczeniowej).
W przypadku krzywej Beziera - przypadek linii prostej, najdokładniejszym sposobem na znalezienie odpowiedzi jest wykonanie następujących czynności:
Przekształć problem tak, aby linia prosta była zawsze pozioma przy Y = 0. Odbywa się to przez pomnożenie wszystkich punktów kontrolnych przez odpowiednią macierz afiniczną. (Zakładam, że znasz reprezentację przekształceń afinicznych płaszczyzny za pomocą macierzy 3x3 z 3 ustalonymi wpisami.)
Sprawdź współrzędne Y punktów kontrolnych. Jeśli nie wszystkie mają ten sam znak, może wystąpić przecięcie z linią. Oblicz pierwiastki części Y krzywej Beziera. W przypadku wielomianów można użyć dowolnej metody wyszukiwania pierwiastków, jest ich mnóstwo w literaturze. Na przykład google „wypukły marsz kadłuba” - jest to dość dobra metoda dla wielomianów używanych w krzywych Beziera. Każdy znaleziony pierwiastek jest wartością czasową przecięcia z linią, gdzie odległość wynosi zero - praca jest zakończona.
Jeśli wszystkie współrzędne Y mają ten sam znak, oblicz pochodną części Y krzywej Beziera. Możesz zignorować współrzędne X punktów, ponieważ nie mają one znaczenia - linia docelowa jest pozioma. Znajdź korzenie tej pochodnej. Są to wartości czasu, w których krzywa jest lokalnie najbliżej linii.
Jawnie oceń krzywą Beziera dla wszystkich pierwiastków znalezionych w poprzednim kroku i zgłoś pierwiastek, który daje najmniejszą odległość od linii. Musisz także sprawdzić punkty końcowe - mogą dać mniejszą odległość niż jakikolwiek root.
Odpowiedzi:
Oto moja próba. Poniższe algorytmy są dalekie od ideału , ale są proste i uważam, że powinieneś zacząć od tego, sprawdzić, czy działają w twojej sytuacji, i przejść na coś szybszego i / lub dokładniejszego później.
Pomysł jest następujący:
Algorytm odległości od krzywej Béziera do linii
Krzywa Béziera jest parametryzowana przez funkcję
F(t)
wykorzystującą zestaw punktów kontrolnych i zmienny parametrt
. Liczba punktów generujących jest nieistotna.Linia jest parametryzowana dwoma punktami
A
iB
.Niech
SAMPLES = 10
na przykładZacznij od
t0 = 0
it1 = 1
Pozwolić
dt = (t1 - t0) / SAMPLES
Jeśli
dt < 1e-10
(lub jakikolwiek inny warunek dokładności, który uznasz za odpowiedni), algorytm jest zakończony i odpowiedź brzmiF(t0)
.Oblicz listę
SAMPLES + 1
punktów na krzywej Béziera:L[0] = F(t0)
L[1] = F(t0 + dt)
L[2] = F(t0 + 2 * dt)
L[SAMPLES] = F(t0 + SAMPLES * dt)
Znajdź punkt
L
z indeksemi
najbliższy linii. Użyj dowolnej znanej metody odległości punkt / linia , na przykład odległości kwadratowej,||AB^L[i]A||² / ||AB||²
gdzie^
oznacza iloczyn krzyżowy i||…||
jest odległością.Jeśli
i == 0
ustawi = 1
; jeślii == SAMPLES
, ustawi = SAMPLES - 1
Niech
t1 = t0 + (i + 1) * dt
it0 = t0 + (i - 1) * dt
Wróć do kroku 3.
Algorytm odległości od krzywej Béziera do krzywej Béziera
Tym razem mamy dwie krzywe Béziera, parametryzowane przez
F(t)
iG(t)
.Niech
SAMPLES = 10
na przykładStart z
t0 = 0
,t1 = 1
,s0 = 0
is1 = 1
Pozwolić
dt = (t1 - t0) / SAMPLES
Pozwolić
ds = (s1 - s0) / SAMPLES
Jeśli
dt < 1e-10
(lub jakikolwiek inny warunek dokładności, który uznasz za odpowiedni), algorytm jest zakończony i odpowiedź brzmiF(t0)
.JEŻELI jest to pierwszy przebieg pętli:
6.1 Oblicz listę
SAMPLES + 1
punktów naF
( patrz wyżej ).6.2 Oblicz listę
SAMPLES + 1
punktów naG
.6.3 Znajdź, która para punktów jest najbliżej siebie.
6.4 Aktualizacja
t0
,t1
,s0
,s1
jak widać powyżej.ELSE : alternatywnie obliczyć listę punktów na
F
OR listę punktówG
, które następnie znaleźć punktF
jest najbliżejG(s0)
i aktualizacjit0
orazt1
, LUB która punktuG
jest najbliżejF(t0)
i aktualizacjis0
orazs1
.Wróć do kroku 3.
Problemy
Z założenia algorytmy te zawsze będą zbieżne do lokalnego minimum. Nie ma jednak gwarancji, że zostaną one dostosowane do najlepszego rozwiązania. W szczególności algorytm krzywej Béziera wcale nie jest zbyt dobry, aw przypadku, gdy dwie krzywe znajdują się blisko siebie w wielu miejscach, możesz niestety przegapić rozwiązanie z dużej odległości.
Ale jak powiedziałem, zanim zaczniesz myśleć o bardziej solidnych rozwiązaniach, powinieneś najpierw poeksperymentować z tymi prostymi.
źródło
1) Przetłumacz wszystko na jedną oś, więc zamiast obliczać długość jednego punktu do „linii”, „linią” jest, powiedzmy, oś Y.
Potem, biorąc pod uwagę krzywą Beziera, powiedziałbym, że zależy to od liczby punktów kontrolnych.
Jeśli są trzy, (początek, „kontrola” i koniec) zrobiłbym jakiś skan (powiedz każdy o kilka procent, a następnie dopracuj między najbliższymi (stosując powiedzmy podejście „binarne”).
Więcej punktów Wypróbuję parę, która była najbliżej (przetłumaczona oś Y).
Jestem pewien, że matematyk może dać ci dokładne rozwiązanie (w matematyce), ale jeśli chcesz znaleźć / rozwiązanie w grze wideo, może być lepiej z nieco ok rozwiązanie, ponieważ prawdziwe rozwiązanie może zawierać kilka odpowiedzi ( Nie mówię nawet o mocy obliczeniowej).
źródło
Niektóre odpowiedzi ze strony blogu Algorytmist , która poprawnie znajduje najbliższy punkt na danej kwadratowej krzywej Béziera.
Demo .
źródło
W przypadku krzywej Beziera - przypadek linii prostej, najdokładniejszym sposobem na znalezienie odpowiedzi jest wykonanie następujących czynności:
źródło