提交 383e5f4c 编写于 作者: M march3

三体运行模拟器

上级 0957d629
...@@ -47,6 +47,18 @@ https://gitcode.net/pythoncr/three_body_sim ...@@ -47,6 +47,18 @@ https://gitcode.net/pythoncr/three_body_sim
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 pyqt5 mayavi
``` ```
# 支持两种模拟器
```shell script
# 进入当前代码的根目录
cd e:\three_body_sim\
SET PYTHONPATH=%CD%
# matplotlib 模拟器(支持动画和导出 gif 文件)
python simulators\mpl_simulator.py
# mayavi模拟器
python simulators\mayavi_simulator.py
```
# 模拟场景运行 # 模拟场景运行
```shell script ```shell script
# 进入当前代码的根目录 # 进入当前代码的根目录
...@@ -54,6 +66,7 @@ cd e:\three_body_sim\ ...@@ -54,6 +66,7 @@ cd e:\three_body_sim\
SET PYTHONPATH=%CD% SET PYTHONPATH=%CD%
# 场景
# 从运行demo开始 # 从运行demo开始
python scenes/demo.py python scenes/demo.py
......
...@@ -51,17 +51,18 @@ def mayavi_run(bodies, dt=SECONDS_PER_WEEK, ...@@ -51,17 +51,18 @@ def mayavi_run(bodies, dt=SECONDS_PER_WEEK,
mlab.show() mlab.show()
def mpl_run(bodies, dt=SECONDS_PER_WEEK): def mpl_run(bodies, dt=SECONDS_PER_WEEK, gif_file_name=None):
""" """
:param bodies: 天体 :param bodies: 天体
:param dt: 单位:秒,按时间差进行演变,值越小越精确,但演变速度会慢。 :param dt: 单位:秒,按时间差进行演变,值越小越精确,但演变速度会慢。
:param gif_file_name: 导出的 gif 文件名,如果为空,则显示动画
:return: :return:
""" """
from simulators.mpl_simulator import MplSimulator from simulators.mpl_simulator import MplSimulator
body_sys = System(bodies) body_sys = System(bodies)
simulator = MplSimulator(body_sys) simulator = MplSimulator(body_sys)
simulator.run(dt) simulator.run(dt, gif_file_name)
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -36,10 +36,16 @@ if __name__ == '__main__': ...@@ -36,10 +36,16 @@ if __name__ == '__main__':
from common.consts import SECONDS_PER_WEEK from common.consts import SECONDS_PER_WEEK
""" """
太阳、地球 3个太阳、1个地球
""" """
bodies = [ bodies = [
Sun(size_scale=1.2e2), # 太阳放大 120 倍 Sun(name='太阳1', mass=1.5e30, init_position=[849597870.700, 0, 0], init_velocity=[0, 7.0, 0],
Earth(size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变 size_scale=5e1, texture="sun1.jpg"), # 太阳放大 100 倍
Sun(name='太阳2', mass=2e30, init_position=[0, 0, 0], init_velocity=[0, -8.0, 0],
size_scale=5e1, texture="sun2.jpg"), # 太阳放大 100 倍
Sun(name='太阳3', mass=2.5e30, init_position=[0, -849597870.700, 0], init_velocity=[18.0, 0, 0],
size_scale=5e1, texture="sun2.jpg"), # 太阳放大 100 倍
Earth(name='地球', init_position=[0, -349597870.700, 0], init_velocity=[15.50, 0, 0],
size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变
] ]
mayavi_run(bodies, SECONDS_PER_WEEK) mayavi_run(bodies, SECONDS_PER_WEEK)
...@@ -12,6 +12,7 @@ from simulators.simulator import Simulator ...@@ -12,6 +12,7 @@ from simulators.simulator import Simulator
from common.system import System from common.system import System
from simulators.views.mpl_view import MplView from simulators.views.mpl_view import MplView
import numpy as np import numpy as np
import copy
plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换默认sans-serif字体) plt.rcParams['font.sans-serif'] = ['SimHei'] # 步骤一(替换默认sans-serif字体)
plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题) plt.rcParams['axes.unicode_minus'] = False # 步骤二(解决坐标轴负数的负号显示问题)
...@@ -25,36 +26,59 @@ class MplSimulator(Simulator): ...@@ -25,36 +26,59 @@ class MplSimulator(Simulator):
def __init__(self, bodies_sys: System): def __init__(self, bodies_sys: System):
super().__init__(bodies_sys, MplView) super().__init__(bodies_sys, MplView)
def run(self, dt): def save_as_gif(self, dt, gif_max_frame=200, gif_file_name='bodies_run.gif'):
""" """
保存 GIF 文件
:param dt: :param dt: 单位:秒,按时间差进行演变,值越小越精确,但演变速度会慢。
:param gif_max_frame: 导出的 gif 的最多帧数
:param gif_file_name: 导出的 gif 文件名
:return: :return:
""" """
fig = plt.figure('天体模拟运行效果', figsize=(16, 12)) fig = plt.figure('天体模拟运行效果', figsize=(16, 12))
ax = fig.gca(projection="3d") ax = fig.gca(projection="3d")
save_gif = True
MAX_FRAME = 200
import copy
views_frames = [] views_frames = []
for i in range(MAX_FRAME): for i in range(gif_max_frame):
self.evolve(dt) self.evolve(dt)
body_views = copy.deepcopy(self.body_views) body_views = copy.deepcopy(self.body_views)
if not save_gif:
self.show_figure(ax, body_views, pause=0.1)
views_frames.append(body_views) views_frames.append(body_views)
if save_gif: def update(num):
# TODO: views_frames 用于 gif 动画 body_views = views_frames[num]
def update(num): print("GIF 生成进度:%d/%d %.2f" % (num + 1, gif_max_frame, ((num + 1) / gif_max_frame) * 100) + "%")
body_views = views_frames[num] return self.show_figure(ax, body_views, pause=0)
return self.show_figure(ax, body_views, pause=0)
ani = animation.FuncAnimation(fig=fig, func=update, frames=np.arange(0, gif_max_frame), interval=1)
ani.save(gif_file_name)
def run(self, dt, gif_file_name=None):
"""
:param dt: 单位:秒,按时间差进行演变,值越小越精确,但演变速度会慢。
:param gif_file_name: 导出的 gif 文件名,如果为空,则显示动画
:return:
"""
if gif_file_name is not None:
self.save_as_gif(dt, gif_max_frame=200, gif_file_name=gif_file_name)
return
fig = plt.figure('天体模拟运行效果', figsize=(16, 12))
ax = fig.gca(projection="3d")
# TODO: 注意:显示动态图,需先进行以下设置:
# Pycharm::File –> Settings –> Tools –> Python Scientific –> Show plots in tool window(取消打勾)
ani = animation.FuncAnimation(fig=fig, func=update, frames=np.arange(0, MAX_FRAME), interval=1) while True:
ani.save('bodies_run.gif') self.evolve(dt)
# plt.show() body_views = copy.deepcopy(self.body_views)
self.show_figure(ax, body_views, pause=0.1)
def show_figure(self, ax, bodies, pause=0.1): def show_figure(self, ax, bodies, pause=0.1):
"""
:param ax:
:param bodies:
:param pause:
:return:
"""
plt.cla() plt.cla()
ax.set_title('天体模拟运行效果') ax.set_title('天体模拟运行效果')
...@@ -89,7 +113,7 @@ class MplSimulator(Simulator): ...@@ -89,7 +113,7 @@ class MplSimulator(Simulator):
if __name__ == '__main__': if __name__ == '__main__':
# TODO: 注意:绘制动态图,需先进行以下设置: # TODO: 注意:显示动态图,需先进行以下设置:
# Pycharm::File –> Settings –> Tools –> Python Scientific –> Show plots in tool window(取消打勾) # Pycharm::File –> Settings –> Tools –> Python Scientific –> Show plots in tool window(取消打勾)
from scenes.func import mpl_run from scenes.func import mpl_run
from bodies import Sun, Earth from bodies import Sun, Earth
...@@ -108,4 +132,6 @@ if __name__ == '__main__': ...@@ -108,4 +132,6 @@ if __name__ == '__main__':
Earth(name='地球', init_position=[0, -349597870.700, 0], init_velocity=[15.50, 0, 0], Earth(name='地球', 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 倍,距离保持不变
] ]
mpl_run(bodies, SECONDS_PER_WEEK) gif_file_name = None # 显示动画
# gif_file_name = 'bodies_run.gif' # 保存 GIF 文件
mpl_run(bodies, SECONDS_PER_WEEK, gif_file_name)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册