提交 d40907cc 编写于 作者: M march3

三体运行模拟器

上级 6644389e
......@@ -9,3 +9,4 @@ from bodies.pluto import Pluto
from bodies.saturn import Saturn
from bodies.uranus import Uranus
from bodies.venus import Venus
from bodies.moon import Moon
......@@ -6,13 +6,14 @@
# notes :
# python_version :3.8
# ==============================================================================
from abc import ABCMeta, abstractmethod
import json
import numpy as np
import math
from common.consts import AU
class Body:
class Body(metaclass=ABCMeta):
def __init__(self, name, mass, init_position, init_velocity,
density=5e3, color=(125 / 255, 125 / 255, 125 / 255),
texture=None, size_scale=1.0, distance_scale=1.0):
......@@ -158,7 +159,8 @@ class Body:
"""
# v = m/ρ
# 体积(m³) = 质量(kg) / 密度(kg/m³)
v = self.mass / self.density
# 体积(km³) = 体积(m³) / 1e9
v = self.mass / self.density / 1e9
return v
@property
......
# -*- coding:utf-8 -*-
# title :
# description :
# author :Python超人
# date :2023-01-22
# notes :
# python_version :3.8
# ==============================================================================
from bodies.body import Body, AU
class Moon(Body):
"""
月球
------------------------
距地距离约 363104 至 405696 km
 逃逸速度: 2.4 km/s
 公转速度: 1.023 km/s + (地球)29.79 km/s
 天体质量: 7.342✕10²² kg
 平均密度: 3.344 g/cm³ -> 3.344✕10³ kg/m³
