axiolid_model/node.rs
1//! Closed set of format-neutral graph node families.
2
3use axiolid_core::{Aabb, Frame2, Frame3, Point2, Point3, Scalar, Transform3, Vec2, Vec3};
4use axiolid_curve::{Curve2, Curve3};
5use axiolid_mesh::{PolygonMesh, TriMesh};
6use axiolid_primitive::{HalfSpace, Primitive};
7use axiolid_profile::Profile;
8use axiolid_surface::Surface;
9use axiolid_topology::BRep;
10
11use crate::{
12 CurveRelation, CurveStation, NodeId, OrientedCurveStation, SolidOperation, SurfaceRelation,
13};
14
15/// Point constrained to a curve parameter.
16#[derive(Debug, Clone, Copy, PartialEq)]
17pub struct PointOnCurve {
18 /// Basis curve.
19 pub curve: NodeId,
20 /// Curve parameter.
21 pub parameter: Scalar,
22}
23
24/// Point constrained to surface parameters.
25#[derive(Debug, Clone, Copy, PartialEq)]
26pub struct PointOnSurface {
27 /// Basis surface.
28 pub surface: NodeId,
29 /// First parameter.
30 pub u: Scalar,
31 /// Second parameter.
32 pub v: Scalar,
33}
34
35/// Source-authored bounded open two-dimensional profile path.
36///
37/// This declaration preserves exact curve intent while carrying no area, width,
38/// closure edge, or evaluation instruction. Graph construction conservatively
39/// admits only known bounded-open forms, including finite source-open
40/// polylines, structurally valid finite B-splines, finite 2D trims with no
41/// exactly equal authored endpoints, and recursively valid relation chains.
42/// Endpoint inequality across arbitrary relations still requires geometric
43/// evaluation.
44#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
45pub struct OpenProfile {
46 /// Exact two-dimensional curve or curve relation authored as the path.
47 pub path: NodeId,
48}
49
50impl OpenProfile {
51 /// Declare `path` as a bounded open profile without implying area or width.
52 pub const fn new(path: NodeId) -> Self {
53 Self { path }
54 }
55}
56
57/// Reuse one graph node under a transform, preserving instancing.
58#[derive(Debug, Clone, Copy, PartialEq)]
59pub struct Instance {
60 /// Reused source node.
61 pub source: NodeId,
62 /// Local-to-parent transform.
63 pub transform: Transform3,
64}
65
66/// One node in an immutable geometry DAG.
67///
68/// The enum is non-exhaustive so representation growth is semver-compatible.
69/// Compilers must turn unknown/unsupported families into a structured
70/// `Unsupported` result rather than a wildcard no-op.
71#[non_exhaustive]
72#[derive(Debug, Clone, PartialEq)]
73pub enum GeometryNode {
74 /// Two-dimensional position.
75 Point2(Point2),
76 /// Three-dimensional position.
77 Point3(Point3),
78 /// Two-dimensional direction/vector.
79 Vector2(Vec2),
80 /// Three-dimensional direction/vector.
81 Vector3(Vec3),
82 /// Two-dimensional axis placement.
83 Frame2(Frame2),
84 /// Three-dimensional axis placement.
85 Frame3(Frame3),
86 /// Composed affine transform.
87 Transform(Transform3),
88 /// Dense two-dimensional point list.
89 PointList2(Vec<Point2>),
90 /// Dense three-dimensional point list.
91 PointList3(Vec<Point3>),
92 /// Atomic two-dimensional curve.
93 Curve2(Curve2),
94 /// Atomic three-dimensional curve.
95 Curve3(Curve3),
96 /// Curve composition/constraint.
97 CurveRelation(CurveRelation),
98 /// Point on a curve.
99 PointOnCurve(PointOnCurve),
100 /// Atomic surface.
101 Surface(Surface),
102 /// Surface composition/constraint.
103 SurfaceRelation(SurfaceRelation),
104 /// Point on a surface.
105 PointOnSurface(PointOnSurface),
106 /// Exact section profile with area semantics.
107 Profile(Profile),
108 /// Authored exact open profile path without area or width semantics.
109 OpenProfile(OpenProfile),
110 /// Exact primitive solid.
111 Primitive(Primitive),
112 /// Unbounded half-space.
113 HalfSpace(HalfSpace),
114 /// Solid construction instruction.
115 SolidOperation(SolidOperation),
116 /// Exact topological representation linked to graph curve/surface nodes.
117 BRep(BRep<NodeId>),
118 /// Polygonal n-gon mesh before triangulation.
119 PolygonMesh(PolygonMesh),
120 /// Triangle mesh.
121 TriMesh(TriMesh),
122 /// Axis-aligned bounds.
123 BoundingBox(Aabb),
124 /// Instanced/mapped geometry.
125 Instance(Instance),
126 /// Ordered geometric set or representation.
127 Collection(Vec<NodeId>),
128 /// A point and frame at a distance along a basis curve, offset in its
129 /// section frame (#241). See [`crate::station`].
130 CurveStation(CurveStation),
131 /// A curve station with an explicit in-section orientation (#246). See
132 /// [`crate::station`].
133 OrientedCurveStation(OrientedCurveStation),
134}
135
136impl GeometryNode {
137 /// Direct graph dependencies in deterministic order.
138 pub fn references(&self) -> Vec<NodeId> {
139 let mut references = Vec::new();
140 match self {
141 Self::CurveRelation(value) => value.references(&mut references),
142 Self::PointOnCurve(value) => references.push(value.curve),
143 Self::SurfaceRelation(value) => value.references(&mut references),
144 Self::PointOnSurface(value) => references.push(value.surface),
145 Self::OpenProfile(value) => references.push(value.path),
146 Self::SolidOperation(value) => value.references(&mut references),
147 Self::BRep(value) => {
148 references.extend(value.edges().iter().filter_map(|edge| edge.curve));
149 // Pcurves are graph references too: omitting them here would
150 // let a referenced trim curve be pruned as unreachable.
151 references.extend(
152 value
153 .loops()
154 .iter()
155 .flat_map(|wire| wire.edges.iter())
156 .filter_map(|use_| use_.pcurve),
157 );
158 references.extend(value.faces().iter().filter_map(|face| face.surface));
159 }
160 Self::Instance(value) => references.push(value.source),
161 Self::Collection(values) => references.extend(values.iter().copied()),
162 Self::CurveStation(value) => references.push(value.basis),
163 Self::OrientedCurveStation(value) => references.push(value.station.basis),
164 Self::Point2(_)
165 | Self::Point3(_)
166 | Self::Vector2(_)
167 | Self::Vector3(_)
168 | Self::Frame2(_)
169 | Self::Frame3(_)
170 | Self::Transform(_)
171 | Self::PointList2(_)
172 | Self::PointList3(_)
173 | Self::Curve2(_)
174 | Self::Curve3(_)
175 | Self::Surface(_)
176 | Self::Profile(_)
177 | Self::Primitive(_)
178 | Self::HalfSpace(_)
179 | Self::PolygonMesh(_)
180 | Self::TriMesh(_)
181 | Self::BoundingBox(_) => {}
182 }
183 references
184 }
185}