Skip to content

Commit 3f7ce94

Browse files
committed
Merge #170
170: Map coords inplace r=frewsxcv a=rory To compliment the `.map_coords()` feature, I've added a `.map_coords_inplace` which will apply a provided function to all coordinatines in place, i.e. not doing any allocations. Some of this has a lot of overlap with #164. I've used that to add a `.translate_inplace()` feature.
2 parents ca33e87 + 31e66e2 commit 3f7ce94

File tree

2 files changed

+156
-36
lines changed

2 files changed

+156
-36
lines changed

src/algorithm/map_coords.rs

+122-6
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub trait MapCoords<T, NT> {
1818
/// assert_eq!(p2, Point::new(1010., 40.));
1919
/// ```
2020
///
21-
/// You can also change the coordinate precision in this way:
21+
/// You can convert the coordinate type this way as well
2222
///
2323
/// ```
2424
/// # use geo::Point;
@@ -30,9 +30,27 @@ pub trait MapCoords<T, NT> {
3030
/// assert_eq!(p2, Point::new(10.0f64, 20.0f64));
3131
/// ```
3232
fn map_coords(&self, func: &Fn(&(T, T)) -> (NT, NT)) -> Self::Output
33-
where
34-
T: Float,
35-
NT: Float;
33+
where T: Float, NT: Float;
34+
35+
36+
37+
}
38+
39+
/// Map all the coordinates in an object in place
40+
pub trait MapCoordsInplace<T> {
41+
/// Apply a function to all the coordinates in a geometric object, in place
42+
///
43+
/// ```
44+
/// use geo::Point;
45+
/// use geo::algorithm::map_coords::MapCoordsInplace;
46+
///
47+
/// let mut p = Point::new(10., 20.);
48+
/// p.map_coords_inplace(&|&(x, y)| (x+1000., y*2.));
49+
///
50+
/// assert_eq!(p, Point::new(1010., 40.));
51+
/// ```
52+
fn map_coords_inplace(&mut self, func: &Fn(&(T, T)) -> (T, T))
53+
where T: Float;
3654
}
3755

3856
impl<T: Float, NT: Float> MapCoords<T, NT> for Point<T> {
@@ -44,6 +62,16 @@ impl<T: Float, NT: Float> MapCoords<T, NT> for Point<T> {
4462
}
4563
}
4664

65+
impl<T: Float> MapCoordsInplace<T> for Point<T> {
66+
67+
fn map_coords_inplace(&mut self, func: &Fn(&(T, T)) -> (T, T))
68+
{
69+
let new_point = func(&(self.0.x, self.0.y));
70+
self.0.x = new_point.0;
71+
self.0.y = new_point.1;
72+
}
73+
}
74+
4775
impl<T: Float, NT: Float> MapCoords<T, NT> for Line<T> {
4876
type Output = Line<NT>;
4977

@@ -52,6 +80,14 @@ impl<T: Float, NT: Float> MapCoords<T, NT> for Line<T> {
5280
}
5381
}
5482

83+
impl<T: Float> MapCoordsInplace<T> for Line<T> {
84+
fn map_coords_inplace(&mut self, func: &Fn(&(T, T)) -> (T, T))
85+
{
86+
self.start.map_coords_inplace(func);
87+
self.end.map_coords_inplace(func);
88+
}
89+
}
90+
5591
impl<T: Float, NT: Float> MapCoords<T, NT> for LineString<T> {
5692
type Output = LineString<NT>;
5793

@@ -60,6 +96,15 @@ impl<T: Float, NT: Float> MapCoords<T, NT> for LineString<T> {
6096
}
6197
}
6298

99+
impl<T: Float> MapCoordsInplace<T> for LineString<T> {
100+
fn map_coords_inplace(&mut self, func: &Fn(&(T, T)) -> (T, T))
101+
{
102+
for p in self.0.iter_mut() {
103+
p.map_coords_inplace(func);
104+
}
105+
}
106+
}
107+
63108
impl<T: Float, NT: Float> MapCoords<T, NT> for Polygon<T> {
64109
type Output = Polygon<NT>;
65110

@@ -71,6 +116,16 @@ impl<T: Float, NT: Float> MapCoords<T, NT> for Polygon<T> {
71116
}
72117
}
73118

119+
impl<T: Float> MapCoordsInplace<T> for Polygon<T> {
120+
fn map_coords_inplace(&mut self, func: &Fn(&(T, T)) -> (T, T))
121+
{
122+
self.exterior.map_coords_inplace(func);
123+
for p in self.interiors.iter_mut() {
124+
p.map_coords_inplace(func);
125+
}
126+
}
127+
}
128+
74129
impl<T: Float, NT: Float> MapCoords<T, NT> for MultiPoint<T> {
75130
type Output = MultiPoint<NT>;
76131

@@ -79,6 +134,15 @@ impl<T: Float, NT: Float> MapCoords<T, NT> for MultiPoint<T> {
79134
}
80135
}
81136

137+
impl<T: Float> MapCoordsInplace<T> for MultiPoint<T> {
138+
fn map_coords_inplace(&mut self, func: &Fn(&(T, T)) -> (T, T))
139+
{
140+
for p in self.0.iter_mut() {
141+
p.map_coords_inplace(func);
142+
}
143+
}
144+
}
145+
82146
impl<T: Float, NT: Float> MapCoords<T, NT> for MultiLineString<T> {
83147
type Output = MultiLineString<NT>;
84148

@@ -87,6 +151,15 @@ impl<T: Float, NT: Float> MapCoords<T, NT> for MultiLineString<T> {
87151
}
88152
}
89153

154+
impl<T: Float> MapCoordsInplace<T> for MultiLineString<T> {
155+
fn map_coords_inplace(&mut self, func: &Fn(&(T, T)) -> (T, T))
156+
{
157+
for p in self.0.iter_mut() {
158+
p.map_coords_inplace(func);
159+
}
160+
}
161+
}
162+
90163
impl<T: Float, NT: Float> MapCoords<T, NT> for MultiPolygon<T> {
91164
type Output = MultiPolygon<NT>;
92165

@@ -95,6 +168,15 @@ impl<T: Float, NT: Float> MapCoords<T, NT> for MultiPolygon<T> {
95168
}
96169
}
97170

171+
impl<T: Float> MapCoordsInplace<T> for MultiPolygon<T> {
172+
fn map_coords_inplace(&mut self, func: &Fn(&(T, T)) -> (T, T))
173+
{
174+
for p in self.0.iter_mut() {
175+
p.map_coords_inplace(func);
176+
}
177+
}
178+
}
179+
98180
impl<T: Float, NT: Float> MapCoords<T, NT> for Geometry<T> {
99181
type Output = Geometry<NT>;
100182

@@ -112,6 +194,22 @@ impl<T: Float, NT: Float> MapCoords<T, NT> for Geometry<T> {
112194
}
113195
}
114196

197+
impl<T: Float> MapCoordsInplace<T> for Geometry<T> {
198+
fn map_coords_inplace(&mut self, func: &Fn(&(T, T)) -> (T, T))
199+
{
200+
match *self {
201+
Geometry::Point(ref mut x) => x.map_coords_inplace(func),
202+
Geometry::Line(ref mut x) => x.map_coords_inplace(func),
203+
Geometry::LineString(ref mut x) => x.map_coords_inplace(func),
204+
Geometry::Polygon(ref mut x) => x.map_coords_inplace(func),
205+
Geometry::MultiPoint(ref mut x) => x.map_coords_inplace(func),
206+
Geometry::MultiLineString(ref mut x) => x.map_coords_inplace(func),
207+
Geometry::MultiPolygon(ref mut x) => x.map_coords_inplace(func),
208+
Geometry::GeometryCollection(ref mut x) => x.map_coords_inplace(func),
209+
}
210+
}
211+
}
212+
115213
impl<T: Float, NT: Float> MapCoords<T, NT> for GeometryCollection<T> {
116214
type Output = GeometryCollection<NT>;
117215

@@ -120,9 +218,19 @@ impl<T: Float, NT: Float> MapCoords<T, NT> for GeometryCollection<T> {
120218
}
121219
}
122220

123-
mod test {
124-
#[allow(unused_imports)]
221+
impl<T: Float> MapCoordsInplace<T> for GeometryCollection<T> {
222+
fn map_coords_inplace(&mut self, func: &Fn(&(T, T)) -> (T, T))
223+
{
224+
for p in self.0.iter_mut() {
225+
p.map_coords_inplace(func);
226+
}
227+
}
228+
}
125229

230+
231+
232+
#[cfg(test)]
233+
mod test {
126234
use super::*;
127235

128236
#[test]
@@ -133,6 +241,14 @@ mod test {
133241
assert_eq!(new_p.y(), 110.);
134242
}
135243

244+
#[test]
245+
fn point_inplace() {
246+
let mut p2 = Point::new(10f32, 10f32);
247+
p2.map_coords_inplace(&|&(x, y)| (x+10., y+100.));
248+
assert_eq!(p2.x(), 20.);
249+
assert_eq!(p2.y(), 110.);
250+
}
251+
136252
#[test]
137253
fn line() {
138254
let line = Line::new(Point::new(0., 0.), Point::new(1., 2.));

src/algorithm/translate.rs

+34-30
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,44 @@
11
use num_traits::Float;
2-
use algorithm::map_coords::MapCoords;
2+
use algorithm::map_coords::{MapCoords, MapCoordsInplace};
33

44
pub trait Translate<T> {
5-
/// Translate a Geometry along its axes by the given offsets
6-
///
7-
///
8-
/// ```
9-
/// use geo::{Point, LineString};
10-
/// use geo::algorithm::translate::{Translate};
11-
///
12-
/// let mut vec = Vec::new();
13-
/// vec.push(Point::new(0.0, 0.0));
14-
/// vec.push(Point::new(5.0, 5.0));
15-
/// vec.push(Point::new(10.0, 10.0));
16-
/// let linestring = LineString(vec);
17-
/// let translated = linestring.translate(1.5, 3.5);
18-
/// let mut correct = Vec::new();
19-
/// correct.push(Point::new(1.5, 3.5));
20-
/// correct.push(Point::new(6.5, 8.5));
21-
/// correct.push(Point::new(11.5, 13.5));
22-
/// let correct_ls = LineString(correct);
23-
/// assert_eq!(translated, correct_ls);
24-
/// ```
25-
fn translate(&self, xoff: T, yoff: T) -> Self
26-
where
27-
T: Float;
5+
/// Translate a Geometry along its axes by the given offsets
6+
///
7+
///
8+
/// ```
9+
/// use geo::{Point, LineString};
10+
/// use geo::algorithm::translate::{Translate};
11+
///
12+
/// let mut vec = Vec::new();
13+
/// vec.push(Point::new(0.0, 0.0));
14+
/// vec.push(Point::new(5.0, 5.0));
15+
/// vec.push(Point::new(10.0, 10.0));
16+
/// let linestring = LineString(vec);
17+
/// let translated = linestring.translate(1.5, 3.5);
18+
/// let mut correct = Vec::new();
19+
/// correct.push(Point::new(1.5, 3.5));
20+
/// correct.push(Point::new(6.5, 8.5));
21+
/// correct.push(Point::new(11.5, 13.5));
22+
/// let correct_ls = LineString(correct);
23+
/// assert_eq!(translated, correct_ls);
24+
/// ```
25+
fn translate(&self, xoff: T, yoff: T) -> Self where T: Float;
26+
27+
/// Translate a Geometry along its axes, but in place.
28+
fn translate_inplace(&mut self, xoff: T, yoff: T) where T: Float;
2829
}
2930

3031
impl<T, G> Translate<T> for G
31-
where
32-
T: Float,
33-
G: MapCoords<T, T, Output = G>,
32+
where T: Float,
33+
G: MapCoords<T, T, Output=G>+MapCoordsInplace<T>
3434
{
35-
fn translate(&self, xoff: T, yoff: T) -> Self {
36-
self.map_coords(&|&(x, y)| (x + xoff, y + yoff))
37-
}
35+
fn translate(&self, xoff: T, yoff: T) -> Self {
36+
self.map_coords(&|&(x, y)| (x + xoff, y + yoff))
37+
}
38+
39+
fn translate_inplace(&mut self, xoff: T, yoff: T) {
40+
self.map_coords_inplace(&|&(x, y)| (x + xoff, y + yoff))
41+
}
3842
}
3943

4044
#[cfg(test)]

0 commit comments

Comments
 (0)