Próbuję przyciągnąć do siebie dwie linie za pomocą Shapely / Geopandas, ale rezultat przyciągania jest bardzo dziwny. Próbowałem :
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")
I uzyskałem ten wynik:
lines1 = czerwone linie
linie2 = czarne linie
Po przyciąganiu (z tolerancją 14): niebieskie linie są wynikiem przyciągania
W takim przypadku linie są poprawnie przyciągane
Kolejny przykład, w którym nie działał zgodnie z oczekiwaniami: (przed snapowaniem)
A oto wynik po przyciągnięciu. Tylko część jest przyciągana do czarnej linii (strona południowa). Chociaż oryginalne linie są dość blisko i w obrębie 14 stóp
Jeśli zwiększę tolerancję, otrzymam błędny wynik, coś takiego (po zdefiniowaniu 20 jako tolerancji przyciągania, wynikiem jest zielona linia):
Wszelkie pomysły na to, dlaczego przyciąganie nie działa poprawnie? Wszelkie sugestie dotyczące rozwiązania tego problemu?
Odpowiedzi:
shapely.ops.snap
Funkcja jest przyciągany do wierzchołków tylko geometrii.Zobacz ilustrację poniżej. Po lewej czerwony wierzchołek mieści się w tolerancji przyciągania do niebieskiego wierzchołka, więc zostanie przyciągnięty. Po prawej czerwony wierzchołek jest poza tolerancją przyciągania (mimo że jest bliżej krawędzi!).
Shapely nie zapewnia algorytmu przyciągania wierzchołków do krawędzi.
shapely.ops.nearest_points
Jednak napisanie takiego przy użyciu nie powinno być trudne . Coś takiego (nie testowane i niezbyt wydajne):źródło
if p1.distance(p2 <= threshold):
powinno byćif p1.distance(p2) <= threshold: