func.py 7.9 KB
Newer Older
M
march3 已提交
1
# -*- coding:utf-8 -*-
M
march3 已提交
2 3
# title           :场景用功能库
# description     :场景用功能库
M
march3 已提交
4
# author          :Python超人
M
march3 已提交
5 6
# date            :2023-02-11
# link            :https://gitcode.net/pythoncr/
M
march3 已提交
7 8
# python_version  :3.8
# ==============================================================================
M
march3 已提交
9
import matplotlib.pyplot as plt
M
march3 已提交
10
from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, SECONDS_PER_HALF_DAY
M
march3 已提交
11
from common.system import System
三月三net's avatar
三月三net 已提交
12
from simulators.ursina.ursina_config import UrsinaConfig
三月三net's avatar
三月三net 已提交
13
from simulators.ursina.ursina_event import UrsinaEvent
M
march3 已提交
14 15 16 17 18 19 20 21


def mayavi_run(bodies, dt=SECONDS_PER_WEEK,
               view_azimuth=0, view_distance='auto', view_focalpoint='auto',
               bgcolor=(1 / 255, 1 / 255, 30 / 255)):
    """
    用 mayavi 查看运行效果
    :param bodies: 天体
M
march3 已提交
22
    :param dt: 单位:秒,按时间差进行演变,值越小越精确,但演变速度会慢。
M
march3 已提交
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
    :param view_azimuth: 观测方位角,可选,float类型(以度为单位,0-360),用x轴投影到x-y平面上的球体上的位置矢量所对的角度。
    :param view_distance: 观测距离,可选,float类型 or 'auto',一个正浮点数,表示距放置相机的焦点的距离。
    :param view_focalpoint: 观测焦点,可选,类型为一个由3个浮点数组成的数组 or 'auto',,代表观测相机的焦点
    :param bgcolor:
    :return:
    """
    from mayavi import mlab
    from simulators.mayavi_simulator import MayaviSimulator
    # 宇宙背景色
    mlab.figure(bgcolor=bgcolor, size=(1440, 810))
    body_sys = System(bodies)
    simulator = MayaviSimulator(body_sys)
    simulator.run(dt)
    # azimuth:
    #    观测方位角,可选,float类型(以度为单位,0-360),用x轴投影到x-y平面上的球体上的位置矢量所对的角度。
    # elevation:
    #    观测天顶角,可选,float类型(以度为单位,0-180), 位置向量和z轴所对的角度。
    # distance:
    #    观测距离,可选,float类型 or 'auto',一个正浮点数,表示距放置相机的焦点的距离。
    #    Mayavi 3.4.0中的新功能:'auto' 使得距离为观察所有对象的最佳位置。
    # focalpoint:
    #    观测焦点,可选,类型为一个由3个浮点数组成的数组 or 'auto',,代表观测相机的焦点
    #    Mayavi 3.4.0中的新功能:'auto',则焦点位于场景中所有对象的中心。
    # roll:
    #    控制滚动,可选,float类型,即摄影机围绕其轴的旋转
    # reset_roll:
    #    布尔值,可选。如果为True,且未指定“滚动”,则重置相机的滚动方向。
    # figure:
    #    要操作的Mayavi图形。如果为 None,则使用当前图形。
    mlab.view(azimuth=view_azimuth, distance=view_distance, focalpoint=view_focalpoint)
    # mlab.view(azimuth=-45, elevation=45, distance=100e8 * 2 * 2 * 4 * 4, focalpoint=[5e10, 5e10, 5e9])
    mlab.show()
M
march3 已提交
55 56


三月三net's avatar
三月三net 已提交
57 58
def ursina_run(bodies,
               dt=SECONDS_PER_HALF_DAY,
三月三net's avatar
三月三net 已提交
59
               position=(0, 0, 0),
三月三net's avatar
三月三net 已提交
60
               # view_azimuth=0,
三月三net's avatar
三月三net 已提交
61 62
               light=True,
               cosmic_bg=None,
三月三net's avatar
三月三net 已提交
63
               bg_music=None,
三月三net's avatar
三月三net 已提交
64
               show_grid=True,
三月三net's avatar
三月三net 已提交
65
               show_trail=False,
三月三net's avatar
三月三net 已提交
66
               show_name=False,
三月三net's avatar
三月三net 已提交
67
               save_as_json=None):
M
march3 已提交
68 69
    """

三月三net's avatar
三月三net 已提交
70 71 72 73 74 75 76
    :param bodies: 天体
    :param dt: 单位:秒,按时间差进行演变,值越小越精确,但演变速度会慢。
    :param position: 摄像头位置
    :param view_azimuth: 摄像头观测方位角,可选,float类型(以度为单位,0-360)
    :param light: 使用灯光效果
    :param cosmic_bg: 宇宙背景图片
    :param show_grid: 是否显示空间网格
三月三net's avatar
三月三net 已提交
77 78
    :param save_as_json: 将所有天体的信息保存为 json 文件
    :param ignore_mass: 忽略所有天体的引力
M
march3 已提交
79 80 81 82
    :return:
    """

    from simulators.ursina_simulator import UrsinaSimulator, UrsinaPlayer
三月三net's avatar
三月三net 已提交
83 84
    from ursina import application, Sequence, camera, held_keys, time, clamp, Entity, Text, color
    from ursina.prefabs.first_person_controller import FirstPersonController
三月三net's avatar
三月三net 已提交
85
    body_sys = System(bodies)
三月三net's avatar
三月三net 已提交
86 87 88 89 90

    if show_name:
        for body in body_sys.bodies:
            body.show_name = True

