1use serde::Serialize;
2
3use crate::proto::{MapObject, SceneMap};
4
5#[derive(Serialize)]
9pub struct FeatureCollection {
10 #[serde(rename = "type")]
11 kind: &'static str,
12 updated_at: f64,
13 features: Vec<Feature>,
14}
15
16#[derive(Serialize)]
17struct Feature {
18 #[serde(rename = "type")]
19 kind: &'static str,
20 geometry: Geometry,
21 properties: Properties,
22}
23
24#[derive(Serialize)]
25struct Geometry {
26 #[serde(rename = "type")]
27 kind: &'static str,
28 coordinates: [f32; 2],
29}
30
31#[derive(Serialize)]
32struct Properties {
33 id: String,
34 label: String,
35 confidence: f32,
36 observation_count: i32,
37 first_seen: f64,
38 last_seen: f64,
39}
40
41impl SceneMap {
42 pub fn to_geojson(&self) -> FeatureCollection {
43 FeatureCollection {
44 kind: "FeatureCollection",
45 updated_at: self.updated_at,
46 features: self.objects.iter().map(Feature::from).collect(),
47 }
48 }
49
50 pub fn to_geojson_json(&self) -> serde_json::Result<String> {
51 serde_json::to_string_pretty(&self.to_geojson())
52 }
53}
54
55impl From<&MapObject> for Feature {
56 fn from(obj: &MapObject) -> Self {
57 Feature {
58 kind: "Feature",
59 geometry: Geometry { kind: "Point", coordinates: [obj.x, obj.y] },
60 properties: Properties {
61 id: obj.id.clone(),
62 label: obj.label.clone(),
63 confidence: obj.confidence,
64 observation_count: obj.observation_count,
65 first_seen: obj.first_seen,
66 last_seen: obj.last_seen,
67 },
68 }
69 }
70}
71
72#[cfg(test)]
73mod tests {
74 use super::*;
75
76 fn sample_map() -> SceneMap {
77 SceneMap {
78 objects: vec![MapObject {
79 id: "abc-123".to_string(),
80 label: "chair".to_string(),
81 x: 1.5,
82 y: -2.5,
83 confidence: 0.87,
84 observation_count: 3,
85 first_seen: 10.0,
86 last_seen: 12.5,
87 }],
88 updated_at: 12.5,
89 }
90 }
91
92 #[test]
93 fn converts_map_objects_to_point_features() {
94 let fc = sample_map().to_geojson();
95 assert_eq!(fc.features.len(), 1);
96 assert_eq!(fc.features[0].geometry.coordinates, [1.5, -2.5]);
97 assert_eq!(fc.features[0].properties.label, "chair");
98 }
99
100 #[test]
101 fn serializes_to_valid_geojson_shaped_json() {
102 let json = sample_map().to_geojson_json().unwrap();
103 let value: serde_json::Value = serde_json::from_str(&json).unwrap();
104
105 assert_eq!(value["type"], "FeatureCollection");
106 assert_eq!(value["features"][0]["type"], "Feature");
107 assert_eq!(value["features"][0]["geometry"]["type"], "Point");
108 assert_eq!(value["features"][0]["geometry"]["coordinates"][0], 1.5);
109 assert_eq!(value["features"][0]["properties"]["id"], "abc-123");
110 }
111}