Matplotlib 3D绘图设置正确纵横比及后续异常问题求解
Matplotlib 3D绘图轴比例匹配实际数值及后续问题修复方案
基础比例匹配方案
原来的3D轴显示比例和实际数值不匹配,是因为默认ax.set_aspect('auto')不会按照轴数值范围自适应比例,Matplotlib 3.3及以上版本可以通过set_box_aspect方法解决,直接用三个轴的实际范围差值作为比例参数即可。
升级后三个问题的对应解决方案
- 问题1:x/y/z轴标签严重重叠
手动调整标签边距、减少刻度密度、旋转刻度标签即可解决,无需依赖自动调整逻辑。 - 问题2:图形大幅缩小、窗口放大时坐标轴不同步、和中心图形重叠
初始化画布时就按照容器的长宽比例设置画布尺寸,同时调整子图边距给标签预留足够空间即可。 - 问题3:
RuntimeWarning: divide by zero encountered in double_scalars和numpy.linalg.LinAlgError: Singular matrix报错
该报错是因为调用set_box_aspect的时机不对,或者轴范围差值出现了0值,需要保证先设置xlim/ylim/zlim再调用比例设置,同时给范围差值加最小值保护即可消除报错。
整合后完整的绘图段代码
将你原代码中if len(colors) > 0:的部分替换为以下代码即可解决所有问题:
if len(colors) > 0: # 初始化画布时适配长条形容器的比例,避免图形被压缩 fig = plt.figure(figsize=(12, 6)) fig.canvas.set_window_title(b.string().split("(")[0]) ax = fig.gca(projection='3d') pc = plotCubeAt2(positions, sizes, colors=colors, edgecolor="k") ax.add_collection3d(pc) # 先设置三个轴的数值范围 x_max = float(b.string().split(",")[0].split("(")[1].split("x")[0]) y_max = float(b.string().split(",")[0].split("(")[1].split("x")[1]) z_max = float(b.string().split(",")[0].split("(")[1].split("x")[2]) ax.set_xlim([0, x_max]) ax.set_ylim([0, y_max]) ax.set_zlim([0, z_max]) # 再设置轴比例,加最小值保护避免除零报错 x_range = max(x_max, 1e-6) y_range = max(y_max, 1e-6) z_range = max(z_max, 1e-6) ax.set_box_aspect([x_range, y_range, z_range]) # 调整标签和刻度,避免重叠 ax.xaxis.labelpad = 20 ax.yaxis.labelpad = 20 ax.zaxis.labelpad = 20 ax.locator_params(axis='x', nbins=6) ax.locator_params(axis='y', nbins=4) ax.locator_params(axis='z', nbins=4) ax.tick_params(axis='x', labelrotation=45) ax.tick_params(axis='y', labelrotation=-45) # 调整子图边距,预留标签空间 plt.subplots_adjust(left=0.15, right=0.85, bottom=0.15, top=0.85)
内容的提问来源于stack exchange,提问作者Jack
相关产品推荐
相关产品推荐

