http://matplotlib.org/examples/pylab_examples/ellipse_rotated.html
我想在这些补丁的重叠区域(准多边形)的轮廓上添加线条,如上例所示。 如何在不解决方程的情况下实现这一目标?
答案 0 :(得分:2)
您可能会发现Coloring Intersection of Circles/Patches in Matplotlib有用。
它使用Shapely库创建所需的几何体,然后将其呈现为使用matplotlib显示。
要在Shapely中获得有角度的椭圆,您可以创建一个缓冲点(圆圈),然后缩放并旋转它。
修改:我无法安装Shapely(Anaconda 3.4 64bit + Windows 10 + Shapely == GRRRR
),所以这是未经测试的:
import numpy as np
import shapely.geometry as sg
import shapely.affinity as sa
import descartes
import matplotlib.pyplot as plt
from functools import reduce
def shapely_ellipse(center, major_axis, minor_axis, rotation=0.):
el = sg.Point(0., 0.).buffer(1.) # a unit circle
el = sa.scale(el, major_axis/2, minor_axis/2) # make it elliptic
el = sa.rotate(el, rotation)
el = sa.translate(el, *center)
return el
def intersect(a, b):
return a.intersection(b)
def main():
# make ellipses
delta = 45. # degrees
angles = np.arange(0., 360. + delta, delta)
ells = [shapely_ellipse((1,1), 4, 2, a) for a in angles]
# find intersection
center = reduce(intersect, ells)
# convert to matplotlib patches
center = descartes.PolygonPatch(center, ec='k', alpha=0.5)
# plot it
# ax = plt.subplot(111, aspect='equal')
ax = plt.gca()
for e in ells:
e = descartes.PolygonPatch(e)
e.set_alpha(0.1)
ax.add_artist(e)
ax.add_patch(center)
ax.set_xlim(-2, 4)
ax.set_ylim(-1, 3)
ax.set_aspect('equal')
plt.show()
if __name__ == "__main__":
main()
答案 1 :(得分:1)
仅使用matplotlib(及其依赖项,NumPy),
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.patches as patches
fig = plt.figure()
ax = plt.subplot(111, aspect='equal')
num_ellipses = 4
angles = np.linspace(0, 180, num_ellipses, endpoint=False)
ellipses = [patches.Ellipse((1, 1), 4, 2, a) for a in angles]
# The transform used for rendering the Ellipse as points depends on the
# axes. So you must add the Ellipses to an axes to fix its transform before
# calling any method that returns coordinates.
for e in ellipses:
e.set_alpha(0.1)
ax.add_artist(e)
# get the points on the ellipses in axes coordinates
axes_points = [e.get_verts() for e in ellipses]
# find which points are inside ALL the paths
all_axes_points = np.row_stack(axes_points)
# create the boolean mask using the points and paths in axes coordinates
in_all_ellipses = np.all(
[e.get_path().contains_points(all_axes_points, e.get_transform(), radius=0.0)
for e in ellipses], axis=0)
# find the points in data coordinates
transdata = ax.transData.inverted()
data_points = [transdata.transform(points) for points in axes_points]
all_data_points = np.row_stack(data_points)
intersection = all_data_points[in_all_ellipses]
# Finding the convex hull of `intersection` would be more robust, but adds another dependency
# import scipy.spatial as spatial
# import matplotlib.collections as mcoll
# hull = spatial.ConvexHull(intersection)
# # Draw a black outline around the intersection
# lc = mcoll.LineCollection(intersection[hull.simplices],
# colors='black', linewidth=2, zorder=5)
# ax.add_collection(lc)
# Instead, we can find the convex hull in this special case by ordering the points
# according to its angle away from (1,1)
idx = np.argsort(np.arctan2(intersection[:,1]-1, intersection[:,0]-1))
# use np.r_[idx, idx[0]] to append the first point to the end, thus connecting
# the outline
intersection = intersection[np.r_[idx, idx[0]]]
plt.plot(intersection[:, 0], intersection[:, 1], 'k', lw=2, zorder=5)
# Draw an outline around each ellipse just for fun.
for points in data_points:
plt.plot(points[:, 0], points[:, 1])
plt.xlim(-2, 4)
plt.ylim(-1, 3)
plt.show()
上面的主要思想是使用path.contains_points
方法来测试a
点在路径内。每个椭圆都有一个路径,每个椭圆都是
大致由点组成。如果我们收集所有这些点并测试它们
每个路径都有path.contains_points
,然后是包含的点
所有路径都在交叉路口。
请注意,如果放大整个区域的角落,您会看到一个
缺少一点交集。这归因于e.get_verts()
缺乏足够高的分辨率。我们可以通过使用NumPy来计算
椭圆上的点,但这可能违反了精神
"没有求解方程式"需求。
您可能想知道matplotlib 如何在高处绘制椭圆
分辨率但却无法访问高分辨率点本身。
"魔术"是在draw
方法中完成的,它使用了一些复杂的方法
用弧度逼近椭圆部分的算法。不幸的是,代码
这样做只会渲染弧线,它不会让你访问弧线或弧线中的点(如
我可以看到。)