# 天体轨道生成系统文档 **版本**: 1.0 **最后更新**: 2025-12-10 --- ## 概述 Cosmo项目中的行星和矮行星轨道采用**预计算**方式存储在数据库中,而不是实时计算。这样做的好处是: 1. **性能优化** - 前端无需实时计算复杂的椭圆轨道 2. **NASA数据** - 使用真实的NASA JPL Horizons API数据 3. **精确性** - 考虑了引力摄动等真实天文因素 --- ## 轨道生成逻辑 ### 1. 适用天体类型 轨道生成功能仅适用于以下两种天体类型: - **行星 (planet)** - 八大行星 - **矮行星 (dwarf_planet)** - 冥王星、谷神星、阋神星等 ### 2. 生成流程 #### 步骤1: 确定轨道参数 在 `backend/app/api/celestial_orbit.py` 中定义了硬编码的轨道周期: ```python ORBITAL_PERIODS = { # 行星 - 一个完整公转周期 "199": 88.0, # 水星 (88天) "299": 224.7, # 金星 "399": 365.25, # 地球 (1年) "499": 687.0, # 火星 "599": 4333.0, # 木星 (11.86年) "699": 10759.0, # 土星 (29.46年) "799": 30687.0, # 天王星 (84.01年) "899": 60190.0, # 海王星 (164.79年) # 矮行星 - 一个完整公转周期 "999": 90560.0, # 冥王星 (247.94年) "2000001": 1680.0, # 谷神星 (4.6年) "136199": 203500.0,# 阋神星 (557年) "136108": 104000.0,# 妊神星 (285年) "136472": 112897.0,# 鸟神星 (309年) } ``` 轨道颜色也是硬编码的: ```python DEFAULT_COLORS = { "199": "#8C7853", # 水星 - 棕色 "299": "#FFC649", # 金星 - 黄色 "399": "#4A90E2", # 地球 - 蓝色 "499": "#CD5C5C", # 火星 - 红色 # ... 其他天体 } ``` #### 步骤2: 计算采样点数量 采样策略(`orbit_service.py`): ```python MIN_POINTS = 100 # 最少100个点,保证椭圆光滑 MAX_POINTS = 1000 # 最多1000个点,避免数据过大 if period_days < 3650: # < 10年 # 行星:约每天1个点,最少100个 num_points = max(MIN_POINTS, min(int(period_days), 365)) else: # >= 10年 # 外行星和矮行星:每月采样一次 num_points = min(int(period_days / 30), MAX_POINTS) ``` **示例**: - 地球 (365.25天) → 365个采样点 - 冥王星 (90560天 ≈ 248年) → 1000个采样点(每90天一个) #### 步骤3: 查询NASA Horizons API 调用NASA JPL Horizons API获取真实轨道数据: ```python positions = await horizons_service.get_body_positions( body_id=body_id, start_time=start_time, end_time=end_time, step=f"{step_days}d" ) ``` **特殊处理**: - 短周期天体(<150年):从当前时间开始 - 长周期天体(≥150年):从1900年开始(避免超出NASA数据范围) #### 步骤4: 存储到数据库 将轨道点存储到 `orbits` 表: ```sql CREATE TABLE orbits ( body_id VARCHAR(50) PRIMARY KEY, points JSONB NOT NULL, -- [{"x": 1.0, "y": 0.5, "z": 0.0}, ...] num_points INTEGER, -- 点的数量 period_days DOUBLE PRECISION, -- 轨道周期(天) color VARCHAR(20), -- 轨道线颜色 created_at TIMESTAMP, updated_at TIMESTAMP ); ``` --- ## 当前问题与解决方案 ### 问题1: 新增天体后轨道不自动生成 **现状**:管理员在天体管理界面新增矮行星后,需要手动执行以下步骤: 1. 到"NASA数据下载"页面 2. 点击"生成轨道"按钮 3. 系统遍历所有行星/矮行星,调用NASA API生成轨道 **问题**: - 流程繁琐,容易遗忘 - 无法针对单个天体生成 - 新增天体时轨道参数(周期、颜色)是硬编码的 ### 问题2: 轨道参数硬编码 **现状**:轨道周期和颜色定义在 `celestial_orbit.py` 中,无法灵活配置。 **问题**: - 新增矮行星必须修改代码添加周期和颜色 - 无法为自定义天体生成轨道 - 缺乏数据库层面的配置灵活性 --- ## 解决方案设计 ### 方案A: 自动触发轨道生成(推荐) **实现思路**: 1. **数据库扩展** - 在 `celestial_bodies` 表添加轨道参数字段: ```sql ALTER TABLE celestial_bodies ADD COLUMN orbit_period_days DOUBLE PRECISION; ALTER TABLE celestial_bodies ADD COLUMN orbit_color VARCHAR(20); ALTER TABLE celestial_bodies ADD COLUMN auto_generate_orbit BOOLEAN DEFAULT FALSE; ``` 2. **创建天体时自动生成** - 修改 `POST /celestial` API: ```python @router.post("") async def create_celestial_body(body_data, db): # 1. 创建天体 new_body = await celestial_body_service.create_body(body_data.dict(), db) # 2. 如果是行星/矮行星且设置了轨道参数,自动生成轨道 if new_body.type in ["planet", "dwarf_planet"] and new_body.orbit_period_days: await orbit_service.generate_orbit( body_id=new_body.id, body_name=new_body.name_zh or new_body.name, period_days=new_body.orbit_period_days, color=new_body.orbit_color or "#CCCCCC", session=db, horizons_service=horizons_service ) ``` 3. **前端界面调整** - 在天体新增表单中添加: - 轨道周期输入框(天) - 轨道颜色选择器 - "自动生成轨道"复选框 **优点**: - ✅ 无需手动操作,完全自动化 - ✅ 轨道参数可配置 - ✅ 新增天体立即可用 **缺点**: - ⚠️ 创建天体时可能耗时较长(等待NASA API响应) - ⚠️ 需要修改数据库结构 ### 方案B: 异步后台生成 **实现思路**: 1. 创建天体时立即返回,在后台异步生成轨道 2. 使用Celery或FastAPI BackgroundTasks 3. 前端显示"轨道生成中..."状态 **优点**: - ✅ 用户体验好,不会阻塞 - ✅ 可以批量生成 **缺点**: - ⚠️ 需要引入任务队列(增加系统复杂度) - ⚠️ 需要轮询检查生成状态 ### 方案C: 手动触发但优化流程(最简单) **实现思路**: 1. 在天体列表页添加"生成轨道"按钮(每行一个) 2. 点击后调用 `POST /celestial/admin/orbits/generate?body_ids={id}` 3. 使用天体的 `extra_data` 字段存储轨道参数 **优点**: - ✅ 实现简单,无需修改数据库 - ✅ 灵活可控 **缺点**: - ⚠️ 仍需手动操作 --- ## 推荐实施步骤 ### Phase 1: 快速修复(方案C) 1. **修改 `CelestialBodyCreate` 模型**,允许在 `extra_data` 中传入: ```json { "orbit_period_days": 90560.0, "orbit_color": "#8B7355" } ``` 2. **修改轨道生成API**,优先从 `extra_data` 读取参数: ```python # 优先从天体的extra_data读取,其次从硬编码字典读取 extra_data = body.extra_data or {} period = extra_data.get("orbit_period_days") or ORBITAL_PERIODS.get(body.id) color = extra_data.get("orbit_color") or DEFAULT_COLORS.get(body.id, "#CCCCCC") ``` 3. **前端添加按钮** - 在天体管理列表每行添加"生成轨道"操作按钮 ### Phase 2: 自动化(方案A) 1. 添加数据库迁移,新增轨道参数字段 2. 修改创建天体API,支持自动生成 3. 前端表单添加轨道参数输入 --- ## API接口文档 ### 生成轨道 **端点**: `POST /celestial/admin/orbits/generate` **查询参数**: - `body_ids` (可选) - 逗号分隔的天体ID列表,如 "999,2000001" - 如果不提供,则为所有行星和矮行星生成轨道 **响应示例**: ```json { "message": "Generated 2 orbits (0 failed)", "results": [ { "body_id": "999", "body_name": "冥王星", "status": "success", "num_points": 1000, "period_days": 90560.0 } ] } ``` ### 获取轨道数据 **端点**: `GET /celestial/orbits` **查询参数**: - `body_type` (可选) - 过滤天体类型,如 "planet" 或 "dwarf_planet" **响应示例**: ```json { "orbits": [ { "body_id": "399", "body_name": "地球", "body_name_zh": "地球", "points": [ {"x": 1.0, "y": 0.0, "z": 0.0}, {"x": 0.99, "y": 0.01, "z": 0.0}, ... ], "num_points": 365, "period_days": 365.25, "color": "#4A90E2", "updated_at": "2025-12-10T10:30:00" } ] } ``` ### 删除轨道 **端点**: `DELETE /celestial/admin/orbits/{body_id}` **响应**: ```json { "message": "Orbit for 999 deleted successfully" } ``` --- ## 数据库结构 ### orbits 表 | 字段 | 类型 | 说明 | |------|------|------| | body_id | VARCHAR(50) | 天体ID(主键,外键到celestial_bodies) | | points | JSONB | 轨道点数组 [{"x", "y", "z"}, ...] | | num_points | INTEGER | 轨道点数量 | | period_days | DOUBLE PRECISION | 轨道周期(天) | | color | VARCHAR(20) | 轨道线颜色(HEX) | | created_at | TIMESTAMP | 创建时间 | | updated_at | TIMESTAMP | 更新时间 | **索引**: - PRIMARY KEY: `body_id` - FOREIGN KEY: `body_id` → `celestial_bodies.id` (ON DELETE CASCADE) --- ## 前端使用 ### 获取并渲染轨道 ```typescript // 1. 获取轨道数据 const response = await request.get('/celestial/orbits?body_type=planet'); const orbits = response.data.orbits; // 2. 渲染轨道线 orbits.forEach(orbit => { const points = orbit.points.map(p => new Vector3(p.x, p.y, p.z)); const geometry = new BufferGeometry().setFromPoints(points); const material = new LineBasicMaterial({ color: orbit.color }); const line = new Line(geometry, material); scene.add(line); }); ``` --- ## 常见问题 ### Q1: 为什么不实时计算轨道? **A**: 实时计算需要考虑多体引力、引力摄动等复杂因素,计算量大且不准确。预计算方式使用NASA真实数据,更准确且性能更好。 ### Q2: 如何为新增的矮行星生成轨道? **A**: 1. **短期方案**:在天体的 `extra_data` 中添加 `orbit_period_days` 和 `orbit_color` 2. **长期方案**:等待数据库迁移,使用独立字段存储轨道参数 ### Q3: NASA Horizons API有哪些限制? **A**: - 时间范围:通常限制在1900-2200年之间 - 频率限制:建议每次查询间隔1秒 - 天体覆盖:只包含太阳系天体,不包括系外行星 ### Q4: 轨道数据多久更新一次? **A**: 理论上轨道是稳定的,无需频繁更新。建议: - 行星:每年更新一次(考虑引力摄动) - 矮行星:每5年更新一次 --- ## 未来优化方向 1. **自动化轨道生成** - 创建天体时自动触发轨道生成 2. **轨道参数配置化** - 从数据库读取而非硬编码 3. **批量生成优化** - 并发调用NASA API,提升生成速度 4. **轨道缓存策略** - 避免重复生成相同天体的轨道 5. **支持更多天体** - 扩展到卫星、小行星等 --- **文档作者**: Claude Code AI **版本历史**: - v1.0 (2025-12-10) - 初始版本,基于现有代码分析