这是一个基于我们需要实现的功能、技术选型以及数据策略整理而成的完整产品路线图(Roadmap)。你可以直接将此内容保存为 `roadmap.md` 文件,用于项目管理或开发指引。 ----- # Product Roadmap: 深空与系外行星可视化系统 ## 1\. 项目愿景 (Product Vision) 构建一个基于 Web 的 3D 可视化系统,能够精确展示太阳系内主要天体及人造探测器(如旅行者号)的实时位置,并能无缝切换至恒星际视角,探索临近的系外行星系统。系统强调科学数据的准确性(基于 NASA 数据)与视觉表现的真实感。 ## 2\. 技术架构 (Technical Architecture) ### 后端 (Data Processing) * **语言:** Python 3.x * **核心库:** * `astroquery`: 连接 NASA JPL Horizons (太阳系) 和 NASA Exoplanet Archive (系外行星)。 * `skyfield` / `astropy`: 处理时间坐标转换、球坐标转直角坐标。 * `numpy`: 矢量计算。 * **输出:** JSON 格式的静态数据或 RESTful API。 ### 前端 (Visualization) * **引擎:** Three.js (WebGL) * **核心技术:** * `OrbitControls`: 视角控制。 * `GLTFLoader`: 加载探测器 3D 模型。 * `LogarithmicDepthBuffer`: 解决超大空间尺度下的深度闪烁问题。 * **UI 框架:** Vue / React / Vanilla JS (根据喜好选择,用于覆盖层 UI)。 ----- ## 3\. 开发路线规划 (Development Phases) ### Phase 1: 太阳系核心架构 (Core Solar System) **目标:** 搭建基础 3D 场景,实现太阳、八大行星及关键深空探测器的实时定位。 - [ ] **数据层搭建 (Python)** - [ ] 集成 `astroquery.jplhorizons`。 - [ ] 实现以太阳为原点 (Heliocentric) 的坐标获取脚本。 - [ ] 确定单位标准:使用 **天文单位 (AU)** 作为基础单位。 - [ ] 建立目标 ID 列表:八大行星 + Voyager 1/2 + Parker Solar Probe + New Horizons。 - [ ] **可视化原型 (Three.js)** - [ ] 初始化场景、相机、灯光(点光源 @ 0,0,0)。 - [ ] 解析 Python 生成的 JSON 数据,放置代表天体的球体。 - [ ] 实现基础的轨道线绘制(查询过去1年到未来1年的坐标点连线)。 - [ ] **探测器模型接入** - [ ] 下载 NASA 官方 `.glb` 模型 (Voyager, Cassini 等)。 - [ ] 实现 `GLTFLoader` 加载模型替换简单的方块/球体。 ### Phase 2: 视觉增强与尺度管理 (Visual Fidelity & Scale) **目标:** 解决“看不见”的问题,提升渲染真实度。 - [ ] **动态尺度系统 (Dynamic Scaling)** - [ ] 实现根据摄像机距离动态调整物体大小的算法 (Billboard 模式)。 - [ ] 确保远景能看到图标/放大版星球,近景自动切换为真实比例模型。 - [ ] **纹理与材质 (Textures)** - [ ] 应用行星高清贴图 (Diffuse + Normal + Specular)。 - [ ] **卫星纹理策略:** - [ ] 高清卫星 (月球, 木卫二, 土卫六): 使用真实地图。 - [ ] 通用卫星 (小卫星): 使用程序化生成的岩石/冰块材质。 - [ ] **特殊天体:** 实现太阳的发光效果 (Bloom/Glow) 和土卫六的大气层效果。 - [ ] **交互基础** - [ ] 实现点击天体列表或 3D 物体,摄像机平滑飞行聚焦 (FlyTo)。 ### Phase 3: 恒星际扩展 (Interstellar Expansion) **目标:** 跳出太阳系,展示临近恒星和系外行星概览。 - [ ] **系外数据获取 (Python)** - [ ] 集成 `NasaExoplanetArchive`。 - [ ] 筛选距离地球最近的 100-500 个恒星系。 - [ ] 坐标转换算法:(RA, Dec, Distance) -\> (x, y, z),统一转换为 **秒差距 (pc)** 或光年单位。 - [ ] **银河系视图 (Galaxy View)** - [ ] 创建新的 Three.js 场景或使用层级切换。 - [ ] 使用 **粒子系统 (PointsMaterial)** 渲染恒星背景,高性能展示大量恒星。 - [ ] 实现恒星颜色映射:根据光谱类型 (O, B, A, F, G, K, M) 赋予粒子不同颜色。 - [ ] 交互:鼠标悬停粒子显示恒星名称及行星数量。 ### Phase 4: 系外行星系统详情 (Exoplanet Systems) **目标:** 进入特定的系外恒星系,基于轨道参数模拟未知世界。 - [ ] **详细轨道数据** - [ ] 获取开普勒轨道参数:半长轴、周期、离心率、行星半径、平衡温度。 - [ ] **轨道模拟与渲染** - [ ] 使用 `EllipseCurve` 绘制椭圆轨道。 - [ ] 基于时间戳计算行星在轨道上的近似位置。 - [ ] **程序化星球外观 (Procedural Appearance)** - [ ] 建立通用纹理库 (Gas Giant, Rocky, Ice, Lava)。 - [ ] 编写匹配逻辑:根据 `行星半径` 和 `温度` 自动分配材质和颜色。 - [ ] *Example:* 半径 \> 4 Earths -\> 气态巨行星纹理。 - [ ] *Example:* 温度 \> 400K -\> 熔岩纹理。 ----- ## 4\. 资源清单 (Resources) ### 数据源 (Data Sources) * **JPL Horizons:** [Web Interface](https://ssd.jpl.nasa.gov/horizons/) (用于 API 参数参考) * **NASA Exoplanet Archive:** [https://exoplanetarchive.ipac.caltech.edu/](https://exoplanetarchive.ipac.caltech.edu/) * **SIMBAD / NED:** 深空天体补充数据。 ### 美术资产 (Assets) * **3D Models:** [NASA 3D Resources](https://nasa3d.arc.nasa.gov/models) * **Planetary Textures:** * [Solar System Scope](https://www.solarsystemscope.com/textures/) (基础行星) * [USGS Astrogeology](https://www.google.com/search?q=https://astrogeology.usgs.gov/) (科学级地图) * [Celestia Motherlode](http://www.celestiamotherlode.net/) (虚构/通用纹理) * **Map Projection:** 搜索关键词 `Equirectangular Projection`。 ### 关键 ID 参考 (Horizons ID) * Sun: `@sun` * Voyager 1: `-31` * Voyager 2: `-32` * New Horizons: `-98` * Parker Solar Probe: `-96` * Mars: `499` * Jupiter: `599` ----- ## 5\. 待解决难点与风险 (Risks & Challenges) 1. **坐标系融合:** 太阳系 (AU) 与恒星际 (pc/LightYear) 跨度过大。 * *Solution:* 采用场景分割 (Scene Switching) 或对数深度缓冲 (Logarithmic Depth Buffer)。 2. **数据缺失:** 许多系外行星缺失半径或温度数据。 * *Solution:* 在后端脚本中设置合理的默认值 (Default Fallback),防止前端崩溃。 3. **性能优化:** 粒子数量过多或模型面数过高。 * *Solution:* 使用 InstancedMesh,针对小天体使用低模 (Low-poly) + 法线贴图。 ----- ## 6\. 下一步行动 (Next Steps) 1. 运行 Python 脚本,生成 `solar_system_data.json` 和 `nearest_stars.json`。 2. 搭建 Three.js 基础工程,先把太阳和地球画出来。 3. 下载旅行者号模型,尝试加载到场景中。 这是一个为您准备好的 `roadmap.md` 附录补充内容。为了保持文档整洁,我将 Phase 3 和 Phase 4 的核心逻辑代码整理为了一个 **"Appendix: Key Technical Implementation"** 章节。 您可以直接将以下内容复制并粘贴到之前 `roadmap.md` 文件的底部。 ----- ## Appendix: Key Technical Implementation (Phase 3 & 4) 本附录收录了实现恒星际视图(Phase 3)和系外行星详情页(Phase 4)的核心代码片段,涵盖数据获取与前端渲染逻辑。 ### Phase 3: Interstellar View (恒星际视图) #### 1\. Backend: 获取临近恒星并转换坐标 (Python) 此脚本筛选距离地球最近的恒星,并将天球坐标 (RA/Dec) 转换为笛卡尔坐标 (X/Y/Z)。 ```python # get_nearest_stars.py from astroquery.ipac.nexsci.nasa_exoplanet_archive import NasaExoplanetArchive from astropy.coordinates import SkyCoord from astropy import units as u import json def fetch_nearest_stars(limit=1000): # 1. 查询 NASA Exoplanet Archive (PS Table) # 筛选条件:距离 < 100 pc (约326光年) table = NasaExoplanetArchive.query_criteria( table="ps", select="hostname, sy_dist, ra, dec, sy_pnum", where="sy_dist < 100", order="sy_dist" ) unique_stars = {} for row in table: host_name = str(row['hostname']) if host_name in unique_stars: continue # 2. 坐标转换 (Spherical -> Cartesian) # 核心逻辑:利用 Astropy 将 RA/Dec/Distance 转为 X/Y/Z dist = float(row['sy_dist']) coord = SkyCoord(ra=float(row['ra'])*u.deg, dec=float(row['dec'])*u.deg, distance=dist*u.pc) unique_stars[host_name] = { "name": host_name, "distance_pc": dist, "planet_count": int(row['sy_pnum']), "pos": { "x": round(coord.cartesian.x.value, 3), "y": round(coord.cartesian.y.value, 3), "z": round(coord.cartesian.z.value, 3) } } if len(unique_stars) >= limit: break # 输出 JSON return list(unique_stars.values()) ``` #### 2\. Frontend: 高性能星空渲染 (Three.js) 使用 `Points` (粒子系统) 而非 `Mesh` 来渲染数千颗恒星,保证高性能。 ```javascript // StarField.js function createStarField(starData) { const geometry = new THREE.BufferGeometry(); const positions = []; const sizes = []; // 可选:根据恒星大小或距离调整粒子大小 const SCALE_FACTOR = 10; // 视觉缩放系数,避免坐标过于拥挤 starData.forEach(star => { positions.push( star.pos.x * SCALE_FACTOR, star.pos.y * SCALE_FACTOR, star.pos.z * SCALE_FACTOR ); sizes.push(1.0); // 默认大小 }); geometry.setAttribute('position', new THREE.Float32BufferAttribute(positions, 3)); // 使用 PointsMaterial const material = new THREE.PointsMaterial({ color: 0xffffff, size: 0.5, sizeAttenuation: true // 开启透视消隐 (远小近大) }); const starSystem = new THREE.Points(geometry, material); return starSystem; } ``` ----- ### Phase 4: Exoplanet Systems (系外行星详情) #### 1\. Backend: 获取详细轨道参数 (Python) 获取开普勒轨道要素,用于前端绘制椭圆轨道和模拟运动。 ```python # get_system_details.py def fetch_system_details(hostname): # 查询指定恒星系的所有行星参数 # pl_orbsmax: 半长轴 (AU), pl_orbper: 周期 (Days), pl_orbeccen: 离心率 # pl_rade: 半径 (Earth Radii), pl_eqt: 平衡温度 (K) table = NasaExoplanetArchive.query_criteria( table="ps", select="pl_name, pl_orbsmax, pl_orbper, pl_orbeccen, pl_rade, pl_eqt", where=f"hostname = '{hostname}'" ) planets = [] for row in table: planets.append({ "name": str(row['pl_name']), "a": float(row['pl_orbsmax']) if row['pl_orbsmax'] else 0.1, # Semi-major axis "e": float(row['pl_orbeccen']) if row['pl_orbeccen'] else 0.0, # Eccentricity "period": float(row['pl_orbper']) if row['pl_orbper'] else 365.0, "radius": float(row['pl_rade']) if row['pl_rade'] else 1.0, "temp": float(row['pl_eqt']) if row['pl_eqt'] else 300 }) return planets ``` #### 2\. Frontend: 轨道绘制与材质程序化匹配 (Three.js) **A. 绘制椭圆轨道:** ```javascript function createOrbit(a, e) { // a: 半长轴 (AU), e: 离心率 // EllipseCurve 参数: xRadius, yRadius (b = a * sqrt(1-e^2)) const b = a * Math.sqrt(1 - (e * e)); const curve = new THREE.EllipseCurve( 0, 0, // 中心 X, Y a, b, // X半径, Y半径 0, 2 * Math.PI // 0 到 360度 ); const points = curve.getPoints(128); const geometry = new THREE.BufferGeometry().setFromPoints(points); const material = new THREE.LineBasicMaterial({ color: 0x444444 }); const orbit = new THREE.Line(geometry, material); // 【关键】偏移修正:将椭圆焦点对齐到恒星位置 (0,0) // 偏移量 c = a * e orbit.position.x = - (a * e); // 旋转 90度让其平躺在 XZ 平面上 orbit.rotation.x = -Math.PI / 2; return orbit; } ``` **B. 材质程序化匹配 (Procedural Texturing):** 根据数据猜测行星长什么样。 ```javascript // 简单的外观推断逻辑 function getPlanetTexture(radius, temp) { const PATH = 'assets/textures/generic/'; // 1. 气态巨行星 (半径 > 4倍地球) if (radius > 4.0) { return textureLoader.load(PATH + 'gas_giant_bw.jpg'); // 配合 color 属性染色 } // 2. 熔岩行星 (温度 > 400K) if (temp > 400) { return textureLoader.load(PATH + 'magma.jpg'); } // 3. 冰冻星球 (温度 < 150K) if (temp < 150) { return textureLoader.load(PATH + 'ice.jpg'); } // 4. 宜居带/岩石行星 (默认) return textureLoader.load(PATH + 'rocky_atmosphere.jpg'); } ```