Chcę sprawdzić, czy punkt znajduje się wewnątrz prostokąta, czy nie. Prostokąt może być zorientowany w dowolny sposób i nie musi być wyrównany do osi.
Jedną z metod, o których mogłem wymyślić, było obrócenie prostokąta i współrzędnych punktu w celu wyrównania osi prostokąta, a następnie po prostu przetestowanie współrzędnych punktu, czy leżą one w granicach prostokąta, czy nie.
Powyższa metoda wymaga rotacji, a więc operacji zmiennoprzecinkowych. Czy istnieje inny skuteczny sposób na zrobienie tego?
Odpowiedzi:
Jak jest reprezentowany prostokąt? Trzy punkty? Cztery punkty? Punkt, boki i kąt? Dwa punkty i bok? Coś innego? Nie wiedząc o tym, wszelkie próby odpowiedzi na twoje pytanie będą miały wyłącznie czysto akademicką wartość.
W każdym razie dla dowolnego wypukłego wielokąta (w tym prostokąta) test jest bardzo prosty: sprawdź każdą krawędź wielokąta, zakładając, że każda krawędź jest zorientowana w kierunku przeciwnym do ruchu wskazówek zegara i sprawdź, czy punkt leży po lewej stronie krawędzi (po lewej półpłaszczyzna ręczna). Jeśli wszystkie krawędzie przejdą test - punkt jest wewnątrz. Jeśli przynajmniej jeden zawodzi - punkt jest na zewnątrz.
Aby sprawdzić, czy punkt
(xp, yp)
leży po lewej stronie krawędzi(x1, y1) - (x2, y2)
, wystarczy obliczyćJeśli
D > 0
punkt znajduje się po lewej stronie. JeśliD < 0
punkt znajduje się po prawej stronie. JeśliD = 0
punkt jest na linii.Poprzednia wersja tej odpowiedzi opisywała pozornie inną wersję testu lewej strony (patrz poniżej). Ale można łatwo wykazać, że oblicza tę samą wartość.
... Aby sprawdzić, czy punkt
(xp, yp)
leży po lewej stronie krawędzi(x1, y1) - (x2, y2)
, musisz zbudować równanie prostej dla prostej zawierającej krawędź. Równanie jest następującegdzie
Teraz wszystko, co musisz zrobić, to obliczyć
Jeśli
D > 0
punkt znajduje się po lewej stronie. JeśliD < 0
punkt znajduje się po prawej stronie. JeśliD = 0
punkt jest na linii.Jednak ten test znowu działa dla każdego wypukłego wielokąta, co oznacza, że może być zbyt ogólny dla prostokąta. Prostokąt może pozwolić na prostszy test ... Na przykład w prostokącie (lub w jakimkolwiek innym równoległoboku) wartości
A
iB
mają tę samą wielkość, ale różne znaki dla przeciwnych (tj. Równoległych) krawędzi, które można wykorzystać do uproszczenia testu .źródło
A'
iB'
mogą być podane przezA'=B
iB'=-A
. 3. Nie ma sensu obliczaćA xp + B yp
obu krawędzi, więc połącz je w jeden test. Wtedy twój test na bycie w prostokącie staje się(v_min < A xp + B yp < v_max) && ( w_min < B xp - A yp < w_max )
.v_min
, etc?v_min
jest minimalną wartościąA x + B y
dla wszystkich wartości we wnętrzu prostokąta (która jest wartością minimalną podczas oceny w rogach).v_max
jest odpowiednim maksimum. Tew_?
wartości są takie same, ale zaBx - A y
.Zakładając, że prostokąt jest reprezentowany przez trzy punkty A, B, C, przy czym AB i BC są prostopadłe, wystarczy sprawdzić rzuty punktu zapytania M na AB i BC:
AB
Jest to wektor AB, o współrzędnych (BX-Ax, Ay, W) idot(U,V)
jest iloczyn skalarny wektorów U i V:Ux*Vx+Uy*Vy
.Aktualizuj . Zilustrujmy to na przykładzie: A (5,0) B (0,2) C (1,5) i D (6,3). Ze współrzędnych punktu otrzymujemy AB = (- 5,2), BC = (1,3), kropka (AB, AB) = 29, kropka (BC, BC) = 10.
Dla punktu zapytania M (4,2) mamy AM = (- 1,2), BM = (4,0), kropka (AB, AM) = 9, kropka (BC, BM) = 4. M znajduje się wewnątrz prostokąta.
Dla punktu zapytania P (6,1) mamy AP = (1,1), BP = (6, -1), kropka (AB, AP) = - 3, kropka (BC, BP) = 3. P nie znajduje się wewnątrz prostokąta, ponieważ jego rzut na bok AB nie znajduje się wewnątrz odcinka AB.
źródło
Pożyczyłem z odpowiedzi Erica Bainville'a:
Co w javascript wygląda tak:
na przykład:
następnie:
Oto kod do narysowania wyniku jako testu wizualnego :) http://codepen.io/mattburns/pen/jrrprN
źródło
mouseover
zdarzenia w moim projekcie, więc za każdym razem, gdy mysz znajdzie się nad punktem, który ma znajdować się wewnątrz prostokąta, wyświetli czarną kropkę wokół myszy, a poza prostokątem nie powinien nic wyświetlać. Potrzebuję pomocy, aby to zadziałało, ale jestem tak zdezorientowany.mouseover
powinno byćmousemove
, po prostu literówka.źródło
a
,b
id
. Podczas gdy trzy punkty są poprawnym sposobem przedstawienia dowolnego prostokąta w teorii, w praktyce niemożliwe jest wykonanie dokładnego pomiaru we współrzędnych pośrednich w ogólnym przypadku. W ogólnym przypadku otrzymamy równoległobok, który jest bardzo zbliżony do prostokąta, ale nadal nie jest prostokątem.Zdaję sobie sprawę, że to stary wątek, ale dla każdego, kto jest zainteresowany spojrzeniem na to z czysto matematycznej perspektywy, jest doskonały wątek na temat wymiany stosów matematycznych, tutaj:
/math/190111/how-to-check-if-a-point-is-inside-a-rectangle
Edycja: Zainspirowany tym wątkiem, opracowałem prostą metodę wektorową, aby szybko określić, gdzie leży twój punkt.
Załóżmy, że masz prostokąt z punktami w punktach p1 = (x1, y1), p2 = (x2, y2), p3 = (x3, y3) i p4 = (x4, y4), zgodnie z ruchem wskazówek zegara. Jeśli punkt p = (x, y) leży wewnątrz prostokąta, to iloczyn skalarny (p - p1). (P2 - p1) będzie leżeć między 0 a | p2 - p1 | ^ 2, a (p - p1). (p4 - p1) będzie leżeć między 0 a | p4 - p1 | ^ 2. Jest to równoważne z rzutem wektora p - p1 wzdłuż długości i szerokości prostokąta, z punktem początkowym p1.
Może to mieć więcej sensu, jeśli pokażę równoważny kod:
I to wszystko. Będzie również działać w przypadku równoległoboków.
źródło
Właśnie zaimplementowałem odpowiedź AnT za pomocą c ++. Użyłem tego kodu, aby sprawdzić, czy koordynacja piksela (X, Y) leży wewnątrz kształtu, czy nie.
źródło
Jeśli nie możesz rozwiązać problemu dla prostokąta, spróbuj podzielić problem na łatwiejsze. Podziel prostokąt na 2 trójkąty i sprawdź, czy punkt znajduje się wewnątrz któregokolwiek z nich, tak jak wyjaśniono tutaj
Zasadniczo przechodzisz między krawędziami na każdych dwóch parach linii z punktu. Następnie za pomocą iloczynu poprzecznego sprawdź, czy punkt znajduje się między dwiema liniami za pomocą iloczynu poprzecznego. Jeśli jest zweryfikowany dla wszystkich 3 punktów, to punkt znajduje się wewnątrz trójkąta. Zaletą tej metody jest to, że nie tworzy ona żadnych błędów punktów zmiennoprzecinkowych, które zdarzają się, gdy sprawdzasz kąty.
źródło
Jeśli punkt znajduje się wewnątrz prostokąta. W samolocie. Dla współrzędnych matematycznych lub geodezji (GPS)
Zrób równanie dla każdego l i . Rodzaj równania:
f i (P) = 0.
P to punkt. W przypadku punktów należących do l i równanie jest prawdziwe.
Więc musimy to sprawdzić:
f AB (P) f AB (C)> = 0
f BC (P) f BC (D)> = 0
f CD (P) f CD (A)> = 0
f DA (P) f DA (B)> = 0
Nierówności nie są ścisłe, bo jeśli punkt znajduje się na granicy, to również należy do prostokąta. Jeśli nie potrzebujesz punktów na granicy, możesz zmienić nierówności na ścisłe. Ale podczas pracy w operacjach zmiennoprzecinkowych wybór nie ma znaczenia.
Pozostaje tylko otrzymać równanie dla prostej przechodzącej przez dwa punkty. Jest to dobrze znane równanie liniowe. Napiszmy to dla prostej AB i punktu P:
f AB (P) ≡ (x A -x B ) (y P -y B ) - (y A -y B ) (x P -x B )
Sprawdzanie można uprościć - przejdźmy wzdłuż prostokąta zgodnie z ruchem wskazówek zegara - A, B, C, D, A. Wtedy wszystkie poprawne strony będą po prawej stronie linii. Nie musimy więc porównywać ze stroną, na której znajduje się inny wierzchołek. I musimy sprawdzić zestaw krótszych nierówności:
f AB (P)> = 0
f BC (P)> = 0
f CD (P)> = 0
f DA (P)> = 0
Ale jest to poprawne dla normalnego, matematycznego (ze szkolnej matematyki) zestawu współrzędnych, gdzie X jest po prawej stronie, a Y do góry. A dla współrzędnych geodezji , które są używane w GPS, gdzie X jest na górze, a Y na prawo, musimy odwrócić równania:
f AB (P) <= 0
f BC (P) <= 0
f CD (P) <= 0
f DA (P) <= 0
Jeśli nie masz pewności co do kierunków osi, zachowaj ostrożność przy tej uproszczonej kontroli - sprawdź jeden punkt ze znanym położeniem, jeśli wybrałeś prawidłowe nierówności.
źródło
Najprostszym sposobem, o którym pomyślałem, było po prostu rzutowanie punktu na oś prostokąta. Pozwól mi wyjaśnić:
Jeśli możesz uzyskać wektor od środka prostokąta do górnej lub dolnej krawędzi i lewej lub prawej krawędzi. Masz również wektor od środka prostokąta do punktu, możesz rzutować ten punkt na wektory szerokości i wysokości.
P = wektor punktowy, H = wektor wysokości, W = wektor szerokości
Uzyskaj wektor jednostkowy W ', H', dzieląc wektory przez ich wielkość
proj_P, H = P - (P.H ') H' proj_P, W = P - (P.W ') W'
Chyba że się mylę, co nie wydaje mi się ... (Popraw mnie, jeśli się mylę), ale jeśli wielkość rzutu twojego punktu na wektorze wysokości jest mniejsza niż wielkość wektora wysokości (który jest połowa wysokości prostokąta) i wielkość rzutu twojego punktu na wektor szerokości wynosi, wtedy masz punkt wewnątrz prostokąta.
Jeśli masz uniwersalny układ współrzędnych, być może będziesz musiał obliczyć wektory wysokości / szerokości / punktów za pomocą odejmowania wektorów. Projekcje wektorowe są niesamowite! Zapamietaj to.
źródło
W dalszej części odpowiedzi. musimy użyć rozwiązania /math/190111/how-to-check-if-a-point-is-inside-a-rectangle/190373#190373 , aby działało
Poniżej nie działa
0 <= kropka (AB, AM) <= kropka (AB, AB) && 0 <= kropka (BC, BM) <= kropka (BC, BC)
Poniżej działa
0 <= kropka (AB, AM) <= kropka (AB, AB) && 0 <= kropka (AM, AC) <= kropka (AC, AC)
sprawdzasz, wklejając poniżej w konsoli javascript // rozwiązanie Javascript dla tego samego
źródło