Matplotlib:解决坐标轴缩放不同时旋转Patch变形问题
解决坐标轴缩放不同时旋转Patch保持屏幕矩形的问题
当坐标轴x、y缩放比例不同时,直接基于ax.transData旋转Patch会导致形状变形——这是因为旋转是在数据坐标系下执行的,会受坐标轴缩放差异影响。要让旋转后的Patch在屏幕上保持矩形,需要在各向同性的空间中完成旋转操作,具体实现步骤如下:
- 计算坐标轴缩放补偿因子:通过数据范围与坐标轴显示区域的尺寸,算出x、y方向单位数据对应的屏幕长度比例,得到y轴的补偿缩放系数,消除坐标轴的缩放差异。
- 构建复合变换链:先将数据坐标转换为补偿后的各向同性空间,执行旋转,再转换回原数据坐标系。
修改后的代码如下:
import matplotlib.pyplot as plt import matplotlib.patches as patches import matplotlib as mpl fig = plt.figure() ax = fig.add_subplot(111) r1 = patches.Rectangle((0,0), 20, 200, color="blue", alpha=0.50) r2 = patches.Rectangle((0,0), 20, 200, color="red", alpha=0.50) # 计算坐标轴的缩放补偿因子,让y轴单位数据的屏幕长度与x轴一致 x_range = ax.get_xlim()[1] - ax.get_xlim()[0] y_range = ax.get_ylim()[1] - ax.get_ylim()[0] bbox = ax.get_window_extent() ax_width, ax_height = bbox.width, bbox.height y_scale = (x_range / ax_width) / (y_range / ax_height) # 构建复合变换:数据坐标 → 补偿y缩放 → 旋转 → 还原y缩放 → 数据坐标 transform = ( ax.transData.inverted() + mpl.transforms.Affine2D().scale(1, y_scale) + mpl.transforms.Affine2D().rotate_deg(-45) + mpl.transforms.Affine2D().scale(1, 1/y_scale) + ax.transData ) r2.set_transform(transform) ax.add_patch(r1) ax.add_patch(r2) plt.xlim(-20, 60) plt.ylim(-100, 300) plt.grid(True) plt.show()
关键说明
ax.get_window_extent()用于获取坐标轴的显示区域像素尺寸,结合数据范围计算出x、y方向的缩放差异,得到的y_scale可以将数据空间转换为各向同性的等价空间。- 复合变换的逻辑是先消除坐标轴的缩放差异,在均匀空间中完成旋转,再还原缩放回到原数据坐标系,这样旋转操作就不会导致Patch在屏幕上变形,始终保持矩形形状。
内容的提问来源于stack exchange,提问作者snakeslayer09
相关产品推荐
相关产品推荐

