Shapely 多边形与 Matplotlib 楔形的交集
Intersection of a Shapely polygon with a Matplotlib wedge
在这种情况下,我正在绘制 matplotlib.patches.Wedge
objects and also buffered shapely.geometry.LineString
个对象。我需要计算这两个对象的重叠区域。但是,Wedge
是一个 matplotlib.wedges
对象,不能与 Shapely 的 .intersection()
方法一起使用。
我该怎么做?
这是一些代码:
from shapely.geometry import LineString
from matplotlib.patches import Wedge
from matplotlib import pyplot as plt
from descartes.patch import PolygonPatch
width = 5
radius = 1
rich = 1
circle_patch = Wedge((0, 0), radius+3,
0, 360, 3)
fig, ax = plt.subplots()
ax.add_patch(circle_patch)
ax.plot(0, 0, 'xr')
plt.autoscale()
coords = [
[0, 0],
[0, 1],
[0, 2],
[1, 2],
[2, 2]
]
stick = LineString(coords)
stick_patch = PolygonPatch(stick.buffer(0.5))
ax.add_patch(stick_patch)
x, y = stick.xy
ax.plot(x, y, 'r-', zorder=1)
plt.show()
area = stick.buffer(0.5).intersection(circle_patch).area
P.S。必须是环状,不能是圆形
想通了。 matplotlib.patches
class 的 ._path.vertices
成员为您提供楔形对象的坐标数组,然后您可以将其与 Shapely 的 LinearRing
class 一起使用像这样创建一个 Shapely 对象:
from shapely.geometry import LineString, LinearRing
from matplotlib.patches import Wedge
width = 5
radius = 1
rich = 1
circle_patch = Wedge((0, 0), radius,
0, 360,)
ring_coords = circle_patch._path.vertices
ring_coords = ring_coords[(ring_coords[:, 0] != 0) & (ring_coords[:, 1] != 0)]
ring = LinearRing(ring_coords)
但是它确实需要对坐标数组进行操作,我认为这不是最可靠的方法,但它对我有用。此外,环并不完全平滑,但我相信可以使用某些或其他 Numpy
或 Scipy
函数对坐标数组进行一些平滑处理。
编辑: 要创建单个楔形线,必须删除楔形的 width
成员。然而,这可以在以后使用 Shapely 的 buffer()
函数重新合并。
最简单的解决方案是不使用 Matplotlib 补丁并首先使用 Shapely 构建 wedge-polygon:
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 多边形的交叉区域。在这两个中,我首先将补丁转换为形状多边形。您 仅使用 Matplotlib 获得交叉区域。
1) 使用 .get_path()
method on the Matplotlib's patch from which you can extract vertices
as a NumPy array and convert it to a Shapely polygon using asPolygon
:
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 中从无效多边形中创建有效多边形的常用技巧。在 中,从 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
在这种情况下,我正在绘制 matplotlib.patches.Wedge
objects and also buffered shapely.geometry.LineString
个对象。我需要计算这两个对象的重叠区域。但是,Wedge
是一个 matplotlib.wedges
对象,不能与 Shapely 的 .intersection()
方法一起使用。
我该怎么做? 这是一些代码:
from shapely.geometry import LineString
from matplotlib.patches import Wedge
from matplotlib import pyplot as plt
from descartes.patch import PolygonPatch
width = 5
radius = 1
rich = 1
circle_patch = Wedge((0, 0), radius+3,
0, 360, 3)
fig, ax = plt.subplots()
ax.add_patch(circle_patch)
ax.plot(0, 0, 'xr')
plt.autoscale()
coords = [
[0, 0],
[0, 1],
[0, 2],
[1, 2],
[2, 2]
]
stick = LineString(coords)
stick_patch = PolygonPatch(stick.buffer(0.5))
ax.add_patch(stick_patch)
x, y = stick.xy
ax.plot(x, y, 'r-', zorder=1)
plt.show()
area = stick.buffer(0.5).intersection(circle_patch).area
P.S。必须是环状,不能是圆形
想通了。 matplotlib.patches
class 的 ._path.vertices
成员为您提供楔形对象的坐标数组,然后您可以将其与 Shapely 的 LinearRing
class 一起使用像这样创建一个 Shapely 对象:
from shapely.geometry import LineString, LinearRing
from matplotlib.patches import Wedge
width = 5
radius = 1
rich = 1
circle_patch = Wedge((0, 0), radius,
0, 360,)
ring_coords = circle_patch._path.vertices
ring_coords = ring_coords[(ring_coords[:, 0] != 0) & (ring_coords[:, 1] != 0)]
ring = LinearRing(ring_coords)
但是它确实需要对坐标数组进行操作,我认为这不是最可靠的方法,但它对我有用。此外,环并不完全平滑,但我相信可以使用某些或其他 Numpy
或 Scipy
函数对坐标数组进行一些平滑处理。
编辑: 要创建单个楔形线,必须删除楔形的 width
成员。然而,这可以在以后使用 Shapely 的 buffer()
函数重新合并。
最简单的解决方案是不使用 Matplotlib 补丁并首先使用 Shapely 构建 wedge-polygon:
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 多边形的交叉区域。在这两个中,我首先将补丁转换为形状多边形。您
1) 使用 .get_path()
method on the Matplotlib's patch from which you can extract vertices
as a NumPy array and convert it to a Shapely polygon using asPolygon
:
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 中从无效多边形中创建有效多边形的常用技巧。在 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