gistools/writers/json/
mod.rs1use super::OnFeature;
2use crate::{
3 geometry::{ConvertVectorFeatureWM, convert},
4 parsers::{FeatureReader, Writer},
5};
6use alloc::{collections::BTreeSet, format, vec::Vec};
7use s2json::{BBox3D, JSONCollection, Projection};
8use serde::Serialize;
9
10#[derive(Debug)]
12pub struct ToJSONOptions<M: Clone, P: Clone + Default + Serialize, D: Clone + Default + Serialize> {
13 pub projection: Option<Projection>,
15 pub build_bbox: Option<bool>,
17 pub geojson: Option<bool>,
19 pub on_feature: Option<OnFeature<M, P, D>>,
21}
22impl<M: Clone, P: Clone + Default + Serialize, D: Clone + Default + Serialize> Default
23 for ToJSONOptions<M, P, D>
24{
25 fn default() -> Self {
26 ToJSONOptions { projection: None, build_bbox: None, geojson: None, on_feature: None }
27 }
28}
29
30pub fn to_json<
71 T: Writer,
72 M: Clone + Serialize,
73 P: Clone + Default + Serialize,
74 D: Clone + Default + Serialize,
75 I: FeatureReader<M, P, D>,
76>(
77 writer: &mut T,
78 readers: Vec<&I>,
79 opts: Option<ToJSONOptions<M, P, D>>,
80) {
81 let opts = opts.unwrap_or_default();
82 let projection = opts.projection.unwrap_or(Projection::S2);
83 let on_feature = opts.on_feature.unwrap_or(Some);
84 let build_bbox = opts.build_bbox.unwrap_or(true);
85 let mut bbox = BBox3D::default();
86 let mut faces: BTreeSet<u8> = BTreeSet::new();
87 let r#type =
88 if projection == Projection::S2 { "S2FeatureCollection" } else { "FeatureCollection" };
89
90 writer.append_string("{\n\t\"type\": \"");
91 writer.append_string(r#type);
92 writer.append_string("\",\n");
93 writer.append_string("\t\"features\": [\n");
94
95 let mut first = true;
96 for reader in readers {
97 for feature in reader.iter() {
98 let converted_features = convert(
99 projection,
100 &JSONCollection::VectorFeature(feature),
101 Some(build_bbox),
102 None,
103 );
104 for converted_feature in converted_features {
105 let user_feature = on_feature(converted_feature);
106 if user_feature.is_none() {
107 continue;
108 }
109 let user_feature = user_feature.unwrap();
110 faces.insert(user_feature.face.into());
111 if build_bbox && let Some(feature_bbox) = user_feature.geometry.bbox() {
112 bbox.merge_in_place(feature_bbox);
113 }
114 if !first {
115 writer.append_string(",\n");
116 } else {
117 first = false;
118 }
119 let feature_str = match opts.geojson.unwrap_or(false) {
120 true => serde_json::to_string(&user_feature.to_feature(true)).unwrap(),
121 false => serde_json::to_string(&user_feature).unwrap(),
122 };
123 writer.append_string("\t\t");
124 writer.append_string(&feature_str);
125 }
126 }
127 }
128
129 writer.append_string("\n\t],");
130 let faces_vec: Vec<&u8> = faces.iter().collect();
131 writer.append_string(&format!("\n\t\"faces\": {faces_vec:?}"));
132 if build_bbox {
133 writer
134 .append_string(&format!(",\n\t\"bbox\": {:?}", &serde_json::to_string(&bbox).unwrap()));
135 }
136 writer.append_string("\n}");
137}
138
139pub fn to_jsonld<
179 T: Writer,
180 M: Clone + Serialize,
181 P: Clone + Default + Serialize,
182 D: Clone + Default + Serialize,
183 I: FeatureReader<M, P, D>,
184>(
185 writer: &mut T,
186 readers: Vec<&I>,
187 opts: Option<ToJSONOptions<M, P, D>>,
188) {
189 let opts = opts.unwrap_or_default();
190 let projection = opts.projection.unwrap_or(Projection::S2);
191 let on_feature = opts.on_feature.unwrap_or(Some);
192 let build_bbox = opts.build_bbox.unwrap_or(true);
193
194 for reader in readers {
195 for feature in reader.iter() {
196 let converted_features = convert(
197 projection,
198 &JSONCollection::VectorFeature(feature),
199 Some(build_bbox),
200 None,
201 );
202 for converted_feature in converted_features {
203 let user_feature = on_feature(converted_feature);
204 if let Some(user_feature) = user_feature {
205 let feature_str = match opts.geojson.unwrap_or(false) {
206 true => serde_json::to_string(&user_feature.to_feature(true)).unwrap(),
207 false => serde_json::to_string(&user_feature).unwrap(),
208 };
209 writer.append_string(&feature_str);
210 writer.append_string("\n");
211 }
212 }
213 }
214 }
215}