geop_core_part/
resolve.rs1use geop_core_math::{
5 geop_error::{GeopError, GeopResult},
6 scalars::Scalar,
7};
8use geop_core_topology::{CoedgeId, EdgeId, FaceId, Sense, SolidId, VertexId};
9
10use crate::ids::{DatumId, RefId, SketchId};
11use crate::part::Part;
12
13impl<S: Scalar> Part<S> {
14 fn named<T>(
16 &self,
17 name: &str,
18 kind: &str,
19 extract: impl Fn(RefId) -> Option<T>,
20 ) -> GeopResult<T> {
21 let id = self
22 .names
23 .id_of(name)
24 .ok_or_else(|| GeopError::new(format!("no entity is named {name:?}")))?;
25 extract(id).ok_or_else(|| GeopError::new(format!("{name:?} names {id}, not a {kind}")))
26 }
27
28 pub fn vertex_id(&self, name: &str) -> GeopResult<VertexId> {
29 self.named(name, "vertex", |r| match r {
30 RefId::Vertex(id) => Some(id),
31 _ => None,
32 })
33 }
34
35 pub fn edge_id(&self, name: &str) -> GeopResult<EdgeId> {
36 self.named(name, "edge", |r| match r {
37 RefId::Edge(id) => Some(id),
38 _ => None,
39 })
40 }
41
42 pub fn face_id(&self, name: &str) -> GeopResult<FaceId> {
43 self.named(name, "face", |r| match r {
44 RefId::Face(id) => Some(id),
45 _ => None,
46 })
47 }
48
49 pub fn solid_id(&self, name: &str) -> GeopResult<SolidId> {
50 self.named(name, "solid", |r| match r {
51 RefId::Solid(id) => Some(id),
52 _ => None,
53 })
54 }
55
56 pub fn sketch_id(&self, name: &str) -> GeopResult<SketchId> {
57 self.named(name, "sketch", |r| match r {
58 RefId::Sketch(id) => Some(id),
59 _ => None,
60 })
61 }
62
63 pub fn datum_id(&self, name: &str) -> GeopResult<DatumId> {
64 self.named(name, "datum", |r| match r {
65 RefId::Datum(id) => Some(id),
66 _ => None,
67 })
68 }
69
70 pub fn coedge_id(&self, edge_name: &str, face_name: &str) -> GeopResult<CoedgeId> {
78 let edge = self.edge_id(edge_name)?;
79 let face = self.face_id(face_name)?;
80 let mut on_face = self
81 .topology
82 .coedges_of_edge(edge)
83 .into_iter()
84 .filter(|&c| {
85 self.topology
86 .get_coedge(c)
87 .map(|co| co.face == face)
88 .unwrap_or(false)
89 });
90 let found = on_face.next().ok_or_else(|| {
91 GeopError::new(format!(
92 "edge {edge_name:?} has no coedge on face {face_name:?}"
93 ))
94 })?;
95 if on_face.next().is_some() {
96 return Err(GeopError::new(format!(
97 "edge {edge_name:?} has more than one coedge on face {face_name:?} — use coedge_id_with_sense to disambiguate"
98 )));
99 }
100 Ok(found)
101 }
102
103 pub fn coedge_id_with_sense(
108 &self,
109 edge_name: &str,
110 face_name: &str,
111 sense: Sense,
112 ) -> GeopResult<CoedgeId> {
113 let edge = self.edge_id(edge_name)?;
114 let face = self.face_id(face_name)?;
115 self.topology
116 .coedges_of_edge(edge)
117 .into_iter()
118 .find(|&c| {
119 self.topology
120 .get_coedge(c)
121 .map(|co| co.face == face && co.sense == sense)
122 .unwrap_or(false)
123 })
124 .ok_or_else(|| {
125 GeopError::new(format!(
126 "edge {edge_name:?} has no {sense:?} coedge on face {face_name:?}"
127 ))
128 })
129 }
130}