Ich versuche, mit Shapely / Geopandas zwei Linien miteinander zu verbinden, aber das Ergebnis des Schnappens ist sehr merkwürdig. Ich habe es versucht :
import geopandas as gpd
from shapely.geometry import *
from shapely.ops import snap
lines1 = gpd.GeoDataFrame.from_file('lines1.shp')
lines1 = lines1.to_crs({'init': 'epsg:2227'})
lines2 = gpd.GeoDataFrame.from_file('lines2.shp')
lines2 = lines2.to_crs({'init': 'epsg:2227'})
res = lines1
lines2_union = lines2.geometry.unary_union
res.geometry = res.geometry.apply(lambda x: snap(x, lines2_union, 14))
res.to_file('result.shp', driver="ESRI Shapefile")
Und bekam dieses Ergebnis:
lines1 = rote Linien
lines2 = schwarze Linien
Nach dem Fang (mit 14 als Toleranz): Die blauen Linien sind das Ergebnis des Fangens
In diesem Fall werden die Linien korrekt eingerastet
Ein weiteres Beispiel, wo es nicht wie erwartet funktioniert hat: (vor dem Einrasten)
Und hier ist das Ergebnis nach dem Einrasten. Nur ein Teil wird an der schwarzen Linie (der Südseite) gefangen. Obwohl die ursprünglichen Linien ziemlich nah und innerhalb der 14 Fuß sind
Wenn ich die Toleranz erhöhe, erhalte ich eine falsche Ausgabe (nach der Definition von 20 als Toleranz für das Einrasten ist die grüne Linie das Ergebnis):
Irgendwelche Ideen, warum das Knipsen nicht richtig funktioniert? Irgendwelche Vorschläge zur Lösung dieses Problems?
Antworten:
Die
shapely.ops.snap
Funktion rastet nur an den Scheitelpunkten von Geometrien ein.Siehe die Abbildung unten. Auf der linken Seite befindet sich der rote Scheitelpunkt innerhalb der Fangtoleranz zum blauen Scheitelpunkt, sodass er schnappt. Rechts befindet sich der rote Scheitelpunkt außerhalb der Fangtoleranz (obwohl er näher am Rand liegt!).
Shapely bietet keinen Algorithmus zum Einrasten von Eckpunkten an Kanten. Es sollte jedoch nicht allzu schwierig sein, einen zu schreiben
shapely.ops.nearest_points
. So etwas (nicht getestet und nicht besonders effizient):quelle
if p1.distance(p2 <= threshold):
sollte seinif p1.distance(p2) <= threshold: