Ich versuche, einen schnellen 2D-Punkt innerhalb des Polygon-Algorithmus zu erstellen , um ihn beim Testen von Treffern zu verwenden (z Polygon.contains(p:Point)
. B. ). Vorschläge für effektive Techniken wären willkommen.
performance
graphics
collision-detection
polygon
point-in-polygon
Scott Evernden
quelle
quelle
Antworten:
Für Grafiken würde ich lieber keine ganzen Zahlen bevorzugen. Viele Systeme verwenden Ganzzahlen für das UI-Malen (Pixel sind schließlich Ints), aber macOS verwendet beispielsweise float für alles. macOS kennt nur Punkte und ein Punkt kann in ein Pixel übersetzt werden. Abhängig von der Monitorauflösung kann er jedoch in etwas anderes übersetzt werden. Auf Retina-Bildschirmen ist ein halber Punkt (0,5 / 0,5) Pixel. Trotzdem habe ich nie bemerkt, dass MacOS-Benutzeroberflächen erheblich langsamer sind als andere Benutzeroberflächen. Schließlich funktionieren 3D-APIs (OpenGL oder Direct3D) auch mit Floats, und moderne Grafikbibliotheken nutzen sehr oft die GPU-Beschleunigung.
Jetzt hast du gesagt, Geschwindigkeit ist dein Hauptanliegen, okay, lass uns Geschwindigkeit anstreben. Bevor Sie einen ausgeklügelten Algorithmus ausführen, führen Sie zunächst einen einfachen Test durch. Erstellen Sie einen achsenausgerichteten Begrenzungsrahmen um Ihr Polygon. Dies ist sehr einfach, schnell und kann Ihnen bereits viele Berechnungen ersparen. Wie funktioniert das? Iterieren Sie über alle Punkte des Polygons und ermitteln Sie die Min / Max-Werte von X und Y.
ZB hast du die Punkte
(9/1), (4/3), (2/7), (8/2), (3/6)
. Dies bedeutet, dass Xmin 2, Xmax 9, Ymin 1 und Ymax 7 ist. Ein Punkt außerhalb des Rechtecks mit den beiden Kanten (2/1) und (9/7) kann nicht innerhalb des Polygons liegen.Dies ist der erste Test, der für einen beliebigen Punkt ausgeführt wird. Wie Sie sehen können, ist dieser Test ultraschnell, aber auch sehr grob. Um Punkte innerhalb des Begrenzungsrechtecks zu behandeln, benötigen wir einen komplexeren Algorithmus. Es gibt verschiedene Möglichkeiten, wie dies berechnet werden kann. Welche Methode funktioniert, hängt auch davon ab, ob das Polygon Löcher haben kann oder immer fest sein wird. Hier sind Beispiele für feste (eine konvexe, eine konkave):
Und hier ist einer mit einem Loch:
Der Grüne hat ein Loch in der Mitte!
Der einfachste Algorithmus, der alle drei oben genannten Fälle behandeln kann und immer noch ziemlich schnell ist, heißt Ray Casting . Die Idee des Algorithmus ist ziemlich einfach: Zeichnen Sie einen virtuellen Strahl von einer beliebigen Stelle außerhalb des Polygons zu Ihrem Punkt und zählen Sie, wie oft er auf eine Seite des Polygons trifft. Wenn die Anzahl der Treffer gerade ist, liegt sie außerhalb des Polygons. Wenn sie ungerade ist, befindet sie sich innerhalb.
Der Wicklungszahlalgorithmus wäre eine Alternative. Er ist genauer für Punkte, die sehr nahe an einer Polygonlinie liegen, aber auch viel langsamer. Das Ray Casting kann für Punkte fehlschlagen, die zu nahe an einer Polygonseite liegen, da die Gleitkommapräzision und Rundungsprobleme begrenzt sind. In der Realität ist dies jedoch kaum ein Problem, da ein Punkt so nahe an einer Seite liegt, dass es für a oft visuell nicht möglich ist Betrachter zu erkennen, ob es bereits drinnen oder noch draußen ist.
Sie haben immer noch den Begrenzungsrahmen von oben, erinnern Sie sich? Wählen Sie einfach einen Punkt außerhalb des Begrenzungsrahmens und verwenden Sie ihn als Ausgangspunkt für Ihren Strahl. ZB liegt der Punkt
(Xmin - e/p.y)
sicher außerhalb des Polygons.Aber was ist das
e
? Nun,e
(eigentlich Epsilon) gibt dem Begrenzungsrahmen etwas Polsterung . Wie gesagt, die Strahlverfolgung schlägt fehl, wenn wir zu nahe an einer Polygonlinie beginnen. Da der Begrenzungsrahmen möglicherweise dem Polygon entspricht (wenn das Polygon ein achsenausgerichtetes Rechteck ist, entspricht der Begrenzungsrahmen dem Polygon selbst!), Benötigen wir eine Auffüllung, um dies sicher zu machen, das ist alles. Wie groß solltest du wählene
? Nicht zu groß. Dies hängt von der Skalierung des Koordinatensystems ab, die Sie zum Zeichnen verwenden. Wenn Ihre Pixelschrittbreite 1,0 beträgt, wählen Sie einfach 1,0 (0,1 hätte jedoch auch funktioniert).Nachdem wir nun den Strahl mit seinen Start- und Endkoordinaten haben, verschiebt sich das Problem von " ist der Punkt innerhalb des Polygons " zu " wie oft schneidet der Strahl eine Polygonseite ". Daher können wir nicht wie bisher mit den Polygonpunkten arbeiten, sondern benötigen jetzt die eigentlichen Seiten. Eine Seite wird immer durch zwei Punkte definiert.
Sie müssen den Strahl gegen alle Seiten testen. Betrachten Sie den Strahl als Vektor und jede Seite als Vektor. Der Strahl muss jede Seite genau einmal oder nie treffen. Es kann nicht zweimal dieselbe Seite treffen. Zwei Linien im 2D-Raum schneiden sich immer genau einmal, es sei denn, sie sind parallel. In diesem Fall schneiden sie sich nie. Da Vektoren jedoch eine begrenzte Länge haben, sind zwei Vektoren möglicherweise nicht parallel und schneiden sich immer noch nie, da sie zu kurz sind, um sich jemals zu treffen.
So weit so gut, aber wie testen Sie, ob sich zwei Vektoren schneiden? Hier ist ein C-Code (nicht getestet), der den Trick machen sollte:
Die Eingabewerte sind die beiden Endpunkte von Vektor 1 (
v1x1/v1y1
undv1x2/v1y2
) und Vektor 2 (v2x1/v2y1
undv2x2/v2y2
). Sie haben also 2 Vektoren, 4 Punkte, 8 Koordinaten.YES
undNO
sind klar.YES
erhöht Kreuzungen,NO
tut nichts.Was ist mit COLLINEAR? Dies bedeutet, dass beide Vektoren auf derselben unendlichen Linie liegen, je nach Position und Länge sich überhaupt nicht oder in einer endlosen Anzahl von Punkten schneiden. Ich bin mir nicht ganz sicher, wie ich mit diesem Fall umgehen soll. Ich würde ihn in keiner Weise als Kreuzung betrachten. Nun, dieser Fall ist in der Praxis ohnehin aufgrund von Gleitkomma-Rundungsfehlern eher selten. Besserer Code würde wahrscheinlich nicht testen,
== 0.0f
sondern auf etwas wie< epsilon
, bei dem epsilon eine eher kleine Zahl ist.Wenn Sie eine größere Anzahl von Punkten testen müssen, können Sie das Ganze sicherlich ein wenig beschleunigen, indem Sie die linearen Gleichungsstandardformen der Polygonseiten im Speicher behalten, sodass Sie diese nicht jedes Mal neu berechnen müssen. Auf diese Weise sparen Sie bei jedem Test zwei Gleitkomma-Multiplikationen und drei Gleitkomma-Subtraktionen, um drei Gleitkommawerte pro Polygonseite im Speicher zu speichern. Es ist ein typischer Kompromiss zwischen Speicher und Rechenzeit.
Last but not least: Wenn Sie zur Lösung des Problems 3D-Hardware verwenden, gibt es eine interessante Alternative. Lassen Sie einfach die GPU die ganze Arbeit für Sie erledigen. Erstellen Sie eine Malfläche außerhalb des Bildschirms. Füllen Sie es vollständig mit der Farbe Schwarz. Lassen Sie nun OpenGL oder Direct3D Ihr Polygon malen (oder sogar alle Ihre Polygone, wenn Sie nur testen möchten, ob der Punkt in einem von ihnen liegt, aber Sie sich nicht darum kümmern, welches) und füllen Sie die Polygone mit einem anderen Farbe, zB weiß. Um zu überprüfen, ob sich ein Punkt innerhalb des Polygons befindet, rufen Sie die Farbe dieses Punkts von der Zeichenfläche ab. Dies ist nur ein O (1) -Speicherabruf.
Natürlich ist diese Methode nur verwendbar, wenn Ihre Zeichenfläche nicht riesig sein muss. Wenn es nicht in den GPU-Speicher passt, ist diese Methode langsamer als auf der CPU. Wenn es riesig sein müsste und Ihre GPU moderne Shader unterstützt, können Sie die GPU weiterhin verwenden, indem Sie das oben gezeigte Ray Casting als GPU-Shader implementieren, was absolut möglich ist. Für eine größere Anzahl von Polygonen oder eine große Anzahl von zu testenden Punkten zahlt sich dies aus. Beachten Sie, dass einige GPUs 64 bis 256 Punkte parallel testen können. Beachten Sie jedoch, dass das Übertragen von Daten von der CPU zur GPU und zurück immer teuer ist. Wenn Sie also nur ein paar Punkte gegen ein paar einfache Polygone testen, bei denen entweder die Punkte oder die Polygone dynamisch sind und sich häufig ändern, zahlt sich ein GPU-Ansatz selten aus aus.
quelle
Ich denke, der folgende Code ist die beste Lösung (von hier übernommen ):
Argumente
Es ist sowohl kurz als auch effizient und funktioniert sowohl für konvexe als auch für konkave Polygone. Wie zuvor vorgeschlagen, sollten Sie zuerst das Begrenzungsrechteck überprüfen und Polygonlöcher separat behandeln.
Die Idee dahinter ist ziemlich einfach. Der Autor beschreibt es wie folgt:
Die Variable c wechselt jedes Mal von 0 auf 1 und von 1 auf 0, wenn der horizontale Strahl eine Kante kreuzt. Im Grunde genommen wird also nachverfolgt, ob die Anzahl der gekreuzten Kanten gerade oder ungerade ist. 0 bedeutet gerade und 1 bedeutet ungerade.
quelle
verty[i]
undverty[j]
ist auf beiden Seitentesty
, so dass sie nie gleich sind.Hier ist eine C # -Version der Antwort von nirg , die von diesem RPI-Professor stammt . Beachten Sie, dass für die Verwendung des Codes aus dieser RPI-Quelle eine Zuordnung erforderlich ist.
Oben wurde ein Begrenzungsrahmen-Häkchen hinzugefügt. Wie James Brown jedoch betont, ist der Hauptcode fast so schnell wie der Begrenzungsrahmen selbst, sodass der Begrenzungsrahmen den Gesamtvorgang tatsächlich verlangsamen kann, falls sich die meisten Punkte, die Sie prüfen, innerhalb des Begrenzungsrahmens befinden . Sie können also den Begrenzungsrahmen auschecken lassen oder alternativ die Begrenzungsrahmen Ihrer Polygone vorberechnen, wenn sich ihre Form nicht zu oft ändert.
quelle
Hier ist eine JavaScript-Variante der Antwort von M. Katz basierend auf Nirgs Ansatz:
quelle
Berechnen Sie die orientierte Winkelsumme zwischen dem Punkt p und jeder der Polygonspitzen. Wenn der gesamte Ausrichtungswinkel 360 Grad beträgt, befindet sich der Punkt im Inneren. Wenn die Summe 0 ist, liegt der Punkt außerhalb.
Ich mag diese Methode besser, weil sie robuster ist und weniger von der numerischen Genauigkeit abhängt.
Methoden, die die Gleichmäßigkeit der Anzahl von Schnittpunkten berechnen, sind begrenzt, da Sie während der Berechnung der Anzahl von Schnittpunkten einen Scheitelpunkt "treffen" können.
EDIT: Diese Methode funktioniert übrigens mit konkaven und konvexen Polygonen.
EDIT: Ich habe kürzlich einen ganzen Wikipedia-Artikel zu diesem Thema gefunden.
quelle
Diese Frage ist so interessant. Ich habe eine andere praktikable Idee, die sich von anderen Antworten auf diesen Beitrag unterscheidet. Die Idee ist, die Summe der Winkel zu verwenden, um zu entscheiden, ob sich das Ziel innerhalb oder außerhalb befindet. Besser bekannt als Wicklungsnummer .
Sei x der Zielpunkt. Das Array [0, 1, .... n] seien alle Punkte des Bereichs. Verbinden Sie den Zielpunkt mit jedem Grenzpunkt mit einer Linie. Wenn sich der Zielpunkt innerhalb dieses Bereichs befindet. Die Summe aller Winkel beträgt 360 Grad. Wenn nicht, sind die Winkel kleiner als 360.
In diesem Bild erhalten Sie ein grundlegendes Verständnis der Idee:
Mein Algorithmus geht davon aus, dass der Uhrzeigersinn die positive Richtung ist. Hier ist eine mögliche Eingabe:
Das Folgende ist der Python-Code, der die Idee implementiert:
quelle
Der von Bobobobo zitierte Artikel von Eric Haines ist wirklich exzellent. Besonders interessant sind die Tabellen, in denen die Leistung der Algorithmen verglichen wird. Die Winkelsummationsmethode ist im Vergleich zu den anderen wirklich schlecht. Interessant ist auch, dass Optimierungen wie die Verwendung eines Suchrasters zur weiteren Unterteilung des Polygons in "In" - und "Out" -Sektoren den Test selbst bei Polygonen mit> 1000 Seiten unglaublich schnell machen können.
Wie auch immer, es ist noch früh, aber meine Stimme geht an die "Crossings" -Methode, die meiner Meinung nach ziemlich genau von Mecki beschrieben wird. Ich fand es jedoch am prägnantesten von David Bourke beschrieben und kodifiziert . Ich finde es toll, dass keine echte Trigonometrie erforderlich ist. Sie funktioniert konvex und konkav und funktioniert mit zunehmender Anzahl der Seiten recht gut.
Übrigens, hier ist eine der Leistungstabellen aus dem Artikel von Eric Haines, die sich mit zufälligen Polygonen befasst.
quelle
Schnelle Version der Antwort von nirg :
quelle
Wirklich wie die Lösung von Nirg gepostet und von Bobobobo bearbeitet. Ich habe es gerade Javascript-freundlich und für meinen Gebrauch etwas lesbarer gemacht:
quelle
Ich habe daran gearbeitet, als ich unter Michael Stonebraker forschte - wissen Sie, der Professor, der sich Ingres , PostgreSQL usw. ausgedacht hat.
Wir haben festgestellt, dass der schnellste Weg darin bestand, zuerst einen Begrenzungsrahmen zu erstellen, weil er SUPER schnell ist. Wenn es außerhalb des Begrenzungsrahmens ist, ist es außerhalb. Ansonsten machst du die härtere Arbeit ...
Wenn Sie einen großartigen Algorithmus wünschen, schauen Sie im Open-Source-Projekt PostgreSQL-Quellcode nach, um die Geo-Arbeit ...
Ich möchte darauf hinweisen, dass wir nie einen Einblick in Rechts- und Linkshändigkeit bekommen haben (auch ausgedrückt als "Innen" - "Außen" -Problem ...
AKTUALISIEREN
Der Link der BKB lieferte eine Reihe vernünftiger Algorithmen. Ich habe an geowissenschaftlichen Problemen gearbeitet und brauchte daher eine Lösung, die in Längen- und Breitengraden funktioniert, und sie hat das eigentümliche Problem der Händigkeit - befindet sich der Bereich innerhalb des kleineren Bereichs oder des größeren Bereichs? Die Antwort ist, dass die "Richtung" der Verticies wichtig ist - entweder für Linkshänder oder für Rechtshänder. Auf diese Weise können Sie jeden Bereich als "innerhalb" eines bestimmten Polygons angeben. Daher verwendete meine Arbeit die auf dieser Seite aufgezählte Lösung drei.
Darüber hinaus verwendete meine Arbeit separate Funktionen für "Online" -Tests.
... Da jemand gefragt hat: Wir haben herausgefunden, dass Bounding-Box-Tests am besten sind, wenn die Anzahl der Verticies über eine bestimmte Anzahl hinausgeht. Führen Sie bei Bedarf einen sehr schnellen Test durch, bevor Sie den längeren Test durchführen. Ein Bounding-Box wird erstellt, indem Sie einfach die größtes x, kleinstes x, größtes y und kleinstes y und füge sie zusammen, um vier Punkte einer Box zu bilden ...
Ein weiterer Tipp für die folgenden: Wir haben alle unsere ausgefeilteren und "lichtdimmenden" Berechnungen in einem Gitterraum durchgeführt, alle an positiven Punkten in einer Ebene, und dann wieder in "echte" Längen- / Breitengrade projiziert, um mögliche Fehler von zu vermeiden Umwickeln, wenn man die Linie 180 der Länge überquert und wenn man mit Polarregionen umgeht. Hat super funktioniert!
quelle
Die Antwort von David Segond ist so ziemlich die allgemeine Standardantwort, und die von Richard T ist die häufigste Optimierung, obwohl es einige andere gibt. Andere starke Optimierungen basieren auf weniger allgemeinen Lösungen. Wenn Sie beispielsweise dasselbe Polygon mit vielen Punkten überprüfen möchten, kann das Triangulieren des Polygons die Dinge erheblich beschleunigen, da es eine Reihe sehr schneller TIN-Suchalgorithmen gibt. Wenn sich das Polygon und die Punkte bei niedriger Auflösung auf einer begrenzten Ebene befinden, z. B. bei einer Bildschirmanzeige, können Sie das Polygon in einer bestimmten Farbe auf einen speicherabgebildeten Anzeigepuffer malen und die Farbe eines bestimmten Pixels überprüfen, um festzustellen, ob es liegt in den Polygonen.
Wie viele Optimierungen basieren diese eher auf spezifischen als auf allgemeinen Fällen und bieten Vorteile, die auf der amortisierten Zeit und nicht auf der einmaligen Verwendung basieren.
Als ich in diesem Bereich arbeitete, fand ich Joeseph O'Rourkes 'Berechnungsgeometrie in C' ISBN 0-521-44034-3 eine große Hilfe.
quelle
Die triviale Lösung wäre, das Polygon in Dreiecke zu teilen und die Dreiecke wie hier erläutert zu testen
Wenn Ihr Polygon CONVEX ist, gibt es möglicherweise einen besseren Ansatz. Betrachten Sie das Polygon als eine Sammlung unendlicher Linien. Jede Zeile teilt den Raum in zwei Teile. Für jeden Punkt ist es leicht zu sagen, ob er sich auf der einen oder der anderen Seite der Linie befindet. Wenn sich ein Punkt auf derselben Seite aller Linien befindet, befindet er sich innerhalb des Polygons.
quelle
Mir ist klar, dass dies alt ist, aber hier ist ein in Cocoa implementierter Ray-Casting-Algorithmus, falls jemand interessiert ist. Ich bin mir nicht sicher, ob dies der effizienteste Weg ist, aber es kann jemandem helfen.
quelle
Obj-C-Version von Nirgs Antwort mit Beispielmethode zum Testen von Punkten. Nirgs Antwort funktionierte gut für mich.
quelle
CGPathContainsPoint()
dein Freund.CGPathContainsPoint()
Es gibt nichts Schöneres als eine induktive Definition eines Problems. Der Vollständigkeit halber haben Sie hier eine Version im Prolog, die auch die Gedanken hinter dem Ray Casting verdeutlichen könnte :
Basierend auf der Simulation des Einfachheitsalgorithmus in http://www.ecse.rpi.edu/Homepages/wrf/Research/Short_Notes/pnpoly.html
Einige Helferprädikate:
Die Gleichung einer Linie mit 2 Punkten A und B (Linie (A, B)) lautet:
Es ist wichtig, dass die Drehrichtung für die Linie für Grenzen im Uhrzeigersinn und für Löcher gegen den Uhrzeigersinn eingestellt wird. Wir werden prüfen, ob der Punkt (X, Y), dh der getestete Punkt, auf der linken Halbebene unserer Linie liegt (es ist Geschmackssache, es könnte auch die rechte Seite sein, aber auch die Richtung der Grenzen Linien müssen in diesem Fall geändert werden), um den Strahl vom Punkt nach rechts (oder links) zu projizieren und den Schnittpunkt mit der Linie zu bestätigen. Wir haben uns entschieden, den Strahl in horizontaler Richtung zu projizieren (wieder ist es Geschmackssache, es könnte auch in vertikaler Richtung mit ähnlichen Einschränkungen erfolgen), also haben wir:
Jetzt müssen wir wissen, ob sich der Punkt nur auf der linken (oder rechten) Seite des Liniensegments befindet, nicht auf der gesamten Ebene. Daher müssen wir die Suche nur auf dieses Segment beschränken. Dies ist jedoch einfach, da wir uns innerhalb des Segments befinden Nur ein Punkt in der Linie kann auf der vertikalen Achse höher als Y sein. Da dies eine stärkere Einschränkung ist, muss es das erste sein, das überprüft wird. Daher nehmen wir zuerst nur die Zeilen, die diese Anforderung erfüllen, und überprüfen dann deren Besitz. Nach dem Jordan-Kurven-Theorem muss sich jeder auf ein Polygon projizierte Strahl mit einer geraden Anzahl von Linien schneiden. Wenn wir fertig sind, werfen wir den Strahl nach rechts und schalten dann jedes Mal, wenn er eine Linie schneidet, seinen Zustand um. Bei unserer Implementierung werden wir jedoch die Länge des Lösungsbeutels überprüfen, der die angegebenen Einschränkungen erfüllt, und die Innership darüber entscheiden. Für jede Linie im Polygon muss dies erfolgen.
quelle
Die C # -Version von Nirgs Antwort ist hier: Ich werde nur den Code teilen. Es kann jemandem Zeit sparen.
quelle
Java-Version:
quelle
.Net-Port:
quelle
VBA-VERSION:
Hinweis: Denken Sie daran, dass, wenn Ihr Polygon ein Bereich innerhalb einer Karte ist, Latitude / Longitude Y / X-Werte im Gegensatz zu X / Y (Latitude = Y, Longitude = X) sind, da meines Wissens historische Implikationen von damals sind Der Längengrad war kein Maß.
KLASSENMODUL: CPoint
MODUL:
quelle
Ich habe eine Python-Implementierung von Nirgs C ++ - Code erstellt :
Eingänge
bounding_box_positions: Zu filternde Kandidatenpunkte. (In meiner Implementierung aus dem Begrenzungsrahmen erstellt.
(Die Eingänge sind Listen von Tupeln in dem Format:
[(xcord, ycord), ...]
)Kehrt zurück
Auch hier ist die Idee von genommen hier
quelle
Überrascht, dass niemand dies früher angesprochen hat, aber für die Pragmatiker, die eine Datenbank benötigen: MongoDB bietet hervorragende Unterstützung für Geo-Abfragen, einschließlich dieser.
Was Sie suchen ist:
Neighborhoods
ist die Sammlung, in der ein oder mehrere Polygone im Standard-GeoJson-Format gespeichert sind. Wenn die Abfrage null zurückgibt, wird sie sonst nicht geschnitten.Sehr gut dokumentiert hier: https://docs.mongodb.com/manual/tutorial/geospatial-tutorial/
Die Leistung für mehr als 6.000 Punkte, die in einem unregelmäßigen Polygonraster von 330 klassifiziert wurden, betrug weniger als eine Minute ohne jegliche Optimierung und einschließlich der Zeit zum Aktualisieren von Dokumenten mit ihrem jeweiligen Polygon.
quelle
Hier ist ein Punkt im Polygontest in C, der kein Raycasting verwendet. Und es kann für überlappende Bereiche (Selbstüberschneidungen) funktionieren, siehe das
use_holes
Argument.Hinweis: Dies ist eine der weniger optimalen Methoden, da sie viele Aufrufe enthält
atan2f
, aber für Entwickler, die diesen Thread lesen, von Interesse sein kann (in meinen Tests ist er ~ 23x langsamer als bei Verwendung der Linienschnittmethode).quelle
Um Treffer auf Polygon zu erkennen, müssen wir zwei Dinge testen:
quelle
Um die folgenden Sonderfälle im Ray Casting-Algorithmus zu behandeln :
Überprüfen Sie, ob sich ein Punkt innerhalb eines komplexen Polygons befindet . Der Artikel bietet eine einfache Möglichkeit, sie zu beheben, sodass für die oben genannten Fälle keine spezielle Behandlung erforderlich ist.
quelle
Sie können dies tun, indem Sie überprüfen, ob der Bereich, der durch Verbinden des gewünschten Punkts mit den Scheitelpunkten Ihres Polygons gebildet wird, mit dem Bereich des Polygons selbst übereinstimmt.
Oder Sie könnten prüfen, ob die Summe der Innenwinkel von Ihrem Punkt zu jedem Paar von zwei aufeinanderfolgenden Polygonscheitelpunkten zu Ihrem Prüfpunkt 360 ergibt, aber ich habe das Gefühl, dass die erste Option schneller ist, da sie weder Unterteilungen noch Berechnungen umfasst der Umkehrung trigonometrischer Funktionen.
Ich weiß nicht, was passiert, wenn Ihr Polygon ein Loch enthält, aber es scheint mir, dass die Hauptidee an diese Situation angepasst werden kann
Sie können die Frage auch in einer Mathe-Community posten. Ich wette, sie haben eine Million Möglichkeiten, das zu tun
quelle
Wenn Sie nach einer Java-Skriptbibliothek suchen, gibt es eine JavaScript-Google Maps v3-Erweiterung für die Polygon-Klasse, um festzustellen, ob sich ein Punkt darin befindet oder nicht.
Google Extention Github
quelle
Beim Benutzen qt(Qt 4.3 und höher), kann man QPolygon die Funktion contains
quelle
Die Antwort hängt davon ab, ob Sie einfache oder komplexe Polygone haben. Einfache Polygone dürfen keine Liniensegmentschnitte haben. Sie können also Löcher haben, aber Linien können sich nicht kreuzen. Komplexe Regionen können Linienschnittpunkte haben - so können sie überlappende Regionen oder Regionen haben, die sich nur durch einen einzelnen Punkt berühren.
Für einfache Polygone ist der beste Algorithmus der Ray Casting-Algorithmus (Crossing Number). Bei komplexen Polygonen erkennt dieser Algorithmus keine Punkte, die sich innerhalb der überlappenden Bereiche befinden. Für komplexe Polygone müssen Sie also den Wicklungszahlalgorithmus verwenden.
Hier ist ein ausgezeichneter Artikel mit C-Implementierung beider Algorithmen. Ich habe sie ausprobiert und sie funktionieren gut.
http://geomalgorithms.com/a03-_inclusion.html
quelle
Scala-Version der Lösung von nirg (setzt voraus, dass die Vorprüfung des Begrenzungsrechtecks separat erfolgt):
quelle
Hier ist die Golang-Version von @nirg answer (inspiriert vom C # -Code von @@ m-katz)
quelle