<p>根据@tcaswell的建议,<a href="http://toblerity.org/shapely/manual.html" rel="nofollow noreferrer">shapely</a>使得这一点相当简单。具体来说,该方法是计算多边形边界和所选x位置的垂直线之间的<a href="http://toblerity.org/shapely/manual.html#object.intersection" rel="nofollow noreferrer">^{<cd1>}</a>(即重叠)。在</p>
<p>这里需要注意的一点是,shapely多边形是填充对象,因此计算这些多边形与直线的重叠将返回多边形内部的直线段。因此,要得到垂直线与多边形边缘相交的点,计算多边形的<a href="http://toblerity.org/shapely/manual.html#object.boundary" rel="nofollow noreferrer">^{<cd2>}</a>属性与垂直线的交集可能是最简单的。在</p>
<h2>实施</h2>
<p>以下函数返回输入多边形与指定x值处垂直线的交点:</p>
<pre><code>import shapely.geometry as sg
def polygon_intersect_x(poly, x_val):
"""
Find the intersection points of a vertical line at
x=`x_val` with the Polygon `poly`.
"""
if x_val < poly.bounds[0] or x_val > poly.bounds[2]:
raise ValueError('`x_val` is outside the limits of the Polygon.')
if isinstance(poly, sg.Polygon):
poly = poly.boundary
vert_line = sg.LineString([[x_val, poly.bounds[1]],
[x_val, poly.bounds[3]]])
pts = [pt.xy[1][0] for pt in poly.intersection(vert_line)]
pts.sort()
return pts
</code></pre>
<h2>示例用法</h2>
<p>首先创建一个示例<code>shapely.geometry.Polygon</code>:</p>
^{pr2}$
<p>请注意,还可以通过以下方式创建shapely对象:
a) <a href="http://toblerity.org/shapely/manual.html#numpy-and-python-arrays" rel="nofollow noreferrer">wrapping NumPy arrays to shapely types</a>,
b) 将MPL路径转换为shapely多边形<code>p = sg.Polygon(my_path.vertices)</code>。在</p>
<p>上述函数现在可用于计算最小/最大交点,如下所示:</p>
<pre><code>x_val = 45
points = polygon_intersect_x(p, x_val)
minmax = [points[0], points[-1]] # The values are already sorted
print minmax
# [-12.5, 88.5714286]
</code></pre>
<p>下面是一个简单的图来演示这种方法:</p>
<pre><code>import matplotlib.pyplot as plt
ax = plt.gca()
ax.fill(*p.boundary.xy, color='y')
ax.axvline(x_val, color='b')
ax.plot([x_val, ] * len(points), points, 'b.')
ax.plot([x_val, ] * 2, minmax, 'ro', ms=10)
</code></pre>
<p><a href="https://i.stack.imgur.com/SZ2fS.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/SZ2fS.png" alt="Example Figure: Red dots are the 'minmax' values, blue dots are the other intersections."/></a></p>