13 KiB
13 KiB
这是一个基于我们需要实现的功能、技术选型以及数据策略整理而成的完整产品路线图(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加载模型替换简单的方块/球体。
- 下载 NASA 官方
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 (用于 API 参数参考)
- NASA Exoplanet Archive: https://exoplanetarchive.ipac.caltech.edu/
- SIMBAD / NED: 深空天体补充数据。
美术资产 (Assets)
- 3D Models: NASA 3D Resources
- Planetary Textures:
- Solar System Scope (基础行星)
- USGS Astrogeology (科学级地图)
- Celestia Motherlode (虚构/通用纹理)
- 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)
- 坐标系融合: 太阳系 (AU) 与恒星际 (pc/LightYear) 跨度过大。
- Solution: 采用场景分割 (Scene Switching) 或对数深度缓冲 (Logarithmic Depth Buffer)。
- 数据缺失: 许多系外行星缺失半径或温度数据。
- Solution: 在后端脚本中设置合理的默认值 (Default Fallback),防止前端崩溃。
- 性能优化: 粒子数量过多或模型面数过高。
- Solution: 使用 InstancedMesh,针对小天体使用低模 (Low-poly) + 法线贴图。
6. 下一步行动 (Next Steps)
- 运行 Python 脚本,生成
solar_system_data.json和nearest_stars.json。 - 搭建 Three.js 基础工程,先把太阳和地球画出来。
- 下载旅行者号模型,尝试加载到场景中。
这是一个为您准备好的 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)。
# 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 来渲染数千颗恒星,保证高性能。
// 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)
获取开普勒轨道要素,用于前端绘制椭圆轨道和模拟运动。
# 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. 绘制椭圆轨道:
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): 根据数据猜测行星长什么样。
// 简单的外观推断逻辑
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');
}