1use std::ops::Add;
9use std::ops::Mul;
10use std::ops::Sub;
11
12const BW_TO_METERS: f32 = 30.0;
14
15const BW_TO_SHIP: f32 = 15.0;
19
20#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
22#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
23#[cfg_attr(feature = "rkyv", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
24pub struct Meters(f32);
25
26#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
28#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
29#[cfg_attr(feature = "rkyv", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
30pub struct BigWorldDistance(f32);
31
32#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
37#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
38#[cfg_attr(feature = "rkyv", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
39pub struct ShipModelDistance(f32);
40
41#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
43#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
44#[cfg_attr(feature = "rkyv", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
45pub struct Km(f32);
46
47#[derive(Clone, Copy, Debug, Default, PartialEq, PartialOrd)]
49#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
50#[cfg_attr(feature = "rkyv", derive(rkyv::Archive, rkyv::Serialize, rkyv::Deserialize))]
51pub struct Millimeters(f32);
52
53impl From<f32> for Meters {
54 fn from(v: f32) -> Self {
55 Self(v)
56 }
57}
58impl From<i32> for Meters {
59 fn from(v: i32) -> Self {
60 Self(v as f32)
61 }
62}
63
64impl From<f32> for BigWorldDistance {
65 fn from(v: f32) -> Self {
66 Self(v)
67 }
68}
69impl From<i32> for BigWorldDistance {
70 fn from(v: i32) -> Self {
71 Self(v as f32)
72 }
73}
74
75impl From<f32> for Km {
76 fn from(v: f32) -> Self {
77 Self(v)
78 }
79}
80impl From<i32> for Km {
81 fn from(v: i32) -> Self {
82 Self(v as f32)
83 }
84}
85
86impl From<f32> for Millimeters {
87 fn from(v: f32) -> Self {
88 Self(v)
89 }
90}
91impl From<i32> for Millimeters {
92 fn from(v: i32) -> Self {
93 Self(v as f32)
94 }
95}
96
97impl Meters {
98 pub const fn new(v: f32) -> Self {
100 Self(v)
101 }
102
103 pub fn value(self) -> f32 {
104 self.0
105 }
106 pub fn to_bigworld(self) -> BigWorldDistance {
107 BigWorldDistance(self.0 / BW_TO_METERS)
108 }
109 pub fn to_ship_model(self) -> ShipModelDistance {
113 ShipModelDistance(self.0 * BW_TO_SHIP / BW_TO_METERS)
114 }
115 pub fn to_km(self) -> Km {
116 Km(self.0 / 1000.0)
117 }
118 pub fn to_mm(self) -> Millimeters {
119 Millimeters(self.0 * 1000.0)
120 }
121}
122
123impl BigWorldDistance {
124 pub fn value(self) -> f32 {
125 self.0
126 }
127 pub fn to_meters(self) -> Meters {
128 Meters(self.0 * BW_TO_METERS)
129 }
130 pub fn to_km(self) -> Km {
131 self.to_meters().to_km()
132 }
133}
134
135impl ShipModelDistance {
136 pub fn value(self) -> f32 {
137 self.0
138 }
139 pub fn to_meters(self) -> Meters {
140 Meters(self.0 * BW_TO_METERS / BW_TO_SHIP)
141 }
142 pub fn to_bigworld(self) -> BigWorldDistance {
143 BigWorldDistance(self.0 / BW_TO_SHIP)
144 }
145}
146
147impl Km {
148 pub const fn new(v: f32) -> Self {
150 Self(v)
151 }
152
153 pub fn value(self) -> f32 {
154 self.0
155 }
156 pub fn to_meters(self) -> Meters {
157 Meters(self.0 * 1000.0)
158 }
159 pub fn to_bigworld(self) -> BigWorldDistance {
160 self.to_meters().to_bigworld()
161 }
162}
163
164impl Millimeters {
165 pub const fn new(v: f32) -> Self {
167 Self(v)
168 }
169
170 pub fn value(self) -> f32 {
171 self.0
172 }
173 pub fn to_meters(self) -> Meters {
174 Meters(self.0 / 1000.0)
175 }
176 pub fn to_bigworld(self) -> BigWorldDistance {
177 self.to_meters().to_bigworld()
178 }
179}
180
181impl Mul<f32> for Meters {
182 type Output = Meters;
183 fn mul(self, rhs: f32) -> Meters {
184 Meters(self.0 * rhs)
185 }
186}
187
188impl Mul<f32> for BigWorldDistance {
189 type Output = BigWorldDistance;
190 fn mul(self, rhs: f32) -> BigWorldDistance {
191 BigWorldDistance(self.0 * rhs)
192 }
193}
194
195impl Mul<f32> for Km {
196 type Output = Km;
197 fn mul(self, rhs: f32) -> Km {
198 Km(self.0 * rhs)
199 }
200}
201
202impl Mul<f32> for Millimeters {
203 type Output = Millimeters;
204 fn mul(self, rhs: f32) -> Millimeters {
205 Millimeters(self.0 * rhs)
206 }
207}
208
209impl Add for Meters {
210 type Output = Meters;
211 fn add(self, rhs: Meters) -> Meters {
212 Meters(self.0 + rhs.0)
213 }
214}
215impl Sub for Meters {
216 type Output = Meters;
217 fn sub(self, rhs: Meters) -> Meters {
218 Meters(self.0 - rhs.0)
219 }
220}
221
222impl Add for BigWorldDistance {
223 type Output = BigWorldDistance;
224 fn add(self, rhs: BigWorldDistance) -> BigWorldDistance {
225 BigWorldDistance(self.0 + rhs.0)
226 }
227}
228impl Sub for BigWorldDistance {
229 type Output = BigWorldDistance;
230 fn sub(self, rhs: BigWorldDistance) -> BigWorldDistance {
231 BigWorldDistance(self.0 - rhs.0)
232 }
233}
234
235impl Add for Km {
236 type Output = Km;
237 fn add(self, rhs: Km) -> Km {
238 Km(self.0 + rhs.0)
239 }
240}
241impl Sub for Km {
242 type Output = Km;
243 fn sub(self, rhs: Km) -> Km {
244 Km(self.0 - rhs.0)
245 }
246}
247
248impl Add for Millimeters {
249 type Output = Millimeters;
250 fn add(self, rhs: Millimeters) -> Millimeters {
251 Millimeters(self.0 + rhs.0)
252 }
253}
254impl Sub for Millimeters {
255 type Output = Millimeters;
256 fn sub(self, rhs: Millimeters) -> Millimeters {
257 Millimeters(self.0 - rhs.0)
258 }
259}
260
261impl Add<BigWorldDistance> for Meters {
262 type Output = Meters;
263 fn add(self, rhs: BigWorldDistance) -> Meters {
264 Meters(self.0 + rhs.to_meters().0)
265 }
266}
267impl Sub<BigWorldDistance> for Meters {
268 type Output = Meters;
269 fn sub(self, rhs: BigWorldDistance) -> Meters {
270 Meters(self.0 - rhs.to_meters().0)
271 }
272}
273
274impl Add<Meters> for BigWorldDistance {
275 type Output = BigWorldDistance;
276 fn add(self, rhs: Meters) -> BigWorldDistance {
277 BigWorldDistance(self.0 + rhs.to_bigworld().0)
278 }
279}
280impl Sub<Meters> for BigWorldDistance {
281 type Output = BigWorldDistance;
282 fn sub(self, rhs: Meters) -> BigWorldDistance {
283 BigWorldDistance(self.0 - rhs.to_bigworld().0)
284 }
285}
286
287impl Add<Km> for Meters {
288 type Output = Meters;
289 fn add(self, rhs: Km) -> Meters {
290 Meters(self.0 + rhs.to_meters().0)
291 }
292}
293impl Sub<Km> for Meters {
294 type Output = Meters;
295 fn sub(self, rhs: Km) -> Meters {
296 Meters(self.0 - rhs.to_meters().0)
297 }
298}
299
300impl Add<Meters> for Km {
301 type Output = Km;
302 fn add(self, rhs: Meters) -> Km {
303 Km(self.0 + rhs.to_km().0)
304 }
305}
306impl Sub<Meters> for Km {
307 type Output = Km;
308 fn sub(self, rhs: Meters) -> Km {
309 Km(self.0 - rhs.to_km().0)
310 }
311}
312
313impl std::ops::Div<f32> for Meters {
314 type Output = Meters;
315 fn div(self, rhs: f32) -> Meters {
316 Meters(self.0 / rhs)
317 }
318}
319
320impl std::ops::Div<f32> for BigWorldDistance {
321 type Output = BigWorldDistance;
322 fn div(self, rhs: f32) -> BigWorldDistance {
323 BigWorldDistance(self.0 / rhs)
324 }
325}
326
327impl std::ops::Div<f32> for Km {
328 type Output = Km;
329 fn div(self, rhs: f32) -> Km {
330 Km(self.0 / rhs)
331 }
332}
333
334impl std::ops::Div<f32> for Millimeters {
335 type Output = Millimeters;
336 fn div(self, rhs: f32) -> Millimeters {
337 Millimeters(self.0 / rhs)
338 }
339}
340
341impl std::iter::Sum for Meters {
342 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
343 Meters(iter.map(|m| m.0).sum())
344 }
345}
346
347impl std::iter::Sum for BigWorldDistance {
348 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
349 BigWorldDistance(iter.map(|d| d.0).sum())
350 }
351}
352
353impl std::iter::Sum for Km {
354 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
355 Km(iter.map(|k| k.0).sum())
356 }
357}
358
359impl std::iter::Sum for Millimeters {
360 fn sum<I: Iterator<Item = Self>>(iter: I) -> Self {
361 Millimeters(iter.map(|m| m.0).sum())
362 }
363}
364
365impl PartialEq<BigWorldDistance> for Meters {
366 fn eq(&self, other: &BigWorldDistance) -> bool {
367 self.0 == other.to_meters().0
368 }
369}
370impl PartialOrd<BigWorldDistance> for Meters {
371 fn partial_cmp(&self, other: &BigWorldDistance) -> Option<std::cmp::Ordering> {
372 self.0.partial_cmp(&other.to_meters().0)
373 }
374}
375
376impl PartialEq<Meters> for BigWorldDistance {
377 fn eq(&self, other: &Meters) -> bool {
378 self.0 == other.to_bigworld().0
379 }
380}
381impl PartialOrd<Meters> for BigWorldDistance {
382 fn partial_cmp(&self, other: &Meters) -> Option<std::cmp::Ordering> {
383 self.0.partial_cmp(&other.to_bigworld().0)
384 }
385}