Czy mogę uprościć nierówność „odległość (p1, p2) <odległość (p1, p3)?”


14

Pracuję nad pewną logiką wektorową, więc pytam: czy mogę zaoszczędzić czas procesora, upraszczając tę ​​nierówność:

distance(vector1, vector2) < distance(vector1, vector3)

Widzę, że vector1powtarza się to w obu przypadkach.


10
Krótka uwaga: twoja obecna metoda jest bardzo czytelna, a jej funkcję można natychmiast zrozumieć. Niektóre z tych odpowiedzi mogą zrealizować zlecone zadanie, ale są znacznie mniej jasne. Jest to w porządku, jeśli wydajność ma zasadnicze znaczenie, ale pamiętaj, aby odpowiednio ją skomentować, aby uwzględnić utratę przejrzystości.
MikeS

3
Aby kontynuować komentarz @ MikeS, wydajność powinna być istotna tylko w takich przypadkach, jeśli wykonałeś już analizę lub profilowanie i zidentyfikowałeś to wezwanie jako wąskie gardło. Utrzymywalność przewyższa surową wydajność, jeśli mówimy o różnicy między 305 fps a 303 fps.
Phoshi

Odpowiedzi:


24

tak , możesz to uprościć. Po pierwsze, przestań nazywać je wektorami. Są punktami. Nazwijmy je A, Bi C.

Chcesz tego:

dist(A, B) < dist(A, C)

