sounding_base/station_info.rs
1use metfor::Meters;
2use optional::Optioned;
3
4/// Station information including location data and identification number.
5#[derive(Debug, Clone, Copy, PartialEq, Default)]
6pub struct StationInfo {
7 /// station number, USAF number, eg 727730
8 num: Optioned<i32>,
9 /// Latitude and longitude.
10 location: Option<(f64, f64)>,
11 /// Elevation, this may be in model terrain which is not necessarily the same as the real world.
12 elevation: Optioned<Meters>,
13}
14
15impl StationInfo {
16 /// Create a new `StationInfo` object.
17 ///
18 /// # Arguments
19 /// station_num: The USAF station identifier, or None.
20 ///
21 /// location: The latitude and longitude as a tuple, or None.
22 ///
23 /// elevation: The elevation of the station **in meters**.
24 ///
25 /// # Examples
26 ///
27 /// ```rust
28 /// use metfor::{Meters, Feet};
29 /// use sounding_base::StationInfo;
30 /// use optional::{some, none};
31 ///
32 /// let _stn = StationInfo::new_with_values(12345, (45.2,-113.5), Meters(2000.0));
33 /// let _stn = StationInfo::new_with_values(12345, (45.2,-113.5), Feet(2000.0));
34 /// let _stn = StationInfo::new_with_values(12345, (45.2,-113.5), some(Meters(2000.0)));
35 /// let _stn = StationInfo::new_with_values(12345, (45.2,-113.5), some(Feet(2000.0)));
36 /// let _stn = StationInfo::new_with_values(12345, Some((45.2,-113.5)), Meters(2000.0));
37 /// let _stn = StationInfo::new_with_values(12345, Some((45.2,-113.5)), Feet(2000.0));
38 /// let _stn = StationInfo::new_with_values(12345, Some((45.2,-113.5)), some(Meters(2000.0)));
39 /// let _stn = StationInfo::new_with_values(12345, Some((45.2,-113.5)), some(Feet(2000.0)));
40 /// let _stn = StationInfo::new_with_values(Some(12345), None, Meters(2000.0));
41 /// let _stn = StationInfo::new_with_values(Some(12345), None, Feet(2000.0));
42 /// let _stn = StationInfo::new_with_values(None, (45.2,-113.5), some(Meters(2000.0)));
43 /// let _stn = StationInfo::new_with_values(None, (45.2,-113.5), some(Feet(2000.0)));
44 ///
45 /// // Note that lat-lon is an `Option` and not an `Optioned`
46 /// let _stn = StationInfo::new_with_values(some(12345), None, none::<Feet>());
47 /// let _stn = StationInfo::new_with_values(some(12345), None, none::<Meters>());
48 /// ```
49 #[inline]
50 pub fn new_with_values<T, U, V, W>(station_num: T, location: U, elevation: V) -> Self
51 where
52 T: Into<Optioned<i32>>,
53 U: Into<Option<(f64, f64)>>,
54 Optioned<W>: From<V>,
55 W: optional::Noned + metfor::Length,
56 Meters: From<W>,
57 {
58 let elev: Optioned<W> = Optioned::from(elevation);
59 let elev: Optioned<Meters> = elev.map_t(Meters::from);
60
61 StationInfo {
62 num: station_num.into(),
63 location: location.into(),
64 elevation: elev,
65 }
66 }
67
68 /// Create a new object with default values.
69 ///
70 /// # Examples
71 ///
72 /// ```rust
73 /// use sounding_base::StationInfo;
74 ///
75 /// assert!(StationInfo::new().station_num().is_none());
76 /// assert!(StationInfo::new().location().is_none());
77 /// assert!(StationInfo::new().elevation().is_none());
78 ///
79 /// ```
80 #[inline]
81 pub fn new() -> Self {
82 Self::default()
83 }
84
85 /// Builder method to add a station number.
86 ///
87 /// # Examples
88 ///
89 /// ```rust
90 /// use sounding_base::StationInfo;
91 ///
92 /// assert_eq!(StationInfo::new().with_station(12345).station_num().unwrap(), 12345);
93 /// assert_eq!(StationInfo::new().with_station(Some(12345)).station_num().unwrap(), 12345);
94 ///
95 /// ```
96 #[inline]
97 pub fn with_station<T>(mut self, number: T) -> Self
98 where
99 Optioned<i32>: From<T>,
100 {
101 self.num = Optioned::from(number);
102
103 self
104 }
105
106 /// Builder method to add a location.
107 ///
108 /// # Examples
109 ///
110 /// ```rust
111 /// use sounding_base::StationInfo;
112 ///
113 /// assert_eq!(
114 /// StationInfo::new().with_lat_lon((45.0, -116.0)).location().unwrap(), (45.0, -116.0));
115 /// assert_eq!(
116 /// StationInfo::new().with_lat_lon(Some((45.0, -116.0)))
117 /// .location()
118 /// .unwrap(),
119 /// (45.0, -116.0));
120 ///
121 /// ```
122 #[inline]
123 pub fn with_lat_lon<T>(mut self, coords: T) -> Self
124 where
125 Option<(f64, f64)>: From<T>,
126 {
127 self.location = Option::from(coords);
128 self
129 }
130
131 /// Builder method to add elevation.
132 ///
133 /// # Examples
134 ///```rust
135 /// use metfor::{Meters, Feet, Km};
136 /// use sounding_base::StationInfo;
137 /// use optional::{some, none};
138 ///
139 /// let _info = StationInfo::new().with_elevation(Feet(200.0));
140 /// let _info = StationInfo::new().with_elevation(Meters(200.0));
141 /// let _info = StationInfo::new().with_elevation(Km(2.0));
142 /// let _info = StationInfo::new().with_elevation(some(Feet(200.0)));
143 /// let _info = StationInfo::new().with_elevation(some(Meters(200.0)));
144 /// let _info = StationInfo::new().with_elevation(some(Km(2.0)));
145 /// let _info = StationInfo::new().with_elevation(none::<Feet>());
146 /// let _info = StationInfo::new().with_elevation(none::<Meters>());
147 /// let _info = StationInfo::new().with_elevation(none::<Km>());
148 ///```
149 #[inline]
150 pub fn with_elevation<T, U>(mut self, elev: T) -> Self
151 where
152 Optioned<U>: From<T>,
153 U: optional::Noned + metfor::Length,
154 Meters: From<U>,
155 {
156 let elevation: Optioned<U> = Optioned::from(elev);
157 let elevation: Optioned<Meters> = elevation.map_t(Meters::from);
158
159 self.elevation = elevation;
160 self
161 }
162
163 /// station number, USAF number, eg 727730
164 #[inline]
165 pub fn station_num(&self) -> Optioned<i32> {
166 self.num
167 }
168
169 /// Latitude and longitude.
170 #[inline]
171 pub fn location(&self) -> Option<(f64, f64)> {
172 self.location
173 }
174
175 /// Elevation in meters, this may be in model terrain, not necessarily the same as
176 /// the real world.
177 #[inline]
178 pub fn elevation(&self) -> Optioned<Meters> {
179 self.elevation
180 }
181}