如何扩展多边形直到其中一个边界到达一个点
How to Expand a Polygon Until One of the Borders Reaches a Point
我有扩展多边形的代码,它的工作原理是将 xs 和 ys 乘以一个因子,然后将所得多边形重新居中于原始多边形的中心。
给定多边形需要到达的点,我也有代码可以找到扩展因子的值:
import numpy as np
import itertools as IT
import copy
from shapely.geometry import LineString, Point
def getPolyCenter(points):
"""
(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)
此代码仅在该点与其中一条多边形线直接相对时才有效。
将您的方法 distancePolygon2PointAndCenter
修改为
Returns the distance from a point to the nearest line of the polygon
到return点到中心到点的射线相交的线段的距离。这是多边形完全展开后与点相交的线。要获得此线段,请取多边形每个线段的两个端点,并将它们代入与前面提到的射线平行和相交的直线方程中。即y = ((centerY-pointY)/(centerX-pointX)) * (x - centerX) + centerY
。您想要找到端点,其中一个端点与线相交,或者两个端点位于线的相对两侧。
然后,唯一剩下要做的就是确保我们选择与直线右侧 "side" 相交的线段。为此,有几个选项。故障安全方法是使用公式 cos(theta) = sqrt((centerX**2 + centerY**2)*(pointX**2 + pointY**2)) / (centerX * pointX + centerY * pointY)
但是,您可以使用诸如比较 x 和 y 值、采用 arctan2()
等方法来找出哪个段在正确的 "side"的中心。您将只需要涵盖很多边缘情况。完成所有这些之后,您的两个端点(除非它不是凸的,在这种情况下取离您中心最远的线段)端点构成要扩展的线段。
确定以"polygon center"为扩展中心点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
确定您想要到达的点,然后计算您的多边形需要扩展多少百分比才能到达该点并使用 shapely.affinity.scale 函数。例如,在我的例子中,我只需要将多边形放大 5%:
region = shapely.affinity.scale(myPolygon,
xfact=1.05, yfact=1.05 )
我有扩展多边形的代码,它的工作原理是将 xs 和 ys 乘以一个因子,然后将所得多边形重新居中于原始多边形的中心。
给定多边形需要到达的点,我也有代码可以找到扩展因子的值:
import numpy as np
import itertools as IT
import copy
from shapely.geometry import LineString, Point
def getPolyCenter(points):
"""
(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)
此代码仅在该点与其中一条多边形线直接相对时才有效。
将您的方法 distancePolygon2PointAndCenter
修改为
Returns the distance from a point to the nearest line of the polygon
到return点到中心到点的射线相交的线段的距离。这是多边形完全展开后与点相交的线。要获得此线段,请取多边形每个线段的两个端点,并将它们代入与前面提到的射线平行和相交的直线方程中。即y = ((centerY-pointY)/(centerX-pointX)) * (x - centerX) + centerY
。您想要找到端点,其中一个端点与线相交,或者两个端点位于线的相对两侧。
然后,唯一剩下要做的就是确保我们选择与直线右侧 "side" 相交的线段。为此,有几个选项。故障安全方法是使用公式 cos(theta) = sqrt((centerX**2 + centerY**2)*(pointX**2 + pointY**2)) / (centerX * pointX + centerY * pointY)
但是,您可以使用诸如比较 x 和 y 值、采用 arctan2()
等方法来找出哪个段在正确的 "side"的中心。您将只需要涵盖很多边缘情况。完成所有这些之后,您的两个端点(除非它不是凸的,在这种情况下取离您中心最远的线段)端点构成要扩展的线段。
确定以"polygon center"为扩展中心点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
确定您想要到达的点,然后计算您的多边形需要扩展多少百分比才能到达该点并使用 shapely.affinity.scale 函数。例如,在我的例子中,我只需要将多边形放大 5%:
region = shapely.affinity.scale(myPolygon,
xfact=1.05, yfact=1.05 )