You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现Matplotlib 3D绘图的坐标轴等比例显示

How to Maintain Equal Axis Scaling in Matplotlib 3D Plots

First, let's spot a critical issue in your code: your zlim setting doesn't match your data. Looking at your vertices, the z-values range from ~1681 up to 22508, but you've set ax.set_zlim(1000., 2500.)—this truncates most of your triangle, which is already contributing to the distorted appearance. Let's fix that first, then address the equal scaling problem.

Matplotlib's 3D axes don't support plt.axis('equal') (as you've seen from the error), but there are reliable workarounds:

Method 1: Use set_box_aspect() (Matplotlib 3.3+)

This is the simplest approach for newer Matplotlib versions. You calculate the range of each axis, then set the box aspect ratio to match those ranges (so each unit of length is visually consistent across axes).

Here's your corrected code with this method:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d.art3d import Poly3DCollection

vertices = np.array([
 [ 2.5800e+06, 1.1090e+06, 1.6817e+03],
 [ 2.5300e+06, 1.1370e+06, 1.0996e+04],
 [ 2.5300e+06, 1.1350e+06, 2.2508e+04]])

fig = plt.figure(figsize=(4,4))
ax = fig.add_subplot(111, projection='3d')

# Calculate axis ranges from your data
x_range = np.max(vertices[:,0]) - np.min(vertices[:,0])
y_range = np.max(vertices[:,1]) - np.min(vertices[:,1])
z_range = np.max(vertices[:,2]) - np.min(vertices[:,2])

# Set equal aspect ratio based on actual data ranges
ax.set_box_aspect([x_range, y_range, z_range])

# Set axis limits to fully contain your data (fixed the zlim issue)
ax.set_xlim(np.min(vertices[:,0]), np.max(vertices[:,0]))
ax.set_ylim(np.min(vertices[:,1]), np.max(vertices[:,1]))
ax.set_zlim(np.min(vertices[:,2]), np.max(vertices[:,2]))

# Add the triangle once (no need for a loop here)
ax.add_collection3d(Poly3DCollection([vertices], facecolor='lightblue', edgecolor='black'))

plt.show()

Method 2: Manual Aspect Adjustment (Older Matplotlib Versions)

If you're using a version before 3.3, you can manually adjust the axis scaling by normalizing all axes to the largest range in your data:

# After setting your initial axis limits
x_lim = ax.get_xlim()
y_lim = ax.get_ylim()
z_lim = ax.get_zlim()

x_range = x_lim[1] - x_lim[0]
y_range = y_lim[1] - y_lim[0]
z_range = z_lim[1] - z_lim[0]

# Find the maximum range to normalize against
max_range = np.max([x_range, y_range, z_range])

# Adjust each axis to span the same total length for consistent scaling
ax.set_xlim(x_lim[0], x_lim[0] + max_range)
ax.set_ylim(y_lim[0], y_lim[0] + max_range)
ax.set_zlim(z_lim[0], z_lim[0] + max_range)

This forces all axes to have the same visual span, making units of length look equal across x, y, and z.

A quick side note: your original loop adding the same Poly3DCollection four times is unnecessary—adding it once is enough to display the triangle correctly.

内容的提问来源于stack exchange,提问作者swiss_knight

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 20:57:43