s2json_core/
vector_point.rs

1use core::{
2    cmp::Ordering,
3    f64::consts::PI,
4    fmt::Debug,
5    ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Rem, RemAssign, Sub, SubAssign},
6};
7use libm::{atan, atan2, fabs, fmod, log, sin, sinh, sqrt};
8use serde::{Deserialize, Serialize};
9
10/// Importing necessary types (equivalent to importing from 'values')
11use crate::*;
12
13/// A Vector Point uses a structure for 2D or 3D points
14#[derive(Serialize, Deserialize, Debug, Clone, Default)]
15#[repr(C)]
16pub struct VectorPoint<M: Clone = MValue> {
17    /// X coordinate
18    pub x: f64,
19    /// Y coordinate
20    pub y: f64,
21    /// Z coordinate or "altitude". May be None
22    pub z: Option<f64>,
23    /// M-Value
24    #[serde(skip_serializing_if = "Option::is_none")]
25    pub m: Option<M>,
26    /// T for tolerance. A tmp value used for simplification
27    #[serde(skip)]
28    pub t: Option<f64>,
29}
30impl VectorPoint<MValue> {
31    /// Helper function for tests. Create a new point quickly from an xy coordinate
32    pub fn from_xy(x: f64, y: f64) -> Self {
33        Self { x, y, z: None, m: None, t: None }
34    }
35
36    /// Helper function for tests. Create a new point quickly from an xyz coordinate
37    pub fn from_xyz(x: f64, y: f64, z: f64) -> Self {
38        Self { x, y, z: Some(z), m: None, t: None }
39    }
40}
41impl<M: Clone> VectorPoint<M> {
42    /// Create a new point
43    pub fn new(x: f64, y: f64, z: Option<f64>, m: Option<M>) -> Self {
44        Self { x, y, z, m, t: None }
45    }
46
47    /// Create a new point with xy
48    pub fn new_xy(x: f64, y: f64, m: Option<M>) -> Self {
49        Self { x, y, z: None, m, t: None }
50    }
51
52    /// Create a new point with xyz
53    pub fn new_xyz(x: f64, y: f64, z: f64, m: Option<M>) -> Self {
54        Self { x, y, z: Some(z), m, t: None }
55    }
56
57    /// Project the point into the 0->1 coordinate system
58    pub fn project(&mut self, bbox: Option<&mut BBox3D>) {
59        let y = self.y;
60        let x = self.x;
61        let sin = sin((y * PI) / 180.);
62        let y2 = 0.5 - (0.25 * log((1. + sin) / (1. - sin))) / PI;
63        self.x = x / 360. + 0.5;
64        self.y = y2.clamp(0., 1.);
65
66        if let Some(bbox) = bbox {
67            bbox.extend_from_point(self)
68        };
69    }
70
71    /// Unproject the point from the 0->1 coordinate system back to a lon-lat coordinate
72    pub fn unproject(&mut self) {
73        let lon = (self.x - 0.5) * 360.;
74        let y2 = 0.5 - self.y;
75        let lat = atan(sinh(PI * (y2 * 2.))).to_degrees();
76
77        self.x = lon;
78        self.y = lat;
79    }
80
81    /// Returns true if the point is the zero vector.
82    pub fn is_empty(&self) -> bool {
83        let zero = f64::default();
84        self.x == zero && self.y == zero && (self.z.is_none() || self.z.unwrap() == zero)
85    }
86
87    /// Returns the S2 face assocated with this point
88    pub fn face(&self, f: u8) -> f64 {
89        if f == 0 {
90            self.x
91        } else if f == 1 {
92            self.y
93        } else {
94            self.z.unwrap_or(0.)
95        }
96    }
97
98    /// Apply modular arithmetic to x, y, and z using `modulus`
99    pub fn modulo(self, modulus: f64) -> Self {
100        let modulus = fabs(modulus); // Ensure positive modulus
101        Self {
102            x: fmod(self.x, modulus),
103            y: fmod(self.y, modulus),
104            z: self.z.map(|z| fmod(z, modulus)),
105            m: self.m,
106            t: None,
107        }
108    }
109
110    /// Returns the angle between "this" and v in radians, in the range [0, pi]. If
111    /// either vector is zero-length, or nearly zero-length, the result will be
112    /// zero, regardless of the other value.
113    pub fn angle<M2: Clone>(&self, b: &VectorPoint<M2>) -> f64 {
114        atan2(self.cross(b).norm(), self.dot(b))
115    }
116
117    /// Get the cross product of two Vector Points
118    pub fn cross<M2: Clone>(&self, b: &VectorPoint<M2>) -> Self {
119        if let (Some(z), Some(bz)) = (self.z, b.z) {
120            Self::new_xyz(
121                self.y * bz - z * b.y,
122                z * b.x - self.x * bz,
123                self.x * b.y - self.y * b.x,
124                None,
125            )
126        } else {
127            Self::new_xy(self.x * b.y - self.y * b.x, self.y * b.x - self.x * b.y, None)
128        }
129    }
130
131    /// dot returns the standard dot product of v and ov.
132    pub fn dot<M2: Clone>(&self, b: &VectorPoint<M2>) -> f64 {
133        if let (Some(z), Some(bz)) = (self.z, b.z) {
134            self.x * b.x + self.y * b.y + z * bz
135        } else {
136            self.x * b.x + self.y * b.y
137        }
138    }
139
140    /// Returns the absolute value of the point.
141    pub fn abs(&self) -> Self {
142        Self::new(fabs(self.x), fabs(self.y), self.z.map(fabs), None)
143    }
144
145    /// Returns the inverse of the point
146    pub fn invert(&self) -> Self {
147        -self
148    }
149
150    /// Returns the length of the point.
151    pub fn len(&self) -> f64 {
152        self.norm()
153    }
154
155    /// norm returns the vector's norm.
156    pub fn norm(&self) -> f64 {
157        sqrt(self.norm2())
158    }
159
160    /// norm2 returns the vector's squared norm.
161    pub fn norm2(&self) -> f64 {
162        self.dot(self)
163    }
164
165    /// Normalize this point to unit length.
166    pub fn normalize(&mut self) {
167        let len = self.len();
168        if len > 0.0 {
169            self.x /= len;
170            self.y /= len;
171            if let Some(z) = self.z {
172                self.z = Some(z / len);
173            }
174        }
175    }
176
177    /// return the distance from this point to the other point in radians
178    pub fn distance<M2: Clone>(&self, b: &VectorPoint<M2>) -> f64 {
179        let d: VectorPoint<M> = self - b;
180        d.len()
181    }
182
183    /// Returns the largest absolute component of the point.
184    pub fn largest_abs_component(&self) -> u8 {
185        let tmp = self.abs();
186        let tmp_z = tmp.z.unwrap_or(-2.);
187        if tmp.x > tmp.y {
188            if tmp.x > tmp_z {
189                0
190            } else {
191                2
192            }
193        } else if tmp.y > tmp_z {
194            1
195        } else {
196            2
197        }
198    }
199
200    /// Returns the intermediate point between this and the other point.
201    pub fn intermediate<M2: Clone>(&self, b: &VectorPoint<M2>, t: f64) -> Self {
202        if let (Some(z), Some(bz)) = (self.z, b.z) {
203            Self::new_xyz(
204                self.x + ((b.x - self.x) * (1.0 - t)),
205                self.y + ((b.y - self.y) * (1.0 - t)),
206                z + ((bz - z) * (1.0 - t)),
207                None,
208            )
209        } else {
210            Self::new_xy(
211                self.x + ((b.x - self.x) * (1.0 - t)),
212                self.y + ((b.y - self.y) * (1.0 - t)),
213                None,
214            )
215        }
216    }
217
218    /// Returns the perpendicular vector
219    pub fn perpendicular(&self) -> Self {
220        if let Some(z) = self.z {
221            let ref_point = if fabs(self.x) > fabs(z) {
222                Self::new_xyz(0., 0., 1., None)
223            } else {
224                Self::new_xyz(1., 0., 0., None)
225            };
226            let cross = self.cross(&ref_point);
227            Self::new_xyz(-self.y, self.x, cross.z.unwrap(), None)
228        } else {
229            Self::new_xy(-self.y, self.x, None)
230        }
231    }
232}
233impl<M: Clone> From<Point> for VectorPoint<M> {
234    fn from(p: Point) -> Self {
235        Self { x: p.0, y: p.1, z: None, m: None, t: None }
236    }
237}
238impl<M: Clone> From<&Point> for VectorPoint<M> {
239    fn from(p: &Point) -> Self {
240        Self { x: p.0, y: p.1, z: None, m: None, t: None }
241    }
242}
243impl<M: Clone> From<Point3D> for VectorPoint<M> {
244    fn from(p: Point3D) -> Self {
245        Self { x: p.0, y: p.1, z: Some(p.2), m: None, t: None }
246    }
247}
248impl<M: Clone> From<&Point3D> for VectorPoint<M> {
249    fn from(p: &Point3D) -> Self {
250        Self { x: p.0, y: p.1, z: Some(p.2), m: None, t: None }
251    }
252}
253impl<M1: Clone, M2: Clone> Add<&VectorPoint<M2>> for &VectorPoint<M1> {
254    type Output = VectorPoint<M1>;
255    fn add(self, other: &VectorPoint<M2>) -> Self::Output {
256        VectorPoint {
257            x: self.x + other.x,
258            y: self.y + other.y,
259            // Only add `z` if both `self.z` and `other.z` are `Some`
260            z: match (self.z, other.z) {
261                (Some(z1), Some(z2)) => Some(z1 + z2),
262                _ => None, // If either `z` is None, the result is `None`
263            },
264            m: None, // Combine m values
265            t: None, // Handle `t` as necessary
266        }
267    }
268}
269impl<M1: Clone, M2: Clone> AddAssign<&VectorPoint<M2>> for VectorPoint<M1> {
270    fn add_assign(&mut self, other: &VectorPoint<M2>) {
271        self.x += other.x;
272        self.y += other.y;
273        if let (Some(z), Some(other_z)) = (self.z, other.z) {
274            self.z = Some(z + other_z);
275        }
276    }
277}
278impl<M: Clone> Add<f64> for &VectorPoint<M> {
279    type Output = VectorPoint<M>;
280    fn add(self, other: f64) -> Self::Output {
281        VectorPoint {
282            x: self.x + other,
283            y: self.y + other,
284            z: self.z.map(|z| z + other),
285            m: None,
286            t: None,
287        }
288    }
289}
290impl<M: Clone> AddAssign<f64> for VectorPoint<M> {
291    fn add_assign(&mut self, other: f64) {
292        self.x += other;
293        self.y += other;
294        if let Some(z) = self.z {
295            self.z = Some(z + other);
296        }
297    }
298}
299// Implementing the Sub trait for VectorPoint
300impl<M1: Clone, M2: Clone> Sub<&VectorPoint<M2>> for &VectorPoint<M1> {
301    type Output = VectorPoint<M1>;
302    fn sub(self, other: &VectorPoint<M2>) -> Self::Output {
303        VectorPoint {
304            x: self.x - other.x,
305            y: self.y - other.y,
306            z: match (self.z, other.z) {
307                (Some(z1), Some(z2)) => Some(z1 - z2),
308                _ => None, // If either `z` is None, the result is `None`
309            },
310            m: None, // Combine m values
311            t: None, // Handle `t` as necessary
312        }
313    }
314}
315impl<M1: Clone, M2: Clone> SubAssign<&VectorPoint<M2>> for VectorPoint<M1> {
316    fn sub_assign(&mut self, other: &VectorPoint<M2>) {
317        self.x -= other.x;
318        self.y -= other.y;
319        if let (Some(z), Some(other_z)) = (self.z, other.z) {
320            self.z = Some(z - other_z);
321        }
322    }
323}
324impl<M: Clone> Sub<f64> for &VectorPoint<M> {
325    type Output = VectorPoint<M>;
326    fn sub(self, other: f64) -> Self::Output {
327        VectorPoint {
328            x: self.x - other,
329            y: self.y - other,
330            z: self.z.map(|z| z - other),
331            m: None,
332            t: None,
333        }
334    }
335}
336impl<M: Clone> SubAssign<f64> for VectorPoint<M> {
337    fn sub_assign(&mut self, other: f64) {
338        self.x -= other;
339        self.y -= other;
340        if let Some(z) = self.z {
341            self.z = Some(z - other);
342        }
343    }
344}
345// Implementing the Neg trait for VectorPoint
346impl<M: Clone> Neg for &VectorPoint<M> {
347    type Output = VectorPoint<M>;
348    fn neg(self) -> Self::Output {
349        VectorPoint { x: -self.x, y: -self.y, z: self.z.map(|z| -z), m: None, t: None }
350    }
351}
352// Implementing the Div trait for VectorPoint
353impl<M1: Clone, M2: Clone> Div<&VectorPoint<M2>> for &VectorPoint<M1> {
354    type Output = VectorPoint<M1>;
355    fn div(self, other: &VectorPoint<M2>) -> Self::Output {
356        VectorPoint {
357            x: self.x / other.x,
358            y: self.y / other.y,
359            z: match (self.z, other.z) {
360                (Some(z1), Some(z2)) => Some(z1 / z2),
361                _ => None, // If either `z` is None, the result is `None`
362            },
363            m: None, // Combine m values
364            t: None, // Handle `t` as necessary
365        }
366    }
367}
368impl<M1: Clone, M2: Clone> DivAssign<&VectorPoint<M2>> for VectorPoint<M1> {
369    fn div_assign(&mut self, other: &VectorPoint<M2>) {
370        self.x /= other.x;
371        self.y /= other.y;
372        if let (Some(z), Some(other_z)) = (self.z, other.z) {
373            self.z = Some(z / other_z);
374        }
375    }
376}
377impl<M: Clone> Div<f64> for &VectorPoint<M> {
378    type Output = VectorPoint<M>;
379    fn div(self, other: f64) -> Self::Output {
380        VectorPoint {
381            x: self.x / other,
382            y: self.y / other,
383            z: self.z.map(|z| z / other),
384            m: None,
385            t: None,
386        }
387    }
388}
389impl<M: Clone> DivAssign<f64> for VectorPoint<M> {
390    fn div_assign(&mut self, other: f64) {
391        self.x /= other;
392        self.y /= other;
393        if let Some(z) = self.z {
394            self.z = Some(z / other);
395        }
396    }
397}
398// Implementing the Mul trait for VectorPoint
399impl<M1: Clone, M2: Clone> Mul<&VectorPoint<M2>> for &VectorPoint<M1> {
400    type Output = VectorPoint<M1>;
401    fn mul(self, other: &VectorPoint<M2>) -> Self::Output {
402        VectorPoint {
403            x: self.x * other.x,
404            y: self.y * other.y,
405            z: match (self.z, other.z) {
406                (Some(z1), Some(z2)) => Some(z1 * z2),
407                _ => None, // If either `z` is None, the result is `None`
408            },
409            m: None, // Combine m values
410            t: None, // Handle `t` as necessary
411        }
412    }
413}
414impl<M1: Clone, M2: Clone> MulAssign<&VectorPoint<M2>> for VectorPoint<M1> {
415    fn mul_assign(&mut self, other: &VectorPoint<M2>) {
416        self.x *= other.x;
417        self.y *= other.y;
418        if let (Some(z), Some(other_z)) = (self.z, other.z) {
419            self.z = Some(z * other_z);
420        }
421    }
422}
423impl<M: Clone> Mul<f64> for &VectorPoint<M> {
424    type Output = VectorPoint<M>;
425    fn mul(self, other: f64) -> Self::Output {
426        VectorPoint {
427            x: self.x * other,
428            y: self.y * other,
429            z: self.z.map(|z| z * other),
430            m: None,
431            t: None,
432        }
433    }
434}
435impl<M: Clone> MulAssign<f64> for VectorPoint<M> {
436    fn mul_assign(&mut self, other: f64) {
437        self.x *= other;
438        self.y *= other;
439        if let Some(z) = self.z {
440            self.z = Some(z * other);
441        }
442    }
443}
444impl<M: Clone> Rem<f64> for VectorPoint<M> {
445    type Output = VectorPoint<M>;
446
447    fn rem(self, modulus: f64) -> Self::Output {
448        self.modulo(modulus)
449    }
450}
451impl<M: Clone> RemAssign<f64> for VectorPoint<M> {
452    fn rem_assign(&mut self, modulus: f64) {
453        let modulus = fabs(modulus);
454        self.x = fmod(self.x, modulus);
455        self.y = fmod(self.y, modulus);
456        if let Some(z) = self.z {
457            self.z = Some(fmod(z, modulus));
458        }
459    }
460}
461impl<M: Clone> Eq for VectorPoint<M> {}
462impl<M: Clone> Ord for VectorPoint<M> {
463    fn cmp(&self, other: &VectorPoint<M>) -> Ordering {
464        match self.x.partial_cmp(&other.x) {
465            Some(Ordering::Equal) => {}
466            other => return other.unwrap_or(Ordering::Greater), /* Handle cases where `x` comparison is not equal */
467        }
468        match self.y.partial_cmp(&other.y) {
469            Some(Ordering::Equal) => {}
470            other => return other.unwrap_or(Ordering::Greater), /* Handle cases where `y` comparison is not equal */
471        }
472        match self.z.partial_cmp(&other.z) {
473            Some(order) => order,
474            None => Ordering::Equal, // This handles the NaN case safely
475        }
476    }
477}
478impl<M: Clone> PartialEq for VectorPoint<M> {
479    fn eq(&self, other: &VectorPoint<M>) -> bool {
480        self.x == other.x && self.y == other.y && self.z == other.z
481    }
482}
483impl<M: Clone> PartialOrd for VectorPoint<M> {
484    fn partial_cmp(&self, other: &VectorPoint<M>) -> Option<Ordering> {
485        Some(self.cmp(other))
486    }
487}
488
489#[cfg(test)]
490mod tests {
491    use super::*;
492
493    #[test]
494    fn size() {
495        assert_eq!(size_of::<VectorPoint<()>>(), 56);
496        assert_eq!(size_of::<VectorPoint<MValue>>(), 80);
497    }
498
499    #[test]
500    fn new() {
501        let vector_point: VectorPoint = VectorPoint::new(1.0, 2.0, None, None);
502        assert_eq!(vector_point.x, 1.0);
503        assert_eq!(vector_point.y, 2.0);
504        assert_eq!(vector_point.z, None);
505        assert_eq!(vector_point.m, None);
506        assert_eq!(vector_point.t, None);
507    }
508
509    #[test]
510    fn new_xy() {
511        let vector_point: VectorPoint = VectorPoint::new_xy(1.0, 2.0, None);
512        assert_eq!(vector_point.x, 1.0);
513        assert_eq!(vector_point.y, 2.0);
514        assert_eq!(vector_point.z, None);
515        assert_eq!(vector_point.m, None);
516        assert_eq!(vector_point.t, None);
517    }
518
519    #[test]
520    fn new_xyz() {
521        let vector_point: VectorPoint = VectorPoint::new_xyz(1.0, 2.0, 3.0, None);
522        assert_eq!(vector_point.x, 1.0);
523        assert_eq!(vector_point.y, 2.0);
524        assert_eq!(vector_point.z, Some(3.0));
525        assert_eq!(vector_point.m, None);
526        assert_eq!(vector_point.t, None);
527    }
528
529    #[test]
530    fn from_xy() {
531        let vector_point: VectorPoint = VectorPoint::from_xy(1.0, 2.0);
532        assert_eq!(vector_point.x, 1.0);
533        assert_eq!(vector_point.y, 2.0);
534        assert_eq!(vector_point.z, None);
535        assert_eq!(vector_point.m, None);
536        assert_eq!(vector_point.t, None);
537    }
538
539    #[test]
540    fn from_xyz() {
541        let vector_point: VectorPoint = VectorPoint::from_xyz(1.0, 2.0, 3.0);
542        assert_eq!(vector_point.x, 1.0);
543        assert_eq!(vector_point.y, 2.0);
544        assert_eq!(vector_point.z, Some(3.0));
545        assert_eq!(vector_point.m, None);
546        assert_eq!(vector_point.t, None);
547    }
548
549    #[test]
550    fn project() {
551        let mut vector_point: VectorPoint = VectorPoint::new(1.0, 2.0, Some(-3.), None);
552        let mut bbox: BBox3D = BBox3D::new(1., 1., 0., 0., 0., 1.);
553        vector_point.project(Some(&mut bbox));
554        assert_eq!(vector_point.x, 0.5027777777777778);
555        assert_eq!(vector_point.y, 0.4944433158879836);
556        assert_eq!(vector_point.z, Some(-3.));
557        assert_eq!(vector_point.m, None);
558        assert_eq!(vector_point.t, None);
559
560        assert_eq!(bbox.left, 0.5027777777777778);
561        assert_eq!(bbox.bottom, 0.4944433158879836);
562        assert_eq!(bbox.right, 0.5027777777777778);
563        assert_eq!(bbox.top, 0.4944433158879836);
564        assert_eq!(bbox.near, -3.);
565        assert_eq!(bbox.far, 1.0);
566    }
567
568    #[test]
569    fn project_no_bbox() {
570        let mut vector_point: VectorPoint = VectorPoint::new(1.0, 2.0, Some(-3.), None);
571        vector_point.project(None);
572        assert_eq!(vector_point.x, 0.5027777777777778);
573        assert_eq!(vector_point.y, 0.4944433158879836);
574        assert_eq!(vector_point.z, Some(-3.));
575        assert_eq!(vector_point.m, None);
576        assert_eq!(vector_point.t, None);
577    }
578
579    #[test]
580    fn unproject() {
581        let mut vector_point: VectorPoint =
582            VectorPoint::new(0.5027777777777778, 0.4944433158879836, Some(-3.), None);
583        vector_point.unproject();
584
585        assert_eq!(vector_point.x, 0.9999999999999964);
586        assert_eq!(vector_point.y, 2.0000000000000093);
587        assert_eq!(vector_point.z, Some(-3.));
588        assert_eq!(vector_point.m, None);
589        assert_eq!(vector_point.t, None);
590    }
591
592    #[test]
593    fn test_distance() {
594        let vector_point: VectorPoint = VectorPoint::new(1.0, 2.0, None, None);
595        let other: VectorPoint = VectorPoint::new(3.0, 4.0, None, None);
596        assert_eq!(vector_point.distance(&other), 2.8284271247461903);
597    }
598
599    #[test]
600    fn from_point() {
601        let point = Point(1.0, 2.0);
602        let vector_point: VectorPoint = point.into();
603        assert_eq!(vector_point.x, 1.0);
604        assert_eq!(vector_point.y, 2.0);
605        assert_eq!(vector_point.z, None);
606        assert_eq!(vector_point.m, None);
607        assert_eq!(vector_point.t, None);
608
609        let point = Point(1.0, 2.0);
610        let vector_point: VectorPoint = (&point).into();
611        assert_eq!(vector_point.x, 1.0);
612        assert_eq!(vector_point.y, 2.0);
613        assert_eq!(vector_point.z, None);
614        assert_eq!(vector_point.m, None);
615        assert_eq!(vector_point.t, None);
616    }
617
618    #[test]
619    fn from_point_3d() {
620        let point: Point3D = Point3D(1.0, 2.0, 3.0);
621        let vector_point: VectorPoint = point.into();
622        assert_eq!(vector_point.x, 1.0);
623        assert_eq!(vector_point.y, 2.0);
624        assert_eq!(vector_point.z, Some(3.0));
625        assert_eq!(vector_point.m, None);
626        assert_eq!(vector_point.t, None);
627
628        let point: Point3D = Point3D(1.0, 2.0, 3.0);
629        let vector_point: VectorPoint = (&point).into();
630        assert_eq!(vector_point.x, 1.0);
631        assert_eq!(vector_point.y, 2.0);
632        assert_eq!(vector_point.z, Some(3.0));
633        assert_eq!(vector_point.m, None);
634        assert_eq!(vector_point.t, None);
635    }
636
637    #[test]
638    fn vector_point() {
639        let vector_point: VectorPoint =
640            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
641        assert_eq!(vector_point.x, 1.0);
642        assert_eq!(vector_point.y, 2.0);
643        assert_eq!(vector_point.z, Some(3.0));
644        assert_eq!(vector_point.m, None);
645        assert_eq!(vector_point.t, None);
646    }
647
648    #[test]
649    fn vector_neg() {
650        let vector_point = VectorPoint::<MValue> { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
651        let result = -&vector_point;
652        assert_eq!(result.x, -1.0);
653        assert_eq!(result.y, -2.0);
654        assert_eq!(result.z, Some(-3.0));
655        assert_eq!(result.m, None);
656        assert_eq!(result.t, None);
657    }
658
659    #[test]
660    fn vector_point_add() {
661        let vector_point1: VectorPoint =
662            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
663        let vector_point2: VectorPoint =
664            VectorPoint { x: 4.0, y: 5.0, z: Some(6.0), m: None, t: Some(5.2) };
665        let result = &vector_point1 + &vector_point2;
666        assert_eq!(result.x, 5.0);
667        assert_eq!(result.y, 7.0);
668        assert_eq!(result.z, Some(9.0));
669        assert_eq!(result.m, None);
670        assert_eq!(result.t, None);
671
672        let vector_point1 = VectorPoint::from_xy(1., 2.);
673        let vector_point2 = VectorPoint::from_xy(4., 5.);
674        let result = &vector_point1 + &vector_point2;
675        assert_eq!(result.x, 5.0);
676        assert_eq!(result.y, 7.0);
677        assert_eq!(result.z, None);
678        assert_eq!(result.m, None);
679        assert_eq!(result.t, None);
680
681        // assign
682        let mut vector_point1 = VectorPoint::from_xyz(1., 2., 3.);
683        let vector_point2 = VectorPoint::from_xyz(4., 5., 6.);
684        vector_point1 += &vector_point2;
685        assert_eq!(vector_point1.x, 5.0);
686        assert_eq!(vector_point1.y, 7.0);
687        assert_eq!(vector_point1.z, Some(9.0));
688        assert_eq!(vector_point1.m, None);
689        assert_eq!(vector_point1.t, None);
690    }
691
692    #[test]
693    fn vector_point_add_f64() {
694        let vector_point1: VectorPoint =
695            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
696        let float: f64 = 4.0;
697        let result = &vector_point1 + float;
698        assert_eq!(result.x, 5.0);
699        assert_eq!(result.y, 6.0);
700        assert_eq!(result.z, Some(7.0));
701        assert_eq!(result.m, None);
702        assert_eq!(result.t, None);
703
704        // assign
705        let mut vector_point1: VectorPoint =
706            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
707        let float: f64 = 4.0;
708        vector_point1 += float;
709        assert_eq!(vector_point1.x, 5.0);
710        assert_eq!(vector_point1.y, 6.0);
711        assert_eq!(vector_point1.z, Some(7.0));
712        assert_eq!(vector_point1.m, None);
713        assert_eq!(vector_point1.t, None);
714    }
715
716    #[test]
717    fn vector_point_sub() {
718        let vector_point1 =
719            VectorPoint::<MValue> { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
720        let vector_point2 =
721            VectorPoint::<MValue> { x: 4.0, y: 5.0, z: Some(6.0), m: None, t: Some(5.2) };
722        let result = &vector_point1 - &vector_point2;
723        assert_eq!(result.x, -3.0);
724        assert_eq!(result.y, -3.0);
725        assert_eq!(result.z, Some(-3.0));
726        assert_eq!(result.m, None);
727        assert_eq!(result.t, None);
728
729        let vector_point1 = VectorPoint::from_xy(1., 2.);
730        let vector_point2 = VectorPoint::from_xy(4., 5.);
731        let result = &vector_point1 - &vector_point2;
732        assert_eq!(result.x, -3.0);
733        assert_eq!(result.y, -3.0);
734        assert_eq!(result.z, None);
735        assert_eq!(result.m, None);
736        assert_eq!(result.t, None);
737
738        // assign
739        let mut vector_point1 = VectorPoint::from_xyz(1., 2., 3.);
740        let vector_point2 = VectorPoint::from_xyz(4., 5., 6.);
741        vector_point1 -= &vector_point2;
742        assert_eq!(vector_point1.x, -3.0);
743        assert_eq!(vector_point1.y, -3.0);
744        assert_eq!(vector_point1.z, Some(-3.0));
745        assert_eq!(vector_point1.m, None);
746        assert_eq!(vector_point1.t, None);
747    }
748
749    #[test]
750    fn vector_point_sub_f64() {
751        let vector_point1: VectorPoint =
752            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
753        let float: f64 = 4.0;
754        let result = &vector_point1 - float;
755        assert_eq!(result.x, -3.0);
756        assert_eq!(result.y, -2.0);
757        assert_eq!(result.z, Some(-1.0));
758        assert_eq!(result.m, None);
759        assert_eq!(result.t, None);
760
761        // assign
762        let mut vector_point1: VectorPoint =
763            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
764        let float: f64 = 4.0;
765        vector_point1 -= float;
766        assert_eq!(vector_point1.x, -3.0);
767        assert_eq!(vector_point1.y, -2.0);
768        assert_eq!(vector_point1.z, Some(-1.0));
769        assert_eq!(vector_point1.m, None);
770        assert_eq!(vector_point1.t, None);
771    }
772
773    #[test]
774    fn vector_point_mul() {
775        let vector_point1: VectorPoint =
776            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
777        let vector_point2: VectorPoint =
778            VectorPoint { x: 4.0, y: 5.0, z: Some(6.0), m: None, t: Some(5.2) };
779        let result = &vector_point1 * &vector_point2;
780        assert_eq!(result.x, 4.0);
781        assert_eq!(result.y, 10.0);
782        assert_eq!(result.z, Some(18.0));
783        assert_eq!(result.m, None);
784        assert_eq!(result.t, None);
785
786        let vector_point1 = VectorPoint::from_xy(1., 2.);
787        let vector_point2 = VectorPoint::from_xy(4., 5.);
788        let result = &vector_point1 * &vector_point2;
789        assert_eq!(result.x, 4.0);
790        assert_eq!(result.y, 10.0);
791        assert_eq!(result.z, None);
792        assert_eq!(result.m, None);
793        assert_eq!(result.t, None);
794
795        // assign
796        let mut vector_point1 = VectorPoint::from_xyz(1., 2., 3.);
797        let vector_point2 = VectorPoint::from_xyz(4., 5., 6.);
798        vector_point1 *= &vector_point2;
799        assert_eq!(vector_point1.x, 4.0);
800        assert_eq!(vector_point1.y, 10.0);
801        assert_eq!(vector_point1.z, Some(18.0));
802        assert_eq!(vector_point1.m, None);
803        assert_eq!(vector_point1.t, None);
804    }
805
806    #[test]
807    fn vector_point_mul_f64() {
808        let vector_point1: VectorPoint =
809            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
810        let float: f64 = 4.0;
811        let result = &vector_point1 * float;
812        assert_eq!(result.x, 4.0);
813        assert_eq!(result.y, 8.0);
814        assert_eq!(result.z, Some(12.0));
815        assert_eq!(result.m, None);
816        assert_eq!(result.t, None);
817
818        // assign
819        let mut vector_point1: VectorPoint =
820            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
821        let float: f64 = 4.0;
822        vector_point1 *= float;
823        assert_eq!(vector_point1.x, 4.0);
824        assert_eq!(vector_point1.y, 8.0);
825        assert_eq!(vector_point1.z, Some(12.0));
826        assert_eq!(vector_point1.m, None);
827        assert_eq!(vector_point1.t, None);
828    }
829
830    #[test]
831    fn vector_point_div() {
832        let vector_point1: VectorPoint =
833            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
834        let vector_point2: VectorPoint =
835            VectorPoint { x: 4.0, y: 5.0, z: Some(6.0), m: None, t: Some(5.2) };
836        let result = &vector_point1 / &vector_point2;
837        assert_eq!(result.x, 0.25);
838        assert_eq!(result.y, 0.4);
839        assert_eq!(result.z, Some(0.5));
840        assert_eq!(result.m, None);
841        assert_eq!(result.t, None);
842
843        let vector_point1 = VectorPoint::from_xy(1., 2.);
844        let vector_point2 = VectorPoint::from_xy(4., 5.);
845        let result = &vector_point1 / &vector_point2;
846        assert_eq!(result.x, 0.25);
847        assert_eq!(result.y, 0.4);
848        assert_eq!(result.z, None);
849        assert_eq!(result.m, None);
850        assert_eq!(result.t, None);
851
852        // assign
853        let mut vector_point1 = VectorPoint::from_xyz(1., 2., 3.);
854        let vector_point2 = VectorPoint::from_xyz(4., 5., 6.);
855        vector_point1 /= &vector_point2;
856        assert_eq!(vector_point1.x, 0.25);
857        assert_eq!(vector_point1.y, 0.4);
858        assert_eq!(vector_point1.z, Some(0.5));
859        assert_eq!(vector_point1.m, None);
860        assert_eq!(vector_point1.t, None);
861    }
862
863    #[test]
864    fn vector_point_div_f64() {
865        let vector_point1: VectorPoint =
866            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
867        let float: f64 = 4.0;
868        let result = &vector_point1 / float;
869        assert_eq!(result.x, 0.25);
870        assert_eq!(result.y, 0.5);
871        assert_eq!(result.z, Some(0.75));
872        assert_eq!(result.m, None);
873        assert_eq!(result.t, None);
874
875        // assign
876        let mut vector_point1: VectorPoint =
877            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
878        let float: f64 = 4.0;
879        vector_point1 /= float;
880        assert_eq!(vector_point1.x, 0.25);
881        assert_eq!(vector_point1.y, 0.5);
882        assert_eq!(vector_point1.z, Some(0.75));
883        assert_eq!(vector_point1.m, None);
884        assert_eq!(vector_point1.t, None);
885    }
886
887    #[test]
888    fn vector_point_rem() {
889        let vector_point1: VectorPoint =
890            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
891        let result = vector_point1 % 2.;
892        assert_eq!(result.x, 1.0);
893        assert_eq!(result.y, 0.0);
894        assert_eq!(result.z, Some(1.0));
895        assert_eq!(result.m, None);
896        assert_eq!(result.t, None);
897    }
898
899    #[test]
900    fn vector_point_rem_assigned() {
901        let mut vector_point1: VectorPoint =
902            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
903        vector_point1 %= 2.;
904        assert_eq!(vector_point1.x, 1.0);
905        assert_eq!(vector_point1.y, 0.0);
906        assert_eq!(vector_point1.z, Some(1.0));
907        assert_eq!(vector_point1.m, None);
908        assert_eq!(vector_point1.t, None);
909    }
910
911    #[test]
912    fn vector_equality() {
913        let vector_point1: VectorPoint =
914            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
915        let vector_point2: VectorPoint =
916            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
917        assert_eq!(vector_point1, vector_point2);
918
919        let vector_point1: VectorPoint =
920            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
921        let vector_point2: VectorPoint =
922            VectorPoint { x: 2.0, y: 3.0, z: Some(4.0), m: None, t: None };
923        assert_ne!(vector_point1, vector_point2);
924
925        let vector_point1: VectorPoint =
926            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
927        let vector_point2: VectorPoint = VectorPoint { x: 1.0, y: 2.0, z: None, m: None, t: None };
928        assert_ne!(vector_point1, vector_point2);
929
930        let vector_point1: VectorPoint =
931            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
932        let vector_point2: VectorPoint =
933            VectorPoint { x: 1.0, y: 2.0, z: Some(1.0), m: None, t: None };
934        assert_ne!(vector_point1, vector_point2);
935    }
936
937    #[test]
938    fn test_vectorpoint_ordering_x() {
939        let a: VectorPoint = VectorPoint { x: 1.0, y: 0.0, z: None, m: None, t: None };
940        let b: VectorPoint = VectorPoint { x: 2.0, y: 0.0, z: None, m: None, t: None };
941        assert_eq!(a.cmp(&b), Ordering::Less);
942        assert_eq!(b.cmp(&a), Ordering::Greater);
943    }
944
945    #[test]
946    fn test_vectorpoint_ordering_y() {
947        let a: VectorPoint = VectorPoint { x: 1.0, y: 1.0, z: None, m: None, t: None };
948        let b = VectorPoint { x: 1.0, y: 2.0, z: None, m: None, t: None };
949        assert_eq!(a.cmp(&b), Ordering::Less);
950        assert_eq!(b.cmp(&a), Ordering::Greater);
951    }
952
953    #[test]
954    fn test_vectorpoint_ordering_z() {
955        let a: VectorPoint = VectorPoint { x: 1.0, y: 1.0, z: Some(1.0), m: None, t: None };
956        let b = VectorPoint { x: 1.0, y: 1.0, z: Some(2.0), m: None, t: None };
957        assert_eq!(a.cmp(&b), Ordering::Less);
958        assert_eq!(b.cmp(&a), Ordering::Greater);
959    }
960
961    #[test]
962    fn test_vectorpoint_ordering_z_none() {
963        let a: VectorPoint = VectorPoint { x: 1.0, y: 1.0, z: None, m: None, t: None };
964        let b = VectorPoint { x: 1.0, y: 1.0, z: Some(2.0), m: None, t: None };
965        assert_eq!(a.cmp(&b), Ordering::Less); // `None` is treated as equal to any value in `z`
966        assert_eq!(b.cmp(&a), Ordering::Greater);
967    }
968
969    #[test]
970    fn test_vectorpoint_ordering_z_some() {
971        let a: VectorPoint = VectorPoint { x: 1.0, y: 1.0, z: Some(-1.0), m: None, t: None };
972        let b = VectorPoint { x: 1.0, y: 1.0, z: Some(2.0), m: None, t: None };
973        assert_eq!(a.cmp(&b), Ordering::Less); // `None` is treated as equal to any value in `z`
974        assert_eq!(b.cmp(&a), Ordering::Greater);
975    }
976
977    #[test]
978    fn test_vectorpoint_equality() {
979        let a: VectorPoint = VectorPoint { x: 1.0, y: 1.0, z: Some(1.0), m: None, t: None };
980        let b = VectorPoint { x: 1.0, y: 1.0, z: Some(1.0), m: None, t: None };
981        assert_eq!(a, b);
982        assert_eq!(a.cmp(&b), Ordering::Equal);
983    }
984
985    #[test]
986    fn test_vectorpoint_nan_handling() {
987        let nan_point: VectorPoint = VectorPoint { x: f64::NAN, y: 1.0, z: None, m: None, t: None };
988        let normal_point = VectorPoint { x: 1.0, y: 1.0, z: None, m: None, t: None };
989
990        // Since `partial_cmp` should return `None` for NaN, `cmp` must not panic.
991        assert_eq!(nan_point.cmp(&normal_point), Ordering::Greater);
992
993        // z nan
994        let nan_point: VectorPoint =
995            VectorPoint { x: 1.0, y: 1.0, z: Some(f64::NAN), m: None, t: None };
996        let normal_point = VectorPoint { x: 1.0, y: 1.0, z: Some(1.0), m: None, t: None };
997        assert_eq!(nan_point.cmp(&normal_point), Ordering::Equal);
998    }
999
1000    #[test]
1001    fn test_vectorpoint_partial_comp() {
1002        let vector_point1: VectorPoint =
1003            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
1004        let vector_point2 = VectorPoint { x: 1.0, y: 2.0, z: Some(1.0), m: None, t: None };
1005
1006        assert_eq!(vector_point1.partial_cmp(&vector_point2), Some(Ordering::Greater));
1007        assert_eq!(vector_point2.partial_cmp(&vector_point1), Some(Ordering::Less));
1008    }
1009
1010    #[test]
1011    fn test_vectorpoint_with_m() {
1012        let vector_point1: VectorPoint<MValue> = VectorPoint {
1013            x: 1.0,
1014            y: 2.0,
1015            z: Some(3.0),
1016            m: Some(Value::from([
1017                ("class".into(), ValueType::Primitive(PrimitiveValue::String("ocean".into()))),
1018                ("offset".into(), ValueType::Primitive(PrimitiveValue::U64(22))),
1019                (
1020                    "info".into(),
1021                    ValueType::Nested(Value::from([
1022                        (
1023                            "name".into(),
1024                            ValueType::Primitive(PrimitiveValue::String("Pacific Ocean".into())),
1025                        ),
1026                        ("value".into(), ValueType::Primitive(PrimitiveValue::F32(22.2))),
1027                    ])),
1028                ),
1029            ])),
1030            t: Some(-1.2),
1031        };
1032        let vector_point2: VectorPoint<MValue> =
1033            VectorPoint { x: 1.0, y: 2.0, z: Some(3.0), m: None, t: None };
1034        assert_eq!(vector_point1.partial_cmp(&vector_point2), Some(Ordering::Equal));
1035        // we only check for equality in x, y, z
1036        assert!(vector_point1 == vector_point2);
1037    }
1038
1039    #[test]
1040    fn is_empty() {
1041        let vector_point1 = VectorPoint::from_xy(1.0, 2.0);
1042        assert!(!vector_point1.is_empty());
1043        let vector_point2 = VectorPoint::from_xyz(1.0, 2.0, 3.0);
1044        assert!(!vector_point2.is_empty());
1045        let vector_point3 = VectorPoint::from_xyz(0.0, 0.0, 0.0);
1046        assert!(vector_point3.is_empty());
1047        let vector_point4 = VectorPoint::from_xy(0.0, 0.0);
1048        assert!(vector_point4.is_empty());
1049    }
1050
1051    #[test]
1052    fn get_face() {
1053        let point = VectorPoint::from_xyz(1.0, 2.0, 3.0);
1054        assert_eq!(point.face(0), 1.);
1055        assert_eq!(point.face(1), 2.);
1056        assert_eq!(point.face(2), 3.);
1057        let point = VectorPoint::from_xy(1.0, 2.0);
1058        assert_eq!(point.face(0), 1.);
1059        assert_eq!(point.face(1), 2.);
1060        assert_eq!(point.face(2), 0.);
1061    }
1062
1063    #[test]
1064    #[allow(clippy::approx_constant)]
1065    fn angle() {
1066        let point1 = VectorPoint::from_xyz(1.0, 0.0, 0.0);
1067        let point2 = VectorPoint::from_xyz(0.0, 1.0, 0.0);
1068        assert_eq!(point1.angle(&point2), 1.5707963267948966);
1069
1070        let point1 = VectorPoint::from_xy(1.0, 0.0);
1071        let point2 = VectorPoint::from_xy(0.0, 1.0);
1072        assert_eq!(point1.angle(&point2), 1.5707963267948966);
1073    }
1074
1075    #[test]
1076    fn abs() {
1077        let point = VectorPoint::from_xyz(1.0, 2.0, 3.0);
1078        assert_eq!(point.abs(), VectorPoint::from_xyz(1.0, 2.0, 3.0));
1079
1080        let point = VectorPoint::from_xyz(-1.0, -2.0, -3.0);
1081        assert_eq!(point.abs(), VectorPoint::from_xyz(1.0, 2.0, 3.0));
1082
1083        let point = VectorPoint::from_xy(1.0, 2.0);
1084        assert_eq!(point.abs(), VectorPoint::from_xy(1.0, 2.0));
1085
1086        let point = VectorPoint::from_xy(-1.0, -2.0);
1087        assert_eq!(point.abs(), VectorPoint::from_xy(1.0, 2.0));
1088    }
1089
1090    #[test]
1091    fn invert() {
1092        let point = VectorPoint::from_xyz(1.0, 2.0, 3.0);
1093        assert_eq!(point.invert(), VectorPoint::from_xyz(-1.0, -2.0, -3.0));
1094
1095        let point = VectorPoint::from_xy(1.0, 2.0);
1096        assert_eq!(point.invert(), VectorPoint::from_xy(-1.0, -2.0));
1097    }
1098
1099    #[test]
1100    fn normalize() {
1101        let mut point = VectorPoint::from_xyz(1.0, 2.0, 3.0);
1102        point.normalize();
1103        assert_eq!(
1104            point,
1105            VectorPoint::from_xyz(0.2672612419124244, 0.5345224838248488, 0.8017837257372732)
1106        );
1107
1108        let mut point = VectorPoint::from_xyz(0.0, 0.0, 0.0);
1109        point.normalize();
1110        assert_eq!(point, VectorPoint::from_xyz(0.0, 0.0, 0.0));
1111    }
1112
1113    #[test]
1114    fn largest_abs_component() {
1115        let point = VectorPoint::from_xyz(1.0, 2.0, 3.0);
1116        assert_eq!(point.largest_abs_component(), 2);
1117        let point = VectorPoint::from_xyz(3.0, 2.0, 1.0);
1118        assert_eq!(point.largest_abs_component(), 0);
1119        let point = VectorPoint::from_xyz(1.0, 3.0, 2.0);
1120        assert_eq!(point.largest_abs_component(), 1);
1121        let point = VectorPoint::from_xyz(2.0, 1.0, 3.0);
1122        assert_eq!(point.largest_abs_component(), 2);
1123    }
1124
1125    #[test]
1126    fn intermediate() {
1127        let point1 = VectorPoint::from_xyz(1.0, 2.0, 3.0);
1128        let point2 = VectorPoint::from_xyz(4.0, 5.0, 6.0);
1129        assert_eq!(point1.intermediate(&point2, 0.5), VectorPoint::from_xyz(2.5, 3.5, 4.5));
1130
1131        let point1 = VectorPoint::from_xy(1.0, 2.0);
1132        let point2 = VectorPoint::from_xy(4.0, 5.0);
1133        assert_eq!(point1.intermediate(&point2, 0.5), VectorPoint::from_xy(2.5, 3.5));
1134    }
1135
1136    #[test]
1137    fn perpendicular() {
1138        let point = VectorPoint::from_xyz(1.0, 2.0, 3.0);
1139        assert_eq!(point.perpendicular(), VectorPoint::from_xyz(-2.0, 1.0, -2.0));
1140
1141        let point = VectorPoint::from_xyz(3.0, 2.0, 1.0);
1142        assert_eq!(point.perpendicular(), VectorPoint::from_xyz(-2.0, 3.0, 0.0));
1143
1144        let point = VectorPoint::from_xy(1.0, 2.0);
1145        assert_eq!(point.perpendicular(), VectorPoint::from_xy(-2., 1.));
1146    }
1147}