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
use crate::{
    primitives::{Arc, Line},
    Vector,
};

/// 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 Length for Line {
    /// Calculates the length of the line.
    ///
    /// ```rust
    /// # use arcs::{algorithms::Length, primitives::Line, Vector};
    /// let line = Line::new(Vector::zero(), Vector::new(5.0, 0.0));
    ///
    /// assert_eq!(line.length(), 5.0);
    /// ```
    fn length(&self) -> f64 { self.displacement().length() }
}

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

impl Length for Arc {
    /// Calculates the length of an [`Arc`].
    ///
    /// ```rust
    /// # use arcs::{algorithms::Length, primitives::Arc, Vector};
    /// # use std::f64::consts::PI;
    /// let radius = 50.0;
    /// let arc = Arc::from_centre_radius(Vector::zero(), radius, 0.0, 2.0 * PI);
    ///
    /// assert_eq!(arc.length(), 2.0 * radius * PI);
    /// ```
    fn length(&self) -> f64 { self.radius() * self.sweep_angle().abs() }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::f64::consts::PI;

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

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

    #[test]
    fn arc() {
        let arc = Arc::from_centre_radius(Vector::zero(), 10.0, 0.0, PI);

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