Ich habe diese Frage mehrmals in Bezug auf Stackoverflow und IRC zwischen #qgis und #postgis gestellt und auch versucht, sie zu codieren oder selbst in postgis zu implementieren, ohne eine echte Antwort zu finden.
Mit der Programmierung (am besten mit Python) möchte ich eine Linie von einer Punktebene bis zu ihrer Projektion auf die nächste Linie einer Linie oder Polygonebene zeichnen.
Ab sofort liegen die meisten meiner Daten in den Formaten ESRI und Postgis vor. ich möchte mich jedoch lieber von einer postgis-lösung fernhalten, da ich überwiegend shp + qgis-benutzer bin.
Eine ideale Lösung wäre die Implementierung von GDAL / OGR mit Python oder ähnlichen Bibliotheken
- Wo soll ich mit der Verwendung der GDAL / OGR-Bibliotheken beginnen? Wäre es möglich, einen Lösungsplan zu erstellen?
- Kann ich mit NetworkX die Analyse des nächsten Nachbarn durchführen?
- Ist das überhaupt möglich?
Wenn es einfacher ist, können die Punkte anstelle eines projizierten Punkts mit dem Segmentendpunkt verbunden werden
Antworten:
Diese Frage stellte sich als etwas kniffliger heraus, als ich gedacht hatte. Es gibt viele Implementierungen für den kürzesten Abstand selbst, z. B. den Shapely Provided Distance (von GEOS). Nur wenige der Lösungen geben den Schnittpunkt selbst an, aber nur die Entfernung.
Bei meinem ersten Versuch wurde der Punkt durch den Abstand zwischen dem Punkt und dem Polygon gepuffert und nach Schnittpunkten gesucht, aber Rundungsfehler verhindern, dass dies eine genaue Antwort ergibt.
Hier ist eine vollständige Lösung mit Shapely, basierend auf diesen Gleichungen :
Für die Nachwelt sieht es so aus, als würde diese ArcView-Erweiterung dieses Problem ganz gut lösen. Schade, dass sie auf einer toten Plattform in einer toten Sprache geschrieben ist ...
quelle
pairs
damit ist algorithmisch O (n) oder so. @eprand-Lösung kann möglicherweise geändert werden, um KNN zu verwenden, aber ich habe es geschafft, bisher ohne PostGIS zu leben ...Eine PostGIS-Antwort (für Multilinestring, wenn Linestring, entfernen Sie die Funktion st_geometryn)
quelle
Dies ist ein bisschen alt, aber ich habe heute nach Lösungen für dieses Problem gesucht (Punkt -> Linie). Die einfachste Lösung für dieses Problem ist:
quelle
Wenn ich Sie richtig verstehe, ist die Funktionalität, nach der Sie fragen, in PostGIS integriert.
Um einen Punkt auf eine Linie projiziert zu bekommen, können Sie ST_Closestpoint (auf PostGIS 1.5) verwenden.
Einige Hinweise zur Verwendung finden Sie hier: http://blog.jordogskog.no/2010/02/07/how-to-use-the-new-distance-related-functions-in-postgis-part1/
Sie können beispielsweise auch den nächsten Punkt auf einem Polygon zu einem anderen Polygon suchen.
Wenn Sie die Linie zwischen den beiden nächstgelegenen Punkten auf beiden Geometrien möchten, können Sie ST_Shortestline verwenden. ST_Closestpoint ist der erste Punkt in ST_Shortestline
Die Länge von ST_Shortestline zwischen zwei Geometrien entspricht der Länge von ST_Distance zwischen den Geometrien.
quelle
Im folgenden Kommentar wird erläutert, wie meine Antwort nicht als verlässliche Lösung angesehen werden kann. Ich werde diesen ursprünglichen Beitrag hier belassen, damit andere das Problem untersuchen können.
Wenn ich die Frage verstehe, sollte dieses allgemeine Verfahren funktionieren.
So finden Sie den kürzesten Weg zwischen einem Punkt (wie durch x, y oder x, y, z definiert) und einem Polyin (wie durch eine Verbindungsmenge von x, y oder x, y, z definiert) im euklidischen Raum:
1) Suchen Sie von einem bestimmten benutzerdefinierten Punkt aus (ich nenne es pt0) den nächsten Scheitelpunkt der Polylinie (pt1). OGRinfo kann die Eckpunkte einer Polylinie abfragen, und dann können Entfernungsberechnungen mit Standardmethoden durchgeführt werden. Beispiel: Iterieren Sie über eine Distanz. Berechnen Sie wie folgt: distance_in_radians = 2 * math.asin (math.sqrt (math.pow ((math.sin ((pt0_radians-ptx_radians) / 2)), 2) + math.cos (pt0_radians) * math.cos (ptx_radians) * math.pow ((math.sin ((pt0_radians-ptx_radians) / 2)), 2)))
2) Den zugehörigen Mindestabstandswert (d1) und (pt1) speichern
3) Sehen Sie sich die beiden Segmente an, die von pt1 abstammen (in der Ogrinfo-Linienfolge sind dies die vorherigen und nachfolgenden Scheitelpunkte). Notieren Sie diese Eckpunkte (n2 und n3).
4) Erstelle für jedes Segment eine y = mx + b Formel
5) Beziehen Sie Ihren Punkt (pt0) für jede dieser beiden Formeln auf die Senkrechte
6) Entfernungen und Schnittpunkte berechnen (d2 und d3; pt2, pt3)
7) Vergleichen Sie die drei Abstände (d1, d2, d3) für den kürzesten. Ihr pt0 zum zugehörigen Knoten (pt1, pt2 oder pt3) ist die kürzeste Verbindung.
Das ist ein Strom von Bewusstseinsantwort - hoffentlich passt mein mentales Bild des Problems und der Lösung.
quelle
Hier ist ein Python-Skript für QGIS> 2.0, das aus den oben angegebenen Hinweisen und Lösungen erstellt wurde. Es funktioniert gut für eine angemessene Anzahl von Punkten und Linien. Aber ich habe es nicht mit einer großen Anzahl von Objekten versucht.
Natürlich musste es im Leerlauf oder in einer anderen weniger "pythonischen Lösung" kopiert und als "next.point.py" gespeichert werden.
Wählen Sie in der QGIS-Toolbox Skript, Werkzeuge, fügen Sie ein Skript hinzu und wählen Sie es aus.
!!! WARNUNG !!! Achten Sie darauf, dass einige "seltsame" / falsch projizierte Punkte aufgrund dieses Zeilenbefehls erzeugt werden können:
Der
counterSelec
Wert darin legt fest, wie viele nextNeighbor zurückgegeben werden. Tatsächlich sollte jeder Punkt so weit wie möglich von jedem Linienobjekt entfernt projiziert werden. und der gefundene Mindestabstand würde die richtige Linie und den richtigen projizierten Punkt als die nächsten Nachbarn ergeben, die wir suchen. Um die Durchlaufzeit zu verkürzen, wird der nächste Nachbarbefehl verwendet. Wenn Sie dencounterSelec
Wert auf 1 reduzieren, wird das "erste" Objekt zurückgegeben (genauer gesagt das Begrenzungsfeld), und es ist möglicherweise nicht das richtige. Objekte mit unterschiedlicher Liniengröße müssen möglicherweise 3 oder 5 auswählen, oder es müssen noch mehr Objekte in der Nähe ausgewählt werden, um die kürzeste Entfernung zu bestimmen. Je höher der Wert, desto länger dauert es. Mit Hunderten von Punkten und Linien wird es bei 3 oder 5 nächsten Nachbarn sehr langsam, bei Tausenden kann es Fehler bei solchen Werten geben.quelle
Abhängig von Ihren Interessen und Ihrem Anwendungsfall kann es hilfreich sein, sich mit "Map Matching-Algorithmen" zu befassen. Es gibt beispielsweise ein RoadMatcher-Projekt im OSM-Wiki: http://wiki.openstreetmap.org/wiki/Roadmatcher .
quelle