pygame 实现三体运动

效果

V1.0.10版
效果
新增添加物体功能
移除物体功能
稍微加快了一点点

实现方法

对于N体模拟,可以这样思考

  • 计算出一个系统中每一个对象(物体Object)的受力情况
  • 根据受力情况计算出每一个物体受的合力
  • 该物体下一帧运动的速度和方向就是所受合力的大小和方向

通过这种方法,就可以简单的模拟出N体运动

预备知识

1.向量

向量,也称矢量,是一种具有大小和方向的量
它可以用一个箭头表示
可以用箭头表示
在坐标系中,可以表示为
a[3.1]
[-2.9]
表示方法
涉及向量的原因是力本身就表示为一个向量
例如:
一个苹果受到10N的重力,在这里10N是力的大小,而方向则是竖直向下

2.合力的计算

合力的计算其实也就是向量的加法
根据平行四边形法则:
平行四边形法则
图甲中F1和F2的合力为F
如果
F1表示为[100,0]
F2表示为[10,60]
那么F就可以表示为[110,60]
至于图乙其实与图甲是一样的
那么,问题来了,物体的受力情况不一定仅有两个啊,怎么办呢?
其实,我们可以两个两个力的算,直到把所有力都算完,就得到了一个最终的合力了

3.引力的计算

两个可看作质点的物体之间的万有引力,可以用以下公式计算:
万有引力公式
即万有引力等于引力常量乘以两物体质量的乘积 除以它们距离的平方。

也就是说,引力与两物体之间距离的平方成反比,
而与两物体质量的乘积成正比

说人话就是靠的近引力就大,靠的远引力就小
在同样的距离时,质量越大引力越大,反之亦然

4.python的运用

你需要拥有这些:

  • python的基本语法
  • pygame库的用法
  • 一个IDE,所谓磨刀不误砍柴工,个人推荐PyCharm
  • 以及…伊文斯的介绍信,嗯,很好,组织没有看错你 ^ _ ^

开始

所有的代码都在最后
先从头开始吧:
注意,如果你对 类(class)不熟悉,那请点

系统(system)

总要有一个系统来容纳一切吧!

class System(object):	# 继承object类
    name = ""			
    objects = []		# 所有的对象(物体)都在这里

非常简单的一个类,不过还应该来点东西

def __init__(self, name):
	self.name = name		# 在建立系统的时候有一个名字的!

def add_object(self, obj):	# 添加物体
	self.objects.append(obj)

嗯,基本的东西以及好了,下面需要一个可以制造物体的神了!

物体(object)

class Objects(object):
    mass = 0        # 质量
    power = []      # 受到的力,矢量[大小,方向]
    speed = []      # 加速度,矢量[大小,方向]
    position = []   # 位置
    position_ = []  # 最初位置
    move_to = []    # 下一帧移动的距离,方向
    positions = []  # 所有的点
    volume = 0      # 体积
    color = []      # 颜色
    name = ""       # 名字

    def __init__(self, name, mass, speed, position, volume, color):
        self.mass = mass
        self.position = position
        self.volume = volume
        self.speed = speed
        self.color = color
        self.name = name
        self.positions.append(position[:])
        self.position_ = position[:]

这一次要多一点,但都很简单,在创作一个物体时当然需要很多数据!

计算

到目前为止,我们拥有了一个系统,拥有了可以创造物体的神
但它们不会动,这显然是无聊的,于是在系统中加入了

def work_power(self):
    for obj in self.objects:		# 遍历系统中的所有物体
        obj.power = []				# 把它们的受力情况清空
        if obj.speed == [0, 0]:		# 如果加速度为0,则跳过
            pass
        else:						# 否则将加速度变成力(物体的加速度可以看作一种力(根据F=am))
            obj.speed[0] = obj.speed[0] * obj.mass
            obj.speed[1] = obj.speed[1] * obj.mass
            obj.power.append(obj.speed)				# 把惯性力添加到受力情况中
        for o in self.objects:						# 遍历其他物体
            v0 = o.position[0] - obj.position[0]	# 算x轴上的距离
            v1 = o.position[1] - obj.position[1]	# 算y轴上的距离
            distance_2 = v0 ** 2 + v1 ** 2			# 算距离,根据勾股定理
            if distance_2 == 0:						# 如果距离为0,则不受力
                pass
            else:
                v0 *= G/distance_2*(obj.mass*o.mass)	# 根据万有引力公式算引力向量
                v1 *= G/distance_2*(obj.mass*o.mass)
                obj.power.append([v0, v1])				# 将引力添加到改物体的受力情况中

