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