geoarrow_array/geozero/import/
point.rs

1use geoarrow_schema::PointType;
2use geozero::{GeomProcessor, GeozeroGeometry};
3
4use crate::array::PointArray;
5use crate::builder::PointBuilder;
6use crate::geozero::import::util::{from_xy, from_xyzm};
7
8/// GeoZero trait to convert to GeoArrow PointArray.
9pub trait ToPointArray {
10    /// Convert to GeoArrow PointArray
11    fn to_point_array(&self, typ: PointType) -> geozero::error::Result<PointArray> {
12        Ok(self.to_point_builder(typ)?.finish())
13    }
14
15    /// Convert to a GeoArrow PointBuilder
16    fn to_point_builder(&self, typ: PointType) -> geozero::error::Result<PointBuilder>;
17}
18
19impl<T: GeozeroGeometry> ToPointArray for T {
20    fn to_point_builder(&self, typ: PointType) -> geozero::error::Result<PointBuilder> {
21        let mut mutable_point_array = PointBuilder::new(typ);
22        self.process_geom(&mut mutable_point_array)?;
23        Ok(mutable_point_array)
24    }
25}
26
27#[allow(unused_variables)]
28impl GeomProcessor for PointBuilder {
29    fn empty_point(&mut self, idx: usize) -> geozero::error::Result<()> {
30        self.push_empty();
31        Ok(())
32    }
33
34    fn xy(&mut self, x: f64, y: f64, _idx: usize) -> geozero::error::Result<()> {
35        self.push_coord(from_xy(x, y).as_ref());
36        Ok(())
37    }
38
39    fn coordinate(
40        &mut self,
41        x: f64,
42        y: f64,
43        z: Option<f64>,
44        m: Option<f64>,
45        t: Option<f64>,
46        tm: Option<u64>,
47        idx: usize,
48    ) -> geozero::error::Result<()> {
49        self.push_coord(from_xyzm(x, y, z, m).as_ref());
50        Ok(())
51    }
52
53    fn geometrycollection_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> {
54        self.reserve_exact(size);
55        Ok(())
56    }
57
58    // Override all other trait _begin methods
59    fn circularstring_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> {
60        Err(geozero::error::GeozeroError::Geometry(
61            "Only point geometries allowed".to_string(),
62        ))
63    }
64
65    fn compoundcurve_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> {
66        Err(geozero::error::GeozeroError::Geometry(
67            "Only point geometries allowed".to_string(),
68        ))
69    }
70
71    fn tin_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> {
72        Err(geozero::error::GeozeroError::Geometry(
73            "Only point geometries allowed".to_string(),
74        ))
75    }
76
77    fn polygon_begin(
78        &mut self,
79        tagged: bool,
80        size: usize,
81        idx: usize,
82    ) -> geozero::error::Result<()> {
83        Err(geozero::error::GeozeroError::Geometry(
84            "Only point geometries allowed".to_string(),
85        ))
86    }
87
88    fn triangle_begin(
89        &mut self,
90        tagged: bool,
91        size: usize,
92        idx: usize,
93    ) -> geozero::error::Result<()> {
94        Err(geozero::error::GeozeroError::Geometry(
95            "Only point geometries allowed".to_string(),
96        ))
97    }
98
99    fn linestring_begin(
100        &mut self,
101        tagged: bool,
102        size: usize,
103        idx: usize,
104    ) -> geozero::error::Result<()> {
105        Err(geozero::error::GeozeroError::Geometry(
106            "Only point geometries allowed".to_string(),
107        ))
108    }
109
110    // fn multicurve_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> {
111    //     Err(geozero::error::GeozeroError::Geometry(
112    //         "Only point geometries allowed".to_string(),
113    //     ))
114    // }
115
116    fn multipoint_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> {
117        Err(geozero::error::GeozeroError::Geometry(
118            "Only point geometries allowed".to_string(),
119        ))
120    }
121
122    fn curvepolygon_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> {
123        Err(geozero::error::GeozeroError::Geometry(
124            "Only point geometries allowed".to_string(),
125        ))
126    }
127
128    fn multipolygon_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> {
129        Err(geozero::error::GeozeroError::Geometry(
130            "Only point geometries allowed".to_string(),
131        ))
132    }
133
134    fn multisurface_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> {
135        Err(geozero::error::GeozeroError::Geometry(
136            "Only point geometries allowed".to_string(),
137        ))
138    }
139
140    fn multilinestring_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> {
141        Err(geozero::error::GeozeroError::Geometry(
142            "Only point geometries allowed".to_string(),
143        ))
144    }
145
146    fn polyhedralsurface_begin(&mut self, size: usize, idx: usize) -> geozero::error::Result<()> {
147        Err(geozero::error::GeozeroError::Geometry(
148            "Only point geometries allowed".to_string(),
149        ))
150    }
151}
152
153#[cfg(test)]
154mod test {
155
156    use geo_types::{Geometry, GeometryCollection};
157    use geoarrow_schema::Dimension;
158
159    use super::*;
160    use crate::GeoArrowArrayAccessor;
161    use crate::test::{linestring, point};
162
163    #[test]
164    fn from_geozero() {
165        let geo = Geometry::GeometryCollection(
166            vec![
167                Geometry::Point(point::p0()),
168                Geometry::Point(point::p1()),
169                Geometry::Point(point::p2()),
170            ]
171            .into(),
172        );
173
174        let typ = PointType::new(Dimension::XY, Default::default());
175        let point_array = geo.to_point_array(typ).unwrap();
176        assert_eq!(point_array.value(0).unwrap(), point::p0());
177        assert_eq!(point_array.value(1).unwrap(), point::p1());
178        assert_eq!(point_array.value(2).unwrap(), point::p2());
179    }
180
181    #[test]
182    fn from_geozero_error_multiple_geom_types() {
183        let geo = Geometry::GeometryCollection(GeometryCollection(vec![
184            Geometry::Point(point::p0()),
185            Geometry::LineString(linestring::ls0()),
186        ]));
187
188        let typ = PointType::new(Dimension::XY, Default::default());
189        let err = ToPointArray::to_point_array(&geo, typ).unwrap_err();
190        assert!(matches!(err, geozero::error::GeozeroError::Geometry(..)));
191    }
192}