最简单的解决方案是不使用 Matplotlib 补丁,而是首先使用 Shapely 构造楔形多边形:
import matplotlib.pyplot as plt
from descartes.patch import PolygonPatch
from shapely.geometry import LineString, Point
outer_circle = Point(0, 0).buffer(4)
inner_circle = Point(0, 0).buffer(1)
wedge = outer_circle.difference(inner_circle)
stick = LineString([(0, 0), (0, 2), (2, 2)])
buffered_stick = stick.buffer(0.5)
intersection = buffered_stick.intersection(wedge)
wedge_patch = PolygonPatch(wedge)
stick_patch = PolygonPatch(buffered_stick, alpha=0.5, hatch='/')
intersection_patch = PolygonPatch(intersection, alpha=0.5, hatch='.')
fig, ax = plt.subplots()
ax.add_patch(wedge_patch)
ax.add_patch(stick_patch)
ax.add_patch(intersection_patch)
plt.autoscale()
如果由于某种原因这是不可能的,而您必须使用 Matplotlib 的 Wedge,那么我可以想出两种方法来获得它与 Shapely 多边形的交集区域。在他们两个中,我首先将补丁转换为 Shapely 多边形。你probably can't 只使用 Matplotlib 获取交叉区域。
1) 在 Matplotlib 的补丁上使用 .get_path() 方法,您可以从中提取 vertices 作为 NumPy 数组,并使用 asPolygon 将其转换为 Shapely 多边形:
import matplotlib.pyplot as plt
from descartes.patch import PolygonPatch
from matplotlib.patches import Wedge
from shapely.geometry import asPolygon, LineString
wedge_patch = Wedge(center=(0, 0),
r=4,
theta1=0,
theta2=360,
width=3)
stick = LineString([(0, 0), (0, 2), (2, 2)])
buffered_stick = stick.buffer(0.5)
wedge_path = wedge_patch.get_path()
wedge_polygon = asPolygon(wedge_path.vertices).buffer(0)
intersection = buffered_stick.intersection(wedge_polygon)
stick_patch = PolygonPatch(buffered_stick, alpha=0.5, hatch='/')
intersection_patch = PolygonPatch(intersection, alpha=0.5, hatch='.')
fig, ax = plt.subplots()
ax.add_patch(wedge_patch)
ax.add_patch(stick_patch)
ax.add_patch(intersection_patch)
plt.autoscale()
注意我应用于楔形多边形的buffer(0)。这是 Shapely 中的一个常见技巧,可以从无效多边形中生成有效多边形。在your answer 中,您在从ring_coords 中删除零时会执行类似的操作。
2) 通过访问Wedge 属性:center、r 和width,并使用它们重新创建多边形:
import matplotlib.pyplot as plt
from descartes.patch import PolygonPatch
from matplotlib.patches import Wedge
from shapely.geometry import LineString, Point
wedge_patch = Wedge(center=(0, 0),
r=4,
theta1=0,
theta2=360,
width=3)
stick = LineString([(0, 0), (0, 2), (2, 2)])
buffered_stick = stick.buffer(0.5)
outer_circle = Point(wedge_patch.center).buffer(wedge_patch.r)
inner_circle = Point(wedge_patch.center).buffer(wedge_patch.r - wedge_patch.width)
wedge_polygon = outer_circle.difference(inner_circle)
intersection = buffered_stick.intersection(wedge_polygon)
stick_patch = PolygonPatch(buffered_stick, alpha=0.5, hatch='/')
intersection_patch = PolygonPatch(intersection, alpha=0.5, hatch='.')
fig, ax = plt.subplots()
ax.add_patch(wedge_patch)
ax.add_patch(stick_patch)
ax.add_patch(intersection_patch)
plt.autoscale()
所有解决方案都提供相同的视觉输出。
所有方法给出的区域大致相同:
>>> intersection.area
3.3774012986988513 # 1st case
3.3823210603713694 # 2nd case and the original without Matplotlib