Skip to main content

roche/
point.rs

1use pyo3::prelude::*;
2use std::fmt;
3use crate::Etype;
4use crate::Vec3;
5
6///
7/// Struct defining a point on the surface of a model grid (e.g. of a star or disc etc.)
8/// A `Point` has a position, a direction which is the surface normal, an area,
9/// a relative gravity, a vector of phase pairs defining when the point is eclipsed by
10/// another model component, and a flux.
11///
12#[pyclass(skip_from_py_object)]
13#[derive(Clone, Debug)]
14pub struct Point {
15    #[pyo3(get)]
16    pub position: Vec3,
17
18    #[pyo3(get)]
19    pub direction: Vec3,
20
21    #[pyo3(get)]
22    pub area: f32,
23
24    #[pyo3(get)]
25    pub gravity: f32,
26
27    #[pyo3(get)]
28    pub eclipse: Etype,
29
30    #[pyo3(get)]
31    pub flux: f32,
32}
33
34
35#[pymethods]
36impl Point {
37    
38    ///
39    /// Creates a new Point.
40    ///
41    #[new]
42    pub fn new(position: Vec3, direction: Vec3, area: f64, gravity: f64, eclipse: Etype) -> Self {
43        Self {
44            position,
45            direction,
46            area: area as f32,
47            gravity: gravity as f32,
48            eclipse,
49            flux: 0.0,
50        }
51    }
52    ///
53    /// sets the point's flux.
54    ///
55    pub fn set_flux(&mut self, flux: f32) {
56        self.flux = flux;
57    }
58    
59    ///
60    ///checks that the given phase is not during one of the
61    /// phase ranges when the point is eclipsed.
62    ///  
63    pub fn is_visible(&self, phase: f64) -> bool {
64        let phi: f64 = phase - phase.floor();
65        for &(p1, p2) in &self.eclipse {
66            if (phi >= p1 && phi <= p2) || phi <= p2 - 1.0 {
67                return false;
68            }
69        }
70        true
71    }
72    
73    ///
74    /// This version of is_visible will not correct for phases outside
75    /// of expected range to speed up large loops.
76    /// run phase = phase - phase.floor();
77    /// outside of loop beforehand
78    ///
79    pub fn is_visible_phase_normed(&self, phase: f64) -> bool {
80        for &(p1, p2) in &self.eclipse {
81            if (phase >= p1 && phase <= p2) || phase <= p2 - 1.0 {
82                return false;
83            }
84        }
85        true
86    }
87
88    fn __repr__(&self) -> String {
89        // We use the `format!` macro to create a string. Its first argument is a
90        // format string, followed by any number of parameters which replace the
91        // `{}`'s in the format string.
92        format!("Point({}, {}, {}, {}, {:?}, {})", self.position, self.direction, self.area, self.gravity, self.eclipse, self.flux)
93    }
94}
95
96impl Default for Point {
97    fn default() -> Self {
98        Self::new(
99            Vec3::new(0.0, 0.0, 0.0),
100            Vec3::new(0.0, 0.0, 0.0),
101            0.0,
102            0.0,
103            vec![(0.0, 0.0)],
104        )
105    }
106}
107
108impl fmt::Display for Point {
109    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110        write!(
111            f,
112            "Point({}, {}, {}, {}, {:?}, {})",
113            self.position,
114            self.direction,
115            self.area,
116            self.gravity,
117            self.eclipse,
118            self.flux
119        )
120    }
121}
122
123