1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use crate::primitives::{Arc, Line};
use euclid::Vector2D;

/// Something which has a finite length.
pub trait Length {
    /// Calculate the length.
    fn length(&self) -> f64;
}

impl<'a, L: Length + ?Sized> Length for &'a L {
    fn length(&self) -> f64 { (*self).length() }
}

impl<Space> Length for Line<Space> {
    /// Calculates the length of the line.
    ///
    /// ```rust
    /// # use arcs_core::{algorithms::Length, primitives::Line};
    /// # type Point = euclid::default::Point2D<f64>;
    /// let line = Line::new(Point::zero(), Point::new(5.0, 0.0));
    ///
    /// assert_eq!(line.length(), 5.0);
    /// ```
    fn length(&self) -> f64 { self.displacement().length() }
}

impl<Space> Length for Vector2D<f64, Space> {
    /// Calculates the [`Vector2D`]'s magnitude.
    ///
    /// ```rust
    /// # use arcs_core::algorithms::Length;
    /// # type Vector = euclid::default::Vector2D<f64>;
    /// let vector = Vector::new(3.0, 4.0);
    ///
    /// assert_eq!(vector.length(), 5.0);
    /// ```
    fn length(&self) -> f64 { euclid::Vector2D::length(self) }
}

impl<Space> Length for Arc<Space> {
    /// Calculates the length of an [`Arc`].
    ///
    /// ```rust
    /// # use arcs_core::{algorithms::Length, primitives::Arc, Angle};
    /// # type Point = euclid::default::Point2D<f64>;
    /// # use std::f64::consts::PI;
    /// let radius = 50.0;
    /// let arc = Arc::from_centre_radius(
    ///     Point::zero(),
    ///     radius,
    ///     Angle::zero(),
    ///     Angle::two_pi(),
    /// );
    ///
    /// assert_eq!(arc.length(), 2.0 * radius * PI);
    /// ```
    fn length(&self) -> f64 { self.radius() * self.sweep_angle().radians.abs() }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::Angle;

    type Point = euclid::default::Point2D<f64>;

    #[test]
    fn line() {
        let thing = Line::new(Point::zero(), Point::new(3.0, 4.0));

        assert_eq!(thing.length(), 5.0);
    }

    #[test]
    fn arc() {
        let arc = Arc::from_centre_radius(
            Point::zero(),
            10.0,
            Angle::zero(),
            Angle::pi(),
        );

        assert_eq!(
            arc.length(),
            arc.sweep_angle().radians.abs() * arc.radius()
        );
    }
}