galileo_types/impls/
contour.rs

1use serde::{Deserialize, Serialize};
2
3use crate::geo::Projection;
4use crate::geometry_type::{ContourGeometryType, GeometryType};
5
6/// Simple [`crate::Contour`] implementation.
7#[derive(Debug, Default, Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Deserialize, Serialize)]
8pub struct Contour<Point> {
9    points: Vec<Point>,
10    is_closed: bool,
11}
12
13impl<Point> Contour<Point> {
14    /// Creates a new contour.
15    pub fn new(points: Vec<Point>, is_closed: bool) -> Self {
16        Self { points, is_closed }
17    }
18
19    /// Creates a new open contour.
20    pub fn open(points: Vec<Point>) -> Self {
21        Self {
22            points,
23            is_closed: false,
24        }
25    }
26
27    /// Creates a new closed contour.
28    pub fn closed(points: Vec<Point>) -> Self {
29        Self {
30            points,
31            is_closed: true,
32        }
33    }
34
35    /// Converts self into a `ClosedContour` instance if the contour is closed, or returns `None` if the contour is
36    /// open.
37    pub fn into_closed(self) -> Option<ClosedContour<Point>> {
38        if self.is_closed {
39            Some(ClosedContour {
40                points: self.points,
41            })
42        } else {
43            None
44        }
45    }
46
47    /// Projects all the points of the contour with the given projection.
48    pub fn project_points<P, Proj>(&self, projection: &Proj) -> Option<Contour<P>>
49    where
50        Proj: Projection<InPoint = Point, OutPoint = P> + ?Sized,
51    {
52        let points = self
53            .points
54            .iter()
55            .map(|p| projection.project(p))
56            .collect::<Option<Vec<P>>>()?;
57        Some(Contour {
58            points,
59            is_closed: self.is_closed,
60        })
61    }
62}
63
64/// Closed contour implementation.
65#[derive(Debug, Clone, Default, PartialEq, PartialOrd, Eq, Ord, Hash, Deserialize, Serialize)]
66pub struct ClosedContour<Point> {
67    /// Points of the contour.
68    pub points: Vec<Point>,
69}
70
71impl<Point> ClosedContour<Point> {
72    /// Creates a new closed contour.
73    pub fn new(points: Vec<Point>) -> Self {
74        Self { points }
75    }
76
77    /// Projects all the points of the contour with the given projection.
78    pub fn project_points<P, Proj>(&self, projection: &Proj) -> Option<ClosedContour<P>>
79    where
80        Proj: Projection<InPoint = Point, OutPoint = P> + ?Sized,
81    {
82        let points = self
83            .points
84            .iter()
85            .map(|p| projection.project(p))
86            .collect::<Option<Vec<P>>>()?;
87        Some(ClosedContour { points })
88    }
89}
90
91impl<P> From<ClosedContour<P>> for Contour<P> {
92    fn from(value: ClosedContour<P>) -> Self {
93        Self {
94            points: value.points,
95            is_closed: true,
96        }
97    }
98}
99
100impl<P: Copy> crate::contour::ClosedContour for ClosedContour<P> {
101    type Point = P;
102
103    fn iter_points(&self) -> impl Iterator<Item = P> {
104        self.points.iter().copied()
105    }
106}
107
108impl<P: Copy> crate::contour::Contour for Contour<P> {
109    type Point = P;
110
111    fn is_closed(&self) -> bool {
112        self.is_closed
113    }
114
115    fn iter_points(&self) -> impl Iterator<Item = P> {
116        self.points.iter().copied()
117    }
118}
119
120impl<P: GeometryType> GeometryType for Contour<P> {
121    type Type = ContourGeometryType;
122    type Space = P::Space;
123}
124
125impl<P: GeometryType> GeometryType for ClosedContour<P> {
126    type Type = ContourGeometryType;
127    type Space = P::Space;
128}