上面的代码算出了每个物体的受力情况
但合力却没有算…
那就再来个方法把!(在system类中)

def work_force(self):
    for obj in self.objects:		# 依然是遍历每个物体
        for n in range(len(obj.power) - 1):		# 遍历物体所受的每一个力
            f1 = obj.power[0]		# 把它们取出来
            f2 = obj.power[1]
            f_t = [f1[0]+f2[0], f1[1]+f2[1]]	# 根据合力的算法将合力算出来
            del obj.power[0]		# 把算过的的力删掉
            del obj.power[0]
            obj.power.append(f_t)	# 把合力添加进去
        obj.position[0] += obj.power[0][0]/obj.mass		# 将物体的位置沿合力的方向移动
        obj.position[1] += obj.power[0][1]/obj.mass
        obj.speed = [obj.power[0][0]/obj.mass, obj.power[0][1]/obj.mass]	#将合力变为加速度

OK,计算部分也完成了
但,我们看不见啊,看不见慌的很啊!

显示

轨道的实现其实是pygame中aalines方法的作用,
通过收集最近经过的点绘制 “曲线”

def display(self, scr, show_orbit, length=500):		# 接受3个参数,scr就是pygame的screen, show_orbit则是是否显示轨道,length就是轨道的长度
    for obj in self.objects:		# 遍历遍历
        pygame.draw.circle(scr, obj.color, (int(obj.position[0]), int(obj.position[1])), obj.volume)	# 给我画下来!
        if show_orbit:				# 如果要显示的话
            obj.positions = obj.positions[:]
            obj.positions.insert(0, [int(obj.position[0]), int(obj.position[1])])	# 收集点
            pygame.draw.aalines(scr, obj.color, False, obj.positions, 3)			# 画轨道
            if len(obj.positions) > length:				# 让轨道在长度之后消失
                del obj.positions[-1]
            elif len(obj.positions) > len(self.objects):	# 解决一个互传问题
                if obj.position_ in obj.positions:
                    for n in range(len(self.objects)):
                        del obj.positions[-1]

除了图像,我们还需要一些数据:

def display_data(self, scr, c):
    font = pygame.font.SysFont("Consolas", 25)
    fps = font.render("FPS: "+str(round(c.get_fps(), 2)), False, (255, 255, 255))
    scr.blit(fps, (50, 50))
    if self.objects:
        for index, obj in enumerate(self.objects):
            pos = font.render(obj.name+": "+str(int(obj.position[0])) + "  " +
                              str(int(obj.position[1])), False, (255, 255, 255))
            scr.blit(pos, (50, 80+index*35))

这里不再过多解释,可以自行百度

运行

完成一切后,
就可以疯狂的调用了
来一波四体运动!

universe = System("Earth University")

earth = Objects("Earth", 1000, [0, 0], [200, 200], 5, [115, 15, 249])
sun = Objects("Sun", 1000, [0, 0], [500, 600], 5, [255, 0, 0])
moon = Objects("Moon", 1000, [0, 0], [500, 300], 5, [0, 255, 0])
mars = Objects("Mars", 1000, [0, 0], [600, 400], 5, [15, 215, 249])

universe.add_object(earth)
universe.add_object(sun)
universe.add_object(moon)
universe.add_object(mars)

universe.work_power()
universe.work_force()

pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode([1500, 1200])
pygame.display.set_caption("Force")

keep = True

while keep:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            keep = False

    screen.fill((0, 0, 0))

    universe.work_power()
    universe.work_force()
    universe.display(screen, True)
    universe.display_data(screen, clock)

    pygame.display.update()
    clock.tick(200)

pygame.quit()

是不是超级简单啊?
OK,全部代码:

