1#[macro_export] macro_rules! inner_define_unsigned_direction {
3 { $with_points:ident } => {
4 pub struct UnsignedDirection<Unit, Number = f64>
9 where
10 Unit: AngleMeasurementUnit,
11 Number: ArithmeticOps,
12 {
13 pub value: Number,
14 phantom: PhantomData<Unit>,
15 }
16
17 impl<Unit, Number> UnsignedDirection<Unit, Number>
18 where
19 Unit: AngleMeasurementUnit,
20 Number: ArithmeticOps,
21 {
22 fn normalize(x: Number) -> Number {
25 let one_cycle = Number::from_f64(Unit::CYCLE_FRACTION);
26 let x2 = x % one_cycle;
27 if x2 >= Number::ZERO {
28 x2
29 } else {
30 x2 + one_cycle
31 }
32 }
33
34 pub fn new(value: Number) -> Self {
36 Self {
37 value: Self::normalize(value),
38 phantom: PhantomData,
39 }
40 }
41
42 measures::if_all_true! { { $with_points }
43 pub fn from_measure_point(m: MeasurePoint<Unit, Number>) -> Self {
45 Self::new(m.value)
46 }
47
48 pub const fn to_measure_point(self) -> MeasurePoint<Unit, Number> {
50 MeasurePoint::<Unit, Number>::new(self.value)
51 }
52 }
53
54 pub fn to_signed_direction(self) -> SignedDirection<Unit, Number> {
56 SignedDirection::<Unit, Number>::new(self.value)
57 }
58
59 pub fn convert<DestUnit>(self) -> UnsignedDirection<DestUnit, Number>
61 where
62 DestUnit: AngleMeasurementUnit<Property = Unit::Property>,
63 {
64 UnsignedDirection::<DestUnit, Number> {
65 value: self.value * Number::from_f64(Unit::RATIO / DestUnit::RATIO)
66 + Number::from_f64((Unit::OFFSET - DestUnit::OFFSET) / DestUnit::RATIO),
67 phantom: PhantomData,
68 }
69 }
70
71 pub fn lossless_into<DestNumber>(self) -> UnsignedDirection<Unit, DestNumber>
73 where
74 DestNumber: ArithmeticOps + From<Number>,
75 {
76 UnsignedDirection::<Unit, DestNumber>::new(DestNumber::from(self.value))
77 }
78
79 pub fn lossy_into<DestNumber>(self) -> UnsignedDirection<Unit, DestNumber>
81 where
82 DestNumber: ArithmeticOps + LossyFrom<Number>,
83 {
84 UnsignedDirection::<Unit, DestNumber> {
85 value: DestNumber::lossy_from(self.value),
86 phantom: PhantomData,
87 }
88 }
89 }
90
91 impl<Unit, Number> Default for UnsignedDirection<Unit, Number>
92 where
93 Unit: AngleMeasurementUnit,
94 Number: ArithmeticOps,
95 {
96 fn default() -> Self {
99 Self::new(Number::ZERO)
100 }
101 }
102
103 measures::if_all_true! { { $with_points }
104 impl<Unit, Number> From<UnsignedDirection<Unit, Number>> for MeasurePoint<Unit, Number>
105 where
106 Unit: AngleMeasurementUnit,
107 Number: ArithmeticOps,
108 {
109 fn from(m: UnsignedDirection<Unit, Number>) -> Self {
112 MeasurePoint::<Unit, Number>::new(m.value)
113 }
114 }
115 }
116
117 impl<Unit> From<UnsignedDirection<Unit, f32>> for UnsignedDirection<Unit, f64>
118 where
119 Unit: AngleMeasurementUnit,
120 {
121 fn from(m: UnsignedDirection<Unit, f32>) -> Self {
124 Self::new(m.value as f64)
125 }
126 }
127
128 impl<Unit, Number> Add<Measure<Unit, Number>> for UnsignedDirection<Unit, Number>
129 where
130 Unit: AngleMeasurementUnit,
131 Number: ArithmeticOps,
132 {
133 type Output = Self;
134
135 fn add(self, other: Measure<Unit, Number>) -> Self::Output {
137 Self::new(self.value + other.value)
138 }
139 }
140
141 impl<Unit, Number> AddAssign<Measure<Unit, Number>> for UnsignedDirection<Unit, Number>
142 where
143 Unit: AngleMeasurementUnit,
144 Number: ArithmeticOps,
145 {
146 fn add_assign(&mut self, other: Measure<Unit, Number>) {
148 *self = *self + other;
149 }
150 }
151
152 impl<Unit, Number> Sub<Measure<Unit, Number>> for UnsignedDirection<Unit, Number>
153 where
154 Unit: AngleMeasurementUnit,
155 Number: ArithmeticOps,
156 {
157 type Output = Self;
158
159 fn sub(self, other: Measure<Unit, Number>) -> Self::Output {
161 Self::new(self.value - other.value)
162 }
163 }
164
165 impl<Unit, Number> SubAssign<Measure<Unit, Number>> for UnsignedDirection<Unit, Number>
166 where
167 Unit: AngleMeasurementUnit,
168 Number: ArithmeticOps,
169 {
170 fn sub_assign(&mut self, other: Measure<Unit, Number>) {
172 *self = *self - other;
173 }
174 }
175
176 impl<Unit, Number> Sub<UnsignedDirection<Unit, Number>> for UnsignedDirection<Unit, Number>
177 where
178 Unit: AngleMeasurementUnit,
179 Number: ArithmeticOps,
180 {
181 type Output = Measure<Unit, Number>;
182
183 fn sub(self, other: UnsignedDirection<Unit, Number>) -> Self::Output {
185 let diff = self.value - other.value;
186 let cycle = Number::from_f64(Unit::CYCLE_FRACTION);
187 let half_cycle = cycle * Number::HALF;
188 Self::Output::new(if diff > half_cycle {
189 diff - cycle
190 } else if diff < -half_cycle {
191 diff + cycle
192 } else {
193 diff
194 })
195 }
196 }
197
198 impl<Unit, Number> Trigonometry for UnsignedDirection<Unit, Number>
199 where
200 Unit: AngleMeasurementUnit,
201 Number: ArithmeticOps,
202 {
203 type Output = Number;
204
205 fn cos(self) -> Self::Output {
207 self.convert::<Radian>().value.cos()
208 }
209
210 fn sin(self) -> Self::Output {
212 self.convert::<Radian>().value.sin()
213 }
214
215 fn tan(self) -> Self::Output {
217 self.convert::<Radian>().value.tan()
218 }
219
220 fn sin_cos(self) -> (Self::Output, Self::Output) {
222 self.convert::<Radian>().value.sin_cos()
223 }
224 }
225
226 impl<Unit, Number> PartialEq<UnsignedDirection<Unit, Number>> for UnsignedDirection<Unit, Number>
227 where
228 Unit: AngleMeasurementUnit,
229 Number: ArithmeticOps,
230 {
231 fn eq(&self, other: &UnsignedDirection<Unit, Number>) -> bool {
233 self.value == other.value
234 }
235 }
236
237 impl<Unit, Number> PartialOrd<UnsignedDirection<Unit, Number>> for UnsignedDirection<Unit, Number>
238 where
239 Unit: AngleMeasurementUnit,
240 Number: ArithmeticOps,
241 {
242 fn partial_cmp(&self, other: &UnsignedDirection<Unit, Number>) -> Option<core::cmp::Ordering> {
244 self.value.partial_cmp(&other.value)
245 }
246 }
247
248 impl<Unit, Number> Clone for UnsignedDirection<Unit, Number>
249 where
250 Unit: AngleMeasurementUnit,
251 Number: ArithmeticOps,
252 {
253 fn clone(&self) -> Self {
255 *self
256 }
257 }
258
259 impl<Unit, Number> Copy for UnsignedDirection<Unit, Number>
261 where
262 Unit: AngleMeasurementUnit,
263 Number: ArithmeticOps,
264 {
265 }
266
267 impl<Unit, Number> fmt::Display for UnsignedDirection<Unit, Number>
268 where
269 Unit: AngleMeasurementUnit,
270 Number: ArithmeticOps,
271 {
272 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
275 formatter.write_str("at ")?;
276 fmt::Display::fmt(&self.value, formatter)?;
277 formatter.write_str(Unit::SUFFIX)?;
278 formatter.write_str(" (in 0°..360°)")
279 }
280 }
281
282 impl<Unit, Number> fmt::Debug for UnsignedDirection<Unit, Number>
283 where
284 Unit: AngleMeasurementUnit,
285 Number: ArithmeticOps,
286 {
287 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
289 formatter.write_str("at ")?;
290 fmt::Display::fmt(&self.value, formatter)?;
291 formatter.write_str(Unit::SUFFIX)?;
292 formatter.write_str(" (in 0°..360°)")
293 }
294 }
295 };
296}