cosmo/frontend/src/utils/renderPosition.ts

113 lines
3.5 KiB
TypeScript
Raw Normal View History

2025-11-29 15:10:00 +00:00
/**
* Position calculator for celestial bodies
* Returns the scaled rendering position without artificial offsets
*/
import { scalePosition } from './scaleDistance';
import type { CelestialBody } from '../types';
/**
* Calculate rendering position using true scaled coordinates
2025-11-29 16:58:58 +00:00
* For satellites, add a radial offset relative to PARENT PLANET
2025-11-29 15:10:00 +00:00
*/
export function calculateRenderPosition(
body: CelestialBody,
allBodies: CelestialBody[]
2025-11-29 16:58:58 +00:00
): { x: number; y: number; z: number; hasOffset: boolean } {
2025-11-29 15:10:00 +00:00
const pos = body.positions[0];
if (!pos) {
2025-11-29 16:58:58 +00:00
return { x: 0, y: 0, z: 0, hasOffset: false };
2025-11-29 15:10:00 +00:00
}
2025-11-29 16:58:58 +00:00
// 1. Calculate base scaled position (fallback)
2025-11-29 15:10:00 +00:00
const scaled = scalePosition(pos.x, pos.y, pos.z);
2025-11-29 16:58:58 +00:00
// 2. Special handling for satellites (like Moon)
2025-11-29 15:10:00 +00:00
if (body.type === 'satellite') {
2025-11-29 16:58:58 +00:00
const parent = findParentPlanet(body, allBodies);
if (parent) {
const parentPos = parent.positions[0];
// Calculate parent's scaled position (where it is rendered)
// Note: Recursion is possible if parent is also a satellite, but unlikely for planets
const parentScaled = scalePosition(parentPos.x, parentPos.y, parentPos.z);
// Calculate vector from Parent to Satellite (in True AU coordinates)
const dx = pos.x - parentPos.x;
const dy = pos.y - parentPos.y;
const dz = pos.z - parentPos.z;
const dist = Math.sqrt(dx*dx + dy*dy + dz*dz);
if (dist > 0) {
// Normalize the direction vector
const nx = dx / dist;
const ny = dy / dist;
const nz = dz / dist;
2025-11-29 15:10:00 +00:00
2025-11-29 16:58:58 +00:00
// Set a fixed visual offset distance
// Earth radius is 0.6, Moon is 0.15.
// A distance of 1.5 units ensures they are close but distinct and don't overlap.
// This simulates a "mini-system" view at the planet's location.
const visualOffset = 1.5;
return {
x: parentScaled.x + nx * visualOffset,
y: parentScaled.y + ny * visualOffset,
z: parentScaled.z + nz * visualOffset,
hasOffset: true
};
}
2025-11-29 15:10:00 +00:00
}
}
2025-11-29 16:58:58 +00:00
return { x: scaled.x, y: scaled.y, z: scaled.z, hasOffset: false };
2025-11-29 15:10:00 +00:00
}
/**
* Find the parent planet for a celestial body (e.g., Moon orbits Earth)
2025-11-29 16:58:58 +00:00
* Returns the planet that this body is closest to
2025-11-29 15:10:00 +00:00
*/
export function findParentPlanet(
body: CelestialBody,
allBodies: CelestialBody[]
): CelestialBody | null {
const pos = body.positions[0];
if (!pos) return null;
2025-11-29 16:58:58 +00:00
// Look for planets or dwarf planets
2025-11-29 15:10:00 +00:00
const planets = allBodies.filter(b => b.type === 'planet' || b.type === 'dwarf_planet');
let closestPlanet: CelestialBody | null = null;
let minDistance = Infinity;
for (const planet of planets) {
const planetPos = planet.positions[0];
if (!planetPos) continue;
const distance = Math.sqrt(
Math.pow(pos.x - planetPos.x, 2) +
Math.pow(pos.y - planetPos.y, 2) +
Math.pow(pos.z - planetPos.z, 2)
);
2025-11-29 16:58:58 +00:00
// Consider as "parent" if within 0.1 AU
// Moon is ~0.0026 AU from Earth
// Io is ~0.0028 AU from Jupiter
if (distance < 0.1 && distance < minDistance) {
2025-11-29 15:10:00 +00:00
closestPlanet = planet;
minDistance = distance;
}
}
return closestPlanet;
}
/**
* Get description for bodies that are close to planets
*/
export function getOffsetDescription(body: CelestialBody, allBodies: CelestialBody[]): string | null {
// This function is kept for compatibility but no longer calculates offsets
// Could be used to show proximity information in the future
return null;
}