system.py 3.7 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
    def __init__(self, bodies, max_distance=60 * AU):
M
march3 已提交
21
        self.bodies = bodies
M
march3 已提交
22
        self.max_distance = max_distance
M
march3 已提交
23 24 25 26 27 28

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

    def total_mass(self):
        """
M
march3 已提交
29
        总质量
M
march3 已提交
30 31
        :return:
        """
M
march3 已提交
32
        total_mass = 0.0
M
march3 已提交
33
        for body in self.bodies:
M
march3 已提交
34 35
            total_mass += body.mass
        return total_mass
M
march3 已提交
36

M
march3 已提交
37 38
    def __repr__(self):
        return 'System({})'.format(self.bodies)
M
march3 已提交
39

M
march3 已提交
40
    def center_of_mass(self):
M
march3 已提交
41
        """
M
march3 已提交
42
        质心
M
march3 已提交
43 44
        :return:
        """
M
march3 已提交
45
        r = np.zeros(2)
M
march3 已提交
46
        for body in self.bodies:
M
march3 已提交
47 48
            r = body.mass * body.position
        return r / self.total_mass()
M
march3 已提交
49

M
march3 已提交
50
    def evolve(self, dt):
M
march3 已提交
51 52
        """

M
march3 已提交
53
        :param dt:
M
march3 已提交
54 55
        :return:
        """
M
march3 已提交
56
        self.calc_bodies_acceleration()
M
march3 已提交
57 58

        for body in self.bodies:
M
march3 已提交
59 60 61 62
            # acceleration 加速度
            body.velocity += body.acceleration * dt
            # body.position += 0.5 * body.acceleration * (dt ** 2)
            body.position += body.velocity * dt
M
march3 已提交
63

M
march3 已提交
64
    def calc_bodies_acceleration(self):
M
march3 已提交
65
        """
M
march3 已提交
66 67
        计算加速度
        :return:
M
march3 已提交
68
        """
M
march3 已提交
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84

        def valid_body(body):
            """
            有效的天体
            :param body:
            :return:
            """
            if not body.appeared:
                return False
            if self.max_distance > 0:
                if calculate_distance(body.position) > self.max_distance:
                    body.appeared = False
                    return False

            return True

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

M
march3 已提交
87
        for body1 in self.bodies:
M
march3 已提交
88 89
            if not valid_body(body1):
                continue
M
march3 已提交
90
            acceleration = np.zeros(3)
M
march3 已提交
91
            for body2 in self.bodies:
M
march3 已提交
92 93 94 95 96 97 98 99 100
                if self.max_distance > 0:
                    if calculate_distance(body1.position) > self.max_distance:  # 太远了,则小时
                        body1.appeared = False
                    if calculate_distance(body2.position) > self.max_distance:  # 太远了,则小时
                        body2.appeared = False

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

M
march3 已提交
101 102
                if body1 is body2:
                    continue
M
march3 已提交
103 104
                elif body1.ignore_gravity(body2) or body2.ignore_gravity(body1):
                    continue
M
march3 已提交
105 106

                r = body2.position - body1.position
M
march3 已提交
107 108 109 110
                # 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 已提交
111
                acceleration += (G * body2.mass * r / np.linalg.norm(r) ** 3) / 1e9
M
march3 已提交
112

M
march3 已提交
113
            body1.acceleration = acceleration
M
march3 已提交
114 115


M
march3 已提交
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
if __name__ == '__main__':
    body_sys = System([
        Sun(),  # 太阳
        Mercury(),  # 水星
        Venus(),  # 金星
        Earth(),  # 地球
        Mars(),  # 火星
        Jupiter(),  # 木星
        Saturn(),  # 土星
        Uranus(),  # 天王星
        Neptune(),  # 海王星
        Pluto()  # 冥王星(从太阳系的行星中排除)
    ])

    print(body_sys)