如何扩展多边形直到其中一个边界到达一个点

Posted

技术标签:

【中文标题】如何扩展多边形直到其中一个边界到达一个点【英文标题】:How to Expand a Polygon Until One of the Borders Reaches a Point 【发布时间】:2018-12-09 04:50:38 【问题描述】:

我有扩展多边形的代码,它的工作原理是将 xs 和 ys 乘以一个因子,然后将生成的多边形重新居中在原始的中心。

给定多边形需要到达的点,我还有代码可以找到扩展因子的值:

import numpy as np
import itertools as IT
import copy
from shapely.geometry import LineString, Point

def getPolyCenter(points):
    """
    http://***.com/a/14115494/190597 (mgamba)
    """
    area = area_of_polygon(*zip(*points))
    result_x = 0
    result_y = 0
    N = len(points)
    points = IT.cycle(points)
    x1, y1 = next(points)
    for i in range(N):
        x0, y0 = x1, y1
        x1, y1 = next(points)
        cross = (x0 * y1) - (x1 * y0)
        result_x += (x0 + x1) * cross
        result_y += (y0 + y1) * cross
    result_x /= (area * 6.0)
    result_y /= (area * 6.0)
    return (result_x, result_y)

def expandPoly(points, factor):
    points = np.array(points, dtype=np.float64)
    expandedPoly = points*factor
    expandedPoly -= getPolyCenter(expandedPoly)
    expandedPoly += getPolyCenter(points)
    return np.array(expandedPoly, dtype=np.int64)

def distanceLine2Point(points, point):
    points = np.array(points, dtype=np.float64)
    point = np.array(point, dtype=np.float64)

    points = LineString(points)
    point = Point(point)
    return points.distance(point)

def distancePolygon2Point(points, point):
    distances = []
    for i in range(len(points)):
        if i==len(points)-1:
            j = 0
        else:
            j = i+1
        line = [points[i], points[j]]
        distances.append(distanceLine2Point(line, point))

    minDistance = np.min(distances)
    #index = np.where(distances==minDistance)[0][0]

    return minDistance 

"""
    Returns the distance from a point to the nearest line of the polygon,
    AND the distance from where the normal to the line (to reach the point)
    intersets the line to the center of the polygon.
"""
def distancePolygon2PointAndCenter(points, point):
    distances = []
    for i in range(len(points)):
        if i==len(points)-1:
            j = 0
        else:
            j = i+1
        line = [points[i], points[j]]
        distances.append(distanceLine2Point(line, point))

    minDistance = np.min(distances)
    i = np.where(distances==minDistance)[0][0]
    if i==len(points)-1:
        j = 0
    else:
        j = i+1
    line = copy.deepcopy([points[i], points[j]])

    centerDistance = distanceLine2Point(line, getPolyCenter(points))

    return minDistance, centerDistance

minDistance, centerDistance = distancePolygon2PointAndCenter(points, point)
expandedPoly = expandPoly(points, 1+minDistance/centerDistance)

此代码仅在点与多边形线之一直接相对时有效。

【问题讨论】:

如果我正确理解了您的描述(不是您的代码),那么您通过将多边形顶点从多边形中心移开来生长多边形。根据您的标题,您希望这样做直到一个(或多个)边框达到特定点,但是您的文本描述然后说您将所有点乘以一个因子。您能解释一下为什么您认为该实现会按照您的标题所暗示的那样去做吗? 我们假设多边形是凸的吗?如果是这样,那么这只是一个几何问题。 @Mike'Pomax'Kamermans 一开始我也很困惑,但现在我想我明白了。想象一下网格上的多边形。要增加大小,请将每个点乘以一个因子,但将其设想为增加网格的粒度,使所有内容保持原样。多边形已有效增长,但使用新坐标,它可能需要平移(无论出于何种原因)。 【参考方案1】:

确定您想要到达的点,然后计算您的多边形需要扩展多少 % 才能到达该点并使用shapely.affinity.scale 函数。例如,在我的例子中,我只需要将多边形放大 5%:

region = shapely.affinity.scale(myPolygon, 
                            xfact=1.05, yfact=1.05 )

【讨论】:

【参考方案2】:

确定什么是“多边形中心”作为扩展的中心点C。也许它是质心(或具有其他属性的某个点?)。

从你的点 P 到 C 做一条线段。找到 PC 和多边形边缘之间的交点 I。如果多边形是凹的并且有一些交点,选择最接近P的一个。

计算膨胀系数:

 E = Length(PC) / Length(CI)

计算新的顶点坐标。对于多边形的第 i 个顶点:

 V'[i].X = C.X + (V[i].X - C.X) * E
 V'[i].Y = C.Y + (V[i].Y - C.Y) * E

【讨论】:

【参考方案3】:

修改你的方法distancePolygon2PointAndCenter 来代替

返回一个点到多边形最近直线的距离

返回从一个点到由中心到该点的射线相交的线段的距离。一旦多边形完全展开,这条线将与该点相交。要获得此段,请取多边形每个段的两个端点,并将它们插入到与前面提到的射线平行和相交的线的方程中。那是y = ((centerY-pointY)/(centerX-pointX)) * (x - centerX) + centerY。您想要找到其中一个与线相交的端点,或者两个端点位于线的相对两侧。

然后,唯一剩下要做的就是确保我们选择与线的右侧“边”相交的线段。为此,有几个选项。故障安全方法是使用公式 cos(theta) = sqrt((centerX**2 + centerY**2)*(pointX**2 + pointY**2)) / (centerX * pointX + centerY * pointY) 但是,您可以使用诸如比较 x 和 y 值、取 arctan2() 等方法来确定哪个段位于中心的正确“一侧” .你只会有很多边缘情况需要覆盖。说完这一切之后,你的两个(除非它不是凸的,在这种情况下取​​离你中心最远的部分)端点组成了要扩展的部分。

【讨论】:

好的,我已经按照你说的做了,它有帮助(我只是使用形状函数来找到交叉点,绘制以确保然后找到距离)。还有一个问题:扩展函数不会“从中心”扩展,当您将所有点乘以 2 时,它确实会扩展多边形,但从中心向所有方向扩展的因子是不同的。 平移多边形和点(一起),使多边形的中心位于原点 (0, 0),然后计算您的扩展系数。然后展开原始多边形并根据需要进行平移。 好吧,不,我的最后一条评论不正确,从中心扩展因子 == 将 (x,y) 乘以因子。我有一个错误,我从 shapely Point 转换为 np.array() 点。现在可以完美运行了!

以上是关于如何扩展多边形直到其中一个边界到达一个点的主要内容,如果未能解决你的问题,请参考以下文章

使用 JTS,如何从外部点找到多边形边界上最近的点?

谁知道如何搜索平面点集的边界?

子集空间点以提取多边形内部的空间点(国家边界)

根据种子点识别多边形边界的最佳方法是啥?

查找给定多边形 w.r.t 的两个“边界”顶点。已知(光源)点

从空间点数据创建边界多边形,以便在传单中绘图