geoarrow_array/scalar/
multipoint.rs

1use arrow_buffer::OffsetBuffer;
2use geo_traits::MultiPointTrait;
3use geoarrow_schema::Dimension;
4
5use crate::array::CoordBuffer;
6use crate::eq::multi_point_eq;
7use crate::scalar::Point;
8use crate::util::OffsetBufferUtils;
9
10/// An Arrow equivalent of a MultiPoint
11///
12/// This implements [MultiPointTrait], which you can use to extract data.
13#[derive(Debug, Clone)]
14pub struct MultiPoint<'a> {
15    /// Buffer of coordinates
16    pub(crate) coords: &'a CoordBuffer,
17
18    /// Offsets into the coordinate array where each geometry starts
19    pub(crate) geom_offsets: &'a OffsetBuffer<i32>,
20
21    pub(crate) geom_index: usize,
22
23    start_offset: usize,
24}
25
26impl<'a> MultiPoint<'a> {
27    pub(crate) fn new(
28        coords: &'a CoordBuffer,
29        geom_offsets: &'a OffsetBuffer<i32>,
30        geom_index: usize,
31    ) -> Self {
32        let (start_offset, _) = geom_offsets.start_end(geom_index);
33        Self {
34            coords,
35            geom_offsets,
36            geom_index,
37            start_offset,
38        }
39    }
40
41    pub(crate) fn native_dim(&self) -> Dimension {
42        self.coords.dim()
43    }
44}
45
46impl<'a> MultiPointTrait for MultiPoint<'a> {
47    type InnerPointType<'b>
48        = Point<'a>
49    where
50        Self: 'b;
51
52    fn num_points(&self) -> usize {
53        let (start, end) = self.geom_offsets.start_end(self.geom_index);
54        end - start
55    }
56
57    unsafe fn point_unchecked(&self, i: usize) -> Self::InnerPointType<'_> {
58        Point::new(self.coords, self.start_offset + i)
59    }
60}
61
62impl<'a> MultiPointTrait for &'a MultiPoint<'a> {
63    type InnerPointType<'b>
64        = Point<'a>
65    where
66        Self: 'b;
67
68    fn num_points(&self) -> usize {
69        let (start, end) = self.geom_offsets.start_end(self.geom_index);
70        end - start
71    }
72
73    unsafe fn point_unchecked(&self, i: usize) -> Self::InnerPointType<'_> {
74        Point::new(self.coords, self.start_offset + i)
75    }
76}
77
78impl<G: MultiPointTrait<T = f64>> PartialEq<G> for MultiPoint<'_> {
79    fn eq(&self, other: &G) -> bool {
80        multi_point_eq(self, other)
81    }
82}
83
84// #[cfg(test)]
85// mod test {
86//     use crate::array::MultiPointArray;
87//     use crate::test::multipoint::{mp0, mp1};
88//     use crate::trait_::ArrayAccessor;
89//     use geoarrow_schema::Dimension;
90
91//     /// Test Eq where the current index is true but another index is false
92//     #[test]
93//     fn test_eq_other_index_false() {
94//         let arr1: MultiPointArray = (vec![mp0(), mp1()].as_slice(), Dimension::XY).into();
95//         let arr2: MultiPointArray = (vec![mp0(), mp0()].as_slice(), Dimension::XY).into();
96
97//         assert_eq!(arr1.value(0), arr2.value(0));
98//         assert_ne!(arr1.value(1), arr2.value(1));
99//     }
100// }