Skip to main content

axiolid_topology/
entity.rs

1//! B-rep entities. `G` is a caller-chosen curve/surface geometry handle.
2
3use axiolid_core::Point3;
4
5use crate::{EdgeId, FaceId, LoopId, ShellId, VertexId};
6
7/// Topological orientation relative to the underlying geometry.
8#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
9#[cfg_attr(
10    feature = "serde",
11    derive(serde::Serialize, serde::Deserialize),
12    serde(deny_unknown_fields)
13)]
14pub enum Orientation {
15    /// Same parameter direction/normal.
16    Forward,
17    /// Reversed parameter direction/normal.
18    Reversed,
19}
20
21/// Vertex with an explicit model-space position.
22#[derive(Debug, Clone, Copy, PartialEq)]
23#[cfg_attr(
24    feature = "serde",
25    derive(serde::Serialize, serde::Deserialize),
26    serde(deny_unknown_fields)
27)]
28pub struct Vertex {
29    /// Position.
30    pub position: Point3,
31}
32
33/// Edge bounded by two vertices and optionally supported by exact curve data.
34#[derive(Debug, Clone, PartialEq)]
35#[cfg_attr(
36    feature = "serde",
37    derive(serde::Serialize, serde::Deserialize),
38    serde(deny_unknown_fields)
39)]
40pub struct Edge<G> {
41    /// Start vertex.
42    pub start: VertexId,
43    /// End vertex.
44    pub end: VertexId,
45    /// Exact support curve handle; absent for a straight topological edge whose
46    /// endpoints are sufficient.
47    pub curve: Option<G>,
48}
49
50/// One oriented use of an edge in a loop.
51///
52/// The `pcurve` is the edge's image in the parameter space of the face this
53/// use belongs to. A 3D edge curve says where a boundary sits in model
54/// space; it does not say where that boundary lies in a surface's `(u, v)`
55/// domain, and inverting a surface to recover it is not generally solvable
56/// in closed form. Trimming a curved face therefore needs it stated, which
57/// is what exchange formats carry alongside the 3D edge curve.
58///
59/// It belongs to the USE rather than the edge: one edge bounds two faces
60/// with different support surfaces, so it has a different parameter image
61/// in each.
62#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
63#[cfg_attr(
64    feature = "serde",
65    derive(serde::Serialize, serde::Deserialize),
66    serde(deny_unknown_fields)
67)]
68pub struct EdgeUse<G> {
69    /// Referenced edge.
70    pub edge: EdgeId,
71    /// Traversal direction.
72    pub orientation: Orientation,
73    /// Optional 2D curve handle in the owning face's surface parameters.
74    pub pcurve: Option<G>,
75}
76
77/// Closed boundary wire.
78#[derive(Debug, Clone, Default, PartialEq, Eq)]
79#[cfg_attr(
80    feature = "serde",
81    derive(serde::Serialize, serde::Deserialize),
82    serde(deny_unknown_fields)
83)]
84pub struct Loop<G> {
85    /// Consecutive oriented edges.
86    pub edges: Vec<EdgeUse<G>>,
87}
88
89/// One oriented loop use on a face.
90#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
91#[cfg_attr(
92    feature = "serde",
93    derive(serde::Serialize, serde::Deserialize),
94    serde(deny_unknown_fields)
95)]
96pub struct FaceBound {
97    /// Referenced loop.
98    pub loop_id: LoopId,
99    /// Whether this bound has the same orientation as the face.
100    pub orientation: Orientation,
101    /// Whether this is the outer bound.
102    pub outer: bool,
103}
104
105/// Face supported by an exact surface and bounded by loops.
106#[derive(Debug, Clone, PartialEq)]
107#[cfg_attr(
108    feature = "serde",
109    derive(serde::Serialize, serde::Deserialize),
110    serde(deny_unknown_fields)
111)]
112pub struct Face<G> {
113    /// Exact support surface handle. Planar polygonal faces may omit it.
114    pub surface: Option<G>,
115    /// Outer and inner bounds.
116    pub bounds: Vec<FaceBound>,
117    /// Orientation relative to the support surface normal.
118    pub orientation: Orientation,
119}
120
121/// Connected collection of oriented faces.
122#[derive(Debug, Clone, Default, PartialEq, Eq)]
123#[cfg_attr(
124    feature = "serde",
125    derive(serde::Serialize, serde::Deserialize),
126    serde(deny_unknown_fields)
127)]
128pub struct Shell {
129    /// Face handles.
130    pub faces: Vec<(FaceId, Orientation)>,
131    /// Whether the source asserts closure.
132    pub closed: bool,
133}
134
135/// Solid with one outer shell and optional void shells.
136#[derive(Debug, Clone, PartialEq, Eq)]
137#[cfg_attr(
138    feature = "serde",
139    derive(serde::Serialize, serde::Deserialize),
140    serde(deny_unknown_fields)
141)]
142pub struct Solid {
143    /// Outer shell.
144    pub outer: ShellId,
145    /// Interior void shells.
146    pub voids: Vec<ShellId>,
147}