import pygame
"""
万有引力公式:
F = G * (m1*m2)/r**2
其中 F 为受某力的大小,m1,m2分别为两物体的质量,r为距离
牛顿第二定律:
F = am
a为加速度
m为物体质量
推导公式:
a = F/m
m = F/a
"""

global G, PI
G = 6.754*0.00001
PI = 3.14159265358979323


class System(object):
    name = ""
    objects = []

    def __init__(self, name):
        self.name = name

    def add_object(self, obj):
        self.objects.append(obj)

    def work_power(self):
        for obj in self.objects:
            obj.power = []
            if obj.speed == [0, 0]:
                pass
            else:
                obj.speed[0] = obj.speed[0] * obj.mass
                obj.speed[1] = obj.speed[1] * obj.mass
                obj.power.append(obj.speed)
            for o in self.objects:
                v0 = o.position[0] - obj.position[0]
                v1 = o.position[1] - obj.position[1]
                distance_2 = v0 ** 2 + v1 ** 2
                if distance_2 == 0:
                    pass
                else:
                    v0 *= G/distance_2*(obj.mass*o.mass)
                    v1 *= G/distance_2*(obj.mass*o.mass)
                    obj.power.append([v0, v1])

    def work_force(self):
        for obj in self.objects:
            for n in range(len(obj.power) - 1):
                f1 = obj.power[0]
                f2 = obj.power[1]
                f_t = [f1[0]+f2[0], f1[1]+f2[1]]
                del obj.power[0]
                del obj.power[0]
                obj.power.append(f_t)
            obj.position[0] += obj.power[0][0]/obj.mass
            obj.position[1] += obj.power[0][1]/obj.mass
            obj.speed = [obj.power[0][0]/obj.mass, obj.power[0][1]/obj.mass]
            # print(obj.speed)

    def display(self, scr, show_orbit, length=500):
        for obj in self.objects:
            pygame.draw.circle(scr, obj.color, (int(obj.position[0]), int(obj.position[1])), obj.volume)
            if show_orbit:
                obj.positions = obj.positions[:]
                obj.positions.insert(0, [int(obj.position[0]), int(obj.position[1])])
                pygame.draw.aalines(scr, obj.color, False, obj.positions, 3)
                if len(obj.positions) > length:
                    del obj.positions[-1]
                elif len(obj.positions) > len(self.objects):
                    if obj.position_ in obj.positions:
                        for n in range(len(self.objects)):
                            del obj.positions[-1]

    def display_data(self, scr, c):
        font = pygame.font.SysFont("Consolas", 25)
        fps = font.render("FPS: "+str(round(c.get_fps(), 2)), False, (255, 255, 255))
        scr.blit(fps, (50, 50))
        if self.objects:
            for index, obj in enumerate(self.objects):
                pos = font.render(obj.name+": "+str(int(obj.position[0])) + "  " +
                                  str(int(obj.position[1])), False, (255, 255, 255))
                scr.blit(pos, (50, 80+index*35))


class Objects(object):
    mass = 0        # 质量
    power = []      # 受到的力,矢量[大小,方向]
    speed = []      # 初速度,矢量[大小,方向]
    position = []   # 位置
    position_ = []  # 最初位置
    move_to = []    # 下一帧移动的距离,方向
    positions = []  # 所有的点
    volume = 0      # 体积
    color = []      # 颜色
    name = ""       # 名字

    def __init__(self, name, mass, speed, position, volume, color):
        self.mass = mass
        self.position = position
        self.volume = volume
        self.speed = speed
        self.color = color
        self.name = name
        self.positions.append(position[:])
        self.position_ = position[:]


universe = System("Earth University")

earth = Objects("Earth", 1000, [0, 0], [200, 200], 5, [115, 15, 249])
sun = Objects("Sun", 1000, [0, 0], [500, 600], 5, [255, 0, 0])
moon = Objects("Moon", 1000, [0, 0], [500, 300], 5, [0, 255, 0])
mars = Objects("Mars", 1000, [0, 0], [600, 400], 5, [15, 215, 249])

universe.add_object(earth)
universe.add_object(sun)
universe.add_object(moon)
universe.add_object(mars)

universe.work_power()
universe.work_force()

pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode([1500, 1200])
pygame.display.set_caption("Force")

keep = True

while keep:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            keep = False

    screen.fill((0, 0, 0))

    universe.work_power()
    universe.work_force()
    universe.display(screen, True)
    universe.display_data(screen, clock)

    pygame.display.update()
    clock.tick(200)

pygame.quit()

进阶

要实现V.1.0.10版就要添加功能:添加和移除物体
实际上就是添加一个方法:

    def set_object(self, scr, k):
        def draw_mesh(w, h, e, scr_, color):	# 画网格
            for n in range(0, w, e):
                pygame.draw.line(scr_, color, (n, 0), (n, h))
            for n in range(0, h, e):
                pygame.draw.line(scr_, color, (0, n), (w, n))
            for n in range(0, w, e * 10):
                pygame.draw.line(scr_, (255, 255, 255), (n, 0), (n, h), 1)
            for n in range(0, h, e * 10):
                pygame.draw.line(scr_, (255, 255, 255), (0, n), (w, n), 1)

        def draw_mouse(scr_):
            pygame.draw.line(scr_, (255, 0, 0), (x, 0), (x, 800), 2)
            pygame.draw.line(scr_, (255, 0, 0), (0, y), (1000, y), 2)

        def display_data(scr_, mx, my):
            font_ = pygame.font.SysFont("Consolas", 25)
            pos = font_.render("Pos: " + str(mx) + "  " + str(my), False, (255, 255, 255))
            scr_.blit(pos, (50, 50))

        def adding_mode(x_, y_):
            def name_it():
                self.name_ = input("Please name the object")
            named = Thread(target=name_it)
            named.start()

            while True:
                for event__ in pygame.event.get():
                    if event__.type == pygame.QUIT:
                        break
                scr.fill((0, 0, 0))
                pygame.mouse.set_visible(True)

                # 画数据
                font_ = pygame.font.SysFont("Consolas", 25)
                fun_ = font_.render("Enter Object's name", False, (155, 155, 255))
                scr.blit(fun_, (550, 50))
                if self.name_ != "":
                    new_object = Objects(self.name_, 1000, [0, 0], [x_, y_], 5, [random.randint(55, 255),
                                                                                 random.randint(55, 255),
                                                                                 random.randint(55, 255)])
                    self.add_object(new_object)
                    self.name_ = ""
                    break

        if k[pygame.K_a]:
            while True:
                for event_ in pygame.event.get():
                    if event_.type == pygame.QUIT:
                        break
                scr.fill((0, 0, 0))
                pygame.mouse.set_visible(False)     # 隐藏鼠标
                # 画网格
                x, y = pygame.mouse.get_pos()
                screen.fill((0, 0, 0))
                draw_mesh(1000, 800, 20, screen, (110, 110, 110))
                draw_mouse(scr)
                display_data(scr, x, y)
                # 画数据
                font = pygame.font.SysFont("Consolas", 25)
                fun = font.render("Press 'q' to stop adding", False, (155, 155, 255))
                scr.blit(fun, (550, 50))
                k = pygame.key.get_pressed()
                if pygame.mouse.get_pressed()[0] == 1:
                    adding_mode(x, y)
                # 退出添加模式
                if k[pygame.K_q]:
                    pygame.mouse.set_visible(True)      # 显示鼠标
                    break
                pygame.display.update()
        elif k[pygame.K_m]:
            f = False
            index = -1

            def name_it_():
                self.name_ = input("Please enter the object's name")

            named_ = Thread(target=name_it_)
            named_.start()
            while True:
                for event___ in pygame.event.get():
                    if event___.type == pygame.QUIT:
                        break
                scr.fill((0, 0, 0))
                pygame.mouse.set_visible(True)

                # 画数据
                font__ = pygame.font.SysFont("Consolas", 25)
                fun__ = font__.render("Enter Object's name", False, (155, 155, 255))
                scr.blit(fun__, (550, 50))
                if self.name_ != "":
                    for n_ in self.objects:
                        index += 1
                        if n_.name == self.name_:
                            f = True
                            del self.objects[index]
                    if f:
                        print("Find it and remove it!")
                    else:
                        print("None!")
                    self.name_ = ""
                    break
                pygame.display.update()

