Пересечение между многоугольником и линией в форме
Я пытаюсь найти пересечения между круговыми многоугольниками и линией, а затем объединить результаты.
Я ожидал бы, что все пересечения принадлежат линии и также их соединению, но это не то, что я вижу.
Вот пример:
from shapely.geometry import LineString, Point
line = LineString([(2, 5), (2.1, 1)]) # slightly oblique line
point1 = Point(2.5, 3)
int1 = line.intersection(point1.buffer(1))
int2 = line.intersection(point1.buffer(1.3))
union = int1.union(int2)
print union.length
print int2.length
Результаты:
+4,22183534925
+2,43702622444
Поскольку int2 содержит int1, я ожидаю, что их объединение будет точно int2. Я бы также ожидал, что объединение будет просто LineString, но вместо этого это MultiLineString, состоящий из 4 строк.
Если я строю линии объединения, я вижу, как они действительно близки друг к другу, но не на одной линии.
Я думаю, что это связано с разрешением значений фигурных объектов.
Любое предложение, как объединить "почти параллельные" линии в одну? Или вы предлагаете другое решение этой проблемы?
2 ответа
Насколько я знаю, нет стройной встроенной функции, чтобы делать то, что вам нужно. Кроме того, как вы заметили, есть несколько ошибок, которые вам нужно устранить. К счастью, есть несколько полезных функций, которые могут помочь вам реализовать краткое решение:
project
метод LineString, который берет точку и дает вам расстояние от первой точки линии до ближайшей точки линии к данной точке.interpolate
метод LineString, который дает расстояние, он дает вам точку, которая находится в LineString с этим расстоянием от первой точки линии.
Я предполагаю, что вы знаете, какая линия находится внутри другой, как в примере. В этом случае вы можете поместить точки более короткой линии в более длинную линию, а затем отсортировать эти точки, учитывая их расстояние до первой точки линии.
С помощью следующего кода,
from shapely.geometry import LineString, Point
from shapely.ops import linemerge
def getProyection(aline, point_coords):
return aline.interpolate(aline.project(Point(point_coords)))
def mergeInside(aline, inside_line):
mline_tups = [(aline.project(Point(p)), p) for p in aline.coords]
mline_tups.extend([ (aline.project(Point(p)), getProyection(aline, p))
for p in inside_line.coords])
mline_tups.sort()
return LineString([p for _, p in mline_tups])
line = LineString([(2, 5), (2.1, 1)]) # slightly oblique line
point1 = Point(2.5, 3)
int1 = line.intersection(point1.buffer(1))
int2 = line.intersection(point1.buffer(1.3))
merged_line = mergeInside(int2, int1)
print(int1)
print(int2)
print(merged_line)
Я получил:
LINESTRING (2.02796158358983 3.881536656406788, 2.072567874421353 2.097285023145893)
LINESTRING (2.019819096605441 4.207236135782384, 2.080725721869193 1.770971125232286)
LINESTRING (2.019819096605441 4.207236135782384, 2.027961583589831 3.881536656406788, 2.072567874421353 2.097285023145893, 2.080725721869193 1.770971125232286)
Поскольку меня интересует, главным образом, длина объединения, а не его точные вершины, я нашел другой способ его измерения.
from shapely.geometry import LineString, Point
line = LineString([(2, 5), (2.1, 1)]) # slightly oblique line
point1 = Point(2.5, 3)
int1 = line.intersection(point1.buffer(1))
int2 = line.intersection(point1.buffer(1.3))
line_not_intersected = line.difference(point1.buffer(1))
line_not_intersected = line_not_intersected.difference(point1.buffer(1.3))
print line.length - line_not_intersected.length
print int2.length
и это дает ожидаемый результат:
+2,43702622444
+2,43702622444
Интересно и раздражает одновременно, если я получу союз как
union = line.difference(line_not_intersected)
union - это LineString, но его длина не равна разнице длин двух строк.
print line.length - line_not_intersected.length
print union.length
+2,43702622444
+4,00124980475