提交 202044b2 编写于 作者: M march3

三体运行模拟器

上级 8f7f33a8
...@@ -27,7 +27,7 @@ class Asteroid(Body): ...@@ -27,7 +27,7 @@ class Asteroid(Body):
""" """
def __init__(self, name="Asteroid", mass=4.1e10, def __init__(self, name="Asteroid", mass=4.1e10,
init_position=[1.5 * AU, 0, 0], init_position=[1.6 * AU, 0, 0],
init_velocity=[0, 25.37, 0], init_velocity=[0, 25.37, 0],
texture="", size_scale=1.0, distance_scale=1.0): texture="", size_scale=1.0, distance_scale=1.0):
params = { params = {
...@@ -43,6 +43,17 @@ class Asteroid(Body): ...@@ -43,6 +43,17 @@ class Asteroid(Body):
} }
super().__init__(**params) super().__init__(**params)
def ignore_gravity(self, body):
"""
是否忽略引力
:param body:
:return:
"""
# 小行星只对恒星有引力,忽略其他行星的引力
if body.is_fixed_star:
return False
return True
if __name__ == '__main__': if __name__ == '__main__':
asteroid = Asteroid() asteroid = Asteroid()
......
...@@ -17,6 +17,7 @@ class Body(metaclass=ABCMeta): ...@@ -17,6 +17,7 @@ class Body(metaclass=ABCMeta):
""" """
天体信息基类 天体信息基类
""" """
def __init__(self, name, mass, init_position, init_velocity, def __init__(self, name, mass, init_position, init_velocity,
density=5e3, color=(125 / 255, 125 / 255, 125 / 255), density=5e3, color=(125 / 255, 125 / 255, 125 / 255),
texture=None, size_scale=1.0, distance_scale=1.0): texture=None, size_scale=1.0, distance_scale=1.0):
...@@ -231,6 +232,15 @@ class Body(metaclass=ABCMeta): ...@@ -231,6 +232,15 @@ class Body(metaclass=ABCMeta):
(self.name, self.mass, self.raduis, (self.name, self.mass, self.raduis,
self.position[0], self.position[1], self.position[2], self.velocity) self.position[0], self.position[1], self.position[2], self.velocity)
def ignore_gravity(self, body):
"""
是否忽略引力
:param body:
:return:
"""
return False
def position_au(self): def position_au(self):
""" """
获取天体的位置(单位:天文单位 A.U.) 获取天体的位置(单位:天文单位 A.U.)
......
...@@ -7,6 +7,9 @@ ...@@ -7,6 +7,9 @@
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from PIL import Image from PIL import Image
from common.consts import AU
import numpy as np
import random
def get_dominant_colors(infile, resize=(20, 20)): def get_dominant_colors(infile, resize=(20, 20)):
...@@ -37,3 +40,136 @@ def get_dominant_colors(infile, resize=(20, 20)): ...@@ -37,3 +40,136 @@ def get_dominant_colors(infile, resize=(20, 20)):
colors.append(tuple(dominant_color)) colors.append(tuple(dominant_color))
return colors return colors
def circle_x_y(points, radius=1.6 * AU):
"""
:param points:
:param radius:
:return:
"""
x = radius * np.cos(points)
y = radius * np.sin(points)
return x, y
def get_position_force(angles, force=1, radius=1, radius_offset=None, force_offset=None):
"""
:param angles:
:param force:
:param radius:
:param radius_offset:
:param force_offset:
:return:
"""
angles = np.array(angles * np.pi)
if isinstance(radius_offset, int):
radius = radius + np.random.rand(len(angles)) * radius_offset
if isinstance(force_offset, int):
force = force + np.random.rand(len(angles)) * force_offset
pxs = radius * np.cos(angles)
pys = radius * np.sin(angles)
fys = force * np.cos(angles) # math.cos(math.radians(angle))
fxs = force * np.sin(angles) # math.sin(math.radians(angle))
# return pxs, pys, fxs, fys
return np.round(pxs, 2), np.round(pys, 2), -np.round(fxs, 2), np.round(fys, 2)
#
#
# import math
#
# """
# 用python写一个函数,根据不同角度的参数列表,返回坐标 pos_x, pos_y,以及分解力fx fy
#
# def get_force(angle_list):
# pos_x = 0
# pos_y = 0
# fx = 0
# fy = 0
# for angle in angle_list:
# force_x, force_y = get_force_from_angle(angle)
# pos_x += force_x
# pos_y += force_y
# fx += force_x
# fy += force_y
#
# return pos_x, pos_y, fx, fy
#
# def get_force_from_angle(angle):
# force_x = math.cos(math.radians(angle))
# force_y = math.sin(math.radians(angle))
# return force_x, force_y
# """
#
# """
# ```python
# def get_positions_forces_from_angles(angles,radius, force):
#
# ```
# """
#
#
# def get_position_force(angle_list, radius=1, force=1):
# fxs = []
# fys = []
# angle_list = np.array(angle_list * np.pi)
# pxs = radius * np.cos(angle_list)
# pys = radius * np.sin(angle_list)
#
# for angle in angle_list:
# fx, fy = get_force_from_angle(angle)
# fxs.append(fx * force)
# fys.append(fy * force)
#
# return np.round(pxs, 2), np.round(pys, 2), np.round(fxs, 2), np.round(fys, 2)
#
#
# def get_force_from_angle(angle):
# force_x = math.cos(angle)
# force_y = math.sin(angle)
# # force_x = math.cos(math.radians(angle))
# # force_y = math.sin(math.radians(angle))
# return force_x, force_y
#
#
# if __name__ == '__main__':
# # a = [0, 45, 90, 135, 180, 225, 270, 315, 360]
# # start:返回样本数据开始点
# # stop:返回样本数据结束点
# # num:生成的样本数据量,默认为50
# points = np.linspace(0, 2 * np.pi, 10)
# # points = np.array([0, 45, 90, 135, 180, 225, 270, 315, 360])
# # points = np.array([0. , 0.17453293, 0.34906585, 0.52359878, 0.6981317 ,
# # 0.87266463, 1.04719755, 1.22173048, 1.3962634 , 1.57079633])
# # x, y = circle_x_y(points, 1)
# # print(x, y)
# print(points)
# pos_x, pos_y, fx, fy = circle_x_y_f(points, radius=1.6, force=25.37)
# print(pos_x, pos_y, fx, fy)
#
# """
# asteroids = [
# Asteroid(size_scale=1e9, # 小行星放大 1000000000 倍,距离保持不变
# init_position=[1.6 * AU, 0, 0],
# init_velocity=[0, 25.37, 0],
# distance_scale=1),
# Asteroid(size_scale=1e9, # 小行星放大 1000000000 倍,距离保持不变
# init_position=[-1.6 * AU, 0, 0],
# init_velocity=[0, -25.37, 0],
# distance_scale=1),
# Asteroid(size_scale=1e9, # 小行星放大 1000000000 倍,距离保持不变
# init_position=[0, 1.6 * AU, 0],
# init_velocity=[-25.37, 0, 0],
# distance_scale=1),
# Asteroid(size_scale=1e9, # 小行星放大 1000000000 倍,距离保持不变
# init_position=[0, -1.6 * AU, 0],
# init_velocity=[25.37, 0, 0],
# distance_scale=1),
# ]
# """
...@@ -69,6 +69,8 @@ class System(object): ...@@ -69,6 +69,8 @@ class System(object):
for body2 in self.bodies: for body2 in self.bodies:
if body1 is body2: if body1 is body2:
continue continue
elif body1.ignore_gravity(body2) or body2.ignore_gravity(body1):
continue
r = body2.position - body1.position r = body2.position - body1.position
# G = 6.67e-11 # 万有引力常数 # G = 6.67e-11 # 万有引力常数
......
...@@ -7,8 +7,11 @@ ...@@ -7,8 +7,11 @@
# python_version :3.8 # python_version :3.8
# ============================================================================== # ==============================================================================
from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto, Asteroid from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto, Asteroid
from bodies.body import AU
from common.consts import SECONDS_PER_WEEK from common.consts import SECONDS_PER_WEEK
from common.func import get_position_force
from scenes.func import mayavi_run from scenes.func import mayavi_run
import numpy as np
if __name__ == '__main__': if __name__ == '__main__':
# 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿) # 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿)
...@@ -20,18 +23,54 @@ if __name__ == '__main__': ...@@ -20,18 +23,54 @@ if __name__ == '__main__':
# 以下展示的效果非太阳系真实的距离和大小 # 以下展示的效果非太阳系真实的距离和大小
# 1、由于宇宙空间尺度非常大,按照实际的大小无法看到行星天体,因此需要对天体的尺寸进行放大 # 1、由于宇宙空间尺度非常大,按照实际的大小无法看到行星天体,因此需要对天体的尺寸进行放大
# 2、对每个行星天体的距离进行了缩放 # 2、对每个行星天体的距离进行了缩放
# 构建4个小行星
# asteroids = [
# Asteroid(size_scale=1e9, # 小行星放大 1000000000 倍,距离保持不变
# init_position=[1.6 * AU, 0, 0],
# init_velocity=[0, 25.37, 0],
# distance_scale=1),
# Asteroid(size_scale=1e9, # 小行星放大 1000000000 倍,距离保持不变
# init_position=[-1.6 * AU, 0, 0],
# init_velocity=[0, -25.37, 0],
# distance_scale=1),
# Asteroid(size_scale=1e9, # 小行星放大 1000000000 倍,距离保持不变
# init_position=[0, 1.6 * AU, 0],
# init_velocity=[-25.37, 0, 0],
# distance_scale=1),
# Asteroid(size_scale=1e9, # 小行星放大 1000000000 倍,距离保持不变
# init_position=[0, -1.6 * AU, 0],
# init_velocity=[25.37, 0, 0],
# distance_scale=1),
# ]
# 构建 50 小行星,太多的小行星会影响电脑性能
NUM_OF_ASTEROIDS = 60
asteroids = []
angles = np.linspace(0, 40 * np.pi, NUM_OF_ASTEROIDS)
pxs, pys, fxs, fys = get_position_force(angles,
radius=1.60 * AU,
force=23.37,
radius_offset=0.2 * AU,
force_offset=0.2)
for i, px in enumerate(pxs):
py, fx, fy = pys[i], fxs[i], fys[i]
asteroids.append(Asteroid(size_scale=1e9, # 小行星放大 1000000000 倍,距离保持不变
init_position=[px, py, 0],
init_velocity=[fx, fy, 0],
distance_scale=1.2))
bodies = [ bodies = [
Sun(size_scale=0.8e2), # 太阳放大 80 倍 Sun(size_scale=0.8e2), # 太阳放大 80 倍
Mercury(size_scale=4e3, distance_scale=1), # 水星放大 4000 倍,距离保持不变 Mercury(size_scale=4e3, distance_scale=1.1), # 水星放大 4000 倍,距离保持不变
Venus(size_scale=4e3, distance_scale=1), # 金星放大 4000 倍,距离保持不变 Venus(size_scale=4e3, distance_scale=1.1), # 金星放大 4000 倍,距离保持不变
Earth(size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变 Earth(size_scale=4e3, distance_scale=1.1), # 地球放大 4000 倍,距离保持不变
Mars(size_scale=4e3, distance_scale=1), # 火星放大 4000 倍,距离保持不变 Mars(size_scale=4e3, distance_scale=1.1), # 火星放大 4000 倍,距离保持不变
# Asteroid(size_scale=4e4, distance_scale=1), # 小行星放大 40000 倍,距离保持不变
Jupiter(size_scale=0.8e3, distance_scale=0.5), # 木星放大 800 倍,距离缩小到真实距离的 0.5 Jupiter(size_scale=0.8e3, distance_scale=0.5), # 木星放大 800 倍,距离缩小到真实距离的 0.5
Saturn(size_scale=0.8e3, distance_scale=0.38), # 土星放大 800 倍,距离缩小到真实距离的 0.38 Saturn(size_scale=0.8e3, distance_scale=0.38), # 土星放大 800 倍,距离缩小到真实距离的 0.38
Uranus(size_scale=0.8e3, distance_scale=0.26), # 天王星放大 800 倍,距离缩小到真实距离的 0.26 Uranus(size_scale=0.8e3, distance_scale=0.26), # 天王星放大 800 倍,距离缩小到真实距离的 0.26
Neptune(size_scale=1e3, distance_scale=0.22), # 海王星放大 1000 倍,距离缩小到真实距离的 0.22 Neptune(size_scale=1e3, distance_scale=0.22), # 海王星放大 1000 倍,距离缩小到真实距离的 0.22
Pluto(size_scale=10e3, distance_scale=0.20), # 冥王星放大 10000 倍,距离缩小到真实距离的 0.2(从太阳系的行星中排除) Pluto(size_scale=10e3, distance_scale=0.20), # 冥王星放大 10000 倍,距离缩小到真实距离的 0.2(从太阳系的行星中排除)
] ]
bodies += asteroids
# mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45)
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])
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册