当前位置:首页>python>Python 可视化升级版:动态太阳系模拟

Python 可视化升级版:动态太阳系模拟

  • 2026-10-11 08:00:24
Python 可视化升级版:动态太阳系模拟

Python 可视化升级版:动态太阳系模拟

✨Python 可视化升级版!带中文标注 + 专业图例的动态太阳系模拟

哈喽各位 Python 爱好者!


unsetunset🎯 升级后核心效果unsetunset

✅ 中文标题 / 标签,彻底解决乱码

 ✅ 黑色星空背景 + 高斯渐变太阳光晕 

✅ 水星、金星、地球(带月球)完整公转 

✅ 椭圆轨道彗星漫游,拖尾效果拉满 

✅ 动态轨迹拖尾 + 实时 FPS 显示 

✅ 专业图例标注(太阳 / 行星 / 卫星 / 彗星 / 轨迹)

 ✅ 坐标轴标注「天文单位」,科普感拉满

 ✅ 支持一键导出 GIF 动图


unsetunset📦 一行安装依赖unsetunset

仅需 3 个 Python 库,数值计算 + 可视化 + 统计分布全覆盖:

pip install numpy matplotlib scipy

unsetunset🌟 完整可运行源码(直接复制)unsetunset

优化版代码,注释详细,中文完美显示:

