From fbf22d4b6de136520492055544d7be3f5a1c8513 Mon Sep 17 00:00:00 2001 From: march3 Date: Wed, 3 May 2023 11:00:22 +0800 Subject: [PATCH] =?UTF-8?q?Python=E8=B6=85=E4=BA=BA-=E5=AE=87=E5=AE=99?= =?UTF-8?q?=E6=A8=A1=E6=8B=9F=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- sim_scenes/funny/dancing_with_jupiter.py | 30 ++++--- sim_scenes/science/lagrangian_points_1.py | 99 +++++++++-------------- sim_scenes/science/lagrangian_points_2.py | 75 ++++++----------- simulators/ursina/ursina_mesh.py | 58 ++++++++++++- 4 files changed, 138 insertions(+), 124 deletions(-) diff --git a/sim_scenes/funny/dancing_with_jupiter.py b/sim_scenes/funny/dancing_with_jupiter.py index 970f2d5..9387afb 100644 --- a/sim_scenes/funny/dancing_with_jupiter.py +++ b/sim_scenes/funny/dancing_with_jupiter.py @@ -8,28 +8,29 @@ # ============================================================================== from bodies import Sun, Earth, Jupiter, Mars, Venus from common.consts import SECONDS_PER_YEAR, SECONDS_PER_MONTH, AU -from sim_scenes.func import mayavi_run, ursina_run, camera_look_at +from sim_scenes.func import ursina_run, camera_look_at from simulators.ursina.entities.body_timer import TimeData from simulators.ursina.ursina_config import UrsinaConfig from simulators.ursina.ursina_event import UrsinaEvent -from simulators.ursina.ursina_mesh import create_line -from ursina import color +from simulators.ursina.ursina_mesh import create_connecting_line if __name__ == '__main__': """ 与木星跳舞 """ # 选择舞者 - Dancer = Earth # 舞者为地球 - Dancer = Venus # 舞者为金星 - Dancer = Mars # 舞者为火星 + # Dancer = Earth # 舞者为地球 + # Dancer = Mars # 舞者为火星 - bodies = [ - Sun(size_scale=0.8e2), # 太阳放大 80 倍 - Dancer(size_scale=5e3), # 舞者放大 5000 倍 - Jupiter(size_scale=5e2), # 木星放大 500 倍 - ] - sun, dancer, jupiter = bodies[0], bodies[1], bodies[2] + sun = Sun(size_scale=0.8e2) # 太阳放大 80 倍 + jupiter = Jupiter(size_scale=5e2) # 木星放大 500 倍 + bodies = [sun, jupiter] + + dancers = [Earth(size_scale=5e3), Mars(size_scale=5e3)] # 两个舞者放大 5000 倍 + dancers = [Earth(size_scale=5e3)] # 舞者为地球,放大 5000 倍 + dancers = [Mars(size_scale=5e3)] # 舞者为火星,放大 5000 倍 + + bodies = bodies + dancers def on_ready(): @@ -41,7 +42,10 @@ if __name__ == '__main__': def on_timer_changed(time_data: TimeData): if int(time_data.total_days) % 10 == 0: - create_line(from_pos=jupiter.planet.position, to_pos=dancer.planet.main_entity.position, color=color.white) + for dancer in dancers: + line_color = dancer.color + line_color = (255, 255, 100) + create_connecting_line(jupiter, dancer, line_color=line_color) # 订阅事件后,上面2个函数功能才会起作用 diff --git a/sim_scenes/science/lagrangian_points_1.py b/sim_scenes/science/lagrangian_points_1.py index 723c08a..d72e02c 100644 --- a/sim_scenes/science/lagrangian_points_1.py +++ b/sim_scenes/science/lagrangian_points_1.py @@ -1,39 +1,28 @@ # -*- coding:utf-8 -*- -# title :拉格朗日点模拟 -# description :拉格朗日点模拟 +# title :地月拉格朗日点模拟 +# description :地月拉格朗日点模拟(理想的拉格朗日点位置) # author :Python超人 -# date :2023-02-11 +# date :2023-05-01 # link :https://gitcode.net/pythoncr/ # python_version :3.8 # ============================================================================== -from bodies import Body, Sun, Earth, Moon -from objs import Obj, Satellite, Satellite2 +from bodies import Earth, Moon +from objs import Satellite, Satellite2 from common.consts import SECONDS_PER_HOUR, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH from sim_scenes.func import ursina_run, camera_look_at from simulators.ursina.entities.body_timer import TimeData -from simulators.ursina.entities.entity_utils import create_directional_light from simulators.ursina.ursina_event import UrsinaEvent -from simulators.ursina.ursina_mesh import create_line +from simulators.ursina.ursina_mesh import create_connecting_lines import math -bodies = [ - Earth(init_position=[0, 0, 0], texture="earth_hd.jpg", - init_velocity=[0, 0, 0], size_scale=0.5e1), # 地球放大 5 倍,距离保持不变 - Moon(init_position=[0, 0, 363104], # 距地距离约: 363104 至 405696 km - init_velocity=[-1.054152222, 0, 0], size_scale=1e1) # 月球放大 10 倍,距离保持不变 -] - -earth = bodies[0] -moon = bodies[1] - def get_lagrangian_points(m1, m2, r): """ - - @param m1: 大质量 - @param m2: 小质量 - @param r: 半径 - @return: + 用于计算理想的拉格朗日点 + @param m1: 大天体的质量 + @param m2: 小天体的质量 + @param r: 小天体绕大天体的半径 + @return: 返回拉格朗日点 L1, L2, L3, L4, L5 的坐标 """ a = m2 / (m1 + m2) l1 = (0, 0, r * (1 - pow(a / 3, 1 / 3))) @@ -45,65 +34,53 @@ def get_lagrangian_points(m1, m2, r): return l1, l2, l3, l4, l5 -# 计算地月拉格朗日点 -L1_p, L2_p, L3_p, L4_p, L5_p = get_lagrangian_points(earth.mass, moon.mass, 363104) +# 月球绕地球的半径 +R = 363104 +# 创建地月 +earth = Earth(init_position=[0, 0, 0], texture="earth_hd.jpg", + init_velocity=[0, 0, 0], size_scale=0.8e1) # 地球放大 8 倍,地月距离保持不变 +moon = Moon(init_position=[0, 0, R], # 距地距离约: 363104 至 405696 km + init_velocity=[-1.054152222, 0, 0], size_scale=1.2e1) # 月球放大 12 倍,地月距离保持不变 + +# 获取地月拉格朗日点(理想数据) +L1_p, L2_p, L3_p, L4_p, L5_p = get_lagrangian_points(earth.mass, moon.mass, R) +# region 在拉格朗日点 L1, L2, L3, L4, L5 上创建卫星 + def create_satellite(name, init_position, init_velocity): """ - 在 L1, L2, L3, L4, L5 创建卫星 - @param name: - @param init_position: - @param init_velocity: + 在指定位置创建卫星,并给予卫星一个初速度 + @param name: 卫星名称 + @param init_position: 初始位置 + @param init_velocity: 初始速度 @return: """ - satellite = Satellite(name=name, mass=1.4e10, size_scale=4e3, color=(255, 200, 0), + satellite = Satellite(name=name, mass=1.4e10, size_scale=2e3, color=(255, 200, 0), init_position=init_position, init_velocity=init_velocity, gravity_only_for=[earth, moon]) return satellite -# L1:point=[0,0,308536.70059015526] velocity=[-0.890136271716, 0, 0] +# 在 L1 位置上创建一个具有初速度的卫星 satelliteL1 = create_satellite(name=f'卫星L1', init_position=L1_p, init_velocity=[-0.890136271716, 0, 0]) -bodies.append(satelliteL1) - -# L2:point=[0,0, 423338.5083198447] velocity=[-1.24, 0, 0] +# 在 L2 位置上创建一个具有初速度的卫星 satelliteL2 = create_satellite(name=f'卫星L2', init_position=L2_p, init_velocity=[-1.24, 0, 0]) -bodies.append(satelliteL2) - vel_L345 = 1.048 -# L3:point=[0,0, -364941.3043941873] velocity=[1.039 , 0, 0] +# 在 L3 位置上创建一个具有初速度的卫星 satelliteL3 = create_satellite(name=f'卫星L3', init_position=L3_p, init_velocity=[vel_L345, 0, 0]) -bodies.append(satelliteL3) - -# L4:point=[0,0, 177142.46945395062] velocity=[1.039 , 0, 0] +# 在 L4 位置上创建一个具有初速度的卫星 satelliteL4 = create_satellite(name=f'卫星L4', init_position=L4_p, init_velocity=[-math.sin(math.pi * 30 / 180) * vel_L345, 0, math.cos(math.pi * 30 / 180) * vel_L345]) -bodies.append(satelliteL4) - -# L5:point=[0,0, 177142.46945395062] velocity=[1.039 , 0, 0] +# 在 L5 位置上创建一个具有初速度的卫星 satelliteL5 = create_satellite(name=f'卫星L5', init_position=L5_p, init_velocity=[-math.sin(math.pi * 30 / 180) * vel_L345, 0, -math.cos(math.pi * 30 / 180) * vel_L345]) -bodies.append(satelliteL5) - - -def create_connecting_lines(satellites_list): - """ - 创建连接线(将卫星列表用线条连接起来) - @param satellites_list: - @return: - """ - lines = [] - for satellites in satellites_list: - line = create_line(from_pos=satellites[0].planet.position, - to_pos=satellites[1].planet.position, alpha=0.3) - lines.append(line) - return lines +# endregion if __name__ == '__main__': @@ -114,12 +91,12 @@ if __name__ == '__main__': def on_timer_changed(time_data: TimeData): - # 删除和创建连接线 + # 实时删除和创建连接线 from ursina import destroy if hasattr(earth, "lines"): for line in earth.lines: destroy(line) - + # 创建连接线(将卫星列表用线条连接起来) earth.lines = create_connecting_lines([ [satelliteL2, satelliteL3], [satelliteL4, satelliteL1], [satelliteL5, satelliteL1], @@ -134,11 +111,13 @@ if __name__ == '__main__': # 运行中,每时每刻都会触发 on_timer_changed UrsinaEvent.on_timer_changed_subscription(on_timer_changed) + bodies = [earth, moon, + satelliteL1, satelliteL2, satelliteL3, satelliteL4, satelliteL5] + # 使用 ursina 查看的运行效果 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # position = 左-右+、上+下-、前+后- ursina_run(bodies, SECONDS_PER_HOUR * 5, - # position=(-300000, 1500000, -100), position=(0, 1500000, 0), show_timer=True, # show_trail=True diff --git a/sim_scenes/science/lagrangian_points_2.py b/sim_scenes/science/lagrangian_points_2.py index 199246f..8c9d95c 100644 --- a/sim_scenes/science/lagrangian_points_2.py +++ b/sim_scenes/science/lagrangian_points_2.py @@ -1,35 +1,30 @@ # -*- coding:utf-8 -*- -# title :拉格朗日点模拟 -# description :拉格朗日点模拟 +# title :地月拉格朗日点模拟 +# description :地月拉格朗日点模拟(对理想的位置进行了调整) # author :Python超人 -# date :2023-02-11 +# date :2023-05-01 # link :https://gitcode.net/pythoncr/ # python_version :3.8 # ============================================================================== -from bodies import Body, Sun, Earth, Moon -from objs import Obj, Satellite, Satellite2 +from bodies import Earth, Moon +from objs import Satellite, Satellite2 from common.consts import SECONDS_PER_HOUR, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH from sim_scenes.func import ursina_run, camera_look_at from simulators.ursina.entities.body_timer import TimeData -from simulators.ursina.entities.entity_utils import create_directional_light from simulators.ursina.ursina_event import UrsinaEvent -from simulators.ursina.ursina_mesh import create_line +from simulators.ursina.ursina_mesh import create_connecting_lines import math -bodies = [ - Earth(init_position=[0, 0, 0], texture="earth_hd.jpg", - init_velocity=[0, 0, 0], size_scale=0.5e1), # 地球放大 5 倍,距离保持不变 - Moon(init_position=[0, 0, 363104], # 距地距离约: 363104 至 405696 km - init_velocity=[-1.054152222, 0, 0], size_scale=1e1) # 月球放大 10 倍,距离保持不变 -] +# 月球绕地球的半径 +R = 363104 +# 创建地月 +earth = Earth(init_position=[0, 0, 0], texture="earth_hd.jpg", + init_velocity=[0, 0, 0], size_scale=0.8e1) # 地球放大 8 倍,地月距离保持不变 +moon = Moon(init_position=[0, 0, R], # 距地距离约: 363104 至 405696 km + init_velocity=[-1.054152222, 0, 0], size_scale=1.2e1) # 月球放大 12 倍,地月距离保持不变 -earth = bodies[0] -moon = bodies[1] - - -# 计算地月拉格朗日点 -# L1_p, L2_p, L3_p, L4_p, L5_p = get_lagrangian_points(earth.mass, moon.mass, 363104) +# region 在拉格朗日点 L1, L2, L3, L4, L5 (对理想的位置进行了调整)上创建卫星 def create_satellite(name, init_position, init_velocity): """ 在 L1, L2, L3, L4, L5 创建卫星 @@ -38,53 +33,31 @@ def create_satellite(name, init_position, init_velocity): @param init_velocity: @return: """ - satellite = Satellite(name=name, mass=1.4e10, size_scale=4e3, color=(255, 200, 0), + satellite = Satellite(name=name, mass=1.4e10, size_scale=2e3, color=(255, 200, 0), init_position=init_position, init_velocity=init_velocity, gravity_only_for=[earth, moon]) return satellite -# L1:point=[0,0,308536.70059015526] velocity=[-0.890136271716, 0, 0] +# 在 L1 位置上创建一个具有初速度的卫星 satelliteL1 = create_satellite(name=f'卫星L1', init_position=[0, 0, 308536.672], init_velocity=[-0.890136271716, 0, 0]) -bodies.append(satelliteL1) - -# L2:point=[0,0, 423338.5083198447] velocity=[-1.24, 0, 0] +# 在 L2 位置上创建一个具有初速度的卫星 satelliteL2 = create_satellite(name=f'卫星L2', init_position=[0, 0, 423338.5083198447], init_velocity=[-1.24, 0, 0]) -bodies.append(satelliteL2) - vel_L345 = 1.048 -# L3:point=[0,0, -364941.3043941873] velocity=[1.039 , 0, 0] +# 在 L3 位置上创建一个具有初速度的卫星 satelliteL3 = create_satellite(name=f'卫星L3', init_position=[0, 0, -364941.3043941873], init_velocity=[vel_L345, 0, 0]) -bodies.append(satelliteL3) - -# L4:point=[0,0, 177142.46945395062] velocity=[1.039 , 0, 0] +# 在 L4 位置上创建一个具有初速度的卫星 satelliteL4 = create_satellite(name=f'卫星L4', init_position=[314457.2882157448, 0, 177142.46945395062], init_velocity=[-math.sin(math.pi * 30 / 180) * vel_L345, 0, math.cos(math.pi * 30 / 180) * vel_L345]) -bodies.append(satelliteL4) - -# L5:point=[0,0, 177142.46945395062] velocity=[1.039 , 0, 0] +# 在 L5 位置上创建一个具有初速度的卫星 satelliteL5 = create_satellite(name=f'卫星L5', init_position=[-314457.2882157448, 0, 177142.46945395062], init_velocity=[-math.sin(math.pi * 30 / 180) * vel_L345, 0, -math.cos(math.pi * 30 / 180) * vel_L345]) -bodies.append(satelliteL5) - - -def create_connecting_lines(satellites_list): - """ - 创建连接线(将卫星列表用线条连接起来) - @param satellites_list: - @return: - """ - lines = [] - for satellites in satellites_list: - line = create_line(from_pos=satellites[0].planet.position, - to_pos=satellites[1].planet.position, alpha=0.3) - lines.append(line) - return lines +# endregion if __name__ == '__main__': @@ -95,12 +68,12 @@ if __name__ == '__main__': def on_timer_changed(time_data: TimeData): - # 删除和创建连接线 + # 实时删除和创建连接线 from ursina import destroy if hasattr(earth, "lines"): for line in earth.lines: destroy(line) - + # 创建连接线(将卫星列表用线条连接起来) earth.lines = create_connecting_lines([ [satelliteL2, satelliteL3], [satelliteL4, satelliteL1], [satelliteL5, satelliteL1], @@ -115,6 +88,8 @@ if __name__ == '__main__': # 运行中,每时每刻都会触发 on_timer_changed UrsinaEvent.on_timer_changed_subscription(on_timer_changed) + bodies = [earth, moon, + satelliteL1, satelliteL2, satelliteL3, satelliteL4, satelliteL5] # 使用 ursina 查看的运行效果 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # position = 左-右+、上+下-、前+后- diff --git a/simulators/ursina/ursina_mesh.py b/simulators/ursina/ursina_mesh.py index d61e1c9..644512d 100644 --- a/simulators/ursina/ursina_mesh.py +++ b/simulators/ursina/ursina_mesh.py @@ -98,7 +98,7 @@ def create_label(parent, label, pos, color, scale=50, alpha=1.0): return text -def create_line(from_pos, to_pos, parent=None, alpha=1.0, len_scale=1,set_light_off=True, +def create_line(from_pos, to_pos, parent=None, alpha=1.0, len_scale=1, set_light_off=True, color=color.white, thickness=1): line = Entity(parent=parent, model=Mesh(vertices=(from_pos * len_scale, to_pos * len_scale), @@ -154,6 +154,62 @@ def create_arrow_line(from_pos, to_pos, parent=None, label=None, return arrow, line, text +def get_obj_planet_position(obj): + """ + 获取对象的位置坐标 + @param obj: + @return: + """ + if hasattr(obj, "planet"): + if hasattr(obj.planet, "main_entity"): + pos1 = obj.planet.main_entity.position + else: + pos1 = obj.planet.position + else: + pos1 = obj.position + return pos1 + + +def create_connecting_line(obj1, obj2, line_color=color.white, alpha=0.3): + """ + 创建物体之间的连接线 + @param obj1: + @param obj2: + @param line_color: 线条颜色 + @param alpha: 透明度(默认0.3) + @return: + """ + 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) + pos1 = get_obj_planet_position(obj1) + pos2 = get_obj_planet_position(obj2) + line = create_line(from_pos=pos1, color=line_color, to_pos=pos2, alpha=alpha) + return line + + +def create_connecting_lines(objs_list, line_color=color.white, alpha=0.3): + """ + 创建物体之间的连接线。(多条线) + 样例如下:
+ create_connecting_lines([ + [obj1, obj2], + [obj3, obj4], + ...... + ]) + @param objs_list: + @param color: 线条颜色 + @param alpha: 透明度(默认0.3) + @return: 被创建的连接线列表 + """ + 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] / 254, alpha) + lines = [] + for objs in objs_list: + line = create_connecting_line(objs[0], objs[1], line_color=line_color, alpha=alpha) + lines.append(line) + return lines + + def create_pyramid(): # 创建金字塔的顶点 verts = [ -- GitLab