Skip to content

Commit b2945e8

Browse files
committed
Implement ConvexHull for all geometry types
1 parent 5568e68 commit b2945e8

File tree

3 files changed

+38
-53
lines changed

3 files changed

+38
-53
lines changed

geo/CHANGES.md

+2
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
* Add `InteriorPoint` trait allowing calculation of a representative point inside
2121
a `Geometry`
2222
* <https://github.com/georust/geo/pull/870>
23+
* Add `ConvexHull` implementation for all remaining geometries.
24+
* <https://github.com/georust/geo/pull/889>
2325

2426
## 0.22.1
2527

geo/src/algorithm/convex_hull/mod.rs

+10-51
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use crate::{Coordinate, GeoNum, LineString, MultiLineString, MultiPoint, MultiPolygon, Polygon};
1+
use crate::geometry::{Coordinate, LineString, Polygon};
2+
use crate::GeoNum;
23

34
/// Returns the convex hull of a Polygon. The hull is always oriented counter-clockwise.
45
///
@@ -36,65 +37,23 @@ use crate::{Coordinate, GeoNum, LineString, MultiLineString, MultiPoint, MultiPo
3637
/// let res = poly.convex_hull();
3738
/// assert_eq!(res.exterior(), &correct_hull);
3839
/// ```
39-
pub trait ConvexHull {
40+
pub trait ConvexHull<'a, T> {
4041
type Scalar: GeoNum;
41-
fn convex_hull(&self) -> Polygon<Self::Scalar>;
42+
fn convex_hull(&'a self) -> Polygon<Self::Scalar>;
4243
}
4344

44-
impl<T> ConvexHull for Polygon<T>
45-
where
46-
T: GeoNum,
47-
{
48-
type Scalar = T;
49-
fn convex_hull(&self) -> Polygon<T> {
50-
Polygon::new(quick_hull(&mut self.exterior().0.clone()), vec![])
51-
}
52-
}
53-
54-
impl<T> ConvexHull for MultiPolygon<T>
55-
where
56-
T: GeoNum,
57-
{
58-
type Scalar = T;
59-
fn convex_hull(&self) -> Polygon<T> {
60-
let mut aggregated: Vec<_> = self
61-
.0
62-
.iter()
63-
.flat_map(|elem| elem.exterior().0.iter().copied())
64-
.collect();
65-
Polygon::new(quick_hull(&mut aggregated), vec![])
66-
}
67-
}
45+
use crate::algorithm::CoordsIter;
6846

69-
impl<T> ConvexHull for LineString<T>
47+
impl<'a, T, G> ConvexHull<'a, T> for G
7048
where
7149
T: GeoNum,
50+
G: CoordsIter<'a, Scalar = T>,
7251
{
7352
type Scalar = T;
74-
fn convex_hull(&self) -> Polygon<T> {
75-
Polygon::new(quick_hull(&mut self.0.clone()), vec![])
76-
}
77-
}
7853

79-
impl<T> ConvexHull for MultiLineString<T>
80-
where
81-
T: GeoNum,
82-
{
83-
type Scalar = T;
84-
fn convex_hull(&self) -> Polygon<T> {
85-
let mut aggregated: Vec<_> = self.iter().flat_map(|elem| elem.clone().0).collect();
86-
Polygon::new(quick_hull(&mut aggregated), vec![])
87-
}
88-
}
89-
90-
impl<T> ConvexHull for MultiPoint<T>
91-
where
92-
T: GeoNum,
93-
{
94-
type Scalar = T;
95-
fn convex_hull(&self) -> Polygon<T> {
96-
let mut aggregated: Vec<_> = self.iter().map(|p| p.0).collect();
97-
Polygon::new(quick_hull(&mut aggregated), vec![])
54+
fn convex_hull(&'a self) -> Polygon<T> {
55+
let mut exterior: Vec<_> = self.exterior_coords_iter().collect();
56+
Polygon::new(quick_hull(&mut exterior), vec![])
9857
}
9958
}
10059

geo/src/algorithm/convex_hull/test.rs

+26-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use super::ConvexHull;
2-
use crate::*;
1+
use super::*;
2+
use crate::geometry::*;
3+
use crate::{coord, line_string, polygon};
34

45
#[test]
56
fn convex_hull_multipoint_test() {
@@ -78,3 +79,26 @@ fn convex_hull_multipolygon_test() {
7879
let res = mp.convex_hull();
7980
assert_eq!(res.exterior().0, correct);
8081
}
82+
83+
#[test]
84+
fn collection() {
85+
let collection = GeometryCollection(vec![
86+
Point::new(0.0, 0.0).into(),
87+
Triangle::new(
88+
coord! { x: 1.0, y: 0.0},
89+
coord! { x: 4.0, y: 0.0},
90+
coord! { x: 4.0, y: 4.0 },
91+
)
92+
.into(),
93+
]);
94+
95+
let convex_hull = collection.convex_hull();
96+
assert_eq!(
97+
convex_hull,
98+
polygon![
99+
coord! { x: 4.0, y: 0.0 },
100+
coord! { x: 4.0, y: 4.0 },
101+
coord! { x: 0.0, y: 0.0 }
102+
]
103+
);
104+
}

0 commit comments

Comments
 (0)