diff --git a/bodies/__init__.py b/bodies/__init__.py index 9698ae7222e06226945fdaebca048288d0f06e02..20f70246f6e96daa99a053c7e2f37e059d3879d9 100644 --- a/bodies/__init__.py +++ b/bodies/__init__.py @@ -9,3 +9,4 @@ from bodies.pluto import Pluto from bodies.saturn import Saturn from bodies.uranus import Uranus from bodies.venus import Venus +from bodies.moon import Moon diff --git a/bodies/body.py b/bodies/body.py index d8e0a446ca1996bd09283be1ed9647f78695a2e1..78bacb3d7f818050b40a6850bb99b4ba99d04913 100644 --- a/bodies/body.py +++ b/bodies/body.py @@ -6,13 +6,14 @@ # notes : # python_version :3.8 # ============================================================================== +from abc import ABCMeta, abstractmethod import json import numpy as np import math from common.consts import AU -class Body: +class Body(metaclass=ABCMeta): def __init__(self, name, mass, init_position, init_velocity, density=5e3, color=(125 / 255, 125 / 255, 125 / 255), texture=None, size_scale=1.0, distance_scale=1.0): @@ -158,7 +159,8 @@ class Body: """ # v = m/ρ # 体积(m³) = 质量(kg) / 密度(kg/m³) - v = self.mass / self.density + # 体积(km³) = 体积(m³) / 1e9 + v = self.mass / self.density / 1e9 return v @property diff --git a/bodies/moon.py b/bodies/moon.py new file mode 100644 index 0000000000000000000000000000000000000000..d8acafb080be3a6278b81d3af7ea9a97930fabad --- /dev/null +++ b/bodies/moon.py @@ -0,0 +1,44 @@ +# -*- coding:utf-8 -*- +# title : +# description : +# author :Python超人 +# date :2023-01-22 +# notes : +# python_version :3.8 +# ============================================================================== +from bodies.body import Body, AU + + +class Moon(Body): + """ + 月球 + ------------------------ + 距地距离约 363104 至 405696 km +  逃逸速度: 2.4 km/s +  公转速度: 1.023 km/s + (地球)29.79 km/s +  天体质量: 7.342✕10²² kg +  平均密度: 3.344 g/cm³ -> 3.344✕10³ kg/m³ + """ + + # 质 量约 [1] 平均密度约 3.344 g/cm³ [1] 质 量约 7.342✕1022 kg [1] + def __init__(self, name="Moon", mass=7.342e22, + init_position=[363104 + 1.12 * AU, 0, 0], + init_velocity=[0, 29.79 + 1.023, 0], + texture="moon.jpg", size_scale=1.0, distance_scale=1.0): + params = { + "name": name, + "mass": mass, + "init_position": init_position, + "init_velocity": init_velocity, + "density": 3.344e3, + "color": (162, 162, 162), + "texture": texture, + "size_scale": size_scale, + "distance_scale": distance_scale + } + super().__init__(**params) + + +if __name__ == '__main__': + earth = Earth() + print(earth) diff --git a/common/calculator.py b/common/calculator.py deleted file mode 100644 index 56ab703fd807e9b4c43d86dad118182f481a3263..0000000000000000000000000000000000000000 --- a/common/calculator.py +++ /dev/null @@ -1,89 +0,0 @@ -# -*- coding:utf-8 -*- -# title : -# description : -# author :Python超人 -# date :2023-01-22 -# notes : -# python_version :3.8 -# ============================================================================== -import numpy as np -import math - - -class MechanicalCalculator: - """ - 力学计算器: - 牛顿引力常数就有万有引力常数:G=6.67x10^-11 (N·m^2 /kg^2) - 计算万有引力时会用到 - 万有引力公式:F=G*m1*m2/r* - """ - - @staticmethod - def getAcc(pos, mass, G, softening): - """ - Calculate the acceleration on each particle due to Newton's Law - pos is an N x 3 matrix of positions - mass is an N x 1 vector of masses - G is Newton's Gravitational constant - softening is the softening length - a is N x 3 matrix of accelerations - - - """ - # positions r = [x,y,z] for all particles - x = pos[:, 0:1] - y = pos[:, 1:2] - z = pos[:, 2:3] - - # matrix that stores all pairwise particle separations: r_j - r_i - dx = x.T - x - dy = y.T - y - dz = z.T - z - - # matrix that stores 1/r^3 for all particle pairwise particle separations - inv_r3 = (dx ** 2 + dy ** 2 + dz ** 2 + softening ** 2) - inv_r3[inv_r3 > 0] = inv_r3[inv_r3 > 0] ** (-1.5) - - ax = G * (dx * inv_r3) @ mass - ay = G * (dy * inv_r3) @ mass - az = G * (dz * inv_r3) @ mass - - # pack together the acceleration components - a = np.hstack((ax, ay, az)) - - return a - - @staticmethod - def getEnergy(pos, vel, mass, G): - """ - Get kinetic energy (KE) and potential energy (PE) of simulation - pos is N x 3 matrix of positions - vel is N x 3 matrix of velocities - mass is an N x 1 vector of masses - G is Newton's Gravitational constant - KE is the kinetic energy of the system - PE is the potential energy of the system - """ - # Kinetic Energy: - KE = 0.5 * np.sum(np.sum(mass * vel ** 2)) - - # Potential Energy: - - # positions r = [x,y,z] for all particles - x = pos[:, 0:1] - y = pos[:, 1:2] - z = pos[:, 2:3] - - # matrix that stores all pairwise particle separations: r_j - r_i - dx = x.T - x - dy = y.T - y - dz = z.T - z - - # matrix that stores 1/r for all particle pairwise particle separations - inv_r = np.sqrt(dx ** 2 + dy ** 2 + dz ** 2) - inv_r[inv_r > 0] = 1.0 / inv_r[inv_r > 0] - - # sum over upper triangle, to count each interaction only once - PE = G * np.sum(np.sum(np.triu(-(mass * mass.T) * inv_r, 1))) - - return KE, PE; diff --git a/common/func.py b/common/func.py index c31a01ec3d375a0bbc1444995dc45f9ad3d0313e..a00a45bc9064ae43073e6b18ff683879f573663d 100644 --- a/common/func.py +++ b/common/func.py @@ -6,9 +6,6 @@ # notes : # python_version :3.8 # ============================================================================== -import numpy as np -import random -from mayavi import mlab from PIL import Image diff --git a/common/simulator.py b/common/simulator.py deleted file mode 100644 index 7632c818bc1af9f9e085133a17bcdb66c3d76b0a..0000000000000000000000000000000000000000 --- a/common/simulator.py +++ /dev/null @@ -1,157 +0,0 @@ -# -*- coding:utf-8 -*- -# title : -# description : -# author :Python超人 -# date :2023-01-22 -# notes : -# python_version :3.8 -# ============================================================================== -from common.consts import SECONDS_PER_DAY, SECONDS_PER_HOUR, SECONDS_PER_MONTH, SECONDS_PER_WEEK -from common.system import System -from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto -from mayavi import mlab -import numpy as np -import matplotlib.pyplot as plt -from mpl_toolkits import mplot3d - -X_MIN, X_MAX = -2e+14, 2e+14 # the x range of the bounding box (m) -Y_MIN, Y_MAX = -2e+14, 2e+14 # the y range of the bounding box (m) -Z_MIN, Z_MAX = -2e+14, 2e+14 # the z range of the bounding box (m) - -X_MIN, X_MAX = -2e+12, 2e+12 # the x range of the bounding box (m) -Y_MIN, Y_MAX = -2e+12, 2e+12 # the y range of the bounding box (m) -Z_MIN, Z_MAX = -2e+12, 2e+12 # the z range of the bounding box (m) - -X_MIN, X_MAX = -1e+9, 1e+9 # the x range of the bounding box (m) -Y_MIN, Y_MAX = -1e+9, 1e+9 # the y range of the bounding box (m) -Z_MIN, Z_MAX = -1e+9, 1e+9 # the z range of the bounding box (m) - -X_MIN, X_MAX = -8e+8, 8e+8 # the x range of the bounding box (m) -Y_MIN, Y_MAX = -8e+8, 8e+8 # the y range of the bounding box (m) -Z_MIN, Z_MAX = -8e+8, 8e+8 # the z range of the bounding box (m) - - -def show_figure(bodies, idx=0): - # from scipy.interpolate import make_interp_spline - - # Creating figures for the plot - fig = plt.figure(figsize=(16, 12)) - ax = plt.axes(projection="3d") - ax.set_xlim(X_MIN, X_MAX) - ax.set_ylim(Y_MIN, Y_MAX) - ax.set_zlim(Z_MIN, Z_MAX) - ax.set_xlabel('X') - ax.set_ylabel('Y') - ax.set_zlabel('Z') - # Creating a plot using the random datasets - colors = ['red', 'blue', 'red', 'red'] - sizes = [800, 500, 800, 800] - for idx, body in enumerate(bodies): - color = 'red' if str(body.name).lower().startswith("sun") else 'blue' - size = 800 if str(body.name).lower().startswith("sun") else 500 - pos = body.position - ax.text(pos[0], pos[1], pos[2] + 1e8, body.name, color=color, fontsize=20) - ax.scatter(pos[0], pos[1], pos[2], color=color, s=size) - # for _his_pos in body.his_position(): - # ax.scatter3D(_his_pos[0], _his_pos[1], _his_pos[2], color=color, alpha=0.5) - # ax.scatter(his_pos[0], his_pos[1], his_pos[2], color=colors[idx], s=10) - his_pos = body.his_position() - if len(his_pos) > 1: - _his_pos = list(zip(*his_pos)) - ax.plot3D(_his_pos[0], _his_pos[1], _his_pos[2], color=color, alpha=0.8) - plt.title("3D %s" % idx) - # display the plot - plt.show() - - -import time - - -class Simulator: - def __init__(self, system, dt): - self.system = system - self.dt = dt - - def evolve(self, dt): - show_figure(self.system.bodies) - self.system.calc_acceleration() - - for body in self.system.bodies: - # acceleration 加速度 - body.velocity += body.acceleration * dt - # body.position += 0.5 * body.acceleration * (dt ** 2) - body.position += body.velocity * dt - print(body) - # print(body.name, body.position) - - def run(self, t): - n = int(t / self.dt) - for i in range(n): - self.evolve(self.dt) - time.sleep(1) - - def run_always(self): - dt = 1 # 时间变化1秒 - while True: - # time.sleep(1) - self.evolve(dt) - - -def run(bodies): - """ - 运行天体 - :param bodies: - :return: - """ - for body1 in bodies: - for body2 in bodies: - if body1 == body2: # 相等说明是同一个天体,跳过计算 - continue - # - r = body2.position - body1.position - # F = G x (m1 x m2) / r² 万有引力定律 - F = G * body1.mass * body2.mass * r / np.linalg.norm(r) / r.dot(r) - body1.momentum = body1.momentum + F * Configs.dt # 动量定理 - body1.position = body1.position + (body1.momentum / body1.mass) * Configs.dt - body1.update_source_data() - - - -def solar_system(): - t = SECONDS_PER_WEEK - _sys = System([ - Sun(), # 太阳 - Mercury(), # 水星 - Venus(), # 金星 - Earth(), # 地球 - Mars(), # 火星 - Jupiter(), # 木星 - Saturn(), # 土星 - Uranus(), # 天王星 - Neptune(), # 海王星 - Pluto() # 冥王星(从太阳系的行星中排除) - ]) - - _sim = Simulator(_sys, t) - _sim.run(t * 100) - - -if __name__ == '__main__': - # t = 60 * 60 * 24 * 10 - solar_system() - # _sys = System([Sun(init_position=[0, 0, 149597870.700]), Earth()]) - - # _sys = System([Sun(init_position=[849597870.700, 0, 0], init_velocity=[0, 9.79, 0]), - # Sun(init_position=[0, 0, 0], init_velocity=[0, -9.79, 0])]) - - # _sys = System([Sun(), Earth()]) - - # _sys = System([Sun(name="sun1", init_position=[849597870.700, 0, 0], init_velocity=[0, 7.0, 0]), - # Sun(name="sun2", init_position=[0, 0, 0], init_velocity=[0, -8.0, 0]), - # Sun(name="sun3", init_position=[0, -849597870.700, 0], init_velocity=[18.0, 0, 0]), - # Earth(init_position=[0, -349597870.700, 0], init_velocity=[15.50, 0, 0])]) - - # _sys = System([Sun(), Earth(), Jupiter()]) - # - # _sim = Simulator(_sys, t) - # _sim.run(t * 100) diff --git a/common/system.py b/common/system.py index 6ce178d69c4576e3783cc47cb67b501bacbde8e3..6309724534a4c90e176159f60550645d802b665b 100644 --- a/common/system.py +++ b/common/system.py @@ -8,9 +8,14 @@ # ============================================================================== import numpy as np from common.consts import AU, G +from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto class System(object): + """ + 天体系统 + """ + def __init__(self, bodies): self.bodies = bodies @@ -18,146 +23,47 @@ class System(object): self.bodies.append(body) def total_mass(self): - total_mass = 0 - for body in self.bodies: - total_mass = body.mass - return total_mass - - def __repr__(self): - return 'System({})'.format(self.bodies) - - def kinetic_energy(self): """ - KE是系统的动能 + 总质量 :return: """ - ke = 0 + total_mass = 0.0 for body in self.bodies: - v = body.velocity # velocity - ke = 0.5 * body.mass * (v[0] ** 2 + v[1] ** 2) # ke = 0.5 * body.mass * (v[0]**2 v[1]**2) - return ke - - # def kinetic_energy(self, vx, vy, vz, mass): - # """ - # 计算动能 - # """ - # v = body.velocity # velocity - # return 0.5 * mass * (vx ** 2 + vy ** 2 + vz ** 2) - - def potential_energy(self, x, y, z, mass,M): - """ - 计算势能 - """ - return -G * M * mass / np.sqrt(x ** 2 + y ** 2 + z ** 2) + total_mass += body.mass + return total_mass - def potential_energy(self): - """ - PE是系统的势能 - :return: - """ - pe = 0 - for body1 in self.bodies: - for body2 in self.bodies: - if body1 is body2: - continue - r = body1.position - body2.position - # pe -= body1.mass * body2.mass / np.sqrt(r[0]**2 r[1]**2) - pe -= body1.mass * body2.mass / np.sqrt(r[0] ** 2 + r[1] ** 2) - return pe + def __repr__(self): + return 'System({})'.format(self.bodies) - def momentum(self): + def center_of_mass(self): """ - 动量 + 质心 :return: """ - p = np.zeros(2) + r = np.zeros(2) for body in self.bodies: - p = body.mass * body.velocity - return p + r = body.mass * body.position + return r / self.total_mass() - def momentum(self, vx, vy, vz, mass): + def evolve(self, dt): """ - 计算动量 - """ - return mass * np.sqrt(vx ** 2 + vy ** 2 + vz ** 2) - def angular_momentum(self): - """ - 角动量 + :param dt: :return: """ - L = 0 - for body in self.bodies: - r = body.position - v = body.velocity - L = body.mass * (r[0] * v[1] - r[1] * v[0]) - return L - - def angular_momentum(self, x, y, z, vx, vy, vz): - """ - 计算角动量 - """ - return self.mass * (x * vy - y * vx) + self.calc_bodies_acceleration() - def center_of_mass(self): - r = np.zeros(2) for body in self.bodies: - r = body.mass * body.position - return r / self.total_mass() + # acceleration 加速度 + body.velocity += body.acceleration * dt + # body.position += 0.5 * body.acceleration * (dt ** 2) + body.position += body.velocity * dt - # def step(m: np.ndarray, v: np.ndarray, p: np.ndarray): - # ''' Calculate the next state of the N-star system. - # args: - # m: np.ndarray[(N,), np.float64], mass. - # v: np.ndarray[(N,3), np.float64], velocity. - # p: np.ndarray[(N,3), np.float64], position. - # returns: - # (next_v, next_p), the next state. - # ''' - # N = m.shape[0] - # a = np.zeros_like(p) - # for i in range(N): - # for j in range(N): - # if i == j: continue - # r = np.sqrt(np.sum(np.square(p[j, :] - p[i, :]))) - # aij = G * m[j] / (r * r) - # dir = (p[j, :] - p[i, :]) / r - # a[i, :] += aij * dir - # next_p = p + (1 / FS) * v + 0.5 * a * ((1 / FS) ** 2) - # next_v = v + (1 / FS) * a - # return (next_v, next_p) - - # next_p = p + dt * v + 0.5 * a * (dt ** 2) - # next_v = v + dt * a - # for body1 in bodies: - # for body2 in bodies: - # if body1 == body2: # 相等说明是同一个天体,跳过计算 - # continue - # r = body2.position - body1.position - # # F = G x (m1 x m2) / r² 万有引力定律 - # F = Configs.G * body1.mass * body2.mass * r / np.linalg.norm(r) / r.dot(r) - # body1.momentum = body1.momentum + F * dt # 动量定理 - # body1.position = body1.position + (body1.momentum / body1.mass) * dt - # body1.update_source_data() - - def acceleration(self, body1, body2): + def calc_bodies_acceleration(self): """ - 计算两个天体之间的加速度 - :param body1: 天体1 - :param body2: 天体2 - :param G: 引力常数 - :return: 加速度 + 计算加速度 + :return: """ - import math - dx = body2.position[0] - body1.position[0] - dy = body2.position[1] - body1.position[1] - dz = body2.position[2] - body1.position[2] - distance = math.sqrt(dx ** 2 + dy ** 2 + dz ** 2) - mag = G * body2.mass / (distance ** 2) - acc = [dx / distance * mag, dy / distance * mag, dz / distance * mag] - return np.array(acc) / 1000 / 1000 / 1000 - - def calc_acceleration(self): for body1 in self.bodies: acceleration = np.zeros(3) for body2 in self.bodies: @@ -165,7 +71,6 @@ class System(object): continue r = body2.position - body1.position - # # G = 6.67e-11 # 万有引力常数 # m/s² = kg * m / m**3 # km/s² = kg * m / m**3 / 1e9 @@ -175,80 +80,18 @@ class System(object): body1.acceleration = acceleration -""" - - -# Python 3 -def get_acceleration(mass1,mass2,position1,position2): - G = 6.67*10**-11 - r = np.linalg.norm(position2-position1) - return G*mass2*(position2-position1)/r**3 - -# Python 2 -# def get_acceleration(mass1,mass2,position1,position2): -# G = 6.67*10**-11 -# r = np.linalg.norm(position2-position1) -# return G*mass2*(position2-position1)/r**3 - - -根据两个天体body1 和 body2 的质量,距离 position[0],position[1],position[2],用python计算两个天体的加速度 - - - - - -# 假设两个天体的质量分别为m1和m2 -m1 = 5.974 * 10 ** 24 -m2 = 7.348 * 10 ** 22 - -# 计算两个天体的位置,假设分别为position1 和 position2 -position1 = [2.21, 3.45, 4.67] -position2 = [1.78, 6.34, -1.23] - -# 计算两个天体的距离 -dist = ( (position1[0]-position2[0])**2 + (position1[1]-position2[1])**2 + (position1[2]-position2[2])**2 ) ** (1/2) - -# 计算两个天体的加速度 -G = 6.674 * 10 ** -11 -acc_1 = G * m2 / (dist**2) -acc_2 = G * m1 / (dist**2) - -# 输出结果 -print("body1的加速度为:", acc_1) -print("body2的加速度为:", acc_2) - - - - -ax1 = (G * m2 * (x/pow(x**2 + y**2 + z**2,3/2))) -ay1 = (G * m2 * (y/pow(x**2 + y**2 + z**2,3/2))) -az1 = (G * m2 * (z/pow(x**2 + y**2 + z**2,3/2))) - -ax2 = (G * m1 * (-x/pow(x**2 + y**2 + z**2,3/2))) - - -ay2 = (G * m1 * (-y/pow(x**2 + y**2 + z**2,3/2))) - - -az2 = (G * m1 * (-z/pow(x**2 + y**2 + z**2,3/2))) - - -加速度可以用万有引力定律计算: - -a = G * m2 / r2 - -其中G为万有引力常数,m2和r2分别为两个天体的质量和距离平方。 - -因此,可以使用以下python代码来计算两个天体的加速度: - -import math - -G = 6.67e-11 # 万有引力常数 -m1 = 1 # 第一个天体的质量 -m2 = 1 # 第二个天体的质量 -r = 1 # 两个天体之间的距离 - -a = G * m2 / math.pow(r, 2) - -print(a) -""" +if __name__ == '__main__': + body_sys = System([ + Sun(), # 太阳 + Mercury(), # 水星 + Venus(), # 金星 + Earth(), # 地球 + Mars(), # 火星 + Jupiter(), # 木星 + Saturn(), # 土星 + Uranus(), # 天王星 + Neptune(), # 海王星 + Pluto() # 冥王星(从太阳系的行星中排除) + ]) + + print(body_sys) diff --git a/data/sun.json b/data/sun.json index 94470eec22db0342029e7738cc0dbdc85babbdf1..9f1eb510e32c67b3ba9fa5a12eb46cd356e23995 100644 --- a/data/sun.json +++ b/data/sun.json @@ -14,11 +14,7 @@ 0 ], "density": 1.408e3, - "color": [ - 125, - 125, - 125 - ], + "color": [170, 98, 25], "texture": "", "size_scale": 1.0, "distance_scale": 1.0 diff --git a/scenes/func.py b/scenes/func.py new file mode 100644 index 0000000000000000000000000000000000000000..f6ecbd290310c3ca0c3d21293ab2ac0e479de0b1 --- /dev/null +++ b/scenes/func.py @@ -0,0 +1,51 @@ +# -*- coding:utf-8 -*- +# title : +# description : +# author :Python超人 +# date :2023-01-22 +# notes : +# python_version :3.8 +# ============================================================================== +from common.consts import SECONDS_PER_WEEK +from common.system import System + + +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: 天体 + :param dt: 按时间差进行演变,值越小越精确,但演变速度会慢。 + :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() diff --git a/scenes/solar_system.py b/scenes/solar_system.py deleted file mode 100644 index 28daa6b1d87d9d94cf901687157b2b42c9e4b531..0000000000000000000000000000000000000000 --- a/scenes/solar_system.py +++ /dev/null @@ -1,58 +0,0 @@ -# -*- coding:utf-8 -*- -# title :太阳系场景 -# description : -# author :Python超人 -# date :2023-01-22 -# notes : -# python_version :3.8 -# ============================================================================== -from mayavi import mlab -from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto -from common.consts import SECONDS_PER_DAY, SECONDS_PER_HOUR, SECONDS_PER_MONTH, SECONDS_PER_WEEK - -from simulators.mayavi_simulator import MayaviSimulator - -if __name__ == '__main__': - # 背景色 - bgcolor = (1 / 255, 1 / 255, 30 / 255) # 宇宙背景色 - mlab.figure(bgcolor=bgcolor, size=(1440, 810)) - # 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿) - # 排列顺序 - # 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056 - # 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553 - # 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星 - bodies = [ - Sun(size_scale=1), # 太阳 - Mercury(size_scale=3e1, distance_scale=1e1), # 水星 - Venus(size_scale=2e1, distance_scale=1e1), # 金星 - Earth(size_scale=2e1, distance_scale=1e1), # 地球 - Mars(size_scale=2e1, distance_scale=1e1), # 火星 - Jupiter(size_scale=0.5e1, distance_scale=0.4e1), # 木星 - Saturn(size_scale=0.5e1, distance_scale=0.3e1), # 土星 - Uranus(size_scale=0.5e1, distance_scale=0.2e1), # 天王星 - Neptune(size_scale=0.5e1, distance_scale=0.15e1), # 海王星 - Pluto(size_scale=5e1, distance_scale=0.12e1), # 冥王星(从太阳系的行星中排除) - ] - from simulators.system import System - - body_sys = System(bodies) - simulator = MayaviSimulator(body_sys) - simulator.run_anim(SECONDS_PER_WEEK) - # 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=-45, distance=9e9) - mlab.show() diff --git a/scenes/solar_system_1.py b/scenes/solar_system_1.py new file mode 100644 index 0000000000000000000000000000000000000000..3e56a9a8f86f248d1b49e5ef89d257b714b08f8b --- /dev/null +++ b/scenes/solar_system_1.py @@ -0,0 +1,34 @@ +# -*- coding:utf-8 -*- +# title :太阳系场景 +# description : +# author :Python超人 +# date :2023-01-22 +# notes : +# python_version :3.8 +# ============================================================================== +from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto, Moon +from common.consts import SECONDS_PER_WEEK +from scenes.func import mayavi_run + +if __name__ == '__main__': + # 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿) + # 排列顺序 + # 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056 + # 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553 + # 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星 + # ===================================================================== + # 以下展示的效果为太阳系真实的距离 + # 但是由于宇宙空间尺度非常大,按照实际的大小无法看到行星天体,因此需要对天体的尺寸进行放大 + bodies = [ + Sun(size_scale=1.2e2), # 太阳放大 120 倍,距离保持不变 + Mercury(size_scale=4e3), # 水星放大 4000 倍,距离保持不变 + Venus(size_scale=4e3), # 金星放大 4000 倍,距离保持不变 + Earth(size_scale=4e3), # 地球放大 4000 倍,距离保持不变 + Mars(size_scale=4e3), # 火星放大 4000 倍,距离保持不变 + Jupiter(size_scale=1e3), # 木星放大 1000 倍,距离保持不变 + Saturn(size_scale=1e3), # 土星放大 1000 倍,距离保持不变 + Uranus(size_scale=1e3), # 天王星放大 1000 倍,距离保持不变 + Neptune(size_scale=1e3), # 海王星放大 1000 倍,距离保持不变 + Pluto(size_scale=10e3), # 冥王星放大 10000 倍,距离保持不变(从太阳系的行星中排除) + ] + mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45) diff --git a/scenes/solar_system_2.py b/scenes/solar_system_2.py new file mode 100644 index 0000000000000000000000000000000000000000..f3363ef5191416a78cb8f46d9e735853f09df849 --- /dev/null +++ b/scenes/solar_system_2.py @@ -0,0 +1,36 @@ +# -*- coding:utf-8 -*- +# title :太阳系场景 +# description : +# author :Python超人 +# date :2023-01-22 +# notes : +# python_version :3.8 +# ============================================================================== +from bodies import Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto +from common.consts import SECONDS_PER_WEEK +from scenes.func import mayavi_run + +if __name__ == '__main__': + # 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿) + # 排列顺序 + # 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056 + # 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553 + # 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星 + # ===================================================================== + # 以下展示的效果非太阳系真实的距离和大小 + # 1、由于宇宙空间尺度非常大,按照实际的大小无法看到行星天体,因此需要对天体的尺寸进行放大 + # 2、对每个行星天体的距离进行了缩放 + bodies = [ + Sun(size_scale=1.2e2), # 太阳放大 120 倍 + Mercury(size_scale=4e3, distance_scale=1), # 水星放大 4000 倍,距离保持不变 + Venus(size_scale=4e3, distance_scale=1), # 金星放大 4000 倍,距离保持不变 + Earth(size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变 + Mars(size_scale=4e3, distance_scale=1), # 火星放大 4000 倍,距离保持不变 + Jupiter(size_scale=1e3, distance_scale=0.5), # 木星放大 1000 倍,距离缩小到真实距离的 0.5 + Saturn(size_scale=1e3, distance_scale=0.38), # 土星放大 1000 倍,距离缩小到真实距离的 0.38 + Uranus(size_scale=1e3, distance_scale=0.26), # 天王星放大 1000 倍,距离缩小到真实距离的 0.26 + Neptune(size_scale=1e3, distance_scale=0.22), # 海王星放大 1000 倍,距离缩小到真实距离的 0.22 + Pluto(size_scale=10e3, distance_scale=0.20), # 冥王星放大 10000 倍,距离缩小到真实距离的 0.2(从太阳系的行星中排除) + ] + + mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45, view_distance=3e9, view_focalpoint=[5e2, 5e2, 5e2]) diff --git a/scenes/sun_earth.py b/scenes/sun_earth.py index fd1a4de4c0f8aa47278aac3586e696b479d24b8f..2e49450778557a405755d7b64423805263e621dc 100644 --- a/scenes/sun_earth.py +++ b/scenes/sun_earth.py @@ -1,50 +1,21 @@ # -*- coding:utf-8 -*- -# title :太阳系场景 +# title : # description : # author :Python超人 # date :2023-01-22 # notes : # python_version :3.8 # ============================================================================== -from mayavi import mlab -from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto -from common.consts import SECONDS_PER_DAY, SECONDS_PER_HOUR, SECONDS_PER_MONTH, SECONDS_PER_WEEK - -from simulators.mayavi_simulator import MayaviSimulator +from bodies import Sun, Earth +from common.consts import SECONDS_PER_WEEK +from scenes.func import mayavi_run if __name__ == '__main__': - # 背景色 - bgcolor = (1 / 255, 1 / 255, 30 / 255) # 宇宙背景色 - mlab.figure(bgcolor=bgcolor, size=(1440, 810)) - # 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿) - # 排列顺序 - # 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056 - # 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553 - # 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星 + """ + 太阳、地球 + """ bodies = [ - Sun(size_scale=1), # 太阳 - Earth(size_scale=2e1, distance_scale=1e1), # 地球 + Sun(size_scale=1.2e2), # 太阳放大 120 倍 + Earth(size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变 ] - from simulators.system import System - - body_sys = System(bodies) - simulator = MayaviSimulator(body_sys) - simulator.run_anim(SECONDS_PER_WEEK) - # 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=-45, distance=9e9) - mlab.show() + mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45) diff --git a/scenes/sun_earth_jupiter.py b/scenes/sun_earth_jupiter.py index 994013161992f4840f77096b06a1cadb02e8005c..c63529aa3fb145ef1143c980bdd0bbeda6ed1466 100644 --- a/scenes/sun_earth_jupiter.py +++ b/scenes/sun_earth_jupiter.py @@ -1,51 +1,22 @@ # -*- coding:utf-8 -*- -# title :太阳系场景 +# title : # description : # author :Python超人 # date :2023-01-22 # notes : # python_version :3.8 # ============================================================================== -from mayavi import mlab -from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto -from common.consts import SECONDS_PER_DAY, SECONDS_PER_HOUR, SECONDS_PER_MONTH, SECONDS_PER_WEEK - -from simulators.mayavi_simulator import MayaviSimulator +from bodies import Sun, Earth, Jupiter +from common.consts import SECONDS_PER_WEEK +from scenes.func import mayavi_run if __name__ == '__main__': - # 背景色 - bgcolor = (1 / 255, 1 / 255, 30 / 255) # 宇宙背景色 - mlab.figure(bgcolor=bgcolor, size=(1440, 810)) - # 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿) - # 排列顺序 - # 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056 - # 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553 - # 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星 + """ + 太阳、地球、木星 + """ bodies = [ - Sun(size_scale=1), # 太阳 - Earth(size_scale=2e1, distance_scale=1e1), # 地球 - Jupiter(size_scale=0.5e1, distance_scale=1e1), # 木星 + Sun(size_scale=1.2e2), # 太阳放大 120 倍 + Earth(size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变 + Jupiter(size_scale=1e3, distance_scale=0.5), # 木星放大 1000 倍,距离缩小到真实距离的 0.5 ] - from simulators.system import System - - body_sys = System(bodies) - simulator = MayaviSimulator(body_sys) - simulator.run_anim(SECONDS_PER_WEEK) - # 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=-45, distance=9e9) - mlab.show() + mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=-45) diff --git a/scenes/three_body_01.py b/scenes/three_body_01.py index d819d835c1d1a7f1f613c337a827b3e7a727ae41..e6d9b51118240136d63df49e06cceae66fcaae7b 100644 --- a/scenes/three_body_01.py +++ b/scenes/three_body_01.py @@ -7,58 +7,26 @@ # python_version :3.8 # ============================================================================== from mayavi import mlab -from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto -from common.consts import SECONDS_PER_DAY, SECONDS_PER_HOUR, SECONDS_PER_MONTH, SECONDS_PER_WEEK -from common.consts import AU -from simulators.mayavi_simulator import MayaviSimulator +from bodies import Sun, Earth +from common.consts import SECONDS_PER_WEEK +from scenes.func import mayavi_run if __name__ == '__main__': - # 背景色 - bgcolor = (1 / 255, 1 / 255, 30 / 255) # 宇宙背景色 - mlab.figure(bgcolor=bgcolor, size=(1440, 810)) - # 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿) - # 排列顺序 - # 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056 - # 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553 - # 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星 + """ + 3个太阳、1个地球(效果1) + 可以修改影响效果的参数为: + 1、三个方向的初始位置 init_position[x, y, z] + 2、三个方向的初始速度 init_velocity[x, y, z] + 3、天体质量 mass + """ bodies = [ Sun(mass=1.5e30, init_position=[849597870.700, 0, 0], init_velocity=[0, 7.0, 0], - texture="sun1.jpg", size_scale=1, distance_scale=1e1), # 太阳1, - + size_scale=1e2, texture="sun1.jpg"), # 太阳放大 100 倍 Sun(mass=2e30, init_position=[0, 0, 0], init_velocity=[0, -8.0, 0], - texture="sun2.jpg", size_scale=1, distance_scale=1e1), # 太阳2, - + size_scale=1e2, texture="sun2.jpg"), # 太阳放大 100 倍 Sun(mass=2.5e30, init_position=[0, -849597870.700, 0], init_velocity=[18.0, 0, 0], - texture="sun2.jpg", size_scale=1, distance_scale=1e1), # 太阳3, - + size_scale=1e2, texture="sun2.jpg"), # 太阳放大 100 倍 Earth(init_position=[0, -349597870.700, 0], init_velocity=[15.50, 0, 0], - size_scale=5e1, distance_scale=1e1) # 地球 + size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变 ] - - # Sun(name="sun1", init_position=[849597870.700, 0, 0], init_velocity=[0, 7.0, 0]), - # # Sun(name="sun2", init_position=[0, 0, 0], init_velocity=[0, -8.0, 0]), - # # Sun(name="sun3", init_position=[0, -849597870.700, 0], init_velocity=[18.0, 0, 0]), - # # Earth(init_position=[0, -349597870.700, 0], init_velocity=[15.50, 0, 0])] - from simulators.system import System - - body_sys = System(bodies) - simulator = MayaviSimulator(body_sys) - simulator.run_anim_10(SECONDS_PER_WEEK) - # 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=-45, distance=9e9) - mlab.show() + mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=0) diff --git a/scenes/three_body_02.py b/scenes/three_body_02.py index 49d062d40e42201a4e33151716e90b4ac68b540b..da2e285022a8e2e8f0db028852b48234d013927e 100644 --- a/scenes/three_body_02.py +++ b/scenes/three_body_02.py @@ -7,55 +7,27 @@ # python_version :3.8 # ============================================================================== from mayavi import mlab -from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto -from common.consts import SECONDS_PER_DAY, SECONDS_PER_HOUR, SECONDS_PER_MONTH, SECONDS_PER_WEEK -from common.consts import AU -from simulators.mayavi_simulator import MayaviSimulator +from bodies import Sun, Earth +from common.consts import SECONDS_PER_WEEK +from scenes.func import mayavi_run if __name__ == '__main__': - # 背景色 - bgcolor = (1 / 255, 1 / 255, 30 / 255) # 宇宙背景色 - mlab.figure(bgcolor=bgcolor, size=(1440, 810)) - # 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿) - # 排列顺序 - # 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056 - # 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553 - # 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星 + """ + 3个太阳、1个地球(效果2) + 可以修改影响效果的参数为: + 1、三个方向的初始位置 init_position[x, y, z] + 2、三个方向的初始速度 init_velocity[x, y, z] + 3、天体质量 mass + """ bodies = [ Sun(mass=1.5e30, init_position=[849597870.700, 0, 0], init_velocity=[0, 7.0, 0], - texture="sun1.jpg", size_scale=1, distance_scale=1e1), # 太阳1, + size_scale=1e2, texture="sun1.jpg"), # 太阳放大 100 倍 + Sun(mass=2e30, init_position=[0, 0, 249597870.700], init_velocity=[0, -8.0, 0], + size_scale=1e2, texture="sun2.jpg"), # 太阳放大 100 倍 + Sun(mass=2.5e30, init_position=[0, -849597870.700, 0], init_velocity=[8.0, 0, 0], + size_scale=1e2, texture="sun2.jpg"), # 太阳放大 100 倍 - Sun(mass=2e30, init_position=[0, 0, 0], init_velocity=[0, -8.0, 0], - texture="sun2.jpg", size_scale=1, distance_scale=1e1), # 太阳2, - - Sun(mass=2.5e30, init_position=[0, -849597870.700, 0], init_velocity=[18.0, 0, 0], - texture="sun2.jpg", size_scale=1, distance_scale=1e1), # 太阳3 + Earth(init_position=[0, -349597870.700, 0], init_velocity=[15.50, 0, 0], + size_scale=4e3, distance_scale=1), # 地球放大 4000 倍,距离保持不变 ] - - # Sun(name="sun1", init_position=[849597870.700, 0, 0], init_velocity=[0, 7.0, 0]), - # # Sun(name="sun2", init_position=[0, 0, 0], init_velocity=[0, -8.0, 0]), - # # Sun(name="sun3", init_position=[0, -849597870.700, 0], init_velocity=[18.0, 0, 0]), - # # Earth(init_position=[0, -349597870.700, 0], init_velocity=[15.50, 0, 0])] - from simulators.system import System - - body_sys = System(bodies) - simulator = MayaviSimulator(body_sys) - simulator.run_anim_10(SECONDS_PER_DAY) - # 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=-45, distance=9e9) - mlab.show() + mayavi_run(bodies, SECONDS_PER_WEEK, view_azimuth=0) diff --git a/simulators/mayavi_simulator.py b/simulators/mayavi_simulator.py index a06a84438d85c6aada4d1904e43a2a87669538e2..a3a6d362031c958536471b09c3489e35baf3dfcd 100644 --- a/simulators/mayavi_simulator.py +++ b/simulators/mayavi_simulator.py @@ -7,78 +7,20 @@ # python_version :3.8 # ============================================================================== from mayavi import mlab -from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto -from common.consts import SECONDS_PER_DAY, SECONDS_PER_HOUR, SECONDS_PER_MONTH, SECONDS_PER_WEEK +from simulators.simulator import Simulator +from common.system import System +from simulators.viewers.mayavi_viewer import MayaviViewer -from simulators.mayavi_body import MayaviBody - -class MayaviSimulator: - """ - - """ - - def __init__(self, sys): - self.sys = sys - self.mayavi_bodies = [] - for body in self.sys.bodies: - mbody = MayaviBody(body) - self.mayavi_bodies.append(mbody) - - def run(self, dt): - self.sys.evolve(dt) - for idx, body in enumerate(self.mayavi_bodies): - # acceleration 加速度 - # body.velocity = self.sys.bodies[idx].velocity - # body.position += 0.5 * body.acceleration * (dt ** 2) - body.position = self.sys.bodies[idx].position * self.sys.bodies[idx].distance_scale - body.update_source_data() - # print(self.sys.bodies[idx]) +class MayaviSimulator(Simulator): + def __init__(self, bodies_sys: System): + super().__init__(bodies_sys, MayaviViewer) @mlab.animate(delay=100, ui=True) - def run_anim(self, dt): - f = mlab.gcf() - while True: - self.run(dt) - # Updating scene... - f.scene.render() - yield - - @mlab.animate(delay=10, ui=True) - def run_anim_10(self, dt): + def run(self, dt): f = mlab.gcf() while True: - self.run(dt) + self.evolve(dt) # Updating scene... f.scene.render() yield - - -if __name__ == '__main__': - # 背景色 - bgcolor = (1 / 255, 1 / 255, 30 / 255) # 宇宙背景色 - mlab.figure(bgcolor=bgcolor, size=(1440, 810)) - # 八大行星:木星(♃)、土星(♄)、天王星(♅)、海王星(♆)、地球(⊕)、金星(♀)、火星(♂)、水星(☿) - # 排列顺序 - # 1、体积:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 1330:745:65:60:1:0.86:0.15:0.056 - # 2、质量:(以地球为1)木星 :土星 :天王星 :海王星 :地球 :金星 :火星 :水星 = 318:95:14.53:17.15:1:0.8:0.11:0.0553 - # 3、离太阳从近到远的顺序:水星、金星、地球、火星、木星、土星、天王星、海王星 - bodies = [ - Sun(size_scale=1), # 太阳 - Mercury(size_scale=3e1, distance_scale=1e1), # 水星 - Venus(size_scale=2e1, distance_scale=1e1), # 金星 - Earth(size_scale=2e1, distance_scale=1e1), # 地球 - Mars(size_scale=2e1, distance_scale=1e1), # 火星 - Jupiter(size_scale=0.5e1, distance_scale=0.4e1), # 木星 - Saturn(size_scale=0.5e1, distance_scale=0.3e1), # 土星 - Uranus(size_scale=0.5e1, distance_scale=0.2e1), # 天王星 - Neptune(size_scale=0.5e1, distance_scale=0.15e1), # 海王星 - Pluto(size_scale=5e1, distance_scale=0.12e1), # 冥王星(从太阳系的行星中排除) - ] - from simulators.system import System - - body_sys = System(bodies) - simulator = MayaviSimulator(body_sys) - simulator.run_anim(SECONDS_PER_WEEK) - mlab.view(azimuth=-45, distance=9e9) - mlab.show() diff --git a/simulators/simulator.py b/simulators/simulator.py new file mode 100644 index 0000000000000000000000000000000000000000..604be3374b1a6b05c35be891ccff38635a2f6969 --- /dev/null +++ b/simulators/simulator.py @@ -0,0 +1,56 @@ +# -*- coding:utf-8 -*- +# title : +# description : +# author :Python超人 +# date :2023-01-22 +# notes : +# python_version :3.8 +# ============================================================================== +from abc import ABCMeta, abstractmethod +from common.system import System + + +class Simulator(metaclass=ABCMeta): + """ + + """ + + def __init__(self, bodies_sys: System, viewer_type: type): + """ + + :param bodies_sys: 天体系统 + :param viewer_type: BodyViewer类型 + """ + self.body_viewers = [] + self.bodies_sys = bodies_sys + self.init_viewers(viewer_type) + + def init_viewers(self, viewer_type: type): + """ + + :param viewer_type: BodyViewer类型 + :return: + """ + for body in self.bodies_sys.bodies: + viewer = viewer_type(body) + self.body_viewers.append(viewer) + + def evolve(self, dt: int): + """ + 按时间差进行演变,值越小越精确,但演变速度会慢。 + :param dt: 时间差(秒) + :return: + """ + self.bodies_sys.evolve(dt) + for idx, viewer in enumerate(self.body_viewers): + viewer.position = self.bodies_sys.bodies[idx].position * self.bodies_sys.bodies[idx].distance_scale + viewer.update() + + @abstractmethod + def run(self, dt: int): + """ + 按时间差运行,值越小越精确,但演变速度会慢。 + :param dt: 时间差(秒) + :return: + """ + pass diff --git a/simulators/system.py b/simulators/system.py deleted file mode 100644 index 6309724534a4c90e176159f60550645d802b665b..0000000000000000000000000000000000000000 --- a/simulators/system.py +++ /dev/null @@ -1,97 +0,0 @@ -# -*- coding:utf-8 -*- -# title : -# description : -# author :Python超人 -# date :2023-01-22 -# notes : -# python_version :3.8 -# ============================================================================== -import numpy as np -from common.consts import AU, G -from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto - - -class System(object): - """ - 天体系统 - """ - - def __init__(self, bodies): - self.bodies = bodies - - def add(self, body): - self.bodies.append(body) - - def total_mass(self): - """ - 总质量 - :return: - """ - total_mass = 0.0 - for body in self.bodies: - total_mass += body.mass - return total_mass - - def __repr__(self): - return 'System({})'.format(self.bodies) - - def center_of_mass(self): - """ - 质心 - :return: - """ - r = np.zeros(2) - for body in self.bodies: - r = body.mass * body.position - return r / self.total_mass() - - def evolve(self, dt): - """ - - :param dt: - :return: - """ - self.calc_bodies_acceleration() - - for body in self.bodies: - # acceleration 加速度 - body.velocity += body.acceleration * dt - # body.position += 0.5 * body.acceleration * (dt ** 2) - body.position += body.velocity * dt - - def calc_bodies_acceleration(self): - """ - 计算加速度 - :return: - """ - for body1 in self.bodies: - acceleration = np.zeros(3) - for body2 in self.bodies: - if body1 is body2: - continue - - r = body2.position - body1.position - # G = 6.67e-11 # 万有引力常数 - # m/s² = kg * m / m**3 - # km/s² = kg * m / m**3 / 1e9 - # acceleration = G * body2.mass * dx / (d ** 3) - acceleration += (G * body2.mass * r / np.linalg.norm(r) ** 3) / 1e9 - - body1.acceleration = acceleration - - -if __name__ == '__main__': - body_sys = System([ - Sun(), # 太阳 - Mercury(), # 水星 - Venus(), # 金星 - Earth(), # 地球 - Mars(), # 火星 - Jupiter(), # 木星 - Saturn(), # 土星 - Uranus(), # 天王星 - Neptune(), # 海王星 - Pluto() # 冥王星(从太阳系的行星中排除) - ]) - - print(body_sys) diff --git a/simulators/viewers/__init__.py b/simulators/viewers/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 diff --git a/simulators/viewers/body_viewer.py b/simulators/viewers/body_viewer.py new file mode 100644 index 0000000000000000000000000000000000000000..df61b27f86820937c564d24ab7b9d508a01c6d6d --- /dev/null +++ b/simulators/viewers/body_viewer.py @@ -0,0 +1,62 @@ +# -*- coding:utf-8 -*- +# title : +# description : +# author :Python超人 +# date :2023-01-22 +# notes : +# python_version :3.8 +# ============================================================================== +from abc import ABCMeta, abstractmethod +from bodies import Body +from common.func import get_dominant_colors +import numpy as np +import os + + +class BodyViewer(metaclass=ABCMeta): + def __init__(self, body: Body): + self.body = body + self.sphere = None + if self.body.texture is None or self.body.texture == '': + self.color = tuple(np.array(body.color) / 255) + else: + self.texture = self.__find_texture(self.body.texture) # 纹理 + if self.texture is None: + self.color = tuple(np.array(body.color) / 255) + else: + self.color = self.__texture_to_color(self.texture) + self.sphere = self.build() + self.position = None + + def __find_texture(self, texture): + """ + 在多路径下寻找纹理图片 + :param texture: 纹理图片 + :return: 纹理图片的路径 + """ + paths = ['./textures', '../textures'] + for path in paths: + p = path + "/" + texture + if os.path.exists(p): + return p + + return None + + def __texture_to_color(self, texture): + """ + 根据纹理图片获取颜色 + :param texture: + :return: + """ + colors = get_dominant_colors(texture) + first_color = colors[0] + # print(self.name, first_color) + return tuple(np.array(first_color) / 255) + + @abstractmethod + def update(self): + pass + + @abstractmethod + def build(self): + pass diff --git a/simulators/mayavi_body.py b/simulators/viewers/mayavi_viewer.py similarity index 80% rename from simulators/mayavi_body.py rename to simulators/viewers/mayavi_viewer.py index 15eae96e518573e921c61e3e92bad66b145b2581..c85cd4f5ae02cf61b7c454961d46c7f1ea9dfa2b 100644 --- a/simulators/mayavi_body.py +++ b/simulators/viewers/mayavi_viewer.py @@ -7,31 +7,18 @@ # python_version :3.8 # ============================================================================== from mayavi import mlab -import numpy as np -from bodies import Body -from mayavi import mlab -import numpy as np from tvtk.api import tvtk -from abc import ABCMeta, abstractmethod import os import matplotlib.pyplot as plt from common.func import get_dominant_colors +from simulators.viewers.body_viewer import BodyViewer +import numpy as np + -class MayaviBody: - def __init__(self, body: Body): - self.body = body - if self.body.texture is None or self.body.texture == '': - self.color = tuple(np.array(body.color) / 255) - else: - self.texture = self.__find_texture(self.body.texture) # 纹理 - if self.texture is None: - self.color = tuple(np.array(body.color) / 255) - else: - self.color = self.__texture_to_color(self.texture) - self.build_body() +class MayaviViewer(BodyViewer): - def update_source_data(self): + def update(self): """ :return: @@ -41,8 +28,6 @@ class MayaviBody: z_offset = self.body.position[2] - self.sphere.mlab_source.z self.sphere.mlab_source.set(x=self.position[0], y=self.position[1], z=self.position[2]) - # print(self.sphere.mlab_source.y, self.position[1]) - # self.sphere.actor.actor.position = self.position return x_offset[0], y_offset[0], z_offset[0] def __find_texture(self, texture): @@ -70,12 +55,12 @@ class MayaviBody: # print(self.name, first_color) return tuple(np.array(first_color) / 255) - def build_body(self): + def build(self): """ 构建球体对象 :return: """ - if not hasattr(self, "sphere"): + if not hasattr(self, "sphere") or self.sphere is None: scale_factor = self.body.size_scale * self.body.raduis sphere = mlab.points3d(self.body.position[0], self.body.position[1], self.body.position[2], scale_factor=scale_factor, diff --git a/simulators/viewers/mpl_viewer.py b/simulators/viewers/mpl_viewer.py new file mode 100644 index 0000000000000000000000000000000000000000..51ae53b868bbabaea6908c1125c44d293d009cb1 --- /dev/null +++ b/simulators/viewers/mpl_viewer.py @@ -0,0 +1,9 @@ +# -*- coding:utf-8 -*- +# title : +# description : +# author :Python超人 +# date :2023-01-22 +# notes : +# python_version :3.8 +# ============================================================================== +