【问题标题】:Setting aspect ratio of 3D plot设置 3D 绘图的纵横比
【发布时间】:2012-05-06 18:28:20
【问题描述】:

我正在尝试根据声纳在 500m x 40m 海底部分上运行的数据绘制海底的 3D 图像。我将 matplotlib/mplot3d 与 Axes3D 一起使用,我希望能够更改轴的纵横比,以便 x 和 y 轴按比例缩放。包含生成数据而不是真实数据的示例脚本是:

import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

# Create figure.
fig = plt.figure()
ax = fig.gca(projection = '3d')

# Generate example data.
R, Y = np.meshgrid(np.arange(0, 500, 0.5), np.arange(0, 40, 0.5))
z = 0.1 * np.abs(np.sin(R/40) * np.sin(Y/6))

# Plot the data.
surf = ax.plot_surface(R, Y, z, cmap=cm.jet, linewidth=0)
fig.colorbar(surf)

# Set viewpoint.
ax.azim = -160
ax.elev = 30

# Label axes.
ax.set_xlabel('Along track (m)')
ax.set_ylabel('Range (m)')
ax.set_zlabel('Height (m)')

# Save image.
fig.savefig('data.png')

以及此脚本的输出图像:

现在我想更改它,以便沿轨道 (x) 轴上的 1 米与范围 (y) 轴上的 1 米相同(或者可能是不同的比率,具体取决于所涉及的相对尺寸)。我还想设置 z 轴的比率,由于数据中的相对大小,再次不一定要设置为 1:1,但是轴比当前绘图要小。

我已经尝试构建和使用this branch of matplotlib,按照this message from the mailing list 中的示例脚本,但将ax.pbaspect = [1.0, 1.0, 0.25] 行添加到我的脚本中(已卸载matplotlib 的“标准”版本以确保正在使用自定义版本) 对生成的图像没有任何影响。

编辑:因此所需的输出将类似于以下(使用 Inkscape 粗略编辑)图像。在这种情况下,我没有在 x/y 轴上设置 1:1 的比例,因为它看起来非常薄,但我已经将它展开,所以它不像原始输出那样是方形的。

【问题讨论】:

标签: python matplotlib mplot3d


【解决方案1】:

在savefig前添加如下代码:

ax.auto_scale_xyz([0, 500], [0, 500], [0, 0.15])

如果你不想要方轴:

编辑 site-packages\mpl_toolkits\mplot3d\axes3d.py 中的 get_proj 函数:

xmin, xmax = np.divide(self.get_xlim3d(), self.pbaspect[0])
ymin, ymax = np.divide(self.get_ylim3d(), self.pbaspect[1])
zmin, zmax = np.divide(self.get_zlim3d(), self.pbaspect[2])

然后添加一行设置pbaspect:

ax = fig.gca(projection = '3d')
ax.pbaspect = [2.0, 0.6, 0.25]

【讨论】:

  • 嗯。这确实使轴的缩放正确,但会导致大量空间浪费。虽然我可以将其保存为 SVG 并手动编辑(就像我对刚刚更新问题的所需图像所做的那样),但当我要创建大量图像时,这会变得非常乏味,而且我不确定它是否可以自动化......
  • 您可以使用 pbaspect 修改来获得无方轴。我已经编辑了答案。
  • 我认为这是一个非常有用的技巧。请注意,它位于get_proj 函数中,必须修改此值。另请注意,按照此处显示的方式对其进行修改后,您必须提供pbaspect 值。可以通过添加try: self.localPbAspect=self.pbaspect except AttributeError: self.localPbAspect=[1,1,1] 之类的内容并除以self.localPbAspect[...] 或类似的内容来避免这种情况……因为您可能并不总是希望手动设置pbaspect
【解决方案2】:

this question 的答案非常适合我。而且您不需要设置任何比率,它会自动完成所有操作。

【讨论】:

    【解决方案3】:

    一个问题已在 github 上打开:https://github.com/matplotlib/matplotlib/issues/8593

    上述解决方案似乎不再起作用。现在必须通过以下方式编辑site-packages\mpl_toolkits\mplot3d\axes3d.py 中的get_proj 函数:

            try:
                self.localPbAspect = self.pbaspect
            except AttributeError:
                self.localPbAspect = [1,1,1]
    
            xmin, xmax = ( lim / self.localPbAspect[0] for lim in self.get_xlim3d() )
            ymin, ymax = ( lim / self.localPbAspect[1] for lim in self.get_ylim3d() )
            zmin, zmax = ( lim / self.localPbAspect[2] for lim in self.get_zlim3d() )
    

    【讨论】:

      【解决方案4】:

      我是如何解决空间浪费问题的:

      try: 
          self.localPbAspect=self.pbaspect
          zoom_out = (self.localPbAspect[0]+self.localPbAspect[1]+self.localPbAspect[2]) 
      except AttributeError: 
          self.localPbAspect=[1,1,1]
          zoom_out = 0 
      xmin, xmax = self.get_xlim3d() /  self.localPbAspect[0]
      ymin, ymax = self.get_ylim3d() /  self.localPbAspect[1]
      zmin, zmax = self.get_zlim3d() /  self.localPbAspect[2]
      
      # transform to uniform world coordinates 0-1.0,0-1.0,0-1.0
      worldM = proj3d.world_transformation(xmin, xmax,
                                               ymin, ymax,
                                               zmin, zmax)
      
      # look into the middle of the new coordinates
      R = np.array([0.5*self.localPbAspect[0], 0.5*self.localPbAspect[1], 0.5*self.localPbAspect[2]])
      xp = R[0] + np.cos(razim) * np.cos(relev) * (self.dist+zoom_out)
      yp = R[1] + np.sin(razim) * np.cos(relev) * (self.dist+zoom_out)
      zp = R[2] + np.sin(relev) * (self.dist+zoom_out)
      E = np.array((xp, yp, zp))
      

      【讨论】:

        猜你喜欢
        • 2011-12-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多