pub fn solar_declination_deg(ls_deg: f64) -> f64 {
let eps = crate::AXIAL_TILT_DEG.to_radians();
let ls = ls_deg.to_radians();
(eps.sin() * ls.sin()).asin().to_degrees()
}
pub struct SolarPosition {
pub elevation_deg: f64,
pub direction: [f64; 3],
}
impl SolarPosition {
pub fn compute(ls_deg: f64, local_time_h: f64, lat_deg: f64, lon_deg: f64) -> Self {
if !lon_deg.is_finite() {
return Self {
elevation_deg: f64::NAN,
direction: [f64::NAN; 3],
};
}
let decl = solar_declination_deg(ls_deg).to_radians();
let hour = ((local_time_h - 12.0) * 15.0).to_radians();
let lat = lat_deg.to_radians();
let sin_elev = lat.sin() * decl.sin() + lat.cos() * decl.cos() * hour.cos();
let elev = sin_elev.asin();
Self {
elevation_deg: elev.to_degrees(),
direction: [0.0, elev.sin(), elev.cos()],
}
}
pub fn is_above_horizon(&self) -> bool {
self.elevation_deg > 0.0
}
}