import numpy as npimport matplotlib.pyplot as pltfrom matplotlib.animation import FuncAnimationimport timefrom scipy.stats import multivariate_normalplt.rcParams['font.sans-serif'] = ['SimHei']  # 解决中文显示乱码# ==================== 全局配置 ====================fig, ax = plt.subplots(figsize=(12, 10))ax.set_xlim(-6, 6)ax.set_ylim(-6, 6)ax.set_aspect('equal')ax.set_facecolor('black')# 中文标题+坐标轴ax.set_title("太阳系天体运动模拟", color='white', fontsize=14, pad=20)ax.set_xlabel("距离 (天文单位)", color='white', fontsize=10)ax.set_ylabel("距离 (天文单位)", color='white', fontsize=10)ax.tick_params(colors='white')  # 坐标轴刻度颜色# 轨迹长度(每个天体保留最近的点数)TRAIL_LEN = 60# ---------- 星空背景 ----------stars = np.random.rand(600, 2) * 12 - 6ax.scatter(stars[:,0], stars[:,1], s=1, c='white', alpha=0.4, zorder=0)# ==================== 太阳光晕配置 ====================halo_config = {'type': 'gaussian',          # 光晕类型:均匀/高斯'n_points': 300,             # 光晕粒子数'radius_range': (0.2, 1.3),   # 光晕半径范围'sigma': 0.4,                # 高斯分布标准差'alpha_range': (0.8, 0.1)    # 透明度渐变}# 生成高斯光晕函数defcreate_halo(center=(0,0), config=halo_config):if config['type'] == 'uniform':        radii = np.random.uniform(config['radius_range'][0], config['radius_range'][1], config['n_points'])        angles = np.random.uniform(0, 2*np.pi, config['n_points'])        x = radii * np.cos(angles) + center[0]        y = radii * np.sin(angles) + center[1]        alpha = np.interp(radii, [config['radius_range'][0], config['radius_range'][1]],                          [config['alpha_range'][0], config['alpha_range'][1]])elif config['type'] == 'gaussian':        cov = [[config['sigma']**2, 0], [0, config['sigma']**2]]        points = multivariate_normal.rvs(mean=center, cov=cov, size=config['n_points'])        x, y = points[:,0], points[:,1]        radii = np.sqrt((x-center[0])**2 + (y-center[1])**2)        max_radius = 2*config['sigma']        alpha = np.interp(radii, [0, max_radius], [config['alpha_range'][0], config['alpha_range'][1]])else:raise ValueError("光晕类型只能是 'uniform' 或 'gaussian'")return x, y, alpha# 绘制太阳+光晕halo_x, halo_y, halo_alpha = create_halo()halo_scatter = ax.scatter(halo_x, halo_y, s=8, c='yellow', alpha=halo_alpha, zorder=2)sun = ax.scatter(0, 0, s=400, c='gold', edgecolors='orange', linewidth=2, zorder=3)# ==================== 行星数据 ====================planets = [    {'name': '水星', 'color': 'gray',   'size': 30, 'radius': 1.2, 'speed': 0.12, 'orbit_color': 'white', 'trail_color': 'gray'},    {'name': '金星', 'color': 'orange', 'size': 50, 'radius': 1.8, 'speed': 0.08, 'orbit_color': 'white', 'trail_color': 'orange'},    {'name': '地球', 'color': 'blue',   'size': 70, 'radius': 2.5, 'speed': 0.06, 'orbit_color': 'white', 'trail_color': 'cyan'},]planet_objs = []          # 行星对象planet_trails = []        # 行星轨迹planet_trail_data = []    # 轨迹坐标数据orbit_objs = []           # 静态轨道线angles = [0.0] * len(planets)# 初始化行星、轨道、轨迹for i, p in enumerate(planets):    planet, = ax.plot([], [], 'o', markersize=np.sqrt(p['size']), color=p['color'],                      markeredgecolor='black', zorder=5)    planet_objs.append(planet)    trail, = ax.plot([], [], '-', color=p['trail_color'], alpha=0.4, linewidth=0.8, zorder=2)    planet_trails.append(trail)    planet_trail_data.append([[], []])# 绘制圆形轨道    theta = np.linspace(0, 2*np.pi, 200)    x_orbit = p['radius'] * np.cos(theta)    y_orbit = p['radius'] * np.sin(theta)    orbit, = ax.plot(x_orbit, y_orbit, '--', color=p['orbit_color'], alpha=0.3, linewidth=0.8, zorder=1)    orbit_objs.append(orbit)# ==================== 卫星数据(月球) ====================satellites = [    {'parent_idx': 2, 'radius': 0.6, 'speed': 0.25, 'color': 'cyan', 'size': 6, 'trail_color': 'lightcyan'},]sat_objs = []sat_trails = []sat_trail_data = []sat_angles = [0.0] * len(satellites)for sat in satellites:    sat_obj, = ax.plot([], [], 'o', markersize=sat['size'], color=sat['color'],                       markeredgecolor='black', zorder=5)    sat_objs.append(sat_obj)    trail, = ax.plot([], [], '-', color=sat['trail_color'], alpha=0.3, linewidth=0.6, zorder=2)    sat_trails.append(trail)    sat_trail_data.append([[], []])# ==================== 彗星数据(椭圆轨道) ====================comets = [    {'a': 4.0, 'b': 2.8, 'speed': 0.035, 'color': 'orange', 'trail_len': 80, 'size': 8, 'trail_color': 'orange'},]comet_objs = []comet_trails = []comet_trail_data = []comet_angles = [0.0] * len(comets)for i, com in enumerate(comets):    comet, = ax.plot([], [], 'o', markersize=com['size'], color=com['color'],                     markeredgecolor='orange', zorder=6)    comet_objs.append(comet)    trail, = ax.plot([], [], '-', color=com['trail_color'], alpha=0.5, linewidth=1.2, zorder=4)    comet_trails.append(trail)    comet_trail_data.append([[], []])# ==================== 专业图例(静态) ====================sun_patch = plt.Line2D([0], [0], marker='o', color='w', markerfacecolor='gold', markersize=12, label='太阳')planet_patch = plt.Line2D([0], [0], marker='o', color='w', markerfacecolor='blue', markersize=8, label='行星')satellite_patch = plt.Line2D([0], [0], marker='o', color='w', markerfacecolor='cyan', markersize=5, label='卫星')comet_patch = plt.Line2D([0], [0], marker='o', color='w', markerfacecolor='orange', markersize=6, label='彗星')trail_patch = plt.Line2D([0], [0], color='white', linestyle='-', linewidth=1, label='天体轨迹')legend = ax.legend(handles=[sun_patch, planet_patch, satellite_patch, comet_patch, trail_patch],                   loc='upper right', fontsize=9, facecolor='black', edgecolor='white', labelcolor='white')legend.get_frame().set_alpha(0.7)# ==================== 实时帧率显示 ====================fps_text = ax.text(0.02, 0.95, '', transform=ax.transAxes, color='white', fontsize=10,                   bbox=dict(facecolor='black', alpha=0.5))last_time = time.time()frame_count = 0# ==================== 轨迹更新函数 ====================defupdate_trail(trail_data, x, y, trail_len):    xlist, ylist = trail_data    xlist.append(x)    ylist.append(y)# 限制轨迹长度if len(xlist) > trail_len:        xlist.pop(0)        ylist.pop(0)return xlist, ylist# ==================== 动画核心更新函数 ====================defupdate(frame):global last_time, frame_count# 1. 更新行星位置与轨迹for i, p in enumerate(planets):        angles[i] += p['speed']        x = p['radius'] * np.cos(angles[i])        y = p['radius'] * np.sin(angles[i])        planet_objs[i].set_data([x], [y])        trail_x, trail_y = update_trail(planet_trail_data[i], x, y, TRAIL_LEN)        planet_trails[i].set_data(trail_x, trail_y)# 2. 更新卫星(绕行星旋转)for i, sat in enumerate(satellites):        sat_angles[i] += sat['speed']        parent_idx = sat['parent_idx']        parent_angle = angles[parent_idx]        parent_r = planets[parent_idx]['radius']        parent_x = parent_r * np.cos(parent_angle)        parent_y = parent_r * np.sin(parent_angle)        rel_x = sat['radius'] * np.cos(sat_angles[i])        rel_y = sat['radius'] * np.sin(sat_angles[i])        sat_x = parent_x + rel_x        sat_y = parent_y + rel_y        sat_objs[i].set_data([sat_x], [sat_y])        trail_x, trail_y = update_trail(sat_trail_data[i], sat_x, sat_y, TRAIL_LEN)        sat_trails[i].set_data(trail_x, trail_y)# 3. 更新彗星(椭圆轨道)for i, com in enumerate(comets):        comet_angles[i] += com['speed']        x = com['a'] * np.cos(comet_angles[i])        y = com['b'] * np.sin(comet_angles[i])        comet_objs[i].set_data([x], [y])        trail_x, trail_y = update_trail(comet_trail_data[i], x, y, com['trail_len'])        comet_trails[i].set_data(trail_x, trail_y)# 4. 计算实时FPS    current_time = time.time()    elapsed = current_time - last_timeif elapsed > 0:        fps = frame_count / elapsed        fps_text.set_text(f'FPS: {fps:.1f}')    frame_count += 1return (planet_objs + planet_trails + sat_objs + sat_trails +            comet_objs + comet_trails + [fps_text])# ==================== 启动动画 ====================ani = FuncAnimation(fig, update, frames=2000, interval=30, blit=True)plt.show()# 可选:保存为GIF动图(需安装pillow)# ani.save('solar_system_with_legend.gif', writer='pillow', fps=30)

