geo/algorithm/
euclidean_length.rs

1use std::iter::Sum;
2
3use crate::{CoordFloat, Line, LineString, MultiLineString};
4
5/// Calculation of the length
6
7pub trait EuclideanLength<T, RHS = Self> {
8    /// Calculation of the length of a Line
9    ///
10    /// # Examples
11    ///
12    /// ```
13    /// use geo::EuclideanLength;
14    /// use geo::line_string;
15    ///
16    /// let line_string = line_string![
17    ///     (x: 40.02f64, y: 116.34),
18    ///     (x: 42.02f64, y: 116.34),
19    /// ];
20    ///
21    /// assert_eq!(
22    ///     2.,
23    ///     line_string.euclidean_length(),
24    /// )
25    /// ```
26    fn euclidean_length(&self) -> T;
27}
28
29impl<T> EuclideanLength<T> for Line<T>
30where
31    T: CoordFloat,
32{
33    fn euclidean_length(&self) -> T {
34        ::geo_types::private_utils::line_euclidean_length(*self)
35    }
36}
37
38impl<T> EuclideanLength<T> for LineString<T>
39where
40    T: CoordFloat + Sum,
41{
42    fn euclidean_length(&self) -> T {
43        self.lines().map(|line| line.euclidean_length()).sum()
44    }
45}
46
47impl<T> EuclideanLength<T> for MultiLineString<T>
48where
49    T: CoordFloat + Sum,
50{
51    fn euclidean_length(&self) -> T {
52        self.0
53            .iter()
54            .fold(T::zero(), |total, line| total + line.euclidean_length())
55    }
56}
57
58#[cfg(test)]
59mod test {
60    use crate::line_string;
61    use crate::EuclideanLength;
62    use crate::{coord, Line, MultiLineString};
63
64    #[test]
65    fn empty_linestring_test() {
66        let linestring = line_string![];
67        assert_relative_eq!(0.0_f64, linestring.euclidean_length());
68    }
69    #[test]
70    fn linestring_one_point_test() {
71        let linestring = line_string![(x: 0., y: 0.)];
72        assert_relative_eq!(0.0_f64, linestring.euclidean_length());
73    }
74    #[test]
75    fn linestring_test() {
76        let linestring = line_string![
77            (x: 1., y: 1.),
78            (x: 7., y: 1.),
79            (x: 8., y: 1.),
80            (x: 9., y: 1.),
81            (x: 10., y: 1.),
82            (x: 11., y: 1.)
83        ];
84        assert_relative_eq!(10.0_f64, linestring.euclidean_length());
85    }
86    #[test]
87    fn multilinestring_test() {
88        let mline = MultiLineString::new(vec![
89            line_string![
90                (x: 1., y: 0.),
91                (x: 7., y: 0.),
92                (x: 8., y: 0.),
93                (x: 9., y: 0.),
94                (x: 10., y: 0.),
95                (x: 11., y: 0.)
96            ],
97            line_string![
98                (x: 0., y: 0.),
99                (x: 0., y: 5.)
100            ],
101        ]);
102        assert_relative_eq!(15.0_f64, mline.euclidean_length());
103    }
104    #[test]
105    fn line_test() {
106        let line0 = Line::new(coord! { x: 0., y: 0. }, coord! { x: 0., y: 1. });
107        let line1 = Line::new(coord! { x: 0., y: 0. }, coord! { x: 3., y: 4. });
108        assert_relative_eq!(line0.euclidean_length(), 1.);
109        assert_relative_eq!(line1.euclidean_length(), 5.);
110    }
111}