2015-10-23 2 views
12

Скажем, у меня есть следующий многоугольник и точка:Найти координата ближайшей точки на Polygon стройные

>>> poly = Polygon([(0, 0), (2,8), (14, 10), (6,1)]) 
>>> point=Point(12,4) 

enter image description here

можно рассчитать расстояние точки на полигоне ...

>>> dist=point.distance(poly) 
>>> print dist 
2.49136439561 

... но я хотел бы знать координату точки на границе полигона, где это кратчайшее расстояние.

Мой первоначальный подход к буферу точку на это расстояние до полигона, и найти точку, в которой этот круг является касательной к полигону:

>>> buff=point.buffer(dist) 

enter image description here Однако, я не знаю, как для вычисления этой точки. Два полигона не пересекаются, поэтому list(poly.intersection(buff)) не даст мне эту точку.

Я нахожусь на правильном пути с этим? Есть ли более простой метод?

+2

Duplicate? Http: // StackOverflow.com/questions/10983872/distance-from-a-point-to-a-polygon –

+0

@ Олег, я не верю, что это дубликат. Как я упоминал выше, у меня нет вопроса о вычислении минимального расстояния до многоугольника. Я пытаюсь найти точку на границе полигона, где измеряется это минимальное расстояние. – AJG519

+0

Было бы интересно узнать, как пройти дистанцию, если точка лежит внутри полигона. Например, когда: 'point = Point (4,4)' – kuanb

ответ

14

Существует простой способ сделать это ретрансляцию на стройных функциях. Во-первых, вам нужно получить внешнее кольцо многоугольника и проецировать на кольцо кольцо . Обязательно получить внешний вид как LinearRing, так как полигоны не имеют функции проекции. В отличие от интуиции, это дает расстояние, расстояние от первой точки кольца до точки в кольце, ближайшем к данной точке. Затем вы просто используете это расстояние, чтобы получить точку с помощью функции интерполяции . См. Код ниже.

from shapely.geometry import Polygon, Point, LinearRing 

poly = Polygon([(0, 0), (2,8), (14, 10), (6,1)]) 
point = Point(12,4) 

pol_ext = LinearRing(poly.exterior.coords) 
d = pol_ext.project(point) 
p = pol_ext.interpolate(d) 
closest_point_coords = list(p.coords)[0] 

Важно отметить, что этот метод работает только если вы знаете, что точка находится вне внешности многоугольника. Если точка находится внутри одного ее внутренних колец, вам необходимо адаптировать код для этой ситуации.

Если многоугольник не имеет внутренних колец, код будет работать даже для точек внутри многоугольника. Это потому, что мы на самом деле работаем с внешним кольцом в виде строки и игнорируем, является ли строка строки из многоугольника или нет.

Этот код легко распространить на общий случай вычисления расстояния любой точки (внутри или снаружи многоугольника) до ближайшей точки на границе многоугольника. Вам нужно всего лишь вычислить ближайшую точку (и расстояние) от точки до всех линейных колец: внешнее кольцо и каждое внутреннее кольцо многоугольника. Тогда вы просто сохраните минимум.

enter image description here

+0

это прекрасно. Я не был знаком с этими функциями Shapely. Может ли это также работать, если внешняя точка вместо этого была полигоном? Я попытался использовать pol_ext.project() как для полигонов, так и для linestring, но получить сообщение об ошибке «третий аргумент GEOSProject_r должен быть точкой *». Любые предложения по этому поводу? – AJG519

+0

Не знаю, что знаю. Я думаю, для этого у вас нет другого выбора, кроме как реализовать что-то самостоятельно. Ответ Tome Karzes можно легко добавить к этому сценарию (но используя один из полигонов как «точку», так как у вас есть вышеупомянутый метод). – eguaio

+0

В ответ на вопрос http://stackoverflow.com/questions/38514607/find-shortest-path-from-one-geometry-to-other-on-shapely/38997756#38997756 вы можете найти реализацию Tom Karzes предложенный алгоритм для получения расстояния между двумя не пересекающимися линиями. Код может быть легко адаптирован для получения расстояния между линией и точкой и не зависит от стройных функций. – eguaio

0

Рассматриваются два случая: (1) ближайшая точка лежит на ребре и (2) ближайшая точка является вершиной. Случай (2) легко проверить - просто возьмите расстояние до каждой вершины и найдите минимум. Случай (1) включает в себя немного больше математики, но все же не так уж плохо. Вам нужно сделать две вещи для случая (1): (a) найти, где нормаль от точки до края пересекает край, и (b) проверить, что она лежит внутри отрезка (в отличие от прохода мимо одного из заканчивается). Если он не находится в сегменте линии, проигнорируйте его (одна из вершин будет ближайшей точкой на этом ребре).

Смежные вопросы