diff --git a/common/color_utils.py b/common/color_utils.py index 0ec48e41c6e5e3d8d16e73292feb097120b5f30a..fe5aad8f2cd4d548acb08c4a01ba8d6de13cbb0b 100644 --- a/common/color_utils.py +++ b/common/color_utils.py @@ -21,6 +21,17 @@ def conv_to_vec4_color(colour: tuple, alpha=1): elif len(colour) == 4: return Vec4(colour[0], colour[1], colour[2], colour[3]) / 255 raise Exception("colour错误") + # if len(color) == 4: + # r, g, b, a = color + # a = color[3] + # elif len(color) == 3: + # r, g, b = color + # a = alpha + # else: + # r, g, b, a = 1.0, 1.0, 1.0, 1.0 + # if r>1 or g>1 or b>1 or isinstance(r,int) or isinstance(g,int) or isinstance(b,int): + # r, g, b = r/255, g/255, b/255 + # color = ursina_color.rgba(r, g, b, a) def adjust_brightness(color, target_brightness: float = 0.6): diff --git a/sim_scenes/fiction/earth_orbit_stopped.py b/sim_scenes/fiction/earth_orbit_stopped.py index 248f61e71501c271596a3a0f6b28b9e16723a7d3..329478536bc258410786a7013e41e06eb77285de 100644 --- a/sim_scenes/fiction/earth_orbit_stopped.py +++ b/sim_scenes/fiction/earth_orbit_stopped.py @@ -6,67 +6,155 @@ # link :https://gitcode.net/pythoncr/ # python_version :3.8 # ============================================================================== -from bodies import Sun, Earth, Moon +from bodies import Sun, Earth, Mercury, Venus 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, two_bodies_colliding, set_camera_parent from bodies.body import AU from simulators.ursina.entities.body_timer import BodyTimer, TimeData from simulators.ursina.ui.control_ui import ControlUI +from simulators.ursina.ursina_config import UrsinaConfig from simulators.ursina.ursina_event import UrsinaEvent from ursina import application, camera, Vec3 import math +from simulators.ursina.ursina_mesh import create_circle_line +from ursina import color -if __name__ == '__main__': - """ - 地球停止公转,多久到达太阳 - 地球如果停止公转,多久能掉入太阳? - https://www.zhihu.com/question/310815418 - 如果地球停止公转,那它需要多久才会掉进太阳? - https://www.guokr.com/article/440341 - - """ +mercury_line = None +# 42天到达 +venus_line = None + + +class EarthOrbitStoppedSim: # 地球的Y方向初始速度 EARTH_INIT_VELOCITY = 0 # 0km/s - sun = Sun(init_position=[0, 0, 0], size_scale=1) - earth = Earth(init_position=[0, 0, -AU], - init_velocity=[0, EARTH_INIT_VELOCITY, 0], - size_scale=1).set_light_disable(True) - bodies = [ - sun, - earth - ] + def __init__(self): + self.sun = Sun(init_position=[0, 0, 0], size_scale=1) + self.earth = Earth(init_position=[0, 0, -AU], + init_velocity=[0, self.EARTH_INIT_VELOCITY, 0], + size_scale=1).set_light_disable(True) + + self.mercury_radius = 0.384 * AU + self.venus_radius = 0.721 * AU + # 水星: [49311300. 0. 28075956.] [ 24.30735 0. -41.926445] + self.mercury = Mercury(name="水星", + # init_position=[0, 0, self.mercury_radius], + # init_position=[0, 0, -self.mercury_radius], # 和地球同一方向 + init_position=[49311300., 0, 28075956.], + init_velocity=[-24.307, 0, 41.9264], + size_scale=1).set_light_disable(True) + # 金星: [-98608848. 0. -42909512.] [-13.869937 0. 32.247845] + self.venus = Venus(name="金星", + # init_position=[0, 0, self.venus_radius], + # init_position=[0, 0, -self.venus_radius], # 和地球同一方向 + init_position=[-98608848., 0, -42909512.], # 和地球同一方向 + init_velocity=[13.869937, 0, -32.247845], + size_scale=1).set_light_disable(True) - def on_ready(): + self.bodies = [ + self.sun, self.mercury, self.venus, self.earth + ] + self.arrived_sun = None + self.arrived_mercury_orbit_line = None + self.arrived_venus_orbit_line = None + + def create_orbit_line(self, radius, color): + orbit_line = create_circle_line(parent=self.sun, radius=radius, thickness=5, color=color, alpha=0.3) + orbit_line.rotation_x = 90 + orbit_line.enabled = False + return orbit_line + + def on_ready(self): # 运行前触发 application.time_scale = 0.00001 camera.fov = 50 + # 创建水星轨道线 + self.mercury_orbit_line = self.create_orbit_line( + radius=self.mercury_radius * UrsinaConfig.SCALE_FACTOR, + color=self.mercury.color) + # 创建金星轨道线 + self.venus_orbit_line = self.create_orbit_line( + radius=self.venus_radius * UrsinaConfig.SCALE_FACTOR, + color=self.venus.color) + def on_timer_changed(self, time_data: TimeData): + camera_look_at(self.earth, rotation_z=0) + earth_pos = self.earth.planet.world_position + camera.world_position = Vec3(earth_pos[0], earth_pos[1] + 0.01, earth_pos[2] - 0.1) - def on_timer_changed(time_data: TimeData): + # 当地球停止公转,如果没有向外的向心力来抵消向内的引力,地球将开始朝着太阳坠落。 + # 据美国康奈尔大学的天文学家戴夫 · 罗斯坦(Dave Rothstein)的计算, + # 地球将在65天后与太阳相撞,期间在第41天穿过金星的轨道,在第57天,我们将穿过水星的轨道 - camera_look_at(earth, rotation_z=0) - earth_pos = earth.planet.world_position - camera.world_position = Vec3(earth_pos[0], earth_pos[1] + 0.01, earth_pos[2] - 0.1) + # 地球[41天 07时]到达金星轨道 + # 地球[57天 01时]到达水星轨道 + # 地球[64天 13时]到达太阳表面 - if two_bodies_colliding(sun, earth): - ControlUI.current_ui.show_message("地球已到达太阳表面", close_time=-1) + if two_bodies_colliding(self.sun, self.earth): + self.arrived_sun = True + msg = "地球[%s]到达太阳表面" % time_data.time_text + print(msg) + ControlUI.current_ui.show_message(msg, close_time=-1) application.pause() + if time_data.days in [40, 41]: + self.venus_orbit_line.enabled = True + else: + self.venus_orbit_line.enabled = False + + if time_data.days in [56, 57]: + self.mercury_orbit_line.enabled = True + else: + self.mercury_orbit_line.enabled = False + + # if time_data.days in [41, 57, 64]: + # UrsinaConfig.run_speed_factor = 0.1 + # else: + # UrsinaConfig.run_speed_factor = 1 + + if abs(self.earth.position[2]) < 0.721 * AU and not self.arrived_venus_orbit_line: + self.arrived_venus_orbit_line = True + msg = "地球[%s]到达金星轨道" % time_data.time_text + print(msg) + print("金星:", self.venus.position, self.venus.velocity) + ControlUI.current_ui.show_message(msg, close_time=5) + + if abs(self.earth.position[2]) < 0.384 * AU and not self.arrived_mercury_orbit_line: + self.arrived_mercury_orbit_line = True + msg = "地球[%s]到达水星轨道" % time_data.time_text + print(msg) + print("水星:", self.mercury.position, self.mercury.velocity) + ControlUI.current_ui.show_message(msg, close_time=5) + + +if __name__ == '__main__': + """ + 地球停止公转,多久到达太阳 + 地球如果停止公转,多久能掉入太阳? + https://www.zhihu.com/question/310815418 + 如果地球停止公转,那它需要多久才会掉进太阳? + https://www.guokr.com/article/440341 + + """ # 设置计时器的最小时间单位为分钟 BodyTimer().min_unit = BodyTimer.MIN_UNIT_HOURS + sim = EarthOrbitStoppedSim() + # 运行前会触发 on_ready - UrsinaEvent.on_ready_subscription(on_ready) + UrsinaEvent.on_ready_subscription(sim.on_ready) # 订阅事件后,上面的函数功能才会起作用 # 运行中,每时每刻都会触发 on_timer_changed - UrsinaEvent.on_timer_changed_subscription(on_timer_changed) + UrsinaEvent.on_timer_changed_subscription(sim.on_timer_changed) # 使用 ursina 查看的运行效果 # 常用快捷键: P:运行和暂停 O:重新开始 I:显示天体轨迹 # position = 左-右+、上+下-、前+后- # position=(0, 0, 0) 的位置是站在地球视角,可以观看月相变化的过程 - ursina_run(bodies, SECONDS_PER_DAY, position=(0, 0.0001 * AU, -0.002 * AU), + ursina_run(sim.bodies, SECONDS_PER_DAY, position=(0, 0.0001 * AU, -0.02 * AU), show_timer=True, show_grid=True) + # ursina_run(bodies, SECONDS_PER_DAY, position=(0, 2*AU, 0), + # show_timer=True, + # show_grid=True) diff --git a/simulators/ursina/ursina_mesh.py b/simulators/ursina/ursina_mesh.py index 825bee8b568b43f79f7fd4c7e534be8c80a3ce4e..68110db185b07d4f5724173e22547336a98d76a6 100644 --- a/simulators/ursina/ursina_mesh.py +++ b/simulators/ursina/ursina_mesh.py @@ -7,11 +7,15 @@ # python_version :3.8 # ============================================================================== # pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com ursina -from ursina import Ursina, window, Entity, Mesh, EditorCamera, color, mouse, Vec2, Vec3, load_texture, Texture, Text +from ursina import Ursina, window, Entity, Mesh, EditorCamera, color, mouse, Vec2, Vec3, load_texture, Texture, Text, \ + Cylinder +import ursina.color as ursina_color from math import pi, sin, cos import numpy as np import math +from common.color_utils import conv_to_vec4_color +from simulators.ursina.entities.circle_line import CircleLine from simulators.ursina.ursina_config import UrsinaConfig @@ -115,10 +119,19 @@ def create_circle(parent=None, pos=Vec3(0, 0, 0), thickness=1, scale=1, color=co return circle -def create_circle_line(parent=None, pos=Vec3(0, 0, 0), thickness=1, scale=1, color=color.white, alpha=1): - circle = Entity(parent=parent, model="circle", thickness=thickness, scale=scale, position=pos, - color=color, alpha=alpha) - return circle +def create_circle_line(parent=None, radius=1, position=None, segments=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 + + circle_line = CircleLine(position=position, radius=radius, segments=segments, thickness=thickness, color=color, + alpha=alpha) + if parent is not None: + if hasattr(parent, "planet"): + parent = parent.planet + circle_line.parent = parent + return circle_line def create_arrow_line(from_pos, to_pos, parent=None, label=None, @@ -395,7 +408,9 @@ if __name__ == '__main__': # arrow = Entity(model=create_arrow(), color=color.yellow) # arrow.set_light_off() - arrow, line, text = create_arrow_line((0, 0, 0), (10, 0, 0)) + # arrow, line, text = create_arrow_line((0, 0, 0), (10, 0, 0)) + + create_circle_line() EditorCamera() app.run()