Чому оснащення Shapely (оснащення GEO) не працює так, як очікувалося?


14

Я намагаюся прив’язати дві лінії один до одного за допомогою Shapely / Geopandas, але результат оснащення дуже дивний. Я намагався :

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")

І отримали такий результат:

лінії1 = червоні лінії

lines2 = чорні лінії

Перед оснащенням

Після оснащення (з допуском 14): сині лінії є результатом оснащення

У цьому випадку лінії правильно прориваються Після хапання

Ще один приклад, коли він не працював так, як очікувалося: (до оснащення) Перед оснащенням

І ось результат після оснащення. Лише частина прив’язана до чорної лінії (південна сторона). Хоча оригінальні лінії досить близькі і в межах 14 футів Після хапання

Якщо я збільшую толерантність, я отримую неправильний вихід, приблизно так (після визначення 20 як допуску оснащення, в результаті з'являється зелена лінія):

Після 20 як толерантність

Будь-які ідеї щодо того, чому оснащення не працює належним чином? Будь-які пропозиції щодо вирішення цієї проблеми?



@gene, ти повинен перетворити свій коментар у відповідь, я думаю.
nmtoken

Чи можете ви поділитися даними або їх частинами для відтворення цієї проблеми?
bugmenot123

2
Надано посібник користувача Shapely 1.6: "Функція snap () у shapely.ops прив'язує вершини в одній геометрії до вершин у другій геометрії із заданим допуском." Як я розумію, він не замикає геометрії, близькі одна до одної, а замикає їх вершини близько один до одного. Отже, якщо будь-яка геометрія близька до іншої геометрії, вона замикає їх вершини в межах порогу.
Кадір Şahbaz

Відповіді:


6

shapely.ops.snapФункція прив'язується до вершин тільки геометрій.

Дивіться ілюстрацію нижче. Зліва червона вершина знаходиться в межах толерантності до синьої вершини, тому вона буде оснащена. Права червона вершина знаходиться поза межами толерантності до хапання (незважаючи на те, що вона знаходиться ближче до краю!).

візуалізація толерантності

Shapely не забезпечує алгоритм прив'язування вершин до ребер. Написати одне за допомогою не повинно бути дуже складноshapely.ops.nearest_points . Щось подібне (не перевірено і не особливо ефективно):

from shapely.ops import nearest_points

def snap(g1, g2, threshold):
    coordinates = []
    for x, y in g1.coords:  # for each vertex in the first line
        point = Point(x, y)
        p1, p2 = nearest_points(point, g2)  # find the nearest point on the second line
        if p1.distance(p2 <= threshold):
            # it's within the snapping tolerance, use the snapped vertex
            coordinates.append(p2.coords[0])
        else:
            # it's too far, use the original vertex
            coordinates.append((x, y))
    # convert coordinates back to a LineString and return
    return LineString(coordinates)

Дуже круто, але я думаю, що if p1.distance(p2 <= threshold):має бутиif p1.distance(p2) <= threshold:
chrislarson
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.