绘制椭圆时为何需重复设置'aspect equal'?
问题分析与解决
你遇到的核心问题是:仅设置ax.set_aspect('equal')时,Matplotlib默认不会自动调整坐标轴范围来包含你添加的椭圆patch,导致椭圆不在可视区域内,所以只显示空白坐标轴。
具体原因
ax.set_aspect('equal')的作用是强制坐标轴纵横比为1(避免椭圆被拉伸变形),但它不会修改坐标轴的默认范围(通常是x∈[0,1]、y∈[0,1])。- 你的椭圆中心和长/短轴计算结果超出了这个默认范围,因此椭圆不在当前可视区域内。
- 而
plt.axis('equal')(等价于面向对象风格的ax.axis('equal'))不仅会设置等纵横比,还会自动调整坐标轴范围,让所有绘制元素(包括你添加的Ellipse patch)都被包含在可视区域中。
解决方案
不需要同时用两种方式设置等纵横比,选以下任意一种方法即可:
方法1:使用面向对象风格的ax.axis('equal')
替换plt.axis('equal')为ax.axis('equal'),保持代码风格统一:
# Imports import numpy as np sqrt = np.sqrt atan = np.arctan degrees = np.degrees import matplotlib.pyplot as plt from matplotlib.patches import Ellipse # Ellipse general equation's coefficients A = 1 ; B = -1.25 ; C = 1.625 ; D = 1.875 ; E = 1.5 ; F = -2 # Previous personal calculations det_M2 = (4*A*C - B**2) / 4 det_M3 = (B*D*E - (A*(E**2) + C*(D**2)) - (B**2 - 4*A*C)*F) / 4 xc = (B*E - 2*C*D) / (4*det_M2) yc = (B*D - 2*A*E) / (4*det_M2) center = [xc, yc] theta = atan(B/(A-C)) / 2 lambda_plus = (A+C)/2 + sqrt(((A+C)/2)**2 - det_M2) lambda_minus = (A+C)/2 - sqrt(((A+C)/2)**2 - det_M2) a = sqrt(2)/2 * sqrt(-lambda_plus * det_M3) / det_M2 b = sqrt(2)/2 * sqrt(-lambda_minus * det_M3) / det_M2 # Plot ellipse = Ellipse(xy=center, width=2 * a, height=2 * b, angle=degrees(theta), edgecolor='red', linestyle='-', linewidth=2, fill=False) fig, ax = plt.subplots(figsize=(8, 4)) ax.set_aspect('equal', adjustable='box') ax.add_patch(ellipse) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_title('Ellipse') ax.legend() ax.grid(False) ax.axis('equal') # 替换为ax的方法 plt.show()
方法2:调用自动缩放让坐标轴适配椭圆
去掉plt.axis('equal'),添加ax.autoscale()让坐标轴自动包含椭圆:
# ... 前面的导入和计算代码不变 ... fig, ax = plt.subplots(figsize=(8, 4)) ax.set_aspect('equal', adjustable='box') ax.add_patch(ellipse) ax.autoscale() # 自动调整坐标轴范围以包含椭圆 ax.set_xlabel('x') ax.set_ylabel('y') ax.set_title('Ellipse') ax.legend() ax.grid(False) plt.show()
方法3:手动设置坐标轴范围
如果你清楚椭圆的大致范围,可以手动设置x、y轴范围,确保椭圆被包含在内:
# ... 前面的导入和计算代码不变 ... fig, ax = plt.subplots(figsize=(8, 4)) ax.set_aspect('equal', adjustable='box') ax.add_patch(ellipse) ax.set_xlabel('x') ax.set_ylabel('y') ax.set_title('Ellipse') ax.legend() ax.grid(False) # 根据椭圆参数手动设置范围,数值可按需调整 ax.set_xlim(xc - a - 1, xc + a + 1) ax.set_ylim(yc - b - 1, yc + b + 1) plt.show()
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

