geoarrow_array/scalar/coord/
interleaved.rs

1use arrow_buffer::ScalarBuffer;
2use geo_traits::CoordTrait;
3use geoarrow_schema::Dimension;
4
5use crate::eq::coord_eq;
6use crate::scalar::SeparatedCoord;
7
8/// An Arrow equivalent of a Coord
9///
10/// This implements [CoordTrait], which you can use to extract data.
11#[derive(Debug, Clone)]
12pub struct InterleavedCoord<'a> {
13    pub(crate) coords: &'a ScalarBuffer<f64>,
14    pub(crate) i: usize,
15    pub(crate) dim: Dimension,
16}
17
18impl InterleavedCoord<'_> {
19    /// Return `true` if all values in the coordinate are f64::NAN
20    pub(crate) fn is_nan(&self) -> bool {
21        (0..self.dim.size()).all(|coord_dim| self.nth_or_panic(coord_dim).is_nan())
22    }
23}
24
25impl PartialEq for InterleavedCoord<'_> {
26    fn eq(&self, other: &Self) -> bool {
27        coord_eq(self, other)
28    }
29}
30
31impl PartialEq<SeparatedCoord<'_>> for InterleavedCoord<'_> {
32    fn eq(&self, other: &SeparatedCoord<'_>) -> bool {
33        coord_eq(self, other)
34    }
35}
36
37impl CoordTrait for InterleavedCoord<'_> {
38    type T = f64;
39
40    fn dim(&self) -> geo_traits::Dimensions {
41        self.dim.into()
42    }
43
44    fn nth_or_panic(&self, n: usize) -> Self::T {
45        debug_assert!(n < self.dim.size());
46        *self.coords.get(self.i * self.dim.size() + n).unwrap()
47    }
48
49    fn x(&self) -> Self::T {
50        *self.coords.get(self.i * self.dim.size()).unwrap()
51    }
52
53    fn y(&self) -> Self::T {
54        *self.coords.get(self.i * self.dim.size() + 1).unwrap()
55    }
56}
57
58impl CoordTrait for &InterleavedCoord<'_> {
59    type T = f64;
60
61    fn dim(&self) -> geo_traits::Dimensions {
62        self.dim.into()
63    }
64
65    fn nth_or_panic(&self, n: usize) -> Self::T {
66        debug_assert!(n < self.dim.size());
67        *self.coords.get(self.i * self.dim.size() + n).unwrap()
68    }
69
70    fn x(&self) -> Self::T {
71        *self.coords.get(self.i * self.dim.size()).unwrap()
72    }
73
74    fn y(&self) -> Self::T {
75        *self.coords.get(self.i * self.dim.size() + 1).unwrap()
76    }
77}
78
79#[cfg(test)]
80mod test {
81    use geoarrow_schema::Dimension;
82
83    use crate::array::{InterleavedCoordBuffer, SeparatedCoordBuffer};
84
85    /// Test Eq where the current index is true but another index is false
86    #[test]
87    fn test_eq_other_index_false() {
88        let coords1 = vec![0., 3., 1., 4., 2., 5.];
89        let buf1 = InterleavedCoordBuffer::new(coords1.into(), Dimension::XY);
90        let coord1 = buf1.value(0);
91
92        let coords2 = vec![0., 3., 100., 400., 200., 500.];
93        let buf2 = InterleavedCoordBuffer::new(coords2.into(), Dimension::XY);
94        let coord2 = buf2.value(0);
95
96        assert_eq!(coord1, coord2);
97    }
98
99    #[test]
100    fn test_eq_against_separated_coord() {
101        let coords1 = vec![0., 3., 1., 4., 2., 5.];
102        let buf1 = InterleavedCoordBuffer::new(coords1.into(), Dimension::XY);
103        let coord1 = buf1.value(0);
104
105        let x = vec![0.];
106        let y = vec![3.];
107        let buf2 = SeparatedCoordBuffer::from_vec(vec![x.into(), y.into()], Dimension::XY).unwrap();
108        let coord2 = buf2.value(0);
109
110        assert_eq!(coord1, coord2);
111    }
112}