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