Skip to main content

axiolid_profile/
contour.rs

1//! Arbitrary closed contours.
2
3use axiolid_core::Interval;
4use axiolid_curve::Curve2;
5
6/// One bounded oriented curve segment.
7#[derive(Debug, Clone, PartialEq)]
8#[cfg_attr(
9    feature = "serde",
10    derive(serde::Serialize, serde::Deserialize),
11    serde(deny_unknown_fields)
12)]
13pub struct ProfileSegment {
14    /// Exact supporting curve.
15    pub curve: Curve2,
16    /// Parameter interval on `curve`.
17    ///
18    /// Always a finite span: a contour edge is bounded, so an unbounded
19    /// support such as a line contributes only this interval, never itself.
20    pub domain: Interval,
21    /// Whether parameter direction follows contour orientation.
22    pub same_sense: bool,
23}
24
25/// One oriented closed contour assembled from bounded exact curve segments.
26#[derive(Debug, Clone, Default, PartialEq)]
27#[cfg_attr(
28    feature = "serde",
29    derive(serde::Serialize, serde::Deserialize),
30    serde(deny_unknown_fields)
31)]
32pub struct Contour {
33    /// Consecutive bounded segments; closure is validated separately.
34    pub segments: Vec<ProfileSegment>,
35}
36
37impl Contour {
38    /// Construct from oriented segments without silently repairing gaps.
39    pub fn new(segments: Vec<ProfileSegment>) -> Self {
40        Self { segments }
41    }
42
43    /// Number of exact segments.
44    pub fn len(&self) -> usize {
45        self.segments.len()
46    }
47
48    /// Whether this contour has no segments.
49    pub fn is_empty(&self) -> bool {
50        self.segments.is_empty()
51    }
52}
53
54/// Closed outer contour and zero or more closed holes.
55#[derive(Debug, Clone, Default, PartialEq)]
56#[cfg_attr(
57    feature = "serde",
58    derive(serde::Serialize, serde::Deserialize),
59    serde(deny_unknown_fields)
60)]
61pub struct ContourProfile {
62    /// Outer boundary.
63    pub outer: Contour,
64    /// Inner boundaries.
65    pub holes: Vec<Contour>,
66}