代码很好理解,就不再赘述
Ok,放V1.0.10版全部代码

import pygame, random
from threading import Thread
"""
万有引力公式:
F = G * (m1*m2)/r**2
其中 F 为受某力的大小,m1,m2分别为两物体的质量,r为距离
牛顿第二定律:
F = am
a为加速度
m为物体质量
推导公式:
a = F/m
m = F/a
"""
G, PI = 6.754*0.00001, 3.14159265358979323


class System(object):
    name = ""
    objects = []
    name_ = ""

    def __init__(self, name):
        self.name = name

    def add_object(self, obj):
        self.objects.append(obj)

    def work_power(self):
        for obj in self.objects:
            obj.power = []
            if obj.speed == [0, 0]:
                pass
            else:
                obj.speed[0] = obj.speed[0] * obj.mass
                obj.speed[1] = obj.speed[1] * obj.mass
                obj.power.append(obj.speed)
            for o in self.objects:
                v0 = o.position[0] - obj.position[0]
                v1 = o.position[1] - obj.position[1]
                distance_2 = v0 ** 2 + v1 ** 2
                if distance_2 == 0:
                    pass
                else:
                    v0 *= G/distance_2*(obj.mass*o.mass)
                    v1 *= G/distance_2*(obj.mass*o.mass)
                    obj.power.append([v0, v1])

    def work_force(self):
        for obj in self.objects:
            for n in range(len(obj.power) - 1):
                f1 = obj.power[0]
                f2 = obj.power[1]
                f_t = [f1[0]+f2[0], f1[1]+f2[1]]
                del obj.power[0]
                del obj.power[0]
                obj.power.append(f_t)
            obj.position[0] += obj.power[0][0]/obj.mass
            obj.position[1] += obj.power[0][1]/obj.mass
            obj.speed = [obj.power[0][0]/obj.mass, obj.power[0][1]/obj.mass]
            # print(obj.speed)

    def display(self, scr, show_orbit, length=500):
        for obj in self.objects:
            pygame.draw.circle(scr, obj.color, (int(obj.position[0]), int(obj.position[1])), obj.volume)
            if show_orbit:
                obj.positions = obj.positions[:]
                obj.positions.insert(0, [int(obj.position[0]), int(obj.position[1])])
                pygame.draw.aalines(scr, obj.color, False, obj.positions, 3)
                if len(obj.positions) > length:
                    del obj.positions[-1]
                elif len(obj.positions) > len(self.objects):
                    if obj.position_ in obj.positions:
                        for n in range(len(self.objects)):
                            del obj.positions[-1]

    def display_data(self, scr, c):
        font = pygame.font.SysFont("Consolas", 25)
        fps = font.render("FPS: "+str(round(c.get_fps(), 2)), False, (255, 255, 255))
        fun = font.render("Press 'a' to add a object", False, (155, 155, 255))
        scr.blit(fun, (550, 50))
        fun = font.render("Press 'm' to remove a object", False, (155, 155, 255))
        scr.blit(fun, (550, 100))
        scr.blit(fps, (50, 50))
        if self.objects:
            for index, obj in enumerate(self.objects):
                pos = font.render(obj.name+": "+str(int(obj.position[0])) + "  " +
                                  str(int(obj.position[1])), False, (255, 255, 255))
                scr.blit(pos, (50, 80+index*35))

    def set_object(self, scr, k):
        def draw_mesh(w, h, e, scr_, color):
            for n in range(0, w, e):
                pygame.draw.line(scr_, color, (n, 0), (n, h))
            for n in range(0, h, e):
                pygame.draw.line(scr_, color, (0, n), (w, n))
            for n in range(0, w, e * 10):
                pygame.draw.line(scr_, (255, 255, 255), (n, 0), (n, h), 1)
            for n in range(0, h, e * 10):
                pygame.draw.line(scr_, (255, 255, 255), (0, n), (w, n), 1)

        def draw_mouse(scr_):
            pygame.draw.line(scr_, (255, 0, 0), (x, 0), (x, 800), 2)
            pygame.draw.line(scr_, (255, 0, 0), (0, y), (1000, y), 2)

        def display_data(scr_, mx, my):
            font_ = pygame.font.SysFont("Consolas", 25)
            pos = font_.render("Pos: " + str(mx) + "  " + str(my), False, (255, 255, 255))
            scr_.blit(pos, (50, 50))

        def adding_mode(x_, y_):
            def name_it():
                self.name_ = input("Please name the object")
            named = Thread(target=name_it)
            named.start()

            while True:
                for event__ in pygame.event.get():
                    if event__.type == pygame.QUIT:
                        break
                scr.fill((0, 0, 0))
                pygame.mouse.set_visible(True)

                # 画数据
                font_ = pygame.font.SysFont("Consolas", 25)
                fun_ = font_.render("Enter Object's name", False, (155, 155, 255))
                scr.blit(fun_, (550, 50))
                if self.name_ != "":
                    new_object = Objects(self.name_, 1000, [0, 0], [x_, y_], 5, [random.randint(55, 255),
                                                                                 random.randint(55, 255),
                                                                                 random.randint(55, 255)])
                    self.add_object(new_object)
                    self.name_ = ""
                    break

        if k[pygame.K_a]:
            while True:
                for event_ in pygame.event.get():
                    if event_.type == pygame.QUIT:
                        break
                scr.fill((0, 0, 0))
                pygame.mouse.set_visible(False)     # 隐藏鼠标
                # 画网格
                x, y = pygame.mouse.get_pos()
                screen.fill((0, 0, 0))
                draw_mesh(1000, 800, 20, screen, (110, 110, 110))
                draw_mouse(scr)
                display_data(scr, x, y)
                # 画数据
                font = pygame.font.SysFont("Consolas", 25)
                fun = font.render("Press 'q' to stop adding", False, (155, 155, 255))
                scr.blit(fun, (550, 50))
                k = pygame.key.get_pressed()
                if pygame.mouse.get_pressed()[0] == 1:
                    adding_mode(x, y)
                # 退出添加模式
                if k[pygame.K_q]:
                    pygame.mouse.set_visible(True)      # 显示鼠标
                    break
                pygame.display.update()
        elif k[pygame.K_m]:
            f = False
            index = -1

            def name_it_():
                self.name_ = input("Please enter the object's name")

            named_ = Thread(target=name_it_)
            named_.start()
            while True:
                for event___ in pygame.event.get():
                    if event___.type == pygame.QUIT:
                        break
                scr.fill((0, 0, 0))
                pygame.mouse.set_visible(True)

                # 画数据
                font__ = pygame.font.SysFont("Consolas", 25)
                fun__ = font__.render("Enter Object's name", False, (155, 155, 255))
                scr.blit(fun__, (550, 50))
                if self.name_ != "":
                    for n_ in self.objects:
                        index += 1
                        if n_.name == self.name_:
                            f = True
                            del self.objects[index]
                    if f:
                        print("Find it and remove it!")
                    else:
                        print("None!")
                    self.name_ = ""
                    break
                pygame.display.update()


