【问题标题】:How to add axis lines to ellipse using python matplotlib.patches.ellipse?如何使用 python matplotlib.patches.ellipse 将轴线添加到椭圆?
【发布时间】:2023-01-20 19:46:24
【问题描述】:

我有这个生成椭圆的简单代码

import matplotlib.patches as patches
import matplotlib.pyplot as plt

fig, ax = plt.subplots(subplot_kw={'aspect': 'equal'})

ellipse = patches.Ellipse((0, 0), 4, 2, angle=45, fill=False)
ax.add_artist(ellipse)

ax.set_xlim(-2.2, 2.2)
ax.set_ylim(-2.2, 2.2)

plt.show()

这是当前输出: ellipse

我需要添加椭圆轴,所以它看起来像这样: ellipse_output

有没有办法做到这一点? 我需要一种通用的方法来使用更复杂的椭圆,谢谢。

我试图在 patches.Ellipse() 中搜索参数来绘制那些轴线,但没有找到任何东西。

【问题讨论】:

  • 首先,第二张图片中轴的绘制非常出色。
  • 好的,你能帮忙吗? :'D
  • 已经发布了一个相对快速的解决方案。

标签: python matplotlib ellipse


【解决方案1】:

您可以添加椭圆的长轴和短轴。

在我展示的代码中,我做了长轴,但你需要处理角度部分(基于椭圆的点),而我只是将它设置为 45 度以发布快速答案。

这样的结果将给出完整的解决方案。

所以,我做这样的事情:

import matplotlib.patches as patches
import matplotlib.pyplot as plt
import numpy as np

fig, ax = plt.subplots(subplot_kw={'aspect': 'equal'})
#################################
# you need to figure this bit out
#################################

ellipse = patches.Ellipse((0, 0), 4, 2, angle=45, fill=False)
ax.add_artist(ellipse)

ellipse.set_clip_box(ax.bbox)
ellipse.set_alpha(0.1)
ax.annotate("",
            xy=(ellipse.center[0], ellipse.center[1] - ellipse.height / 2),
            xytext=(ellipse.center[0], ellipse.center[1] + ellipse.height / 2),
            arrowprops=dict(arrowstyle="<->", color="black"))
ax.annotate("",
            xy=(ellipse.center[0] - ellipse.width / 2, ellipse.center[1]),
            xytext=(ellipse.center[0] + ellipse.width / 2, ellipse.center[1]),
            arrowprops=dict(arrowstyle="<->", color="black"))
ax.annotate("",
            xy=(ellipse.center[0] - ellipse.width / 2 * np.cos(np.deg2rad(ellipse.angle)), 
                ellipse.center[1] - ellipse.height / 2 * np.sin(np.deg2rad(ellipse.angle))),
            xytext=(ellipse.center[0] + ellipse.width / 2 * np.cos(np.deg2rad(ellipse.angle)), 
                    ellipse.center[1] + ellipse.height / 2 * np.sin(np.deg2rad(ellipse.angle))),
            arrowprops=dict(arrowstyle="<->", color="black"))

ax.set_xlim(-2.2, 2.2)
ax.set_ylim(-2.2, 2.2)

plt.show()


这给你留下了这样的情节:

基本上,总而言之,注释行可让您完成所需的最后几步。

编辑: 我能够减少到这个:

import matplotlib.patches as patches
import matplotlib.pyplot as plt

fig, ax = plt.subplots(subplot_kw={'aspect': 'equal'})

# patches.Ellipse(center, width, height, angle)
ellipse = patches.Ellipse((0, 0), 4, 2, angle=45, fill=False)
ax.add_artist(ellipse)

ellipse.set_clip_box(ax.bbox)

ax.annotate("",
            xy=(ellipse.center[0] - ellipse.width+2 , 
                ellipse.center[1] - ellipse.height ),
            xytext=(ellipse.center[0] + ellipse.width-1, 
                    ellipse.center[1] + ellipse.height+1),
            arrowprops=dict(arrowstyle="<->", color="red"))
ax.set_xlim(-2.2, 2.2;)
ax.set_ylim(-2.2, 2.2)


plt.show()

看起来像这样:

【讨论】:

  • 谢谢,但我一直在寻找更简单、更易读的东西,像 ellipse.plot_axis() 这样简单的东西(我知道那不存在,但想知道是否有更直接的方法)
  • 您可以删除前 2 个ax.annotate,它们只是垂直线和水平线....
【解决方案2】:
from math import sin, cos, radians
import matplotlib.patches as patches
import matplotlib.pyplot as plt

fig, ax = plt.subplots(subplot_kw={'aspect': 'equal'})

##############
ellipse_size = (4,2)
ellipse_rotation = 45
ellipse_position = (0,0)

ellipse = patches.Ellipse(ellipse_position, ellipse_size[0], ellipse_size[1], angle=ellipse_rotation, fill=False)
ax.add_artist(ellipse)

ax.set_xlim(-2.2, 2.2)
ax.set_ylim(-2.2, 2.2)

# math for the start and end axis point positions
ax1_points = [
    (ellipse_position[0]+ellipse_size[0]/2*cos(radians(ellipse_rotation)), 
    ellipse_position[1]+ellipse_size[0]/2*sin(radians(ellipse_rotation))),
    (ellipse_position[0]+ellipse_size[0]/2*cos(radians(ellipse_rotation + 180)), 
    ellipse_position[1]+ellipse_size[0]/2*sin(radians(ellipse_rotation + 180)))
    ]
ax2_points = [
    (ellipse_position[0]+ellipse_size[1]/2*cos(radians(ellipse_rotation+90)), 
    ellipse_position[1]+ellipse_size[1]/2*sin(radians(ellipse_rotation+90))),
    (ellipse_position[0]+ellipse_size[1]/2*cos(radians(ellipse_rotation + 270)), 
    ellipse_position[1]+ellipse_size[1]/2*sin(radians(ellipse_rotation + 270)))]

# ax1 and ax2 contains the start and the end point of the axis ([x,y] format)

# drawing the arrows
arrowprops=dict(arrowstyle="<->", color="red")
ax.annotate("", xy=ax1_points[0], xytext=ax1_points[1], arrowprops=arrowprops)
ax.annotate("", xy=ax2_points[0], xytext=ax2_points[1], arrowprops=arrowprops)
plt.show()

产生这个:

希望这可以帮助。

【讨论】:

  • 我喜欢这段代码,它改进了我的代码。我修改了结尾部分,使 ax1_pointsax1_points 不会太长(并添加了图片)。干得好。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多