Skip to content

Commit 7ff170a

Browse files
bors[bot]frewsxcv
andauthored
Merge #563
563: Introduce `num_coords` method on all geometry types. r=michaelkirk a=frewsxcv I'm going to use these methods in a project to preallocate vectors of coordinates. - [x] I agree to follow the project's [code of conduct](https://github.com/georust/geo/blob/master/CODE_OF_CONDUCT.md). - [x] I added an entry to `CHANGES.md` if knowledge of this change could be valuable to users. --- Co-authored-by: Corey Farwell <coreyf@rwell.org>
2 parents d51ddab + db616ad commit 7ff170a

7 files changed

Lines changed: 104 additions & 7 deletions

File tree

geo-types/CHANGES.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## Unreleased
44

5+
* `geo_types::LineString::num_coords` has been deprecated in favor of `geo::algorithm::coords_iter::CoordsIter::coords_count`
6+
* <https://github.com/georust/geo/pull/563>
7+
58
## 0.6.2
69

710
* Add `into_iter`, `iter` and `iter_mut` methods for `MultiPolygon`, `MultiPoint`, and `MultiLineString`

geo-types/src/line_string.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,7 @@ impl<T: CoordinateType> LineString<T> {
201201
/// let line_string: LineString<f32> = coords.into_iter().collect();
202202
/// assert_eq!(3, line_string.num_coords());
203203
/// ```
204+
#[deprecated(note = "Use geo::algorithm::coords_iter::CoordsIter::coords_count instead")]
204205
pub fn num_coords(&self) -> usize {
205206
self.0.len()
206207
}

geo/CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
* Introduce `coords_count` method on `CoordsIter`.
6+
* <https://github.com/georust/geo/pull/563>
57
* Fix non-empty MultiPoint has 0-dimensions, not 1.
68
* <https://github.com/georust/geo/pull/561>
79

geo/src/algorithm/coords_iter.rs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,24 @@ pub trait CoordsIter<'a, T: CoordinateType> {
3333
/// assert_eq!(None, iter.next());
3434
/// ```
3535
fn coords_iter(&'a self) -> Self::Iter;
36+
37+
/// Return the number of coordinates in a geometry.
38+
///
39+
/// # Examples
40+
///
41+
/// ```
42+
/// use geo::coords_iter::CoordsIter;
43+
/// use geo::line_string;
44+
///
45+
/// let ls = line_string![
46+
/// (x: 1., y: 2.),
47+
/// (x: 23., y: 82.),
48+
/// (x: -1., y: 0.),
49+
/// ];
50+
///
51+
/// assert_eq!(3, ls.coords_count());
52+
/// ```
53+
fn coords_count(&'a self) -> usize;
3654
}
3755

3856
// ┌──────────────────────────┐
@@ -45,6 +63,11 @@ impl<'a, T: CoordinateType> CoordsIter<'a, T> for Point<T> {
4563
fn coords_iter(&'a self) -> Self::Iter {
4664
iter::once(self.0)
4765
}
66+
67+
/// Return the number of coordinates in the `Point`.
68+
fn coords_count(&'a self) -> usize {
69+
1
70+
}
4871
}
4972

5073
// ┌─────────────────────────┐
@@ -57,6 +80,11 @@ impl<'a, T: CoordinateType> CoordsIter<'a, T> for Line<T> {
5780
fn coords_iter(&'a self) -> Self::Iter {
5881
iter::once(self.start).chain(iter::once(self.end))
5982
}
83+
84+
/// Return the number of coordinates in the `Line`.
85+
fn coords_count(&'a self) -> usize {
86+
2
87+
}
6088
}
6189

6290
// ┌───────────────────────────────┐
@@ -69,6 +97,11 @@ impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for LineString<T> {
6997
fn coords_iter(&'a self) -> Self::Iter {
7098
self.0.iter().copied()
7199
}
100+
101+
/// Return the number of coordinates in the `LineString`.
102+
fn coords_count(&'a self) -> usize {
103+
self.0.len()
104+
}
72105
}
73106

74107
// ┌────────────────────────────┐
@@ -87,6 +120,12 @@ impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for Polygon<T> {
87120
.coords_iter()
88121
.chain(MapCoordsIter(self.interiors().iter(), marker::PhantomData).flatten())
89122
}
123+
124+
/// Return the number of coordinates in the `Polygon`.
125+
fn coords_count(&'a self) -> usize {
126+
self.exterior().coords_count() +
127+
self.interiors().iter().map(|i| i.coords_count()).sum::<usize>()
128+
}
90129
}
91130

92131
// ┌───────────────────────────────┐
@@ -99,6 +138,11 @@ impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for MultiPoint<T> {
99138
fn coords_iter(&'a self) -> Self::Iter {
100139
MapCoordsIter(self.0.iter(), marker::PhantomData).flatten()
101140
}
141+
142+
/// Return the number of coordinates in the `MultiPoint`.
143+
fn coords_count(&'a self) -> usize {
144+
self.0.len()
145+
}
102146
}
103147

104148
// ┌────────────────────────────────────┐
@@ -111,6 +155,11 @@ impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for MultiLineString<T> {
111155
fn coords_iter(&'a self) -> Self::Iter {
112156
MapCoordsIter(self.0.iter(), marker::PhantomData).flatten()
113157
}
158+
159+
/// Return the number of coordinates in the `MultiLineString`.
160+
fn coords_count(&'a self) -> usize {
161+
self.0.iter().map(|line_string| line_string.coords_count()).sum()
162+
}
114163
}
115164

116165
// ┌─────────────────────────────────┐
@@ -123,6 +172,11 @@ impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for MultiPolygon<T> {
123172
fn coords_iter(&'a self) -> Self::Iter {
124173
MapCoordsIter(self.0.iter(), marker::PhantomData).flatten()
125174
}
175+
176+
/// Return the number of coordinates in the `MultiPolygon`.
177+
fn coords_count(&'a self) -> usize {
178+
self.0.iter().map(|polygon| polygon.coords_count()).sum()
179+
}
126180
}
127181

128182
// ┌───────────────────────────────────────┐
@@ -135,6 +189,11 @@ impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for GeometryCollection<T> {
135189
fn coords_iter(&'a self) -> Self::Iter {
136190
Box::new(self.0.iter().flat_map(|geometry| geometry.coords_iter()))
137191
}
192+
193+
/// Return the number of coordinates in the `GeometryCollection`.
194+
fn coords_count(&'a self) -> usize {
195+
self.0.iter().map(|geometry| geometry.coords_count()).sum()
196+
}
138197
}
139198

140199
// ┌─────────────────────────┐
@@ -167,6 +226,14 @@ impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for Rect<T> {
167226
y: self.min().y,
168227
}))
169228
}
229+
230+
/// Return the number of coordinates in the `Rect`.
231+
///
232+
/// Note: Although a `Rect` is represented by two coordinates, it is
233+
/// spatially represented by four, so this method returns `4`.
234+
fn coords_count(&'a self) -> usize {
235+
4
236+
}
170237
}
171238

