system.py 4.1 KB
Newer Older
M
march3 已提交
1
# -*- coding:utf-8 -*-
M
march3 已提交
2 3
# title           :天体系统
# description     :天体系统,多个天体就是一个系统
M
march3 已提交
4
# author          :Python超人
M
march3 已提交
5 6
# date            :2023-02-11
# link            :https://gitcode.net/pythoncr/
M
march3 已提交
7 8 9
# python_version  :3.8
# ==============================================================================
import numpy as np
M
march3 已提交
10
from common.consts import AU, G
M
march3 已提交
11
from bodies import Body, Sun, Mercury, Venus, Earth, Mars, Jupiter, Saturn, Uranus, Neptune, Pluto
M
march3 已提交
12
from common.func import calculate_distance
M
march3 已提交
13 14 15


class System(object):
M
march3 已提交
16 17 18 19
    """
    天体系统
    """

M
march3 已提交
20 21 22 23 24 25
    def __init__(self, bodies, max_distance=200 * AU):
        """

        :param bodies:
        :param max_distance:系统的最大范围,超出范围的天体就不显示了
        """
M
march3 已提交
26
        self.bodies = bodies
M
march3 已提交
27
        self.max_distance = max_distance
M
march3 已提交
28 29 30 31 32 33

    def add(self, body):
        self.bodies.append(body)

    def total_mass(self):
        """
M
march3 已提交
34
        总质量
M
march3 已提交
35 36
        :return:
        """
M
march3 已提交
37
        total_mass = 0.0
M
march3 已提交
38
        for body in self.bodies:
M
march3 已提交
39 40
            total_mass += body.mass
        return total_mass
M
march3 已提交
41

M
march3 已提交
42 43
    def __repr__(self):
        return 'System({})'.format(self.bodies)
M
march3 已提交
44

M
march3 已提交
45
    def center_of_mass(self):
M
march3 已提交
46
        """
M
march3 已提交
47
        质心
M
march3 已提交
48 49
        :return:
        """
M
march3 已提交
50
        r = np.zeros(2)
M
march3 已提交
51
        for body in self.bodies:
M
march3 已提交
52 53
            r = body.mass * body.position
        return r / self.total_mass()
M
march3 已提交
54

M
march3 已提交
55
    def evolve(self, dt):
M
march3 已提交
56 57
        """

M
march3 已提交
58
        :param dt:
M
march3 已提交
59 60
        :return:
        """
M
march3 已提交
61
        self.calc_bodies_acceleration()
M
march3 已提交
62 63

        for body in self.bodies:
M
march3 已提交
64 65 66 67
            # acceleration 加速度
            body.velocity += body.acceleration * dt
            # body.position += 0.5 * body.acceleration * (dt ** 2)
            body.position += body.velocity * dt
M
march3 已提交
68

M
march3 已提交
69
    def calc_bodies_acceleration(self):
M
march3 已提交
70
        """
M
march3 已提交
71 72
        计算加速度
        :return:
M
march3 已提交
73
        """
M
march3 已提交
74 75 76

        def valid_body(body):
            """
M
march3 已提交
77
            判断是否为有效的天体
M
march3 已提交
78 79 80
            :param body:
            :return:
            """
M
march3 已提交
81
            if not body.appeared:  # 不显示
M
march3 已提交
82 83
                return False
            if self.max_distance > 0:
M
march3 已提交
84
                # 超过了 max_distance 距离,则不显示,并消失
M
march3 已提交
85 86 87 88 89 90
                if calculate_distance(body.position) > self.max_distance:
                    body.appeared = False
                    return False

            return True

M
march3 已提交
91
        # self.bodies = list(filter(valid_body, self.bodies))
M
march3 已提交
92

M
march3 已提交
93
        for body1 in self.bodies:
三月三net's avatar
三月三net 已提交
94 95
            if body1.ignore_mass:
                continue
M
march3 已提交
96 97
            if not valid_body(body1):
                continue
M
march3 已提交
98
            acceleration = np.zeros(3)
M
march3 已提交
99
            for body2 in self.bodies:
三月三net's avatar
三月三net 已提交
100 101
                if body2.ignore_mass:
                    continue
M
march3 已提交
102
                if self.max_distance > 0:
M
march3 已提交
103
                    if calculate_distance(body1.position) > self.max_distance:  # 超过了max_distance距离,则消失
M
march3 已提交
104
                        body1.appeared = False
M
march3 已提交
105
                    if calculate_distance(body2.position) > self.max_distance:  # 超过了max_distance距离,则消失
M
march3 已提交
106 107 108 109 110
                        body2.appeared = False

                if False == body1.appeared or body2.appeared == False:
                    continue

M
march3 已提交
111 112
                if body1 is body2:
                    continue
M
march3 已提交
113 114
                elif body1.ignore_gravity(body2) or body2.ignore_gravity(body1):
                    continue
M
march3 已提交
115 116

                r = body2.position - body1.position
M
march3 已提交
117 118 119 120
                # G = 6.67e-11 # 万有引力常数
                # m/s² = kg * m / m**3
                # km/s² = kg * m / m**3 / 1e9
                # acceleration = G * body2.mass * dx / (d ** 3)
M
march3 已提交
121
                acceleration += (G * body2.mass * r / np.linalg.norm(r) ** 3) / 1e9
M
march3 已提交
122

M
march3 已提交
123
            body1.acceleration = acceleration
M
march3 已提交
124 125


M
march3 已提交
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
if __name__ == '__main__':
    body_sys = System([
        Sun(),  # 太阳
        Mercury(),  # 水星
        Venus(),  # 金星
        Earth(),  # 地球
        Mars(),  # 火星
        Jupiter(),  # 木星
        Saturn(),  # 土星
        Uranus(),  # 天王星
        Neptune(),  # 海王星
        Pluto()  # 冥王星(从太阳系的行星中排除)
    ])

    print(body_sys)