1use crate::{AffineOps, AffineTransform, CoordNum};
2
3pub trait Translate<T: CoordNum> {
4 #[must_use]
34 fn translate(&self, x_offset: T, y_offset: T) -> Self;
35
36 fn translate_mut(&mut self, x_offset: T, y_offset: T);
38}
39
40impl<T, G> Translate<T> for G
41where
42 T: CoordNum,
43 G: AffineOps<T>,
44{
45 fn translate(&self, x_offset: T, y_offset: T) -> Self {
46 let transform = AffineTransform::translate(x_offset, y_offset);
47 self.affine_transform(&transform)
48 }
49
50 fn translate_mut(&mut self, x_offset: T, y_offset: T) {
51 let transform = AffineTransform::translate(x_offset, y_offset);
52 self.affine_transform_mut(&transform)
53 }
54}
55
56#[cfg(test)]
57mod test {
58 use super::*;
59 use crate::{line_string, point, polygon, Coord, LineString, Polygon};
60
61 #[test]
62 fn test_translate_point() {
63 let p = point!(x: 1.0, y: 5.0);
64 let translated = p.translate(30.0, 20.0);
65 assert_eq!(translated, point!(x: 31.0, y: 25.0));
66 }
67 #[test]
68 fn test_translate_point_in_place() {
69 let mut p = point!(x: 1.0, y: 5.0);
70 p.translate_mut(30.0, 20.0);
71 assert_eq!(p, point!(x: 31.0, y: 25.0));
72 }
73 #[test]
74 fn test_translate_linestring() {
75 let linestring = line_string![
76 (x: 0.0, y: 0.0),
77 (x: 5.0, y: 1.0),
78 (x: 10.0, y: 0.0),
79 ];
80 let translated = linestring.translate(17.0, 18.0);
81 assert_eq!(
82 translated,
83 line_string![
84 (x: 17.0, y: 18.0),
85 (x: 22.0, y: 19.0),
86 (x: 27., y: 18.),
87 ]
88 );
89 }
90 #[test]
91 fn test_translate_polygon() {
92 let poly1 = polygon![
93 (x: 5., y: 1.),
94 (x: 4., y: 2.),
95 (x: 4., y: 3.),
96 (x: 5., y: 4.),
97 (x: 6., y: 4.),
98 (x: 7., y: 3.),
99 (x: 7., y: 2.),
100 (x: 6., y: 1.),
101 (x: 5., y: 1.),
102 ];
103 let translated = poly1.translate(17.0, 18.0);
104 let correct = polygon![
105 (x: 22.0, y: 19.0),
106 (x: 21.0, y: 20.0),
107 (x: 21.0, y: 21.0),
108 (x: 22.0, y: 22.0),
109 (x: 23.0, y: 22.0),
110 (x: 24.0, y: 21.0),
111 (x: 24.0, y: 20.0),
112 (x: 23.0, y: 19.0),
113 (x: 22.0, y: 19.0),
114 ];
115 assert_eq!(translated, correct);
117 }
118 #[test]
119 fn test_rotate_polygon_holes() {
120 let ls1 = LineString::from(vec![
121 (5.0, 1.0),
122 (4.0, 2.0),
123 (4.0, 3.0),
124 (5.0, 4.0),
125 (6.0, 4.0),
126 (7.0, 3.0),
127 (7.0, 2.0),
128 (6.0, 1.0),
129 (5.0, 1.0),
130 ]);
131
132 let ls2 = LineString::from(vec![(5.0, 1.3), (5.5, 2.0), (6.0, 1.3), (5.0, 1.3)]);
133
134 let poly1 = Polygon::new(ls1, vec![ls2]);
135 let rotated = poly1.translate(17.0, 18.0);
136 let correct_outside = vec![
137 Coord::from((22.0, 19.0)),
138 Coord::from((21.0, 20.0)),
139 Coord::from((21.0, 21.0)),
140 Coord::from((22.0, 22.0)),
141 Coord::from((23.0, 22.0)),
142 Coord::from((24.0, 21.0)),
143 Coord::from((24.0, 20.0)),
144 Coord::from((23.0, 19.0)),
145 Coord::from((22.0, 19.0)),
146 ];
147 let correct_inside = vec![
148 Coord::from((22.0, 19.3)),
149 Coord::from((22.5, 20.0)),
150 Coord::from((23.0, 19.3)),
151 Coord::from((22.0, 19.3)),
152 ];
153 assert_eq!(rotated.exterior().0, correct_outside);
154 assert_eq!(rotated.interiors()[0].0, correct_inside);
155 }
156}