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}