331 lines
13 KiB
Markdown
331 lines
13 KiB
Markdown
这是一个基于我们需要实现的功能、技术选型以及数据策略整理而成的完整产品路线图(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');
|
||
}
|
||
``` |