dwarfplanetsfactory 0.0.1

Dwarf planet factory — classify, build and catalogue dwarf planets of any type: Kuiper belt, scattered disk, plutino, cold classical, detached, binary, Ceres-type, and sednoid.
Documentation
use crate::config::parameters;

/// Sednoid: extreme trans-Neptunian object with perihelion far beyond
/// Neptune (q > 50 AU) and semi-major axis > 150 AU.
/// Sedna (a ≈ 506 AU, q ≈ 76 AU) is the archetype.
#[derive(Debug)]
pub struct Sednoid {
    pub radius: f64,
    pub density: f64,
    pub albedo: f64,
    pub semi_major_axis: f64,
    pub eccentricity: f64,
    pub inclination: f64,
    pub rotation_period: f64,
}

impl Sednoid {
    pub fn new(radius: f64, semi_major_axis: f64, eccentricity: f64) -> Self {
        Self {
            radius: radius.clamp(parameters::MIN_DWARF_RADIUS, parameters::MAX_DWARF_RADIUS),
            density: 2000.0,
            albedo: 0.15,
            semi_major_axis: semi_major_axis.clamp(150.0, 2000.0),
            eccentricity: eccentricity.clamp(0.5, 0.99),
            inclination: 12.0,
            rotation_period: 10.0 * 3600.0,
        }
    }

    pub fn with_density(mut self, density: f64) -> Self {
        self.density = density.clamp(500.0, 3500.0);
        self
    }

    pub fn with_albedo(mut self, albedo: f64) -> Self {
        self.albedo = albedo.clamp(0.01, 0.99);
        self
    }

    pub fn with_inclination(mut self, inc: f64) -> Self {
        self.inclination = inc.clamp(0.0, 90.0);
        self
    }

    pub fn with_rotation_period(mut self, period_s: f64) -> Self {
        self.rotation_period = period_s.clamp(3600.0, 1.0e7);
        self
    }

    pub fn mass(&self) -> f64 {
        parameters::sphere_mass(self.radius, self.density)
    }

    pub fn perihelion(&self) -> f64 {
        parameters::perihelion_au(self.semi_major_axis, self.eccentricity)
    }

    pub fn aphelion(&self) -> f64 {
        parameters::aphelion_au(self.semi_major_axis, self.eccentricity)
    }

    pub fn orbital_period_years(&self) -> f64 {
        parameters::orbital_period(self.semi_major_axis, parameters::SOLAR_MASS) / parameters::YEAR
    }

    /// Sednoids have perihelia far beyond Neptune: q > 50 AU
    pub fn is_true_sednoid(&self) -> bool {
        self.perihelion() > 50.0
    }

    /// Inner Oort Cloud candidate if a > 1000 AU
    pub fn is_inner_oort_candidate(&self) -> bool {
        self.semi_major_axis > 1000.0
    }

    /// Planet Nine candidate alignment check:
    /// longitude of perihelion clustering heuristic
    pub fn planet_nine_alignment_score(&self) -> f64 {
        let q = self.perihelion();
        let a = self.semi_major_axis;
        if q > 40.0 && a > 150.0 {
            1.0 - (self.inclination / 90.0).min(1.0)
        } else {
            0.0
        }
    }

    pub fn surface_gravity(&self) -> f64 {
        parameters::surface_gravity(self.mass(), self.radius)
    }

    pub fn escape_velocity(&self) -> f64 {
        parameters::escape_velocity(self.mass(), self.radius)
    }

    pub fn equilibrium_temp(&self) -> f64 {
        parameters::equilibrium_temperature(self.semi_major_axis * parameters::AU, self.albedo)
    }
}