三月三net's avatar
三月三net 已提交
91 92
    if save_as_json is not None:
        try:
三月三net's avatar
三月三net 已提交
93 94
            body_sys.save_to_json(save_as_json, {"dt": dt, "position": position,
                                                 "show_trail": show_trail, "show_name": show_name})
三月三net's avatar
三月三net 已提交
95 96 97 98
            print(f"{save_as_json} 文件生成成功!")
        except Exception as e:
            print(f"{save_as_json} 文件生成失败!" + str(e))
        return
M
march3 已提交
99
    simulator = UrsinaSimulator(body_sys)
三月三net's avatar
三月三net 已提交
100 101
    view_azimuth = 0  # 暂时未用
    player = UrsinaPlayer(position, view_azimuth, simulator.ursina_views)
三月三net's avatar
三月三net 已提交
102

三月三net's avatar
三月三net 已提交
103 104 105 106 107 108 109 110
    # # player = FirstPersonController(model='cube', y=-1e20, color=color.orange, origin_y=-5000, speed=8)
    # # player.on_disable()
    # # player.position = position
    #
    # player = FirstPersonController()
    # cube = Entity(model='cube', color=color.red, scale=2)
    # player.parent = cube  # 设置 FirstPersonController 的父实体为 cube
    # cube.position = position  # 修改父实体的位置,从而间接地修改 FirstPersonController 的位置
M
march3 已提交
111

三月三net's avatar
三月三net 已提交
112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134
    # # 创建一个实体(在屏幕中央)和一个摄像机
    # TODO: 未使用
    # entity = Entity(model='cube', position=(0, 0, 5), scale=2)
    # camera = Camera()
    #
    # # 设置初始的 FOV 值(默认值为 90)
    # camera.fov = 60
    #
    # # 创建一个用于显示当前 FOV 值的文本
    # fov_text = Text(text=f'FOV: {camera.fov}', position=(-0.5, 0.4), scale=2)
    # # 每一帧更新摄像机 FOV 值
    # def update():
    #     # 通过鼠标滚轮来调整 FOV 值
    #     camera.fov -= held_keys['scroll'] * 10 * time.dt
    #     # 限制 FOV 值的范围(1 到 120 之间)
    #     camera.fov = clamp(camera.fov, 1, 120)
    #     # 更新文本内容
    #     fov_text.text = f'FOV: {camera.fov:.2f}'  # 保留两位小数
    #
    #     # 将摄像机移到实体旁边,并对着它
    #     camera.position = entity.position + (0, 0, -5)
    #     camera.look_at(entity.position)

M
march3 已提交
135
    def callback_update():
三月三net's avatar
三月三net 已提交
136
        UrsinaEvent.on_application_run()
M
march3 已提交
137 138
        for ursina_view in simulator.ursina_views:
            simulator.check_and_evolve()
三月三net's avatar
三月三net 已提交
139 140
            if ursina_view.appeared:
                ursina_view.update()
三月三net's avatar
三月三net 已提交
141
        # print('....')
M
march3 已提交
142

三月三net's avatar
三月三net 已提交
143 144
    import sys
    sys.modules["__main__"].update = callback_update
三月三net's avatar
三月三net 已提交
145 146
    if show_trail:
        UrsinaConfig.show_trail = show_trail
三月三net's avatar
三月三net 已提交
147
    simulator.run(dt, light=light, cosmic_bg=cosmic_bg, show_grid=show_grid, bg_music=bg_music)
M
march3 已提交
148 149


M
march3 已提交
150
def mpl_run(bodies, dt=SECONDS_PER_WEEK, gif_file_name=None, gif_max_frame=200):
M
march3 已提交
151 152 153 154
    """

    :param bodies: 天体
    :param dt: 单位:秒,按时间差进行演变,值越小越精确,但演变速度会慢。
M
march3 已提交
155
    :param gif_file_name: 导出的 gif 文件名,如果为空,则显示动画
M
march3 已提交
156 157 158 159 160
    :return:
    """
    from simulators.mpl_simulator import MplSimulator
    body_sys = System(bodies)
    simulator = MplSimulator(body_sys)
M
march3 已提交
161 162

    simulator.run(dt, gif_file_name=gif_file_name, gif_max_frame=gif_max_frame)
M
march3 已提交
163 164


M
march3 已提交
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180
COSMIC_BG_COLOR = "#002563"
COSMIC_FORE_COLOR = "white"


def create_fig_ax(styles={}):
    bg_color = styles["bg_color"] if "bg_color" in styles else COSMIC_BG_COLOR
    fore_color = styles["fore_color"] if "fore_color" in styles else COSMIC_FORE_COLOR
    if bg_color is None:
        fig = plt.figure('天体模拟运行效果', figsize=(20, 12))
    else:
        fig = plt.figure('天体模拟运行效果', figsize=(20, 12), facecolor=bg_color)
    ax = fig.gca(projection="3d")

    return fig, ax


M
march3 已提交
181 182 183 184 185 186 187 188 189 190
if __name__ == '__main__':
    from bodies import Sun, Earth

    """
    太阳、地球
    """
    bodies = [
        Sun(size_scale=1.2e2),  # 太阳放大 120 倍
        Earth(size_scale=4e3, distance_scale=1),  # 地球放大 4000 倍,距离保持不变
    ]
M
march3 已提交
191 192
    # mpl_run(bodies, SECONDS_PER_WEEK)
    ursina_run(bodies, SECONDS_PER_WEEK)