#python #polygon #intersection #shapely
#python #многоугольник #пересечение #shapely
Вопрос:
При работе с shapely я столкнулся со странной проблемой. Есть 2 точки p1 и p2, где первая принадлежит полигону, а вторая — нет. Когда я попытался найти пересечение между строкой строк, содержащей эти 2 точки в качестве конечных точек, с граничными линиями многоугольника, я получил сообщение о том, что пересечение не найдено. Интересно, как это возможно?
from shapely.geometry import Polygon as SPolygon, Point, LineString
p1 = Point(5.414213562373095, 2.585786437626905)
p2 = Point(15.17279752753168, -7.172797527531679)
l = LineString([p1, p2])
l1 = LineString([(2, 2), (2, 6)])
l2 = LineString([(2, 6), (6, 6)])
l3 = LineString([(6, 6), (6, 2)])
l4 = LineString([(6, 2), (2, 2)])
sp = SPolygon([(2, 2), (2, 6), (6, 6), (6, 2)])
print "Polygon contains p1:", sp.contains(p1)
print "Polygon contains p2:", sp.contains(p2)
for i, line in enumerate((l1, l2, l3, l4)):
res = l.intersects(line)
print "Line {0} intersects l1: {1}".format(i, res)
И вот выходные данные:
Polygon contains p1: True
Polygon contains p2: False
Line 0 intersects l1: False
Line 1 intersects l1: False
Line 2 intersects l1: False
Line 3 intersects l1: False
Комментарии:
1. Если я не ошибаюсь, ваша линия
l
проходит прямо через угол многоугольника. Я предполагаю, что числовые неточности приводят к тому, что он пропускает оба сегмента линии, встречающихся в этом углу, хотя он должен попасть в любой (или оба!) из них.2. Это странно. Это должно работать хотя бы для одной строки.
l.distance(l3)
дает0.0
иl.distance(l4)
дает6.435738891173273e-17
. Вот крупный план: i.stack.imgur.com/Foa7j.png Рассмотрите возможность открытия проблемы на GitHub: github.com/Toblerity/Shapely/issues
Ответ №1:
Я изменил l.intersects(line)
на l.intersection(line)
, и я действительно получил пересечение в
LINESTRING (6 6, 6 2) at Point (6, 2)
Не уверен, почему .instersects()
действует по-другому.
Затем я округлил p1 и p2
p1 = Point(round(5.414213562373095, 2), round(2.585786437626905, 2))
p2 = Point(round(15.17279752753168, 2), round(-7.172797527531679, 2))
И я получил 2 пересечения в
LINESTRING (6 6, 6 2) at POINT (6 2)
LINESTRING (6 2, 2 2) at POINT (6 2)
Это исправление также работало с .intersects()
(2 True)
Shapely может быть немного неудобным с точностью с плавающей запятой, и я обычно могу исправить проблему путем округления. Хотя это может быть неприемлемо для вас.