Skip to main content

geop_core_topology/model/
get.rs

1use crate::{
2    Coedge, CoedgeGeometry, CoedgeId, Edge, EdgeId, Face, FaceId, Sense, Shell, ShellId, Solid,
3    SolidId, Vertex, VertexId, WireId,
4};
5use geop_core_math::{
6    geop_error::{GeopError, GeopResult},
7    vector::Vector3,
8};
9
10use super::Model;
11
12impl Model {
13    pub fn get_vertex(&self, id: VertexId) -> GeopResult<&Vertex> {
14        self.vertices
15            .get(&id)
16            .ok_or_else(|| GeopError::new(format!("vertex with id {} does not exist", id.0)))
17    }
18
19    pub fn get_vertex_mut(&mut self, id: VertexId) -> GeopResult<&mut Vertex> {
20        self.vertices
21            .get_mut(&id)
22            .ok_or_else(|| GeopError::new(format!("vertex with id {} does not exist", id.0)))
23    }
24
25    pub fn get_edge(&self, id: EdgeId) -> GeopResult<&Edge> {
26        self.edges
27            .get(&id)
28            .ok_or_else(|| GeopError::new(format!("edge with id {} does not exist", id.0)))
29    }
30
31    pub fn get_edge_mut(&mut self, id: EdgeId) -> GeopResult<&mut Edge> {
32        self.edges
33            .get_mut(&id)
34            .ok_or_else(|| GeopError::new(format!("edge with id {} does not exist", id.0)))
35    }
36
37    pub fn get_coedge(&self, id: CoedgeId) -> GeopResult<&Coedge> {
38        self.coedges
39            .get(&id)
40            .ok_or_else(|| GeopError::new(format!("coedge with id {} does not exist", id.0)))
41    }
42
43    pub fn get_coedge_mut(&mut self, id: CoedgeId) -> GeopResult<&mut Coedge> {
44        self.coedges
45            .get_mut(&id)
46            .ok_or_else(|| GeopError::new(format!("coedge with id {} does not exist", id.0)))
47    }
48
49    pub fn get_face(&self, id: FaceId) -> GeopResult<&Face> {
50        self.faces
51            .get(&id)
52            .ok_or_else(|| GeopError::new(format!("face with id {} does not exist", id.0)))
53    }
54
55    pub fn get_face_mut(&mut self, id: FaceId) -> GeopResult<&mut Face> {
56        self.faces
57            .get_mut(&id)
58            .ok_or_else(|| GeopError::new(format!("face with id {} does not exist", id.0)))
59    }
60
61    pub fn get_shell(&self, id: ShellId) -> GeopResult<&Shell> {
62        self.shells
63            .get(&id)
64            .ok_or_else(|| GeopError::new(format!("shell with id {} does not exist", id.0)))
65    }
66
67    pub fn get_shell_mut(&mut self, id: ShellId) -> GeopResult<&mut Shell> {
68        self.shells
69            .get_mut(&id)
70            .ok_or_else(|| GeopError::new(format!("shell with id {} does not exist", id.0)))
71    }
72
73    pub fn get_solid(&self, id: SolidId) -> GeopResult<&Solid> {
74        self.solids
75            .get(&id)
76            .ok_or_else(|| GeopError::new(format!("solid with id {} does not exist", id.0)))
77    }
78
79    pub fn get_solid_mut(&mut self, id: SolidId) -> GeopResult<&mut Solid> {
80        self.solids
81            .get_mut(&id)
82            .ok_or_else(|| GeopError::new(format!("solid with id {} does not exist", id.0)))
83    }
84
85    /// The wire `edge` is an edge of, if any.
86    pub fn wire_of_edge(&self, edge: EdgeId) -> Option<WireId> {
87        self.wires
88            .iter()
89            .find(|(_, w)| w.edges.contains(&edge))
90            .map(|(&id, _)| id)
91    }
92
93    pub fn coedge_start_vertex_id(&self, coedge: CoedgeId) -> GeopResult<VertexId> {
94        let coedge = self.get_coedge(coedge)?;
95        match coedge.geometry {
96            CoedgeGeometry::Edge(edge_id) => {
97                let edge = self.get_edge(edge_id)?;
98                Ok(match coedge.sense {
99                    Sense::Forward => edge.start_vertex,
100                    Sense::Reversed => edge.end_vertex,
101                })
102            }
103            // Degenerate: sits at one vertex the whole way, so "start" and
104            // "end" are the same.
105            CoedgeGeometry::Vertex(vertex_id) => Ok(vertex_id),
106        }
107    }
108
109    pub fn coedge_start_vertex(&self, coedge: CoedgeId) -> GeopResult<&Vertex> {
110        let vertex_id = self.coedge_start_vertex_id(coedge)?;
111        self.get_vertex(vertex_id)
112    }
113
114    pub fn coedge_end_vertex_id(&self, coedge: CoedgeId) -> GeopResult<VertexId> {
115        let coedge = self.get_coedge(coedge)?;
116        match coedge.geometry {
117            CoedgeGeometry::Edge(edge_id) => {
118                let edge = self.get_edge(edge_id)?;
119                Ok(match coedge.sense {
120                    Sense::Forward => edge.end_vertex,
121                    Sense::Reversed => edge.start_vertex,
122                })
123            }
124            CoedgeGeometry::Vertex(vertex_id) => Ok(vertex_id),
125        }
126    }
127
128    pub fn coedge_end_vertex(&self, coedge: CoedgeId) -> GeopResult<&Vertex> {
129        let vertex_id = self.coedge_end_vertex_id(coedge)?;
130        self.get_vertex(vertex_id)
131    }
132
133    /// The unit normal of `face`'s surface at its own vertex `vertex`: at
134    /// the `(u, v)` its loop gives the vertex — where a coedge of it
135    /// starting there starts — not at one searched for by the vertex's
136    /// point. Where the patch's parametrization degenerates at the vertex —
137    /// a SubD patch whose two sides leave its corner along one line — a
138    /// whole valley of `(u, v)` lies within a search's reach of the point,
139    /// and the search runs out of nodes; the loop knows which `(u, v)` it
140    /// is. An error if no coedge of the face starts there.
141    pub fn normal_at_vertex(&self, face: FaceId, vertex: VertexId) -> GeopResult<Vector3> {
142        for coedge in self.iterate_face_coedges(face) {
143            if self.coedge_start_vertex_id(coedge)? != vertex {
144                continue;
145            }
146            let pcurve = &self.get_coedge(coedge)?.pcurve;
147            let uv = pcurve.evaluate(pcurve.domain().0)?;
148            return self.get_face(face)?.surface.normal(uv[0], uv[1]);
149        }
150        Err(GeopError::new(format!(
151            "no coedge of face {face} starts at vertex {vertex}: it is no vertex of the face"
152        )))
153    }
154}