Skip to main content

path_traits/
differential.rs

1//! Differential geometry queries for paths.
2//!
3//! Once you can sample a path's position, these opt-in traits let you query
4//! how the path is oriented and bending at any point:
5//!
6//! - [`Tangent`] - unit tangent vector at any arc-length
7//! - [`Heading`] - planar heading angle (radians) at any arc-length
8//! - [`Curved`] - curvature (scalar in 2D, vector in 3D) at any arc-length
9//! - [`FrenetFrame`] - full Frenet–Serret frame (T, N[, B]) at any arc-length
10
11use crate::{Path, Point};
12
13/// Query the unit tangent vector at any point along a path.
14///
15/// The returned vector is unit-length and points in the direction of
16/// increasing arc-length.
17pub trait Tangent: Path {
18    /// Unit tangent vector at arc-length `s`.
19    ///
20    /// Returns an error when `s` is outside the domain or the path is not
21    /// differentiable at `s`.
22    fn tangent_at(&self, s: Self::Scalar) -> Result<<Self::Point as Point>::Vector, Self::Error>;
23}
24
25/// Query the planar heading angle at any point along a path.
26///
27/// Heading is meaningful only for 2D paths, where it represents the angle
28/// (in radians, counter-clockwise from the positive x-axis) of the tangent.
29pub trait Heading: Path {
30    /// Planar heading angle (radians) at arc-length `s`.
31    ///
32    /// Returns an error when `s` is outside the domain or the heading is
33    /// undefined at this point.
34    fn heading_at(&self, s: Self::Scalar) -> Result<Self::Scalar, Self::Error>;
35}
36
37/// Query the curvature at any point along a path.
38///
39/// In 2D the curvature is a signed scalar (positive for left turns, negative
40/// for right turns). In 3D it is a curvature vector (`κ · N`).
41pub trait Curved: Path {
42    /// The type representing curvature (scalar in 2D, vector in 3D).
43    type Curvature;
44
45    /// Curvature at arc-length `s`.
46    ///
47    /// Returns an error when `s` is outside the domain or curvature is
48    /// undefined at this point.
49    fn curvature_at(&self, s: Self::Scalar) -> Result<Self::Curvature, Self::Error>;
50}
51
52/// Query the full Frenet frame (T, N[, B]) at any point along a path.
53///
54/// In 2D the frame consists of the tangent and normal. In 3D it additionally
55/// includes the binormal.
56pub trait FrenetFrame: Tangent + Curved {
57    /// Frame type, e.g. `(Tangent, Normal)` in 2D or `(T, N, B)` in 3D.
58    type Frame;
59
60    /// Frenet frame at arc-length `s`.
61    ///
62    /// Returns an error when `s` is outside the domain or the frame cannot be
63    /// computed (e.g. zero curvature in 3D).
64    fn frame_at(&self, s: Self::Scalar) -> Result<Self::Frame, Self::Error>;
65}