"""
# 质 量约 [1] 平均密度约 3.344 g/cm³ [1] 质 量约 7.342✕1022 kg [1]
def __init__(self, name="Moon", mass=7.342e22,
init_position=[363104 + 1.12 * AU, 0, 0],
init_velocity=[0, 29.79 + 1.023, 0],
texture="moon.jpg", size_scale=1.0, distance_scale=1.0):
params = {
"name": name,
"mass": mass,
"init_position": init_position,
"init_velocity": init_velocity,
"density": 3.344e3,
"color": (162, 162, 162),
"texture": texture,
"size_scale": size_scale,
"distance_scale": distance_scale
}
super().__init__(**params)
if __name__ == '__main__':
earth = Earth()
print(earth)
# -*- coding:utf-8 -*-
# title :
# description :
# author :Python超人
# date :2023-01-22
# notes :
# python_version :3.8
# ==============================================================================
import numpy as np
import math
class MechanicalCalculator:
"""
力学计算器:
牛顿引力常数就有万有引力常数:G=6.67x10^-11 (N·m^2 /kg^2)
计算万有引力时会用到
万有引力公式:F=G*m1*m2/r*
"""
@staticmethod
def getAcc(pos, mass, G, softening):
"""
Calculate the acceleration on each particle due to Newton's Law
pos is an N x 3 matrix of positions
mass is an N x 1 vector of masses
G is Newton's Gravitational constant
softening is the softening length
a is N x 3 matrix of accelerations
"""
# positions r = [x,y,z] for all particles
x = pos[:, 0:1]
y = pos[:, 1:2]
z = pos[:, 2:3]
# matrix that stores all pairwise particle separations: r_j - r_i
dx = x.T - x
dy = y.T - y
dz = z.T - z
# matrix that stores 1/r^3 for all particle pairwise particle separations
inv_r3 = (dx ** 2 + dy ** 2 + dz ** 2 + softening ** 2)
inv_r3[inv_r3 > 0] = inv_r3[inv_r3 > 0] ** (-1.5)
ax = G * (dx * inv_r3) @ mass
ay = G * (dy * inv_r3) @ mass
az = G * (dz * inv_r3) @ mass
# pack together the acceleration components
a = np.hstack((ax, ay, az))
return a
@staticmethod
def getEnergy(pos, vel, mass, G):
"""
Get kinetic energy (KE) and potential energy (PE) of simulation
pos is N x 3 matrix of positions
vel is N x 3 matrix of velocities
mass is an N x 1 vector of masses
G is Newton's Gravitational constant
KE is the kinetic energy of the system
PE is the potential energy of the system
"""
# Kinetic Energy:
KE = 0.5 * np.sum(np.sum(mass * vel ** 2))
# Potential Energy:
# positions r = [x,y,z] for all particles
x = pos[:, 0:1]
y = pos[:, 1:2]
z = pos[:, 2:3]
# matrix that stores all pairwise particle separations: r_j - r_i
dx = x.T - x
dy = y.T - y
dz = z.T - z
# matrix that stores 1/r for all particle pairwise particle separations
inv_r = np.sqrt(dx ** 2 + dy ** 2 + dz ** 2)
inv_r[inv_r > 0] = 1.0 / inv_r[inv_r > 0]
# sum over upper triangle, to count each interaction only once
PE = G * np.sum(np.sum(np.triu(-(mass * mass.T) * inv_r, 1)))
return KE, PE;
......@@ -6,9 +6,6 @@
# notes :
# python_version :3.8
# ==============================================================================
import numpy as np
import random
from mayavi import mlab
from PIL import Image
......
# -*- coding:utf-8 -*-
# title :
# description :
# author :Python超人
# date :2023-01-22
# notes :
# python_version :3.8
# ==============================================================================
from common.consts import SECONDS_PER_DAY, SECONDS_PER_HOUR, SECONDS_PER_MONTH, SECONDS_PER_WEEK
from common.system import System
from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
from mayavi import mlab
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
X_MIN, X_MAX = -2e+14, 2e+14 # the x range of the bounding box (m)
Y_MIN, Y_MAX = -2e+14, 2e+14 # the y range of the bounding box (m)
Z_MIN, Z_MAX = -2e+14, 2e+14 # the z range of the bounding box (m)
X_MIN, X_MAX = -2e+12, 2e+12 # the x range of the bounding box (m)
Y_MIN, Y_MAX = -2e+12, 2e+12 # the y range of the bounding box (m)
Z_MIN, Z_MAX = -2e+12, 2e+12 # the z range of the bounding box (m)
X_MIN, X_MAX = -1e+9, 1e+9 # the x range of the bounding box (m)
Y_MIN, Y_MAX = -1e+9, 1e+9 # the y range of the bounding box (m)
Z_MIN, Z_MAX = -1e+9, 1e+9 # the z range of the bounding box (m)
X_MIN, X_MAX = -8e+8, 8e+8 # the x range of the bounding box (m)
Y_MIN, Y_MAX = -8e+8, 8e+8 # the y range of the bounding box (m)
Z_MIN, Z_MAX = -8e+8, 8e+8 # the z range of the bounding box (m)
def show_figure(bodies, idx=0):
# from scipy.interpolate import make_interp_spline
# Creating figures for the plot
fig = plt.figure(figsize=(16, 12))
ax = plt.axes(projection="3d")
ax.set_xlim(X_MIN, X_MAX)
ax.set_ylim(Y_MIN, Y_MAX)
ax.set_zlim(Z_MIN, Z_MAX)
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
# Creating a plot using the random datasets
colors = ['red', 'blue', 'red', 'red']
sizes = [800, 500, 800, 800]
for idx, body in enumerate(bodies):
color = 'red' if str(body.name).lower().startswith("sun") else 'blue'
size = 800 if str(body.name).lower().startswith("sun") else 500
pos = body.position
ax.text(pos[0], pos[1], pos[2] + 1e8, body.name, color=color, fontsize=20)
ax.scatter(pos[0], pos[1], pos[2], color=color, s=size)
# for _his_pos in body.his_position():
# ax.scatter3D(_his_pos[0], _his_pos[1], _his_pos[2], color=color, alpha=0.5)
# ax.scatter(his_pos[0], his_pos[1], his_pos[2], color=colors[idx], s=10)
his_pos = body.his_position()
if len(his_pos) > 1:
_his_pos = list(zip(*his_pos))
ax.plot3D(_his_pos[0], _his_pos[1], _his_pos[2], color=color, alpha=0.8)
plt.title("3D %s" % idx)
# display the plot
plt.show()
import time
class Simulator:
def __init__(self, system, dt):
self.system = system
self.dt = dt
def evolve(self, dt):
show_figure(self.system.bodies)
self.system.calc_acceleration()
for body in self.system.bodies:
# acceleration 加速度
body.velocity += body.acceleration * dt
# body.position += 0.5 * body.acceleration * (dt ** 2)
body.position += body.velocity * dt
print(body)
# print(body.name, body.position)
def run(self, t):
n = int(t / self.dt)
for i in range(n):
self.evolve(self.dt)
time.sleep(1)
def run_always(self):
dt = 1 # 时间变化1秒
while True:
# time.sleep(1)
self.evolve(dt)
def run(bodies):
"""
运行天体
:param bodies:
:return:
"""
for body1 in bodies:
for body2 in bodies:
if body1 == body2: # 相等说明是同一个天体,跳过计算
continue
#
r = body2.position - body1.position
# F = G x (m1 x m2) / r² 万有引力定律
F = G * body1.mass * body2.mass * r / np.linalg.norm(r) / r.dot(r)
body1.momentum = body1.momentum + F * Configs.dt # 动量定理
body1.position = body1.position + (body1.momentum / body1.mass) * Configs.dt
body1.update_source_data()
def solar_system():
t = SECONDS_PER_WEEK
_sys = System([
Sun(), # 太阳
Mercury(), # 水星
Venus(), # 金星
Earth(), # 地球
Mars(), # 火星
Jupiter(), # 木星
Saturn(), # 土星
Uranus(), # 天王星
Neptune(), # 海王星
Pluto() # 冥王星(从太阳系的行星中排除)
])
_sim = Simulator(_sys, t)
_sim.run(t * 100)
if __name__ == '__main__':
# t = 60 * 60 * 24 * 10
solar_system()
# _sys = System([Sun(init_position=[0, 0, 149597870.700]), Earth()])
# _sys = System([Sun(init_position=[849597870.700, 0, 0], init_velocity=[0, 9.79, 0]),
# Sun(init_position=[0, 0, 0], init_velocity=[0, -9.79, 0])])
# _sys = System([Sun(), Earth()])
# _sys = System([Sun(name="sun1", init_position=[849597870.700, 0, 0], init_velocity=[0, 7.0, 0]),
# Sun(name="sun2", init_position=[0, 0, 0], init_velocity=[0, -8.0, 0]),
# Sun(name="sun3", init_position=[0, -849597870.700, 0], init_velocity=[18.0, 0, 0]),
# Earth(init_position=[0, -349597870.700, 0], init_velocity=[15.50, 0, 0])])
# _sys = System([Sun(), Earth(), Jupiter()])
#
# _sim = Simulator(_sys, t)
# _sim.run(t * 100)
......@@ -8,9 +8,14 @@
# ==============================================================================
import numpy as np
from common.consts import AU, G
from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
class System(object):
"""
天体系统
"""
def __init__(self, bodies):
self.bodies = bodies
......@@ -18,146 +23,47 @@ class System(object):
self.bodies.append(body)
def total_mass(self):
total_mass = 0
for body in self.bodies:
total_mass = body.mass
return total_mass
def __repr__(self):
return 'System({})'.format(self.bodies)
def kinetic_energy(self):
"""
KE是系统的动能
总质量
:return:
"""
ke = 0
total_mass = 0.0
for body in self.bodies:
v = body.velocity # velocity
ke = 0.5 * body.mass * (v[0] ** 2 + v[1] ** 2) # ke = 0.5 * body.mass * (v[0]**2 v[1]**2)
return ke
# def kinetic_energy(self, vx, vy, vz, mass):
# """
# 计算动能
# """
# v = body.velocity # velocity
# return 0.5 * mass * (vx ** 2 + vy ** 2 + vz ** 2)
def potential_energy(self, x, y, z, mass,M):
"""
计算势能
"""
return -G * M * mass / np.sqrt(x ** 2 + y ** 2 + z ** 2)
total_mass += body.mass
return total_mass
def potential_energy(self):
"""
PE是系统的势能
:return:
"""
pe = 0
for body1 in self.bodies:
for body2 in self.bodies:
if body1 is body2:
continue
r = body1.position - body2.position
# pe -= body1.mass * body2.mass / np.sqrt(r[0]**2 r[1]**2)
pe -= body1.mass * body2.mass / np.sqrt(r[0] ** 2 + r[1] ** 2)
return pe
def __repr__(self):
return 'System({})'.format(self.bodies)
def momentum(self):
def center_of_mass(self):
"""
动量
质心
:return:
"""
p = np.zeros(2)
r = np.zeros(2)
for body in self.bodies:
p = body.mass * body.velocity
return p
r = body.mass * body.position
return r / self.total_mass()
def momentum(self, vx, vy, vz, mass):
def evolve(self, dt):
"""
计算动量
"""
return mass * np.sqrt(vx ** 2 + vy ** 2 + vz ** 2)
def angular_momentum(self):
"""
角动量
:param dt:
:return:
"""
L = 0
for body in self.bodies:
r = body.position
v = body.velocity
L = body.mass * (r[0] * v[1] - r[1] * v[0])
return L
def angular_momentum(self, x, y, z, vx, vy, vz):
"""
计算角动量
"""
return self.mass * (x * vy - y * vx)
self.calc_bodies_acceleration()
def center_of_mass(self):
r = np.zeros(2)
for body in self.bodies:
r = body.mass * body.position
return r / self.total_mass()
# acceleration 加速度
body.velocity += body.acceleration * dt
# body.position += 0.5 * body.acceleration * (dt ** 2)
body.position += body.velocity * dt
# def step(m: np.ndarray, v: np.ndarray, p: np.ndarray):
# ''' Calculate the next state of the N-star system.
# args:
# m: np.ndarray[(N,), np.float64], mass.
# v: np.ndarray[(N,3), np.float64], velocity.
# p: np.ndarray[(N,3), np.float64], position.
# returns:
# (next_v, next_p), the next state.
# '''
# N = m.shape[0]
# a = np.zeros_like(p)
# for i in range(N):
# for j in range(N):
# if i == j: continue
# r = np.sqrt(np.sum(np.square(p[j, :] - p[i, :])))
# aij = G * m[j] / (r * r)
# dir = (p[j, :] - p[i, :]) / r
# a[i, :] += aij * dir
# next_p = p + (1 / FS) * v + 0.5 * a * ((1 / FS) ** 2)
# next_v = v + (1 / FS) * a
# return (next_v, next_p)
# next_p = p + dt * v + 0.5 * a * (dt ** 2)
# next_v = v + dt * a
# for body1 in bodies:
# for body2 in bodies:
# if body1 == body2: # 相等说明是同一个天体,跳过计算
# continue
# r = body2.position - body1.position
# # F = G x (m1 x m2) / r² 万有引力定律
# F = Configs.G * body1.mass * body2.mass * r / np.linalg.norm(r) / r.dot(r)
# body1.momentum = body1.momentum + F * dt # 动量定理
# body1.position = body1.position + (body1.momentum / body1.mass) * dt
# body1.update_source_data()
def acceleration(self, body1, body2):
def calc_bodies_acceleration(self):
"""
计算两个天体之间的加速度
:param body1: 天体1
:param body2: 天体2
:param G: 引力常数
:return: 加速度
计算加速度
:return:
"""
import math
dx = body2.position[0] - body1.position[0]
dy = body2.position[1] - body1.position[1]
dz = body2.position[2] - body1.position[2]
distance = math.sqrt(dx ** 2 + dy ** 2 + dz ** 2)
mag = G * body2.mass / (distance ** 2)
acc = [dx / distance * mag, dy / distance * mag, dz / distance * mag]
return np.array(acc) / 1000 / 1000 / 1000
def calc_acceleration(self):
for body1 in self.bodies:
acceleration = np.zeros(3)
for body2 in self.bodies:
......@@ -165,7 +71,6 @@ class System(object):
continue
r = body2.position - body1.position
#
# G = 6.67e-11 # 万有引力常数
# m/s² = kg * m / m**3
# km/s² = kg * m / m**3 / 1e9
......@@ -175,80 +80,18 @@ class System(object):
body1.acceleration = acceleration
"""
# Python 3
def get_acceleration(mass1,mass2,position1,position2):
G = 6.67*10**-11
r = np.linalg.norm(position2-position1)
return G*mass2*(position2-position1)/r**3
# Python 2
# def get_acceleration(mass1,mass2,position1,position2):
# G = 6.67*10**-11
# r = np.linalg.norm(position2-position1)
# return G*mass2*(position2-position1)/r**3
根据两个天体body1 和 body2 的质量,距离 position[0],position[1],position[2],用python计算两个天体的加速度
# 假设两个天体的质量分别为m1和m2
m1 = 5.974 * 10 ** 24
m2 = 7.348 * 10 ** 22
# 计算两个天体的位置,假设分别为position1 和 position2
position1 = [2.21, 3.45, 4.67]
position2 = [1.78, 6.34, -1.23]
# 计算两个天体的距离
dist = ( (position1[0]-position2[0])**2 + (position1[1]-position2[1])**2 + (position1[2]-position2[2])**2 ) ** (1/2)
# 计算两个天体的加速度
G = 6.674 * 10 ** -11
acc_1 = G * m2 / (dist**2)
acc_2 = G * m1 / (dist**2)
# 输出结果
print("body1的加速度为:", acc_1)
print("body2的加速度为:", acc_2)
ax1 = (G * m2 * (x/pow(x**2 + y**2 + z**2,3/2)))
ay1 = (G * m2 * (y/pow(x**2 + y**2 + z**2,3/2)))
az1 = (G * m2 * (z/pow(x**2 + y**2 + z**2,3/2)))
ax2 = (G * m1 * (-x/pow(x**2 + y**2 + z**2,3/2)))
ay2 = (G * m1 * (-y/pow(x**2 + y**2 + z**2,3/2)))
az2 = (G * m1 * (-z/pow(x**2 + y**2 + z**2,3/2)))
加速度可以用万有引力定律计算:
a = G * m2 / r2
其中G为万有引力常数,m2和r2分别为两个天体的质量和距离平方。
因此,可以使用以下python代码来计算两个天体的加速度:
import math
G = 6.67e-11 # 万有引力常数
m1 = 1 # 第一个天体的质量
m2 = 1 # 第二个天体的质量
r = 1 # 两个天体之间的距离
a = G * m2 / math.pow(r, 2)
print(a)
"""
if __name__ == '__main__':
body_sys = System([
Sun(), # 太阳
Mercury(), # 水星
Venus(), # 金星
Earth(), # 地球
Mars(), # 火星
Jupiter(), # 木星
Saturn(), # 土星
Uranus(), # 天王星
Neptune(), # 海王星
Pluto() # 冥王星(从太阳系的行星中排除)
])
print(body_sys)
......@@ -14,11 +14,7 @@
0
],
"density": 1.408e3,
"color": [
125,
125,
125
],
"color": [170, 98, 25],
"texture": "",
"size_scale": 1.0,
"distance_scale": 1.0
......
# -*- coding:utf-8 -*-
# title :太阳系场景
# title :
# description :
# author :Python超人
# date :2023-01-22
# notes :
# python_version :3.8
# ==============================================================================
from mayavi import mlab
from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
from common.consts import SECONDS_PER_DAY, SECONDS_PER_HOUR, SECONDS_PER_MONTH, SECONDS_PER_WEEK
from common.consts import SECONDS_PER_WEEK
from common.system import System
from simulators.mayavi_simulator import MayaviSimulator
if __name__ == '__main__':
# 背景色
bgcolor = (1 / 255, 1 / 255, 30 / 255) # 宇宙背景色
def mayavi_run(bodies, dt=SECONDS_PER_WEEK,
view_azimuth=0, view_distance='auto', view_focalpoint='auto',
bgcolor=(1 / 255, 1 / 255, 30 / 255)):
"""
用 mayavi 查看运行效果
:param bodies: 天体
:param dt: 按时间差进行演变,值越小越精确,但演变速度会慢。
:param view_azimuth: 观测方位角,可选,float类型(以度为单位,0-360),用x轴投影到x-y平面上的球体上的位置矢量所对的角度。
:param view_distance: 观测距离,可选,float类型 or 'auto',一个正浮点数,表示距放置相机的焦点的距离。
:param view_focalpoint: 观测焦点,可选,类型为一个由3个浮点数组成的数组 or 'auto',,代表观测相机的焦点
:param bgcolor:
:return:
"""
from mayavi import mlab
from simulators.mayavi_simulator import MayaviSimulator
# 宇宙背景色
mlab.figure(bgcolor=bgcolor, size=(1440, 810))
# 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿)
# 排列顺序
# 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056
# 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553
# 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星
bodies = [
Sun(size_scale=1), # 太阳
Mercury(size_scale=3e1, distance_scale=1e1), # 水星
Venus(size_scale=2e1, distance_scale=1e1), # 金星
Earth(size_scale=2e1, distance_scale=1e1), # 地球
Mars(size_scale=2e1, distance_scale=1e1), # 火星
Jupiter(size_scale=0.5e1, distance_scale=0.4e1), # 木星
Saturn(size_scale=0.5e1, distance_scale=0.3e1), # 土星
Uranus(size_scale=0.5e1, distance_scale=0.2e1), # 天王星
Neptune(size_scale=0.5e1, distance_scale=0.15e1), # 海王星
Pluto(size_scale=5e1, distance_scale=0.12e1), # 冥王星(从太阳系的行星中排除)
]
from simulators.system import System
body_sys = System(bodies)
simulator = MayaviSimulator(body_sys)
simulator.run_anim(SECONDS_PER_WEEK)
simulator.run(dt)
# azimuth:
# 观测方位角,可选,float类型(以度为单位,0-360),用x轴投影到x-y平面上的球体上的位置矢量所对的角度。
# elevation:
......@@ -54,5 +46,6 @@ if __name__ == '__main__':
# 布尔值,可选。如果为True,且未指定“滚动”,则重置相机的滚动方向。
# figure:
# 要操作的Mayavi图形。如果为 None,则使用当前图形。
mlab.view(azimuth=-45, distance=9e9)
mlab.view(azimuth=view_azimuth, distance=view_distance, focalpoint=view_focalpoint)
# mlab.view(azimuth=-45, elevation=45, distance=100e8 * 2 * 2 * 4 * 4, focalpoint=[5e10, 5e10, 5e9])
mlab.show()
# -*- coding:utf-8 -*-
# title :太阳系场景
# description :
# author :Python超人
# date :2023-01-22
# notes :
# python_version :3.8
# ==============================================================================
from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto, Moon
from common.consts import SECONDS_PER_WEEK
from scenes.func import mayavi_run
if __name__ == '__main__':
# 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿)
# 排列顺序
# 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056
# 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553
# 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星
# =====================================================================
# 以下展示的效果为太阳系真实的距离
# 但是由于宇宙空间尺度非常大,按照实际的大小无法看到行星天体,因此需要对天体的尺寸进行放大
bodies = [
Sun(size_scale=1.2e2), # 太阳放大 120 倍,距离保持不变
Mercury(size_scale=4e3), # 水星放大 4000 倍,距离保持不变
Venus(size_scale=4e3), # 金星放大 4000 倍,距离保持不变
Earth(size_scale=4e3), # 地球放大 4000 倍,距离保持不变
Mars(size_scale=4e3), # 火星放大 4000 倍,距离保持不变
Jupiter(size_scale=1e3), # 木星放大 1000 倍,距离保持不变
Saturn(size_scale=1e3), # 土星放大 1000 倍,距离保持不变
Uranus(size_scale=1e3), # 天王星放大 1000 倍,距离保持不变
Neptune(size_scale=1e3), # 海王星放大 1000 倍,距离保持不变
Pluto(size_scale=10e3), # 冥王星放大 10000 倍,距离保持不变(从太阳系的行星中排除)
]
mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45)
# -*- coding:utf-8 -*-
# title :太阳系场景
# description :
# author :Python超人
# date :2023-01-22
# notes :
# python_version :3.8
# ==============================================================================
from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
from common.consts import SECONDS_PER_WEEK
from scenes.func import mayavi_run
if __name__ == '__main__':
# 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿)
# 排列顺序
# 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056
# 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553
# 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星
# =====================================================================
# 以下展示的效果非太阳系真实的距离和大小
# 1、由于宇宙空间尺度非常大,按照实际的大小无法看到行星天体,因此需要对天体的尺寸进行放大
# 2、对每个行星天体的距离进行了缩放
bodies = [
Sun(size_scale=1.2e2), # 太阳放大 120 倍
Mercury(size_scale=4e3, distance_scale=1), # 水星放大 4000 倍,距离保持不变
Venus(size_scale=4e3, distance_scale=1), # 金星放大 4000 倍,距离保持不变
Earth(size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变
Mars(size_scale=4e3, distance_scale=1), # 火星放大 4000 倍,距离保持不变
Jupiter(size_scale=1e3, distance_scale=0.5), # 木星放大 1000 倍,距离缩小到真实距离的 0.5
Saturn(size_scale=1e3, distance_scale=0.38), # 土星放大 1000 倍,距离缩小到真实距离的 0.38
Uranus(size_scale=1e3, distance_scale=0.26), # 天王星放大 1000 倍,距离缩小到真实距离的 0.26
Neptune(size_scale=1e3, distance_scale=0.22), # 海王星放大 1000 倍,距离缩小到真实距离的 0.22
Pluto(size_scale=10e3, distance_scale=0.20), # 冥王星放大 10000 倍,距离缩小到真实距离的 0.2(从太阳系的行星中排除)
]
mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45, view_distance=3e9, view_focalpoint=[5e2, 5e2, 5e2])
# -*- coding:utf-8 -*-
# title :太阳系场景
# title :
# description :
# author :Python超人
# date :2023-01-22
# notes :
# python_version :3.8
# ==============================================================================
from mayavi import mlab
from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
from common.consts import SECONDS_PER_DAY, SECONDS_PER_HOUR, SECONDS_PER_MONTH, SECONDS_PER_WEEK
from simulators.mayavi_simulator import MayaviSimulator
from bodies import Sun, Earth
from common.consts import SECONDS_PER_WEEK
from scenes.func import mayavi_run
if __name__ == '__main__':
# 背景色
bgcolor = (1 / 255, 1 / 255, 30 / 255) # 宇宙背景色
mlab.figure(bgcolor=bgcolor, size=(1440, 810))
# 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿)
# 排列顺序
# 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056
# 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553
# 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星
"""
太阳、地球
"""
bodies = [
Sun(size_scale=1), # 太阳
Earth(size_scale=2e1, distance_scale=1e1), # 地球
Sun(size_scale=1.2e2), # 太阳放大 120 倍
Earth(size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变
]
from simulators.system import System
body_sys = System(bodies)
simulator = MayaviSimulator(body_sys)
simulator.run_anim(SECONDS_PER_WEEK)
# azimuth:
# 观测方位角,可选,float类型(以度为单位,0-360),用x轴投影到x-y平面上的球体上的位置矢量所对的角度。
# elevation:
# 观测天顶角,可选,float类型(以度为单位,0-180), 位置向量和z轴所对的角度。
# distance:
# 观测距离,可选,float类型 or 'auto',一个正浮点数,表示距放置相机的焦点的距离。
# Mayavi 3.4.0中的新功能:'auto' 使得距离为观察所有对象的最佳位置。
# focalpoint:
# 观测焦点,可选,类型为一个由3个浮点数组成的数组 or 'auto',,代表观测相机的焦点
# Mayavi 3.4.0中的新功能:'auto',则焦点位于场景中所有对象的中心。
# roll:
# 控制滚动,可选,float类型,即摄影机围绕其轴的旋转
# reset_roll:
# 布尔值,可选。如果为True,且未指定“滚动”,则重置相机的滚动方向。
# figure:
# 要操作的Mayavi图形。如果为 None,则使用当前图形。
mlab.view(azimuth=-45, distance=9e9)
mlab.show()
mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45)
# -*- coding:utf-8 -*-
# title :太阳系场景
# title :
# description :
# author :Python超人
# date :2023-01-22
# notes :
# python_version :3.8
# ==============================================================================
from mayavi import mlab
from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
from common.consts import SECONDS_PER_DAY, SECONDS_PER_HOUR, SECONDS_PER_MONTH, SECONDS_PER_WEEK
from simulators.mayavi_simulator import MayaviSimulator
from bodies import Sun, Earth, Jupiter
from common.consts import SECONDS_PER_WEEK
from scenes.func import mayavi_run
if __name__ == '__main__':
# 背景色
bgcolor = (1 / 255, 1 / 255, 30 / 255) # 宇宙背景色
mlab.figure(bgcolor=bgcolor, size=(1440, 810))
# 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿)
# 排列顺序
# 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056
# 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553
# 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星
"""
太阳、地球、木星
"""
bodies = [
Sun(size_scale=1), # 太阳
Earth(size_scale=2e1, distance_scale=1e1), # 地球
Jupiter(size_scale=0.5e1, distance_scale=1e1), # 木星
Sun(size_scale=1.2e2), # 太阳放大 120 倍
Earth(size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变
Jupiter(size_scale=1e3, distance_scale=0.5), # 木星放大 1000 倍,距离缩小到真实距离的 0.5
]
from simulators.system import System
body_sys = System(bodies)
simulator = MayaviSimulator(body_sys)
simulator.run_anim(SECONDS_PER_WEEK)
# azimuth:
# 观测方位角,可选,float类型(以度为单位,0-360),用x轴投影到x-y平面上的球体上的位置矢量所对的角度。
# elevation:
# 观测天顶角,可选,float类型(以度为单位,0-180), 位置向量和z轴所对的角度。
# distance:
# 观测距离,可选,float类型 or 'auto',一个正浮点数,表示距放置相机的焦点的距离。
# Mayavi 3.4.0中的新功能:'auto' 使得距离为观察所有对象的最佳位置。
# focalpoint:
# 观测焦点,可选,类型为一个由3个浮点数组成的数组 or 'auto',,代表观测相机的焦点
# Mayavi 3.4.0中的新功能:'auto',则焦点位于场景中所有对象的中心。
# roll:
# 控制滚动,可选,float类型,即摄影机围绕其轴的旋转
# reset_roll:
# 布尔值,可选。如果为True,且未指定“滚动”,则重置相机的滚动方向。
# figure:
# 要操作的Mayavi图形。如果为 None,则使用当前图形。
mlab.view(azimuth=-45, distance=9e9)
mlab.show()
mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45)
......@@ -7,58 +7,26 @@
# python_version :3.8
# ==============================================================================
from mayavi import mlab
from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
from common.consts import SECONDS_PER_DAY, SECONDS_PER_HOUR, SECONDS_PER_MONTH, SECONDS_PER_WEEK
from common.consts import AU
from simulators.mayavi_simulator import MayaviSimulator
from bodies import Sun, Earth
from common.consts import SECONDS_PER_WEEK
from scenes.func import mayavi_run
if __name__ == '__main__':
# 背景色
bgcolor = (1 / 255, 1 / 255, 30 / 255) # 宇宙背景色
mlab.figure(bgcolor=bgcolor, size=(1440, 810))
# 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿)
# 排列顺序
# 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056
# 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553
# 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星
"""
3个太阳、1个地球(效果1)
可以修改影响效果的参数为:
1、三个方向的初始位置 init_position[x, y, z]
2、三个方向的初始速度 init_velocity[x, y, z]
3、天体质量 mass
"""
bodies = [
Sun(mass=1.5e30, init_position=[849597870.700, 0, 0], init_velocity=[0, 7.0, 0],
texture="sun1.jpg", size_scale=1, distance_scale=1e1), # 太阳1,
size_scale=1e2, texture="sun1.jpg"), # 太阳放大 100 倍
Sun(mass=2e30, init_position=[0, 0, 0], init_velocity=[0, -8.0, 0],
texture="sun2.jpg", size_scale=1, distance_scale=1e1), # 太阳2,
size_scale=1e2, texture="sun2.jpg"), # 太阳放大 100 倍
Sun(mass=2.5e30, init_position=[0, -849597870.700, 0], init_velocity=[18.0, 0, 0],
texture="sun2.jpg", size_scale=1, distance_scale=1e1), # 太阳3,
size_scale=1e2, texture="sun2.jpg"), # 太阳放大 100 倍
Earth(init_position=[0, -349597870.700, 0], init_velocity=[15.50, 0, 0],
size_scale=5e1, distance_scale=1e1) # 地球
size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变
]
# Sun(name="sun1", init_position=[849597870.700, 0, 0], init_velocity=[0, 7.0, 0]),
# # Sun(name="sun2", init_position=[0, 0, 0], init_velocity=[0, -8.0, 0]),
# # Sun(name="sun3", init_position=[0, -849597870.700, 0], init_velocity=[18.0, 0, 0]),
# # Earth(init_position=[0, -349597870.700, 0], init_velocity=[15.50, 0, 0])]
from simulators.system import System
body_sys = System(bodies)
simulator = MayaviSimulator(body_sys)
simulator.run_anim_10(SECONDS_PER_WEEK)
# azimuth:
# 观测方位角,可选,float类型(以度为单位,0-360),用x轴投影到x-y平面上的球体上的位置矢量所对的角度。
# elevation:
# 观测天顶角,可选,float类型(以度为单位,0-180), 位置向量和z轴所对的角度。
# distance:
# 观测距离,可选,float类型 or 'auto',一个正浮点数,表示距放置相机的焦点的距离。
# Mayavi 3.4.0中的新功能:'auto' 使得距离为观察所有对象的最佳位置。
# focalpoint:
# 观测焦点,可选,类型为一个由3个浮点数组成的数组 or 'auto',,代表观测相机的焦点
# Mayavi 3.4.0中的新功能:'auto',则焦点位于场景中所有对象的中心。
# roll:
# 控制滚动,可选,float类型,即摄影机围绕其轴的旋转
# reset_roll:
# 布尔值,可选。如果为True,且未指定“滚动”,则重置相机的滚动方向。
# figure:
# 要操作的Mayavi图形。如果为 None,则使用当前图形。
mlab.view(azimuth=-45, distance=9e9)
mlab.show()
mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=0)
......@@ -7,55 +7,27 @@
# python_version :3.8
# ==============================================================================
from mayavi import mlab
from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
from common.consts import SECONDS_PER_DAY, SECONDS_PER_HOUR, SECONDS_PER_MONTH, SECONDS_PER_WEEK
from common.consts import AU
from simulators.mayavi_simulator import MayaviSimulator
from bodies import Sun, Earth
from common.consts import SECONDS_PER_WEEK
from scenes.func import mayavi_run
if __name__ == '__main__':
# 背景色
bgcolor = (1 / 255, 1 / 255, 30 / 255) # 宇宙背景色
mlab.figure(bgcolor=bgcolor, size=(1440, 810))
# 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿)
# 排列顺序
# 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056
# 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553
# 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星
"""
3个太阳、1个地球(效果2)
可以修改影响效果的参数为:
1、三个方向的初始位置 init_position[x, y, z]
2、三个方向的初始速度 init_velocity[x, y, z]
3、天体质量 mass
"""
bodies = [
Sun(mass=1.5e30, init_position=[849597870.700, 0, 0], init_velocity=[0, 7.0, 0],
texture="sun1.jpg", size_scale=1, distance_scale=1e1), # 太阳1,
size_scale=1e2, texture="sun1.jpg"), # 太阳放大 100 倍
Sun(mass=2e30, init_position=[0, 0, 249597870.700], init_velocity=[0, -8.0, 0],
size_scale=1e2, texture="sun2.jpg"), # 太阳放大 100 倍
Sun(mass=2.5e30, init_position=[0, -849597870.700, 0], init_velocity=[8.0, 0, 0],
size_scale=1e2, texture="sun2.jpg"), # 太阳放大 100 倍
Sun(mass=2e30, init_position=[0, 0, 0], init_velocity=[0, -8.0, 0],
texture="sun2.jpg", size_scale=1, distance_scale=1e1), # 太阳2,
Sun(mass=2.5e30, init_position=[0, -849597870.700, 0], init_velocity=[18.0, 0, 0],
texture="sun2.jpg", size_scale=1, distance_scale=1e1), # 太阳3
Earth(init_position=[0, -349597870.700, 0], init_velocity=[15.50, 0, 0],
size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变
]
# Sun(name="sun1", init_position=[849597870.700, 0, 0], init_velocity=[0, 7.0, 0]),
# # Sun(name="sun2", init_position=[0, 0, 0], init_velocity=[0, -8.0, 0]),
# # Sun(name="sun3", init_position=[0, -849597870.700, 0], init_velocity=[18.0, 0, 0]),
# # Earth(init_position=[0, -349597870.700, 0], init_velocity=[15.50, 0, 0])]
from simulators.system import System
body_sys = System(bodies)
simulator = MayaviSimulator(body_sys)
simulator.run_anim_10(SECONDS_PER_DAY)
# azimuth:
# 观测方位角,可选,float类型(以度为单位,0-360),用x轴投影到x-y平面上的球体上的位置矢量所对的角度。
# elevation:
# 观测天顶角,可选,float类型(以度为单位,0-180), 位置向量和z轴所对的角度。
# distance:
# 观测距离,可选,float类型 or 'auto',一个正浮点数,表示距放置相机的焦点的距离。
# Mayavi 3.4.0中的新功能:'auto' 使得距离为观察所有对象的最佳位置。
# focalpoint:
# 观测焦点,可选,类型为一个由3个浮点数组成的数组 or 'auto',,代表观测相机的焦点
# Mayavi 3.4.0中的新功能:'auto',则焦点位于场景中所有对象的中心。
# roll:
# 控制滚动,可选,float类型,即摄影机围绕其轴的旋转
# reset_roll:
# 布尔值,可选。如果为True,且未指定“滚动”,则重置相机的滚动方向。
# figure:
# 要操作的Mayavi图形。如果为 None,则使用当前图形。
mlab.view(azimuth=-45, distance=9e9)
mlab.show()
mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=0)
......@@ -7,78 +7,20 @@
# python_version :3.8
# ==============================================================================
from mayavi import mlab
from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
from common.consts import SECONDS_PER_DAY, SECONDS_PER_HOUR, SECONDS_PER_MONTH, SECONDS_PER_WEEK
from simulators.simulator import Simulator
from common.system import System
from simulators.viewers.mayavi_viewer import MayaviViewer
from simulators.mayavi_body import MayaviBody
class MayaviSimulator:
"""
"""
def __init__(self, sys):
self.sys = sys
self.mayavi_bodies = []
for body in self.sys.bodies:
mbody = MayaviBody(body)
self.mayavi_bodies.append(mbody)
def run(self, dt):
self.sys.evolve(dt)
for idx, body in enumerate(self.mayavi_bodies):
# acceleration 加速度
# body.velocity = self.sys.bodies[idx].velocity
# body.position += 0.5 * body.acceleration * (dt ** 2)
body.position = self.sys.bodies[idx].position * self.sys.bodies[idx].distance_scale
body.update_source_data()
# print(self.sys.bodies[idx])
class MayaviSimulator(Simulator):
def __init__(self, bodies_sys: System):
super().__init__(bodies_sys, MayaviViewer)
@mlab.animate(delay=100, ui=True)
def run_anim(self, dt):
f = mlab.gcf()
while True:
self.run(dt)
# Updating scene...
f.scene.render()
yield
@mlab.animate(delay=10, ui=True)
def run_anim_10(self, dt):
def run(self, dt):
f = mlab.gcf()
while True:
self.run(dt)
self.evolve(dt)
# Updating scene...
f.scene.render()
yield
if __name__ == '__main__':
# 背景色
bgcolor = (1 / 255, 1 / 255, 30 / 255) # 宇宙背景色
mlab.figure(bgcolor=bgcolor, size=(1440, 810))
# 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿)
# 排列顺序
# 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056
# 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553
# 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星
bodies = [
Sun(size_scale=1), # 太阳
Mercury(size_scale=3e1, distance_scale=1e1), # 水星
Venus(size_scale=2e1, distance_scale=1e1), # 金星
Earth(size_scale=2e1, distance_scale=1e1), # 地球
Mars(size_scale=2e1, distance_scale=1e1), # 火星
Jupiter(size_scale=0.5e1, distance_scale=0.4e1), # 木星
Saturn(size_scale=0.5e1, distance_scale=0.3e1), # 土星
Uranus(size_scale=0.5e1, distance_scale=0.2e1), # 天王星
Neptune(size_scale=0.5e1, distance_scale=0.15e1), # 海王星
Pluto(size_scale=5e1, distance_scale=0.12e1), # 冥王星(从太阳系的行星中排除)
]
from simulators.system import System
body_sys = System(bodies)
simulator = MayaviSimulator(body_sys)
simulator.run_anim(SECONDS_PER_WEEK)
mlab.view(azimuth=-45, distance=9e9)
mlab.show()
# -*- coding:utf-8 -*-
# title :
# description :
# author :Python超人
# date :2023-01-22
# notes :
# python_version :3.8
# ==============================================================================
from abc import ABCMeta, abstractmethod
from common.system import System
class Simulator(metaclass=ABCMeta):
"""
"""
def __init__(self, bodies_sys: System, viewer_type: type):
"""
:param bodies_sys: 天体系统
:param viewer_type: BodyViewer类型
"""
self.body_viewers = []
self.bodies_sys = bodies_sys
self.init_viewers(viewer_type)
def init_viewers(self, viewer_type: type):
"""
:param viewer_type: BodyViewer类型
:return:
"""
for body in self.bodies_sys.bodies:
viewer = viewer_type(body)
self.body_viewers.append(viewer)
def evolve(self, dt: int):
"""
按时间差进行演变,值越小越精确,但演变速度会慢。
:param dt: 时间差(秒)
:return:
"""
self.bodies_sys.evolve(dt)
for idx, viewer in enumerate(self.body_viewers):
viewer.position = self.bodies_sys.bodies[idx].position * self.bodies_sys.bodies[idx].distance_scale
viewer.update()
@abstractmethod
def run(self, dt: int):
"""
按时间差运行,值越小越精确,但演变速度会慢。
:param dt: 时间差(秒)
:return:
"""
pass
# -*- coding:utf-8 -*-
# title :
# description :
# author :Python超人
# date :2023-01-22
# notes :
# python_version :3.8
# ==============================================================================
import numpy as np
from common.consts import AU, G
from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
class System(object):
"""
天体系统
"""
def __init__(self, bodies):
self.bodies = bodies
def add(self, body):
self.bodies.append(body)
def total_mass(self):
"""
总质量
:return:
"""
total_mass = 0.0
for body in self.bodies:
total_mass += body.mass
return total_mass
def __repr__(self):
return 'System({})'.format(self.bodies)
def center_of_mass(self):
"""
质心
:return:
"""
r = np.zeros(2)
for body in self.bodies:
r = body.mass * body.position
return r / self.total_mass()
def evolve(self, dt):
"""
:param dt:
:return:
"""
self.calc_bodies_acceleration()
for body in self.bodies:
# acceleration 加速度
body.velocity += body.acceleration * dt
# body.position += 0.5 * body.acceleration * (dt ** 2)
body.position += body.velocity * dt
def calc_bodies_acceleration(self):
"""
计算加速度
:return:
"""
for body1 in self.bodies:
acceleration = np.zeros(3)
for body2 in self.bodies:
if body1 is body2:
continue
r = body2.position - body1.position
# G = 6.67e-11 # 万有引力常数
# m/s² = kg * m / m**3
# km/s² = kg * m / m**3 / 1e9
# acceleration = G * body2.mass * dx / (d ** 3)
acceleration += (G * body2.mass * r / np.linalg.norm(r) ** 3) / 1e9
body1.acceleration = acceleration
if __name__ == '__main__':
body_sys = System([
Sun(), # 太阳
Mercury(), # 水星
Venus(), # 金星
Earth(), # 地球
Mars(), # 火星
Jupiter(), # 木星
Saturn(), # 土星
Uranus(), # 天王星
Neptune(), # 海王星
Pluto() # 冥王星(从太阳系的行星中排除)
])
print(body_sys)
# -*- coding:utf-8 -*-
# title :
# description :
# author :Python超人
# date :2023-01-22
# notes :
# python_version :3.8
# ==============================================================================
from abc import ABCMeta, abstractmethod
from bodies import Body
from common.func import get_dominant_colors
import numpy as np
import os
class BodyViewer(metaclass=ABCMeta):
def __init__(self, body: Body):
self.body = body
self.sphere = None
if self.body.texture is None or self.body.texture == '':
self.color = tuple(np.array(body.color) / 255)
else:
self.texture = self.__find_texture(self.body.texture) # 纹理
if self.texture is None:
self.color = tuple(np.array(body.color) / 255)
else:
self.color = self.__texture_to_color(self.texture)
self.sphere = self.build()
self.position = None
def __find_texture(self, texture):
"""
在多路径下寻找纹理图片
:param texture: 纹理图片
:return: 纹理图片的路径
"""
paths = ['./textures', '../textures']
for path in paths:
p = path + "/" + texture
if os.path.exists(p):
return p
return None
def __texture_to_color(self, texture):
"""
根据纹理图片获取颜色
:param texture:
:return:
"""
colors = get_dominant_colors(texture)
first_color = colors[0]
# print(self.name, first_color)
return tuple(np.array(first_color) / 255)
@abstractmethod
def update(self):
pass
@abstractmethod
def build(self):
pass
......@@ -7,31 +7,18 @@
# python_version :3.8
# ==============================================================================
from mayavi import mlab
import numpy as np
from bodies import Body
from mayavi import mlab
import numpy as np
from tvtk.api import tvtk
from abc import ABCMeta, abstractmethod
import os
import matplotlib.pyplot as plt
from common.func import get_dominant_colors
from simulators.viewers.body_viewer import BodyViewer
import numpy as np
class MayaviBody:
def __init__(self, body: Body):
self.body = body
if self.body.texture is None or self.body.texture == '':
self.color = tuple(np.array(body.color) / 255)
else:
self.texture = self.__find_texture(self.body.texture) # 纹理
if self.texture is None:
self.color = tuple(np.array(body.color) / 255)
else:
self.color = self.__texture_to_color(self.texture)
self.build_body()
class MayaviViewer(BodyViewer):
def update_source_data(self):
def update(self):
"""
:return:
......@@ -41,8 +28,6 @@ class MayaviBody:
z_offset = self.body.position[2] - self.sphere.mlab_source.z
self.sphere.mlab_source.set(x=self.position[0], y=self.position[1], z=self.position[2])
# print(self.sphere.mlab_source.y, self.position[1])
# self.sphere.actor.actor.position = self.position
return x_offset[0], y_offset[0], z_offset[0]
def __find_texture(self, texture):
......@@ -70,12 +55,12 @@ class MayaviBody:
# print(self.name, first_color)
return tuple(np.array(first_color) / 255)
def build_body(self):
def build(self):
"""
构建球体对象
:return:
"""
if not hasattr(self, "sphere"):
if not hasattr(self, "sphere") or self.sphere is None:
scale_factor = self.body.size_scale * self.body.raduis
sphere = mlab.points3d(self.body.position[0], self.body.position[1], self.body.position[2],
scale_factor=scale_factor,
......
# -*- coding:utf-8 -*-
# title :
# description :
# author :Python超人
# date :2023-01-22
# notes :
# python_version :3.8
# ==============================================================================
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册