From e74d6ce927a9e0417c7ef67fd4488c94bc89d6e6 Mon Sep 17 00:00:00 2001 From: Prathmesh Prabhu Date: Fri, 4 Mar 2022 22:32:38 +0000 Subject: [PATCH 01/17] Add LinesIter trait, impl for Line --- geo/src/algorithm/lines_iter.rs | 67 +++++++++++++++++++++++++++++++++ geo/src/algorithm/mod.rs | 2 + 2 files changed, 69 insertions(+) create mode 100644 geo/src/algorithm/lines_iter.rs diff --git a/geo/src/algorithm/lines_iter.rs b/geo/src/algorithm/lines_iter.rs new file mode 100644 index 0000000000..db4f1472ce --- /dev/null +++ b/geo/src/algorithm/lines_iter.rs @@ -0,0 +1,67 @@ +use crate::{CoordNum, Line, LineString}; +use std::iter::{self, FromFn}; + +pub trait LinesIter<'a> { + type Scalar: CoordNum; + type Iter: Iterator>; + + fn lines_iter(&'a self) -> Self::Iter; +} + +// ┌────────────────────────────┐ +// │ Implementation for Line │ +// └────────────────────────────┘ + +impl<'a, T: CoordNum + 'a> LinesIter<'a> for Line { + type Scalar = T; + type Iter = iter::Copied>>; + + fn lines_iter(&'a self) -> Self::Iter { + iter::once(self).copied() + } +} + +/* +// ┌──────────────────────────────────┐ +// │ Implementation for LineString │ +// └──────────────────────────────────┘ + +impl<'a, T: CoordNum + 'a> LinesIter<'a, T> for LineString { + type Iter = iter::Map>>; + + fn lines_iter(&'a self) -> Self::Iter { + self.0.windows(2).map(|w| { + // slice::windows(N) is guaranteed to yield a slice with exactly N elements + unsafe { Line::new(*w.get_unchecked(0), *w.get_unchecked(1)) } + }) + } +} + +pub struct LinesIterIter<'a, T, + +struct LineStringLinesIterator>> (Iter); + +impl>> Iterator for LineStringLinesIterator { + type Item = Line; + + fn next(&mut self) -> Option { + self.0.next() + } +} + */ +#[cfg(test)] +mod test { + + use super::LinesIter; + use crate::{Coordinate, Line}; + + #[test] + fn test_line() { + let line = Line::new(Coordinate { x: 0., y: 0. }, Coordinate { x: 5., y: 10. }); + let want = vec![Line::new( + Coordinate { x: 0., y: 0. }, + Coordinate { x: 5., y: 10. }, + )]; + assert_eq!(want, line.lines_iter().collect::>()); + } +} diff --git a/geo/src/algorithm/mod.rs b/geo/src/algorithm/mod.rs index e7eb41c5ab..ce93bbcbc7 100644 --- a/geo/src/algorithm/mod.rs +++ b/geo/src/algorithm/mod.rs @@ -61,6 +61,8 @@ pub mod line_interpolate_point; pub mod line_intersection; /// Locate a point along a `Line` or `LineString`. pub mod line_locate_point; +/// Iterate over the lines in a geometry. +pub mod lines_iter; /// Apply a function to all `Coordinates` of a `Geometry`. pub mod map_coords; /// Orient a `Polygon`'s exterior and interior rings. From 77af02d50b109cf0891470fa3efefe205930e530 Mon Sep 17 00:00:00 2001 From: Prathmesh Prabhu Date: Fri, 4 Mar 2022 22:56:41 +0000 Subject: [PATCH 02/17] Implement LinesIter for LineString --- geo/src/algorithm/lines_iter.rs | 68 +++++++++++++++++++++++++-------- 1 file changed, 53 insertions(+), 15 deletions(-) diff --git a/geo/src/algorithm/lines_iter.rs b/geo/src/algorithm/lines_iter.rs index db4f1472ce..32e3f404b2 100644 --- a/geo/src/algorithm/lines_iter.rs +++ b/geo/src/algorithm/lines_iter.rs @@ -1,5 +1,6 @@ -use crate::{CoordNum, Line, LineString}; -use std::iter::{self, FromFn}; +use crate::{Coordinate, CoordNum, Line, LineString}; +use core::slice; +use std::iter; pub trait LinesIter<'a> { type Scalar: CoordNum; @@ -21,39 +22,48 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for Line { } } -/* + // ┌──────────────────────────────────┐ // │ Implementation for LineString │ // └──────────────────────────────────┘ -impl<'a, T: CoordNum + 'a> LinesIter<'a, T> for LineString { - type Iter = iter::Map>>; +impl<'a, T: CoordNum + 'a> LinesIter<'a> for LineString { + type Scalar = T; + type Iter = LineStringLinesIter<'a, T>; fn lines_iter(&'a self) -> Self::Iter { - self.0.windows(2).map(|w| { - // slice::windows(N) is guaranteed to yield a slice with exactly N elements - unsafe { Line::new(*w.get_unchecked(0), *w.get_unchecked(1)) } - }) + LineStringLinesIter::new(self) } } -pub struct LinesIterIter<'a, T, +pub struct LineStringLinesIter<'a, T: CoordNum>(slice::Windows<'a, Coordinate>); -struct LineStringLinesIterator>> (Iter); +impl<'a, T: CoordNum> LineStringLinesIter<'a, T> { + fn new(line_string: &'a LineString) -> Self { + Self(line_string.0.windows(2)) + } +} -impl>> Iterator for LineStringLinesIterator { +impl<'a, T: CoordNum> Iterator for LineStringLinesIter<'a, T> { type Item = Line; fn next(&mut self) -> Option { - self.0.next() + // Can't use LineString::lines() because it returns an `impl Trait` + // and there is no way to name that type in `LinesIter::Iter` until [RFC 2071] is stabilized. + // + // [RFC 2071]: https://rust-lang.github.io/rfcs/2071-impl-trait-existential-types.html + self.0.next().map(|w| { + // slice::windows(2) is guaranteed to yield a slice with exactly 2 elements + unsafe { Line::new(*w.get_unchecked(0), *w.get_unchecked(1)) } + }) } } - */ + #[cfg(test)] mod test { use super::LinesIter; - use crate::{Coordinate, Line}; + use crate::{line_string, Coordinate, Line, LineString}; #[test] fn test_line() { @@ -64,4 +74,32 @@ mod test { )]; assert_eq!(want, line.lines_iter().collect::>()); } + + #[test] + fn test_empty_line_string() { + let ls: LineString = line_string![]; + assert_eq!(Vec::>::new(), ls.lines_iter().collect::>()); + } + + #[test] + fn test_open_line_string() { + let ls = line_string![(x: 0., y: 0.), (x: 1., y: 1.), (x:2., y: 2.)]; + let want = vec![ + Line::new(Coordinate { x: 0., y: 0. }, Coordinate { x: 1., y: 1. }), + Line::new(Coordinate { x: 1., y: 1. }, Coordinate { x: 2., y: 2. }), + ]; + assert_eq!(want, ls.lines_iter().collect::>()); + } + + #[test] + fn test_closed_line_string() { + let mut ls = line_string![(x: 0., y: 0.), (x: 1., y: 1.), (x:2., y: 2.)]; + ls.close(); + let want = vec![ + Line::new(Coordinate { x: 0., y: 0. }, Coordinate { x: 1., y: 1. }), + Line::new(Coordinate { x: 1., y: 1. }, Coordinate { x: 2., y: 2. }), + Line::new(Coordinate { x: 2., y: 2. }, Coordinate { x: 0., y: 0. }), + ]; + assert_eq!(want, ls.lines_iter().collect::>()); + } } From e407ab036438cf50a869311c24c9e63890e97410 Mon Sep 17 00:00:00 2001 From: Prathmesh Prabhu Date: Fri, 4 Mar 2022 23:20:46 +0000 Subject: [PATCH 03/17] Implement LinesIter for MultiLineString --- geo/src/algorithm/lines_iter.rs | 46 +++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/geo/src/algorithm/lines_iter.rs b/geo/src/algorithm/lines_iter.rs index 32e3f404b2..8f90cff5cf 100644 --- a/geo/src/algorithm/lines_iter.rs +++ b/geo/src/algorithm/lines_iter.rs @@ -1,4 +1,4 @@ -use crate::{Coordinate, CoordNum, Line, LineString}; +use crate::{Coordinate, CoordNum, Line, LineString, MultiLineString}; use core::slice; use std::iter; @@ -59,11 +59,38 @@ impl<'a, T: CoordNum> Iterator for LineStringLinesIter<'a, T> { } } + +// ┌───────────────────────────────────────┐ +// │ Implementation for MultiLineString │ +// └───────────────────────────────────────┘ + + +impl<'a, T: CoordNum + 'a> LinesIter<'a> for MultiLineString { + type Scalar = T; + type Iter = iter::Flatten>, LineString>>; + + fn lines_iter(&'a self) -> Self::Iter { + MapLinesIter(self.0.iter()).flatten() + } +} + +pub struct MapLinesIter<'a, Iter1: Iterator, Iter2: 'a + LinesIter<'a>>(Iter1); + +impl<'a, Iter1: Iterator, Iter2: LinesIter<'a>> Iterator + for MapLinesIter<'a, Iter1, Iter2> +{ + type Item = Iter2::Iter; + + fn next(&mut self) -> Option { + self.0.next().map(|g| g.lines_iter()) + } +} + #[cfg(test)] mod test { use super::LinesIter; - use crate::{line_string, Coordinate, Line, LineString}; + use crate::{line_string, Coordinate, Line, LineString, MultiLineString}; #[test] fn test_line() { @@ -102,4 +129,19 @@ mod test { ]; assert_eq!(want, ls.lines_iter().collect::>()); } + + #[test] + fn test_multi_line_string() { + let mls = MultiLineString(vec![ + line_string![], + line_string![(x: 0., y: 0.), (x: 1., y: 1.)], + line_string![(x: 0., y: 0.), (x: 1., y: 1.), (x:2., y: 2.)], + ]); + let want = vec![ + Line::new(Coordinate { x: 0., y: 0. }, Coordinate { x: 1., y: 1. }), + Line::new(Coordinate { x: 0., y: 0. }, Coordinate { x: 1., y: 1. }), + Line::new(Coordinate { x: 1., y: 1. }, Coordinate { x: 2., y: 2. }), + ]; + assert_eq!(want, mls.lines_iter().collect::>()); + } } From 15547daf1df5274931544b9af2d7aa1389380dcd Mon Sep 17 00:00:00 2001 From: Prathmesh Prabhu Date: Fri, 4 Mar 2022 23:39:57 +0000 Subject: [PATCH 04/17] Implement LinesIter for Polygon --- geo/src/algorithm/lines_iter.rs | 52 +++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/geo/src/algorithm/lines_iter.rs b/geo/src/algorithm/lines_iter.rs index 8f90cff5cf..2c246f6ac4 100644 --- a/geo/src/algorithm/lines_iter.rs +++ b/geo/src/algorithm/lines_iter.rs @@ -1,4 +1,4 @@ -use crate::{Coordinate, CoordNum, Line, LineString, MultiLineString}; +use crate::{Coordinate, CoordNum, Line, LineString, MultiLineString, Polygon}; use core::slice; use std::iter; @@ -86,11 +86,31 @@ impl<'a, Iter1: Iterator, Iter2: LinesIter<'a>> Iterator } } + +// ┌───────────────────────────────┐ +// │ Implementation for Polygon │ +// └───────────────────────────────┘ + +type PolygonIter<'a, T> = iter::Chain< + LineStringLinesIter<'a, T>, + iter::Flatten>, LineString>> +>; + +impl<'a, T: CoordNum + 'a> LinesIter<'a> for Polygon { + type Scalar = T; + type Iter = PolygonIter<'a, T>; + + fn lines_iter(&'a self) -> Self::Iter { + self.exterior().lines_iter().chain(MapLinesIter(self.interiors().iter()).flatten()) + } +} + + #[cfg(test)] mod test { use super::LinesIter; - use crate::{line_string, Coordinate, Line, LineString, MultiLineString}; + use crate::{line_string, polygon, Coordinate, Line, LineString, MultiLineString}; #[test] fn test_line() { @@ -144,4 +164,32 @@ mod test { ]; assert_eq!(want, mls.lines_iter().collect::>()); } + + #[test] + fn test_polygon() { + let p = polygon!( + exterior: [(x: 0., y: 0.), (x: 0., y: 10.), (x: 10., y: 10.), (x: 10., y: 0.)], + interiors: [ + [(x: 1., y: 1.), (x: 1., y: 2.), (x: 2., y: 2.), (x: 2., y: 1.)], + [(x: 3., y: 3.), (x: 5., y: 3.), (x: 5., y: 5.), (x: 3., y: 5.)], + ], + ); + let want = vec![ + Line::new(Coordinate { x: 0., y: 0. }, Coordinate { x: 0., y: 10. }), + Line::new(Coordinate { x: 0., y: 10. }, Coordinate { x: 10., y: 10. }), + Line::new(Coordinate { x: 10., y: 10. }, Coordinate { x: 10., y: 0. }), + Line::new(Coordinate { x: 10., y: 0. }, Coordinate { x: 0., y: 0. }), + + Line::new(Coordinate { x: 1., y: 1. }, Coordinate { x: 1., y: 2. }), + Line::new(Coordinate { x: 1., y: 2. }, Coordinate { x: 2., y: 2. }), + Line::new(Coordinate { x: 2., y: 2. }, Coordinate { x: 2., y: 1. }), + Line::new(Coordinate { x: 2., y: 1. }, Coordinate { x: 1., y: 1. }), + + Line::new(Coordinate { x: 3., y: 3. }, Coordinate { x: 5., y: 3. }), + Line::new(Coordinate { x: 5., y: 3. }, Coordinate { x: 5., y: 5. }), + Line::new(Coordinate { x: 5., y: 5. }, Coordinate { x: 3., y: 5. }), + Line::new(Coordinate { x: 3., y: 5. }, Coordinate { x: 3., y: 3. }), + ]; + assert_eq!(want, p.lines_iter().collect::>()); + } } From 62418baa75534d82ea9114f6f457271fde167035 Mon Sep 17 00:00:00 2001 From: Prathmesh Prabhu Date: Fri, 4 Mar 2022 23:49:34 +0000 Subject: [PATCH 05/17] Implement LinesIter for MultiPolygon --- geo/src/algorithm/lines_iter.rs | 65 ++++++++++++++++++++++++++++----- 1 file changed, 55 insertions(+), 10 deletions(-) diff --git a/geo/src/algorithm/lines_iter.rs b/geo/src/algorithm/lines_iter.rs index 2c246f6ac4..dcc683f800 100644 --- a/geo/src/algorithm/lines_iter.rs +++ b/geo/src/algorithm/lines_iter.rs @@ -1,4 +1,4 @@ -use crate::{Coordinate, CoordNum, Line, LineString, MultiLineString, Polygon}; +use crate::{CoordNum, Coordinate, Line, LineString, MultiLineString, MultiPolygon, Polygon}; use core::slice; use std::iter; @@ -22,7 +22,6 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for Line { } } - // ┌──────────────────────────────────┐ // │ Implementation for LineString │ // └──────────────────────────────────┘ @@ -59,12 +58,10 @@ impl<'a, T: CoordNum> Iterator for LineStringLinesIter<'a, T> { } } - // ┌───────────────────────────────────────┐ // │ Implementation for MultiLineString │ // └───────────────────────────────────────┘ - impl<'a, T: CoordNum + 'a> LinesIter<'a> for MultiLineString { type Scalar = T; type Iter = iter::Flatten>, LineString>>; @@ -86,14 +83,13 @@ impl<'a, Iter1: Iterator, Iter2: LinesIter<'a>> Iterator } } - // ┌───────────────────────────────┐ // │ Implementation for Polygon │ // └───────────────────────────────┘ type PolygonIter<'a, T> = iter::Chain< LineStringLinesIter<'a, T>, - iter::Flatten>, LineString>> + iter::Flatten>, LineString>>, >; impl<'a, T: CoordNum + 'a> LinesIter<'a> for Polygon { @@ -101,16 +97,32 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for Polygon { type Iter = PolygonIter<'a, T>; fn lines_iter(&'a self) -> Self::Iter { - self.exterior().lines_iter().chain(MapLinesIter(self.interiors().iter()).flatten()) + self.exterior() + .lines_iter() + .chain(MapLinesIter(self.interiors().iter()).flatten()) } } +// ┌────────────────────────────────────┐ +// │ Implementation for MultiPolygon │ +// └────────────────────────────────────┘ + +impl<'a, T: CoordNum + 'a> LinesIter<'a> for MultiPolygon { + type Scalar = T; + type Iter = iter::Flatten>, Polygon>>; + + fn lines_iter(&'a self) -> Self::Iter { + MapLinesIter(self.0.iter()).flatten() + } +} #[cfg(test)] mod test { use super::LinesIter; - use crate::{line_string, polygon, Coordinate, Line, LineString, MultiLineString}; + use crate::{ + line_string, polygon, Coordinate, Line, LineString, MultiLineString, MultiPolygon, + }; #[test] fn test_line() { @@ -175,16 +187,17 @@ mod test { ], ); let want = vec![ + // exterior ring Line::new(Coordinate { x: 0., y: 0. }, Coordinate { x: 0., y: 10. }), Line::new(Coordinate { x: 0., y: 10. }, Coordinate { x: 10., y: 10. }), Line::new(Coordinate { x: 10., y: 10. }, Coordinate { x: 10., y: 0. }), Line::new(Coordinate { x: 10., y: 0. }, Coordinate { x: 0., y: 0. }), - + // first interior ring Line::new(Coordinate { x: 1., y: 1. }, Coordinate { x: 1., y: 2. }), Line::new(Coordinate { x: 1., y: 2. }, Coordinate { x: 2., y: 2. }), Line::new(Coordinate { x: 2., y: 2. }, Coordinate { x: 2., y: 1. }), Line::new(Coordinate { x: 2., y: 1. }, Coordinate { x: 1., y: 1. }), - + // second interior ring Line::new(Coordinate { x: 3., y: 3. }, Coordinate { x: 5., y: 3. }), Line::new(Coordinate { x: 5., y: 3. }, Coordinate { x: 5., y: 5. }), Line::new(Coordinate { x: 5., y: 5. }, Coordinate { x: 3., y: 5. }), @@ -192,4 +205,36 @@ mod test { ]; assert_eq!(want, p.lines_iter().collect::>()); } + + #[test] + fn test_multi_polygon() { + let mp = MultiPolygon(vec![ + polygon!( + exterior: [(x: 0., y: 0.), (x: 0., y: 10.), (x: 10., y: 10.), (x: 10., y: 0.)], + interiors: [[(x: 1., y: 1.), (x: 1., y: 2.), (x: 2., y: 2.), (x: 2., y: 1.)]], + ), + polygon!( + exterior: [(x: 3., y: 3.), (x: 5., y: 3.), (x: 5., y: 5.), (x: 3., y: 5.)], + interiors: [], + ), + ]); + let want = vec![ + // first polygon - exterior ring + Line::new(Coordinate { x: 0., y: 0. }, Coordinate { x: 0., y: 10. }), + Line::new(Coordinate { x: 0., y: 10. }, Coordinate { x: 10., y: 10. }), + Line::new(Coordinate { x: 10., y: 10. }, Coordinate { x: 10., y: 0. }), + Line::new(Coordinate { x: 10., y: 0. }, Coordinate { x: 0., y: 0. }), + // first polygon - interior ring + Line::new(Coordinate { x: 1., y: 1. }, Coordinate { x: 1., y: 2. }), + Line::new(Coordinate { x: 1., y: 2. }, Coordinate { x: 2., y: 2. }), + Line::new(Coordinate { x: 2., y: 2. }, Coordinate { x: 2., y: 1. }), + Line::new(Coordinate { x: 2., y: 1. }, Coordinate { x: 1., y: 1. }), + // second polygon - exterior ring + Line::new(Coordinate { x: 3., y: 3. }, Coordinate { x: 5., y: 3. }), + Line::new(Coordinate { x: 5., y: 3. }, Coordinate { x: 5., y: 5. }), + Line::new(Coordinate { x: 5., y: 5. }, Coordinate { x: 3., y: 5. }), + Line::new(Coordinate { x: 3., y: 5. }, Coordinate { x: 3., y: 3. }), + ]; + assert_eq!(want, mp.lines_iter().collect::>()); + } } From 5797f4615311de55f9be537cb5f3c7494c4aab03 Mon Sep 17 00:00:00 2001 From: Prathmesh Prabhu Date: Sat, 5 Mar 2022 05:34:08 +0000 Subject: [PATCH 06/17] Implement LinesIter for Rect --- geo-types/src/rect.rs | 8 ++++---- geo/src/algorithm/lines_iter.rs | 26 ++++++++++++++++++++++++-- 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/geo-types/src/rect.rs b/geo-types/src/rect.rs index a7b69523b0..c5a76df339 100644 --- a/geo-types/src/rect.rs +++ b/geo-types/src/rect.rs @@ -248,8 +248,8 @@ impl Rect { ), Line::new( Coordinate { - x: self.min.x, - y: self.min.y, + x: self.max.x, + y: self.max.y, }, Coordinate { x: self.max.x, @@ -262,8 +262,8 @@ impl Rect { y: self.min.y, }, Coordinate { - x: self.max.x, - y: self.max.y, + x: self.min.x, + y: self.min.y, }, ), ] diff --git a/geo/src/algorithm/lines_iter.rs b/geo/src/algorithm/lines_iter.rs index dcc683f800..acdd53386e 100644 --- a/geo/src/algorithm/lines_iter.rs +++ b/geo/src/algorithm/lines_iter.rs @@ -1,4 +1,4 @@ -use crate::{CoordNum, Coordinate, Line, LineString, MultiLineString, MultiPolygon, Polygon}; +use crate::{CoordNum, Coordinate, Line, LineString, MultiLineString, MultiPolygon, Polygon, Rect}; use core::slice; use std::iter; @@ -116,12 +116,27 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for MultiPolygon { } } +// ┌────────────────────────────┐ +// │ Implementation for Rect │ +// └────────────────────────────┘ + +impl<'a, T: CoordNum + 'a> LinesIter<'a> for Rect { + type Scalar = T; + type Iter = <[Line; 4] as IntoIterator>::IntoIter; + + fn lines_iter(&'a self) -> Self::Iter { + // Explicitly iterate by value so this works for pre-2021 rust editions. + // See https://doc.rust-lang.org/std/primitive.array.html#editions + IntoIterator::into_iter(self.to_lines()) + } +} + #[cfg(test)] mod test { use super::LinesIter; use crate::{ - line_string, polygon, Coordinate, Line, LineString, MultiLineString, MultiPolygon, + line_string, polygon, Coordinate, Line, LineString, MultiLineString, MultiPolygon, Rect, }; #[test] @@ -237,4 +252,11 @@ mod test { ]; assert_eq!(want, mp.lines_iter().collect::>()); } + + #[test] + fn test_rect() { + let rect = Rect::new(Coordinate { x: 0., y: 0. }, Coordinate { x: 1., y: 2. }); + let want = rect.to_polygon().lines_iter().collect::>(); + assert_eq!(want, rect.lines_iter().collect::>()); + } } From 807aca69bbad783496b265c9de99c8dbe1935d34 Mon Sep 17 00:00:00 2001 From: Prathmesh Prabhu Date: Sat, 5 Mar 2022 05:41:30 +0000 Subject: [PATCH 07/17] Implement LinesIter for Triangle --- geo/src/algorithm/lines_iter.rs | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/geo/src/algorithm/lines_iter.rs b/geo/src/algorithm/lines_iter.rs index acdd53386e..4f75a41ca4 100644 --- a/geo/src/algorithm/lines_iter.rs +++ b/geo/src/algorithm/lines_iter.rs @@ -1,4 +1,4 @@ -use crate::{CoordNum, Coordinate, Line, LineString, MultiLineString, MultiPolygon, Polygon, Rect}; +use crate::{CoordNum, Coordinate, Line, LineString, MultiLineString, MultiPolygon, Polygon, Rect, Triangle}; use core::slice; use std::iter; @@ -131,12 +131,29 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for Rect { } } + +// ┌────────────────────────────────┐ +// │ Implementation for Triangle │ +// └────────────────────────────────┘ + + +impl<'a, T: CoordNum + 'a> LinesIter<'a> for Triangle { + type Scalar = T; + type Iter = <[Line; 3] as IntoIterator>::IntoIter; + + fn lines_iter(&'a self) -> Self::Iter { + // Explicitly iterate by value so this works for pre-2021 rust editions. + // See https://doc.rust-lang.org/std/primitive.array.html#editions + IntoIterator::into_iter(self.to_lines()) + } +} + #[cfg(test)] mod test { use super::LinesIter; use crate::{ - line_string, polygon, Coordinate, Line, LineString, MultiLineString, MultiPolygon, Rect, + line_string, polygon, Coordinate, Line, LineString, MultiLineString, MultiPolygon, Rect, Triangle }; #[test] @@ -259,4 +276,11 @@ mod test { let want = rect.to_polygon().lines_iter().collect::>(); assert_eq!(want, rect.lines_iter().collect::>()); } + + #[test] + fn test_triangle() { + let triangle = Triangle(Coordinate { x: 0., y: 0. }, Coordinate { x: 1., y: 2. }, Coordinate { x: 2., y: 3.}); + let want = triangle.to_polygon().lines_iter().collect::>(); + assert_eq!(want, triangle.lines_iter().collect::>()); + } } From c4a5a68b78e5c7045be8b178cb749fb62cae9a56 Mon Sep 17 00:00:00 2001 From: Prathmesh Prabhu Date: Sat, 5 Mar 2022 06:05:45 +0000 Subject: [PATCH 08/17] Uniformly use Self::Scalar in associated types --- geo/src/algorithm/lines_iter.rs | 50 ++++++++++++++++++++++----------- 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/geo/src/algorithm/lines_iter.rs b/geo/src/algorithm/lines_iter.rs index 4f75a41ca4..2c1eb02771 100644 --- a/geo/src/algorithm/lines_iter.rs +++ b/geo/src/algorithm/lines_iter.rs @@ -1,4 +1,8 @@ -use crate::{CoordNum, Coordinate, Line, LineString, MultiLineString, MultiPolygon, Polygon, Rect, Triangle}; + +use std::fmt::Debug; +use crate::{ + CoordNum, Coordinate, Line, LineString, MultiLineString, MultiPolygon, Polygon, Rect, Triangle, +}; use core::slice; use std::iter; @@ -15,7 +19,7 @@ pub trait LinesIter<'a> { impl<'a, T: CoordNum + 'a> LinesIter<'a> for Line { type Scalar = T; - type Iter = iter::Copied>>; + type Iter = iter::Copied>>; fn lines_iter(&'a self) -> Self::Iter { iter::once(self).copied() @@ -28,22 +32,22 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for Line { impl<'a, T: CoordNum + 'a> LinesIter<'a> for LineString { type Scalar = T; - type Iter = LineStringLinesIter<'a, T>; + type Iter = LineStringIter<'a, Self::Scalar>; fn lines_iter(&'a self) -> Self::Iter { - LineStringLinesIter::new(self) + LineStringIter::new(self) } } -pub struct LineStringLinesIter<'a, T: CoordNum>(slice::Windows<'a, Coordinate>); +pub struct LineStringIter<'a, T: CoordNum>(slice::Windows<'a, Coordinate>); -impl<'a, T: CoordNum> LineStringLinesIter<'a, T> { +impl<'a, T: CoordNum> LineStringIter<'a, T> { fn new(line_string: &'a LineString) -> Self { Self(line_string.0.windows(2)) } } -impl<'a, T: CoordNum> Iterator for LineStringLinesIter<'a, T> { +impl<'a, T: CoordNum> Iterator for LineStringIter<'a, T> { type Item = Line; fn next(&mut self) -> Option { @@ -62,15 +66,21 @@ impl<'a, T: CoordNum> Iterator for LineStringLinesIter<'a, T> { // │ Implementation for MultiLineString │ // └───────────────────────────────────────┘ +type MultiLineStringIter<'a, T> = + iter::Flatten>, LineString>>; + impl<'a, T: CoordNum + 'a> LinesIter<'a> for MultiLineString { type Scalar = T; - type Iter = iter::Flatten>, LineString>>; + type Iter = MultiLineStringIter<'a, Self::Scalar>; fn lines_iter(&'a self) -> Self::Iter { MapLinesIter(self.0.iter()).flatten() } } +// Utility to transform Iterator into Iterator> +#[doc(hidden)] +#[derive(Debug)] pub struct MapLinesIter<'a, Iter1: Iterator, Iter2: 'a + LinesIter<'a>>(Iter1); impl<'a, Iter1: Iterator, Iter2: LinesIter<'a>> Iterator @@ -88,13 +98,13 @@ impl<'a, Iter1: Iterator, Iter2: LinesIter<'a>> Iterator // └───────────────────────────────┘ type PolygonIter<'a, T> = iter::Chain< - LineStringLinesIter<'a, T>, + LineStringIter<'a, T>, iter::Flatten>, LineString>>, >; impl<'a, T: CoordNum + 'a> LinesIter<'a> for Polygon { type Scalar = T; - type Iter = PolygonIter<'a, T>; + type Iter = PolygonIter<'a, Self::Scalar>; fn lines_iter(&'a self) -> Self::Iter { self.exterior() @@ -107,9 +117,12 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for Polygon { // │ Implementation for MultiPolygon │ // └────────────────────────────────────┘ +type MultiPolygonIter<'a, T> = + iter::Flatten>, Polygon>>; + impl<'a, T: CoordNum + 'a> LinesIter<'a> for MultiPolygon { type Scalar = T; - type Iter = iter::Flatten>, Polygon>>; + type Iter = MultiPolygonIter<'a, Self::Scalar>; fn lines_iter(&'a self) -> Self::Iter { MapLinesIter(self.0.iter()).flatten() @@ -122,7 +135,7 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for MultiPolygon { impl<'a, T: CoordNum + 'a> LinesIter<'a> for Rect { type Scalar = T; - type Iter = <[Line; 4] as IntoIterator>::IntoIter; + type Iter = <[Line; 4] as IntoIterator>::IntoIter; fn lines_iter(&'a self) -> Self::Iter { // Explicitly iterate by value so this works for pre-2021 rust editions. @@ -131,15 +144,13 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for Rect { } } - // ┌────────────────────────────────┐ // │ Implementation for Triangle │ // └────────────────────────────────┘ - impl<'a, T: CoordNum + 'a> LinesIter<'a> for Triangle { type Scalar = T; - type Iter = <[Line; 3] as IntoIterator>::IntoIter; + type Iter = <[Line; 3] as IntoIterator>::IntoIter; fn lines_iter(&'a self) -> Self::Iter { // Explicitly iterate by value so this works for pre-2021 rust editions. @@ -153,7 +164,8 @@ mod test { use super::LinesIter; use crate::{ - line_string, polygon, Coordinate, Line, LineString, MultiLineString, MultiPolygon, Rect, Triangle + line_string, polygon, Coordinate, Line, LineString, MultiLineString, MultiPolygon, Rect, + Triangle, }; #[test] @@ -279,7 +291,11 @@ mod test { #[test] fn test_triangle() { - let triangle = Triangle(Coordinate { x: 0., y: 0. }, Coordinate { x: 1., y: 2. }, Coordinate { x: 2., y: 3.}); + let triangle = Triangle( + Coordinate { x: 0., y: 0. }, + Coordinate { x: 1., y: 2. }, + Coordinate { x: 2., y: 3. }, + ); let want = triangle.to_polygon().lines_iter().collect::>(); assert_eq!(want, triangle.lines_iter().collect::>()); } From e3f1680d339e436574e41e6bdff0e19a2f6b5b80 Mon Sep 17 00:00:00 2001 From: Prathmesh Prabhu Date: Sat, 5 Mar 2022 06:33:45 +0000 Subject: [PATCH 09/17] Add docs --- geo/src/algorithm/lines_iter.rs | 60 +++++++++++++++++++++++---------- 1 file changed, 43 insertions(+), 17 deletions(-) diff --git a/geo/src/algorithm/lines_iter.rs b/geo/src/algorithm/lines_iter.rs index 2c1eb02771..6996b72713 100644 --- a/geo/src/algorithm/lines_iter.rs +++ b/geo/src/algorithm/lines_iter.rs @@ -1,15 +1,35 @@ - -use std::fmt::Debug; use crate::{ CoordNum, Coordinate, Line, LineString, MultiLineString, MultiPolygon, Polygon, Rect, Triangle, }; use core::slice; +use std::fmt::Debug; use std::iter; +/// Iterate over lines of a geometry. pub trait LinesIter<'a> { type Scalar: CoordNum; type Iter: Iterator>; + /// Iterate over all exterior and (if any) interior lines of a geometry. + /// + /// # Examples + /// + /// ``` + /// use geo::{Coordinate, Line}; + /// use geo::line_string; + /// use geo::lines_iter::LinesIter; + /// + /// let ls = line_string![ + /// (x: 1., y: 2.), + /// (x: 23., y: 82.), + /// (x: -1., y: 0.), + /// ]; + /// + /// let mut iter = ls.lines_iter(); + /// assert_eq!(Some(Line::new(Coordinate{x: 1., y: 2.}, Coordinate{x: 23., y:82.})), iter.next()); + /// assert_eq!(Some(Line::new(Coordinate{x: 23., y: 82.}, Coordinate{x: -1., y:0.})), iter.next()); + /// assert_eq!(None, iter.next()); + /// ``` fn lines_iter(&'a self) -> Self::Iter; } @@ -39,6 +59,8 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for LineString { } } +#[doc(hidden)] +#[derive(Debug)] pub struct LineStringIter<'a, T: CoordNum>(slice::Windows<'a, Coordinate>); impl<'a, T: CoordNum> LineStringIter<'a, T> { @@ -78,21 +100,6 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for MultiLineString { } } -// Utility to transform Iterator into Iterator> -#[doc(hidden)] -#[derive(Debug)] -pub struct MapLinesIter<'a, Iter1: Iterator, Iter2: 'a + LinesIter<'a>>(Iter1); - -impl<'a, Iter1: Iterator, Iter2: LinesIter<'a>> Iterator - for MapLinesIter<'a, Iter1, Iter2> -{ - type Item = Iter2::Iter; - - fn next(&mut self) -> Option { - self.0.next().map(|g| g.lines_iter()) - } -} - // ┌───────────────────────────────┐ // │ Implementation for Polygon │ // └───────────────────────────────┘ @@ -159,6 +166,25 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for Triangle { } } +// ┌───────────┐ +// │ Utilities │ +// └───────────┘ + +// Transform Iterator into Iterator> +#[doc(hidden)] +#[derive(Debug)] +pub struct MapLinesIter<'a, Iter1: Iterator, Iter2: 'a + LinesIter<'a>>(Iter1); + +impl<'a, Iter1: Iterator, Iter2: LinesIter<'a>> Iterator + for MapLinesIter<'a, Iter1, Iter2> +{ + type Item = Iter2::Iter; + + fn next(&mut self) -> Option { + self.0.next().map(|g| g.lines_iter()) + } +} + #[cfg(test)] mod test { From 2fb1314bd237521735854530661cfeed83d209b3 Mon Sep 17 00:00:00 2001 From: Prathmesh Prabhu Date: Sat, 5 Mar 2022 06:44:01 +0000 Subject: [PATCH 10/17] Update changelog --- geo/CHANGES.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/geo/CHANGES.md b/geo/CHANGES.md index 461b812015..aa1205bbb3 100644 --- a/geo/CHANGES.md +++ b/geo/CHANGES.md @@ -2,7 +2,9 @@ ## Unreleased -* +* Add `LinesIter` algorithm to iterate over the lines in geometries. + * Very similar to `CoordsIter`, but only implemented where it makes sense (e.g., for `Polygon`, `Rect`, but not `Point`). + * TODO: PR ref TBD ## 0.19.0 From cdf0b225ba3d9ef6147526de9c9f54b87a0c822e Mon Sep 17 00:00:00 2001 From: Prathmesh Prabhu Date: Sat, 5 Mar 2022 06:46:12 +0000 Subject: [PATCH 11/17] Changelog for geo-types --- geo-types/CHANGES.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/geo-types/CHANGES.md b/geo-types/CHANGES.md index 0f5d67695d..f45e4a591a 100644 --- a/geo-types/CHANGES.md +++ b/geo-types/CHANGES.md @@ -2,8 +2,10 @@ ## Unreleased +* Make `Rect::to_lines` return lines in winding order for `Rect::to_polygon`. + * TODO: PR number TBD. * Macros `coord!`, `point!`, `line_string!`, and `polygon!` now support trailing commas such as `coord! { x: 181.2, y: 51.79, }` - * + * ## 0.7.3 From 59e8403033d35b8168e2af6760bde8b8d3085616 Mon Sep 17 00:00:00 2001 From: Prathmesh Prabhu Date: Sat, 5 Mar 2022 06:50:53 +0000 Subject: [PATCH 12/17] Add PR reference --- geo-types/CHANGES.md | 2 +- geo/CHANGES.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/geo-types/CHANGES.md b/geo-types/CHANGES.md index f45e4a591a..314dfbd4e2 100644 --- a/geo-types/CHANGES.md +++ b/geo-types/CHANGES.md @@ -3,7 +3,7 @@ ## Unreleased * Make `Rect::to_lines` return lines in winding order for `Rect::to_polygon`. - * TODO: PR number TBD. + * * Macros `coord!`, `point!`, `line_string!`, and `polygon!` now support trailing commas such as `coord! { x: 181.2, y: 51.79, }` * diff --git a/geo/CHANGES.md b/geo/CHANGES.md index aa1205bbb3..5caa1dc97b 100644 --- a/geo/CHANGES.md +++ b/geo/CHANGES.md @@ -4,7 +4,7 @@ * Add `LinesIter` algorithm to iterate over the lines in geometries. * Very similar to `CoordsIter`, but only implemented where it makes sense (e.g., for `Polygon`, `Rect`, but not `Point`). - * TODO: PR ref TBD + * ## 0.19.0 From 0b20e6d847642f56f06c86c5190fd3ed07927cc9 Mon Sep 17 00:00:00 2001 From: Prathmesh Prabhu Date: Mon, 7 Mar 2022 05:15:17 +0000 Subject: [PATCH 13/17] Address review comments --- geo-types/CHANGES.md | 2 +- geo/src/algorithm/lines_iter.rs | 57 +++++++++++---------------------- 2 files changed, 19 insertions(+), 40 deletions(-) diff --git a/geo-types/CHANGES.md b/geo-types/CHANGES.md index 314dfbd4e2..6b931beaa1 100644 --- a/geo-types/CHANGES.md +++ b/geo-types/CHANGES.md @@ -2,7 +2,7 @@ ## Unreleased -* Make `Rect::to_lines` return lines in winding order for `Rect::to_polygon`. +* BREAKING: Make `Rect::to_lines` return lines in winding order for `Rect::to_polygon`. * * Macros `coord!`, `point!`, `line_string!`, and `polygon!` now support trailing commas such as `coord! { x: 181.2, y: 51.79, }` * diff --git a/geo/src/algorithm/lines_iter.rs b/geo/src/algorithm/lines_iter.rs index 6996b72713..648ffea726 100644 --- a/geo/src/algorithm/lines_iter.rs +++ b/geo/src/algorithm/lines_iter.rs @@ -15,9 +15,9 @@ pub trait LinesIter<'a> { /// # Examples /// /// ``` - /// use geo::{Coordinate, Line}; /// use geo::line_string; /// use geo::lines_iter::LinesIter; + /// use geo::{Coordinate, Line}; /// /// let ls = line_string![ /// (x: 1., y: 2.), @@ -26,17 +26,25 @@ pub trait LinesIter<'a> { /// ]; /// /// let mut iter = ls.lines_iter(); - /// assert_eq!(Some(Line::new(Coordinate{x: 1., y: 2.}, Coordinate{x: 23., y:82.})), iter.next()); - /// assert_eq!(Some(Line::new(Coordinate{x: 23., y: 82.}, Coordinate{x: -1., y:0.})), iter.next()); + /// assert_eq!( + /// Some(Line::new( + /// Coordinate { x: 1., y: 2. }, + /// Coordinate { x: 23., y: 82. } + /// )), + /// iter.next() + /// ); + /// assert_eq!( + /// Some(Line::new( + /// Coordinate { x: 23., y: 82. }, + /// Coordinate { x: -1., y: 0. } + /// )), + /// iter.next() + /// ); /// assert_eq!(None, iter.next()); /// ``` fn lines_iter(&'a self) -> Self::Iter; } -// ┌────────────────────────────┐ -// │ Implementation for Line │ -// └────────────────────────────┘ - impl<'a, T: CoordNum + 'a> LinesIter<'a> for Line { type Scalar = T; type Iter = iter::Copied>>; @@ -46,10 +54,6 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for Line { } } -// ┌──────────────────────────────────┐ -// │ Implementation for LineString │ -// └──────────────────────────────────┘ - impl<'a, T: CoordNum + 'a> LinesIter<'a> for LineString { type Scalar = T; type Iter = LineStringIter<'a, Self::Scalar>; @@ -59,7 +63,7 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for LineString { } } -#[doc(hidden)] +/// Iterator over lines in a [LineString]. #[derive(Debug)] pub struct LineStringIter<'a, T: CoordNum>(slice::Windows<'a, Coordinate>); @@ -78,16 +82,12 @@ impl<'a, T: CoordNum> Iterator for LineStringIter<'a, T> { // // [RFC 2071]: https://rust-lang.github.io/rfcs/2071-impl-trait-existential-types.html self.0.next().map(|w| { - // slice::windows(2) is guaranteed to yield a slice with exactly 2 elements + // SAFETY: slice::windows(2) is guaranteed to yield a slice with exactly 2 elements unsafe { Line::new(*w.get_unchecked(0), *w.get_unchecked(1)) } }) } } -// ┌───────────────────────────────────────┐ -// │ Implementation for MultiLineString │ -// └───────────────────────────────────────┘ - type MultiLineStringIter<'a, T> = iter::Flatten>, LineString>>; @@ -100,10 +100,6 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for MultiLineString { } } -// ┌───────────────────────────────┐ -// │ Implementation for Polygon │ -// └───────────────────────────────┘ - type PolygonIter<'a, T> = iter::Chain< LineStringIter<'a, T>, iter::Flatten>, LineString>>, @@ -120,10 +116,6 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for Polygon { } } -// ┌────────────────────────────────────┐ -// │ Implementation for MultiPolygon │ -// └────────────────────────────────────┘ - type MultiPolygonIter<'a, T> = iter::Flatten>, Polygon>>; @@ -136,10 +128,6 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for MultiPolygon { } } -// ┌────────────────────────────┐ -// │ Implementation for Rect │ -// └────────────────────────────┘ - impl<'a, T: CoordNum + 'a> LinesIter<'a> for Rect { type Scalar = T; type Iter = <[Line; 4] as IntoIterator>::IntoIter; @@ -151,10 +139,6 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for Rect { } } -// ┌────────────────────────────────┐ -// │ Implementation for Triangle │ -// └────────────────────────────────┘ - impl<'a, T: CoordNum + 'a> LinesIter<'a> for Triangle { type Scalar = T; type Iter = <[Line; 3] as IntoIterator>::IntoIter; @@ -166,12 +150,7 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for Triangle { } } -// ┌───────────┐ -// │ Utilities │ -// └───────────┘ - -// Transform Iterator into Iterator> -#[doc(hidden)] +/// An iterator that transform Iterator into Iterator> #[derive(Debug)] pub struct MapLinesIter<'a, Iter1: Iterator, Iter2: 'a + LinesIter<'a>>(Iter1); From d9510be4f2a9468408cb362b524fb41e7460fee8 Mon Sep 17 00:00:00 2001 From: Prathmesh Prabhu Date: Mon, 7 Mar 2022 05:27:23 +0000 Subject: [PATCH 14/17] Add TODO and top-level docs link --- geo/src/algorithm/lines_iter.rs | 10 +++++++++- geo/src/lib.rs | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/geo/src/algorithm/lines_iter.rs b/geo/src/algorithm/lines_iter.rs index 648ffea726..b17f0ce2fc 100644 --- a/geo/src/algorithm/lines_iter.rs +++ b/geo/src/algorithm/lines_iter.rs @@ -135,6 +135,10 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for Rect { fn lines_iter(&'a self) -> Self::Iter { // Explicitly iterate by value so this works for pre-2021 rust editions. // See https://doc.rust-lang.org/std/primitive.array.html#editions + // + // TODO: Simplify once [#741] bumps MSRV. + // + // [#741]: https://github.com/georust/geo/pull/741 IntoIterator::into_iter(self.to_lines()) } } @@ -146,11 +150,15 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for Triangle { fn lines_iter(&'a self) -> Self::Iter { // Explicitly iterate by value so this works for pre-2021 rust editions. // See https://doc.rust-lang.org/std/primitive.array.html#editions + // + // TODO: Simplify once [#741] bumps MSRV. + // + // [#741]: https://github.com/georust/geo/pull/741 IntoIterator::into_iter(self.to_lines()) } } -/// An iterator that transform Iterator into Iterator> +/// Utility to transform Iterator into Iterator>. #[derive(Debug)] pub struct MapLinesIter<'a, Iter1: Iterator, Iter2: 'a + LinesIter<'a>>(Iter1); diff --git a/geo/src/lib.rs b/geo/src/lib.rs index 2fe7436345..478fa2e71c 100644 --- a/geo/src/lib.rs +++ b/geo/src/lib.rs @@ -103,6 +103,7 @@ //! coordinates in a geometry in-place //! - **[`TryMapCoords`](algorithm::map_coords::TryMapCoords)**: Map a fallible function over all //! the coordinates in a geometry, returning a new geometry wrapped in a `Result` +//! - **[`LinesIter`](algorithm::lines_iter::LinesIter)**: Iterate over lines of a geometry //! //! ## Boundary //! From 4a1f61e5babf8ee0ae445de7dc548575eaddbd0b Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 8 Mar 2022 17:52:30 -0500 Subject: [PATCH 15/17] point ctor --- geo-types/src/point.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/geo-types/src/point.rs b/geo-types/src/point.rs index 53cf8aef02..f3d9a0cbf2 100644 --- a/geo-types/src/point.rs +++ b/geo-types/src/point.rs @@ -232,10 +232,10 @@ impl Point { /// # Examples /// /// ``` - /// use geo_types::{coord, Point}; + /// use geo_types::Point; /// - /// let point = Point(coord! { x: 1.5, y: 0.5 }); - /// let dot = point.dot(Point(coord! { x: 2.0, y: 4.5 })); + /// let point = Point::new(1.5, 0.5); + /// let dot = point.dot(Point::new(2.0, 4.5); /// /// assert_eq!(dot, 5.25); /// ``` @@ -250,11 +250,11 @@ impl Point { /// # Examples /// /// ``` - /// use geo_types::{coord, Point}; + /// use geo_types::Point; /// - /// let point_a = Point(coord! { x: 1., y: 2. }); - /// let point_b = Point(coord! { x: 3., y: 5. }); - /// let point_c = Point(coord! { x: 7., y: 12. }); + /// let point_a = Point::new(1., 2.); + /// let point_b = Point::new(3., 5.); + /// let point_c = Point::new(7., 12.); /// /// let cross = point_a.cross_prod(point_b, point_c); /// From cb6c55f8d2ebf9452d5edcf4270af313801d00ed Mon Sep 17 00:00:00 2001 From: Yuri Astrakhan Date: Tue, 8 Mar 2022 18:33:55 -0500 Subject: [PATCH 16/17] Revert "point ctor" This reverts commit 4a1f61e5babf8ee0ae445de7dc548575eaddbd0b. --- geo-types/src/point.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/geo-types/src/point.rs b/geo-types/src/point.rs index f3d9a0cbf2..53cf8aef02 100644 --- a/geo-types/src/point.rs +++ b/geo-types/src/point.rs @@ -232,10 +232,10 @@ impl Point { /// # Examples /// /// ``` - /// use geo_types::Point; + /// use geo_types::{coord, Point}; /// - /// let point = Point::new(1.5, 0.5); - /// let dot = point.dot(Point::new(2.0, 4.5); + /// let point = Point(coord! { x: 1.5, y: 0.5 }); + /// let dot = point.dot(Point(coord! { x: 2.0, y: 4.5 })); /// /// assert_eq!(dot, 5.25); /// ``` @@ -250,11 +250,11 @@ impl Point { /// # Examples /// /// ``` - /// use geo_types::Point; + /// use geo_types::{coord, Point}; /// - /// let point_a = Point::new(1., 2.); - /// let point_b = Point::new(3., 5.); - /// let point_c = Point::new(7., 12.); + /// let point_a = Point(coord! { x: 1., y: 2. }); + /// let point_b = Point(coord! { x: 3., y: 5. }); + /// let point_c = Point(coord! { x: 7., y: 12. }); /// /// let cross = point_a.cross_prod(point_b, point_c); /// From 3605cb8c6d7e82433ceddbb458c39315086e1e77 Mon Sep 17 00:00:00 2001 From: Prathmesh Prabhu Date: Wed, 9 Mar 2022 05:21:15 +0000 Subject: [PATCH 17/17] Update array iteration to post-2021 rustc flavor --- geo/src/algorithm/lines_iter.rs | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/geo/src/algorithm/lines_iter.rs b/geo/src/algorithm/lines_iter.rs index b17f0ce2fc..8f3d2374fa 100644 --- a/geo/src/algorithm/lines_iter.rs +++ b/geo/src/algorithm/lines_iter.rs @@ -133,13 +133,7 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for Rect { type Iter = <[Line; 4] as IntoIterator>::IntoIter; fn lines_iter(&'a self) -> Self::Iter { - // Explicitly iterate by value so this works for pre-2021 rust editions. - // See https://doc.rust-lang.org/std/primitive.array.html#editions - // - // TODO: Simplify once [#741] bumps MSRV. - // - // [#741]: https://github.com/georust/geo/pull/741 - IntoIterator::into_iter(self.to_lines()) + self.to_lines().into_iter() } } @@ -148,13 +142,7 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for Triangle { type Iter = <[Line; 3] as IntoIterator>::IntoIter; fn lines_iter(&'a self) -> Self::Iter { - // Explicitly iterate by value so this works for pre-2021 rust editions. - // See https://doc.rust-lang.org/std/primitive.array.html#editions - // - // TODO: Simplify once [#741] bumps MSRV. - // - // [#741]: https://github.com/georust/geo/pull/741 - IntoIterator::into_iter(self.to_lines()) + self.to_lines().into_iter() } }