titanss 0.0.3

Titanss is a celestial simulation crate for the MilkyWay SolarSystem workspace
Documentation
pub struct CloudLayer {
    pub name: &'static str,
    pub composition: &'static str,
    pub base_altitude_m: f64,
    pub top_altitude_m: f64,
    pub optical_depth: f64,
}

pub struct CloudSystemEndpoint {
    pub layers: Vec<CloudLayer>,
}

impl CloudSystemEndpoint {
    pub fn titan_default() -> Self {
        Self {
            layers: vec![
                CloudLayer {
                    name: "stratospheric_haze",
                    composition: "C4N2 + HCN aerosols",
                    base_altitude_m: 300_000.0,
                    top_altitude_m: 500_000.0,
                    optical_depth: 0.5,
                },
                CloudLayer {
                    name: "detached_haze",
                    composition: "tholin aerosols",
                    base_altitude_m: 400_000.0,
                    top_altitude_m: 520_000.0,
                    optical_depth: 0.3,
                },
                CloudLayer {
                    name: "main_haze",
                    composition: "tholin + nitrile aerosols",
                    base_altitude_m: 100_000.0,
                    top_altitude_m: 300_000.0,
                    optical_depth: 3.0,
                },
                CloudLayer {
                    name: "tropospheric_methane",
                    composition: "CH4 droplets",
                    base_altitude_m: 8_000.0,
                    top_altitude_m: 30_000.0,
                    optical_depth: 1.5,
                },
                CloudLayer {
                    name: "low_ethane_fog",
                    composition: "C2H6 + CH4 condensate",
                    base_altitude_m: 0.0,
                    top_altitude_m: 5_000.0,
                    optical_depth: 0.8,
                },
            ],
        }
    }

    pub fn cloud_top_altitude_m(&self) -> f64 {
        self.layers
            .iter()
            .map(|l| l.top_altitude_m)
            .fold(0.0_f64, f64::max)
    }

    pub fn cloud_base_altitude_m(&self) -> f64 {
        self.layers
            .iter()
            .map(|l| l.base_altitude_m)
            .fold(f64::INFINITY, f64::min)
    }

    pub fn total_optical_depth(&self) -> f64 {
        self.layers.iter().map(|l| l.optical_depth).sum()
    }

    pub fn transmission(&self) -> f64 {
        (-self.total_optical_depth()).exp()
    }

    pub fn layer_at_altitude(&self, altitude_m: f64) -> Option<&CloudLayer> {
        self.layers
            .iter()
            .find(|l| altitude_m >= l.base_altitude_m && altitude_m <= l.top_altitude_m)
    }
}