axiolid_curve_evaluate_contract/
convention.rs

1//! Distance convention a provider evaluates against.
2
3/// Which distance a [`CurveEvaluator`](crate::CurveEvaluator) measures.
4///
5/// Naming this is not bureaucracy. For a [`Curve3::Elevated`] the plan
6/// distance and the true 3D arc length differ by `sqrt(1 + grade^2)`, so a
7/// caller that assumes the wrong one misplaces a structure by 0.125 m per
8/// 100 m at a 5% grade and 0.5 m per 100 m at 10%. A silent mismatch is
9/// exactly the failure this contract exists to prevent, so the convention
10/// is part of the contract rather than provider trivia.
11///
12/// [`Curve3::Elevated`]: axiolid_curve::Curve3::Elevated
13#[non_exhaustive]
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
15pub enum DistanceConvention {
16    /// True arc length along the 3D curve.
17    ///
18    /// Distance `d` advances `d` metres along the curve as built.
19    ArcLength3d,
20    /// Distance along the horizontal projection.
21    ///
22    /// This is how an alignment is authored: both the plan and the
23    /// vertical profile are functions of plan distance, and a station
24    /// written on a drawing is a plan distance. It is NOT the distance a
25    /// wheel travels, which is longer by the grade factor.
26    PlanDistance,
27    /// This provider cannot recover a distance for this curve.
28    ///
29    /// Reported rather than approximated: an ellipse needs elliptic
30    /// integrals and a B-spline needs numeric inversion, and returning the
31    /// native parameter as though it were a distance would be a lie a
32    /// caller cannot detect.
33    Unsupported,
34}
35
36impl DistanceConvention {
37    /// Whether a distance can be evaluated at all.
38    #[must_use]
39    pub fn is_supported(self) -> bool {
40        !matches!(self, Self::Unsupported)
41    }
42}