From 4d74c8dae88c77192b8a59893f7a54adfbd016cb Mon Sep 17 00:00:00 2001 From: march3 Date: Sun, 7 Apr 2024 13:44:44 +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_earth_to_sun.py | 342 ++++++++++++++++++ sim_scenes/featured/earth_seasons_base.py | 5 +- sim_scenes/featured/earth_seasons_live.py | 8 +- 3 files changed, 350 insertions(+), 5 deletions(-) create mode 100644 sim_scenes/featured/center_point_moving_earth_to_sun.py diff --git a/sim_scenes/featured/center_point_moving_earth_to_sun.py b/sim_scenes/featured/center_point_moving_earth_to_sun.py new file mode 100644 index 0000000..995da3d --- /dev/null +++ b/sim_scenes/featured/center_point_moving_earth_to_sun.py @@ -0,0 +1,342 @@ +# -*- 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 common.func import calculate_distance +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=37000, + 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 = 5.5e1 + 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.6e3) + self.saturn = Saturn(size_scale=0.6e3) + self.uranus = Uranus(size_scale=1.5e3) + self.neptune = Neptune(size_scale=1.5e3) + + 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 = [] + + 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=4) + 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=0.8) + if orbit_line is not None: + self.orbit_lines.append(orbit_line) + return self.orbit_lines + + def count_days(self, key, time_data, days): + key = "k_" + str(key) + days_counter_key = f"{key}_days_counter" + days_counter_init_val_key = f"{key}_days_counter_init_val" + if not hasattr(self, days_counter_key): + setattr(self, days_counter_key, 0) + setattr(self, days_counter_init_val_key, time_data.total_days) + else: + d = time_data.total_days - getattr(self, days_counter_init_val_key) + setattr(self, days_counter_key, d) + + rd = getattr(self, days_counter_key) + if rd >= days: + delattr(self, days_counter_key) + delattr(self, days_counter_init_val_key) + return True + return False + + def get_center_pos(self, dt, time_data): + ec = UrsinaSimulator.EditorCamera + d_sun = self.get_distance_sun() + + 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 < 7 or self.phase_num == 2) and self.moving_factor < 1: + self.moving_factor += 0.01 * UrsinaConfig.run_speed_factor + 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 = 500 + + 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() + + self.sky.rotation_y = 20 + self.sky.rotation_x = -290 + self.sky.rotation_z = -95 + + UrsinaConfig.trail_type = "line" + # UrsinaConfig.trail_length = 91 + UrsinaConfig.trail_type = "curve_line" + UrsinaConfig.trail_length = 180 + # UrsinaConfig.trail_length = 1000 + UrsinaConfig.trail_thickness_factor = 4 + UrsinaConfig.trail_alpha = 0.8 + UrsinaConfig.trail_factor = 4 + + for body in self.bodies: + body.planet.trail_scale = 0.5 + + self.moon.planet.trail_scale = 0.5 + + # WorldGrid().draw_axises(100) + + 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 + # self.window_size() + self.orbit_lines = self.create_orbit_lines() + + # def window_size(self): + # # window.fullscreen = True + # # window.position = (1920, 0) + # # self.set_window_size() + # # # # 设置窗口的宽度和高度 + # # window.size = (2340, 1079) + # # window.position = (0, 0) + # self.set_window_size((2376, 1080),fullscreen=True) + + 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) + + _dt = (time_data.dt / 28788) + + # print("total_days:", time_data.total_days) + if time_data.total_days > 2800: + exit() + + ec = UrsinaSimulator.EditorCamera + + if self.phase_num == 1: + ec.world_position += ec.up * 2 * _dt * UrsinaConfig.run_speed_factor # 前进 + ec.world_position += ec.back * 1 * _dt * UrsinaConfig.run_speed_factor # 下 + elif self.phase_num == 2: + self.hide_orbit_lines() + elif self.phase_num == 3: + if self.count_days(self.phase_num, time_data, 370): + self.phase_num = 4 + elif self.phase_num == 4: + ec.world_position -= ec.up * 2* _dt * UrsinaConfig.run_speed_factor # 后退 + ec.world_position -= ec.back * 1.4* _dt * UrsinaConfig.run_speed_factor # 下(快一点) + ec.world_position += ec.right * 0.8 * _dt* UrsinaConfig.run_speed_factor # 左 + d_sun = self.get_distance_sun() + # print("d_sun:", d_sun) + if d_sun > 48: + self.phase_num = 5 + # elif self.phase_num == 5: + # ec.world_position -= ec.back * 1.4* _dt * UrsinaConfig.run_speed_factor # 下 + # ec.world_position += ec.right * 0.7* _dt * UrsinaConfig.run_speed_factor # 左 + # pos = camera.world_position + # if pos[2] > 2000: + # self.phase_num = 6 + # print("pos:", pos) + + # if d_sun > 4500: + + # ec.target_z -= 0.01 + # self.camera_around() + + def get_distance_sun(self): + d_sun = distance(camera.world_position, self.sun.planet.world_position) + return round(d_sun / UrsinaConfig.SCALE_FACTOR / AU, 4) + + 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): + return + aspect_ratio = window.aspect_ratio + position, origin = (-0.5 * aspect_ratio + 0.02, 0.48), (-0.05, 0.1) + text1 = Text(text="地球为中心的轨道是这样", color=color.white, scale=2, position=position, # (-0.98, 0.48), + font=self.font) + + + def show_clock(self, dt): + """ + 显示时钟 + @param dt: 时间 datetime + @return: + """ + # if self.clock_position_center: + # position, origin = (0, .25), (0, 0), + # else: + return + 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 * 15, + # 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 411232a..7e3fa98 100644 --- a/sim_scenes/featured/earth_seasons_base.py +++ b/sim_scenes/featured/earth_seasons_base.py @@ -26,7 +26,7 @@ class EarthSeasonsSimBase(UniverseSimScenes): look_at_earth=True, show_china=True, exit_at_total_days=375, - earth_cn_size_factor=1.001, + earth_cn_size_factor=1.005, earth_clouds_size_factor=1.01, show_name=True, delay_run=True): @@ -75,7 +75,7 @@ class EarthSeasonsSimBase(UniverseSimScenes): def create_earth(self, earth_cn_size_factor, earth_clouds_size_factor): return create_earth(earth_texture="earth-huge.jpg", - earth_cn_texture="earth-huge-cn.png", + earth_cn_texture="earth-huge-cn-flag.png", with_clouds=True, earth_rotation_speed=0.7, clouds_rotation_speed=0.78, earth_cn_size_factor=earth_cn_size_factor, @@ -97,6 +97,7 @@ class EarthSeasonsSimBase(UniverseSimScenes): self.earth_4.planet.alpha = 0.2 self.earth_cn.planet.rotation_y -= 185 # 一开始就正对太阳 + self.earth.planet.rotation_y -= 185 # 一开始就正对太阳 self.earth_clouds.planet.rotation_y -= 50 # 一开始就正对太阳 diff --git a/sim_scenes/featured/earth_seasons_live.py b/sim_scenes/featured/earth_seasons_live.py index 481d313..db5c72f 100644 --- a/sim_scenes/featured/earth_seasons_live.py +++ b/sim_scenes/featured/earth_seasons_live.py @@ -10,7 +10,7 @@ from ursina import camera, window, Text, color, Vec3, destroy from bodies import * from common.celestial_data_service import set_solar_system_celestial_position, conv_to_astropy_time, get_body_posvel -from common.consts import SECONDS_PER_DAY, AU +from common.consts import * 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 @@ -32,6 +32,7 @@ class EarthSeasonsSimLive(EarthSeasonsSimBase): earth_cn_size_factor=1.01, earth_clouds_size_factor=1.015) self.start_time = '2023-12-20 00:00:00' + # self.start_time = '2024-04-08 00:00:00' self.sun.size_scale = 3e1 self.earth.size_scale = 2e3 self.earth_clouds.size_scale = self.earth.size_scale @@ -254,8 +255,9 @@ if __name__ == '__main__': sim = EarthSeasonsSimLive() sim.run( # dt=SECONDS_PER_DAY * 10, - # dt=SECONDS_PER_DAY * 3, - init_position=[0, 0, -2 * AU], + dt=SECONDS_PER_DAY * 3, + # dt=SECONDS_PER_HOUR, + init_position=[0, 0, -3 * AU], show_exit_button=False, show_camera_info=False, gravity_works=False, -- GitLab