提交 9cd2a861 编写于 作者: 三月三net's avatar 三月三net

Merge remote-tracking branch 'origin/dev'

...@@ -9,6 +9,7 @@ ...@@ -9,6 +9,7 @@
我们可以自己通过调整天体的初始坐标、质量和矢量速度等等参数来自定义各种场景来控制天体的运行效果。 我们可以自己通过调整天体的初始坐标、质量和矢量速度等等参数来自定义各种场景来控制天体的运行效果。
# 效果图 # 效果图
<img src="https://gitcode.net/pythoncr/three_body_sim/-/raw/dev/images/solar_system_3.png" width="80.7%">
<img src="https://gitcode.net/pythoncr/three_body_sim/-/raw/master/images/solar_system_1.png" width="40%"> <img src="https://gitcode.net/pythoncr/three_body_sim/-/raw/master/images/solar_system_1.png" width="40%">
<img src="https://gitcode.net/pythoncr/three_body_sim/-/raw/master/images/solar_system_2.png" width="40%"> <img src="https://gitcode.net/pythoncr/three_body_sim/-/raw/master/images/solar_system_2.png" width="40%">
<img src="https://gitcode.net/pythoncr/three_body_sim/-/raw/master/images/three_body_1.png" width="40%"> <img src="https://gitcode.net/pythoncr/three_body_sim/-/raw/master/images/three_body_1.png" width="40%">
...@@ -44,10 +45,10 @@ https://gitcode.net/pythoncr/three_body_sim ...@@ -44,10 +45,10 @@ https://gitcode.net/pythoncr/three_body_sim
# 安装 Python 库 # 安装 Python 库
```shell script ```shell script
# 先安装基础包 # 先安装基础包
pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com pyqt5 mayavi pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com ursina pyqt5 pyglet mayavi
``` ```
# 支持种模拟器 # 支持种模拟器
```shell script ```shell script
# 进入当前代码的根目录 # 进入当前代码的根目录
cd e:\three_body_sim\ cd e:\three_body_sim\
...@@ -58,6 +59,9 @@ python simulators\mpl_simulator.py ...@@ -58,6 +59,9 @@ python simulators\mpl_simulator.py
# mayavi模拟器 # mayavi模拟器
python simulators\mayavi_simulator.py python simulators\mayavi_simulator.py
# ursina模拟器
python simulators\ursina_simulator.py
``` ```
# 模拟场景运行 # 模拟场景运行
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies.body import Body, AU from bodies.body import Body, AU
from bodies import Earth
class Moon(Body): class Moon(Body):
...@@ -37,6 +38,18 @@ class Moon(Body): ...@@ -37,6 +38,18 @@ class Moon(Body):
} }
super().__init__(**params) super().__init__(**params)
def ignore_gravity(self, body):
"""
是否忽略引力
:param body:
:return:
"""
# 月球只对地球有引力,忽略其他的引力
if isinstance(body, Earth):
return False
return True
if __name__ == '__main__': if __name__ == '__main__':
moon = Moon() moon = Moon()
......
# -*- coding:utf-8 -*-
# title :宇宙背景星空图片生成
# description :宇宙背景星空图片生成
# author :Python超人
# date :2023-02-11
# link :https://gitcode.net/pythoncr/
# python_version :3.8
# ==============================================================================
from PIL import Image
from random import randint
import time
xSize = 2048
ySize = 1024
x = int(xSize / 2)
y = int(ySize / 2)
im = Image.new('RGBA', (xSize, ySize), 'black')
im.getpixel((x, y))
step = 2000
def move():
"""随机生成并返回12345678个数字,分别代表 上右下左 右上 右下 左下 左上"""
return randint(0, xSize - 1), randint(0, ySize - 1)
def color():
"""在所在像素下点涂颜色"""
global im, x, y
add_color = 255
src_str_list = im.load()
data = src_str_list[x, y]
data_list = list(data)
print(data)
if data_list[0] < 255:
data_list[0] += add_color
data_list[1] += add_color
data_list[2] += add_color
data = tuple(data_list)
im.putpixel((x, y), data)
def judge():
"""判断是否已经走到边界上"""
global x, y, xSize, ySize
b = int(xSize / 2)
if x >= xSize - 1:
x -= b
if y >= ySize - 1:
y -= b
if x <= 1:
x += b
if y <= 0:
y += b
def draw():
"""根据move返回值来移动图片上的像素点"""
global x, y, im
x, y = move()
color()
for i in range(step):
move()
draw()
judge()
im.save(f'cosmic.png')
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
# ============================================================================== # ==============================================================================
from bodies import Sun, Earth from bodies import Sun, Earth
from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY
from scenes.func import mayavi_run, mpl_run from scenes.func import mayavi_run, mpl_run, ursina_run
from bodies.body import Body, AU from bodies.body import Body, AU
if __name__ == '__main__': if __name__ == '__main__':
...@@ -40,7 +40,10 @@ if __name__ == '__main__': ...@@ -40,7 +40,10 @@ if __name__ == '__main__':
texture="pythoncr.jpg", size_scale=5e3, distance_scale=1.0), texture="pythoncr.jpg", size_scale=5e3, distance_scale=1.0),
] ]
# 使用 mayavi 查看的运行效果 # 使用 mayavi 查看的运行效果
mayavi_run(bodies, SECONDS_PER_DAY, view_azimuth=135) # mayavi_run(bodies, SECONDS_PER_DAY, view_azimuth=135)
# 使用 matplotlib 查看运行效果 # 使用 matplotlib 查看运行效果
# mpl_run(bodies, SECONDS_PER_WEEK) # mpl_run(bodies, SECONDS_PER_WEEK)
# 使用 ursina 查看的运行效果
ursina_run(bodies, SECONDS_PER_WEEK, position=(0, 0, 0))
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Sun, Earth, Moon from bodies import Sun, Earth, Moon
from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY from common.consts import SECONDS_PER_HOUR, SECONDS_PER_HALF_DAY, SECONDS_PER_DAY, SECONDS_PER_WEEK
from scenes.func import mayavi_run from scenes.func import mayavi_run, ursina_run
from bodies.body import AU from bodies.body import AU
if __name__ == '__main__': if __name__ == '__main__':
...@@ -24,3 +24,6 @@ if __name__ == '__main__': ...@@ -24,3 +24,6 @@ if __name__ == '__main__':
init_velocity=[0, EARTH_INIT_VELOCITY + 1.023, 0], size_scale=1e1) # 月球放大 10 倍,距离保持不变 init_velocity=[0, EARTH_INIT_VELOCITY + 1.023, 0], size_scale=1e1) # 月球放大 10 倍,距离保持不变
] ]
mayavi_run(bodies, SECONDS_PER_HALF_DAY / 2, view_azimuth=-45) mayavi_run(bodies, SECONDS_PER_HALF_DAY / 2, view_azimuth=-45)
# 使用 ursina 查看的运行效果
# ursina_run(bodies, SECONDS_PER_DAY, position=(0, 0, 0))
\ No newline at end of file
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from common.consts import SECONDS_PER_WEEK from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, SECONDS_PER_HALF_DAY
from common.system import System from common.system import System
...@@ -52,6 +52,37 @@ def mayavi_run(bodies, dt=SECONDS_PER_WEEK, ...@@ -52,6 +52,37 @@ def mayavi_run(bodies, dt=SECONDS_PER_WEEK,
mlab.show() mlab.show()
def ursina_run(bodies,
dt=SECONDS_PER_HALF_DAY,
position=(4000000, 800000000, 4000000),
light=True,
cosmic_bg=None,
show_grid=True):
"""
:param bodies:
:param dt:
:return:
"""
from simulators.ursina_simulator import UrsinaSimulator, UrsinaPlayer
from ursina import application, Sequence
body_sys = System(bodies)
simulator = UrsinaSimulator(body_sys)
player = UrsinaPlayer(position, simulator.ursina_views)
def callback_update():
for ursina_view in simulator.ursina_views:
simulator.check_and_evolve()
ursina_view.update()
# print('....')
import sys
sys.modules["__main__"].update = callback_update
simulator.run(dt, light=light, cosmic_bg=cosmic_bg, show_grid=show_grid)
def mpl_run(bodies, dt=SECONDS_PER_WEEK, gif_file_name=None, gif_max_frame=200): def mpl_run(bodies, dt=SECONDS_PER_WEEK, gif_file_name=None, gif_max_frame=200):
""" """
...@@ -93,4 +124,5 @@ if __name__ == '__main__': ...@@ -93,4 +124,5 @@ if __name__ == '__main__':
Sun(size_scale=1.2e2), # 太阳放大 120 倍 Sun(size_scale=1.2e2), # 太阳放大 120 倍
Earth(size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变 Earth(size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变
] ]
mpl_run(bodies, SECONDS_PER_WEEK) # mpl_run(bodies, SECONDS_PER_WEEK)
ursina_run(bodies, SECONDS_PER_WEEK)
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto, Moon from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto, Moon
from common.consts import SECONDS_PER_WEEK from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY
from scenes.func import mayavi_run from scenes.func import mayavi_run, ursina_run
if __name__ == '__main__': if __name__ == '__main__':
# 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿) # 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿)
...@@ -31,4 +31,7 @@ if __name__ == '__main__': ...@@ -31,4 +31,7 @@ if __name__ == '__main__':
Neptune(size_scale=1e3), # 海王星放大 1000 倍,距离保持不变 Neptune(size_scale=1e3), # 海王星放大 1000 倍,距离保持不变
Pluto(size_scale=10e3), # 冥王星放大 10000 倍,距离保持不变(从太阳系的行星中排除) Pluto(size_scale=10e3), # 冥王星放大 10000 倍,距离保持不变(从太阳系的行星中排除)
] ]
mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45)
# mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45)
ursina_run(bodies, SECONDS_PER_DAY, position=(0, 0, 0))
\ No newline at end of file
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
from common.consts import SECONDS_PER_WEEK from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY
from scenes.func import mayavi_run from scenes.func import mayavi_run, ursina_run
if __name__ == '__main__': if __name__ == '__main__':
# 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿) # 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿)
...@@ -36,4 +36,6 @@ if __name__ == '__main__': ...@@ -36,4 +36,6 @@ if __name__ == '__main__':
] ]
# endregion # endregion
mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45, view_distance=3e9, view_focalpoint=[5e2, 5e2, 5e2]) # mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45, view_distance=3e9, view_focalpoint=[5e2, 5e2, 5e2])
ursina_run(bodies, SECONDS_PER_DAY, position=(0, 0, 0))
\ No newline at end of file
...@@ -7,8 +7,8 @@ ...@@ -7,8 +7,8 @@
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Sun, Earth from bodies import Sun, Earth
from common.consts import SECONDS_PER_WEEK from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY
from scenes.func import mayavi_run from scenes.func import mayavi_run, ursina_run
if __name__ == '__main__': if __name__ == '__main__':
""" """
...@@ -18,4 +18,6 @@ if __name__ == '__main__': ...@@ -18,4 +18,6 @@ if __name__ == '__main__':
Sun(size_scale=1.2e2), # 太阳放大 120 倍 Sun(size_scale=1.2e2), # 太阳放大 120 倍
Earth(size_scale=2e3, distance_scale=1), # 地球放大 2000 倍,距离保持不变 Earth(size_scale=2e3, distance_scale=1), # 地球放大 2000 倍,距离保持不变
] ]
mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45) # mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45)
ursina_run(bodies, SECONDS_PER_DAY, position=(0, 0, 0))
...@@ -6,10 +6,9 @@ ...@@ -6,10 +6,9 @@
# link :https://gitcode.net/pythoncr/ # link :https://gitcode.net/pythoncr/
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from mayavi import mlab
from bodies import Sun, Earth from bodies import Sun, Earth
from common.consts import SECONDS_PER_WEEK from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY
from scenes.func import mayavi_run from scenes.func import mayavi_run, ursina_run
if __name__ == '__main__': if __name__ == '__main__':
""" """
...@@ -21,7 +20,7 @@ if __name__ == '__main__': ...@@ -21,7 +20,7 @@ if __name__ == '__main__':
""" """
bodies = [ bodies = [
Sun(mass=1.5e30, init_position=[849597870.700, 0, 0], init_velocity=[0, 7.0, 0], Sun(mass=1.5e30, init_position=[849597870.700, 0, 0], init_velocity=[0, 7.0, 0],
size_scale=5e1, texture="sun1.jpg"), # 太阳放大 100 倍 size_scale=5e1, texture="sun2.jpg"), # 太阳放大 100 倍
Sun(mass=2e30, init_position=[0, 0, 0], init_velocity=[0, -8.0, 0], Sun(mass=2e30, init_position=[0, 0, 0], init_velocity=[0, -8.0, 0],
size_scale=5e1, texture="sun2.jpg"), # 太阳放大 100 倍 size_scale=5e1, texture="sun2.jpg"), # 太阳放大 100 倍
Sun(mass=2.5e30, init_position=[0, -849597870.700, 0], init_velocity=[18.0, 0, 0], Sun(mass=2.5e30, init_position=[0, -849597870.700, 0], init_velocity=[18.0, 0, 0],
...@@ -29,4 +28,8 @@ if __name__ == '__main__': ...@@ -29,4 +28,8 @@ if __name__ == '__main__':
Earth(init_position=[0, -349597870.700, 0], init_velocity=[15.50, 0, 0], Earth(init_position=[0, -349597870.700, 0], init_velocity=[15.50, 0, 0],
size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变 size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变
] ]
mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=0) # 使用 mayavi 查看的运行效果
# mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=0)
# 使用 ursina 查看的运行效果
ursina_run(bodies, SECONDS_PER_DAY, position=(0, 0, 0))
\ No newline at end of file
...@@ -6,10 +6,9 @@ ...@@ -6,10 +6,9 @@
# link :https://gitcode.net/pythoncr/ # link :https://gitcode.net/pythoncr/
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from mayavi import mlab
from bodies import Sun, Earth from bodies import Sun, Earth
from common.consts import SECONDS_PER_WEEK from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY
from scenes.func import mayavi_run from scenes.func import mayavi_run, ursina_run
if __name__ == '__main__': if __name__ == '__main__':
""" """
......
...@@ -6,10 +6,9 @@ ...@@ -6,10 +6,9 @@
# link :https://gitcode.net/pythoncr/ # link :https://gitcode.net/pythoncr/
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from mayavi import mlab
from bodies import Sun, Earth from bodies import Sun, Earth
from common.consts import SECONDS_PER_WEEK from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY
from scenes.func import mayavi_run, mpl_run from scenes.func import mayavi_run, mpl_run, ursina_run
if __name__ == '__main__': if __name__ == '__main__':
""" """
...@@ -51,5 +50,11 @@ if __name__ == '__main__': ...@@ -51,5 +50,11 @@ if __name__ == '__main__':
初始速度:(-3.0, 1.0, -2.0) km/s 初始速度:(-3.0, 1.0, -2.0) km/s
质量:2.8 x 10^30 kg 质量:2.8 x 10^30 kg
""" """
# 使用 mayavi 查看的运行效果
# mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=0) # mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=0)
# 使用 matplotlib 查看运行效果
mpl_run(bodies, SECONDS_PER_WEEK) mpl_run(bodies, SECONDS_PER_WEEK)
# 使用 ursina 查看的运行效果
# ursina_run(bodies, SECONDS_PER_WEEK, position=(0, 0, 0))
...@@ -6,7 +6,6 @@ ...@@ -6,7 +6,6 @@
# link :https://gitcode.net/pythoncr/ # link :https://gitcode.net/pythoncr/
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from mayavi import mlab
from bodies import Sun, Earth from bodies import Sun, Earth
from common.consts import SECONDS_PER_WEEK from common.consts import SECONDS_PER_WEEK
from scenes.func import mayavi_run from scenes.func import mayavi_run
......
# -*- coding:utf-8 -*-
# title :manim天体运行模拟器
# description :manim天体运行模拟器
# author :Python超人
# date :2023-02-11
# link :https://gitcode.net/pythoncr/
# python_version :3.8
# manim version :Manim Community v0.17.2
# ==============================================================================
# 环境安装教程参考:
# https://blog.csdn.net/FRIGIDWINTER/article/details/121526956
import os
from manim import *
from manim import *
from manim.mobject.three_d import Sphere
from manim.three_d.light import *
from manim.mobject.opengl import *
from PIL import Image
class TexturedSphere(ThreeDVMobject):
def __init__(self, radius=1, u_min=0, u_max=1, v_min=0, v_max=1, **kwargs):
self.radius = radius
self.u_min = u_min
self.u_max = u_max
self.v_min = v_min
self.v_max = v_max
super().__init__(**kwargs)
def init_points(self):
sphere = Sphere(radius=self.radius).mesh
for i in range(len(sphere[0])):
u, v = sphere[0][i], sphere[1][i]
self.add_point(self.radius * np.array([
np.cos(u) * np.sin(v),
np.sin(u) * np.sin(v),
np.cos(v)
]))
self.add_tex_coords([
interpolate(self.u_min, self.u_max, u / (2 * np.pi)),
interpolate(self.v_min, self.v_max, v / np.pi)
])
self.set_color_by_tex()
def set_color_by_tex(self, texture_file='saturn.jpg'):
texture_path = f'textures/{texture_file}'
texture = Image.open(texture_path).transpose(Image.FLIP_TOP_BOTTOM).convert('RGBA')
self.set_texture(texture)
class TexturedSaturn(Scene):
def construct(self):
sphere = TexturedSphere(radius=2.5, texture_file='saturn.jpg')
rings = TexturedSphere(radius=3.5, texture_file='saturnRings.jpg', u_min=0.2, u_max=0.8, v_min=0.2, v_max=0.8)
rings.set_rotation(right=PI / 2)
rings.set_shade_in_3d(True)
rings.set_opacity(0.8)
light = ThreeDPointLight(
location=5 * OUT + 5 * RIGHT + 5 * UP,
color=WHITE,
)
ambient = ThreeDAmbientLight(color="#444444")
self.add(light, ambient, sphere, rings)
self.set_camera_orientation(phi=75 * DEGREES, theta=-30 * DEGREES)
self.begin_ambient_camera_rotation(rate=0.2)
self.wait(20)
self.stop_ambient_camera_rotation()
if __name__ == '__main__':
os.system("manim -pqh manim_simulator.py TexturedSaturn")
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
# date :2023-02-11 # date :2023-02-11
# link :https://gitcode.net/pythoncr/ # link :https://gitcode.net/pythoncr/
# python_version :3.8 # python_version :3.8
# mayavi version :4.8.1
# ============================================================================== # ==============================================================================
from mayavi import mlab from mayavi import mlab
from simulators.simulator import Simulator from simulators.simulator import Simulator
......
# -*- coding:utf-8 -*-
# title :pyglet天体运行模拟器
# description :pyglet天体运行模拟器
# author :Python超人
# date :2023-02-11
# link :https://gitcode.net/pythoncr/
# python_version :3.8
# ==============================================================================
# pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com pyglet
# -*- coding:utf-8 -*-
# title :ursina天体运行模拟器
# description :ursina天体运行模拟器
# author :Python超人
# date :2023-02-11
# link :https://gitcode.net/pythoncr/
# python_version :3.8
# ==============================================================================
# pip install -i http://pypi.douban.com/simple/ --trusted-host=pypi.douban.com ursina
from ursina import Ursina, window, Entity, Grid, Mesh, camera, color, mouse, Vec2, Vec3, load_texture, held_keys
from ursina.prefabs.first_person_controller import FirstPersonController
from simulators.views.ursina_view import UrsinaView, UrsinaPlayer
from simulators.simulator import Simulator
from common.system import System
import time
import datetime
from ursina import EditorCamera, PointLight, SpotLight, AmbientLight
from scenes.func import ursina_run
class WorldGrid(Entity): # Entity # 定义构造方法
def __init__(self):
super().__init__()
s = 100
grid = Entity(model=Grid(s, s), scale=s * 20, color=color.color(0, 0, .1, 1), rotation_x=90,
position=(0, -80, 0))
vertsx = ((0, 0, 0), (10, 0, 0))
Entity(model=Mesh(vertices=vertsx, mode='line', thickness=3), color=color.cyan).set_light_off()
vertsyz = [(0, 0, 0), (0, 10, 0), (0, 0, 0), (0, 0, 10)]
Entity(model=Mesh(vertices=vertsyz, mode='line', thickness=3), color=color.yellow).set_light_off()
grid.set_light_off()
class UrsinaSimulator(Simulator):
def __init__(self, bodies_sys: System):
self.app = Ursina()
self.ursina_views = []
window.color = color.black
super().__init__(bodies_sys, UrsinaView)
# ps = ["sun", "mercury", "venus", "earth", "mars", "jupiter", "saturn", "uranus", "neptune"]
# cp = [200, 15, 35, 42, 20, 160, 145, 90, 80]
# x, y, z = 0, 0, 0
for i, view in enumerate(self.body_views):
# pos = tuple(body.position)
# ursina_view = UrsinaView(body)
view.update()
self.ursina_views.append(view)
# planets.append(newPlanet)
# x += cp[i] * 10
def check_elapsed_time(self):
"""检查时间间隔是否已过"""
now = datetime.datetime.now()
elapsed_time = now - self.last_time
value = elapsed_time >= self.interval
if value:
self.last_time = now
return value
def check_and_evolve(self):
if self.check_elapsed_time():
super().evolve(self.evolve_dt)
def cosmic_background(self, texture='../textures/cosmic1.jpg'):
"""
加入宇宙背景
:param texture:
:return:
"""
# Add skybox
from ursina import Sky
Sky(texture=texture)
# texture = load_texture(texture)
# sky_dome = Entity(model='sky_dome', texture=texture, scale=10000,
# color=color.white,
# position=(0, 0, 0),
# rotation=(0, 0, 0))
def run(self, dt, **kwargs):
from ursina import EditorCamera, PointLight, SpotLight, AmbientLight, DirectionalLight
self.evolve_dt = dt
# 设定时间间隔为1秒
self.interval = datetime.timedelta(seconds=0.01)
self.last_time = datetime.datetime.now() - datetime.timedelta(seconds=2)
if "light" in kwargs:
if kwargs["light"]:
for v in self.ursina_views:
if v.body.is_fixed_star:
v.light = PointLight(parent=v)
# PointLight(parent=camera, color=color.white, position=(0, 0, 0))
# AmbientLight(color=color.rgba(100, 100, 100, 0.1))
# DirectionalLight
# SpotLight
if "show_grid" in kwargs:
if kwargs["show_grid"]:
WorldGrid()
if "cosmic_bg" in kwargs:
cosmic_bg = kwargs["cosmic_bg"]
if cosmic_bg is None:
# cosmic_bg = '../textures/cosmic1.png'
cosmic_bg = '../textures/cosmic2.jpg'
import os
if cosmic_bg is not None and os.path.exists(cosmic_bg):
self.cosmic_background(cosmic_bg)
EditorCamera()
self.app.run()
if __name__ == '__main__':
from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto, Moon
from bodies.body import AU
from common.consts import SECONDS_PER_WEEK, SECONDS_PER_DAY, SECONDS_PER_HALF_DAY
"""
3个太阳、1个地球
"""
bodies = [
Sun(name='太阳1', mass=1.5e30, init_position=[849597870.700, 0, 0], init_velocity=[0, 7.0, 0],
size_scale=5e1, texture="sun.png"), # 太阳放大 100 倍
Sun(name='太阳2', mass=2e30, init_position=[0, 0, 0], init_velocity=[0, -8.0, 0],
size_scale=5e1, texture="sun.png"), # 太阳放大 100 倍
Sun(name='太阳3', mass=2.5e30, init_position=[0, -849597870.700, 0], init_velocity=[18.0, 0, 0],
size_scale=5e1, texture="sun.png"), # 太阳放大 100 倍
Earth(name='地球', init_position=[0, -349597870.700, 0], init_velocity=[15.50, 0, 0],
size_scale=4e3, texture="earth.png", distance_scale=1), # 地球放大 4000 倍,距离保持不变
]
# bodies = [
#
# Sun(name='太阳2', mass=1.5e30, init_position=[0, 0, 0], init_velocity=[0, -8.0, 0],
# size_scale=5e1, texture="sun.png"), # 太阳放大 100 倍
# Sun(name='太阳2', mass=1.5e30, init_position=[849597870.700, 0, 0], init_velocity=[0, -8.0, 0],
# size_scale=5e1, texture="sun.png"), # 太阳放大 100 倍
# Sun(name='太阳2', mass=1.5e30, init_position=[0, -849597870.700, 0], init_velocity=[0, -8.0, 0],
# size_scale=5e1, texture="sun.png"), # 太阳放大 100 倍
# Earth(name='地球', mass=5.97237e24, init_position=[0, -349597870.700, 0], init_velocity=[15.50, 0, 0],
# size_scale=4e3, texture="earth.png", distance_scale=1), # 地球放大 4000 倍,距离保持不变
# ]
bodies = [
Sun(size_scale=0.8e2), # 太阳放大 80 倍
Mercury(size_scale=4e3, distance_scale=1.3), # 水星放大 4000 倍,距离放大 1.3 倍
Venus(size_scale=4e3, distance_scale=1.3), # 金星放大 4000 倍,距离放大 1.3 倍
Earth(init_position=[1.12 * AU, 0, 0],
init_velocity=[0, 29.79, 0], size_scale=4e3, distance_scale=1.3), # 地球放大 4000 倍,距离放大 1.3 倍
Moon(init_position=[363104 + 1.12 * AU, 0, 0],
init_velocity=[-9, 29.79 + 1.023, 0], size_scale=4e3, distance_scale=1.3),
Mars(size_scale=4e3, distance_scale=1.3), # 火星放大 4000 倍,距离放大 1.3 倍
Jupiter(size_scale=0.68e3, distance_scale=0.65), # 木星放大 680 倍,距离缩小到真实距离的 0.65
Saturn(size_scale=0.68e3, distance_scale=0.52), # 土星放大 680 倍,距离缩小到真实距离的 0.52
Uranus(size_scale=0.8e3, distance_scale=0.36), # 天王星放大 800 倍,距离缩小到真实距离的 0.36
Neptune(size_scale=1e3, distance_scale=0.27), # 海王星放大 1000 倍,距离缩小到真实距离的 0.27
Pluto(size_scale=10e3, distance_scale=0.23), # 冥王星放大 10000 倍,距离缩小到真实距离的 0.23(从太阳系的行星中排除)
]
ursina_run(bodies, SECONDS_PER_DAY, position=(AU * 2, AU * 2, AU * 3), show_grid=True)
...@@ -30,11 +30,11 @@ class BodyView(metaclass=ABCMeta): ...@@ -30,11 +30,11 @@ class BodyView(metaclass=ABCMeta):
else: else:
self.color = self.__get_texture_main_color(self.texture) self.color = self.__get_texture_main_color(self.texture)
self.appear() self.appear()
self.position = [None, None, None] self.position = body.position
self.name = None self.name = body.name
self.mass = None self.mass = body.mass
self.raduis = None self.raduis = body.raduis
self.velocity = None self.velocity = body.velocity
self.appeared = True self.appeared = True
......
# -*- coding:utf-8 -*-
# title :ursina天体视图
# description :ursina天体视图(天体效果展示用,需要安装 ursina)
# author :Python超人
# date :2023-02-11
# link :https://gitcode.net/pythoncr/
# 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, SmoothFollow, Texture, clamp, time, camera, color, mouse, Vec2, Vec3, \
load_texture, held_keys
# from ursina.camera import OrthographicCamera
from math import sin, cos, radians
from ursina.prefabs.first_person_controller import FirstPersonController
import sys
import random as rd
import os
from bodies import Body
import random
from simulators.views.body_view import BodyView
import numpy as np
import math
SCALE_FACTOR = 1e-6
class UrsinaPlayer(FirstPersonController):
"""
"""
def __init__(self, position, targets=None):
super().__init__()
camera.fov = 100
camera.rotation_y = 90
self.planets = None
if targets is not None:
self.planets = []
# targets = [view.planet.parent for view in targets]
# targets_parent = Entity()
for view in targets:
# view.planet.parent = targets_parent
self.planets.append(view.planet)
# self.camera_adj(planets)
# # planets.append(view.planet)
#
# camera.add_script(SmoothFollow(targets_parent, offset=(0, 8, -20)))
pos = np.array(position) * SCALE_FACTOR
self.position = Vec3(pos[0], pos[1], pos[2])
# 将摄像机位置设置为 x=0、y=1、z=0 的位置
# camera.position = Vec3(pos[0], pos[1], pos[2])
# self.position = Vec3(pos[0], pos[1], pos[2])
# 将摄像机的观察角度绕 x 轴旋转 45 度,绕 y 轴旋转 0 度,绕 z 轴旋转 0 度
camera.rotation = Vec3(45, 90, 0)
# self.gravity = 0
# self.vspeed = 400
# self.speed = 1000
# self.mouse_sensitivity = Vec2(160, 160)
self.on_enable()
# self.rotation_speed = 80
def input(self, key):
if key == "escape":
if mouse.locked:
self.on_disable()
else:
sys.exit()
return super().input(key)
class Planet(Entity):
def __init__(self, body_view: BodyView):
self.body_view = body_view
# 旋转速度和大小成反比(未使用真实数据)
self.rotspeed = 30000 / self.body_view.raduis # random.uniform(1.0, 2.0)
self.rotMode = 'x' # random.choice(["x", "y", "z"])
self.name = body_view.name
pos = body_view.position * body_view.body.distance_scale * SCALE_FACTOR
scale = body_view.body.diameter * body_view.body.size_scale * SCALE_FACTOR
if hasattr(body_view, "texture"):
texture = load_texture(body_view.texture)
else:
texture = None
super().__init__(
model="sphere",
scale=scale,
texture=texture,
color=color.white,
position=pos,
rotation=(0, 0, 0))
def turn(self):
pos = self.body_view.position * SCALE_FACTOR
self.x = -pos[1]
self.y = pos[2]
self.z = pos[0]
self.rotation_y -= self.rotspeed
def input(self, key):
if key == "enter":
self.fastMode = 1 - self.fastMode
class UrsinaView(BodyView):
"""
ursina天体视图(天体效果展示用)
"""
def __init__(self, body: Body):
BodyView.__init__(self, body)
self.velocity = body.velocity
self.planet = Planet(self)
if body.has_rings:
self.create_rings()
if self.body.is_fixed_star:
# 如果是恒星(如:太阳),自身会发光,则需要关闭灯光
self.planet.set_light_off()
def create_rings(self):
"""
创建星环(使用土星贴图)
:return:
"""
scale = 3 * self.body.diameter * self.body.size_scale * SCALE_FACTOR
pos = self.planet.position
self.ring = Entity(model="circle", texture='../textures/saturnRings.jpg', scale=scale, position=pos,
rotation=(70, 0, 0), double_sided=True)
# 假设星环自身会发光
self.ring.set_light_off()
def update(self):
self.planet.turn()
if hasattr(self, "light"):
self.light.position = Vec3(self.planet.x, self.planet.y, self.planet.z)
if hasattr(self, "ring"):
self.ring.position = Vec3(self.planet.x, self.planet.y, self.planet.z)
def appear(self):
pass
def disappear(self):
self.planet.disable()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册