Skip to main content

egml_core/model/geometry/primitives/
line_string.rs

1use crate::Error::{AdjacentDuplicatePositions, TooFewElements};
2use crate::model::geometry::primitives::{AbstractCurve, AsAbstractCurve, AsAbstractCurveMut};
3use crate::model::geometry::{DirectPosition, Envelope};
4use crate::{Error, impl_abstract_curve_traits};
5use nalgebra::Isometry3;
6
7/// An ordered sequence of two or more coordinate positions forming a 1-D curve.
8///
9/// Corresponds to `gml:LineString` in ISO 19136 §10.4.4.
10#[derive(Debug, Clone, PartialEq, Default)]
11pub struct LineString {
12    pub(crate) abstract_curve: AbstractCurve,
13    points: Vec<DirectPosition>,
14}
15
16impl LineString {
17    /// Creates a new `LineString` from an ordered list of positions.
18    ///
19    /// # Errors
20    ///
21    /// Returns [`Error::TooFewElements`] if `points` contains fewer than 2 entries.
22    /// Returns [`Error::AdjacentDuplicatePositions`] if adjacent positions are equal.
23    pub fn new(abstract_curve: AbstractCurve, points: Vec<DirectPosition>) -> Result<Self, Error> {
24        let duplicates_count = points.windows(2).filter(|x| x[0] == x[1]).count();
25        if duplicates_count > 0 {
26            return Err(AdjacentDuplicatePositions);
27        }
28        if points.len() < 2 {
29            return Err(TooFewElements {
30                geometry: "gml:LineString",
31                minimum: 2,
32                spec: Some("ISO 19136 §10.4.4"),
33                id: None,
34                message: None,
35            });
36        }
37
38        Ok(Self {
39            abstract_curve,
40            points,
41        })
42    }
43
44    /// Returns the ordered positions of this line string.
45    pub fn points(&self) -> &[DirectPosition] {
46        &self.points
47    }
48
49    /// Applies a rigid-body transform to all positions in place.
50    pub fn apply_transform(&mut self, m: &Isometry3<f64>) {
51        self.points.iter_mut().for_each(|p| {
52            p.apply_transform(m);
53        });
54    }
55
56    pub fn compute_envelope(&self) -> Envelope {
57        Envelope::from_points(&self.points).expect("line string must have valid points")
58    }
59}
60
61impl AsAbstractCurve for LineString {
62    fn abstract_curve(&self) -> &AbstractCurve {
63        &self.abstract_curve
64    }
65}
66
67impl AsAbstractCurveMut for LineString {
68    fn abstract_curve_mut(&mut self) -> &mut AbstractCurve {
69        &mut self.abstract_curve
70    }
71}
72
73impl_abstract_curve_traits!(LineString);