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

Python超人-宇宙模拟器

上级 7387b622
......@@ -14,6 +14,7 @@ from astropy.coordinates import get_body_barycentric_posvel
from astropy.time import Time
from bodies import Body, Sun, Asteroids, Moon, Earth
from common.consts import G, AU, SECONDS_PER_DAY
from simulators.ursina.ursina_config import UrsinaConfig
def calc_solar_acceleration(body_or_pos, big_body):
......@@ -362,6 +363,24 @@ def init_bodies_pos_vels(bodies):
body.init_velocity = pos_vels['vel']
def get_reality_orbit_points(body_name, start_time=None, days=365, segments=100, scale_factor=1):
if start_time is None:
start_time = Time.now()
if days < segments:
s = 1
else:
s = int(round(days / segments))
points = []
for d in range(0, days, s):
dt = d + start_time
pos, vel = get_body_barycentric_posvel(body_name, dt)
x, y, z = pos.x.value * AU * scale_factor, pos.z.value * AU * scale_factor, pos.y.value * AU * scale_factor
points.append((x, y, z))
return points
def init_bodies_reality_pos_vels(bodies, dt=None):
from astropy.coordinates import solar_system_ephemeris as sse
if dt is None:
......@@ -391,13 +410,14 @@ def init_bodies_reality_pos_vels(bodies, dt=None):
# if pos_vels is None:
# continue
pos, vel = [pos.x.value * AU, pos.z.value * AU, pos.y.value * AU], \
[vel.x.value * AU / SECONDS_PER_DAY,
vel.z.value * AU / SECONDS_PER_DAY,
vel.y.value * AU / SECONDS_PER_DAY]
[vel.x.value * AU / SECONDS_PER_DAY,
vel.z.value * AU / SECONDS_PER_DAY,
vel.y.value * AU / SECONDS_PER_DAY]
body.init_position = pos
body.init_velocity = vel
if __name__ == '__main__':
from astropy.time import Time # 时间
......@@ -421,5 +441,5 @@ if __name__ == '__main__':
# # show_bodies_posvels(dt)
# bs = gen_real_pos_vel_bodies('sun,Mercury,Venus,Earth,Mars,Jupiter,Saturn,Uranus,Neptune',dt)
# print(bs)
print(get_init_pos_vels()['sun'])
print(get_reality_orbit_points('earth'))
# print(get_init_pos_vels()['sun'])
......@@ -11,7 +11,7 @@ import math
from ursina import camera, application
from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
from common.celestial_data_service import get_init_pos_vels, init_bodies_reality_pos_vels
from common.celestial_data_service import get_init_pos_vels, init_bodies_reality_pos_vels, get_reality_orbit_points
from common.color_utils import trail_color_brightest
from common.consts import SECONDS_PER_YEAR, AU
from common.func import calculate_distance
......@@ -21,7 +21,7 @@ from sim_scenes.func import ursina_run, create_sphere_sky
from simulators.ursina.entities.world_grid import WorldGrid
from simulators.ursina.ursina_config import UrsinaConfig
from simulators.ursina.ursina_event import UrsinaEvent
from simulators.ursina.ursina_mesh import create_orbit_line
from simulators.ursina.ursina_mesh import create_orbit_line, create_orbit_by_points
class HalleyCometSim:
......@@ -34,7 +34,7 @@ class HalleyCometSim:
def build_solar_system(self):
# region 构建太阳系
show_trail = True
show_trail = False
self.sun = Sun(size_scale=0.8e2, show_trail=show_trail)
self.mercury = Mercury(size_scale=5e3, show_trail=show_trail)
self.venus = Venus(size_scale=5e3, show_trail=show_trail)
......@@ -57,11 +57,20 @@ class HalleyCometSim:
self.neptune, # 海王星
# self.pluto, # 冥王星
]
self.bodies = [
self.sun, # 太阳
self.mars, # 火星
self.neptune, # 海王星
]
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)
init_bodies_reality_pos_vels(self.bodies)
......@@ -88,40 +97,48 @@ class HalleyCometSim:
def build(self):
self.build_solar_system()
# self.build_halley_comet()
self.build_halley_comet()
def calculate_rotation_angles(self, point1, point2):
def calculate_angles(self, point1, point2):
dx = point2.x - point1.x
dy = point2.y - point1.y
dz = point2.z - point1.z
roll = math.atan2(dy, dz)
pitch = math.atan2(dx, math.sqrt(dy ** 2 + dz ** 2))
yaw = math.atan2(math.sin(roll), math.cos(roll))
roll = math.degrees(math.atan2(dy, dz))
pitch = math.degrees(math.atan2(dx, math.sqrt(dy ** 2 + dz ** 2)))
yaw = math.degrees(math.atan2(math.sin(roll), math.cos(roll)))
return roll, pitch, yaw
def calculate_angles(self, point1, point2):
import numpy as np
# 计算向量AB
AB = point1 - point2
# 计算向量AB与x轴、y轴和z轴之间的夹角
angle_x = np.arctan2(AB.y, AB.x) * 180 / np.pi
angle_y = np.arctan2(AB.z, np.sqrt(AB.x ** 2 + AB.y ** 2)) * 180 / np.pi
angle_z = np.arctan2(np.sqrt(AB.x ** 2 + AB.y ** 2), AB.z) * 180 / np.pi
return angle_x, angle_y, angle_z
def calculate_angles(self, point1, point2):
# 计算向量AB
AB = point2 - point1
# 计算向量AB与x轴、y轴和z轴之间的夹角
angle_x = math.degrees(math.atan2(AB.z, AB.y))
angle_y = math.degrees(math.atan2(AB.z, AB.x))
angle_z = math.degrees(math.atan2(AB.y, AB.x))
return angle_x, angle_y, angle_z
#
# def calculate_angles(self, point1, point2):
# import numpy as np
# # 计算向量AB
# AB = point1 - point2
#
# # 计算向量AB与x轴、y轴和z轴之间的夹角
# angle_x = np.arctan2(AB.y, AB.x) * 180 / np.pi
# angle_y = np.arctan2(AB.z, np.sqrt(AB.x ** 2 + AB.y ** 2)) * 180 / np.pi
# angle_z = np.arctan2(np.sqrt(AB.x ** 2 + AB.y ** 2), AB.z) * 180 / np.pi
#
# return angle_x, angle_y, angle_z
# def calculate_angles(self, point1, point2):
#
# # 计算向量AB
# AB = point2 - point1
# # 计算向量AB与x轴、y轴和z轴之间的夹角
# angle_x = -math.degrees(-math.atan2(AB.z, AB.y))
# angle_y = -math.degrees(-math.atan2(AB.z, AB.x))
# angle_z = math.degrees(math.atan2(AB.y, AB.x))
# return angle_x, angle_y, angle_z
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(), 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):
"""
......@@ -132,16 +149,16 @@ class HalleyCometSim:
from ursina import scene
UrsinaConfig.trail_type = "line"
UrsinaConfig.trail_length = 91
UrsinaConfig.trail_length = 1000
# 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)
# WorldGrid().draw_axises(10)
application.time_scale = 5
self.orbit_lines = []
# self.orbit_lines = []
for body in self.bodies[1:]:
if isinstance(body, HalleComet):
continue
......@@ -160,28 +177,42 @@ body.position - sun.position
"""
orbit_line = create_orbit_line(self.sun, body)
angle_x, angle_y, angle_z = self.calculate_angles(self.sun.planet.position,body.planet.position)
# # 获取body相对于self.sun的位置向量
# relative_position = body.planet.position - self.sun.planet.position
#
# rotation_x = -math.degrees(
# math.atan2(relative_position.y, math.sqrt(relative_position.x ** 2 + relative_position.z ** 2)))
# rotation_y = math.degrees(math.atan2(relative_position.x, relative_position.z))
# # 计算旋转角度
# orbit_line.rotation_x = rotation_x + 90
# orbit_line.rotation_z = 0
# orbit_line.rotation_y = rotation_y + 120
orbit_line = self.create_orbit_line(self.sun, body)
# # orbit_line.enabled = False
# angle_x, angle_y, angle_z = self.calculate_angles(self.sun.planet.position, body.planet.position)
# # # 获取body相对于self.sun的位置向量
# # relative_position = body.planet.position - self.sun.planet.position
# #
# angle = math.atan2(relative_position.y, relative_position.x)
orbit_line.rotation_x = angle_x
orbit_line.rotation_y = angle_y # - 50
orbit_line.rotation_z = -angle_z
# # rotation_x = -math.degrees(
# # math.atan2(relative_position.y, math.sqrt(relative_position.x ** 2 + relative_position.z ** 2)))
# # rotation_y = math.degrees(math.atan2(relative_position.x, relative_position.z))
# # # 计算旋转角度
# # orbit_line.rotation_x = rotation_x + 90
# # orbit_line.rotation_z = 0
# # orbit_line.rotation_y = rotation_y + 120
# # #
# # angle = math.atan2(relative_position.y, relative_position.x)
# #
# # orbit_line.rotation_x = angle_x - 110 # angle_x+90 # angle_x # angle_x
# # orbit_line.rotation_y = angle_y # angle_y+90 # angle_y # - 50
# # orbit_line.rotation_z = angle_z - 90 # angle_z# angle_z # angle_z
#
# # print(body.name,angle_x,angle_y,angle_z)
# # print(body.name, orbit_line.rotation_x, orbit_line.rotation_y, orbit_line.rotation_z)
# # orbit_line.look_at(body.planet)
# # print(body.name, orbit_line.rotation_x, orbit_line.rotation_y, orbit_line.rotation_z)
# # 火星 -90.0 -90.0 0.0
# # 火星 -0.0 -0.0 0.0
# # 火星 113.2222958819701 137.6691000401162 -158.65250912389882
# # 火星 16.115840911865234 -132.33090209960938 104.18995666503906
#
# # 海王星 -90.0 -90.0 0.0
# # 海王星 -0.0 -0.0 0.0
# # 海王星 131.3906379192235 3.0188762268681826 -2.6611704409164667
# # 海王星 2.6574795246124268 93.01887512207031 -90.14009857177734
orbit_line.body = body
self.orbit_lines.append(orbit_line)
# orbit_line.body = body
# self.orbit_lines.append(orbit_line)
self.text_panel = create_text_panel()
......@@ -191,7 +222,7 @@ body.position - sun.position
@param time_data:
@return:
"""
if hasattr(self, "self.halley_comet"):
if hasattr(self, "halley_comet"):
# 哈雷彗星飞行的翻转效果
if self.halley_comet.planet.enabled:
self.halley_comet.planet.rotation_x += 0.1
......@@ -201,13 +232,13 @@ body.position - sun.position
d = calculate_distance(self.halley_comet.position, self.sun.position)
self.text_panel.text = "哈雷彗星距离太阳:%.3f AU" % (d / AU)
for i, orbit_line in enumerate(self.orbit_lines):
if i < 4:
adj_scale = False
else:
adj_scale = True
# 由于天体运行不是标准的圆形,则需要动态调整轨道的大小,保证轨道线始终在天体的中心位置
orbit_line.auto_adjust(adj_scale=adj_scale)
# for i, orbit_line in enumerate(self.orbit_lines):
# if i < 4:
# adj_scale = False
# else:
# adj_scale = True
# # 由于天体运行不是标准的圆形,则需要动态调整轨道的大小,保证轨道线始终在天体的中心位置
# orbit_line.auto_adjust(adj_scale=adj_scale)
if __name__ == '__main__':
......@@ -217,8 +248,6 @@ if __name__ == '__main__':
sim = HalleyCometSim()
sim.build()
# 订阅事件后,上面2个函数功能才会起作用
# 运行中,每时每刻都会触发 on_timer_changed
UrsinaEvent.on_timer_changed_subscription(sim.on_timer_changed)
......
此差异已折叠。
......@@ -17,6 +17,7 @@ import math
from common.color_utils import conv_to_vec4_color
from common.func import calculate_distance
from simulators.ursina.entities.circle_line import CircleLine
from simulators.ursina.entities.orbit_line import OrbitLine
from simulators.ursina.ursina_config import UrsinaConfig
......@@ -136,6 +137,22 @@ def create_circle_line(parent=None, radius=1, position=None, segments=100, thick
return circle_line
def create_orbit_line(parent=None, position=None, points=100, thickness=0.1, color=color.white, alpha=1):
if isinstance(color, tuple) or isinstance(color, list):
color = conv_to_vec4_color(color)
if alpha < 1:
color[3] = alpha
orbit_line = OrbitLine(position=position, points=points, thickness=thickness, color=color,
alpha=alpha)
orbit_line.set_light_off(True)
if parent is not None:
if hasattr(parent, "planet"):
parent = parent.planet
orbit_line.parent = parent
return orbit_line
def create_arrow_line(from_pos, to_pos, parent=None, label=None,
set_light_off=True, alpha=1.0, len_scale=0.5,
color=color.white, thickness=2,
......@@ -263,6 +280,32 @@ def create_orbit_line(center_obj, orbiting_obj, thickness=5, line_color=None, al
return orbit_line
def create_orbit_by_points(center_pos, orbiting_points, thickness=5, line_color=color.white, alpha=0.6,
scale_factor=None):
if isinstance(line_color, tuple) or isinstance(line_color, list):
line_color = conv_to_vec4_color(line_color)
if alpha < 1:
line_color[3] = alpha
if scale_factor is None:
scale_factor = UrsinaConfig.SCALE_FACTOR
if scale_factor != 1:
center_pos = center_pos * scale_factor
for i, point in enumerate(orbiting_points):
orbiting_points[i] = np.array([point[0] * scale_factor, point[1] * scale_factor, point[2] * scale_factor])
orbit_line = OrbitLine(points=orbiting_points, position=center_pos, thickness=thickness, color=line_color,
alpha=alpha)
orbit_line.set_light_off(True)
# if parent is not None:
# if hasattr(parent, "planet"):
# parent = parent.planet
# circle_line.parent = parent
return orbit_line
def create_orbit_line2(center_obj, orbiting_obj, line_color=color.white, alpha=0.3):
if isinstance(line_color, tuple) or isinstance(line_color, list):
line_color = color.rgba(line_color[0] / 255, line_color[1] / 255, line_color[2] / 255, alpha)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册