如何获取Matplotlib中旋转矩形Patch的坐标与所有顶点?
解决你的Matplotlib旋转Patch问题
首先咱们先搞清楚核心问题:为什么旋转后的r2和r1的get_bbox()、get_xy()结果一致?因为Matplotlib里,Patch的原始属性(比如起始坐标、边界框)存储的是未应用变换的原始数据,你设置的trafo只是在绘制阶段对Patch做视觉变换,并没有修改Patch本身的底层坐标。要拿到旋转后的实际坐标,得手动用变换矩阵去转换原始点。
下面一步步解决你的需求和疑问:
1. 获取旋转后Patch的坐标
你可以用定义好的trafo变换对象,把原始坐标点转换为旋转后的实际坐标。比如:
- 旋转后的起始点:用
trafo.transform(r2.get_xy())直接转换原始起始点 - 旋转后的边界框:先提取原始边界框的关键点位,再逐个应用变换
2. 获取旋转后矩形的所有顶点
先根据矩形的原始起始点、宽度、高度算出四个顶点的原始坐标,再用变换矩阵转换每个点,就能得到旋转后的顶点坐标。
3. 关于旋转后矩形边角的疑问
这不是单纯的视觉效果!默认情况下Matplotlib的坐标轴比例不是等比例的(x轴和y轴的单位长度在屏幕上显示不一致),所以旋转后的矩形看起来边角不是90度。只需要加上ax.set_aspect('equal'),让坐标轴比例一致,就能看到标准的旋转矩形了。
修改后的完整代码示例
import numpy as np import matplotlib.pyplot as plt import matplotlib.patches as patches import matplotlib as mpl from matplotlib.transforms import Affine2D fig = plt.figure() ax = fig.add_subplot(111) angle = np.deg2rad(45) # 原始矩形 r1 = patches.Rectangle((8,4), 5,3, fill=False, color="red", alpha=0.50) # 待旋转的矩形 r2 = patches.Rectangle((8,4), 5,3, fill=False, color="blue", alpha=0.50) # 定义旋转变换:围绕(8,4)旋转45度,叠加轴的坐标变换 trafo = mpl.transforms.Affine2D().rotate_around(8,4,angle) + ax.transData r2.set_transform(trafo) ax.add_patch(r1) ax.add_patch(r2) # 设置坐标轴等比例,解决旋转后矩形边角视觉变形问题 ax.set_aspect('equal') plt.xlim(0,15) plt.ylim(0,15) plt.grid(False) plt.show() # ---------------------- 获取旋转后的坐标和顶点 ---------------------- # 1. 获取旋转后的起始坐标 original_xy = r2.get_xy() rotated_xy = trafo.transform(original_xy) print(f"原始起始坐标: {original_xy}") print(f"旋转后起始坐标: {rotated_xy}") # 2. 获取旋转后的所有顶点 x0, y0 = r2.get_xy() w, h = r2.get_width(), r2.get_height() # 原始矩形的四个顶点:左下、右下、右上、左上 original_vertices = np.array([ [x0, y0], [x0 + w, y0], [x0 + w, y0 + h], [x0, y0 + h] ]) # 对所有顶点应用旋转变换 rotated_vertices = trafo.transform(original_vertices) print("\n旋转后矩形的所有顶点坐标:") for idx, vertex in enumerate(rotated_vertices): print(f"顶点{idx+1}: {vertex.round(2)}") # 3. 获取旋转后的边界框(通过顶点的极值计算) rotated_bbox = np.array([ [rotated_vertices[:,0].min(), rotated_vertices[:,1].min()], [rotated_vertices[:,0].max(), rotated_vertices[:,1].max()] ]) print("\n旋转后的边界框(左下、右上):") print(rotated_bbox.round(2))
关键说明
trafo.transform()是核心:它能把原始坐标转换为经过旋转和轴映射后的实际显示坐标ax.set_aspect('equal')让x、y轴单位长度一致,旋转后的矩形边角会显示为标准90度- 原始顶点的计算基于矩形的基础属性,变换后就能得到旋转后的准确顶点位置
内容的提问来源于stack exchange,提问作者beginh
相关产品推荐
相关产品推荐

