geoarrow_geojson/encoder/
multipolygon.rs1use arrow_json::Encoder;
2use geo_traits::MultiPolygonTrait;
3use geoarrow_array::GeoArrowArrayAccessor;
4use geoarrow_array::array::MultiPolygonArray;
5
6use crate::encoder::polygon::encode_polygon_rings;
7
8pub struct MultiPolygonEncoder(MultiPolygonArray);
10
11impl MultiPolygonEncoder {
12 pub fn new(array: MultiPolygonArray) -> Self {
13 Self(array)
14 }
15}
16
17impl Encoder for MultiPolygonEncoder {
18 fn encode(&mut self, idx: usize, out: &mut Vec<u8>) {
19 let geom = self.0.value(idx).unwrap();
20 encode_multi_polygon(&geom, out);
21 }
22}
23
24pub(crate) fn encode_multi_polygon(geom: &impl MultiPolygonTrait<T = f64>, out: &mut Vec<u8>) {
26 out.extend(br#"{"type":"MultiPolygon","coordinates":"#);
27 encode_multi_polygon_inner(geom, out);
28 out.push(b'}');
29}
30
31fn encode_multi_polygon_inner(geom: &impl MultiPolygonTrait<T = f64>, out: &mut Vec<u8>) {
32 out.push(b'[');
33 let num_polygons = geom.num_polygons();
34 for (idx, polygon) in geom.polygons().enumerate() {
35 encode_polygon_rings(&polygon, out);
36 if idx < num_polygons - 1 {
37 out.push(b',');
38 }
39 }
40 out.push(b']');
41}
42
43#[cfg(test)]
44mod test {
45 use std::str::FromStr;
46
47 use geoarrow_array::test::multipolygon::array;
48 use geoarrow_schema::{CoordType, Dimension};
49
50 use super::*;
51
52 #[test]
53 fn encode_multi_polygon() {
54 let mut encoder = MultiPolygonEncoder::new(array(CoordType::Separated, Dimension::XY));
55
56 let mut out = vec![];
57 encoder.encode(0, &mut out);
58 let s = String::from_utf8(out).unwrap();
59 let expected = r#"{"type":"MultiPolygon","coordinates":[[[[30,10],[40,40],[20,40],[10,20],[30,10]]]]}"#;
60 assert_eq!(s, expected);
61
62 geojson::Geometry::from_str(expected).expect("Should be valid GeoJSON");
63 }
64}