93 lines
2.7 KiB
TypeScript
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;
|
||
|
|
}
|