Ich habe eine Reihe von Punkten. Ich möchte sie in zwei verschiedene Gruppen aufteilen. Dazu wähle ich zwei Punkte ( a und b ) und zeichne eine imaginäre Linie zwischen ihnen. Jetzt möchte ich alle Punkte, die von dieser Linie übrig sind, in einem Satz und diejenigen, die direkt von dieser Linie in dem anderen Satz sind, haben.
Wie kann ich für einen bestimmten Punkt z feststellen, ob er sich in der linken oder in der rechten Menge befindet? Ich habe versucht, den Winkel zwischen azb zu berechnen - Winkel kleiner als 180 sind auf der rechten Seite, größer als 180 auf der linken Seite - aber aufgrund der Definition von ArcCos sind die berechneten Winkel immer kleiner als 180 °. Gibt es eine Formel zur Berechnung von Winkeln größer als 180 ° (oder eine andere Formel zur Auswahl der rechten oder linken Seite)?
quelle
Antworten:
Verwenden Sie das Vorzeichen der Determinante von Vektoren
(AB,AM)
, wobeiM(X,Y)
sich der Abfragepunkt befindet:Es ist
0
auf der Linie und+1
auf der einen Seite,-1
auf der anderen Seite.quelle
positions
?Probieren Sie diesen Code aus, der ein Kreuzprodukt verwendet :
Wobei a = Linienpunkt 1; b = Linienpunkt 2; c = zu prüfender Punkt.
Wenn die Formel gleich 0 ist, sind die Punkte kolinear.
Wenn die Linie horizontal ist, gibt dies true zurück, wenn der Punkt über der Linie liegt.
quelle
return (b.x - a.x)*(c.y - a.y) > (b.y - a.y)*(c.x - a.x);
, aber der Compiler optimiert das wahrscheinlich trotzdem.Sie betrachten das Zeichen der Determinante von
Es ist positiv für Punkte auf der einen Seite und negativ für die andere Seite (und Null für Punkte auf der Linie selbst).
quelle
Der Vektor
(y1 - y2, x2 - x1)
ist senkrecht zur Linie und zeigt immer nach rechts (oder immer nach links, wenn sich die Ausrichtung Ihrer Ebene von meiner unterscheidet).Sie können dann das Punktprodukt dieses Vektors berechnen und
(x3 - x1, y3 - y1)
feststellen, ob der Punkt auf derselben Seite der Linie liegt wie der senkrechte Vektor (Punktprodukt>0
) oder nicht.quelle
Ermitteln Sie mithilfe der Gleichung der Linie ab die x-Koordinate auf der Linie an derselben y-Koordinate wie der zu sortierende Punkt.
quelle
Überprüfen Sie zunächst, ob Sie eine vertikale Linie haben:
Berechnen Sie dann die Steigung:
m = (y2-y1)/(x2-x1)
Erstellen Sie dann eine Gleichung der Linie mit der Punktsteigungsform :
y - y1 = m*(x-x1) + y1
. Vereinfachen Sie es für meine Erklärung zur Steigungsschnittform (in Ihrem Algorithmus nicht erforderlich) :y = mx+b
.Jetzt
(x3, y3)
fürx
und einsteckeny
. Hier ist ein Pseudocode, der genau beschreibt, was passieren soll:quelle
Ich habe dies in Java implementiert und einen Unit-Test durchgeführt (Quelle unten). Keine der oben genannten Lösungen funktioniert. Dieser Code besteht den Komponententest. Wenn jemand einen Unit-Test findet, der nicht bestanden wird, lassen Sie es mich bitte wissen.
Code: HINWEIS:
nearlyEqual(double,double)
Gibt true zurück, wenn die beiden Zahlen sehr nahe beieinander liegen.Hier ist der Unit-Test:
quelle
Angenommen, die Punkte sind (Axe, Ay) (Bx, By) und (Cx, Cy), müssen Sie Folgendes berechnen:
(Bx - Axe) * (Cy - Ay) - (By - Ay) * (Cx - Axe)
Dies ist gleich Null, wenn sich der Punkt C auf der Linie befindet, die durch die Punkte A und B gebildet wird, und hat je nach Seite ein anderes Vorzeichen. Welche Seite dies ist, hängt von der Ausrichtung Ihrer (x, y) -Koordinaten ab. Sie können jedoch Testwerte für A, B und C in diese Formel einfügen, um festzustellen, ob negative Werte links oder rechts liegen.
quelle
Ich wollte eine Lösung anbieten, die von der Physik inspiriert ist.
Stellen Sie sich eine Kraft vor, die entlang der Linie ausgeübt wird, und Sie messen das Drehmoment der Kraft um den Punkt. Wenn das Drehmoment positiv ist (gegen den Uhrzeigersinn), befindet sich der Punkt links von der Linie. Wenn das Drehmoment negativ ist, ist der Punkt rechts von der Linie.
Wenn also der Kraftvektor der Spanne der beiden Punkte entspricht, die die Linie definieren
Sie testen die Seite eines Punktes
(px,py)
anhand des Vorzeichens des folgenden Testsquelle
Grundsätzlich denke ich, dass es eine Lösung gibt, die viel einfacher und unkomplizierter ist. Für jedes Polygon, das beispielsweise aus vier Eckpunkten besteht (p1, p2, p3, p4), finden Sie die beiden extrem entgegengesetzten Eckpunkte im Polygon in einem anderen Wörter, finden Sie zum Beispiel den Scheitelpunkt oben links (sagen wir p1) und den gegenüberliegenden Scheitelpunkt, der sich höchstens unten rechts befindet (sagen wir mal). Angesichts Ihres Testpunktes C (x, y) müssen Sie nun eine doppelte Überprüfung zwischen C und p1 und C und p4 durchführen:
wenn cx> p1x UND cy> p1y ==> bedeutet, dass C niedriger und rechts von p1 als nächstes ist, wenn cx <p2x UND cy <p2y ==> bedeutet, dass C oben und links von p4 ist
Schlussfolgerung: C befindet sich innerhalb des Rechtecks.
Vielen Dank :)
quelle
@ AVBs Antwort in Rubin
Wenn
det
positiv ist, ist es oben, wenn negativ, ist es unten. Wenn 0, ist es in der Leitung.quelle
Hier ist eine Version, die wiederum die produktübergreifende Logik verwendet und in Clojure geschrieben wurde.
Anwendungsbeispiel:
Das heißt, der Punkt (0, 10) liegt links von der durch (-3, -1) und (3, 1) bestimmten Linie.
HINWEIS: Diese Implementierung löst ein Problem, das (bisher) keiner der anderen hat! Die Reihenfolge ist wichtig, wenn Sie die Punkte angeben, die die Linie bestimmen. Das heißt, es ist in gewissem Sinne eine "gerichtete Linie". Mit dem obigen Code erzeugt dieser Aufruf also auch das Ergebnis von
true
:Das liegt an diesem Codeausschnitt:
Schließlich gibt diese Lösung wie die anderen produktübergreifenden Lösungen einen Booleschen Wert zurück und liefert kein drittes Ergebnis für die Kollinearität. Aber es wird ein Ergebnis ergeben, das Sinn macht, z.
quelle
Eine alternative Möglichkeit, sich ein Bild von den Lösungen zu machen, die von Nettern bereitgestellt werden, besteht darin, einige Implikationen der Geometrie zu verstehen.
Sei pqr = [P, Q, R] Punkte, die eine Ebene bilden, die durch die Linie [P, R] in zwei Seiten unterteilt ist . Wir müssen herausfinden, ob zwei Punkte auf der pqr- Ebene A, B auf derselben Seite liegen.
Jeder Punkt T auf der pqr-Ebene kann mit 2 Vektoren dargestellt werden: v = PQ und u = RQ als:
T '= TQ = i * v + j * u
Nun die Geometrie Implikationen:
i+j: <0 0 <1 =1 >1 ---------Q------[PR]--------- <== this is PQR plane ^ pr line
Allgemein,
Die anderen Geometriebedeutungen von i und j (nicht mit dieser Lösung verbunden) sind:
Der Wert von i, j kann durch Lösen der Gleichungen erhalten werden:
Wir erhalten also 2 Punkte, A, B in der Ebene:
A = a1 * v + a2 * u B = b1 * v + b2 * u
Wenn A, B auf derselben Seite sind, ist dies wahr:
sign(a1+a2-1) = sign(b1+b2-1)
Beachten Sie, dass dies auch für die Frage gilt: Befinden sich A, B auf derselben Seite der Ebene [P, Q, R] , in der:
T = i * P + j * Q + k * R.
und i + j + k = 1 impliziert, dass T auf der Ebene [P, Q, R] liegt und das Vorzeichen von i + j + k-1 seine Nebenwirkung impliziert. Daraus haben wir:
A = a1 * P + a2 * Q + a3 * R B = b1 * P + b2 * Q + b3 * R
und A, B liegen auf derselben Seite der Ebene [P, Q, R], wenn
sign(a1+a2+a3-1) = sign(b1+b2+b3-1)
quelle