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