Лучший способ получить правильное соотношение сторон на 3D-графиках? - PullRequest
0 голосов
/ 21 февраля 2019

Прежде всего, полный отказ от ответственности, я новичок в python, и мой вопрос может быть глупым, но, поскольку мое исследование научило меня, кажется, что в matplotlib нет поддерживаемого способа сделать то, что я хочу.

Мне нужно построить траектории задачи трех тел, и я пытаюсь сделать это с помощью 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

, что даетрезультат такой:

Сюжет без каких-либо изменений

Это далеко не то, что мне нужно, поскольку ни одно из небесных тел не представлено в виде сфер.Я подумал, что соотношение сторон можно настроить так, чтобы оно соответствовало представленным данным, но ни один из поддерживаемых методов, которые я обнаружил, похоже, не справился с этим.Это следующие методы: ax.axis('equal'), ax.set_aspect('equal'), ax.axis('scaled'), ax.set_aspect('equal', adjustable='box'), ax.set_aspect('equal', adjustable='datalim').Ничто из этого не делает работу.

Первая ближайшая вещь, которую я нашел, это ответ , который в основном создает прямоугольник, так что все оси имеют одинаковые размеры.Это делает свое дело, но в моем случае одно из измерений намного больше, чем другие, и это приводит к большому потерянному пространству:

График с решением, которое создает коробку

Наконец, лучшее, что я смог найти, это решение в здесь , которое требует изменения файла 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]))

Результат это .Если вы посмотрите внимательно, график не центрируется, и в зависимости от ориентации не все данные находятся внутри области рисования.Пока я буду использовать этот последний метод, но после всех исследований, которые я провел, я все еще не могу поверить, что что-то подобное не поддерживается, как это должно быть с помощью инструмента черчения (что фантастично во всем остальном, насколько язнаю) и, таким образом, мой вопрос: я что-то упускаю очевидное?

Заранее спасибо:)

...