From e7ba41e651cfeb78b2da1b1d88394053117a31a8 Mon Sep 17 00:00:00 2001 From: march3 Date: Tue, 4 Apr 2023 19:17:58 +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 --- common/func.py | 41 ++++++++++++- simulators/ursina/entities/body_trail.py | 68 +++++++++++++++++----- simulators/ursina/entities/entity_utils.py | 59 ++++++++++++++----- 3 files changed, 138 insertions(+), 30 deletions(-) diff --git a/common/func.py b/common/func.py index dd992b1..28f3aa3 100644 --- a/common/func.py +++ b/common/func.py @@ -11,6 +11,7 @@ from common.consts import AU import numpy as np import random import os +import math def get_dominant_colors(infile, resize=(20, 20)): @@ -107,7 +108,45 @@ def calculate_distance(pos1, pos2=[0, 0, 0]): pow(np.array(pos1[2]) - np.array(pos2[2]), 2), 1 / 2) return d +G = 6.67408e-11 +# AU = 149597870700.0 + +def calculate_velocity(mass, semimajor_axis, eccentricity): + """ + 计算天体在椭圆轨道上的速度。 + + 参数: + - mass: 天体质量,单位 kg + - semimajor_axis: 轨道半长轴,单位 m + - eccentricity: 轨道离心率 + + 返回值: + 天体在轨道上的速度,单位 m/s。 + """ + # 计算轨道的半短轴和半焦距 + semiminor_axis = semimajor_axis * math.sqrt(1 - eccentricity ** 2) + focus_distance = semimajor_axis * eccentricity + + # 计算轨道的第一和第二离心率角 + theta = math.atan2(focus_distance, semiminor_axis) + psi = math.atan2(math.sqrt(1 - eccentricity ** 2) * math.sin(theta), eccentricity + math.cos(theta)) + + # 计算轨道的速率 + v = math.sqrt(G * mass * (2 / semimajor_axis - 1 / semiminor_axis)) + + # 计算天体在轨道上的速度,注意要考虑太阳的质量 + return v * math.sqrt(1 + (2 * mass) / (v ** 2 * AU)) * math.sin(psi) + if __name__ == '__main__': # print(calculate_distance([6, 8, 0], [3, 4, 0])) - print(find_file("common/func.py")) + # print(find_file("common/func.py")) + + # 使用地球数据测试 + mass_earth = 5.972e24 + semimajor_axis_earth = AU + eccentricity_earth = 0.0167 + + velocity_earth = calculate_velocity(mass_earth, semimajor_axis_earth, eccentricity_earth) + + print("地球在轨道上的速度是:{:.2f} km/s".format(velocity_earth / 1000)) \ No newline at end of file diff --git a/simulators/ursina/entities/body_trail.py b/simulators/ursina/entities/body_trail.py index 7b43d9e..3b0f49d 100644 --- a/simulators/ursina/entities/body_trail.py +++ b/simulators/ursina/entities/body_trail.py @@ -9,11 +9,22 @@ # pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com ursina from ursina import Entity, Mesh, Text, color, destroy, Vec3 +from common.color_utils import get_inverse_color from simulators.ursina.ursina_mesh import create_arrow_line class BodyTrail(Entity): def __init__(self, **kwargs): + if "last_pos" in kwargs: + from_pos = kwargs["last_pos"] + else: + from_pos = (0, 0, 0) + + if "to_pos" in kwargs: + to_pos = kwargs["to_pos"] + else: + to_pos = (1, 1, 1) + super().__init__( model='sphere', collider='sphere', @@ -21,6 +32,8 @@ class BodyTrail(Entity): **kwargs ) + self.set_light_off() + def input(self, key): if self.hovered: if key == 'left mouse down': @@ -29,11 +42,18 @@ class BodyTrail(Entity): self.show_infos() def show_infos(self): + if not hasattr(self, "origin_alpha"): + self.origin_color = self.color + self.origin_alpha = self.alpha if len(self.children) > 0: for c in self.children: destroy(c) + # self.color = self.origin_color + self.alpha = self.origin_alpha return + self.alpha = 0.2 + # self.color = get_inverse_color(self.origin_color) vel_info, vel_direction, vel_position = self.entity_infos["velocity"] acc_info, acc_direction, acc_position = self.entity_infos["acceleration"] @@ -53,19 +73,35 @@ class BodyTrail(Entity): a_line.enabled = False -# class BodyTrail(Entity): -# def __init__(self, **kwargs): -# from_pos = (0, 0, 0) -# to_pos = (1, 1, 1) -# super().__init__( -# # model='line', -# model=Mesh(vertices=(from_pos, to_pos), mode='line', thickness=3), -# ignore_paused=True, -# **kwargs -# ) -# -# def update(self): -# self.look_at(self.parent) -# # line = Entity(parent=parent, -# # model=Mesh(vertices=(from_pos * len_scale, to_pos * len_scale), mode='line', thickness=thickness), -# # color=color, alpha=alpha) +class BodyTrailLine_OK(Entity): + def __init__(self, **kwargs): + if "last_pos" in kwargs: + from_pos = kwargs["last_pos"] + else: + from_pos = (0, 0, 0) + + if "to_pos" in kwargs: + to_pos = kwargs["to_pos"] + else: + to_pos = (1, 1, 1) + super().__init__( + # model='line', + model=Mesh(vertices=(from_pos, to_pos), mode='line', thickness=3), + ignore_paused=True, + **kwargs + ) + + +class BodyTrailLine(Entity): + def __init__(self, **kwargs): + if "direction" in kwargs: + direction = kwargs["direction"] + else: + direction = (0, 0, 0) + + super().__init__( + # model='line', + model=Mesh(vertices=((0, 0, 0), direction), mode='line', thickness=2), + ignore_paused=True, + **kwargs + ) diff --git a/simulators/ursina/entities/entity_utils.py b/simulators/ursina/entities/entity_utils.py index 1143151..008b40b 100644 --- a/simulators/ursina/entities/entity_utils.py +++ b/simulators/ursina/entities/entity_utils.py @@ -11,7 +11,7 @@ from ursina import Ursina, window, Entity, Mesh, SmoothFollow, Texture, clamp, t camera, color, mouse, Vec2, Vec3, Vec4, Text, \ load_texture, held_keys, destroy, PointLight -from simulators.ursina.entities.body_trail import BodyTrail +from simulators.ursina.entities.body_trail import BodyTrail, BodyTrailLine from simulators.ursina.ursina_config import UrsinaConfig from common.color_utils import adjust_brightness, conv_to_vec4_color, get_inverse_color from simulators.ursina.ursina_mesh import create_torus @@ -28,8 +28,8 @@ def create_name_text(parent): """ b_color = parent.body_view.color name_text = Text(parent.body_view.body.name, scale=1, billboard=True, parent=parent, - font=UrsinaConfig.CN_FONT, background=True, - origin=(0, 0)) + font=UrsinaConfig.CN_FONT, background=True, + origin=(0, 0)) name_text.background.color = color.rgba(b_color[0], b_color[1], b_color[2], 0.3) name_text.resolution = 24 # self.name_text.scale = self.scale @@ -89,6 +89,7 @@ def create_trails(parent): parent.destroy_all() return trails_keys = parent.trails.keys() + trail_int_scale = 1.2 # 如果有拖尾 if len(trails_keys) > 0: # 获取最后一个拖尾的位置 @@ -101,11 +102,15 @@ def create_trails(parent): # if self_pos_distance < self.scale_x + (self.trail_scale / 2): # pass # 如果位置比较近,就不创建拖尾了,保证拖尾间隔一定的距离 - if last_pos_distance < parent.trail_scale * 1.2: # 间隔距离不小于1.2倍的拖尾球体 + if last_pos_distance < parent.trail_scale * trail_int_scale: # 间隔距离不小于1.2倍的拖尾球体 return - trail = create_trail(parent, pos) - create_trail_info(parent.body, trail) + # trail = create_trail_line(parent, pos) + trail = create_trail_sphere(parent, pos) + + if trail is not None: + create_trail_info(parent.body, trail) + # 创建拖尾球体,并作为字典的key,存放拖尾球体的位置 parent.trails[trail] = pos @@ -121,7 +126,7 @@ def create_trails(parent): break -def create_trail(parent, pos): +def create_trail_sphere(parent, pos): """ 在天体当前的位置创建一个拖尾球体 :param pos: @@ -129,13 +134,43 @@ def create_trail(parent, pos): """ # sphere = create_sphere(1,6) diamond sphere trail = BodyTrail(color=parent.trail_color, scale=parent.trail_scale, position=pos) - trail.set_light_off() + # trail.set_color_off() # trail.set_color_scale_off() # trail.enabled = False return trail +def merge_vectors(vectors): + # 计算速度的大小 + x, y, z = vectors[0], vectors[1], vectors[2] + value = math.sqrt(x ** 2 + y ** 2 + z ** 2) + # 计算速度的方向 + direction = (x / value, y / value, z / value) + # 返回速度大小和速度方向 + return value, direction + + +def create_trail_line(parent, pos): + """ + 在天体当前的位置创建一个拖尾球体 + :param pos: + :return: + """ + if hasattr(parent, "trail_last_pos"): + trail_last_pos = parent.trail_last_pos + value, direction = merge_vectors(pos - trail_last_pos) + trail = BodyTrailLine(color=parent.trail_color, scale=parent.trail_scale, position=trail_last_pos, + direction=Vec3(direction)) + trail.set_light_off() + parent.last_trail = trail + + else: + trail = None + parent.trail_last_pos = pos + return trail + + def create_rings(self): """ 创建行星环(使用土星贴图) @@ -250,7 +285,6 @@ def create_trail_info(body, trail): else: acc_info = "%.2fmm/s²" % (acc_m * 1000) - vel_direction = velocity[1] vel_direction = np.array(vel_direction) * 5 @@ -262,7 +296,6 @@ def create_trail_info(body, trail): acc_position = acc_direction # acc_position = (acc_position[0], acc_position[1], acc_position[2]) - - trail.entity_infos = {"velocity": [vel_info, vel_direction, vel_position], - "acceleration": [acc_info, acc_direction, acc_position]} - + if trail is not None: + trail.entity_infos = {"velocity": [vel_info, vel_direction, vel_position], + "acceleration": [acc_info, acc_direction, acc_position]} -- GitLab