提交 b95ecbda 编写于 作者: 三月三net's avatar 三月三net

Python超人-宇宙模拟器

上级 f5d53e79
...@@ -28,6 +28,9 @@ def calc_solar_acceleration(body_or_pos, big_body): ...@@ -28,6 +28,9 @@ def calc_solar_acceleration(body_or_pos, big_body):
body_pos = body_or_pos.position body_pos = body_or_pos.position
else: else:
body_pos = body_or_pos body_pos = body_or_pos
if big_body is None:
return [0, 0, 0]
x, y, z = body_pos[0] * 1000 - big_body.position[0] * 1000, \ x, y, z = body_pos[0] * 1000 - big_body.position[0] * 1000, \
body_pos[1] * 1000 - big_body.position[1] * 1000, \ body_pos[1] * 1000 - big_body.position[1] * 1000, \
body_pos[2] * 1000 - big_body.position[2] * 1000 body_pos[2] * 1000 - big_body.position[2] * 1000
......
...@@ -3,53 +3,53 @@ from 引力世界 import 造物主 ...@@ -3,53 +3,53 @@ from 引力世界 import 造物主
class 太阳(Sun): class 太阳(Sun):
def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放大小=1): def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放倍数=1):
super(太阳, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放大小) super(太阳, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放倍数)
class 地球(Earth): class 地球(Earth):
def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放大小=1): def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放倍数=1):
super(地球, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放大小) super(地球, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放倍数)
class 月球(Moon): class 月球(Moon):
def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放大小=1): def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放倍数=1):
super(月球, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放大小) super(月球, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放倍数)
class 水星(Mercury): class 水星(Mercury):
def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放大小=1): def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放倍数=1):
super(水星, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放大小) super(水星, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放倍数)
class 金星(Venus): class 金星(Venus):
def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放大小=1): def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放倍数=1):
super(金星, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放大小) super(金星, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放倍数)
class 火星(Mars): class 火星(Mars):
def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放大小=1): def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放倍数=1):
super(火星, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放大小) super(火星, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放倍数)
class 木星(Jupiter): class 木星(Jupiter):
def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放大小=1): def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放倍数=1):
super(木星, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放大小) super(木星, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放倍数)
class 土星(Saturn): class 土星(Saturn):
def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放大小=1): def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放倍数=1):
super(土星, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放大小) super(土星, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放倍数)
class 天王星(Uranus): class 天王星(Uranus):
def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放大小=1): def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放倍数=1):
super(天王星, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放大小) super(天王星, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放倍数)
class 海王星(Neptune): class 海王星(Neptune):
def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放大小=1): def __init__(self, 初始位置=[0, 0, 0], 初始速度=[0, 0, 0], 缩放倍数=1):
super(海王星, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放大小) super(海王星, self).__init__(init_velocity=初始速度, init_position=初始位置, size_scale=缩放倍数)
造物主.登记(['太阳', 'sun'], 太阳) 造物主.登记(['太阳', 'sun'], 太阳)
......
...@@ -9,7 +9,7 @@ ...@@ -9,7 +9,7 @@
from ursina import Ursina, camera, EditorCamera, Sky, Entity, load_model, color from ursina import Ursina, camera, EditorCamera, Sky, Entity, load_model, color
from common.celestial_data_service import set_solar_system_celestial_position, conv_to_astropy_time, \ from common.celestial_data_service import set_solar_system_celestial_position, conv_to_astropy_time, \
get_reality_orbit_points get_reality_orbit_points, get_body_posvel, recalc_moon_position, calc_solar_acceleration
from common.consts import SECONDS_PER_DAY, AU from common.consts import SECONDS_PER_DAY, AU
from bodies.body import Body from bodies.body import Body
from bodies import * from bodies import *
...@@ -21,10 +21,24 @@ from simulators.ursina.ursina_config import UrsinaConfig ...@@ -21,10 +21,24 @@ from simulators.ursina.ursina_config import UrsinaConfig
from simulators.ursina.ursina_event import UrsinaEvent from simulators.ursina.ursina_event import UrsinaEvent
from simulators.ursina.ursina_mesh import create_orbit_by_points from simulators.ursina.ursina_mesh import create_orbit_by_points
from 引力世界.数据.天体数据 import get_body_pos_vel from 引力世界.数据.天体数据 import get_body_pos_vel
import numpy as np
关闭=False
打开=True
=None
class 模拟配置:
显示轨道 = 关闭
地月距离倍数 = 1.0
中心天体=
class 模拟场景(UniverseSimScenes): class 模拟场景(UniverseSimScenes):
def 配置(self, 配置项: 模拟配置):
pass
def __init__(self): def __init__(self):
# self.app = Ursina() # self.app = Ursina()
# #
# self.sky = create_sphere_sky(scale=80000) # self.sky = create_sphere_sky(scale=80000)
...@@ -32,6 +46,14 @@ class 模拟场景(UniverseSimScenes): ...@@ -32,6 +46,14 @@ class 模拟场景(UniverseSimScenes):
# #
# EditorCamera() # EditorCamera()
self.配置项 = 模拟配置()
self.配置(self.配置项)
def get_body_pos_vel(self, body):
pos, vel = get_body_pos_vel(body)
return pos, vel
def 获取天体列表(self): def 获取天体列表(self):
for p in vars(self): for p in vars(self):
f = getattr(self, p) f = getattr(self, p)
...@@ -39,7 +61,12 @@ class 模拟场景(UniverseSimScenes): ...@@ -39,7 +61,12 @@ class 模拟场景(UniverseSimScenes):
yield f yield f
def 获取坐标和速度(self, 天体名称): def 获取坐标和速度(self, 天体名称):
pos, vel = get_body_pos_vel(天体名称) pos, vel = self.get_body_pos_vel(天体名称)
if not self.配置项.中心天体 is None:
center_pos, _ = self.get_body_pos_vel(self.配置项.中心天体.名称)
pos = pos - center_pos
return pos, vel return pos, vel
def 造物(self): def 造物(self):
...@@ -49,13 +76,11 @@ class 模拟场景(UniverseSimScenes): ...@@ -49,13 +76,11 @@ class 模拟场景(UniverseSimScenes):
camera.look_at(物体) camera.look_at(物体)
camera.rotation_z = 0 camera.rotation_z = 0
def on_ready(self): def on_ready(self):
from ursina import application, window from ursina import application, window
# application.time_scale = 0.0001 application.time_scale = 1
window_size = (int(1920/2), int(1079/2)) window_size = (int(1920 / 2), int(1079 / 2))
UniverseSimScenes.set_window_size(window_size, False) UniverseSimScenes.set_window_size(window_size, False)
window.borderless = False window.borderless = False
window.position = (20, 20) window.position = (20, 20)
...@@ -91,19 +116,18 @@ class 模拟场景(UniverseSimScenes): ...@@ -91,19 +116,18 @@ class 模拟场景(UniverseSimScenes):
UrsinaEvent.on_ready_subscription(self.on_ready) UrsinaEvent.on_ready_subscription(self.on_ready)
# UrsinaEvent.on_timer_changed_subscription(on_timer_changed) # UrsinaEvent.on_timer_changed_subscription(on_timer_changed)
ursina_run(bodies, SECONDS_PER_DAY, position=(0, 0, -2*AU), ursina_run(bodies, SECONDS_PER_DAY, position=(0, 0, -2 * AU),
cosmic_bg="", cosmic_bg="",
view_closely=0.001) view_closely=0.001)
# self.app.run() # self.app.run()
class 太阳系模拟场景(模拟场景): class 太阳系模拟场景(模拟场景):
def __init__(self): # def __init__(self):
self.造物() # self.造物()
def create_orbit_line(self,center_body, body, start_time, alpha=0.2): def create_orbit_line(self, center_body, body, start_time, alpha=0.2):
import math import math
if not hasattr(body, "orbital_days"): if not hasattr(body, "orbital_days"):
return None return None
...@@ -134,6 +158,107 @@ class 太阳系模拟场景(模拟场景): ...@@ -134,6 +158,107 @@ class 太阳系模拟场景(模拟场景):
if orbit_line is not None: if orbit_line is not None:
self.orbit_lines.append(orbit_line) self.orbit_lines.append(orbit_line)
def set_solar_system_celestial_position(self, bodies, dt, recalc_moon_pos, recalc_moon_pos_scale=50,
set_velocity=True, set_acceleration=True):
"""
根据日期时间 dt 设置太阳系中天体的真实位置
@param bodies: 太阳系中天体
@param dt: 时间
@param recalc_moon_pos: 是否对月球的位置进行重新计算。
为了更好的展示效果,需要对月球的位置重新计算(使得地月距离放大,月球相对地球方向不变),
重新计算位置后,地球和月球可以放大1000倍以上
@param set_velocity: 是否设置速度
@param set_acceleration: 是否设置加速度
@return:
"""
earth_pos = None
sun_pos = None
earth = None
sun = None
moon = None
for body in bodies:
if isinstance(body, Sun):
sun = body
elif isinstance(body, Earth):
earth = body
elif isinstance(body, Moon):
moon = body
for body in bodies:
if isinstance(body, Asteroids): # 小行星带是模拟,不是正常的天体
posvel = None
else:
try:
# 获取天体的三维位置和矢量速度
posvel = get_body_posvel(body, dt)
except Exception:
continue
if isinstance(body, Moon): # 如果是月球,为了更好的展示效果,需要对月球的位置重新计算
moon_real_pos = [posvel[0].x.value * AU, posvel[0].z.value * AU, posvel[0].y.value * AU]
# TODO:注释下行,月球就会在真实的位置
if recalc_moon_pos:
posvel = recalc_moon_position(posvel, earth_pos, scale=recalc_moon_pos_scale)
if not self.配置项.中心天体 is None:
center_pos, _ = get_body_posvel(self.配置项.中心天体.name, dt)
center_pos = [center_pos.x.value * AU, center_pos.z.value * AU, center_pos.y.value * AU]
else:
center_pos = [0, 0, 0]
if posvel is None:
# posvel 为空,则使用太阳的坐标
position, velocity = [sun_pos.x.value * AU,
sun_pos.z.value * AU,
sun_pos.y.value * AU], [0, 0, 0]
else:
# 坐标单位:千米 速度单位:千米/秒
position, velocity = [posvel[0].x.value * AU, posvel[0].z.value * AU, posvel[0].y.value * AU], \
[posvel[1].x.value * AU / SECONDS_PER_DAY,
posvel[1].z.value * AU / SECONDS_PER_DAY,
posvel[1].y.value * AU / SECONDS_PER_DAY]
if not self.配置项.中心天体 is None:
position = [position[0]-center_pos[0],position[1]-center_pos[1],position[2]-center_pos[2]]
# 实时调整天体的位置和速度
body.position = np.array(position)
if set_velocity:
body.velocity = np.array(velocity)
if isinstance(body, Asteroids):
pass
elif isinstance(body, Sun):
# 记录太阳的位置
sun_pos = posvel[0]
elif isinstance(body, Moon):
if set_acceleration:
# 月球受到2个影响比较大的天体引力(地球和太阳),计算引力引起的加速度和
acc_earth = calc_solar_acceleration(moon_real_pos, earth)
acc_sun = calc_solar_acceleration(moon_real_pos, sun)
body.acceleration = [acc_earth[0] + acc_sun[0],
acc_earth[1] + acc_sun[1],
acc_earth[2] + acc_sun[2]]
# elif isinstance(body, Earth):
# # 月球受到2个影响比较大的天体引力(地球和太阳),计算引力引起的加速度和
# acc_earth = calc_solar_acceleration(earth, moon)
# acc_sun = calc_solar_acceleration(earth, sun)
# body.acceleration = [acc_earth[0] + acc_sun[0],
# acc_earth[1] + acc_sun[1],
# acc_earth[2] + acc_sun[2]]
else:
if set_acceleration:
# 其他天体受到太阳引力
body.acceleration = calc_solar_acceleration(body, sun)
if isinstance(body, Earth):
# 记录地球的位置
earth_pos = posvel[0]
def set_bodies_position(self, time_data: TimeData): def set_bodies_position(self, time_data: TimeData):
""" """
设置天体的位置(包含速度和加速度的信息) 设置天体的位置(包含速度和加速度的信息)
...@@ -141,10 +266,11 @@ class 太阳系模拟场景(模拟场景): ...@@ -141,10 +266,11 @@ class 太阳系模拟场景(模拟场景):
@return: @return:
""" """
t = self.start_time + time_data.total_days t = self.start_time + time_data.total_days
set_solar_system_celestial_position(self.bodies, t, True, self.地月距离放大倍数) self.set_solar_system_celestial_position(self.bodies, t, True, self.配置项.地月距离倍数)
def on_ready(self): def on_ready(self):
super(太阳系模拟场景, self).on_ready() super(太阳系模拟场景, self).on_ready()
if self.配置项.显示轨道:
self.create_orbit_lines() self.create_orbit_lines()
def show_clock(self, time_data): def show_clock(self, time_data):
...@@ -185,7 +311,7 @@ class 太阳系模拟场景(模拟场景): ...@@ -185,7 +311,7 @@ class 太阳系模拟场景(模拟场景):
# 使用 ursina 查看的运行效果 # 使用 ursina 查看的运行效果
# 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹
# position = 左-右+、上+下-、前+后- # position = 左-右+、上+下-、前+后-
self.地月距离放大倍数 = 10
if isinstance(运行时间, str): if isinstance(运行时间, str):
self.start_time = conv_to_astropy_time(运行时间) self.start_time = conv_to_astropy_time(运行时间)
else: else:
......
# -*- coding:utf-8 -*-
# title :太阳地球月球模拟
# description :太阳地球月球模拟
# date :2024-03-20
# python_version :3.9
# ==============================================================================
from 引力世界 import 造物主
from 引力世界.模拟场景 import *
class 太阳系模拟(太阳系模拟场景):
def 配置(self, 配置项: 模拟配置):
配置项.地月距离倍数 = 20
配置项.中心天体 = self.地球
def 造物(self):
self.地球 = 造物主.造物(名称='地球', 缩放倍数=5.5e2)
self.月球 = 造物主.造物(名称='月球', 缩放倍数=5e2)
场景 = 太阳系模拟()
# 场景.摄像机看向(场景.地球)
场景.运行(运行时间='1982-09-24 00:00:00')
...@@ -6,38 +6,27 @@ ...@@ -6,38 +6,27 @@
# ============================================================================== # ==============================================================================
from 引力世界 import 造物主 from 引力世界 import 造物主
from 引力世界.模拟场景 import 太阳系模拟场景 from 引力世界.模拟场景 import *
class 太阳系模拟(太阳系模拟场景): class 太阳系模拟(太阳系模拟场景):
def 造物(self): def 配置(self, 配置项: 模拟配置):
太阳坐标, 太阳速度 = self.获取坐标和速度('太阳') 配置项.显示轨道 = 打开
地球坐标, 地球速度 = self.获取坐标和速度('地球') 配置项.地月距离倍数 = 20
月球坐标, 月球速度 = self.获取坐标和速度('月球') 配置项.中心天体 = self.太阳
水星坐标, 水星速度 = self.获取坐标和速度('水星')
金星坐标, 金星速度 = self.获取坐标和速度('金星')
火星坐标, 火星速度 = self.获取坐标和速度('火星')
木星坐标, 木星速度 = self.获取坐标和速度('木星')
土星坐标, 土星速度 = self.获取坐标和速度('土星')
天王星坐标, 天王星速度 = self.获取坐标和速度('天王星')
海王星坐标, 海王星速度 = self.获取坐标和速度('海王星')
self.太阳 = 造物主.造物(名称='太阳', 缩放大小=1e1)
self.地球 = 造物主.造物(名称='地球', 缩放大小=5.5e2)
self.月球 = 造物主.造物(名称='月球', 缩放大小=5e2)
self.水星 = 造物主.造物(名称='水星', 缩放大小=1e3) def 造物(self):
self.金星 = 造物主.造物(名称='金星', 缩放大小=5e2) self.太阳 = 造物主.造物(名称='太阳', 缩放倍数=1e1)
self.火星 = 造物主.造物(名称='火星', 缩放大小=5e2) self.地球 = 造物主.造物(名称='地球', 缩放倍数=5.5e2)
self.木星 = 造物主.造物(名称='木星', 缩放大小=5e2) self.月球 = 造物主.造物(名称='月球', 缩放倍数=5e2)
self.土星 = 造物主.造物(名称='土星', 缩放大小=5e2)
self.天王星 = 造物主.造物(名称='天王星', 缩放大小=5e2) self.水星 = 造物主.造物(名称='水星', 缩放倍数=1e3)
self.海王星 = 造物主.造物(名称='海王星', 缩放大小=5e2) self.金星 = 造物主.造物(名称='金星', 缩放倍数=5e2)
self.火星 = 造物主.造物(名称='火星', 缩放倍数=5e2)
self.木星 = 造物主.造物(名称='木星', 缩放倍数=5e2)
# print(self.太阳) self.土星 = 造物主.造物(名称='土星', 缩放倍数=5e2)
self.天王星 = 造物主.造物(名称='天王星', 缩放倍数=5e2)
self.海王星 = 造物主.造物(名称='海王星', 缩放倍数=5e2)
场景 = 太阳系模拟() 场景 = 太阳系模拟()
......
...@@ -15,9 +15,9 @@ class 太阳地球月球模拟(太阳系模拟场景): ...@@ -15,9 +15,9 @@ class 太阳地球月球模拟(太阳系模拟场景):
地球坐标, 地球速度 = self.获取坐标和速度('地球') 地球坐标, 地球速度 = self.获取坐标和速度('地球')
月球坐标, 月球速度 = self.获取坐标和速度('月球') 月球坐标, 月球速度 = self.获取坐标和速度('月球')
self.太阳 = 造物主.造物(名称='太阳', 初始位置=太阳坐标, 初始速度=太阳速度, 缩放大小=1e1) self.太阳 = 造物主.造物(名称='太阳', 初始位置=太阳坐标, 初始速度=太阳速度, 缩放倍数=1e1)
self.地球 = 造物主.造物(名称='地球', 初始位置=地球坐标, 初始速度=地球速度, 缩放大小=5.5e2) self.地球 = 造物主.造物(名称='地球', 初始位置=地球坐标, 初始速度=地球速度, 缩放倍数=5.5e2)
self.月球 = 造物主.造物(名称='月球', 初始位置=月球坐标, 初始速度=月球速度, 缩放大小=5e2) self.月球 = 造物主.造物(名称='月球', 初始位置=月球坐标, 初始速度=月球速度, 缩放倍数=5e2)
# print(self.太阳) # print(self.太阳)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册