import numpy as np
import matplotlib as mpl
mpl.use("TkAgg")
from matplotlib import pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import matplotlib.animation as animmation
r1 = 10 #地球环绕轨迹的半径
r2 = 1 #月球环绕轨迹的半径
omega1 = 2 * np.pi #地球运动的角速度
omega2 = 24 * np.pi #地球自转速度
phi = 5.1454 * np.pi / 180 #地球自转轴角
def update(data): #随时间t变换设置新的地球位置的坐标,也即是随animmation.FuncAnimation函数的帧数参数变化每一帧的不同坐标位置的图片对象参数
global line1, line2 , line3
line1.set_data([data[0], data[1]])
line1.set_3d_properties(data[2])
line2.set_data([data[3], data[4]])
line2.set_3d_properties(data[5])
line3.set_data([data[6], data[7]])
line3.set_3d_properties(data[8])
return line1,line2,line3,
def init(): #地球的起始位置
global line1, line2, line3
ti = 0
t = t_drange[np.mod(ti, t_dlen)]
xt1 = x0 + r1 * np.cos(omega1 * t)
yt1 = y0 + r1 * np.sin(omega1 * t)
zt1 = z0 + 0
xt2 = xt1 + r2 * np.sin(omega2 * t)
yt2 = yt1 + r2 * np.cos(omega2 * t)/(np.cos(phi) * (1 + np.tan(phi) ** 2))
zt2 = zt1 + (yt2 - yt1) * np.tan(phi)
xt21 = xt1 + r2 * np.sin(2 * np.pi * t_range)
yt21 = yt1 + r2 * np.cos(2 * np.pi * t_range)/(np.cos(phi) * (1 + np.tan(phi) ** 2))
zt21 = zt1 + (yt21 - yt1) * np.tan(phi)
line1, = ax.plot([xt1], [yt1], [zt1], marker='o', color='blue',markersize=8)
line2, = ax.plot([xt2], [yt2], [zt2], marker='o', color='orange',markersize=4)
line3, = ax.plot(xt21, yt21, zt21, color='purple')
return line1,line2,line3
def data_gen(): #随时间t变换的地球和月球坐标,也即是animmation.FuncAnimation函数的帧数参数
global x0,y0,z0,t_dlen
data = []
for ti in range(1,t_dlen):
t = t_drange[ti]
xt1 = x0 + r1 * np.cos(omega1 * t)
yt1 = y0 + r1 * np.sin(omega1 * t)
zt1 = z0
xt2 = xt1 + r2 * np.sin(omega2 * t)
yt2 = yt1 + r2 * np.cos(omega2 * t)/(np.cos(phi) * (1 + np.tan(phi) ** 2))
zt2 = zt1 + (yt2 - yt1) * np.tan(phi)
xt21 = xt1 + r2 * np.sin(2 * np.pi * t_range)
yt21 = yt1 + r2 * np.cos(2 * np.pi * t_range)/(np.cos(phi) * (1 + np.tan(phi) ** 2))
zt21 = zt1 + (yt21 - yt1) * np.tan(phi)
data.append([xt1, yt1, zt1, xt2, yt2, zt2, xt21, yt21, zt21])
return data
t_range = np.arange(0, 1 + 0.005, 0.005) #设置环绕一周时间的范围以及运动间隔时间
t_drange = np.arange(0, 1, 0.005 )
t_len = len(t_range)
t_dlen = len(t_drange)
#sun's coordination
x0 = 0
y0 = 0
z0 = 0
#地球轨道
x1 = x0 + r1 * np.cos(omega1 * t_range)
y1 = y0 + r1 * np.sin(omega1 * t_range)
z1 = z0 + np.zeros(t_len)
#月球轨道
x2 = x1 + r2 * np.sin(omega2 * t_range)
y2 = y1 + r2 * np.cos(omega2 * t_range)/(np.cos(phi) * (1 + np.tan(phi) ** 2))
z2 = z1 + (y2 - y1) * np.tan(phi)
f = plt.figure(figsize=(6,6)) #绘图的画布
ax = f.add_subplot(111,projection='3d') #设置3d坐标系
ax.set_title("Sun-Earth-Moon Model") #设置图像标题(太阳-地球-月亮转动模型)
ax.plot([0], [0], [0], marker='o', color= 'red', markersize=16) #绘制太阳的各种属性
ax.plot(x1, y1, z1, 'r') #绘制地球图像
ax.plot(x2, y2, z2, 'b') #绘制月球图像
ax.set_xlim([-(r1 + 2), (r1 + 2)]) #太阳用动模型在坐标系中的范围
ax.set_ylim([-(r1 + 2), (r1 + 2)]) #地球用动模型在坐标系中的范围
ax.set_zlim([-5, 5]) #月球用动模型在坐标系中的范围
#红色球体代表太阳,蓝色球体代表地球,橙色球体代表月亮
line1, = ax.plot([], [], [], marker='o', color='blue',markersize=8,animated = True)
line2, = ax.plot([], [], [], marker='o', color='orange',markersize=4,animated = True)
line3, = ax.plot([], [], [], color='purple',animated = True)
# 将上述函数对象传如animmation.FuncAnimation函数以生成连读的地球运动模型
ani = animmation.FuncAnimation(f, update, frames = data_gen(), init_func = init,interval = 20)
plt.show()