diff --git a/sim_scenes/earth/parallel_earths.py b/sim_scenes/fiction/parallel_earths.py similarity index 60% rename from sim_scenes/earth/parallel_earths.py rename to sim_scenes/fiction/parallel_earths.py index fe3cee2f60fab0309039394ec1f664587c0ec582..4d93ef812de709ed7288e208f895270b8005493b 100644 --- a/sim_scenes/earth/parallel_earths.py +++ b/sim_scenes/fiction/parallel_earths.py @@ -7,7 +7,7 @@ # python_version :3.8 # ============================================================================== import random - +import sys from bodies import Earth, Moon from common.consts import SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH from sim_scenes.func import ursina_run, camera_look_at @@ -17,6 +17,10 @@ from simulators.ursina.ursina_event import UrsinaEvent def sim_show(): + """ + 使用模拟器(慢) + @return: + """ bodies = [] num = 2 r = 30000 @@ -39,54 +43,80 @@ def sim_show(): def ursina_show(): + """ + 直接使用 ursina 模拟,无需考虑万有引力(性能高) + @return: + """ from ursina import Ursina, Entity, color, EditorCamera, camera app = Ursina() + # 黑色背景的宇宙背景 SphereSky(texture='../../textures/bg_black.png') + + # 控制地球的数量,这里的 num 不代表数量 + # 地球数量 = num_x * num_y * num_z num = 5 num_x = num * 2 num_y = num num_z = num * 2 + # 控制运行的速度 + run_speed = 0.1 + # 控制地球之间的距离 r = 10 - def create_sphere(x, y, z): - sphere = Entity(model="sphere", texture='../../textures/earth2.jpg', + def create_earth(x, y, z): + """ + 在指定的三维坐标上创建地球 + @param x: + @param y: + @param z: + @return: + """ + earth = Entity(model="sphere", texture='../../textures/earth2.jpg', x=x * r * 2, y=y * r, z=z * r * 2, scale=3) - sphere.name = "%s:%s:%s" % (x, y, z) + earth.name = "%s:%s:%s" % (x, y, z) def update(): def inner(s, b): if not hasattr(s, "initial_y"): - s.rotation_y -= 1 - # print(s.name, s.rotation_y) + # 随机生成一个地球自转的初始量 + s.initial_y = random.randint(20, 200) / 100 * run_speed + # 地球进行自转 + s.rotation_y -= s.initial_y - return inner(sphere, y) + return inner(earth, y) - sphere.update = update + earth.update = update for x in range(-num_x, num_x): for y in range(-num_y, num_y): for z in range(-num_z, num_z): - create_sphere(x, y, z) + create_earth(x, y, z) ed = EditorCamera() camera.fov = 80 ed.position = [0, 0, r/2] - import sys + + # 控制摄像机三个维度的移动方向,值为 1 和 -1 camera.x_d = 1 camera.y_d = 1 camera.z_d = 1 def camera_update(): - camera.world_rotation_y += 0.05 - camera.world_rotation_z += 0.01 - # camera.x += ((random.randint(100, 300) - 100) / 3000) * camera.x_d - camera.y += ((random.randint(100, 300) - 100) / 5000) * camera.y_d - # camera.z += ((random.randint(100, 300) - 100) / 3000) * camera.z_d + # 更新摄像机位置和角度 + + # 控制摄像机旋转(以y、z轴进行旋转) + camera.world_rotation_y += 0.005 + camera.world_rotation_z += 0.001 + + # 控制摄像机来回移动(x为左右移动,y为上下移动) + camera.x += ((random.randint(100, 300) - 100) / 2500 * run_speed) * camera.x_d + camera.y += ((random.randint(100, 300) - 100) / 5000 * run_speed) * camera.y_d + # camera.z += ((random.randint(100, 300) - 100) / 3000 * run_speed) * camera.z_d range_val = 5 - # if camera.x > range_val: - # camera.x_d = -1 - # elif camera.x < -range_val: - # camera.x_d = 1 + if camera.x > range_val: + camera.x_d = -1 + elif camera.x < -range_val: + camera.x_d = 1 if camera.y > range_val: camera.y_d = -1 elif camera.y < -range_val: diff --git a/sim_scenes/science/sun_earth_moon.py b/sim_scenes/science/sun_earth_moon.py new file mode 100644 index 0000000000000000000000000000000000000000..c476ba76ad8b10154293dfedb22527d2019d27e3 --- /dev/null +++ b/sim_scenes/science/sun_earth_moon.py @@ -0,0 +1,97 @@ +# -*- coding:utf-8 -*- +# title :地月场景模拟(观看月相变化的过程) +# description :地月场景模拟(观看月相变化的过程) +# author :Python超人 +# date :2023-02-11 +# link :https://gitcode.net/pythoncr/ +# python_version :3.8 +# ============================================================================== +from bodies import Sun, Earth, Moon +from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY, SECONDS_PER_WEEK, SECONDS_PER_MONTH +from sim_scenes.func import mayavi_run, ursina_run, camera_look_at, set_camera_parent +from bodies.body import AU +from simulators.ursina.entities.body_timer import TimeData +from simulators.ursina.ursina_config import UrsinaConfig +from simulators.ursina.ursina_event import UrsinaEvent +import numpy as np + +if __name__ == '__main__': + """ + 地月场景模拟 + """ + # # 地球的Y方向初始速度 + # EARTH_INIT_VELOCITY = 0 # 0km/s + # sun = Sun(init_position=[0, 0, AU], size_scale=2e1) # 太阳放大 20 倍 + # # 忽略质量的引力 + # sun.ignore_mass = True + # + # # 观看月相变化的过程:分别是 新月、蛾眉月、上弦月、盈凸、满月、亏凸、下弦月、残月 + # # 参考:images/moon/月相变化过程.jpeg + # # TODO: 月球在摄像机的前方(从 “新月” 开始) + # moon_pos, moon_vel = [0, 0, 384400], [-(EARTH_INIT_VELOCITY + 1.03), 0, 0] + # # TODO: 月球在摄像机的右方(从 “下弦月” 开始),将会从右方出现 + # # moon_pos, moon_vel = [384400, 0, 0], [-EARTH_INIT_VELOCITY, 0, 1.03] + # # TODO: 月球在摄像机的左方(从 “上弦月” 开始) + # # moon_pos, moon_vel = [-384400, 0, 0], [EARTH_INIT_VELOCITY, 0, -1.03] + # moon = Moon(init_position=moon_pos, # 距地距离约: 363104 至 405696 km + # init_velocity=moon_vel, + # size_scale=2e1) # 月球放大 20 倍,距离保持不变 + # bodies = [ + # sun, + # Earth(init_position=[0, 0, 0], + # init_velocity=[0, EARTH_INIT_VELOCITY, 0], + # size_scale=1e1), # 地球放大 10 倍,距离保持不变 + # moon + # ] + + sun = Sun(name="太阳", size_scale=1e2) # 太阳放大 100 倍,距离保持不变 + earth = Earth(name="地球", size_scale=1.8e3) # 地球放大 1800 倍,距离保持不变 + earth_moon_d = 20000000 # 因为地球放大 1800 倍,为了较好的效果,地月距离要比实际大才行 + moon = Moon(name="月球", size_scale=3e3, # 月球球放大 3000 倍,为了较好的效果,地月距离要比实际大 + init_position=[earth_moon_d, 0, AU], + init_velocity=[0, 0, 0], + ignore_mass=True, + rotation_speed=0.4065, + # gravity_only_for_earth=True + )# .set_light_disable(True) + bodies = [ + sun, earth, moon + ] + + + def on_timer_changed(time_data: TimeData): + # 显示轨迹,并设置轨迹长度 + UrsinaConfig.show_trail = True + UrsinaConfig.trail_length = 500 + # 设置运行速度(加速10倍) + UrsinaConfig.run_speed_factor = 10 + + # 1个月有29.5天 + days_per_month = 29.5 + # 1天多少角度 + angle_per_day = 360 / days_per_month + # 当前天数的角度(度) + angle = time_data.total_days * angle_per_day + # 当前天数的角度(弧度) + angle = angle * np.pi / 180 + # 计算月亮的坐标(这里没有用到万有引力) + px = earth_moon_d * np.cos(angle) + pz = earth_moon_d * np.sin(angle) + moon.position = [earth.position[0] + px, 0, earth.position[2] + pz] + + + def on_ready(): + camera_look_at(sun) + + + # 订阅事件后,上面2个函数功能才会起作用 + # 运行前会触发 on_ready + UrsinaEvent.on_ready_subscription(on_ready) + # 运行中,每时每刻都会触发 on_timer_changed + UrsinaEvent.on_timer_changed_subscription(on_timer_changed) + + # 使用 ursina 查看的运行效果 + # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 + # position = 左-右+、上+下-、前+后- + # position=(0, 0, 0) 的位置是站在地球视角,可以观看月相变化的过程 + ursina_run(bodies, SECONDS_PER_DAY, position=(0, 4 * AU, 0), show_timer=True) diff --git a/sim_scenes/solar_system/solar_system_habitable_zone.py b/sim_scenes/solar_system/solar_system_habitable_zone.py index fe09705fe524912727de4243b843cdba7d813f6e..37736072fe5b3e7d3d48750e5ecbbf44acf50f51 100644 --- a/sim_scenes/solar_system/solar_system_habitable_zone.py +++ b/sim_scenes/solar_system/solar_system_habitable_zone.py @@ -20,7 +20,7 @@ import math if __name__ == '__main__': # 目前认为 太阳系 的宜居带范围是从距离太阳0.95个天文单位 (约1.42亿千米)到 2.4个天文单位(约3.59亿千米)的范围为宜居带, # 其宽度约为2.17亿千米, 按照这个标准,太阳系的宜居带中只有三个大型天体,分别是地球、 月球 以及火星(1.52天文单位)。 - sun = Sun(name="太阳", size_scale=0.5e2) # 太阳放大 80 倍,距离保持不变 + sun = Sun(name="太阳", size_scale=0.5e2) # 太阳放大 50 倍,距离保持不变 earth = Earth(name="地球", size_scale=1.5e3) # 地球放大 1500 倍,距离保持不变 earth_moon_d = 20000000 # 因为地球放大 1500 倍,为了较好的效果,地月距离要比实际大才行 moon = Moon(name="月球", size_scale=1.5e3,