class Objects(object):
    mass = 0        # 质量
    power = []      # 受到的力,矢量[大小,方向]
    speed = []      # 初速度,矢量[大小,方向]
    position = []   # 位置
    position_ = []  # 最初位置
    move_to = []    # 下一帧移动的距离,方向
    positions = []  # 所有的点
    volume = 0      # 体积
    color = []      # 颜色
    name = ""       # 名字

    def __init__(self, name, mass, speed, position, volume, color):
        self.mass = mass
        self.position = position
        self.volume = volume
        self.speed = speed
        self.color = color
        self.name = name
        self.positions.append(position[:])
        self.position_ = position[:]


universe = System("Earth University")

universe.work_power()
universe.work_force()

pygame.init()
clock = pygame.time.Clock()
screen = pygame.display.set_mode([1000, 800])
pygame.display.set_caption("Force")

keep = True

while keep:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            keep = False

    screen.fill((0, 0, 0))

    universe.work_power()
    universe.work_force()
    universe.display(screen, True)
    universe.display_data(screen, clock)

    pygame.display.update()
    clock.tick(200)
    key = pygame.key.get_pressed()
    universe.set_object(screen, key)

pygame.quit()

转载请声明来处.

  • 10
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
三体问题是指三个天体之间相互作用的问题,可以用牛顿万有引力定律来描述。为了模拟三体问题,我们需要定义每个天体的质量、初始位置和速度,并使用数值积分方法来计算它们的运动轨迹。以下是一个使用 Python 模拟三体问题的示例代码: ```python import numpy as np import matplotlib.pyplot as plt # 定义天体质量、初始位置和速度 m1, m2, m3 = 1, 1, 1 G = 1 r1 = np.array([-0.5, 0, 0]) r2 = np.array([0.5, 0, 0]) r3 = np.array([0, 1, 0]) v1 = np.array([0.5, 0.5, 0]) v2 = np.array([-0.5, -0.5, 0]) v3 = np.array([0, 0, 0]) # 定义运动方程 def f(r): x1, y1, z1, x2, y2, z2, x3, y3, z3 = r r12 = np.sqrt((x1 - x2)**2 + (y1 - y2)**2 + (z1 - z2)**2) r13 = np.sqrt((x1 - x3)**2 + (y1 - y3)**2 + (z1 - z3)**2) r23 = np.sqrt((x2 - x3)**2 + (y2 - y3)**2 + (z2 - z3)**2) ax1 = G * m2 * (x2 - x1) / r12**3 + G * m3 * (x3 - x1) / r13**3 ay1 = G * m2 * (y2 - y1) / r12**3 + G * m3 * (y3 - y1) / r13**3 az1 = G * m2 * (z2 - z1) / r12**3 + G * m3 * (z3 - z1) / r13**3 ax2 = G * m1 * (x1 - x2) / r12**3 + G * m3 * (x3 - x2) / r23**3 ay2 = G * m1 * (y1 - y2) / r12**3 + G * m3 * (y3 - y2) / r23**3 az2 = G * m1 * (z1 - z2) / r12**3 + G * m3 * (z3 - z2) / r23**3 ax3 = G * m1 * (x1 - x3) / r13**3 + G * m2 * (x2 - x3) / r23**3 ay3 = G * m1 * (y1 - y3) / r13**3 + G * m2 * (y2 - y3) / r23**3 az3 = G * m1 * (z1 - z3) / r13**3 + G * m2 * (z2 - z3) / r23**3 return np.array([v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2], ax1, ay1, az1, ax2, ay2, az2, ax3, ay3, az3]) # 使用 Runge-Kutta 数值积分方法计算运动轨迹 r = np.array([r1[0], r1[1], r1[2], r2[0], r2[1], r2[2], r3[0], r3[1], r3[2], v1[0], v1[1], v1[2], v2[0], v2[1], v2[2], v3[0], v3[1], v3[2]]) dt = 0.01 t = np.arange(0, 100, dt) x1, y1, z1, x2, y2, z2, x3, y3, z3 = np.zeros((9, len(t))) for i in range(len(t)): x1[i], y1[i], z1[i], x2[i], y2[i], z2[i], x3[i], y3[i], z3[i], vx1, vy1, vz1, vx2, vy2, vz2, vx3, vy3, vz3 = r k1 = dt * f(r) k2 = dt * f(r + 0.5 * k1) k3 = dt * f(r + 0.5 * k2) k4 = dt * f(r + k3) r += (k1 + 2 * k2 + 2 * k3 + k4) / 6 # 绘制运动轨迹 fig = plt.figure() ax = fig.add_subplot(111, projection='3d') ax.plot(x1, y1, z1, label='Body 1') ax.plot(x2, y2, z2, label='Body 2') ax.plot(x3, y3, z3, label='Body 3') ax.set_xlabel('X') ax.set_ylabel('Y') ax.set_zlabel('Z') ax.legend() plt.show() ``` 在上述代码中,我们使用了 Runge-Kutta 数值积分方法来计算天体的运动轨迹。具体来说,我们将运动方程表示为 $f(r)$,其中 $r$ 是一个包含位置和速度的向量,然后使用 Runge-Kutta 方法迭代计算 $r$ 的值。最后,我们使用 Matplotlib 库绘制了三个天体的运动轨迹。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值