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

Python超人-宇宙模拟器

上级 8a13f772
...@@ -137,8 +137,11 @@ def set_solar_system_celestial_position(bodies, dt, recalc_moon_pos): ...@@ -137,8 +137,11 @@ def set_solar_system_celestial_position(bodies, dt, recalc_moon_pos):
if isinstance(body, Asteroids): # 小行星带是模拟,不是正常的天体 if isinstance(body, Asteroids): # 小行星带是模拟,不是正常的天体
posvel = None posvel = None
else: else:
try:
# 获取天体的三维位置和矢量速度 # 获取天体的三维位置和矢量速度
posvel = get_body_posvel(body, dt) posvel = get_body_posvel(body, dt)
except Exception:
continue
if isinstance(body, Moon): # 如果是月球,为了更好的展示效果,需要对月球的位置重新计算 if isinstance(body, Moon): # 如果是月球,为了更好的展示效果,需要对月球的位置重新计算
moon_real_pos = [posvel[0].x.value * AU, posvel[0].z.value * AU, posvel[0].y.value * AU] moon_real_pos = [posvel[0].x.value * AU, posvel[0].z.value * AU, posvel[0].y.value * AU]
......
# -*- coding:utf-8 -*-
# title :哈雷彗星场景模拟
# description :哈雷彗星场景模拟
# author :Python超人
# date :2023-10-28
# link :https://gitcode.net/pythoncr/
# python_version :3.9
# ==============================================================================
import math
from astropy.time import Time
from ursina import camera, application
from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
from common.celestial_data_service import init_bodies_reality_pos_vels, get_reality_orbit_points, \
conv_to_astropy_time, set_solar_system_celestial_position
from common.color_utils import trail_color_brightest
from common.consts import SECONDS_PER_YEAR, AU
from common.func import calculate_distance
from objs import HalleComet
from sim_scenes.func import create_text_panel
from sim_scenes.func import ursina_run, create_sphere_sky
from simulators.ursina.entities.body_timer import TimeData
from simulators.ursina.ui.control_ui import ControlUI
from simulators.ursina.ursina_config import UrsinaConfig
from simulators.ursina.ursina_event import UrsinaEvent
from simulators.ursina.ursina_mesh import create_orbit_by_points
class HalleyCometSim:
"""
哈雷彗星场景模拟
"""
def __init__(self, start_time=None):
if start_time is None:
self.start_time = Time.now()
elif isinstance(start_time, str):
self.start_time = conv_to_astropy_time(start_time)
else:
self.start_time = start_time
# print("北京时间:", dt.to_datetime(timezone=pytz.timezone('Asia/Shanghai')))
def build_solar_system(self):
# region 构建太阳系
show_trail = False
self.sun = Sun(size_scale=0.6e2, show_trail=show_trail)
self.mercury = Mercury(size_scale=5e3, show_trail=show_trail)
self.venus = Venus(size_scale=5e3, show_trail=show_trail)
self.earth = Earth(size_scale=5e3, rotate_angle=0, show_trail=show_trail)
self.mars = Mars(size_scale=5e3, show_trail=show_trail)
self.jupiter = Jupiter(size_scale=2.5e3, show_trail=show_trail)
self.saturn = Saturn(size_scale=2.5e3, show_trail=show_trail)
self.uranus = Uranus(size_scale=6e3, show_trail=show_trail)
self.neptune = Neptune(size_scale=6e3, show_trail=show_trail)
self.pluto = Pluto(size_scale=1e5, show_trail=show_trail)
self.bodies = [
self.sun, # 太阳
self.mercury, # 水星
self.venus, # 金星
self.earth, # 地球
self.mars, # 火星
self.jupiter, # 木星
self.saturn, # 土星
self.uranus, # 天王星
self.neptune, # 海王星
# self.pluto, # 冥王星
]
self.mercury.orbital_days = 87.9691
self.venus.orbital_days = 224.701
self.earth.orbital_days = 365.24219
self.mars.orbital_days = 686.971
self.jupiter.orbital_days = 11.862 * 365.24219
self.saturn.orbital_days = 29.4571 * 365.24219
self.uranus.orbital_days = 84.0205 * 365.24219
self.neptune.orbital_days = 164.8 * 365.24219
# self.bodies = [
# self.sun, # 太阳
# self.mars, # 火星
# self.neptune, # 海王星
# ]
# endregion
trail_color_brightest(self.bodies)
for body in self.bodies[1:]:
body.init_velocity = [0, 0, 0]
body.set_ignore_gravity(True)
init_bodies_reality_pos_vels(self.bodies, self.start_time)
def build_halley_comet(self):
"""
创建哈雷彗星
@return:
"""
# 哈雷彗星的平均运行速度约为每小时 70,000 英里或每小时 126,000 公里 。(35公里/秒)
# 每76.1年环绕太阳一周的周期彗星
self.halley_comet = HalleComet( # size_scale=4e7,
size_scale=0.2e8,
# [3.34, 0, 10.7] 2060-4-
# [3.34, 0, 10.712] 2061-5
# [3.34, 0, 10.715] 2061-6-24
# [3.34, 0, 10.718] 2061-8
init_velocity=[3.34, 0, 10.718],
init_position=[0, 0.5 * AU, -10 * AU]) \
.set_light_disable(True)
self.bodies.append(self.halley_comet)
def build(self):
self.build_solar_system()
self.build_halley_comet()
def create_orbit_line(self, center_body, body):
orbital_days = int(math.ceil(body.orbital_days * 1.02))
points = get_reality_orbit_points(type(body).__name__.lower(), start_time=self.start_time, days=orbital_days,
segments=100)
# print(points)
orbit_line = create_orbit_by_points(center_body.position, points, line_color=body.trail_color)
return orbit_line
def on_ready(self):
"""
事件绑定后,模拟器运行前会触发
@return:
"""
# 创建天空
UrsinaConfig.trail_type = "line"
UrsinaConfig.trail_length = 91
# UrsinaConfig.trail_length = 1000
UrsinaConfig.trail_thickness_factor = 3
# camera.clip_plane_near = 0.1
camera.clip_plane_far = 1000000
create_sphere_sky(scale=200000)
# WorldGrid().draw_axises(10)
application.time_scale = 5
self.orbit_lines = []
for body in self.bodies[1:]:
if isinstance(body, HalleComet):
continue
orbit_line = self.create_orbit_line(self.sun, body)
self.orbit_lines.append(orbit_line)
self.text_panel = create_text_panel()
def show_clock(self, dt):
"""
显示时钟
@param dt: 时间 datetime
@return:
"""
# if self.clock_position_center:
# position, origin = (0, .25), (0, 0),
# else:
position, origin = (0.60, -0.465), (-0.5, 0.5),
ControlUI.current_ui.show_message(dt.strftime('%Y-%m-%d %H:%M:%S'),
position=position,
origin=origin,
font="verdana.ttf",
close_time=-1)
def set_bodies_position(self, time_data: TimeData):
"""
设置天体的位置(包含速度和加速度的信息)
@param time_data:
@return:
"""
t = self.start_time + time_data.total_days
set_solar_system_celestial_position(self.bodies, t, False)
def on_timer_changed(self, time_data):
"""
@param time_data:
@return:
"""
dt = time_data.get_datetime(str(self.start_time))
if hasattr(self, "halley_comet"):
# 哈雷彗星飞行的翻转效果
if self.halley_comet.planet.enabled:
self.halley_comet.planet.rotation_x += 0.1
self.halley_comet.planet.rotation_y += 1
d = calculate_distance(self.halley_comet.position, self.sun.position)
self.text_panel.text = "哈雷彗星距离太阳:%.3f AU" % (d / AU)
self.set_bodies_position(time_data)
self.show_clock(dt)
for i, orbit_line in enumerate(self.orbit_lines):
orbit_line.position = self.sun.planet.position
if __name__ == '__main__':
"""
哈雷彗星场景模拟
"""
# 近日点 0.586 AU
# 上次通过近日点: 1986年2月9日
# 下次通过近日点: 2061年7月28日
# 远日点 35.1 AU 2023年12月9日
sim = HalleyCometSim(start_time='1983-03-20 00:00:00')
sim.build()
# 订阅事件后,上面2个函数功能才会起作用
# 运行中,每时每刻都会触发 on_timer_changed
UrsinaEvent.on_timer_changed_subscription(sim.on_timer_changed)
# 运行前会触发 on_ready
UrsinaEvent.on_ready_subscription(sim.on_ready)
# 使用 ursina 查看的运行效果
# 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹
# position = 左-右+、上+下-、前+后-
ursina_run(sim.bodies,
SECONDS_PER_YEAR,
# position=(0, 2 * AU, -11 * AU),
position=(0, 0.5 * AU, -5 * AU),
cosmic_bg='',
show_trail=True,
# bg_music='sounds/no_glory.mp3',
show_camera_info=False,
show_control_info=False,
timer_enabled=True,
show_grid=False
)
...@@ -48,7 +48,7 @@ class Simulator(metaclass=ABCMeta): ...@@ -48,7 +48,7 @@ class Simulator(metaclass=ABCMeta):
for idx, view in enumerate(self.body_views): for idx, view in enumerate(self.body_views):
body = self.bodies_sys.bodies[idx] body = self.bodies_sys.bodies[idx]
body.dt = dt body.start_time = dt
view.appeared = body.appeared view.appeared = body.appeared
if not view.appeared: if not view.appeared:
view.disappear() view.disappear()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册