axiolid-model 0.3.5

Format-neutral geometry item tree. The currency between a format reader and a kernel.
Documentation
//! Surface relationships that compose curve and surface nodes.

use axiolid_core::{Scalar, Vec3};

use crate::{NodeId, SectionAtStation, StationFrame, StationedOpenSection};

/// Relationship between surface nodes.
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub enum SurfaceRelation {
    /// Surface bounded by oriented curve nodes.
    CurveBounded {
        basis: NodeId,
        boundaries: Vec<NodeId>,
        implicit_outer: bool,
    },
    /// Rectangular parameter-space trim.
    RectangularTrimmed {
        basis: NodeId,
        u: (Scalar, Scalar),
        v: (Scalar, Scalar),
        u_sense: bool,
        v_sense: bool,
    },
    /// Constant-distance offset surface.
    Offset {
        basis: NodeId,
        distance: Scalar,
        self_intersect: Option<bool>,
    },
    /// Surface generated by translating a curve.
    LinearExtrusion {
        swept_curve: NodeId,
        direction: Vec3,
    },
    /// Surface generated by revolving a curve around an axis.
    Revolution {
        swept_curve: NodeId,
        axis_origin: axiolid_core::Point3,
        axis_direction: Vec3,
    },
    /// Open sections standing at stations along a directrix, joined by tag
    /// (#241).
    ///
    /// Each section's open polyline is placed in the directrix's `frame` at
    /// its station (profile `x` to the lateral axis, `y` to up; see
    /// [`crate::station`]). Between two stations, points with equal tags
    /// are joined and interpolated linearly in distance, as are the
    /// offsets. At least two sections, strictly increasing in distance,
    /// with one tag sequence (or none) are required.
    SectionedSurface {
        directrix: NodeId,
        sections: Vec<StationedOpenSection>,
        frame: StationFrame,
    },
    /// Open sections standing at stations along a directrix, each
    /// optionally explicitly oriented (#246): the general form of
    /// [`SurfaceRelation::SectionedSurface`].
    ///
    /// Each section's open polyline is placed as in a `SectionedSurface`,
    /// its plane turned by the section's orientation. Sections are joined
    /// by tag, or by index when none is tagged (see [`crate::station`]).
    /// At least two sections, strictly increasing in distance, all tagged
    /// or none, are required.
    OpenSectionsAtStations {
        directrix: NodeId,
        sections: Vec<SectionAtStation>,
        frame: StationFrame,
    },
}

impl SurfaceRelation {
    pub(crate) fn references(&self, out: &mut Vec<NodeId>) {
        match self {
            Self::CurveBounded {
                basis, boundaries, ..
            } => {
                out.push(*basis);
                out.extend(boundaries.iter().copied());
            }
            Self::RectangularTrimmed { basis, .. } | Self::Offset { basis, .. } => out.push(*basis),
            Self::LinearExtrusion { swept_curve, .. } | Self::Revolution { swept_curve, .. } => {
                out.push(*swept_curve)
            }
            Self::SectionedSurface {
                directrix,
                sections,
                ..
            } => {
                out.push(*directrix);
                out.extend(sections.iter().map(|section| section.profile));
            }
            Self::OpenSectionsAtStations {
                directrix,
                sections,
                ..
            } => {
                out.push(*directrix);
                out.extend(sections.iter().map(|section| section.profile));
            }
        }
    }
}