geoarrow_array/scalar/coord/
separated.rs

1use arrow_buffer::ScalarBuffer;
2use geo_traits::CoordTrait;
3use geoarrow_schema::Dimension;
4
5use crate::eq::coord_eq;
6use crate::scalar::InterleavedCoord;
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 SeparatedCoord<'a> {
13    pub(crate) buffers: &'a [ScalarBuffer<f64>; 4],
14    pub(crate) i: usize,
15    pub(crate) dim: Dimension,
16}
17
18impl SeparatedCoord<'_> {
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 SeparatedCoord<'_> {
26    fn eq(&self, other: &SeparatedCoord) -> bool {
27        coord_eq(self, other)
28    }
29}
30
31impl PartialEq<InterleavedCoord<'_>> for SeparatedCoord<'_> {
32    fn eq(&self, other: &InterleavedCoord) -> bool {
33        coord_eq(self, other)
34    }
35}
36
37impl CoordTrait for SeparatedCoord<'_> {
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        self.buffers[n][self.i]
46    }
47
48    fn x(&self) -> Self::T {
49        self.buffers[0][self.i]
50    }
51
52    fn y(&self) -> Self::T {
53        self.buffers[1][self.i]
54    }
55}
56
57impl CoordTrait for &SeparatedCoord<'_> {
58    type T = f64;
59
60    fn dim(&self) -> geo_traits::Dimensions {
61        self.dim.into()
62    }
63
64    fn nth_or_panic(&self, n: usize) -> Self::T {
65        self.buffers[n][self.i]
66    }
67
68    fn x(&self) -> Self::T {
69        self.buffers[0][self.i]
70    }
71
72    fn y(&self) -> Self::T {
73        self.buffers[1][self.i]
74    }
75}
76
77#[cfg(test)]
78mod test {
79    use geoarrow_schema::Dimension;
80
81    use crate::array::{InterleavedCoordBuffer, SeparatedCoordBuffer};
82
83    /// Test Eq where the current index is true but another index is false
84    #[test]
85    fn test_eq_other_index_false() {
86        let x1 = vec![0., 1., 2.];
87        let y1 = vec![3., 4., 5.];
88        let buf1 =
89            SeparatedCoordBuffer::from_vec(vec![x1.into(), y1.into()], Dimension::XY).unwrap();
90        let coord1 = buf1.value(0);
91
92        let x2 = vec![0., 100., 2.];
93        let y2 = vec![3., 400., 5.];
94        let buf2 =
95            SeparatedCoordBuffer::from_vec(vec![x2.into(), y2.into()], Dimension::XY).unwrap();
96        let coord2 = buf2.value(0);
97
98        assert_eq!(coord1, coord2);
99    }
100
101    #[test]
102    fn test_eq_against_interleaved_coord() {
103        let x1 = vec![0., 1., 2.];
104        let y1 = vec![3., 4., 5.];
105        let buf1 =
106            SeparatedCoordBuffer::from_vec(vec![x1.into(), y1.into()], Dimension::XY).unwrap();
107        let coord1 = buf1.value(0);
108
109        let coords2 = vec![0., 3., 1., 4., 2., 5.];
110        let buf2 = InterleavedCoordBuffer::new(coords2.into(), Dimension::XY);
111        let coord2 = buf2.value(0);
112
113        assert_eq!(coord1, coord2);
114    }
115}