Пересечение между многоугольником и линией в форме

Я пытаюсь найти пересечения между круговыми многоугольниками и линией, а затем объединить результаты.

Я ожидал бы, что все пересечения принадлежат линии и также их соединению, но это не то, что я вижу.

Вот пример:

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 ответа

Насколько я знаю, нет стройной встроенной функции, чтобы делать то, что вам нужно. Кроме того, как вы заметили, есть несколько ошибок, которые вам нужно устранить. К счастью, есть несколько полезных функций, которые могут помочь вам реализовать краткое решение:

  1. project метод LineString, который берет точку и дает вам расстояние от первой точки линии до ближайшей точки линии к данной точке.
  2. 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

Другие вопросы по тегам