提交 6a6612d7 编写于 作者: 三月三net's avatar 三月三net

Python超人-宇宙模拟器

上级 a401d894
...@@ -341,6 +341,21 @@ def smooth_speed_transition2(run_speed_maps, transition_secs=1): ...@@ -341,6 +341,21 @@ def smooth_speed_transition2(run_speed_maps, transition_secs=1):
return speed_maps return speed_maps
def check_calc_run_speed_maps(run_speed_maps):
# 循环每一个分段
for i, speed_map in enumerate(run_speed_maps):
if i == 0:
continue
if i + 1 >= len(run_speed_maps):
continue
prev_speed_map = run_speed_maps[i - 1]
next_speed_map = run_speed_maps[i + 1]
if isinstance(speed_map["au"], str):
speed_map["au"] = (next_speed_map["au"] + prev_speed_map["au"]) / 2
return run_speed_maps
def smooth_speed_transition(run_speed_maps, transition_secs=1): def smooth_speed_transition(run_speed_maps, transition_secs=1):
""" """
通过逐步调整速度在给定的过渡时间内实现运行速度地图中速度的圆滑过渡。 通过逐步调整速度在给定的过渡时间内实现运行速度地图中速度的圆滑过渡。
...@@ -349,25 +364,20 @@ def smooth_speed_transition(run_speed_maps, transition_secs=1): ...@@ -349,25 +364,20 @@ def smooth_speed_transition(run_speed_maps, transition_secs=1):
其中au是以天文单位(AU)表示的距离,seconds则是以秒为单位的时间。 其中au是以天文单位(AU)表示的距离,seconds则是以秒为单位的时间。
transition_secs: 运行速度过渡的时间(秒数),默认为1秒。 transition_secs: 运行速度过渡的时间(秒数),默认为1秒。
""" """
# assuming 60 steps per second
transition_steps = transition_secs * 30
from scipy.interpolate import CubicSpline
from scipy.interpolate import InterpolatedUnivariateSpline from scipy.interpolate import InterpolatedUnivariateSpline
# 初始化速度分段序列
speed_maps = []
xs = np.array([p["au"] for p in run_speed_maps]) xs = np.array([p["au"] for p in run_speed_maps])
ys = np.array([p["secs"] for p in run_speed_maps]) ys = np.array([p["secs"] for p in run_speed_maps])
# x = 2
# y = spl(x)
# 计算 dydx(即导数) # 计算 dydx(即导数)
# dydx = np.diff(ys) / np.diff(xs) # dydx = np.diff(ys) / np.diff(xs)
# spl = CubicSpline(xs, ys) # spl = CubicSpline(xs, ys)
spl = InterpolatedUnivariateSpline(xs, ys, k=2) spl = InterpolatedUnivariateSpline(xs, ys, k=1) # k=5)
# x = 2
# y = spl(x)
# 初始化速度分段序列
speed_maps = []
# 循环每一个分段 # 循环每一个分段
for i, speed_map in enumerate(run_speed_maps): for i, speed_map in enumerate(run_speed_maps):
...@@ -387,19 +397,21 @@ def smooth_speed_transition(run_speed_maps, transition_secs=1): ...@@ -387,19 +397,21 @@ def smooth_speed_transition(run_speed_maps, transition_secs=1):
next_speed_map = run_speed_maps[i + 1] next_speed_map = run_speed_maps[i + 1]
current_speed_map = speed_map current_speed_map = speed_map
distance_step = (current_speed_map["au"] - prev_speed_map["au"]) / 3 diff_au = current_speed_map["au"] - prev_speed_map["au"]
for j in range(2): distance_step = 0.01
for j in range(int(diff_au / distance_step)):
d = prev_speed_map["au"] + (distance_step * (j + 1)) d = prev_speed_map["au"] + (distance_step * (j + 1))
s = spl(d) s = spl(d)
s = np.clip(s, 1, 1800) s = np.clip(s, 1, 1800)
speed_maps.append({"au": d, "secs": float(s)}) speed_maps.append({"au": d, "secs": float(s)})
speed_maps.append(speed_map) speed_maps.append(speed_map)
diff_au = next_speed_map["au"] - current_speed_map["au"]
# distance_step = diff_au / 10
distance_step = (next_speed_map["au"] - current_speed_map["au"]) / 5 for j in range(int(diff_au / distance_step)):
for j in range(4):
d = current_speed_map["au"] + (distance_step * (j + 1)) d = current_speed_map["au"] + (distance_step * (j + 1))
s = spl(d) s = spl(d)
s = np.clip(s, 1, 1800) s = np.clip(s, 1, 1800)
...@@ -409,45 +421,79 @@ def smooth_speed_transition(run_speed_maps, transition_secs=1): ...@@ -409,45 +421,79 @@ def smooth_speed_transition(run_speed_maps, transition_secs=1):
return speed_maps return speed_maps
def smooth_speed_transition3(run_speed_maps):
# 初始化速度分段序列
speed_maps = []
# 循环每一个分段
for i, speed_map in enumerate(run_speed_maps):
if i == 0:
# 对于第一个分段,直接添加到速度分段序列中
speed_maps.append(speed_map)
continue
if speed_map["secs"] <= 1:
# 如果当前分段所用时间小于等于1秒,直接添加到速度分段序列中
speed_maps.append(speed_map)
continue
if i + 1 >= len(run_speed_maps):
speed_maps.append(speed_map)
continue
# 否则,保存前一个速度分段
prev_speed_map = run_speed_maps[i - 1]
next_speed_map = run_speed_maps[i + 1]
current_speed_map = speed_map
speed_maps.append(speed_map)
return speed_maps
def speed_smooth_adjust_test(): def speed_smooth_adjust_test():
# 运行速度配置
run_speed_maps = [ run_speed_maps = [
{"au": 0., "secs": 1},
{"au": 0.008, "secs": 1}, {"au": 0.008, "secs": 1},
{"au": 0.36, "secs": SECONDS_PER_MINUTE * 2}, {"au": "?", "secs": SECONDS_PER_MINUTE * 10},
{"au": 0.376, "secs": SECONDS_PER_MINUTE}, {"au": 0.3855, "secs": 1},
{"au": 0.386, "secs": 1}, # [00:03:12] 到达 [水星] 0.384 AU {"au": 0.386, "secs": 1}, # [00:03:12] 到达 [水星] 0.384 AU
{"au": 0.715, "secs": SECONDS_PER_MINUTE}, {"au": "?", "secs": SECONDS_PER_MINUTE * 10},
{"au": 0.723, "secs": 1}, # [00:06:00] 到达 [金星] 0.721 AU {"au": 0.719, "secs": 1},
{"au": 0.996, "secs": SECONDS_PER_MINUTE}, # {"au": 0.723, "secs": 1}, # [00:06:00] 到达 [金星] 0.721 AU
{"au": 1.002, "secs": 1}, # [00:08:19] 到达 [地球] 1.0 AU # {"au": "?", "secs": SECONDS_PER_MINUTE * 10},
{"au": 1.50, "secs": SECONDS_PER_MINUTE * 2}, # {"au": 0.99, "secs": 1},
{"au": 1.516, "secs": SECONDS_PER_MINUTE}, # {"au": 1.002, "secs": 1}, # [00:08:19] 到达 [地球] 1.0 AU
{"au": 1.522, "secs": 1}, # [00:12:39] 到达 [火星] 1.52 AU # {"au": "?", "secs": SECONDS_PER_MINUTE * 10},
# {"au": 5.1, "secs": SECONDS_PER_HOUR}, # {"au": 1.51, "secs": 1},
{"au": 5.1, "secs": SECONDS_PER_MINUTE * 10}, # {"au": 1.522, "secs": 1}, # [00:12:39] 到达 [火星] 1.52 AU
{"au": 5.182, "secs": SECONDS_PER_MINUTE * 2}, # # {"au": 5.1, "secs": SECONDS_PER_HOUR},
{"au": 5.192, "secs": 1}, # [00:43:10] 到达 [木星] 5.19 AU # {"au": "?", "secs": SECONDS_PER_MINUTE * 20},
# {"au": 9.44, "secs": SECONDS_PER_HOUR}, # {"au": 5.189, "secs": 1},
{"au": 9.44, "secs": SECONDS_PER_MINUTE * 20}, # {"au": 5.192, "secs": 1}, # [00:43:10] 到达 [木星] 5.19 AU
{"au": 9.492, "secs": SECONDS_PER_MINUTE}, # # {"au": 9.44, "secs": SECONDS_PER_HOUR},
{"au": 9.502, "secs": 1}, # [01:19:01] 到达 [土星] 9.5 AU # {"au": "?", "secs": SECONDS_PER_MINUTE * 20},
# {"au": 19.15, "secs": SECONDS_PER_HOUR}, # {"au": 9.492, "secs": 1},
{"au": 19.15, "secs": SECONDS_PER_MINUTE * 30}, # {"au": 9.502, "secs": 1}, # [01:19:01] 到达 [土星] 9.5 AU
{"au": 19.192, "secs": SECONDS_PER_MINUTE}, # # {"au": 19.15, "secs": SECONDS_PER_HOUR},
{"au": 19.202, "secs": 1}, # [02:39:41] 到达 [天王星] 19.2 AU # {"au": "?", "secs": SECONDS_PER_MINUTE * 30},
# {"au": 30.67, "secs": SECONDS_PER_HOUR}, # {"au": 19.192, "secs": 1},
{"au": 30.67, "secs": SECONDS_PER_MINUTE * 30}, # {"au": 19.202, "secs": 1}, # [02:39:41] 到达 [天王星] 19.2 AU
{"au": 30.692, "secs": SECONDS_PER_MINUTE}, # # {"au": 30.67, "secs": SECONDS_PER_HOUR},
{"au": 30.702, "secs": 1}, # [04:15:19] 到达 [海王星] 30.7 AU # {"au": "?", "secs": SECONDS_PER_MINUTE * 30},
# {"au": 39.52, "secs": SECONDS_PER_HOUR * 1.2}, # {"au": 30.692, "secs": 1},
{"au": 39.52, "secs": SECONDS_PER_MINUTE * 30}, # {"au": 30.702, "secs": 1}, # [04:15:19] 到达 [海王星] 30.7 AU
{"au": 39.54, "secs": SECONDS_PER_MINUTE}, # # {"au": 39.52, "secs": SECONDS_PER_HOUR * 1.2},
{"au": 40, "secs": 1} # [05:28:55] 到达 [冥王星] 39.55 AU # {"au": "?", "secs": SECONDS_PER_MINUTE * 30},
# {"au": 39.54, "secs": 1},
# {"au": 40, "secs": 1} # [05:28:55] 到达 [冥王星] 39.55 AU
] ]
run_speed_maps = check_calc_run_speed_maps(run_speed_maps)
data1 = [(m["au"], m["secs"]) for m in run_speed_maps] data1 = [(m["au"], m["secs"]) for m in run_speed_maps]
x1, y1 = zip(*data1) x1, y1 = zip(*data1)
import copy import copy
run_speed_maps2 = smooth_speed_transition(copy.deepcopy(run_speed_maps)) run_speed_maps2 = smooth_speed_transition(run_speed_maps)
data2 = [(m["au"], m["secs"]) for m in run_speed_maps2] data2 = [(m["au"], m["secs"]) for m in run_speed_maps2]
x2, y2 = zip(*data2) x2, y2 = zip(*data2)
...@@ -458,8 +504,8 @@ def speed_smooth_adjust_test(): ...@@ -458,8 +504,8 @@ def speed_smooth_adjust_test():
# 生成一个Figure画布和一个Axes坐标系 # 生成一个Figure画布和一个Axes坐标系
fig, ax = plt.subplots() fig, ax = plt.subplots()
# 在生成的坐标系下画折线图 # 在生成的坐标系下画折线图
# ax.plot(x1, y1, 'o', linewidth=1) ax.plot(x1, y1, 'o', linewidth=1)
ax.plot(x2, y2, 'b', linewidth=1) ax.plot(x2, y2, 'r', linewidth=1)
# 显示图形 # 显示图形
plt.show() plt.show()
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
# ============================================================================== # ==============================================================================
from bodies import Sun, Asteroids, Body from bodies import Sun, Asteroids, Body
from common.consts import AU, LIGHT_SPEED, SECONDS_PER_MINUTE, SECONDS_PER_HOUR from common.consts import AU, LIGHT_SPEED, SECONDS_PER_MINUTE, SECONDS_PER_HOUR
from sim_scenes.func import create_text_panel, smooth_speed_transition from sim_scenes.func import create_text_panel, smooth_speed_transition, check_calc_run_speed_maps
from simulators.ursina.entities.body_timer import TimeData from simulators.ursina.entities.body_timer import TimeData
from simulators.ursina.ui.control_ui import ControlUI from simulators.ursina.ui.control_ui import ControlUI
from simulators.ursina.ursina_config import UrsinaConfig from simulators.ursina.ursina_config import UrsinaConfig
...@@ -84,6 +84,9 @@ class SpeedOfLightInit: ...@@ -84,6 +84,9 @@ class SpeedOfLightInit:
点击了重置按钮触发 点击了重置按钮触发
@return: @return:
""" """
if hasattr(self, "run_speed_maps"):
delattr(self, "run_speed_maps")
self.arrived_bodies.clear() # 重置存放记录光体已到达天体列表 self.arrived_bodies.clear() # 重置存放记录光体已到达天体列表
self.arrived_info = "距离[太阳中心]:${distance}\n\n" self.arrived_info = "距离[太阳中心]:${distance}\n\n"
if self.text_panel is not None: if self.text_panel is not None:
...@@ -160,66 +163,79 @@ class SpeedOfLightInit: ...@@ -160,66 +163,79 @@ class SpeedOfLightInit:
""" """
if self.__camera_follow_light != "SideViewActualSize": if self.__camera_follow_light != "SideViewActualSize":
return return
# 运行速度配置
run_speed_maps = [ if not hasattr(self, "run_speed_maps"):
{"au": 0.008, "secs": 1}, # 运行速度配置
{"au": 0.36, "secs": SECONDS_PER_MINUTE * 2}, run_speed_maps = [
{"au": 0.376, "secs": SECONDS_PER_MINUTE}, {"au": 0., "secs": 1},
{"au": 0.386, "secs": 1}, # [00:03:12] 到达 [水星] 0.384 AU {"au": 0.008, "secs": 1},
{"au": 0.715, "secs": SECONDS_PER_MINUTE}, {"au": "?", "secs": SECONDS_PER_MINUTE * 10},
{"au": 0.723, "secs": 1}, # [00:06:00] 到达 [金星] 0.721 AU {"au": 0.386, "secs": 1},
{"au": 0.996, "secs": SECONDS_PER_MINUTE}, {"au": 0.3865, "secs": 1}, # [00:03:12] 到达 [水星] 0.384 AU
{"au": 1.002, "secs": 1}, # [00:08:19] 到达 [地球] 1.0 AU {"au": "?", "secs": SECONDS_PER_MINUTE * 10},
{"au": 1.50, "secs": SECONDS_PER_MINUTE * 2}, {"au": 0.721, "secs": 1},
{"au": 1.516, "secs": SECONDS_PER_MINUTE}, {"au": 0.723, "secs": 1}, # [00:06:00] 到达 [金星] 0.721 AU
{"au": 1.522, "secs": 1}, # [00:12:39] 到达 [火星] 1.52 AU {"au": "?", "secs": SECONDS_PER_MINUTE * 10},
# {"au": 5.1, "secs": SECONDS_PER_HOUR}, {"au": 1.0, "secs": 1},
{"au": 5.1, "secs": SECONDS_PER_MINUTE * 10}, {"au": 1.002, "secs": 1}, # [00:08:19] 到达 [地球] 1.0 AU
{"au": 5.182, "secs": SECONDS_PER_MINUTE * 2}, {"au": "?", "secs": SECONDS_PER_MINUTE * 10},
{"au": 5.192, "secs": 1}, # [00:43:10] 到达 [木星] 5.19 AU {"au": 1.52, "secs": 1},
# {"au": 9.44, "secs": SECONDS_PER_HOUR}, {"au": 1.522, "secs": 1}, # [00:12:39] 到达 [火星] 1.52 AU
{"au": 9.44, "secs": SECONDS_PER_MINUTE * 20}, {"au": "?", "secs": SECONDS_PER_MINUTE * 30},
{"au": 9.492, "secs": SECONDS_PER_MINUTE}, {"au": 5.19, "secs": 1},
{"au": 9.502, "secs": 1}, # [01:19:01] 到达 [土星] 9.5 AU {"au": 5.20, "secs": 1}, # [00:43:10] 到达 [木星] 5.19 AU
# {"au": 19.15, "secs": SECONDS_PER_HOUR}, {"au": "?", "secs": SECONDS_PER_MINUTE * 30},
{"au": 19.15, "secs": SECONDS_PER_MINUTE * 30}, {"au": 9.5, "secs": 1},
{"au": 19.192, "secs": SECONDS_PER_MINUTE}, {"au": 9.51, "secs": 1}, # [01:19:01] 到达 [土星] 9.5 AU
{"au": 19.202, "secs": 1}, # [02:39:41] 到达 [天王星] 19.2 AU {"au": "?", "secs": SECONDS_PER_MINUTE * 30},
# {"au": 30.67, "secs": SECONDS_PER_HOUR}, {"au": 19.2, "secs": 1},
{"au": 30.67, "secs": SECONDS_PER_MINUTE * 30}, {"au": 19.21, "secs": 1}, # [02:39:41] 到达 [天王星] 19.2 AU
{"au": 30.692, "secs": SECONDS_PER_MINUTE}, {"au": "?", "secs": SECONDS_PER_MINUTE * 30},
{"au": 30.702, "secs": 1}, # [04:15:19] 到达 [海王星] 30.7 AU {"au": 30.7, "secs": 1},
# {"au": 39.52, "secs": SECONDS_PER_HOUR * 1.2}, {"au": 30.71, "secs": 1}, # [04:15:19] 到达 [海王星] 30.7 AU
{"au": 39.52, "secs": SECONDS_PER_MINUTE * 30}, {"au": "?", "secs": SECONDS_PER_MINUTE * 30},
{"au": 39.54, "secs": SECONDS_PER_MINUTE}, {"au": 39.55, "secs": 1},
{"au": 1000, "secs": 1} # [05:28:55] 到达 [冥王星] 39.55 AU {"au": 40, "secs": 1} # [05:28:55] 到达 [冥王星] 39.55 AU
] ]
run_speed_maps = check_calc_run_speed_maps(run_speed_maps)
# run_speed_maps = smooth_speed_transition(run_speed_maps) run_speed_maps = smooth_speed_transition(run_speed_maps)
self.run_speed_maps = run_speed_maps
light_distance = self.light_body.position[2] light_distance = self.light_body.position[2]
for i, m in enumerate(run_speed_maps): current_idx = 0
for i, m in enumerate(self.run_speed_maps):
if i == 0: if i == 0:
au_min = 0 au_min = 0
else: else:
au_min = run_speed_maps[i - 1]["au"] au_min = self.run_speed_maps[i - 1]["au"]
au_max = m["au"] au_max = m["au"]
if light_distance < au_min * AU:
# 如果光体的距离小于 au_min 则无需再循环
break
if au_max * AU > light_distance >= au_min * AU: if au_max * AU > light_distance >= au_min * AU:
if UrsinaConfig.seconds_per != m["secs"]: if UrsinaConfig.seconds_per != m["secs"]:
seconds_per = m["secs"] # int(round(m["secs"], 0)) seconds_per = m["secs"] # int(round(m["secs"], 0))
UrsinaConfig.seconds_per = seconds_per UrsinaConfig.seconds_per = seconds_per
if seconds_per >= 10000: if seconds_per >= 10000:
msg = f" {int(seconds_per / 10000)} 万" msg = f"加速到 {int(seconds_per / 10000)} 万"
elif seconds_per >= 1000: elif seconds_per >= 1000:
msg = f" {int(seconds_per / 1000)} 千" msg = f"加速到 {int(seconds_per / 1000)} 千"
elif seconds_per > 1:
msg = f"加速到 {int(seconds_per)} "
else: else:
msg = f" {int(seconds_per)} " msg = f"当前为 {int(seconds_per)} "
msg = f"当前为{msg}倍光速" msg = f"{msg}倍光速"
ControlUI.current_ui.show_message(msg, close_time=-1) ControlUI.current_ui.show_message(msg, close_time=-1)
current_idx = i
break
if current_idx > 0:
self.run_speed_maps = self.run_speed_maps[current_idx:]
def on_timer_changed(self, time_data: TimeData): def on_timer_changed(self, time_data: TimeData):
""" """
...@@ -239,8 +255,9 @@ class SpeedOfLightInit: ...@@ -239,8 +255,9 @@ class SpeedOfLightInit:
self.arrived_bodies.append(body) self.arrived_bodies.append(body)
if self.text_panel is not None: if self.text_panel is not None:
self.arrived_info += f"[{time_data.time_text}]\t到达\t[{body.name}]\n\n" self.arrived_info += f"[{time_data.time_text}]\t到达\t[{body.name}]\n\n"
distance = round(self.light_body.position[2] / AU, 2) # distance = round(self.light_body.position[2] / AU, 4)
self.text_panel.text = self.arrived_info.replace("${distance}", f"{distance} AU") # # print("浮点数保留两位小数,宽5位,不足补0:%05.5f " % 2.222)
# self.text_panel.text = self.arrived_info.replace("${distance}", "%.4f AU" % distance)
print(f"[{time_data.time_text}] 到达 [{body.name}] {round(self.light_body.position[2] / AU, 4)} AU") print(f"[{time_data.time_text}] 到达 [{body.name}] {round(self.light_body.position[2] / AU, 4)} AU")
return return
...@@ -248,6 +265,9 @@ class SpeedOfLightInit: ...@@ -248,6 +265,9 @@ class SpeedOfLightInit:
self.last_time = datetime.datetime.now() self.last_time = datetime.datetime.now()
else: else:
if datetime.datetime.now() - datetime.timedelta(milliseconds=1000) > self.last_time: if datetime.datetime.now() - datetime.timedelta(milliseconds=1000) > self.last_time:
distance = round(self.light_body.position[2] / AU, 2) # distance = round(self.light_body.position[2] / AU, 4)
self.text_panel.text = self.arrived_info.replace("${distance}", f"{distance} AU") # self.text_panel.text = self.arrived_info.replace("${distance}", "%.4f AU" % distance)
self.last_time = datetime.datetime.now() self.last_time = datetime.datetime.now()
distance = round(self.light_body.position[2] / AU, 4)
self.text_panel.text = self.arrived_info.replace("${distance}", "%.4f AU" % distance)
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册