microcad_core/geo2d/
reflect.rs1use super::*;
9use cgmath::InnerSpace;
10
11pub trait Reflect2D<T = Self> {
13 fn reflect_2d(&self, l: &Line) -> T;
15}
16
17pub trait Mirror2D<T = Self>: Reflect2D<T> + Into<Geometry2D> {
19 fn mirror_2d(self, l: &Line) -> Geometries2D {
21 let orig: Geometry2D = self.into();
22 let refl: Geometry2D = orig.reflect_2d(l);
23 Geometries2D::new(vec![orig, refl])
24 }
25}
26
27impl Reflect2D for Point {
28 fn reflect_2d(&self, l: &Line) -> Self {
29 let d = l.vec();
30 let t = ((self.x() - l.0.x()) * d.x + (self.y() - l.0.y()) * d.y) / d.magnitude();
31 let q = 2.0 * (Vec2::from(l.0.0.x_y()) + t * d);
32 Self::new(q.x - self.x(), q.y - self.y())
33 }
34}
35
36impl Reflect2D for geo::Coord {
37 fn reflect_2d(&self, l: &Line) -> Self {
38 Point::from(self.x_y()).reflect_2d(l).into()
39 }
40}
41
42impl Reflect2D for LineString {
43 fn reflect_2d(&self, l: &Line) -> Self {
44 Self::new(self.0.iter().map(|c| c.reflect_2d(l)).rev().collect())
45 }
46}
47
48impl Mirror2D for LineString {}
49
50impl Reflect2D for MultiLineString {
51 fn reflect_2d(&self, l: &Line) -> Self {
52 Self::new(
53 self.0
54 .iter()
55 .map(|line_string| line_string.reflect_2d(l))
56 .collect(),
57 )
58 }
59}
60
61impl Mirror2D for MultiLineString {}
62
63impl Reflect2D for Polygon {
64 fn reflect_2d(&self, l: &Line) -> Self {
65 Self::new(
66 self.exterior().reflect_2d(l),
67 self.interiors()
68 .iter()
69 .map(|interior| interior.reflect_2d(l))
70 .collect(),
71 )
72 }
73}
74
75impl Mirror2D for Polygon {}
76
77impl Reflect2D for MultiPolygon {
78 fn reflect_2d(&self, l: &Line) -> Self {
79 Self::new(self.0.iter().map(|polygon| polygon.reflect_2d(l)).collect())
80 }
81}
82
83impl Mirror2D for MultiPolygon {}
84
85impl Reflect2D<Polygon> for Rect {
86 fn reflect_2d(&self, l: &Line) -> Polygon {
87 self.to_polygon().reflect_2d(l)
88 }
89}
90
91impl Mirror2D<Polygon> for Rect {}
92
93impl Reflect2D for Line {
94 fn reflect_2d(&self, l: &Line) -> Self {
95 Self(self.1.reflect_2d(l), self.0.reflect_2d(l))
96 }
97}
98
99impl Mirror2D for Line {}
100
101impl Reflect2D for Geometries2D {
102 fn reflect_2d(&self, l: &Line) -> Self {
103 Self::from_iter(
104 self.iter()
105 .map(|geometry| std::rc::Rc::new(geometry.as_ref().reflect_2d(l))),
106 )
107 }
108}
109
110impl Mirror2D for Geometries2D {}
111
112impl Reflect2D for Geometry2D {
113 fn reflect_2d(&self, l: &Line) -> Self {
114 match &self {
115 Geometry2D::LineString(line_string) => line_string.reflect_2d(l).into(),
116 Geometry2D::MultiLineString(multi_line_string) => {
117 multi_line_string.reflect_2d(l).into()
118 }
119 Geometry2D::Polygon(polygon) => polygon.reflect_2d(l).into(),
120 Geometry2D::MultiPolygon(multi_polygon) => multi_polygon.reflect_2d(l).into(),
121 Geometry2D::Rect(rect) => rect.reflect_2d(l).into(),
122 Geometry2D::Line(line) => line.reflect_2d(l).into(),
123 Geometry2D::Collection(collection) => collection.reflect_2d(l).into(),
124 }
125 }
126}
127
128impl Mirror2D for Geometry2D {}