1use crate::appearance::{Appearance, MaterialObject, TextureObject};
2use crate::city_object::CityObject;
3use crate::error::Result;
4use crate::geometry::GeometryTemplates;
5use crate::metadata::{Metadata, Transform};
6use serde::{Deserialize, Serialize};
7use serde_json::{json, Value};
8use std::collections::HashMap;
9
10fn reindex<T: Clone>(all: &[T], oldnew: &HashMap<usize, usize>) -> Vec<T> {
23 let mut pairs: Vec<(usize, usize)> = oldnew.iter().map(|(o, n)| (*n, *o)).collect();
24 pairs.sort_unstable();
25 pairs.into_iter().map(|(_, old)| all[old].clone()).collect()
26}
27
28#[derive(Clone)]
29pub enum SortingStrategy {
30 Random,
31 Lexicographical,
32 Morton, Hilbert, }
35
36#[derive(Serialize, Deserialize, Debug, Clone)]
37pub struct CityJSON {
38 #[serde(rename = "type")]
39 pub thetype: CityJSONType,
40 pub version: String,
41 pub transform: Transform,
42 #[serde(rename = "CityObjects")]
43 pub city_objects: HashMap<String, CityObject>,
44 pub vertices: Vec<Vec<i64>>,
45 #[serde(skip_serializing_if = "Option::is_none")]
46 pub metadata: Option<Metadata>,
47 #[serde(skip_serializing_if = "Option::is_none")]
48 pub appearance: Option<Appearance>,
49 #[serde(rename = "geometry-templates")]
50 #[serde(skip_serializing_if = "Option::is_none")]
51 pub geometry_templates: Option<GeometryTemplates>,
52 #[serde(skip_serializing_if = "Option::is_none")]
53 pub extensions: Option<Value>,
54 #[serde(flatten)]
55 pub other: serde_json::Value,
56 #[serde(skip)]
57 sorted_ids: Vec<String>,
58 #[serde(skip)]
59 transform_correction: Option<Transform>,
60}
61
62impl PartialEq for CityJSON {
75 fn eq(&self, other: &Self) -> bool {
76 self.thetype == other.thetype
77 && self.version == other.version
78 && self.transform == other.transform
79 && self.city_objects == other.city_objects
80 && self.vertices == other.vertices
81 && self.metadata == other.metadata
82 && self.appearance == other.appearance
83 && self.geometry_templates == other.geometry_templates
84 && self.extensions == other.extensions
85 && self.other == other.other
86 }
87}
88
89impl CityJSON {
90 pub fn new() -> Self {
92 let co: HashMap<String, CityObject> = HashMap::new();
93 let v: Vec<Vec<i64>> = Vec::new();
94 let tr = Transform::new();
95 CityJSON {
96 thetype: CityJSONType::CityJSON,
97 version: "2.0".to_string(),
98 transform: tr,
99 city_objects: co,
100 vertices: v,
101 metadata: None,
102 appearance: None,
103 geometry_templates: None,
104 extensions: None,
105 other: json!(null),
106 sorted_ids: vec![],
107 transform_correction: None,
108 }
109 }
110 pub fn from_str(s: &str) -> Result<Self> {
112 let mut cjj: CityJSON = serde_json::from_str(s)?;
113 for (key, co) in &cjj.city_objects {
115 if co.is_toplevel() {
116 cjj.sorted_ids.push(key.clone());
117 }
118 }
119 Ok(cjj)
120 }
121
122 pub fn get_metadata(&self) -> Self {
124 let co: HashMap<String, CityObject> = HashMap::new();
125 let v: Vec<Vec<i64>> = Vec::new();
126 let mut cj0 = CityJSON {
127 thetype: self.thetype.clone(),
128 version: self.version.clone(),
129 transform: self.transform.clone(),
130 metadata: self.metadata.clone(),
131 city_objects: co,
132 vertices: v,
133 appearance: None,
134 geometry_templates: self.geometry_templates.clone(),
135 other: self.other.clone(),
136 extensions: self.extensions.clone(),
137 sorted_ids: vec![],
138 transform_correction: None,
139 };
140 match &self.geometry_templates {
143 Some(x) => {
144 let mut gts2: GeometryTemplates = x.clone();
145 let mut m_oldnew: HashMap<usize, usize> = HashMap::new();
146 let mut t_oldnew: HashMap<usize, usize> = HashMap::new();
147 let mut t_v_oldnew: HashMap<usize, usize> = HashMap::new();
148 for g in &mut gts2.templates {
149 g.update_material(&mut m_oldnew);
150 g.update_texture(&mut t_oldnew, &mut t_v_oldnew, 0);
151 }
152 if self.appearance.is_some() {
154 let a = self.appearance.as_ref().unwrap();
155 let mut acjf: Appearance = Appearance::new();
156 acjf.default_theme_material = a.default_theme_material.clone();
157 acjf.default_theme_texture = a.default_theme_texture.clone();
158 if let Some(am) = a.materials.as_ref() {
159 acjf.materials = Some(reindex(am, &m_oldnew));
160 }
161 if let Some(at) = a.textures.as_ref() {
162 acjf.textures = Some(reindex(at, &t_oldnew));
163 }
164 if let Some(atv) = a.vertices_texture.as_ref() {
165 acjf.vertices_texture = Some(reindex(atv, &t_v_oldnew));
166 }
167 cj0.appearance = Some(acjf);
168 }
169 }
170 None => (),
171 }
172 cj0
173 }
174 pub fn get_cjfeature(&self, i: usize) -> Option<CityJSONFeature> {
177 let i2 = self.sorted_ids.get(i);
178 if i2.is_none() {
179 return None;
180 }
181 let obj = self.city_objects.get(i2.unwrap());
182 if obj.is_none() {
183 return None;
184 }
185 let co = obj.unwrap();
186 let mut cjf = CityJSONFeature::new();
188 let mut co2: CityObject = co.clone();
189 let mut g_vi_oldnew: HashMap<usize, usize> = HashMap::new();
190 let mut m_oldnew: HashMap<usize, usize> = HashMap::new();
191 let mut t_oldnew: HashMap<usize, usize> = HashMap::new();
192 let mut t_v_oldnew: HashMap<usize, usize> = HashMap::new();
193 match &mut co2.geometry {
194 Some(x) => {
195 for g in x.iter_mut() {
196 g.update_geometry_boundaries(&mut g_vi_oldnew);
197 g.update_material(&mut m_oldnew);
198 g.update_texture(&mut t_oldnew, &mut t_v_oldnew, 0);
199 }
200 }
201 None => (),
202 }
203 cjf.add_co(self.sorted_ids[i].clone(), co2);
204 cjf.id = self.sorted_ids[i].to_string();
205 for childkey in co.get_children_keys() {
208 let coc = self.city_objects.get(&childkey).unwrap();
209 let mut coc2: CityObject = coc.clone();
210 match &mut coc2.geometry {
211 Some(x) => {
212 for g in x.iter_mut() {
213 g.update_geometry_boundaries(&mut g_vi_oldnew);
214 g.update_material(&mut m_oldnew);
215 g.update_texture(&mut t_oldnew, &mut t_v_oldnew, 0);
216 }
217 }
218 None => (),
219 }
220 cjf.add_co(childkey.clone(), coc2);
221 }
222 let allvertices = &self.vertices;
224 let mut g_new_vertices: Vec<Vec<i64>> = Vec::new();
225 g_new_vertices.resize(g_vi_oldnew.len(), vec![]);
226 for (old, new) in &g_vi_oldnew {
227 g_new_vertices[*new] = allvertices[*old].clone();
228 }
229 cjf.vertices = g_new_vertices;
230 if self.appearance.is_some() {
232 let a = self.appearance.as_ref().unwrap();
233 let mut acjf: Appearance = Appearance::new();
234 acjf.default_theme_material = a.default_theme_material.clone();
235 acjf.default_theme_texture = a.default_theme_texture.clone();
236 if let Some(am) = a.materials.as_ref() {
237 acjf.materials = Some(reindex(am, &m_oldnew));
238 }
239 if let Some(at) = a.textures.as_ref() {
240 acjf.textures = Some(reindex(at, &t_oldnew));
241 }
242 if let Some(atv) = a.vertices_texture.as_ref() {
243 acjf.vertices_texture = Some(reindex(atv, &t_v_oldnew));
244 }
245 cjf.appearance = Some(acjf);
246 }
247 Some(cjf)
248 }
249 pub fn add_transform_correction(&mut self, t: Transform) {
252 self.transform_correction = Some(t);
253 }
254 pub fn add_cjfeature(&mut self, cjf: &mut CityJSONFeature) {
255 let mut m_oldnew: HashMap<usize, usize> = HashMap::new();
256 let mut t_oldnew: HashMap<usize, usize> = HashMap::new();
257 let mut t_v_oldnew: HashMap<usize, usize> = HashMap::new();
258 let g_offset = self.vertices.len();
259 let mut t_offset = 0;
260 if let Some(cjf_app) = &cjf.appearance {
261 if let Some(cjf_mat) = &cjf_app.materials {
262 for (i, m) in cjf_mat.iter().enumerate() {
263 m_oldnew.insert(i, self.add_material(m.clone()));
264 }
265 }
266 if let Some(cjf_tex) = &cjf_app.textures {
267 for (i, m) in cjf_tex.iter().enumerate() {
268 t_oldnew.insert(i, self.add_texture(m.clone()));
269 }
270 }
271 if let Some(cjf_v_tex) = &cjf_app.vertices_texture {
272 t_offset = cjf_v_tex.len();
273 self.add_vertices_texture(cjf_v_tex.clone());
274 }
275 }
276
277 for (key, co) in &mut cjf.city_objects {
278 if let Some(ref mut geoms) = &mut co.geometry {
280 for g in geoms.iter_mut() {
281 g.offset_geometry_boundaries(g_offset);
283 g.update_material(&mut m_oldnew);
286 g.update_texture(&mut t_oldnew, &mut t_v_oldnew, t_offset);
288 }
289 }
290 self.add_co(key.to_string(), co.clone());
292 }
293 self.add_vertices(&mut cjf.vertices);
295 self.sorted_ids.push(cjf.id.clone());
297 }
298 pub fn remove_duplicate_vertices(&mut self) {
299 let mut h: HashMap<String, usize> = HashMap::new();
301 let mut newids: HashMap<usize, usize> = HashMap::new();
302 let mut newvertices: Vec<Vec<i64>> = Vec::new();
303 for (i, v) in self.vertices.iter().enumerate() {
304 let k = format!("{} {} {}", v[0], v[1], v[2]);
306 match h.get(&k) {
307 Some(x) => {
308 let _ = newids.insert(i, *x);
309 }
310 None => {
311 newids.insert(i, newvertices.len());
312 h.insert(k.clone(), newvertices.len());
313 newvertices.push(v.clone());
314 }
315 }
316 }
317 let cos = &mut self.city_objects;
319 for (_key, co) in cos.iter_mut() {
320 match &mut co.geometry {
321 Some(x) => {
322 for g in x.iter_mut() {
323 g.update_geometry_boundaries(&mut newids);
324 }
325 }
326 None => (),
327 }
328 }
329 self.vertices = newvertices;
331 }
332 pub fn update_geographicalextent(&mut self) {
333 if let Some(m) = &mut self.metadata {
334 if let Some(ref mut ge) = m.geographical_extent {
335 let mut mins: Vec<i64> = vec![i64::MAX, i64::MAX, i64::MAX];
336 let mut maxs: Vec<i64> = vec![i64::MIN, i64::MIN, i64::MIN];
337 for v in &self.vertices {
338 for i in 0..3 {
339 if v[i] < mins[i] {
340 mins[i] = v[i];
341 }
342 if v[i] > maxs[i] {
343 maxs[i] = v[i];
344 }
345 }
346 }
347 *ge = [
348 mins[0] as f64 * self.transform.scale[0] + self.transform.translate[0],
349 mins[1] as f64 * self.transform.scale[1] + self.transform.translate[1],
350 mins[2] as f64 * self.transform.scale[2] + self.transform.translate[2],
351 maxs[0] as f64 * self.transform.scale[0] + self.transform.translate[0],
352 maxs[1] as f64 * self.transform.scale[1] + self.transform.translate[1],
353 maxs[2] as f64 * self.transform.scale[2] + self.transform.translate[2],
354 ];
355 }
356 }
357 }
358 pub fn update_transform(&mut self) {
359 let mut newvertices: Vec<Vec<i64>> = Vec::new();
360 let mut mins: Vec<i64> = vec![i64::MAX, i64::MAX, i64::MAX];
361 for v in &self.vertices {
363 for i in 0..3 {
364 if v[i] < mins[i] {
365 mins[i] = v[i];
366 }
367 }
368 }
369 for v in &self.vertices {
371 let v: Vec<i64> = vec![v[0] - mins[0], v[1] - mins[1], v[2] - mins[2]];
372 newvertices.push(v);
373 }
374 self.vertices = newvertices;
376 let ttx = (mins[0] as f64 * self.transform.scale[0]) + self.transform.translate[0];
378 let tty = (mins[1] as f64 * self.transform.scale[1]) + self.transform.translate[1];
379 let ttz = (mins[2] as f64 * self.transform.scale[2]) + self.transform.translate[2];
380 self.transform.translate = vec![ttx, tty, ttz];
381 }
382 pub fn number_of_city_objects(&self) -> usize {
383 let mut total: usize = 0;
384 for (_key, co) in &self.city_objects {
385 if co.is_toplevel() {
386 total += 1;
387 }
388 }
389 total
390 }
391 pub fn sort_cjfeatures(&mut self, ss: SortingStrategy) {
394 self.sorted_ids.clear();
395 match ss {
396 SortingStrategy::Random => {
397 for (key, co) in &self.city_objects {
398 if co.is_toplevel() {
399 self.sorted_ids.push(key.clone());
400 }
401 }
402 }
403 SortingStrategy::Lexicographical => {
404 for (key, co) in &self.city_objects {
405 if co.is_toplevel() {
406 self.sorted_ids.push(key.clone());
407 }
408 }
409 self.sorted_ids.sort();
410 }
411 _ => todo!(),
412 }
413 }
414 fn add_co(&mut self, id: String, co: CityObject) {
415 self.city_objects.insert(id.clone(), co);
416 }
417 fn add_vertices(&mut self, vs: &mut Vec<Vec<i64>>) {
418 if self.transform_correction.is_none() {
419 self.vertices.append(vs);
420 } else {
421 let c = self.transform_correction.as_ref().unwrap();
423 for v in vs {
424 let cx: i64 = (((v[0] as f64 * c.scale[0]) + c.translate[0]
425 - self.transform.translate[0])
426 / self.transform.scale[0])
427 .round() as i64;
428 let cy: i64 = (((v[1] as f64 * c.scale[1]) + c.translate[1]
429 - self.transform.translate[1])
430 / self.transform.scale[1])
431 .round() as i64;
432 let cz: i64 = (((v[2] as f64 * c.scale[2]) + c.translate[2]
433 - self.transform.translate[2])
434 / self.transform.scale[2])
435 .round() as i64;
436 self.vertices.push(vec![cx, cy, cz]);
437 }
438 }
439 }
440 fn add_vertices_texture(&mut self, vs: Vec<[f64; 2]>) {
441 match &mut self.appearance {
442 Some(x) => x.add_vertices_texture(vs),
443 None => {
444 let mut a: Appearance = Appearance::new();
445 a.add_vertices_texture(vs);
446 self.appearance = Some(a);
447 }
448 };
449 }
450 fn add_material(&mut self, jm: MaterialObject) -> usize {
451 let re = match &mut self.appearance {
452 Some(x) => x.add_material(jm),
453 None => {
454 let mut a: Appearance = Appearance::new();
455 let re = a.add_material(jm);
456 self.appearance = Some(a);
457 re
458 }
459 };
460 re
461 }
462 fn add_texture(&mut self, jm: TextureObject) -> usize {
463 let re = match &mut self.appearance {
464 Some(x) => x.add_texture(jm),
465 None => {
466 let mut a: Appearance = Appearance::new();
467 let re = a.add_texture(jm);
468 self.appearance = Some(a);
469 re
470 }
471 };
472 re
473 }
474}
475
476#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
477pub struct CityJSONFeature {
478 #[serde(rename = "type")]
479 pub thetype: CityJSONFeatureType,
480 pub id: String,
481 #[serde(rename = "CityObjects")]
482 pub city_objects: HashMap<String, CityObject>,
483 pub vertices: Vec<Vec<i64>>,
484 #[serde(skip_serializing_if = "Option::is_none")]
485 pub appearance: Option<Appearance>,
486}
487impl CityJSONFeature {
488 pub fn new() -> Self {
489 let co: HashMap<String, CityObject> = HashMap::new();
490 let v: Vec<Vec<i64>> = Vec::new();
491 CityJSONFeature {
492 thetype: CityJSONFeatureType::CityJSONFeature,
493 id: "".to_string(),
494 city_objects: co,
495 vertices: v,
496 appearance: None,
497 }
498 }
499 pub fn from_str(s: &str) -> Result<Self> {
500 let cjf: CityJSONFeature = serde_json::from_str(s)?;
501 Ok(cjf)
502 }
503 pub fn add_co(&mut self, id: String, co: CityObject) {
504 self.city_objects.insert(id, co);
505 }
506 pub fn centroid(&self) -> Vec<f64> {
507 let mut totals: Vec<f64> = vec![0., 0., 0.];
508 for v in &self.vertices {
509 for i in 0..3 {
510 totals[i] += v[i] as f64;
511 }
512 }
513 for i in 0..3 {
514 totals[i] /= self.vertices.len() as f64;
515 }
516 return totals;
517 }
518}
519
520pub fn cjseq_to_cj(mut base_cj: CityJSON, features: Vec<CityJSONFeature>) -> CityJSON {
523 for mut feature in features {
524 base_cj.add_cjfeature(&mut feature);
525 }
526
527 base_cj.remove_duplicate_vertices();
528 base_cj.update_transform();
529 base_cj.update_geographicalextent();
530
531 base_cj
532}
533
534#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
540pub enum CityJSONType {
541 CityJSON,
542}
543
544#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Hash)]
549pub enum CityJSONFeatureType {
550 CityJSONFeature,
551}
552
553#[cfg(test)]
554mod tests {
555 use super::*;
556
557 #[test]
560 fn cityjson_feature_with_equal_fields_is_equal() {
561 let input = serde_json::json!({
562 "type": "CityJSONFeature",
563 "id": "id-1",
564 "CityObjects": {},
565 "vertices": []
566 });
567 let a: CityJSONFeature = serde_json::from_value(input.clone()).unwrap();
568 let b: CityJSONFeature = serde_json::from_value(input).unwrap();
569 assert_eq!(a, b);
570 let mut c = b.clone();
571 c.id = "id-2".to_string();
572 assert_ne!(a, c);
573 }
574
575 #[test]
576 fn cityjson_with_equal_fields_is_equal() {
577 let a = CityJSON::new();
578 let b = CityJSON::new();
579 assert_eq!(a, b);
580 let mut c = CityJSON::new();
581 c.version = "1.1".to_string();
582 assert_ne!(a, c);
583 }
584
585 #[test]
596 fn cityjson_parsed_twice_from_the_same_string_is_equal_regardless_of_hashmap_order() {
597 let input = serde_json::json!({
598 "type": "CityJSON",
599 "version": "2.0",
600 "transform": {"scale": [1.0, 1.0, 1.0], "translate": [0.0, 0.0, 0.0]},
601 "CityObjects": {
602 "id-a": {"type": "Building"},
603 "id-b": {"type": "Building"},
604 "id-c": {"type": "Building"},
605 "id-d": {"type": "Building"},
606 "id-e": {"type": "Building"}
607 },
608 "vertices": []
609 })
610 .to_string();
611 let a = CityJSON::from_str(&input).unwrap();
612 let b = CityJSON::from_str(&input).unwrap();
613 assert_eq!(
614 a, b,
615 "the same document parsed twice must be equal, independent of internal \
616 bookkeeping order"
617 );
618 }
619
620 #[test]
621 fn cityjson_type_round_trips() {
622 let t: CityJSONType = serde_json::from_value(serde_json::json!("CityJSON")).unwrap();
623 assert_eq!(t, CityJSONType::CityJSON);
624 assert_eq!(
625 serde_json::to_value(&t).unwrap(),
626 serde_json::json!("CityJSON")
627 );
628 }
629
630 #[test]
631 fn cityjson_type_rejects_any_other_value() {
632 assert!(
633 serde_json::from_value::<CityJSONType>(serde_json::json!("CityJSONFeature")).is_err()
634 );
635 assert!(serde_json::from_value::<CityJSONType>(serde_json::json!("+CityJSON")).is_err());
636 }
637
638 #[test]
639 fn cityjson_feature_type_round_trips() {
640 let t: CityJSONFeatureType =
641 serde_json::from_value(serde_json::json!("CityJSONFeature")).unwrap();
642 assert_eq!(t, CityJSONFeatureType::CityJSONFeature);
643 assert_eq!(
644 serde_json::to_value(&t).unwrap(),
645 serde_json::json!("CityJSONFeature")
646 );
647 }
648
649 #[test]
650 fn cityjson_feature_type_rejects_any_other_value() {
651 assert!(
652 serde_json::from_value::<CityJSONFeatureType>(serde_json::json!("CityJSON")).is_err()
653 );
654 }
655}