Skip to main content

path_traits/
path.rs

1//! Core traits for parametric curves.
2//!
3//! This module defines the two foundational traits of the crate:
4//!
5//! - [`Path`] - the core trait for arc-length-parameterized curves. It requires
6//!   `length()`, `sample_at(s)`, and provides `start()`, `end()`, `domain()`.
7//! - [`ParametricPath`] - extends [`Path`] with normalized-parameter sampling
8//!   `sample_t(t) ∈ [0, 1]`, plus conversion helpers `t_to_s` / `s_to_t`.
9
10use crate::PathError;
11use crate::Point;
12use crate::Scalar;
13
14/// A curve that can be sampled by arc-length `s`.
15///
16/// Every path has a total `length`, and `sample_at(s)` returns a [`Point`](crate::Point)
17/// for `s ∈ [0, length]`. The trait provides convenience methods `start()`, `end()`,
18/// and `domain()`.
19pub trait Path {
20    /// The scalar type for arc-length, parameter, and distance computations.
21    type Scalar: Scalar;
22    /// The point type representing positions on the path.
23    type Point: Point<Scalar = Self::Scalar>;
24    /// The error type for fallible operations. Must be convertible from [`PathError<Self::Scalar>`].
25    type Error: From<PathError<Self::Scalar>>;
26
27    /// Total arc-length of the path.
28    fn length(&self) -> Self::Scalar;
29
30    /// Sample the path at arc-length `s ∈ [0, length]`.
31    ///
32    /// Returns an error when `s` is outside the valid domain.
33    fn sample_at(&self, s: Self::Scalar) -> Result<Self::Point, Self::Error>;
34
35    /// The start point of the path, equivalent to `sample_at(0)`.
36    fn start(&self) -> Result<Self::Point, Self::Error> {
37        self.sample_at(Self::Scalar::zero())
38    }
39
40    /// The end point of the path, equivalent to `sample_at(length)`.
41    fn end(&self) -> Result<Self::Point, Self::Error> {
42        self.sample_at(self.length())
43    }
44
45    /// The valid domain for arc-length sampling: `[0, length]`.
46    fn domain(&self) -> core::ops::RangeInclusive<Self::Scalar> {
47        Self::Scalar::zero()..=self.length()
48    }
49}
50
51/// A curve that also supports sampling by a normalized parameter `t ∈ [0, 1]`.
52///
53/// Extends [`Path`] with `sample_t(t)`. Default implementations of `t_to_s` and
54/// `s_to_t` use linear conversion (`s = t * length`), which is exact only for
55/// arc-length-parameterized paths. Implementers may override these for exact
56/// conversions.
57pub trait ParametricPath: Path {
58    /// Sample the path at normalized parameter `t ∈ [0, 1]`.
59    ///
60    /// Returns an error when `t` is outside the valid domain.
61    fn sample_t(&self, t: Self::Scalar) -> Result<Self::Point, Self::Error>;
62
63    /// Convert normalized parameter `t` to arc-length `s`.
64    ///
65    /// Default: `t * length()`. Override for exact conversions.
66    fn t_to_s(&self, t: Self::Scalar) -> Self::Scalar {
67        t * self.length()
68    }
69
70    /// Convert arc-length `s` to normalized parameter `t`.
71    ///
72    /// Default: `s / length()`. Override for exact conversions.
73    fn s_to_t(&self, s: Self::Scalar) -> Self::Scalar {
74        s / self.length()
75    }
76}