geop_ops_model/
describe.rs1use std::collections::BTreeMap;
4
5use geop_core_math::geop_error::GeopResult;
6use geop_core_topology::{CoedgeGeometry, Sense, boundary::BoundaryType};
7use serde::{Deserialize, Serialize};
8
9use super::{NamedModel, ids::RefId};
10
11#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
15pub struct FaceDescription {
16 pub outer: Vec<String>,
17 pub holes: Vec<Vec<String>>,
18}
19
20#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
21pub struct EdgeDescription {
22 pub start: String,
23 pub end: String,
24}
25
26#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
32pub struct PartDescription {
33 pub solids: BTreeMap<String, Vec<Vec<String>>>,
35 pub faces: BTreeMap<String, FaceDescription>,
36 pub edges: BTreeMap<String, EdgeDescription>,
37 pub vertices: BTreeMap<String, [f64; 3]>,
38}
39
40impl PartDescription {
41 pub fn of(part: &NamedModel) -> GeopResult<Self> {
42 let model = part.topology();
43 let name = |id: RefId| part.name(id).map(str::to_string);
44 let describe_loop = |boundary: BoundaryType| -> GeopResult<Vec<String>> {
45 let mut entries = match boundary {
46 BoundaryType::Vertex(v) => vec![format!("@{}", name(v.into())?)],
47 BoundaryType::Loop(anchor) => model
48 .iterate_loop_coedges(anchor)
49 .map(|c| {
50 let coedge = model.get_coedge(c)?;
51 Ok(match coedge.geometry {
52 CoedgeGeometry::Edge(e) => match coedge.sense {
53 Sense::Forward => format!("+{}", name(e.into())?),
54 Sense::Reversed => format!("-{}", name(e.into())?),
55 },
56 CoedgeGeometry::Vertex(v) => format!("@{}", name(v.into())?),
57 })
58 })
59 .collect::<GeopResult<Vec<_>>>()?,
60 };
61 if let Some(first) = (0..entries.len()).min_by_key(|&i| &entries[i]) {
62 entries.rotate_left(first);
63 }
64 Ok(entries)
65 };
66
67 let mut solids = BTreeMap::new();
68 for (&id, solid) in &model.solids {
69 let shells = solid
70 .shells
71 .iter()
72 .map(|&shell| {
73 let mut faces = model
74 .get_shell(shell)?
75 .faces
76 .iter()
77 .map(|&f| name(f.into()))
78 .collect::<GeopResult<Vec<_>>>()?;
79 faces.sort();
80 Ok(faces)
81 })
82 .collect::<GeopResult<Vec<_>>>()?;
83 solids.insert(name(id.into())?, shells);
84 }
85 let mut faces = BTreeMap::new();
86 for (&id, face) in &model.faces {
87 let mut holes = face
88 .holes
89 .iter()
90 .map(|&h| describe_loop(h))
91 .collect::<GeopResult<Vec<_>>>()?;
92 holes.sort();
93 faces.insert(
94 name(id.into())?,
95 FaceDescription {
96 outer: describe_loop(face.outer)?,
97 holes,
98 },
99 );
100 }
101 let mut edges = BTreeMap::new();
102 for (&id, edge) in &model.edges {
103 edges.insert(
104 name(id.into())?,
105 EdgeDescription {
106 start: name(edge.start_vertex.into())?,
107 end: name(edge.end_vertex.into())?,
108 },
109 );
110 }
111 let mut vertices = BTreeMap::new();
112 for (&id, vertex) in &model.vertices {
113 let p = vertex.point;
114 vertices.insert(name(id.into())?, p.to_f64_array());
115 }
116 Ok(Self {
117 solids,
118 faces,
119 edges,
120 vertices,
121 })
122 }
123}