From b4b2d814dde2e33470c4dc23d9fcc1b431883626 Mon Sep 17 00:00:00 2001 From: march3 Date: Tue, 2 Apr 2024 19:28:40 +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 --- .../center_point_moving_sun_to_earth.py | 307 ++++++++++++++++++ sim_scenes/featured/earth_seasons_base.py | 44 +-- 2 files changed, 332 insertions(+), 19 deletions(-) create mode 100644 sim_scenes/featured/center_point_moving_sun_to_earth.py diff --git a/sim_scenes/featured/center_point_moving_sun_to_earth.py b/sim_scenes/featured/center_point_moving_sun_to_earth.py new file mode 100644 index 0000000..e30ea4e --- /dev/null +++ b/sim_scenes/featured/center_point_moving_sun_to_earth.py @@ -0,0 +1,307 @@ +# -*- coding:utf-8 -*- +# title :地球季节模拟(四季和24节气) +# description :地球季节模拟(四季和24节气) +# author :Python超人 +# date :2023-02-11 +# link :https://gitcode.net/pythoncr/ +# python_version :3.8 +# ============================================================================== +from ursina import camera, window, Text, color, Vec3, destroy, distance + +from bodies import * +from common.celestial_data_service import set_solar_system_celestial_position, conv_to_astropy_time, get_body_posvel, \ + get_reality_orbit_points +from common.consts import SECONDS_PER_DAY, AU +from sim_scenes.featured.earth_seasons_base import EarthSeasonsSimBase +from sim_scenes.func import ursina_run, camera_look_at, create_sphere_sky +from sim_scenes.science.earth_season_func import create_important_pos_earths, get_solar_terms_angles, create_earth +from sim_scenes.universe_sim_scenes import UniverseSimScenes +from simulators.ursina.entities.body_timer import TimeData, BodyTimer +from simulators.ursina.entities.world_grid import WorldGrid +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 +from simulators.ursina_simulator import UrsinaSimulator +import numpy as np +import math + + +class CenterPointMovingSimLive(EarthSeasonsSimBase): + def __init__(self): + super(CenterPointMovingSimLive, self).__init__(sun_transparent=False, + exit_at_total_days=3700, + delay_run=False, + look_at_earth=False, + earth_cn_size_factor=1.01, + earth_clouds_size_factor=1.015) + self.start_time = '2023-12-20 00:00:00' + self.sun.size_scale = 3e1 + self.earth.size_scale = 2e3 + self.earth_clouds.size_scale = self.earth.size_scale + self.earth_cn.size_scale = self.earth.size_scale + + self.moon = Moon(name="月球", size_scale=2e3, + rotation_speed=0.645 + ) # 月球 + self.mercury = Mercury(size_scale=2e3) + self.venus = Venus(name="金星", size_scale=2e3) + self.mars = Mars(size_scale=2e3) + self.jupiter = Jupiter(size_scale=0.2e3) + self.saturn = Saturn(size_scale=0.2e3) + self.uranus = Uranus(size_scale=2e3) + self.neptune = Neptune(size_scale=2e3) + + self.bodies += [self.moon, self.mercury, self.venus, self.mars, + self.jupiter, self.saturn, self.uranus, self.neptune + ] + + self.last_year = None + + for body in self.bodies: + if isinstance(body, Earth): + body.show_name = False + body.rotate_angle -= 22 + body.rotation_speed *= 2.5 + body.set_resolution(50) + + self.season_earths = [self.earth_1, self.earth_2, self.earth_3, self.earth_4] + self.planets = [] + + # self.jieqis = { + # "春分-2023": '2023-03-21 00:00:00', + # "夏至-2023": '2023-06-21 00:00:00', + # "秋分-2023": '2023-09-23 00:00:00', + # "冬至-2023": '2023-12-22 00:00:00', + # "春分-2024": '2024-03-20 00:00:00', + # "夏至-2024": '2024-06-21 00:00:00', + # "秋分-2024": '2024-09-22 00:00:00', + # "冬至-2024": '2024-12-21 00:00:00', + # "春分-2025": '2025-03-20 00:00:00', + # "夏至-2025": '2025-06-21 00:00:00', + # "秋分-2025": '2025-09-23 00:00:00', + # "冬至-2025": '2024-12-21 00:00:00', + # } + + font = "fonts/DroidSansFallback.ttf" + from common.func import find_file + self.font = find_file(f"{font}", UrsinaConfig.CN_FONT) + + for body in self.bodies: + if body not in self.season_earths: + self.planets.append(body) + else: + body.texture = "transparent.png" + body.show_trail = False + + self.bodies = self.planets + + def create_orbit_line(self, center_body, body, start_time, alpha=0.2): + if not hasattr(body, "orbital_days"): + return None + orbital_days = int(math.ceil(body.orbital_days)) + points = get_reality_orbit_points(type(body).__name__.lower(), + start_time=start_time, + days=orbital_days, + segments=100) + # print(points) + orbit_line = create_orbit_by_points(center_body.position, points, line_color=body.trail_color, + alpha=alpha,thickness=2) + return orbit_line + + def create_orbit_lines(self): + """ + 创建太阳系天体的真实轨迹(太阳和哈雷彗星除外) + @return: + """ + self.orbit_lines = [] + for body in self.planets: + if body is self.sun: + continue + if isinstance(body, Earth): + alpha = 0.5 + else: + alpha = 0.2 + start_time = conv_to_astropy_time(self.start_time) + orbit_line = self.create_orbit_line(self.sun, body, start_time, alpha=1.0) + if orbit_line is not None: + self.orbit_lines.append(orbit_line) + return self.orbit_lines + + def get_center_pos(self, dt, time_data): + ec = UrsinaSimulator.EditorCamera + d_sun = distance(ec.world_position, self.sun.planet.world_position) + + if not hasattr(self, "moving_factor"): + self.moving_factor = 1e-6 + self.phase_num = 1 + # elif time_data.total_days > 1500 and self.moving_factor < 1: + elif d_sun > 4500 and self.moving_factor < 1: + self.moving_factor += 0.01 + if self.phase_num == 1: + for b in self.bodies: + from simulators.ursina.entities.entity_utils import clear_trails + clear_trails(b.planet.main_entity) + UrsinaConfig.trail_type = "line" + # UrsinaConfig.trail_length = 91 + self.phase_num = 2 + + if self.moving_factor > 1: + self.moving_factor = 1 + if self.phase_num == 2: + for b in self.bodies: + from simulators.ursina.entities.entity_utils import clear_trails + clear_trails(b.planet.main_entity) + UrsinaConfig.trail_type = "curve_line" + UrsinaConfig.trail_length = 91 + self.phase_num = 3 + + e_posvel = get_body_posvel(self.earth, dt) + s_posvel = get_body_posvel(self.sun, dt) + + e_position = [e_posvel[0].x.value * AU, e_posvel[0].z.value * AU, e_posvel[0].y.value * AU] + s_position = [s_posvel[0].x.value * AU, s_posvel[0].z.value * AU, s_posvel[0].y.value * AU] + + center_pos = np.array(e_position) * self.moving_factor + return center_pos + + def on_ready(self): + super(CenterPointMovingSimLive, self).on_ready() + + UrsinaConfig.trail_type = "line" + # UrsinaConfig.trail_length = 91 + UrsinaConfig.trail_type = "curve_line" + UrsinaConfig.trail_length = 200 + # UrsinaConfig.trail_length = 1000 + UrsinaConfig.trail_thickness_factor = 2 + UrsinaConfig.trail_factor = 2 + + for body in self.bodies: + body.planet.trail_scale = 2 + + self.moon.planet.trail_scale = 1 + + # WorldGrid().draw_axises(10) + + camera.clip_plane_near = 1 + camera.look_at(Vec3(0, 0, 0)) + + destroy(self.earth_clouds.planet) + destroy(self.earth_cn.planet) + + self.earth.planet.name_text.enabled = False + + self.moon.planet.rotation_y = 180 + + self.show_title() + # camera.fov = 140 + + window.borderless = True + window.exit_button = False + # window.fullscreen = True + # window.position = (1920, 0) + # # 设置窗口的宽度和高度 + # window.size = (2340, 1079) + self.orbit_lines = self.create_orbit_lines() + + def hide_orbit_lines(self): + for orbit_line in self.orbit_lines: + destroy(orbit_line) + + def on_timer_changed(self, time_data: TimeData): + super(CenterPointMovingSimLive, self).on_timer_changed(time_data) + camera.rotation_z = -8 + dt = time_data.get_datetime(self.start_time) + self.set_bodies_position(time_data) + self.show_clock(dt) + + ec = UrsinaSimulator.EditorCamera + d_sun = distance(ec.world_position, self.sun.planet.world_position) + print("Sun distance:", d_sun) + + if self.phase_num == 1: + ec.world_position += ec.up * 2 * UrsinaConfig.run_speed_factor + ec.world_position += ec.back * 1 * UrsinaConfig.run_speed_factor + elif self.phase_num == 2: + self.hide_orbit_lines() + elif self.phase_num == 3: + pass + # ec.world_position -= ec.up * 2 * UrsinaConfig.run_speed_factor + # ec.world_position -= ec.back * 1 * UrsinaConfig.run_speed_factor + + # if d_sun > 4500: + + # ec.target_z -= 0.01 + # self.camera_around() + + def camera_around(self): + + ec = UrsinaSimulator.EditorCamera + ec.rotation_y -= 0.01 * UrsinaConfig.run_speed_factor # 每帧绕y轴旋转1度 + # print(self.earth.planet.world_position) + # print(self.earth.planet.position) + + def set_bodies_position(self, time_data: TimeData): + """ + 设置天体的位置(包含速度和加速度的信息) + @param time_data: + @return: + """ + dt = conv_to_astropy_time(self.start_time) + + t = dt + time_data.total_days + center_pos = self.get_center_pos(t, time_data) + set_solar_system_celestial_position(self.planets, t, True, recalc_moon_pos_scale=60, center_pos=center_pos) + + def exit_handle(self): + UrsinaEvent.on_reset() + return True + + def show_title(self): + aspect_ratio = window.aspect_ratio + position, origin = (-0.5 * aspect_ratio - 0.1, 0.48), (-0.05, 0.1) + position2, origin2 = (-0.5 * aspect_ratio - 0.1, 0.40), (-0.05, 0.1) + # text1 = Text(text="太阳视角:观察日食月食", color=color.white, scale=2.5, position=position, # (-0.98, 0.48), + # font=font) + ext1 = Text(text="太阳视角:2024年重要天象", color=color.white, scale=2.5, position=position, # (-0.98, 0.48), + font=self.font) + text2 = Text(text="(地球自转放慢10倍)", color=color.white, scale=1.5, position=position2, # (-0.98, 0.48), + font=self.font) + # 2024年重要天象 + + def show_clock(self, dt): + """ + 显示时钟 + @param dt: 时间 datetime + @return: + """ + # if self.clock_position_center: + # position, origin = (0, .25), (0, 0), + # else: + from ursina import window + aspect_ratio = window.aspect_ratio + position, origin = (0., 0.45), (0., 0.), + ControlUI.current_ui.show_message(dt.strftime('%Y-%m-%d'), + position=position, + origin=origin, + # font="verdana.ttf", + font="fonts/Digital-7Mono.TTF", + font_scale=2, + font_color=(0, 255, 0), + close_time=-1) + + +if __name__ == '__main__': + """ + 摄像机以太阳的视角看地球(四季和24节气) + """ + sim = CenterPointMovingSimLive() + sim.run( + dt=SECONDS_PER_DAY * 20, + # dt=SECONDS_PER_DAY * 3, + init_position=[0, -60 * AU, 30 * AU], + show_exit_button=False, + show_camera_info=False, + gravity_works=False, + show_trail=True, + show_control_info=False) diff --git a/sim_scenes/featured/earth_seasons_base.py b/sim_scenes/featured/earth_seasons_base.py index bc15325..411232a 100644 --- a/sim_scenes/featured/earth_seasons_base.py +++ b/sim_scenes/featured/earth_seasons_base.py @@ -83,23 +83,25 @@ class EarthSeasonsSimBase(UniverseSimScenes): def on_ready(self): # 将 4 个节气位置的地球进行旋转,让中国面对太阳 - self.earth_1.planet.rotation_y += 115 # 春分 - self.earth_2.planet.rotation_y += 15 # 夏至 - self.earth_3.planet.rotation_y -= 80 # 秋分 - self.earth_4.planet.rotation_y -= 145 # 冬至 + if hasattr(self.earth_1, "planet"): + self.earth_1.planet.rotation_y += 115 # 春分 + self.earth_1.planet.alpha = 0.2 + if hasattr(self.earth_2, "planet"): + self.earth_2.planet.rotation_y += 15 # 夏至 + self.earth_2.planet.alpha = 0.2 + if hasattr(self.earth_3, "planet"): + self.earth_3.planet.rotation_y -= 80 # 秋分 + self.earth_3.planet.alpha = 0.2 + if hasattr(self.earth_4, "planet"): + self.earth_4.planet.rotation_y -= 145 # 冬至 + self.earth_4.planet.alpha = 0.2 - self.earth.planet.rotation_y -= 185 # 一开始就正对太阳 self.earth_cn.planet.rotation_y -= 185 # 一开始就正对太阳 self.earth_clouds.planet.rotation_y -= 50 # 一开始就正对太阳 - self.earth_1.planet.alpha = 0.2 - self.earth_2.planet.alpha = 0.2 - self.earth_3.planet.alpha = 0.2 - self.earth_4.planet.alpha = 0.2 - if self.show_sphere_sky: - self.sky = create_sphere_sky(scale=8000) + self.sky = create_sphere_sky(scale=800000) self.sky.rotation_y = 100 self.sky.rotation_x = 20 self.sky.rotation_z = -65 @@ -110,17 +112,21 @@ class EarthSeasonsSimBase(UniverseSimScenes): text_scale = self.earth.name_text.scale * 2 self.earth.name_text.scale = text_scale - self.earth_1.name_text.scale = text_scale - self.earth_2.name_text.scale = text_scale - self.earth_3.name_text.scale = text_scale - self.earth_4.name_text.scale = text_scale + if hasattr(self.earth_1, "name_text"): + self.earth_1.name_text.scale = text_scale + self.earth_1.name_text.font = font + if hasattr(self.earth_2, "name_text"): + self.earth_2.name_text.scale = text_scale + self.earth_2.name_text.font = font + if hasattr(self.earth_3, "name_text"): + self.earth_3.name_text.scale = text_scale + self.earth_3.name_text.font = font + if hasattr(self.earth_4, "name_text"): + self.earth_4.name_text.scale = text_scale + self.earth_4.name_text.font = font self.earth.name_text.font = font self.earth.name_text.color = color.yellow - self.earth_1.name_text.font = font - self.earth_2.name_text.font = font - self.earth_3.name_text.font = font - self.earth_4.name_text.font = font if hasattr(self.earth_clouds, "name_text"): self.earth_clouds.name_text.enabled = False -- GitLab