Wymienić odległości z odległościami do kwadratu, a następnie iloczyn skalarny (z definicji długości euklidesowej . Wymień ACzAB + BC (obecnie są to rzeczywiste wektory) Rozwiń, uproszczenia, czynnik.:

dist(A, B < dist(A, C
dot(AB, AB) < dot(AC, AC)
dot(AB, AB) < dot(AB + BC, AB + BC)
dot(AB, AB) < dot(AB, AB) + dot(BC, BC) + 2 dot(AB, BC)
0 < dot(BC, BC) + 2 dot(AB, BC)
0 < dot(BC + 2 AB, BC)

Tutaj jesteś:

dot(AB + AC, BC) > 0

Za pomocą notacji wektorowej:

dot(v2 - v1 + v3 - v1, v3 - v2) > 0

To kilka dodatków i jeden produkt kropkowy zamiast poprzednich dwóch produktów kropkowych.


Czy możesz wyjaśnić, jak możesz zastąpić a + b b = a a + c c wersją produktu kropkowego?
TravisG,

2
@TravisG Nie jestem pewien, o co pytasz. Jeśli twoje pytanie brzmi, dlaczego dist(A, B)²jest to samo dot(AB, AB), pochodzi od samej definicji długości euklidesowej .
sam hocevar,

2
Oczywiście to (nieco) upraszcza matematyczne równanie, ale niekoniecznie „oszczędza czas procesora” dla OP. Powoduje to większą złożoność i więcej obliczeń niż usunięcie pierwiastka kwadratowego z pierwotnych równań odległości.
MichaelHouse

1
Popraw mnie, jeśli się mylę, ale dwa iloczyny to 5 operacji na iloczyn iloczynu plus dwa odejmowania vec3, co łącznie daje 16 operacji, na twojej drodze są 3 odejmowania vec3 plus dodatek, który daje 12 operacji plus iloczyn kropki sprawia, że ​​17.
Luis W

2
Co ciekawe, wynikiem jest iloczyn iloczynu dwóch przeciwnych przekątnych równoległoboku. Ale to nie ma znaczenia. Chciałem powiedzieć, że z tego pełnego uproszczenia nie można uzyskać ogromnej kwoty ; jak wspomnieli inni, robi to całkiem przyzwoicie, aby zaciemnić lub skomplikować to, co faktycznie próbujesz obliczyć. Jednak zdecydowanie chcesz skorzystać z pierwszego kroku. Zawsze warto tego unikać. Samo porównanie kwadratów odległości jest takie samo, ponieważ odległość jest dodatnia, nawet w płaszczyźnie złożonej.
TASagent

16

Tak.Zakładając, że distancefunkcja używa pierwiastka kwadratowego, możesz to uprościć, usuwając pierwiastek kwadratowy.

Próbując znaleźć większą (lub mniejszą) odległość, x^2 > y^2 nadal obowiązuje x > y.

Jednak dalsze próby matematycznego uproszczenia równania są prawdopodobnie bezcelowe. Odległość między vector1i vector2nie jest taka sama jak odległość między vector1i vector3. Chociaż równanie można uprościć matematycznie, jak pokazuje odpowiedź Sama , forma, w jakiej się obecnie znajduje, jest prawdopodobnie tak prosta, jak to możliwe z perspektywy użycia procesora.


Nie mam wystarczającej liczby przedstawicieli, ale uważam, że jest to zasadniczo niepoprawne: „czy mogę zaoszczędzić czas procesora, upraszczając tę ​​nierówność?” Odpowiedź brzmi tak.
jestem tak zdezorientowany

Odpowiedź jest twierdząca tylko wtedy, gdy równanie odległości wykorzystuje pierwiastek kwadratowy. Które wspominam.
MichaelHouse

Ważny punkt, wycofałbym moje oświadczenie. Jednak jest 99% gwarancji, że użytkownik oznacza euklidesową odległość sqrt (suma (różnice w wymiarach do kwadratu))
jestem tak zdezorientowany

@imsoconfused W porządku, zmieniłem kolejność mojej odpowiedzi, aby najpierw podać najbardziej prawdopodobny (99%) scenariusz.
MichaelHouse

2
Tak, z mojego doświadczenia wynika, że ​​gdy masz do czynienia z tego rodzaju rzeczami, funkcja DistanceSquared jest bardzo przydatna. Jest to równie jasne i pozwala uniknąć kosztownej operacji sqrt.
Loren Pechtel

0

Niektóre matematyki mogą pomóc.

To, co próbujesz zrobić, to:

<v1, v2> < <v1, v3> =>
sqrt((y2-y1)^2+(x2-x1)^2) < sqrt((y3-y1)^2+(x3-x1)^2) =>
y2^2 - 2*y2y1 + y1^2 + x2^2 - 2*x2x1 + x1^2 < y3^2 - 2*y3y1 + y1^2 + x3^2 - 2*x3x1 + x1^2

Z tego, co możesz usunąć powtarzające się zmienne i pogrupować kilka innych. Operacja, którą musisz sprawdzić, to:

y3^2 - y2^2 - 2*y1(y3-y2) + x3^2 - x2^2 - 2*x1(x3-x2) > 0

Mam nadzieję, że to pomoże.


-1

Prawdziwe pytanie wydaje się być to, jak ograniczyć obliczenia do określania najbliższego obiektu?

Optymalizacja jest często przeprowadzana w grach, chociaż przy wszystkich optymalizacjach powinna być prowadzona przez profil i często nie upraszcza rzeczy.

Sposobem uniknięcia niepotrzebnych obliczeń odległości w celu ustalenia najbliższej rzeczy - lub wszystkich rzeczy w określonym zakresie - jest użycie indeksu przestrzennego, np. Oktetu . .

Opłaca się to tylko w przypadku dużej liczby obiektów. W przypadku zaledwie trzech przedmiotów jest mało prawdopodobne, aby się spłaciło i na pewno nie upraszcza kodu.


4
Myślę, że rzeczywiste pytanie jest dość proste i ta odpowiedź nie rozwiązuje tego. Jeśli chcesz spekulować, co do głębszych, nieopowiedzianych pytań OP, to naprawdę powinno być zrobione jako komentarz, jeśli nie masz zamiaru odpowiedzieć na zadane pytanie.

Głosuję za tym, ponieważ powoływanie się na ewentualną przedwczesną optymalizację nie jest odpowiedzią na problem, w którym wyraźna optymalizacja nie szkodzi ani czytelności, ani konserwacji kodu, ani nie zachęca do niejasnych praktyk. Jeśli możesz napisać prosty i zoptymalizowany kod, dlaczego tego nie zrobić? Z pewnością nie zaszkodzi to zrobić, nawet jeśli masz plan wyższego poziomu (żaden twórca gier nigdy nie odmówi dodatkowych mikrosekund na klatkę, szczególnie na konsolach).
teodron

@teodron: „Jeśli możesz napisać prosty i zoptymalizowany kod, dlaczego tego nie zrobić?” - Ponieważ OP (a teraz i my) spędził teraz znaczącą ilość czasu na optymalizacji czegoś, co może nie przynieść mu żadnych korzyści.
BlueRaja - Danny Pflughoeft

@ BlueRaja-DannyPflughoeft Zgadzam się z tym, że jest to drobna sprawa (stąd nieznaczna optymalizacja przy kilkuset wywołaniach na ramkę, ale jeśli współczynnik wielkości wzrośnie do tysięcy, rzeczy na pewno się zmienią). Jednak wszyscy mamy swobodę, aby nie marnować czasu na próby odpowiedzi / optymalizacji czegoś, co uważamy za nieopłacalne. PO poprosił o jedną rzecz, ludzie założyli, że PO nie był świadomy strategii wyższego poziomu i praktyk profilowania. Osobiście wolę robić takie uwagi w komentarzach, a nie w odpowiedziach. Przepraszamy za bycie tak gadatliwym :(.
teodron

-3

zależy to od tego, jaka jest wydajność odległości (v1, v2)

jeśli jest to liczba dziesiętna (liczba zmiennoprzecinkowa lub podwójna) nad wektorem, prawdopodobne jest, że pokonane odległości byłyby znacznie szybsze


5
Nie rozumiem, co to floatma wspólnego z niczym.
MichaelHouse


5
Nie byłem celowo nieporozumieniem. Nadal nie jestem pewien, co masz na myśli. Nie wiem, dlaczego funkcja odległości zwróciłaby wektor.
MichaelHouse
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.