You need to enable JavaScript to run this app. Python FuncAnimation多行星椭圆轨道动画异常及颜色匹配问题
优惠活动
大模型
产品
解决方案
定价
更多

Python FuncAnimation多行星椭圆轨道动画异常及颜色匹配问题

椭圆轨道行星运动动画实现说明

基础背景

已有的matplotlib多圆点圆周运动动画实现方案,无法适配当前“用小点代表行星,沿椭圆轨道绕中心原点运动”的目标需求。

初始实现问题

  • 初始运行效果表现:仅最外层的行星沿轨道运动,内侧3个行星全部静止
  • 问题根因:FuncAnimation实例被写在for j in range(1, planet_count):循环内部,最后一次循环生成的动画实例覆盖了之前所有循环的实例
planet_count = 5

df = pd.read_csv("Wincoll_prog_chall_1/data2.csv")

df["b"] = df["a"]*(1-df["Epsilon"]**2)


def position(theta, a, eps):
    r = a*(1-eps**2)/(1-eps*np.cos(theta))
    x = r*np.cos(theta)
    y = r*np.sin(theta)

    return r, x, y


num_to_color = {
    1: "orange",
    2: "pink",
    3: "green",
    4: "red",
    5: "brown",
    6: "yellow",
    7: "blue",
    8: "purple",
    9: "grey",
}



def animate(i, a, eps):
    theta = i*math.pi/180
    r = a*(1-eps**2)/(1-eps*np.cos(theta))
    x = r*np.cos(theta)
    y = r*np.sin(theta)
    planet.set_data(x, y)
    return planet,


plt.style.use('dark_background')
fig, ax = plt.subplots(figsize=(10, 10))


if planet_count > 5:
    ax.plot(0, 0, 'X', markersize=5, color="yellow")
else:
    ax.plot(0, 0, 'X', markersize=15, color="yellow")

# planet = []

for j in range(1, planet_count):
    theta = np.linspace(0, 2*math.pi, 1000)
    r, x, y = position(theta, df["a"][j], df["Epsilon"][j])
    ax.plot(x, y, color=num_to_color[j], linewidth=2, label=df["Object"][j])

    planet, = ax.plot(x[0], y[0], '.', markersize=15, color="white")
    
    # Animation
    animation = FuncAnimation(fig, animate, frames=360, interval=5, fargs=(
        df["a"][j], df["Epsilon"][j],), blit=True)

plt.xlabel("x", size=20)
plt.ylabel("y", size=20)
plt.legend(fontsize=12, loc="upper right", numpoints=1)
plt.grid(True, lw=0.3)
plt.show()

初步修正方案

  • 修正思路:新增dataX、dataY两个数组,每次动画帧更新时计算所有行星的坐标存入数组后统一下发更新
  • 修正后效果:所有行星可正常沿轨道完成动画,当前待实现的效果为每个行星点的颜色与对应轨道颜色匹配
import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import math
from matplotlib.animation import FuncAnimation

AU = 149597870700
P = 5

df = pd.read_csv("Wincoll_prog_chall_1/data2.csv")

df["b"] = df["a"]*(1-df["Epsilon"]**2)


def position(theta, a, eps):
    r = a*(1-eps**2)/(1-eps*np.cos(theta))
    x = r*np.cos(theta)
    y = r*np.sin(theta)

    return r, x, y


num_to_color = {
    1: "orange",
    2: "pink",
    3: "green",
    4: "red",
    5: "brown",
    6: "yellow",
    7: "blue",
    8: "purple",
    9: "grey",
}

starting_planet = 1
planet_count = 5

if (planet_count < 6):
    anim_speed = 2.125
else:
    anim_speed = 50


def animate(i):
    dataX = []
    dataY = []

    years = round(1000*i*anim_speed/360)/1000

    for j in range(starting_planet, planet_count):
        theta = (i*anim_speed*np.pi)/(df["P"][j]*180)
        # theta = i*1/df["P"][j]*np.pi/180
        r = df["a"][j]*(1-df["Epsilon"][j]**2) / \
            (1-df["Epsilon"][j]*np.cos(theta))
        x = r*np.cos(theta)
        y = r*np.sin(theta)
        dataX.append(x)
        dataY.append(y)
        # planet.set_color(num_to_color[j])
    planet.set_data(dataX, dataY)
    title.set_text(u"Years: {}".format(years))
    return planet, title,


plt.style.use('dark_background')
fig, ax = plt.subplots(figsize=(10, 10))
# planet, = ax.plot([], [], '.')


if planet_count > 5:
    ax.plot(0, 0, 'X', markersize=5, color="yellow")
else:
    ax.plot(0, 0, 'X', markersize=15, color="yellow")


planet, = ax.plot([], [], '.', markersize=11)


title = ax.text(0.5, 0.97, "", bbox={'facecolor': 'w', 'alpha': 0.0, 'pad': 5},
                transform=ax.transAxes, ha="center")


dataX = []
dataY = []

for j in range(starting_planet, planet_count):
    theta = np.linspace(0, 2*math.pi, 1000)
    r, x, y = position(theta, df["a"][j], df["Epsilon"][j])
    ax.plot(x, y, color=num_to_color[j], linewidth=2, label=df["Object"][j])

    # planet.set_color(num_to_color[j])
    dataX.append(x[0])
    dataY.append(y[0])
animation = FuncAnimation(fig, animate, interval=1, blit=True)


planet.set_data(dataX, dataY)

plt.xlabel("x", size=20)
plt.ylabel("y", size=20)
plt.legend(fontsize=12, loc="upper right", numpoints=1)
plt.grid(True, lw=0.3)
plt.show()

内容的提问来源于stack exchange,提问作者Leon_K

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.02 06:06:04