我有扩展多边形的代码,它的工作原理是将 xs 和 ys 乘以一个因子,然后将所得多边形重新居中于原始多边形的中心。
我还有代码来查找扩展因子的值,给定多边形需要到达的点:
import numpy as np
import itertools as IT
import copy
from shapely.geometry import LineString, Point
def getPolyCenter(points):
"""
http://stackoverflow.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)
此代码仅在该点与其中一条多边形线直接相对时才有效。
将您的方法
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()
等方法来找出哪一段位于中心的正确“一侧” 。您将需要处理很多边缘情况。完成所有这些操作后,您的两个端点(除非它不是凸的,在这种情况下取距离您中心最远的线段)端点构成要扩展的线段。
从点 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 )