unsetunset📝 核心升级点解析(对比基础版)unsetunset

1. 中文显示完美修复

添加一行代码,解决 Matplotlib 中文乱码问题,标题、标签全正常显示:

plt.rcParams['font.sans-serif'] = ['SimHei']

2. 专业界面标注

  • 新增中文标题:太阳系天体运动模拟

  • 新增坐标轴标签:距离 (天文单位),科普更规范

  • 坐标轴 / 刻度改为白色,适配黑色背景,视觉更舒适

3. 高清智能图例

自动生成太阳、行星、卫星、彗星、轨迹的统一图例,无需手动标注,适合教学 / 展示使用。

4. 画布优化

调整为 12×10 比例,预留充足空间展示图例和标题,整体布局更美观。


unsetunset🎨 零基础自定义教程unsetunset

不用改核心逻辑,修改参数就能打造专属太阳系:

  1. 添加行星:在 planets 列表中复制字典,修改名称、颜色、轨道半径即可

  2. 调整速度:增大 speed 数值,天体会公转更快

  3. 修改轨迹:调整 TRAIL\_LEN 控制拖尾长短

  4. 新增彗星:在 comets 中添加字典,修改 a/b 调整椭圆轨道形状

  5. 更换颜色:支持英文颜色 / 十六进制色值,自由搭配


unsetunset🎥 一键保存 GIF 动图unsetunset

取消最后两行注释,即可生成高清动图,发朋友圈 / PPT 超合适:

ani.save('solar_system_with_legend.gif', writer='pillow', fps=30)

💡 保存时动画会后台渲染,等待 10-20 秒即可生成。


unsetunset💡 写在最后unsetunset

这个升级版太阳系模拟,完美兼顾了可视化效果、科普规范性、代码可读性,是 Python 新手学习「数值计算 + 动画可视化」的绝佳练手项目。

从简单的散点星空,到复杂的多天体联动运动,一步步拆解,你会彻底掌握 Matplotlib 动画的核心逻辑~

快运行代码,看看属于你的专属动态太阳系吧!🚀


最新文章

随机文章