cosmo/frontend/src/utils/renderPosition.ts

93 lines
2.7 KiB
TypeScript

/**
* 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
* For satellites, add a radial offset to avoid being hidden by parent planet
*/
export function calculateRenderPosition(
body: CelestialBody,
allBodies: CelestialBody[]
): { x: number; y: number; z: number } {
const pos = body.positions[0];
if (!pos) {
return { x: 0, y: 0, z: 0 };
}
// Use improved scaling that handles near-Earth objects properly
const scaled = scalePosition(pos.x, pos.y, pos.z);
// For satellites, add a radial offset to separate from parent planet
if (body.type === 'satellite') {
const distance = Math.sqrt(scaled.x ** 2 + scaled.y ** 2 + scaled.z ** 2);
if (distance > 0) {
// Add fixed offset: push satellite 1.2 units further from Sun
// This ensures it's always visible outside the parent planet's visual radius
const fixedOffset = 1.05;
const direction = {
x: scaled.x / distance,
y: scaled.y / distance,
z: scaled.z / distance
};
return {
x: scaled.x + direction.x * fixedOffset,
y: scaled.y + direction.y * fixedOffset,
z: scaled.z + direction.z * fixedOffset
};
}
}
return { x: scaled.x, y: scaled.y, z: scaled.z };
}
/**
* Find the parent planet for a celestial body (e.g., Moon orbits Earth)
* Returns the planet that this body is closest to, if within a threshold
*/
export function findParentPlanet(
body: CelestialBody,
allBodies: CelestialBody[]
): CelestialBody | null {
const pos = body.positions[0];
if (!pos) return null;
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)
);
// Consider as "near" if within 0.05 AU (~7.5 million km)
if (distance < 0.05 && distance < minDistance) {
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;
}