【问题标题】:Find coordinate of the closest point on polygon in Shapely在Shapely中查找多边形上最近点的坐标
【发布时间】:2015-10-23 21:24:24
【问题描述】:

假设我有以下多边形和点:

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

我可以计算点到多边形的距离...

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

...但我想知道最短距离测量到的多边形边界上点的坐标。

我最初的方法是通过点到多边形的距离来缓冲该点,并找到该圆与多边形相切的点:

>>> buff = point.buffer(dist) 

但是,我不确定如何计算这一点。这两个多边形不相交,所以list(poly.intersection(buff)) 不会给我那个点。

我在正确的轨道上吗?有没有更直接的方法?

【问题讨论】:

标签: python shapely


【解决方案1】:

虽然eguaio 的答案完成了这项工作,但还有一种更自然的方法可以使用shapely.ops.nearest_points 函数获得最近点:

from shapely.geometry import Point, Polygon
from shapely.ops import nearest_points

poly = Polygon([(0, 0), (2, 8), (14, 10), (6, 1)])
point = Point(12, 4)
# The points are returned in the same order as the input geometries:
p1, p2 = nearest_points(poly, point)
print(p1.wkt)
# POINT (10.13793103448276 5.655172413793103)

结果与其他答案相同:

from shapely.geometry import LinearRing
pol_ext = LinearRing(poly.exterior.coords)
d = pol_ext.project(point)
p = pol_ext.interpolate(d)
print(p.wkt)
# POINT (10.13793103448276 5.655172413793103)
print(p.equals(p1))
# True

【讨论】:

  • 现在应该是正确答案了。在我编写原始答案时,此功能不可用。看来我现在应该重新阅读库文档了。
  • @eguaio Version historyGitHubnearest_points 是在 2014 年添加的。
  • 那我应该更仔细地阅读文档! @Georgy 感谢您的贡献。
  • 如果您的点在多边形内,您可以使用:p1, p2 = nearest_points(poly.boundary, point)
  • @ZeeshanEqbal 这应该回答你的问题:Find longest “straight” path between Point and Polygon
【解决方案2】:

请不要对此答案投票,正确答案是@Georgy 下面的答案。

我的答案供参考:

有一个简单的方法可以依靠 Shapely 函数来做到这一点。 首先,您需要获取多边形的外环并将点投影到环上。必须将外部设置为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]

值得一提的是,此方法仅在您知道该点位于多边形外部时才有效。如果该点位于其内环之一内,则需要针对这种情况调整代码。

如果多边形没有内环,则代码甚至适用于多边形内的点。那是因为我们实际上将外环作为线串来处理,而忽略了线串是否来自多边形。

很容易将此代码扩展到计算任何点(多边形内部或外部)到多边形边界中最近点的距离的一般情况。您只需要计算从该点到所有线环的最近点(和距离):外环和多边形的每个内环。然后,您只需保留其中的最小值。

【讨论】:

  • 这是完美的。我不熟悉那些 Shapely 函数。如果外部点是多边形,这也可以吗?我尝试将 pol_ext.project() 用于多边形和线串,但收到错误消息“GEOSProject_r 的第三个参数必须是 Point*”。对此有何建议?
  • 我不知道。我认为除了自己实施某些东西之外,您别无选择。 Tome Karzes 的回答可以很容易地适应这种情况(但使用其中一个多边形作为“点”,因为你有上述方法)。
  • stackoverflow.com/questions/38514607/… 问题的答案中,您可以找到 Tom Karzes 建议算法的实现,以获取两个不相交的线串之间的距离。那里的代码可以很容易地适应获取线串和点之间的距离,并且不依赖于形状函数。
  • 谢谢,这很有帮助。您能否更详细地说明为什么当点在多边形内时它不起作用?我用不同的点运行了这段代码几次,结果看起来是正确的。
  • 当然。我会完成答案。我假设你的多边形没有内环,在这种情况下,代码确实可以工作。
【解决方案3】:

有两种情况需要考虑:(1)最近点位于边上,(2)最近点是顶点。案例 (2) 很容易检查 - 只需获取到每个顶点的距离并找到最小值。案例(1)涉及更多的数学,但仍然不算太糟糕。对于情况 (1),您需要做两件事:(a) 找到从点到边缘的法线与边缘相交的位置,以及 (b) 验证它是否位于线段内(而不是延伸超过其中一个结束)。如果它不在线段上,则忽略它(其中一个顶点将是该边上最近的点)。

【讨论】:

    【解决方案4】:

    我喜欢将多边形 poly 与以 point 点为中心的圆 buff 相交的想法,正如您在问题中所写的那样.我会建议: poly.boundary.intersection(buff.boundary)

    【讨论】:

      猜你喜欢
      • 2014-08-16
      • 2013-12-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-02
      • 2011-06-20
      • 1970-01-01
      相关资源
      最近更新 更多