1use crate::{
2 Arrow, BoundingBox, Cylinder, Graph, Line, Mesh, Objects, Plane, Point, PointCloud, Polyline,
3 Tree, TreeNode,
4};
5use serde::{Deserialize, Serialize};
6use std::collections::HashMap;
7use std::fmt;
8use std::fs;
9use uuid::Uuid;
10
11#[derive(Debug, Clone)]
14pub enum Geometry {
15 Arrow(Arrow),
16 BoundingBox(BoundingBox),
17 Cylinder(Cylinder),
18 Line(Line),
19 Mesh(Mesh),
20 Plane(Plane),
21 Point(Point),
22 PointCloud(PointCloud),
23 Polyline(Polyline),
24}
25
26impl Geometry {
27 pub fn guid(&self) -> &str {
29 match self {
30 Geometry::Arrow(g) => &g.guid,
31 Geometry::BoundingBox(g) => &g.guid,
32 Geometry::Cylinder(g) => &g.guid,
33 Geometry::Line(g) => &g.guid,
34 Geometry::Mesh(g) => &g.guid,
35 Geometry::Plane(g) => &g.guid,
36 Geometry::Point(g) => &g.guid,
37 Geometry::PointCloud(g) => &g.guid,
38 Geometry::Polyline(g) => &g.guid,
39 }
40 }
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize)]
49#[serde(tag = "type", rename = "Session")]
50pub struct Session {
51 pub guid: String,
53 pub name: String,
55 #[serde(rename = "objects")]
57 pub objects: Objects,
58 #[serde(skip)]
60 pub lookup: HashMap<String, Geometry>,
61 #[serde(rename = "tree")]
63 pub tree: Tree,
64 #[serde(rename = "graph")]
66 pub graph: Graph,
67}
68
69impl Default for Session {
70 fn default() -> Self {
72 Self::new("my_session")
73 }
74}
75
76impl Session {
77 pub fn new(name: &str) -> Self {
86 let guid = Uuid::new_v4().to_string();
87 let objects = Objects::new();
88 let lookup = HashMap::new();
89 let mut tree = Tree::new(&format!("{name}_tree"));
90 let graph = Graph::new(&format!("{name}_graph"));
91
92 let root_node = TreeNode::new(name);
94 tree.add(&root_node, None);
95
96 Self {
97 guid,
98 name: name.to_string(),
99 objects,
100 lookup,
101 tree,
102 graph,
103 }
104 }
105
106 pub fn jsondump(&self) -> Result<String, Box<dyn std::error::Error>> {
116 let graph_json: serde_json::Value = serde_json::from_str(&self.graph.jsondump()?)?;
119
120 let json_obj = serde_json::json!({
121 "type": "Session",
122 "guid": self.guid,
123 "name": self.name,
124 "objects": self.objects,
125 "tree": self.tree,
126 "graph": graph_json
127 });
128
129 Ok(serde_json::to_string_pretty(&json_obj)?)
130 }
131
132 pub fn jsonload(json_data: &str) -> Result<Self, Box<dyn std::error::Error>> {
140 let json_obj: serde_json::Value = serde_json::from_str(json_data)?;
141
142 let objects: Objects = serde_json::from_value(json_obj["objects"].clone())?;
144 let tree: Tree = serde_json::from_value(json_obj["tree"].clone())?;
145 let graph_json_str = serde_json::to_string(&json_obj["graph"])?;
147 let graph: Graph = Graph::jsonload(&graph_json_str)?;
148
149 let mut lookup = HashMap::new();
151 for arrow in &objects.arrows {
152 lookup.insert(arrow.guid.clone(), Geometry::Arrow(arrow.clone()));
153 }
154 for bbox in &objects.bboxes {
155 lookup.insert(bbox.guid.clone(), Geometry::BoundingBox(bbox.clone()));
156 }
157 for cylinder in &objects.cylinders {
158 lookup.insert(cylinder.guid.clone(), Geometry::Cylinder(cylinder.clone()));
159 }
160 for line in &objects.lines {
161 lookup.insert(line.guid.clone(), Geometry::Line(line.clone()));
162 }
163 for mesh in &objects.meshes {
164 lookup.insert(mesh.guid.clone(), Geometry::Mesh(mesh.clone()));
165 }
166 for plane in &objects.planes {
167 lookup.insert(plane.guid.clone(), Geometry::Plane(plane.clone()));
168 }
169 for point in &objects.points {
170 lookup.insert(point.guid.clone(), Geometry::Point(point.clone()));
171 }
172 for pointcloud in &objects.pointclouds {
173 lookup.insert(
174 pointcloud.guid.clone(),
175 Geometry::PointCloud(pointcloud.clone()),
176 );
177 }
178 for polyline in &objects.polylines {
179 lookup.insert(polyline.guid.clone(), Geometry::Polyline(polyline.clone()));
180 }
181
182 let session = Session {
183 guid: json_obj["guid"].as_str().unwrap_or("").to_string(),
184 name: json_obj["name"]
185 .as_str()
186 .unwrap_or("my_session")
187 .to_string(),
188 objects,
189 lookup,
190 tree,
191 graph,
192 };
193
194 Ok(session)
195 }
196
197 pub fn to_json(&self, filepath: &str) -> Result<(), Box<dyn std::error::Error>> {
205 let json = self.jsondump()?;
206 fs::write(filepath, json)?;
207 Ok(())
208 }
209
210 pub fn from_json(filepath: &str) -> Result<Self, Box<dyn std::error::Error>> {
218 let json = fs::read_to_string(filepath)?;
219 Self::jsonload(&json)
220 }
221
222 pub fn add_point(&mut self, point: Point) -> TreeNode {
237 let point_guid = point.guid.clone();
238 let point_name = point.name.clone();
239 self.objects.points.push(point.clone());
240 self.lookup
241 .insert(point_guid.clone(), Geometry::Point(point));
242 self.graph
243 .add_node(&point_guid, &format!("point_{point_name}"));
244 TreeNode::new(&point_guid)
245 }
246
247 pub fn add_line(&mut self, line: Line) -> TreeNode {
248 let guid = line.guid.clone();
249 let name = line.name.clone();
250 self.objects.lines.push(line.clone());
251 self.lookup.insert(guid.clone(), Geometry::Line(line));
252 self.graph.add_node(&guid, &format!("line_{name}"));
253 TreeNode::new(&guid)
254 }
255
256 pub fn add_plane(&mut self, plane: Plane) -> TreeNode {
257 let guid = plane.guid.clone();
258 let name = plane.name.clone();
259 self.objects.planes.push(plane.clone());
260 self.lookup.insert(guid.clone(), Geometry::Plane(plane));
261 self.graph.add_node(&guid, &format!("plane_{name}"));
262 TreeNode::new(&guid)
263 }
264
265 pub fn add_bbox(&mut self, bbox: BoundingBox) -> TreeNode {
266 let guid = bbox.guid.clone();
267 let name = bbox.name.clone();
268 self.objects.bboxes.push(bbox.clone());
269 self.lookup
270 .insert(guid.clone(), Geometry::BoundingBox(bbox));
271 self.graph.add_node(&guid, &format!("bbox_{name}"));
272 TreeNode::new(&guid)
273 }
274
275 pub fn add_polyline(&mut self, polyline: Polyline) -> TreeNode {
276 let guid = polyline.guid.clone();
277 let name = polyline.name.clone();
278 self.objects.polylines.push(polyline.clone());
279 self.lookup
280 .insert(guid.clone(), Geometry::Polyline(polyline));
281 self.graph.add_node(&guid, &format!("polyline_{name}"));
282 TreeNode::new(&guid)
283 }
284
285 pub fn add_pointcloud(&mut self, pointcloud: PointCloud) -> TreeNode {
286 let guid = pointcloud.guid.clone();
287 let name = pointcloud.name.clone();
288 self.objects.pointclouds.push(pointcloud.clone());
289 self.lookup
290 .insert(guid.clone(), Geometry::PointCloud(pointcloud));
291 self.graph.add_node(&guid, &format!("pointcloud_{name}"));
292 TreeNode::new(&guid)
293 }
294
295 pub fn add_mesh(&mut self, mesh: Mesh) -> TreeNode {
296 let guid = mesh.guid.clone();
297 let name = mesh.name.clone();
298 self.objects.meshes.push(mesh.clone());
299 self.lookup.insert(guid.clone(), Geometry::Mesh(mesh));
300 self.graph.add_node(&guid, &format!("mesh_{name}"));
301 TreeNode::new(&guid)
302 }
303
304 pub fn add_cylinder(&mut self, cylinder: Cylinder) -> TreeNode {
305 let guid = cylinder.guid.clone();
306 let name = cylinder.name.clone();
307 self.objects.cylinders.push(cylinder.clone());
308 self.lookup
309 .insert(guid.clone(), Geometry::Cylinder(cylinder));
310 self.graph.add_node(&guid, &format!("cylinder_{name}"));
311 TreeNode::new(&guid)
312 }
313
314 pub fn add_arrow(&mut self, arrow: Arrow) -> TreeNode {
315 let guid = arrow.guid.clone();
316 let name = arrow.name.clone();
317 self.objects.arrows.push(arrow.clone());
318 self.lookup.insert(guid.clone(), Geometry::Arrow(arrow));
319 self.graph.add_node(&guid, &format!("arrow_{name}"));
320 TreeNode::new(&guid)
321 }
322
323 pub fn add<'a>(&mut self, node: &TreeNode, parent: impl Into<Option<&'a TreeNode>>)
345 where
346 TreeNode: 'a,
347 {
348 let parent_opt = parent.into();
349 if parent_opt.is_none() {
350 if let Some(root) = self.tree.root() {
351 self.tree.add(node, Some(&root));
352 }
353 } else {
354 self.tree.add(node, parent_opt);
355 }
356 }
357
358 pub fn add_edge(&mut self, from_guid: &str, to_guid: &str, attribute: &str) {
365 self.graph.add_edge(from_guid, to_guid, attribute);
366 }
367
368 pub fn get_object(&self, guid: &str) -> Option<&Geometry> {
380 self.lookup.get(guid)
381 }
382
383 pub fn remove_object(&mut self, guid: &str) -> bool {
391 if !self.lookup.contains_key(guid) {
393 return false;
394 }
395
396 self.objects.points.retain(|point| point.guid != guid);
399
400 self.lookup.remove(guid);
402
403 if let Some(node) = self.tree.find_node_by_guid(&guid.to_string()) {
405 self.tree.remove(&node);
406 }
407
408 if self.graph.has_node(guid) {
410 self.graph.remove_node(guid);
411 }
412
413 true
414 }
415
416 pub fn add_hierarchy(&mut self, parent_guid: &str, child_guid: &str) -> bool {
429 self.tree
430 .add_child_by_guid(&parent_guid.to_string(), &child_guid.to_string())
431 }
432
433 pub fn get_children(&self, guid: &str) -> Vec<String> {
441 self.tree.get_children(guid)
442 }
443
444 pub fn add_relationship(&mut self, from_guid: &str, to_guid: &str, relationship_type: &str) {
455 self.graph.add_edge(from_guid, to_guid, relationship_type);
456 }
457
458 pub fn get_neighbours(&self, guid: &str) -> Vec<String> {
466 self.graph.get_neighbors(guid)
467 }
468}
469
470impl fmt::Display for Session {
471 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
472 write!(
473 f,
474 "Session({}, {}, points={}, vertices={}, edges={})",
475 self.name,
476 self.guid,
477 self.objects.points.len(),
478 self.graph.vertex_count,
479 self.graph.edge_count
480 )
481 }
482}
483
484#[cfg(test)]
485#[path = "session_test.rs"]
486mod session_test;