在3D图中获得正确的纵横比的正确方法?

时间:2019-02-21 17:05:58

标签: python matplotlib plot aspect-ratio mplot3d

首先完全免责声明,我是python的新手,我的问题可能很愚蠢,但据我的研究告诉我,matplotlib中似乎没有支持的方法可以完成我想要的事情。 / p>

我必须绘制“三体问题”的轨迹,并且尝试使用python来减少对Matlab的依赖(这是他们在我的大学所教的)。在这些图中,地球和月球都出现了,对我来说重要的是它们看起来是球形的。下面的代码给出了我必须绘制的那种东西的基本示例:

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D, proj3d # Needed to 3Dplots
plt.close('all') # Close plots of previous scripts

#Data
Er = 0.0166         # Earth radius
Mr = 0.0045         # Moon radius
mu = 0.01215        # Mass parameter
#
def plotCC(ax,rad,pos): # Plot celestial bodies
     u = np.linspace(0, 2 * np.pi, 53)
     v = np.linspace(0, np.pi, 53)
     x = pos +  rad * np.outer(np.cos(u), np.sin(v))
     y = rad * np.outer(np.sin(u), np.sin(v))
     z = rad * np.outer(np.ones(np.size(u)), np.cos(v))
     ax.plot_surface(x, y, z)

# Dummy Halo orbit    
u   = np.linspace(0, 2 * np.pi, 30)
xh  = (1-mu)*np.ones(len(u))
yh  = 20*Mr*np.sin(u)
zh  = 0.12 + 30*Mr*np.cos(u)

# Dummy trajectory
xt  = np.linspace(1-mu,-mu,20)
yt  = (xt-(1-mu))*(xt+mu)*-1.2
zt  = (xt-(1-mu))*(xt+mu)*-0.8

使用以下命令可以绘制所需的所有内容:

# Plots
fig     = plt.figure(figsize=(8,8))
ax      = fig.gca(projection='3d',proj_type = 'ortho')
ax.plot(xh,yh,zh, lw=1.2)   # Plot Halo orbit
ax.plot(xt,yt,zt, lw=1.2)   # Plot trajectory
plotCC(ax,Mr,1-mu)          # Plot Moon
plotCC(ax,Er,-mu)           # Plot Earth

因此给出以下内容:

Plot without any changes

这远不是我所需要的,因为没有一个天体被表示为球体。我以为可以将长宽比配置为匹配所表示数据的长宽比,但是我发现没有一种受支持的方法可以做到这一点。这些方法是:ax.axis('equal')ax.set_aspect('equal')ax.axis('scaled')ax.set_aspect('equal', adjustable='box')ax.set_aspect('equal', adjustable='datalim')。这些都不起作用。

我发现的第一个最接近的东西是这个answer,它基本上会创建一个盒子,以便所有轴的尺寸都相同。这可以解决问题,但是在我的情况下,其中一个维度比其他维度大得多,这会导致大量的空间浪费:

Plot with the solution that creates a box

最后,我能找到的最好的东西是here中的解决方案,它需要修改文件axes.py,以便get_proj()接受您赋予它的宽高比:

ay = (ax.get_ylim3d()[1]-ax.get_ylim3d()[0])/(ax.get_xlim3d()[1]-ax.get_xlim3d()[0])
az = (ax.get_zlim3d()[1]-ax.get_zlim3d()[0])/(ax.get_xlim3d()[1]-ax.get_xlim3d()[0])
ax.pbaspect = list(1.8*np.array([1,ay,az]))

结果为this。如果仔细观察,图不会居中,并且根据方向,并非所有数据都在绘图区域内。现在,我将使用最后一种方法,但是在完成所有研究之后,我仍然无法相信绘图工具不应该支持像这样的东西(就我而言,这在其他所有方面都很棒)知道),因此我的问题是:我是否遗漏了明显的东西?

预先感谢:)

0 个答案:

没有答案