use core::cmp::Ordering;
use core::fmt;
use crate::{constants::celestial_objects::SUN, frames::Frame};
use hifitime::Epoch;
#[cfg(feature = "python")]
use pyo3::prelude::*;
#[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "python", pyclass)]
#[cfg_attr(feature = "python", pyo3(module = "anise.astro"))]
pub struct Occultation {
pub epoch: Epoch,
pub percentage: f64,
pub back_frame: Frame,
pub front_frame: Frame,
}
#[cfg_attr(feature = "python", pymethods)]
impl Occultation {
pub fn factor(&self) -> f64 {
self.percentage / 100.0
}
pub const fn is_eclipse_computation(&self) -> bool {
self.back_frame.ephem_origin_id_match(SUN)
}
pub fn is_visible(&self) -> bool {
self.percentage < 1e-3
}
pub fn is_obstructed(&self) -> bool {
self.percentage > 99.999
}
pub fn is_partial(&self) -> bool {
!self.is_visible() && !self.is_obstructed()
}
}
#[cfg_attr(feature = "python", pymethods)]
#[cfg(feature = "python")]
impl Occultation {
#[getter]
fn get_epoch(&self) -> PyResult<Epoch> {
Ok(self.epoch)
}
#[setter]
fn set_epoch(&mut self, epoch: Epoch) -> PyResult<()> {
self.epoch = epoch;
Ok(())
}
#[getter]
fn get_percentage(&self) -> PyResult<f64> {
Ok(self.percentage)
}
#[setter]
fn set_percentage(&mut self, percentage: f64) -> PyResult<()> {
self.percentage = percentage;
Ok(())
}
#[getter]
fn get_back_frame(&self) -> PyResult<Frame> {
Ok(self.back_frame)
}
#[setter]
fn set_back_frame(&mut self, back_frame: Frame) -> PyResult<()> {
self.back_frame = back_frame;
Ok(())
}
#[getter]
fn get_front_frame(&self) -> PyResult<Frame> {
Ok(self.front_frame)
}
#[setter]
fn set_front_frame(&mut self, front_frame: Frame) -> PyResult<()> {
self.front_frame = front_frame;
Ok(())
}
fn __str__(&self) -> String {
format!("{self}")
}
fn __repr__(&self) -> String {
format!("{self} (@{self:p})")
}
}
impl fmt::Display for Occultation {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
if self.is_eclipse_computation() {
if self.is_visible() {
write!(
f,
"{}: no eclipse due to {:e}",
self.epoch, self.front_frame
)
} else if self.is_obstructed() {
write!(f, "{}: umbra due to {:e}", self.epoch, self.front_frame)
} else {
write!(
f,
"{}: penumbra of {:.3}% due to {:e}",
self.epoch, self.percentage, self.front_frame
)
}
} else {
write!(
f,
"{}: {:.3}% occultation of {:e} due to {:e}",
self.epoch, self.percentage, self.front_frame, self.back_frame
)
}
}
}
impl PartialOrd for Occultation {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
if self.front_frame != other.front_frame || self.back_frame != other.back_frame {
None
} else {
self.percentage.partial_cmp(&other.percentage)
}
}
}