172239
// ┌─────────────────────────────┐
@@ -181,6 +248,11 @@ impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for Triangle<T> {
181248
.chain(iter::once(self.1))
182249
.chain(iter::once(self.2))
183250
}
251+
252+
/// Return the number of coordinates in the `Triangle`.
253+
fn coords_count(&'a self) -> usize {
254+
3
255+
}
184256
}
185257

186258
// ┌─────────────────────────────┐
@@ -206,6 +278,22 @@ impl<'a, T: CoordinateType + 'a> CoordsIter<'a, T> for Geometry<T> {
206278
Geometry::Triangle(g) => GeometryCoordsIter::Triangle(g.coords_iter()),
207279
}
208280
}
281+
282+
/// Return the number of coordinates in the `Geometry`.
283+
fn coords_count(&'a self) -> usize {
284+
match self {
285+
Geometry::Point(g) => g.coords_count(),
286+
Geometry::Line(g) => g.coords_count(),
287+
Geometry::LineString(g) => g.coords_count(),
288+
Geometry::Polygon(g) => g.coords_count(),
289+
Geometry::MultiPoint(g) => g.coords_count(),
290+
Geometry::MultiLineString(g) => g.coords_count(),
291+
Geometry::MultiPolygon(g) => g.coords_count(),
292+
Geometry::GeometryCollection(g) => g.coords_count(),
293+
Geometry::Rect(g) => g.coords_count(),
294+
Geometry::Triangle(g) => g.coords_count(),
295+
}
296+
}
209297
}
210298

211299
// ┌───────────┐

geo/src/algorithm/frechet_distance.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::coords_iter::CoordsIter;
12
use crate::euclidean_distance::EuclideanDistance;
23
use crate::{LineString, Point};
34
use num_traits::{Float, FromPrimitive};
@@ -45,13 +46,13 @@ where
4546
T: Float + FromPrimitive,
4647
{
4748
fn frechet_distance(&self, ls: &LineString<T>) -> T {
48-
if self.num_coords() != 0 && ls.num_coords() != 0 {
49+
if self.coords_count() != 0 && ls.coords_count() != 0 {
4950
let mut data = Data {
50-
cache: vec![vec![T::nan(); ls.num_coords()]; self.num_coords()],
51+
cache: vec![vec![T::nan(); ls.coords_count()]; self.coords_count()],
5152
ls_a: self,
5253
ls_b: ls,
5354
};
54-
data.compute(self.num_coords() - 1, ls.num_coords() - 1)
55+
data.compute(self.coords_count() - 1, ls.coords_count() - 1)
5556
} else {
5657
T::zero()
5758
}

geo/src/algorithm/line_interpolate_point.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::coords_iter::CoordsIter;
12
use num_traits::Float;
23
use std::ops::AddAssign;
34

@@ -93,7 +94,7 @@ where
9394
}
9495
// either cum_length + length is never larger than fractional_length, i.e.
9596
// fractional_length is nan, or the linestring has no lines to loop through
96-
debug_assert!(fractional_length.is_nan() || (self.num_coords() == 0));
97+
debug_assert!(fractional_length.is_nan() || (self.coords_count() == 0));
9798
None
9899
} else if fraction < T::zero() {
99100
// negative fractions replaced with zero

geo/src/algorithm/winding_order.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use super::kernels::*;
2+
use crate::coords_iter::CoordsIter;
23
use crate::utils::EitherIter;
34
use crate::{CoordinateType, LineString, Point};
45
use geo_types::PointsIter;
@@ -101,20 +102,20 @@ where
101102
// If linestring has at most 3 coords, it is either
102103
// not closed, or is at most two distinct points.
103104
// Either way, the WindingOrder is unspecified.
104-
if self.num_coords() < 4 || !self.is_closed() {
105+
if self.coords_count() < 4 || !self.is_closed() {
105106
return None;
106107
}
107108

108109
let increment = |x: &mut usize| {
109110
*x += 1;
110-
if *x >= self.num_coords() {
111+
if *x >= self.coords_count() {
111112
*x = 0;
112113
}
113114
};
114115

115116
let decrement = |x: &mut usize| {
116117
if *x == 0 {
117-
*x = self.num_coords() - 1;
118+
*x = self.coords_count() - 1;
118119
} else {
119120
*x -= 1;
120121
}

0 commit comments

Comments
 (0)