/** * DwarfPlanetOrbits - renders orbital paths for dwarf planets using NASA data * * Dwarf planets have highly inclined orbits that deviate from the ecliptic plane */ import { useEffect, useState } from 'react'; import { Line } from '@react-three/drei'; import * as THREE from 'three'; import { scalePosition } from '../utils/scaleDistance'; import { request } from '../utils/request'; interface OrbitData { bodyId: string; bodyName: string; points: THREE.Vector3[]; color: string; } export function DwarfPlanetOrbits() { const [orbits, setOrbits] = useState([]); const [loading, setLoading] = useState(true); // Helper function to get default colors const getDefaultColor = (name: string): string => { const colorMap: Record = { 'Pluto': '#8B7355', 'Ceres': '#9E9E9E', 'Eris': '#E0E0E0', 'Haumea': '#D4A574', 'Makemake': '#C49A6C', }; return colorMap[name] || '#CCCCCC'; }; useEffect(() => { const fetchOrbits = async () => { console.log('🌌 Fetching dwarf planet orbits from NASA...'); const orbitData: OrbitData[] = []; try { // Step 1: Get list of dwarf planets from backend const listResponse = await request.get('/celestial/list?body_type=dwarf_planet'); const listData = listResponse.data; const dwarfPlanets = listData.bodies || []; if (dwarfPlanets.length === 0) { console.log('No dwarf planets found in database'); setLoading(false); return; } console.log(`Found ${dwarfPlanets.length} dwarf planets:`, dwarfPlanets.map((p: any) => p.name_zh || p.name)); // Step 2: Fetch orbital data for all dwarf planets in ONE request // Using a 10-year range with monthly samples const startDate = new Date('2020-01-01'); const endDate = new Date('2030-01-01'); // Use body_ids parameter to fetch all dwarf planets const bodyIds = dwarfPlanets.map((p: any) => p.id).join(','); const response = await request.get('/celestial/positions', { params: { body_ids: bodyIds, start_time: startDate.toISOString(), end_time: endDate.toISOString(), step: '30d', }, }); const data = response.data; // Step 3: Process each dwarf planet's orbital data for (const planet of dwarfPlanets) { const bodyData = data.bodies.find((b: any) => b.id === planet.id); if (bodyData && bodyData.positions && bodyData.positions.length > 0) { // Convert positions to Vector3 points with proper scaling const points = bodyData.positions.map((pos: any) => { // Apply the same non-linear scaling used by CelestialBody const scaled = scalePosition(pos.x, pos.y, pos.z); // Convert to Three.js coordinate system (x, z, y) return new THREE.Vector3(scaled.x, scaled.z, scaled.y); }); // Close the orbit loop if endpoints are close enough const firstPoint = points[0]; const lastPoint = points[points.length - 1]; if (firstPoint.distanceTo(lastPoint) < 5) { points.push(firstPoint.clone()); } // Use color from database or default color const color = planet.color || getDefaultColor(planet.name); orbitData.push({ bodyId: planet.id, bodyName: planet.name_zh || planet.name, points, color, }); console.log(`✅ Loaded orbit for ${planet.name_zh || planet.name}: ${points.length} points`); } } } catch (error) { console.error('Error fetching dwarf planet orbits:', error); } setOrbits(orbitData); setLoading(false); console.log(`🎉 Loaded ${orbitData.length} dwarf planet orbits`); }; fetchOrbits(); }, []); if (loading) { console.log('⏳ Loading planet orbits...'); return null; } if (orbits.length === 0) { console.warn('⚠️ No planet orbits loaded'); return null; } return ( {orbits.map((orbit) => ( {/* Orbital path */} ))} ); }