1use crate::{
2 CoordNum, Geometry, Line, LineString, MultiLineString, MultiPoint, MultiPolygon, Point,
3 Polygon, Rect, Triangle,
4};
5use geo_types::GeometryCollection;
6use num_traits::FromPrimitive;
7
8pub trait RemoveRepeatedPoints<T>
16where
17 T: CoordNum + FromPrimitive,
18{
19 fn remove_repeated_points(&self) -> Self;
21 fn remove_repeated_points_mut(&mut self);
23}
24
25impl<T> RemoveRepeatedPoints<T> for MultiPoint<T>
26where
27 T: CoordNum + FromPrimitive,
28{
29 fn remove_repeated_points(&self) -> Self {
31 let mut points = vec![];
32 for p in self.0.iter() {
33 if !points.contains(p) {
34 points.push(*p);
35 }
36 }
37 MultiPoint(points)
38 }
39
40 fn remove_repeated_points_mut(&mut self) {
42 let mut points = vec![];
43 for p in self.0.iter() {
44 if !points.contains(p) {
45 points.push(*p);
46 }
47 }
48 self.0 = points;
49 }
50}
51
52impl<T> RemoveRepeatedPoints<T> for LineString<T>
53where
54 T: CoordNum + FromPrimitive,
55{
56 fn remove_repeated_points(&self) -> Self {
58 let mut coords = self.0.clone();
59 coords.dedup();
60 LineString(coords)
61 }
62
63 fn remove_repeated_points_mut(&mut self) {
65 self.0.dedup();
66 }
67}
68
69impl<T> RemoveRepeatedPoints<T> for Polygon<T>
70where
71 T: CoordNum + FromPrimitive,
72{
73 fn remove_repeated_points(&self) -> Self {
75 Polygon::new(
76 self.exterior().remove_repeated_points(),
77 self.interiors()
78 .iter()
79 .map(|ls| ls.remove_repeated_points())
80 .collect(),
81 )
82 }
83
84 fn remove_repeated_points_mut(&mut self) {
86 self.exterior_mut(|exterior| exterior.remove_repeated_points_mut());
87 self.interiors_mut(|interiors| {
88 for interior in interiors {
89 interior.remove_repeated_points_mut();
90 }
91 });
92 }
93}
94
95impl<T> RemoveRepeatedPoints<T> for MultiLineString<T>
96where
97 T: CoordNum + FromPrimitive,
98{
99 fn remove_repeated_points(&self) -> Self {
101 MultiLineString::new(
102 self.0
103 .iter()
104 .map(|ls| ls.remove_repeated_points())
105 .collect(),
106 )
107 }
108
109 fn remove_repeated_points_mut(&mut self) {
111 for ls in self.0.iter_mut() {
112 ls.remove_repeated_points_mut();
113 }
114 }
115}
116
117impl<T> RemoveRepeatedPoints<T> for MultiPolygon<T>
118where
119 T: CoordNum + FromPrimitive,
120{
121 fn remove_repeated_points(&self) -> Self {
123 MultiPolygon::new(self.0.iter().map(|p| p.remove_repeated_points()).collect())
124 }
125
126 fn remove_repeated_points_mut(&mut self) {
128 for p in self.0.iter_mut() {
129 p.remove_repeated_points_mut();
130 }
131 }
132}
133
134macro_rules! impl_for_not_candidate_types {
138 ($type:ident) => {
139 impl<T> RemoveRepeatedPoints<T> for $type<T>
140 where
141 T: CoordNum + FromPrimitive,
142 {
143 fn remove_repeated_points(&self) -> Self {
144 self.clone()
145 }
146
147 fn remove_repeated_points_mut(&mut self) {
148 }
150 }
151 };
152}
153
154impl_for_not_candidate_types!(Point);
155impl_for_not_candidate_types!(Rect);
156impl_for_not_candidate_types!(Triangle);
157impl_for_not_candidate_types!(Line);
158
159impl<T> RemoveRepeatedPoints<T> for GeometryCollection<T>
160where
161 T: CoordNum + FromPrimitive,
162{
163 fn remove_repeated_points(&self) -> Self {
166 GeometryCollection::new_from(self.0.iter().map(|g| g.remove_repeated_points()).collect())
167 }
168
169 fn remove_repeated_points_mut(&mut self) {
171 for g in self.0.iter_mut() {
172 g.remove_repeated_points_mut();
173 }
174 }
175}
176
177impl<T> RemoveRepeatedPoints<T> for Geometry<T>
178where
179 T: CoordNum + FromPrimitive,
180{
181 fn remove_repeated_points(&self) -> Self {
191 match self {
192 Geometry::Point(p) => Geometry::Point(p.remove_repeated_points()),
193 Geometry::Line(l) => Geometry::Line(l.remove_repeated_points()),
194 Geometry::LineString(ls) => Geometry::LineString(ls.remove_repeated_points()),
195 Geometry::Polygon(p) => Geometry::Polygon(p.remove_repeated_points()),
196 Geometry::MultiPoint(mp) => Geometry::MultiPoint(mp.remove_repeated_points()),
197 Geometry::MultiLineString(mls) => {
198 Geometry::MultiLineString(mls.remove_repeated_points())
199 }
200 Geometry::MultiPolygon(mp) => Geometry::MultiPolygon(mp.remove_repeated_points()),
201 Geometry::Rect(r) => Geometry::Rect(r.remove_repeated_points()),
202 Geometry::Triangle(t) => Geometry::Triangle(t.remove_repeated_points()),
203 Geometry::GeometryCollection(gc) => {
204 Geometry::GeometryCollection(gc.remove_repeated_points())
205 }
206 }
207 }
208
209 fn remove_repeated_points_mut(&mut self) {
211 match self {
212 Geometry::Point(p) => p.remove_repeated_points_mut(),
213 Geometry::Line(l) => l.remove_repeated_points_mut(),
214 Geometry::LineString(ls) => ls.remove_repeated_points_mut(),
215 Geometry::Polygon(p) => p.remove_repeated_points_mut(),
216 Geometry::MultiPoint(mp) => mp.remove_repeated_points_mut(),
217 Geometry::MultiLineString(mls) => mls.remove_repeated_points_mut(),
218 Geometry::MultiPolygon(mp) => mp.remove_repeated_points_mut(),
219 Geometry::Rect(r) => r.remove_repeated_points_mut(),
220 Geometry::Triangle(t) => t.remove_repeated_points_mut(),
221 Geometry::GeometryCollection(gc) => gc.remove_repeated_points_mut(),
222 }
223 }
224}
225
226#[cfg(test)]
227mod test {
228 use crate::RemoveRepeatedPoints;
229 use crate::{
230 Coord, GeometryCollection, LineString, MultiLineString, MultiPoint, MultiPolygon, Point,
231 Polygon,
232 };
233
234 fn make_test_mp_integer() -> MultiPoint<i32> {
235 MultiPoint(vec![
236 Point::new(0, 0),
237 Point::new(1, 1),
238 Point::new(1, 1),
239 Point::new(1, 1),
240 Point::new(2, 2),
241 Point::new(0, 0),
242 ])
243 }
244
245 fn make_result_mp_integer() -> MultiPoint<i32> {
246 MultiPoint(vec![Point::new(0, 0), Point::new(1, 1), Point::new(2, 2)])
247 }
248
249 fn make_test_mp1() -> MultiPoint {
250 MultiPoint(vec![
251 Point::new(0., 0.),
252 Point::new(1., 1.),
253 Point::new(1., 1.),
254 Point::new(1., 1.),
255 Point::new(2., 2.),
256 Point::new(0., 0.),
257 ])
258 }
259
260 fn make_result_mp1() -> MultiPoint {
261 MultiPoint(vec![
262 Point::new(0., 0.),
263 Point::new(1., 1.),
264 Point::new(2., 2.),
265 ])
266 }
267
268 fn make_test_line1() -> LineString {
269 LineString(vec![
270 Coord { x: 0., y: 0. },
271 Coord { x: 1., y: 1. },
272 Coord { x: 1., y: 1. },
273 Coord { x: 1., y: 1. },
274 Coord { x: 2., y: 2. },
275 Coord { x: 2., y: 2. },
276 Coord { x: 0., y: 0. },
277 ])
278 }
279
280 fn make_result_line1() -> LineString {
281 LineString(vec![
282 Coord { x: 0., y: 0. },
283 Coord { x: 1., y: 1. },
284 Coord { x: 2., y: 2. },
285 Coord { x: 0., y: 0. },
286 ])
287 }
288
289 fn make_test_line2() -> LineString {
290 LineString(vec![
291 Coord { x: 10., y: 10. },
292 Coord { x: 11., y: 11. },
293 Coord { x: 11., y: 11. },
294 Coord { x: 11., y: 11. },
295 Coord { x: 12., y: 12. },
296 Coord { x: 12., y: 12. },
297 Coord { x: 10., y: 10. },
298 ])
299 }
300
301 fn make_result_line2() -> LineString {
302 LineString(vec![
303 Coord { x: 10., y: 10. },
304 Coord { x: 11., y: 11. },
305 Coord { x: 12., y: 12. },
306 Coord { x: 10., y: 10. },
307 ])
308 }
309
310 fn make_test_poly1() -> Polygon {
311 Polygon::new(
312 LineString(vec![
313 Coord { x: 0., y: 0. },
314 Coord { x: 1., y: 1. },
315 Coord { x: 1., y: 1. },
316 Coord { x: 1., y: 1. },
317 Coord { x: 0., y: 2. },
318 Coord { x: 0., y: 2. },
319 Coord { x: 0., y: 0. },
320 ]),
321 vec![],
322 )
323 }
324
325 fn make_result_poly1() -> Polygon {
326 Polygon::new(
327 LineString(vec![
328 Coord { x: 0., y: 0. },
329 Coord { x: 1., y: 1. },
330 Coord { x: 0., y: 2. },
331 Coord { x: 0., y: 0. },
332 ]),
333 vec![],
334 )
335 }
336
337 fn make_test_poly2() -> Polygon {
338 Polygon::new(
339 LineString(vec![
340 Coord { x: 10., y: 10. },
341 Coord { x: 11., y: 11. },
342 Coord { x: 11., y: 11. },
343 Coord { x: 11., y: 11. },
344 Coord { x: 10., y: 12. },
345 Coord { x: 10., y: 12. },
346 Coord { x: 10., y: 10. },
347 ]),
348 vec![],
349 )
350 }
351
352 fn make_result_poly2() -> Polygon {
353 Polygon::new(
354 LineString(vec![
355 Coord { x: 10., y: 10. },
356 Coord { x: 11., y: 11. },
357 Coord { x: 10., y: 12. },
358 Coord { x: 10., y: 10. },
359 ]),
360 vec![],
361 )
362 }
363
364 #[test]
365 fn test_remove_repeated_points_multipoint_integer() {
366 let mp = make_test_mp_integer();
367 let expected = make_result_mp_integer();
368
369 assert_eq!(mp.remove_repeated_points(), expected);
370 }
371
372 #[test]
373 fn test_remove_repeated_points_multipoint() {
374 let mp = make_test_mp1();
375 let expected = make_result_mp1();
376
377 assert_eq!(mp.remove_repeated_points(), expected);
378 }
379
380 #[test]
381 fn test_remove_repeated_points_linestring() {
382 let ls = make_test_line1();
383 let expected = make_result_line1();
384
385 assert_eq!(ls.remove_repeated_points(), expected);
386 }
387
388 #[test]
389 fn test_remove_repeated_points_polygon() {
390 let poly = make_test_poly1();
391 let expected = make_result_poly1();
392
393 assert_eq!(poly.remove_repeated_points(), expected);
394 }
395
396 #[test]
397 fn test_remove_repeated_points_multilinestring() {
398 let mls = MultiLineString(vec![make_test_line1(), make_test_line2()]);
399
400 let expected = MultiLineString(vec![make_result_line1(), make_result_line2()]);
401
402 assert_eq!(mls.remove_repeated_points(), expected);
403 }
404
405 #[test]
406 fn test_remove_repeated_points_multipolygon() {
407 let mpoly = MultiPolygon(vec![make_test_poly1(), make_test_poly2()]);
408
409 let expected = MultiPolygon(vec![make_result_poly1(), make_result_poly2()]);
410
411 assert_eq!(mpoly.remove_repeated_points(), expected);
412 }
413
414 #[test]
415 fn test_remove_repeated_points_geometrycollection() {
416 let gc = GeometryCollection::new_from(vec![
417 make_test_mp1().into(),
418 make_test_line1().into(),
419 make_test_poly1().into(),
420 ]);
421
422 let expected = GeometryCollection::new_from(vec![
423 make_result_mp1().into(),
424 make_result_line1().into(),
425 make_result_poly1().into(),
426 ]);
427
428 assert_eq!(gc.remove_repeated_points(), expected);
429 }
430
431 #[test]
432 fn test_remove_repeated_points_mut_multipoint_integer() {
433 let mut mp = make_test_mp_integer();
434 mp.remove_repeated_points_mut();
435 let expected = make_result_mp_integer();
436
437 assert_eq!(mp, expected);
438 }
439
440 #[test]
441 fn test_remove_repeated_points_mut_multipoint() {
442 let mut mp = make_test_mp1();
443 mp.remove_repeated_points_mut();
444 let expected = make_result_mp1();
445
446 assert_eq!(mp, expected);
447 }
448
449 #[test]
450 fn test_remove_repeated_points_mut_linestring() {
451 let mut ls = make_test_line1();
452 ls.remove_repeated_points_mut();
453 let expected = make_result_line1();
454
455 assert_eq!(ls, expected);
456 }
457
458 #[test]
459 fn test_remove_repeated_points_mut_polygon() {
460 let mut poly = make_test_poly1();
461 poly.remove_repeated_points_mut();
462 let expected = make_result_poly1();
463
464 assert_eq!(poly, expected);
465 }
466
467 #[test]
468 fn test_remove_repeated_points_mut_multilinestring() {
469 let mut mls = MultiLineString(vec![make_test_line1(), make_test_line2()]);
470 mls.remove_repeated_points_mut();
471 let expected = MultiLineString(vec![make_result_line1(), make_result_line2()]);
472
473 assert_eq!(mls, expected);
474 }
475
476 #[test]
477 fn test_remove_repeated_points_mut_multipolygon() {
478 let mut mpoly = MultiPolygon(vec![make_test_poly1(), make_test_poly2()]);
479 mpoly.remove_repeated_points_mut();
480 let expected = MultiPolygon(vec![make_result_poly1(), make_result_poly2()]);
481
482 assert_eq!(mpoly, expected);
483 }
484
485 #[test]
486 fn test_remove_repeated_points_mut_geometrycollection() {
487 let mut gc = GeometryCollection::new_from(vec![
488 make_test_mp1().into(),
489 make_test_line1().into(),
490 make_test_poly1().into(),
491 ]);
492 gc.remove_repeated_points_mut();
493
494 let expected = GeometryCollection::new_from(vec![
495 make_result_mp1().into(),
496 make_result_line1().into(),
497 make_result_poly1().into(),
498 ]);
499
500 assert_eq!(gc, expected);
501 }
502}