From c083f643bab67ee343b634cfb3785707dfb70c4b Mon Sep 17 00:00:00 2001 From: Michael Kirk Date: Fri, 22 Apr 2022 10:34:40 -0700 Subject: [PATCH] Deprecate pub geo-type fields, add getters/setters plus some other methods to help migrate from direct field access. This is intended to be a non-breaking change for now, to give people an upgrade window. In an upcoming *breaking* release of geo-types we'll drop pub field access altogether. This is in pursuit of adding support for 3D/4D geometries. We'll leverage generics in a way that is intended to avoid runtime cost for our mostly 2D user base. See https://github.com/georust/geo/issues/5 for more. This commit includes a bunch of new methods that correspond to the deprecated field access. See geo-types/CHANGES.md for a summary. `#[inline]` hints were added to maintain performance (it's actually improved in some places!) geo was updated to address all the deprecations. --- geo-postgis/src/to_postgis.rs | 20 ++- geo-types/CHANGES.md | 52 +++++++ geo-types/src/coordinate.rs | 124 +++++++++++------ geo-types/src/geometry_collection.rs | 50 +++++-- geo-types/src/lib.rs | 6 +- geo-types/src/line.rs | 73 ++++++++-- geo-types/src/line_string.rs | 111 +++++++++++---- geo-types/src/macros.rs | 2 +- geo-types/src/multi_line_string.rs | 59 ++++++-- geo-types/src/multi_point.rs | 58 ++++++-- geo-types/src/multi_polygon.rs | 59 ++++++-- geo-types/src/point.rs | 130 ++++++++++++++---- geo-types/src/polygon.rs | 17 ++- geo-types/src/private_utils.rs | 37 ++--- geo-types/src/rect.rs | 64 ++++----- geo-types/src/triangle.rs | 101 ++++++++++++-- geo/Cargo.toml | 1 + geo/benches/relate.rs | 2 +- geo/examples/concavehull-usage.rs | 27 ++-- geo/examples/types.rs | 5 +- geo/fuzz/fuzz_targets/simplify.rs | 4 +- geo/src/algorithm/area.rs | 18 ++- geo/src/algorithm/bounding_rect.rs | 28 ++-- geo/src/algorithm/centroid.rs | 69 +++++----- geo/src/algorithm/chaikin_smoothing.rs | 22 ++- .../algorithm/chamberlain_duquette_area.rs | 4 +- geo/src/algorithm/closest_point.rs | 12 +- geo/src/algorithm/concave_hull.rs | 25 ++-- geo/src/algorithm/contains/geometry.rs | 2 +- geo/src/algorithm/contains/line.rs | 20 +-- geo/src/algorithm/contains/line_string.rs | 34 ++--- geo/src/algorithm/contains/point.rs | 4 +- geo/src/algorithm/contains/polygon.rs | 4 +- geo/src/algorithm/contains/rect.rs | 18 +-- geo/src/algorithm/contains/triangle.rs | 9 +- geo/src/algorithm/convex_hull/graham.rs | 4 +- geo/src/algorithm/convex_hull/mod.rs | 11 +- geo/src/algorithm/convex_hull/qhull.rs | 26 ++-- geo/src/algorithm/convex_hull/test.rs | 8 +- geo/src/algorithm/coordinate_position.rs | 44 +++--- geo/src/algorithm/coords_iter.rs | 58 ++++---- geo/src/algorithm/dimensions.rs | 30 ++-- geo/src/algorithm/euclidean_distance.rs | 43 +++--- geo/src/algorithm/euclidean_length.rs | 3 +- geo/src/algorithm/extremes.rs | 12 +- geo/src/algorithm/geodesic_length.rs | 2 +- geo/src/algorithm/haversine_length.rs | 3 +- geo/src/algorithm/intersects/coordinate.rs | 2 +- geo/src/algorithm/intersects/line.rs | 24 ++-- geo/src/algorithm/intersects/mod.rs | 4 +- geo/src/algorithm/intersects/point.rs | 2 +- geo/src/algorithm/intersects/polygon.rs | 4 +- geo/src/algorithm/intersects/rect.rs | 19 +-- geo/src/algorithm/is_convex.rs | 8 +- geo/src/algorithm/k_nearest_concave_hull.rs | 41 +++--- geo/src/algorithm/kernels/mod.rs | 8 +- geo/src/algorithm/kernels/robust.rs | 12 +- geo/src/algorithm/line_interpolate_point.rs | 6 +- geo/src/algorithm/line_intersection.rs | 96 ++++++------- geo/src/algorithm/line_locate_point.rs | 2 +- geo/src/algorithm/lines_iter.rs | 6 +- geo/src/algorithm/map_coords.rs | 130 +++++++++--------- geo/src/algorithm/orient.rs | 4 +- .../algorithm/polygon_distance_fast_path.rs | 80 +++++------ geo/src/algorithm/relate/geomgraph/edge.rs | 4 +- .../algorithm/relate/geomgraph/edge_end.rs | 2 +- .../relate/geomgraph/geometry_graph.rs | 20 +-- .../algorithm/relate/geomgraph/node_map.rs | 18 +-- .../geomgraph/robust_line_intersector.rs | 16 +-- geo/src/algorithm/rotate.rs | 4 +- geo/src/algorithm/simplify.rs | 3 +- geo/src/algorithm/simplifyvw.rs | 69 +++++----- geo/src/algorithm/translate.rs | 4 +- geo/src/algorithm/vincenty_length.rs | 2 +- geo/src/algorithm/winding_order.rs | 20 +-- geo/src/utils.rs | 5 +- jts-test-runner/src/runner.rs | 8 +- 77 files changed, 1318 insertions(+), 820 deletions(-) diff --git a/geo-postgis/src/to_postgis.rs b/geo-postgis/src/to_postgis.rs index 885c4b810a..435cec5374 100644 --- a/geo-postgis/src/to_postgis.rs +++ b/geo-postgis/src/to_postgis.rs @@ -21,7 +21,7 @@ pub trait ToPostgis { impl ToPostgis for Coordinate { fn to_postgis_with_srid(&self, srid: Option) -> ewkb::Point { - ewkb::Point::new(self.x, self.y, srid) + ewkb::Point::new(self.x(), self.y(), srid) } } @@ -52,11 +52,7 @@ macro_rules! to_postgis_impl { ($from:ident, $to:path, $name:ident) => { impl ToPostgis<$to> for $from { fn to_postgis_with_srid(&self, srid: Option) -> $to { - let $name = self - .0 - .iter() - .map(|x| x.to_postgis_with_srid(srid)) - .collect(); + let $name = self.iter().map(|x| x.to_postgis_with_srid(srid)).collect(); $to { $name, srid } } } @@ -66,7 +62,17 @@ to_postgis_impl!(GeometryCollection, ewkb::GeometryCollection, geometries); to_postgis_impl!(MultiPolygon, ewkb::MultiPolygon, polygons); to_postgis_impl!(MultiLineString, ewkb::MultiLineString, lines); to_postgis_impl!(MultiPoint, ewkb::MultiPoint, points); -to_postgis_impl!(LineString, ewkb::LineString, points); + +impl ToPostgis for LineString { + fn to_postgis_with_srid(&self, srid: Option) -> ewkb::LineString { + let points = self + .coords() + .map(|x| x.to_postgis_with_srid(srid)) + .collect(); + ewkb::LineString { points, srid } + } +} + impl ToPostgis for Geometry { fn to_postgis_with_srid(&self, srid: Option) -> ewkb::Geometry { match *self { diff --git a/geo-types/CHANGES.md b/geo-types/CHANGES.md index 11018c3ba0..e1b3878a30 100644 --- a/geo-types/CHANGES.md +++ b/geo-types/CHANGES.md @@ -1,5 +1,57 @@ # Changes +## UNRELEASED + +* DEPRECATED: Direct access to geometry fields (this is a big change). + + This is intended to be a non-breaking change for now, to give people an + upgrade window. In an upcoming *breaking* release of geo-types we'll drop pub + field access altogether. + + This is in pursuit of adding support for 3D/4D geometries. We'll leverage + generics in a way that is intended to avoid runtime cost for our mostly 2D + user base. See https://github.com/georust/geo/issues/5 for more. + + ADDED: A bunch of new methods that correspond to the deprecated field access. + Here's a cheatsheet of new methods, and a reminder of few existing methods, + which you might now need: + * Coordinate: + - `Coordinate::new(x, y)` + - `coord.x()` / `coord.x_mut()` + - `coord.y()` / `coord.y_mut()` + * Point: + - `point.coord()` / `point.coord_mut()` + - `point.x_mut()` + - `point.y_mut()` + - `point.x()` / `point.y()` are not new, but you might need them now. + * GeometryCollection: + - `GeometryCollection::new_from(geometry_vec)` + - `gc.geometries()` / `gc.geometries_mut()` + - `gc.push(geometry)`: add a Geometry + - `gc.into_inner()`: decompose into an owned Vec + * Line: + - `line.start()` / `line.start_mut()` + - `line.end()` / `line.end_mut()` + * LineString: + - `line_string.inner()` / `line_string.inner_mut()` + - `line_string.push(coord)` + - `line_string[2]` get a particular coord. This isn't new, but you might need it now. + - `line_string[0..2]` - you can now access a slice of coords too. + * MultiPoint: + - `multi_point.points()` / `multi_point.points_mut()` + - `multi_point.push(point)` - add a point + - `multi_point.into_inner()` - decompose into an owned Vec + * MultiLineString: + - `mls.line_strings()` / `mls.line_strings_mut()` + - `mls.push(line_string)` - add a LineString + - `mls.into_inner()`: decompose into an owned Vec + * MultiPolygon: + - `multi_poly.polygons()` / `multi_poly.polygons_mut()` + - `multi_poly.push(polygon)`: add a Polygon + - `multi_poly.into_inner()`: decompose into an owned Vec + + Something missing? Let us know! https://github.com/georust/geo/issues/new + ## 0.7.4 * BREAKING: Make `Rect::to_lines` return lines in winding order for `Rect::to_polygon`. diff --git a/geo-types/src/coordinate.rs b/geo-types/src/coordinate.rs index 5abf0fb689..21e8c4ef94 100644 --- a/geo-types/src/coordinate.rs +++ b/geo-types/src/coordinate.rs @@ -26,10 +26,55 @@ use approx::{AbsDiffEq, RelativeEq, UlpsEq}; #[derive(Eq, PartialEq, Clone, Copy, Debug, Hash, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Coordinate { + #[deprecated( + since = "0.7.5", + note = "Direct field access is deprecated - use `coord.x()` or `coord.x_mut()` for field access and `coord!(x: 1, y: 2)` or `Coordinate::new(x, y)` for construction" + )] pub x: T, + #[deprecated( + since = "0.7.5", + note = "Direct field access is deprecated - use `coord.y()` or `coord.y_mut()` for field access and `coord!(x: 1, y: 2)` or `Coordinate::new(x, y)` for construction" + )] pub y: T, } +impl Coordinate { + #[inline] + pub fn new(x: T, y: T) -> Self { + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] + Self { x, y } + } + + #[inline] + pub fn x(&self) -> T { + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] + self.x + } + + #[inline] + pub fn x_mut(&mut self) -> &mut T { + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] + &mut self.x + } + + #[inline] + pub fn y(&self) -> T { + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] + self.y + } + + #[inline] + pub fn y_mut(&mut self) -> &mut T { + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] + &mut self.y + } +} + impl From<(T, T)> for Coordinate { #[inline] fn from(coords: (T, T)) -> Self { @@ -63,14 +108,14 @@ impl From> for Coordinate { impl From> for (T, T) { #[inline] fn from(coord: Coordinate) -> Self { - (coord.x, coord.y) + (coord.x(), coord.y()) } } impl From> for [T; 2] { #[inline] fn from(coord: Coordinate) -> Self { - [coord.x, coord.y] + [coord.x(), coord.y()] } } @@ -93,7 +138,7 @@ impl Coordinate { /// ``` #[inline] pub fn x_y(&self) -> (T, T) { - (self.x, self.y) + (self.x(), self.y()) } } @@ -109,8 +154,8 @@ use std::ops::{Add, Div, Mul, Neg, Sub}; /// let p = coord! { x: 1.25, y: 2.5 }; /// let q = -p; /// -/// assert_eq!(q.x, -p.x); -/// assert_eq!(q.y, -p.y); +/// assert_eq!(q.x(), -p.x()); +/// assert_eq!(q.y(), -p.y()); /// ``` impl Neg for Coordinate where @@ -121,8 +166,8 @@ where #[inline] fn neg(self) -> Self { coord! { - x: -self.x, - y: -self.y, + x: -self.x(), + y: -self.y(), } } } @@ -138,8 +183,8 @@ where /// let q = coord! { x: 1.5, y: 2.5 }; /// let sum = p + q; /// -/// assert_eq!(sum.x, 2.75); -/// assert_eq!(sum.y, 5.0); +/// assert_eq!(sum.x(), 2.75); +/// assert_eq!(sum.y(), 5.0); /// ``` impl Add for Coordinate { type Output = Self; @@ -147,8 +192,8 @@ impl Add for Coordinate { #[inline] fn add(self, rhs: Self) -> Self { coord! { - x: self.x + rhs.x, - y: self.y + rhs.y, + x: self.x() + rhs.x(), + y: self.y() + rhs.y(), } } } @@ -164,8 +209,8 @@ impl Add for Coordinate { /// let q = coord! { x: 1.25, y: 2.5 }; /// let diff = p - q; /// -/// assert_eq!(diff.x, 0.25); -/// assert_eq!(diff.y, 0.); +/// assert_eq!(diff.x(), 0.25); +/// assert_eq!(diff.y(), 0.); /// ``` impl Sub for Coordinate { type Output = Self; @@ -173,8 +218,8 @@ impl Sub for Coordinate { #[inline] fn sub(self, rhs: Self) -> Self { coord! { - x: self.x - rhs.x, - y: self.y - rhs.y, + x: self.x() - rhs.x(), + y: self.y() - rhs.y(), } } } @@ -189,8 +234,8 @@ impl Sub for Coordinate { /// let p = coord! { x: 1.25, y: 2.5 }; /// let q = p * 4.; /// -/// assert_eq!(q.x, 5.0); -/// assert_eq!(q.y, 10.0); +/// assert_eq!(q.x(), 5.0); +/// assert_eq!(q.y(), 10.0); /// ``` impl Mul for Coordinate { type Output = Self; @@ -198,8 +243,8 @@ impl Mul for Coordinate { #[inline] fn mul(self, rhs: T) -> Self { coord! { - x: self.x * rhs, - y: self.y * rhs, + x: self.x() * rhs, + y: self.y() * rhs, } } } @@ -214,8 +259,8 @@ impl Mul for Coordinate { /// let p = coord! { x: 5., y: 10. }; /// let q = p / 4.; /// -/// assert_eq!(q.x, 1.25); -/// assert_eq!(q.y, 2.5); +/// assert_eq!(q.x(), 1.25); +/// assert_eq!(q.y(), 2.5); /// ``` impl Div for Coordinate { type Output = Self; @@ -223,8 +268,8 @@ impl Div for Coordinate { #[inline] fn div(self, rhs: T) -> Self { coord! { - x: self.x / rhs, - y: self.y / rhs, + x: self.x() / rhs, + y: self.y() / rhs, } } } @@ -240,8 +285,8 @@ use num_traits::Zero; /// /// let p: Coordinate = Zero::zero(); /// -/// assert_eq!(p.x, 0.); -/// assert_eq!(p.y, 0.); +/// assert_eq!(p.x(), 0.); +/// assert_eq!(p.y(), 0.); /// ``` impl Coordinate { #[inline] @@ -260,7 +305,7 @@ impl Zero for Coordinate { } #[inline] fn is_zero(&self) -> bool { - self.x.is_zero() && self.y.is_zero() + self.x().is_zero() && self.y().is_zero() } } @@ -278,7 +323,8 @@ where #[inline] fn abs_diff_eq(&self, other: &Self, epsilon: T::Epsilon) -> bool { - T::abs_diff_eq(&self.x, &other.x, epsilon) && T::abs_diff_eq(&self.y, &other.y, epsilon) + T::abs_diff_eq(&self.x(), &other.x(), epsilon) + && T::abs_diff_eq(&self.y(), &other.y(), epsilon) } } @@ -294,8 +340,8 @@ where #[inline] fn relative_eq(&self, other: &Self, epsilon: T::Epsilon, max_relative: T::Epsilon) -> bool { - T::relative_eq(&self.x, &other.x, epsilon, max_relative) - && T::relative_eq(&self.y, &other.y, epsilon, max_relative) + T::relative_eq(&self.x(), &other.x(), epsilon, max_relative) + && T::relative_eq(&self.y(), &other.y(), epsilon, max_relative) } } @@ -311,8 +357,8 @@ where #[inline] fn ulps_eq(&self, other: &Self, epsilon: T::Epsilon, max_ulps: u32) -> bool { - T::ulps_eq(&self.x, &other.x, epsilon, max_ulps) - && T::ulps_eq(&self.y, &other.y, epsilon, max_ulps) + T::ulps_eq(&self.x(), &other.x(), epsilon, max_ulps) + && T::ulps_eq(&self.y(), &other.y(), epsilon, max_ulps) } } @@ -336,8 +382,8 @@ where #[inline] fn nth(&self, index: usize) -> Self::Scalar { match index { - 0 => self.x, - 1 => self.y, + 0 => self.x(), + 1 => self.y(), _ => unreachable!(), } } @@ -345,8 +391,8 @@ where #[inline] fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar { match index { - 0 => &mut self.x, - 1 => &mut self.y, + 0 => self.x_mut(), + 1 => self.y_mut(), _ => unreachable!(), } } @@ -372,8 +418,8 @@ where #[inline] fn nth(&self, index: usize) -> Self::Scalar { match index { - 0 => self.x, - 1 => self.y, + 0 => self.x(), + 1 => self.y(), _ => unreachable!(), } } @@ -381,8 +427,8 @@ where #[inline] fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar { match index { - 0 => &mut self.x, - 1 => &mut self.y, + 0 => self.x_mut(), + 1 => self.y_mut(), _ => unreachable!(), } } diff --git a/geo-types/src/geometry_collection.rs b/geo-types/src/geometry_collection.rs index 8abc544a90..d996eaf685 100644 --- a/geo-types/src/geometry_collection.rs +++ b/geo-types/src/geometry_collection.rs @@ -71,7 +71,13 @@ use std::ops::{Index, IndexMut}; /// #[derive(Eq, PartialEq, Clone, Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct GeometryCollection(pub Vec>); +pub struct GeometryCollection( + #[deprecated( + since = "0.7.5", + note = "Direct field access is deprecated - use `geometry_collection.geometries()` or `geometry_collection.geometries_mut()` for field access and `GeometryCollection::new(geometry_vec)` for construction" + )] + pub Vec>, +); // Implementing Default by hand because T does not have Default restriction // todo: consider adding Default as a CoordNum requirement @@ -97,14 +103,38 @@ impl GeometryCollection { Self(value) } + /// The constituent Geometries of this collection. + pub fn geometries(&self) -> &[Geometry] { + #[allow(deprecated)] + &self.0 + } + + /// Mutable borrow the constituent Geometries of this collection. + pub fn geometries_mut(&mut self) -> &mut [Geometry] { + #[allow(deprecated)] + &mut self.0 + } + + /// Consume the collection to get ownership of the constituent Geometries. + pub fn into_inner(self) -> Vec> { + #[allow(deprecated)] + self.0 + } + /// Number of geometries in this GeometryCollection pub fn len(&self) -> usize { - self.0.len() + self.geometries().len() } /// Is this GeometryCollection empty pub fn is_empty(&self) -> bool { - self.0.is_empty() + self.geometries().is_empty() + } + + /// Is this GeometryCollection empty + pub fn push(&mut self, value: Geometry) { + #[allow(deprecated)] + self.0.push(value) } } @@ -127,13 +157,13 @@ impl Index for GeometryCollection { type Output = Geometry; fn index(&self, index: usize) -> &Geometry { - self.0.index(index) + self.geometries().index(index) } } impl IndexMut for GeometryCollection { fn index_mut(&mut self, index: usize) -> &mut Geometry { - self.0.index_mut(index) + self.geometries_mut().index_mut(index) } } @@ -152,7 +182,7 @@ impl IntoIterator for GeometryCollection { // note that into_iter() is consuming self fn into_iter(self) -> Self::IntoIter { IntoIteratorHelper { - iter: self.0.into_iter(), + iter: self.into_inner().into_iter(), } } } @@ -182,7 +212,7 @@ impl<'a, T: CoordNum> IntoIterator for &'a GeometryCollection { // note that into_iter() is consuming self fn into_iter(self) -> Self::IntoIter { IterHelper { - iter: self.0.iter(), + iter: self.geometries().iter(), } } } @@ -212,7 +242,7 @@ impl<'a, T: CoordNum> IntoIterator for &'a mut GeometryCollection { // note that into_iter() is consuming self fn into_iter(self) -> Self::IntoIter { IterMutHelper { - iter: self.0.iter_mut(), + iter: self.geometries_mut().iter_mut(), } } } @@ -267,7 +297,7 @@ where epsilon: Self::Epsilon, max_relative: Self::Epsilon, ) -> bool { - if self.0.len() != other.0.len() { + if self.len() != other.len() { return false; } @@ -304,7 +334,7 @@ where /// ``` #[inline] fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool { - if self.0.len() != other.0.len() { + if self.len() != other.len() { return false; } diff --git a/geo-types/src/lib.rs b/geo-types/src/lib.rs index 546e68360b..82cbde1234 100644 --- a/geo-types/src/lib.rs +++ b/geo-types/src/lib.rs @@ -147,10 +147,10 @@ mod tests { let p = Point::from(c); - let Point(c2) = p; + let c2 = p.coord(); assert_eq!(c, c2); - assert_relative_eq!(c.x, c2.x); - assert_relative_eq!(c.y, c2.y); + assert_relative_eq!(c.x(), c2.x()); + assert_relative_eq!(c.y(), c2.y()); let p: Point = (0f32, 1f32).into(); assert_relative_eq!(p.x(), 0.); diff --git a/geo-types/src/line.rs b/geo-types/src/line.rs index fbee02a9d3..9c1792d381 100644 --- a/geo-types/src/line.rs +++ b/geo-types/src/line.rs @@ -12,7 +12,15 @@ use approx::{AbsDiffEq, RelativeEq}; #[derive(Eq, PartialEq, Clone, Copy, Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] pub struct Line { + #[deprecated( + since = "0.7.5", + note = "Direct field access is deprecated - use `line.start()` or `line.start_mut()` for field access and `Line::new(start, end)` for construction" + )] pub start: Coordinate, + #[deprecated( + since = "0.7.5", + note = "Direct field access is deprecated - use `line.end()` or `line.end_mut()` for field access and `Line::new(start, end)` for construction" + )] pub end: Coordinate, } @@ -26,22 +34,57 @@ impl Line { /// /// let line = Line::new(coord! { x: 0., y: 0. }, coord! { x: 1., y: 2. }); /// - /// assert_eq!(line.start, coord! { x: 0., y: 0. }); - /// assert_eq!(line.end, coord! { x: 1., y: 2. }); + /// assert_eq!(line.start(), coord! { x: 0., y: 0. }); + /// assert_eq!(line.end(), coord! { x: 1., y: 2. }); /// ``` + #[inline] pub fn new(start: C, end: C) -> Self where C: Into>, { + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] Self { start: start.into(), end: end.into(), } } + /// Get the first coordinate of the line. + #[inline] + pub fn start(&self) -> Coordinate { + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] + self.start + } + + /// Mutably borrow the first coordinate of the line. + #[inline] + pub fn start_mut(&mut self) -> &mut Coordinate { + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] + &mut self.start + } + + /// Get the second, and final, coordinate of the line. + #[inline] + pub fn end(&self) -> Coordinate { + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] + self.end + } + + /// Mutably borrow the second, and final, coordinate of the line. + #[inline] + pub fn end_mut(&mut self) -> &mut Coordinate { + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] + &mut self.end + } + /// Calculate the difference in coordinates (Δx, Δy). pub fn delta(&self) -> Coordinate { - self.end - self.start + self.end() - self.start() } /// Calculate the difference in ‘x’ components (Δx). @@ -56,11 +99,11 @@ impl Line { /// # ); /// # assert_eq!( /// # line.dx(), - /// line.end.x - line.start.x + /// line.end().x() - line.start().x() /// # ); /// ``` pub fn dx(&self) -> T { - self.delta().x + self.delta().x() } /// Calculate the difference in ‘y’ components (Δy). @@ -75,11 +118,11 @@ impl Line { /// # ); /// # assert_eq!( /// # line.dy(), - /// line.end.y - line.start.y + /// line.end().y() - line.start().y() /// # ); /// ``` pub fn dy(&self) -> T { - self.delta().y + self.delta().y() } /// Calculate the slope (Δy/Δx). @@ -124,7 +167,7 @@ impl Line { /// # ); /// # assert_eq!( /// # line.determinant(), - /// line.start.x * line.end.y - line.start.y * line.end.x + /// line.start().x() * line.end().y() - line.start().y() * line.end().x() /// # ); /// ``` /// @@ -139,15 +182,15 @@ impl Line { /// # ); /// ``` pub fn determinant(&self) -> T { - self.start.x * self.end.y - self.start.y * self.end.x + self.start().x() * self.end().y() - self.start().y() * self.end().x() } pub fn start_point(&self) -> Point { - Point::from(self.start) + Point::from(self.start()) } pub fn end_point(&self) -> Point { - Point::from(self.end) + Point::from(self.end()) } pub fn points(&self) -> (Point, Point) { @@ -189,8 +232,9 @@ where epsilon: Self::Epsilon, max_relative: Self::Epsilon, ) -> bool { - self.start.relative_eq(&other.start, epsilon, max_relative) - && self.end.relative_eq(&other.end, epsilon, max_relative) + self.start() + .relative_eq(&other.start(), epsilon, max_relative) + && self.end().relative_eq(&other.end(), epsilon, max_relative) } } @@ -217,7 +261,8 @@ impl + CoordNum> AbsDiffEq for Line { /// ``` #[inline] fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool { - self.start.abs_diff_eq(&other.start, epsilon) && self.end.abs_diff_eq(&other.end, epsilon) + self.start().abs_diff_eq(&other.start(), epsilon) + && self.end().abs_diff_eq(&other.end(), epsilon) } } diff --git a/geo-types/src/line_string.rs b/geo-types/src/line_string.rs index 594d057821..f8ca124ff7 100644 --- a/geo-types/src/line_string.rs +++ b/geo-types/src/line_string.rs @@ -3,7 +3,7 @@ use approx::{AbsDiffEq, RelativeEq}; use crate::{CoordNum, Coordinate, Line, Point, Triangle}; use std::iter::FromIterator; -use std::ops::{Index, IndexMut}; +use std::ops::{Index, IndexMut, RangeFrom}; /// An ordered collection of two or more [`Coordinate`]s, representing a /// path between locations. @@ -106,11 +106,11 @@ use std::ops::{Index, IndexMut}; /// ]); /// /// for coord in &line_string { -/// println!("Coordinate x = {}, y = {}", coord.x, coord.y); +/// println!("Coordinate x = {}, y = {}", coord.x(), coord.y()); /// } /// /// for coord in line_string { -/// println!("Coordinate x = {}, y = {}", coord.x, coord.y); +/// println!("Coordinate x = {}, y = {}", coord.x(), coord.y()); /// } /// /// ``` @@ -132,7 +132,13 @@ use std::ops::{Index, IndexMut}; #[derive(Eq, PartialEq, Clone, Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct LineString(pub Vec>); +pub struct LineString( + #[deprecated( + since = "0.7.5", + note = "Direct field access is deprecated - use `line_string.inner()` or `point.inner_mut()` for field access and `LineString::new(coords)` for construction" + )] + pub Vec>, +); /// A [`Point`] iterator returned by the `points` method #[derive(Debug)] @@ -192,6 +198,7 @@ impl<'a, T: CoordNum> DoubleEndedIterator for CoordinatesIter<'a, T> { impl LineString { /// Instantiate Self from the raw content value + #[inline] pub fn new(value: Vec>) -> Self { Self(value) } @@ -199,34 +206,79 @@ impl LineString { /// Return an iterator yielding the coordinates of a [`LineString`] as [`Point`]s #[deprecated(note = "Use points() instead")] pub fn points_iter(&self) -> PointsIter { - PointsIter(self.0.iter()) + PointsIter(self.inner().iter()) } /// Return an iterator yielding the coordinates of a [`LineString`] as [`Point`]s pub fn points(&self) -> PointsIter { - PointsIter(self.0.iter()) + PointsIter(self.inner().iter()) } /// Return an iterator yielding the members of a [`LineString`] as [`Coordinate`]s pub fn coords(&self) -> impl Iterator> { - self.0.iter() + self.inner().iter() } /// Return an iterator yielding the coordinates of a [`LineString`] as mutable [`Coordinate`]s pub fn coords_mut(&mut self) -> impl Iterator> { - self.0.iter_mut() + self.inner_mut().iter_mut() } /// Return the coordinates of a [`LineString`] as a [`Vec`] of [`Point`]s pub fn into_points(self) -> Vec> { - self.0.into_iter().map(Point::from).collect() + self.inner().iter().cloned().map(Point::from).collect() + } + + /// Access the coordinates of this [`LineString`]. + /// + /// ``` + /// use geo_types::{coord, line_string, LineString}; + /// let line_string: LineString = line_string![(x: 0.0, y: 0.0), (x: 1.0, y: 1.0), (x: 2.0, y: 2.0)]; + /// + /// let first_coord = line_string[0]; + /// let final_coord = line_string[2]; + /// assert_eq!(first_coord, coord!(x: 0.0, y: 0.0)); + /// assert_eq!(final_coord, coord!(x: 2.0, y: 2.0)); + /// ``` + #[inline] + pub fn inner(&self) -> &[Coordinate] { + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] + &self.0 + } + + /// Mutably borrow the coordinates of this [`LineString`]. + /// + /// ``` + /// use geo_types::{coord, line_string, LineString}; + /// let mut line_string: LineString = line_string![(x: 0.0, y: 0.0), (x: 1.0, y: 1.0), (x: 2.0, y: 2.0)]; + /// + /// line_string.inner_mut()[1] = coord!(x: 6.0, y: 6.0); + /// + /// assert_eq!(line_string, line_string![(x: 0.0, y: 0.0), (x: 6.0, y: 6.0), (x: 2.0, y: 2.0)]); + /// ``` + #[inline] + pub fn inner_mut(&mut self) -> &mut [Coordinate] { + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] + &mut self.0 } /// Return the coordinates of a [`LineString`] as a [`Vec`] of [`Coordinate`]s + #[inline] pub fn into_inner(self) -> Vec> { + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] self.0 } + /// Push a [`Coordinate`] onto the end of this [`LineString`] + #[inline] + pub fn push(&mut self, value: Coordinate) { + #[allow(deprecated)] + self.0.push(value) + } + /// Return an iterator yielding one [Line] for each line segment /// in the [`LineString`]. /// @@ -256,7 +308,7 @@ impl LineString { /// assert!(lines.next().is_none()); /// ``` pub fn lines(&'_ self) -> impl ExactSizeIterator + Iterator> + '_ { - self.0.windows(2).map(|w| { + self.inner().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)) } }) @@ -264,7 +316,7 @@ impl LineString { /// An iterator which yields the coordinates of a [`LineString`] as [Triangle]s pub fn triangles(&'_ self) -> impl ExactSizeIterator + Iterator> + '_ { - self.0.windows(3).map(|w| { + self.inner().windows(3).map(|w| { // slice::windows(N) is guaranteed to yield a slice with exactly N elements unsafe { Triangle::new( @@ -282,8 +334,9 @@ impl LineString { pub fn close(&mut self) { if !self.is_closed() { // by definition, we treat empty LineString's as closed. - debug_assert!(!self.0.is_empty()); - self.0.push(self.0[0]); + debug_assert!(!self.inner().is_empty()); + let first = self[0]; + self.push(first); } } @@ -304,7 +357,7 @@ impl LineString { /// ``` #[deprecated(note = "Use geo::algorithm::coords_iter::CoordsIter::coords_count instead")] pub fn num_coords(&self) -> usize { - self.0.len() + self.inner().len() } /// Checks if the linestring is closed; i.e. it is @@ -331,7 +384,7 @@ impl LineString { /// seems to be no reason to maintain the separate behavior for [`LineString`]s used in /// non-`LinearRing` contexts. pub fn is_closed(&self) -> bool { - self.0.first() == self.0.last() + self.inner().first() == self.inner().last() } } @@ -344,7 +397,7 @@ impl>> From> for LineString { impl From> for LineString { fn from(line: Line) -> Self { - Self(vec![line.start, line.end]) + Self(vec![line.start(), line.end()]) } } @@ -361,7 +414,7 @@ impl IntoIterator for LineString { type IntoIter = ::std::vec::IntoIter>; fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() + self.into_inner().into_iter() } } @@ -370,7 +423,7 @@ impl<'a, T: CoordNum> IntoIterator for &'a LineString { type IntoIter = CoordinatesIter<'a, T>; fn into_iter(self) -> Self::IntoIter { - CoordinatesIter(self.0.iter()) + CoordinatesIter(self.inner().iter()) } } @@ -380,7 +433,7 @@ impl<'a, T: CoordNum> IntoIterator for &'a mut LineString { type IntoIter = ::std::slice::IterMut<'a, Coordinate>; fn into_iter(self) -> ::std::slice::IterMut<'a, Coordinate> { - self.0.iter_mut() + self.inner_mut().iter_mut() } } @@ -388,13 +441,21 @@ impl Index for LineString { type Output = Coordinate; fn index(&self, index: usize) -> &Coordinate { - self.0.index(index) + self.inner().index(index) + } +} + +impl Index> for LineString { + type Output = [Coordinate]; + + fn index(&self, index: RangeFrom) -> &[Coordinate] { + self.inner().index(index) } } impl IndexMut for LineString { fn index_mut(&mut self, index: usize) -> &mut Coordinate { - self.0.index_mut(index) + self.inner_mut().index_mut(index) } } @@ -430,7 +491,7 @@ where epsilon: Self::Epsilon, max_relative: Self::Epsilon, ) -> bool { - if self.0.len() != other.0.len() { + if self.inner().len() != other.inner().len() { return false; } @@ -470,7 +531,7 @@ impl + CoordNum> AbsDiffEq for LineString { /// approx::assert_relative_eq!(a, b, epsilon=0.1) /// ``` fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool { - if self.0.len() != other.0.len() { + if self.inner().len() != other.inner().len() { return false; } let mut points_zipper = self.points().zip(other.points()); @@ -496,8 +557,8 @@ macro_rules! impl_rstar_line_string { Point::new(Bounded::max_value(), Bounded::max_value()), ), Some(b) => ::$rstar::AABB::from_corners( - Point::new(b.min().x, b.min().y), - Point::new(b.max().x, b.max().y), + Point::new(b.min().x(), b.min().y()), + Point::new(b.max().x(), b.max().y()), ), } } diff --git a/geo-types/src/macros.rs b/geo-types/src/macros.rs index ff69cc8651..129220fe19 100644 --- a/geo-types/src/macros.rs +++ b/geo-types/src/macros.rs @@ -56,7 +56,7 @@ macro_rules! point { #[macro_export] macro_rules! coord { (x: $x:expr, y: $y:expr $(,)* ) => { - $crate::Coordinate { x: $x, y: $y } + $crate::Coordinate::new($x, $y) }; } diff --git a/geo-types/src/multi_line_string.rs b/geo-types/src/multi_line_string.rs index fbb54ae7a4..7919c3c513 100644 --- a/geo-types/src/multi_line_string.rs +++ b/geo-types/src/multi_line_string.rs @@ -33,10 +33,17 @@ use std::iter::FromIterator; /// of a closed `MultiLineString` is always empty. #[derive(Eq, PartialEq, Clone, Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct MultiLineString(pub Vec>); +pub struct MultiLineString( + #[deprecated( + since = "0.7.5", + note = "Direct field access is deprecated - use `multi_line_string.line_strings()` or `multi_line_string.line_strings_mut()` for field access and `MultiLineString::new(line_strings)` for construction" + )] + pub Vec>, +); impl MultiLineString { /// Instantiate Self from the raw content value + #[inline] pub fn new(value: Vec>) -> Self { Self(value) } @@ -65,6 +72,34 @@ impl MultiLineString { // Note: Unlike JTS et al, we consider an empty MultiLineString as closed. self.iter().all(LineString::is_closed) } + + /// The constituent [`LineString`]s + #[inline] + pub fn line_strings(&self) -> &[LineString] { + #[allow(deprecated)] + &self.0 + } + + /// Mutable borrow the constituent [`LineString`]s. + #[inline] + pub fn line_strings_mut(&mut self) -> &mut [LineString] { + #[allow(deprecated)] + &mut self.0 + } + + /// Push a [`LineString`] onto the end of this [`MultiLineString`]. + #[inline] + pub fn push(&mut self, value: LineString) { + #[allow(deprecated)] + self.0.push(value) + } + + /// Consume self to return the constituent [`LineString`]s. + #[inline] + pub fn into_inner(self) -> Vec> { + #[allow(deprecated)] + self.0 + } } impl>> From for MultiLineString { @@ -84,7 +119,7 @@ impl IntoIterator for MultiLineString { type IntoIter = ::std::vec::IntoIter>; fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() + self.into_inner().into_iter() } } @@ -93,7 +128,7 @@ impl<'a, T: CoordNum> IntoIterator for &'a MultiLineString { type IntoIter = ::std::slice::Iter<'a, LineString>; fn into_iter(self) -> Self::IntoIter { - (&self.0).iter() + self.line_strings().iter() } } @@ -102,17 +137,17 @@ impl<'a, T: CoordNum> IntoIterator for &'a mut MultiLineString { type IntoIter = ::std::slice::IterMut<'a, LineString>; fn into_iter(self) -> Self::IntoIter { - (&mut self.0).iter_mut() + self.line_strings_mut().iter_mut() } } impl MultiLineString { pub fn iter(&self) -> impl Iterator> { - self.0.iter() + self.line_strings().iter() } pub fn iter_mut(&mut self) -> impl Iterator> { - self.0.iter_mut() + self.line_strings_mut().iter_mut() } } @@ -146,7 +181,7 @@ where epsilon: Self::Epsilon, max_relative: Self::Epsilon, ) -> bool { - if self.0.len() != other.0.len() { + if self.line_strings().len() != other.line_strings().len() { return false; } @@ -183,7 +218,7 @@ where /// ``` #[inline] fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool { - if self.0.len() != other.0.len() { + if self.line_strings().len() != other.line_strings().len() { return false; } @@ -248,15 +283,15 @@ mod test { for line_string in &mut multi { for coord in line_string { - coord.x += 1; - coord.y += 1; + *coord.x_mut() += 1; + *coord.y_mut() += 1; } } for line_string in multi.iter_mut() { for coord in line_string { - coord.x += 1; - coord.y += 1; + *coord.x_mut() += 1; + *coord.y_mut() += 1; } } diff --git a/geo-types/src/multi_point.rs b/geo-types/src/multi_point.rs index 6a7acfdbe2..6a001d777a 100644 --- a/geo-types/src/multi_point.rs +++ b/geo-types/src/multi_point.rs @@ -30,7 +30,13 @@ use std::iter::FromIterator; /// ``` #[derive(Eq, PartialEq, Clone, Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct MultiPoint(pub Vec>); +pub struct MultiPoint( + #[deprecated( + since = "0.7.5", + note = "Direct field access is deprecated - use `multi_point.points()` or `multi_point.points_mut()` for field access and `MultiPoint::new(points)` for construction" + )] + pub Vec>, +); impl>> From for MultiPoint { /// Convert a single `Point` (or something which can be converted to a `Point`) into a @@ -61,7 +67,7 @@ impl IntoIterator for MultiPoint { type IntoIter = ::std::vec::IntoIter>; fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() + self.into_inner().into_iter() } } @@ -70,7 +76,7 @@ impl<'a, T: CoordNum> IntoIterator for &'a MultiPoint { type IntoIter = ::std::slice::Iter<'a, Point>; fn into_iter(self) -> Self::IntoIter { - (&self.0).iter() + self.points().iter() } } @@ -79,21 +85,49 @@ impl<'a, T: CoordNum> IntoIterator for &'a mut MultiPoint { type IntoIter = ::std::slice::IterMut<'a, Point>; fn into_iter(self) -> Self::IntoIter { - (&mut self.0).iter_mut() + self.points_mut().iter_mut() } } impl MultiPoint { + #[inline] pub fn new(value: Vec>) -> Self { Self(value) } + /// The constituent points of this `MultiPoint`. + #[inline] + pub fn points(&self) -> &[Point] { + #[allow(deprecated)] + &self.0 + } + + /// Mutably borrow the constituent points of this `MultiPoint`. + #[inline] + pub fn points_mut(&mut self) -> &mut [Point] { + #[allow(deprecated)] + &mut self.0 + } + + /// Consume this `MultiPoint` to get the underlying owned points. + #[inline] + pub fn into_inner(self) -> Vec> { + #[allow(deprecated)] + self.0 + } + + #[inline] + pub fn push(&mut self, value: Point) { + #[allow(deprecated)] + self.0.push(value) + } + pub fn iter(&self) -> impl Iterator> { - self.0.iter() + self.points().iter() } pub fn iter_mut(&mut self) -> impl Iterator> { - self.0.iter_mut() + self.points_mut().iter_mut() } } @@ -127,7 +161,7 @@ where epsilon: Self::Epsilon, max_relative: Self::Epsilon, ) -> bool { - if self.0.len() != other.0.len() { + if self.points().len() != other.points().len() { return false; } @@ -164,7 +198,7 @@ where /// ``` #[inline] fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool { - if self.0.len() != other.0.len() { + if self.points().len() != other.points().len() { return false; } @@ -209,13 +243,13 @@ mod test { let mut multi = MultiPoint::new(vec![point![x: 0, y: 0], point![x: 10, y: 10]]); for point in &mut multi { - point.0.x += 1; - point.0.y += 1; + *point.x_mut() += 1; + *point.y_mut() += 1; } for point in multi.iter_mut() { - point.0.x += 1; - point.0.y += 1; + *point.x_mut() += 1; + *point.y_mut() += 1; } let mut first = true; diff --git a/geo-types/src/multi_polygon.rs b/geo-types/src/multi_polygon.rs index 881d250dd4..570fa5612d 100644 --- a/geo-types/src/multi_polygon.rs +++ b/geo-types/src/multi_polygon.rs @@ -27,7 +27,13 @@ use std::iter::FromIterator; /// predicates that operate on it. #[derive(Eq, PartialEq, Clone, Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct MultiPolygon(pub Vec>); +pub struct MultiPolygon( + #[deprecated( + since = "0.7.5", + note = "Direct field access is deprecated - use `multi_poly.polygons()` or `multi_poly.polygons_mut()` for field access and `MultiPolygon::new(polygons_vec)` for construction" + )] + pub Vec>, +); impl>> From for MultiPolygon { fn from(x: IP) -> Self { @@ -52,7 +58,7 @@ impl IntoIterator for MultiPolygon { type IntoIter = ::std::vec::IntoIter>; fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() + self.into_inner().into_iter() } } @@ -61,7 +67,7 @@ impl<'a, T: CoordNum> IntoIterator for &'a MultiPolygon { type IntoIter = ::std::slice::Iter<'a, Polygon>; fn into_iter(self) -> Self::IntoIter { - (&self.0).iter() + self.polygons().iter() } } @@ -70,22 +76,51 @@ impl<'a, T: CoordNum> IntoIterator for &'a mut MultiPolygon { type IntoIter = ::std::slice::IterMut<'a, Polygon>; fn into_iter(self) -> Self::IntoIter { - (&mut self.0).iter_mut() + self.polygons_mut().iter_mut() } } impl MultiPolygon { /// Instantiate Self from the raw content value + #[inline] pub fn new(value: Vec>) -> Self { Self(value) } + /// The constituent [`Polygon`]s. + #[inline] + pub fn polygons(&self) -> &[Polygon] { + #[allow(deprecated)] + &self.0 + } + + /// Mutable borrow the constituent `Polygon`s. + #[inline] + pub fn polygons_mut(&mut self) -> &mut [Polygon] { + #[allow(deprecated)] + &mut self.0 + } + + /// Push a polygon onto the end of the multi polygon. + #[inline] + pub fn push(&mut self, value: Polygon) { + #[allow(deprecated)] + self.0.push(value) + } + + /// Consume this `MultiPolygon` to get ownership of its constituent `Polygon`s. + #[inline] + pub fn into_inner(self) -> Vec> { + #[allow(deprecated)] + self.0 + } + pub fn iter(&self) -> impl Iterator> { - self.0.iter() + self.polygons().iter() } pub fn iter_mut(&mut self) -> impl Iterator> { - self.0.iter_mut() + self.polygons_mut().iter_mut() } } @@ -121,7 +156,7 @@ where epsilon: Self::Epsilon, max_relative: Self::Epsilon, ) -> bool { - if self.0.len() != other.0.len() { + if self.polygons().len() != other.polygons().len() { return false; } @@ -160,7 +195,7 @@ where /// ``` #[inline] fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool { - if self.0.len() != other.0.len() { + if self.polygons().len() != other.polygons().len() { return false; } @@ -225,8 +260,8 @@ mod test { for poly in &mut multi { poly.exterior_mut(|exterior| { for coord in exterior { - coord.x += 1; - coord.y += 1; + *coord.x_mut() += 1; + *coord.y_mut() += 1; } }); } @@ -234,8 +269,8 @@ mod test { for poly in multi.iter_mut() { poly.exterior_mut(|exterior| { for coord in exterior { - coord.x += 1; - coord.y += 1; + *coord.x_mut() += 1; + *coord.y_mut() += 1; } }); } diff --git a/geo-types/src/point.rs b/geo-types/src/point.rs index cb704d2a92..a31ae4d67a 100644 --- a/geo-types/src/point.rs +++ b/geo-types/src/point.rs @@ -1,4 +1,4 @@ -use crate::{point, CoordFloat, CoordNum, Coordinate}; +use crate::{CoordFloat, CoordNum, Coordinate}; #[cfg(any(feature = "approx", test))] use approx::{AbsDiffEq, RelativeEq}; @@ -28,21 +28,30 @@ use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Neg, Sub, SubAssi /// ``` #[derive(Eq, PartialEq, Clone, Copy, Debug, Hash, Default)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct Point(pub Coordinate); +pub struct Point( + #[deprecated( + since = "0.7.5", + note = "Direct field access is deprecated - use `point.coord()` or `point.coord_mut()` for field access and `point!(x: 1, y: 2)` or `Point::new(x, y)` for construction" + )] + pub Coordinate, +); impl From> for Point { + #[inline] fn from(x: Coordinate) -> Self { Point(x) } } impl From<(T, T)> for Point { + #[inline] fn from(coords: (T, T)) -> Self { Point::new(coords.0, coords.1) } } impl From<[T; 2]> for Point { + #[inline] fn from(coords: [T; 2]) -> Self { Point::new(coords[0], coords[1]) } @@ -50,13 +59,13 @@ impl From<[T; 2]> for Point { impl From> for (T, T) { fn from(point: Point) -> Self { - point.0.into() + point.coord().into() } } impl From> for [T; 2] { fn from(point: Point) -> Self { - point.0.into() + point.coord().into() } } @@ -73,8 +82,28 @@ impl Point { /// assert_eq!(p.x(), 1.234); /// assert_eq!(p.y(), 2.345); /// ``` + #[inline] pub fn new(x: T, y: T) -> Self { - point! { x: x, y: y } + #[allow(deprecated)] + { + Point(Coordinate { x, y }) + } + } + + /// Return the point's [`Coordinate`]. + #[inline] + pub fn coord(self) -> Coordinate { + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] + self.0 + } + + /// Mutably borrow the point's [`Coordinate`]. + #[inline] + pub fn coord_mut(&mut self) -> &mut Coordinate { + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] + &mut self.0 } /// Returns the x/horizontal component of the point. @@ -88,10 +117,31 @@ impl Point { /// /// assert_eq!(p.x(), 1.234); /// ``` + #[inline] pub fn x(self) -> T { + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] self.0.x } + /// Returns a mutable reference to the x/horizontal component of the point. + /// + /// # Examples + /// + /// ``` + /// use geo_types::Point; + /// + /// let mut p = Point::new(1.0, 2.0); + /// *p.x_mut() = 4.0; + /// + /// assert_eq!(p, Point::new(4.0, 2.0)); + /// ``` + #[inline] + pub fn x_mut(&mut self) -> &mut T { + #[allow(deprecated)] + &mut self.0.x + } + /// Sets the x/horizontal component of the point. /// /// # Examples @@ -104,8 +154,9 @@ impl Point { /// /// assert_eq!(p.x(), 9.876); /// ``` + #[inline] pub fn set_x(&mut self, x: T) -> &mut Self { - self.0.x = x; + *self.x_mut() = x; self } @@ -120,10 +171,30 @@ impl Point { /// /// assert_eq!(p.y(), 2.345); /// ``` + #[inline] pub fn y(self) -> T { + #[allow(deprecated)] self.0.y } + /// Returns a mutable reference to the y/vertical component of the point. + /// + /// # Examples + /// + /// ``` + /// use geo_types::Point; + /// + /// let mut p = Point::new(1.0, 2.0); + /// *p.y_mut() = 4.0; + /// + /// assert_eq!(p, Point::new(1.0, 4.0)); + /// ``` + #[inline] + pub fn y_mut(&mut self) -> &mut T { + #[allow(deprecated)] + &mut self.0.y + } + /// Sets the y/vertical component of the point. /// /// # Examples @@ -136,8 +207,9 @@ impl Point { /// /// assert_eq!(p.y(), 9.876); /// ``` + #[inline] pub fn set_y(&mut self, y: T) -> &mut Self { - self.0.y = y; + *self.y_mut() = y; self } @@ -154,8 +226,11 @@ impl Point { /// assert_eq!(y, 2.345); /// assert_eq!(x, 1.234); /// ``` + #[inline] pub fn x_y(self) -> (T, T) { - (self.0.x, self.0.y) + // we can delete the deprecations and allow(deprecated) once the fields are no longer pub + #[allow(deprecated)] + self.0.x_y() } /// Returns the longitude/horizontal component of the point. /// @@ -323,7 +398,7 @@ where /// assert_eq!(p.y(), -2.5); /// ``` fn neg(self) -> Self::Output { - Point::from(-self.0) + Point::from(-self.coord()) } } @@ -343,7 +418,7 @@ impl Add for Point { /// assert_eq!(p.y(), 5.0); /// ``` fn add(self, rhs: Self) -> Self::Output { - Point::from(self.0 + rhs.0) + Point::from(self.coord() + rhs.coord()) } } @@ -362,7 +437,7 @@ impl AddAssign for Point { /// assert_eq!(p.y(), 5.0); /// ``` fn add_assign(&mut self, rhs: Self) { - self.0 = self.0 + rhs.0; + *self.coord_mut() = self.coord() + rhs.coord(); } } @@ -382,7 +457,7 @@ impl Sub for Point { /// assert_eq!(p.y(), 0.5); /// ``` fn sub(self, rhs: Self) -> Self::Output { - Point::from(self.0 - rhs.0) + Point::from(self.coord() - rhs.coord()) } } @@ -401,7 +476,7 @@ impl SubAssign for Point { /// assert_eq!(p.y(), 0.0); /// ``` fn sub_assign(&mut self, rhs: Self) { - self.0 = self.0 - rhs.0; + *self.coord_mut() = self.coord() - rhs.coord(); } } @@ -421,7 +496,7 @@ impl Mul for Point { /// assert_eq!(p.y(), 6.0); /// ``` fn mul(self, rhs: T) -> Self::Output { - Point::from(self.0 * rhs) + Point::from(self.coord() * rhs) } } @@ -440,7 +515,7 @@ impl MulAssign for Point { /// assert_eq!(p.y(), 6.0); /// ``` fn mul_assign(&mut self, rhs: T) { - self.0 = self.0 * rhs + *self.coord_mut() = self.coord() * rhs } } @@ -460,7 +535,7 @@ impl Div for Point { /// assert_eq!(p.y(), 1.5); /// ``` fn div(self, rhs: T) -> Self::Output { - Point::from(self.0 / rhs) + Point::from(self.coord() / rhs) } } @@ -479,7 +554,7 @@ impl DivAssign for Point { /// assert_eq!(p.y(), 1.5); /// ``` fn div_assign(&mut self, rhs: T) { - self.0 = self.0 / rhs + *self.coord_mut() = self.coord() / rhs } } @@ -512,7 +587,8 @@ where epsilon: Self::Epsilon, max_relative: Self::Epsilon, ) -> bool { - self.0.relative_eq(&other.0, epsilon, max_relative) + self.coord() + .relative_eq(&other.coord(), epsilon, max_relative) } } @@ -543,7 +619,7 @@ where /// ``` #[inline] fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool { - self.0.abs_diff_eq(&other.0, epsilon) + self.coord().abs_diff_eq(&other.coord(), epsilon) } } @@ -563,15 +639,15 @@ where fn nth(&self, index: usize) -> Self::Scalar { match index { - 0 => self.0.x, - 1 => self.0.y, + 0 => self.x(), + 1 => self.y(), _ => unreachable!(), } } fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar { match index { - 0 => &mut self.0.x, - 1 => &mut self.0.y, + 0 => self.x_mut(), + 1 => self.y_mut(), _ => unreachable!(), } } @@ -592,15 +668,15 @@ where fn nth(&self, index: usize) -> Self::Scalar { match index { - 0 => self.0.x, - 1 => self.0.y, + 0 => self.x(), + 1 => self.y(), _ => unreachable!(), } } fn nth_mut(&mut self, index: usize) -> &mut Self::Scalar { match index { - 0 => &mut self.0.x, - 1 => &mut self.0.y, + 0 => self.x_mut(), + 1 => self.y_mut(), _ => unreachable!(), } } diff --git a/geo-types/src/polygon.rs b/geo-types/src/polygon.rs index e450a4034b..fb9744f9c5 100644 --- a/geo-types/src/polygon.rs +++ b/geo-types/src/polygon.rs @@ -389,7 +389,7 @@ impl Polygon { where T: Float, { - (current_vertex + (self.exterior.0.len() - 1) - 1) % (self.exterior.0.len() - 1) + (current_vertex + (self.exterior.inner().len() - 1) - 1) % (self.exterior.inner().len() - 1) } } @@ -418,8 +418,7 @@ impl Polygon { pub fn is_convex(&self) -> bool { let convex = self .exterior - .0 - .iter() + .coords() .enumerate() .map(|(idx, _)| { let prev_1 = self.previous_vertex(idx); @@ -445,11 +444,11 @@ impl From> for Polygon { fn from(r: Rect) -> Self { Polygon::new( vec![ - (r.min().x, r.min().y), - (r.max().x, r.min().y), - (r.max().x, r.max().y), - (r.min().x, r.max().y), - (r.min().x, r.min().y), + (r.min().x(), r.min().y()), + (r.max().x(), r.min().y()), + (r.max().x(), r.max().y()), + (r.min().x(), r.max().y()), + (r.min().x(), r.min().y()), ] .into(), Vec::new(), @@ -459,7 +458,7 @@ impl From> for Polygon { impl From> for Polygon { fn from(t: Triangle) -> Self { - Polygon::new(vec![t.0, t.1, t.2, t.0].into(), Vec::new()) + t.to_polygon() } } diff --git a/geo-types/src/private_utils.rs b/geo-types/src/private_utils.rs index a70e68e1c7..192a55db72 100644 --- a/geo-types/src/private_utils.rs +++ b/geo-types/src/private_utils.rs @@ -16,7 +16,7 @@ pub fn line_bounding_rect(line: Line) -> Rect where T: CoordNum, { - Rect::new(line.start, line.end) + Rect::new(line.start(), line.end()) } pub fn get_bounding_rect(collection: I) -> Option> @@ -26,8 +26,8 @@ where { let mut iter = collection.into_iter(); if let Some(pnt) = iter.next() { - let mut xrange = (pnt.x, pnt.x); - let mut yrange = (pnt.y, pnt.y); + let mut xrange = (pnt.x(), pnt.x()); + let mut yrange = (pnt.y(), pnt.y()); for pnt in iter { let (px, py) = pnt.x_y(); xrange = get_min_max(px, xrange.0, xrange.1); @@ -70,16 +70,17 @@ where if start == end { return line_euclidean_length(Line::new(point, start)); } - let dx = end.x - start.x; - let dy = end.y - start.y; - let r = ((point.x - start.x) * dx + (point.y - start.y) * dy) / (dx.powi(2) + dy.powi(2)); + let dx = end.x() - start.x(); + let dy = end.y() - start.y(); + let r = + ((point.x() - start.x()) * dx + (point.y() - start.y()) * dy) / (dx.powi(2) + dy.powi(2)); if r <= T::zero() { return line_euclidean_length(Line::new(point, start)); } if r >= T::one() { return line_euclidean_length(Line::new(point, end)); } - let s = ((start.y - point.y) * dx - (start.x - point.x) * dy) / (dx * dx + dy * dy); + let s = ((start.y() - point.y()) * dx - (start.x() - point.x()) * dy) / (dx * dx + dy * dy); s.abs() * dx.hypot(dy) } @@ -95,11 +96,11 @@ where T: CoordFloat, { // No need to continue if the point is on the LineString, or it's empty - if line_string_contains_point(l, p) || l.0.is_empty() { + if line_string_contains_point(l, p) || l.inner().is_empty() { return T::zero(); } l.lines() - .map(|line| line_segment_distance(p.0, line.start, line.end)) + .map(|line| line_segment_distance(p.coord(), line.start(), line.end())) .fold(T::max_value(), |accum, val| accum.min(val)) } @@ -108,7 +109,7 @@ where T: CoordFloat, C: Into>, { - line_segment_distance(p.into(), l.start, l.end) + line_segment_distance(p.into(), l.start(), l.end()) } pub fn point_contains_point(p1: Point, p2: Point) -> bool @@ -124,15 +125,15 @@ where T: CoordFloat, { // LineString without points - if line_string.0.is_empty() { + if line_string.inner().is_empty() { return false; } // LineString with one point equal p - if line_string.0.len() == 1 { + if line_string.inner().len() == 1 { return point_contains_point(Point::from(line_string[0]), point); } // check if point is a vertex - if line_string.0.contains(&point.0) { + if line_string.inner().contains(&point.coord()) { return true; } for line in line_string.lines() { @@ -140,25 +141,25 @@ where let tx = if line.dx() == T::zero() { None } else { - Some((point.x() - line.start.x) / line.dx()) + Some((point.x() - line.start().x()) / line.dx()) }; let ty = if line.dy() == T::zero() { None } else { - Some((point.y() - line.start.y) / line.dy()) + Some((point.y() - line.start().y()) / line.dy()) }; let contains = match (tx, ty) { (None, None) => { // Degenerate line - point.0 == line.start + point.coord() == line.start() } (Some(t), None) => { // Horizontal line - point.y() == line.start.y && T::zero() <= t && t <= T::one() + point.y() == line.start().y() && T::zero() <= t && t <= T::one() } (None, Some(t)) => { // Vertical line - point.x() == line.start.x && T::zero() <= t && t <= T::one() + point.x() == line.start().x() && T::zero() <= t && t <= T::one() } (Some(t_x), Some(t_y)) => { // All other lines diff --git a/geo-types/src/rect.rs b/geo-types/src/rect.rs index 2c7e0bc526..d50d8a13f2 100644 --- a/geo-types/src/rect.rs +++ b/geo-types/src/rect.rs @@ -65,15 +65,15 @@ impl Rect { { let c1 = c1.into(); let c2 = c2.into(); - let (min_x, max_x) = if c1.x < c2.x { - (c1.x, c2.x) + let (min_x, max_x) = if c1.x() < c2.x() { + (c1.x(), c2.x()) } else { - (c2.x, c1.x) + (c2.x(), c1.x()) }; - let (min_y, max_y) = if c1.y < c2.y { - (c1.y, c2.y) + let (min_y, max_y) = if c1.y() < c2.y() { + (c1.y(), c2.y()) } else { - (c2.y, c1.y) + (c2.y(), c1.y()) }; Self { min: coord! { x: min_x, y: min_y }, @@ -170,7 +170,7 @@ impl Rect { /// assert_eq!(rect.width(), 10.); /// ``` pub fn width(self) -> T { - self.max().x - self.min().x + self.max().x() - self.min().x() } /// Returns the height of the `Rect`. @@ -188,7 +188,7 @@ impl Rect { /// assert_eq!(rect.height(), 10.); /// ``` pub fn height(self) -> T { - self.max().y - self.min().y + self.max().y() - self.min().y() } /// Create a `Polygon` from the `Rect`. @@ -216,11 +216,11 @@ impl Rect { /// ``` pub fn to_polygon(self) -> Polygon { polygon![ - (x: self.min.x, y: self.min.y), - (x: self.min.x, y: self.max.y), - (x: self.max.x, y: self.max.y), - (x: self.max.x, y: self.min.y), - (x: self.min.x, y: self.min.y), + (x: self.min.x(), y: self.min.y()), + (x: self.min.x(), y: self.max.y()), + (x: self.max.x(), y: self.max.y()), + (x: self.max.x(), y: self.min.y()), + (x: self.min.x(), y: self.min.y()), ] } @@ -228,42 +228,42 @@ impl Rect { [ Line::new( coord! { - x: self.min.x, - y: self.min.y, + x: self.min.x(), + y: self.min.y(), }, coord! { - x: self.min.x, - y: self.max.y, + x: self.min.x(), + y: self.max.y(), }, ), Line::new( coord! { - x: self.min.x, - y: self.max.y, + x: self.min.x(), + y: self.max.y(), }, coord! { - x: self.max.x, - y: self.max.y, + x: self.max.x(), + y: self.max.y(), }, ), Line::new( coord! { - x: self.max.x, - y: self.max.y, + x: self.max.x(), + y: self.max.y(), }, coord! { - x: self.max.x, - y: self.min.y, + x: self.max.x(), + y: self.min.y(), }, ), Line::new( coord! { - x: self.max.x, - y: self.min.y, + x: self.max.x(), + y: self.min.y(), }, coord! { - x: self.min.x, - y: self.min.y, + x: self.min.x(), + y: self.min.y(), }, ), ] @@ -276,7 +276,7 @@ impl Rect { } fn has_valid_bounds(&self) -> bool { - self.min.x <= self.max.x && self.min.y <= self.max.y + self.min.x() <= self.max.x() && self.min.y() <= self.max.y() } } @@ -298,8 +298,8 @@ impl Rect { pub fn center(self) -> Coordinate { let two = T::one() + T::one(); coord! { - x: (self.max.x + self.min.x) / two, - y: (self.max.y + self.min.y) / two, + x: (self.max.x() + self.min.x()) / two, + y: (self.max.y() + self.min.y()) / two, } } } diff --git a/geo-types/src/triangle.rs b/geo-types/src/triangle.rs index 7cd54da0d1..d89071087c 100644 --- a/geo-types/src/triangle.rs +++ b/geo-types/src/triangle.rs @@ -9,23 +9,82 @@ use approx::{AbsDiffEq, RelativeEq}; /// vertices must not be collinear and they must be distinct. #[derive(Copy, Clone, Debug, Hash, Eq, PartialEq)] #[cfg_attr(feature = "serde", derive(Serialize, Deserialize))] -pub struct Triangle(pub Coordinate, pub Coordinate, pub Coordinate); +pub struct Triangle( + #[deprecated( + since = "0.7.5", + note = "Direct field access is deprecated - use `triangle.vertex_0()` or `triangle.vertex_0_mut()` for field access and `Triangle::new(v0, v1, v2) for construction" + )] + pub Coordinate, + #[deprecated( + since = "0.7.5", + note = "Direct field access is deprecated - use `triangle.vertex_1()` or `triangle.vertex_1_mut()` for field access and `Triangle::new(v0, v1, v2) for construction" + )] + pub Coordinate, + #[deprecated( + since = "0.7.5", + note = "Direct field access is deprecated - use `triangle.vertex_2()` or `triangle.vertex_2_mut()` for field access and `Triangle::new(v0, v1, v2) for construction" + )] + pub Coordinate, +); impl Triangle { /// Instantiate Self from the raw content value - pub fn new(v1: Coordinate, v2: Coordinate, v3: Coordinate) -> Self { - Self(v1, v2, v3) + #[inline] + pub fn new(v0: Coordinate, v1: Coordinate, v2: Coordinate) -> Self { + Self(v0, v1, v2) + } + + /// Get the first of triangles three corners + #[inline] + pub fn vertex_0(&self) -> Coordinate { + #[allow(deprecated)] + self.0 + } + + /// Mutably borrow the first of triangles three corners + #[inline] + pub fn vertex_0_mut(&mut self) -> &mut Coordinate { + #[allow(deprecated)] + &mut self.0 + } + + /// Get the first of triangles three corners + #[inline] + pub fn vertex_1(&self) -> Coordinate { + #[allow(deprecated)] + self.1 + } + + /// Mutably borrow the first of triangles three corners + #[inline] + pub fn vertex_1_mut(&mut self) -> &mut Coordinate { + #[allow(deprecated)] + &mut self.1 + } + + /// Get the first of triangles three corners + #[inline] + pub fn vertex_2(&self) -> Coordinate { + #[allow(deprecated)] + self.2 + } + + /// Mutably borrow the first of triangles three corners + #[inline] + pub fn vertex_2_mut(&mut self) -> &mut Coordinate { + #[allow(deprecated)] + &mut self.2 } pub fn to_array(&self) -> [Coordinate; 3] { - [self.0, self.1, self.2] + [self.vertex_0(), self.vertex_1(), self.vertex_2()] } pub fn to_lines(&self) -> [Line; 3] { [ - Line::new(self.0, self.1), - Line::new(self.1, self.2), - Line::new(self.2, self.0), + Line::new(self.vertex_0(), self.vertex_1()), + Line::new(self.vertex_1(), self.vertex_2()), + Line::new(self.vertex_2(), self.vertex_0()), ] } @@ -53,7 +112,12 @@ impl Triangle { /// ); /// ``` pub fn to_polygon(self) -> Polygon { - polygon![self.0, self.1, self.2, self.0] + polygon![ + self.vertex_0(), + self.vertex_1(), + self.vertex_2(), + self.vertex_0() + ] } } @@ -93,13 +157,22 @@ where epsilon: Self::Epsilon, max_relative: Self::Epsilon, ) -> bool { - if !self.0.relative_eq(&other.0, epsilon, max_relative) { + if !self + .vertex_0() + .relative_eq(&other.vertex_0(), epsilon, max_relative) + { return false; } - if !self.1.relative_eq(&other.1, epsilon, max_relative) { + if !self + .vertex_1() + .relative_eq(&other.vertex_1(), epsilon, max_relative) + { return false; } - if !self.2.relative_eq(&other.2, epsilon, max_relative) { + if !self + .vertex_2() + .relative_eq(&other.vertex_2(), epsilon, max_relative) + { return false; } @@ -135,13 +208,13 @@ where /// ``` #[inline] fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool { - if !self.0.abs_diff_eq(&other.0, epsilon) { + if !self.vertex_0().abs_diff_eq(&other.vertex_0(), epsilon) { return false; } - if !self.1.abs_diff_eq(&other.1, epsilon) { + if !self.vertex_1().abs_diff_eq(&other.vertex_1(), epsilon) { return false; } - if !self.2.abs_diff_eq(&other.2, epsilon) { + if !self.vertex_2().abs_diff_eq(&other.vertex_2(), epsilon) { return false; } diff --git a/geo/Cargo.toml b/geo/Cargo.toml index 37f5b4490f..0466ec3c1a 100644 --- a/geo/Cargo.toml +++ b/geo/Cargo.toml @@ -16,6 +16,7 @@ proj-network = ["use-proj", "proj/network"] use-serde = ["serde", "geo-types/serde"] [dependencies] +# TODO: bump to 0.7.5 before release to adapt to deprecated fields geo-types = { version = "0.7.4", features = ["approx", "use-rstar"] } geographiclib-rs = "0.2" log = "0.4.11" diff --git a/geo/benches/relate.rs b/geo/benches/relate.rs index 13d10e44bb..70203ee438 100644 --- a/geo/benches/relate.rs +++ b/geo/benches/relate.rs @@ -9,7 +9,7 @@ use geo::{LineString, Polygon}; fn criterion_benchmark(c: &mut Criterion) { c.bench_function("relate overlapping 50-point polygons", |bencher| { let norway = geo_test_fixtures::norway_main::(); - let points = norway.0; + let points = norway.into_inner(); let sub_polygon = { let points = points[0..50].to_vec(); diff --git a/geo/examples/concavehull-usage.rs b/geo/examples/concavehull-usage.rs index 01598e9ecd..d9dbf2ea91 100644 --- a/geo/examples/concavehull-usage.rs +++ b/geo/examples/concavehull-usage.rs @@ -1,5 +1,6 @@ use geo::algorithm::concave_hull::ConcaveHull; use geo::algorithm::convex_hull::ConvexHull; +use geo::coords_iter::CoordsIter; use geo::{Coordinate, Point}; use geo_types::MultiPoint; use std::fs::File; @@ -8,7 +9,7 @@ use std::io::Write; fn generate_polygon_str(coords: &[Coordinate]) -> String { let mut points_str = String::from(""); for coord in coords { - points_str.push_str(format!("{},{} ", coord.x, coord.y).as_ref()); + points_str.push_str(format!("{},{} ", coord.x(), coord.y()).as_ref()); } return format!( " \n", @@ -20,7 +21,12 @@ fn generate_consecutive_circles(coords: &[Coordinate]) -> String { let mut circles_str = String::from(""); for coord in coords { circles_str.push_str( - format!("\n", coord.x, coord.y).as_ref(), + format!( + "\n", + coord.x(), + coord.y() + ) + .as_ref(), ); } circles_str @@ -38,17 +44,13 @@ fn move_points_in_viewbox(width: f64, height: f64, points: Vec>) -> V let mut new_points = vec![]; for point in points { new_points.push(Point::new( - point.0.x + width / 2.0, - point.0.y + height / 2.0, + point.x() + width / 2.0, + point.y() + height / 2.0, )); } new_points } -fn map_points_to_coords(points: Vec>) -> Vec> { - points.iter().map(|point| point.0).collect() -} - fn main() -> std::io::Result<()> { let mut points_file = File::create("points.svg")?; let mut concave_hull_file = File::create("concavehull.svg")?; @@ -61,17 +63,16 @@ fn main() -> std::io::Result<()> { ); let norway = geo_test_fixtures::norway_main::(); let v: Vec<_> = norway - .0 .into_iter() - .map(|coord| Point::new(coord.x, coord.y)) + .map(|coord| Point::new(coord.x(), coord.y())) .collect(); let moved_v = move_points_in_viewbox(width as f64, height as f64, v); let multipoint = MultiPoint::from(moved_v); let concave = multipoint.concave_hull(2.0); let convex = multipoint.convex_hull(); - let concave_polygon_str = generate_polygon_str(&concave.exterior().0); - let convex_polygon_str = generate_polygon_str(&convex.exterior().0); - let v_coords = map_points_to_coords(multipoint.0); + let concave_polygon_str = generate_polygon_str(concave.exterior().inner()); + let convex_polygon_str = generate_polygon_str(convex.exterior().inner()); + let v_coords: Vec<_> = multipoint.coords_iter().collect(); let circles_str = generate_consecutive_circles(&v_coords); let points_str = produce_file_content(&svg_file_string, &circles_str); let concave_hull_str = produce_file_content(&svg_file_string, &concave_polygon_str); diff --git a/geo/examples/types.rs b/geo/examples/types.rs index 38c9302c57..0103d1f75f 100644 --- a/geo/examples/types.rs +++ b/geo/examples/types.rs @@ -1,6 +1,5 @@ extern crate geo; -use geo::Point; use geo_types::point; fn main() { @@ -9,6 +8,6 @@ fn main() { y: 116.34, }; - let Point(coord) = p; - println!("Point at ({}, {})", coord.x, coord.y); + let coord = p.coord(); + println!("Point at ({}, {})", coord.x(), coord.y()); } diff --git a/geo/fuzz/fuzz_targets/simplify.rs b/geo/fuzz/fuzz_targets/simplify.rs index ee785a23f9..b9dd7f9533 100644 --- a/geo/fuzz/fuzz_targets/simplify.rs +++ b/geo/fuzz/fuzz_targets/simplify.rs @@ -13,11 +13,11 @@ fuzz_target!(|tuple: (geo_types::Polygon, f32)| { }); fn check_result(original: geo_types::Polygon, simplified: geo_types::Polygon) { - assert!(simplified.exterior().0.len() <= original.exterior().0.len()); + assert!(simplified.exterior().inner().len() <= original.exterior().inner().len()); assert!(simplified.exterior().euclidean_length() <= original.exterior().euclidean_length()); for interior in simplified.interiors() { - assert!(simplified.exterior().0.len() <= interior.0.len()); + assert!(simplified.exterior().inner().len() <= interior.0.len()); assert!(simplified.exterior().euclidean_length() <= interior.euclidean_length()); } } diff --git a/geo/src/algorithm/area.rs b/geo/src/algorithm/area.rs index b3882b589a..5ad32f4873 100644 --- a/geo/src/algorithm/area.rs +++ b/geo/src/algorithm/area.rs @@ -9,13 +9,13 @@ where { // LineString with less than 3 points is empty, or a // single point, or is not closed. - if linestring.0.len() < 3 { + if linestring.inner().len() < 3 { return T::zero(); } // Above test ensures the vector has at least 2 elements. // We check if linestring is closed, and return 0 otherwise. - if linestring.0.first().unwrap() != linestring.0.last().unwrap() { + if linestring.inner().first().unwrap() != linestring.inner().last().unwrap() { return T::zero(); } @@ -29,12 +29,12 @@ where // of the coordinates, but it is not fool-proof to // divide by the length of the linestring (eg. a long // line-string with T = u8) - let shift = linestring.0[0]; + let shift = linestring[0]; let mut tmp = T::zero(); for line in linestring.lines() { use crate::algorithm::map_coords::MapCoords; - let line = line.map_coords(|(x, y)| (x - shift.x, y - shift.y)); + let line = line.map_coords(|(x, y)| (x - shift.x(), y - shift.y())); tmp = tmp + line.determinant(); } @@ -190,13 +190,13 @@ where T: CoordFloat, { fn signed_area(&self) -> T { - self.0 + self.polygons() .iter() .fold(T::zero(), |total, next| total + next.signed_area()) } fn unsigned_area(&self) -> T { - self.0 + self.polygons() .iter() .fold(T::zero(), |total, next| total + next.signed_area().abs()) } @@ -247,15 +247,13 @@ where T: CoordFloat, { fn signed_area(&self) -> T { - self.0 - .iter() + self.iter() .map(|g| g.signed_area()) .fold(T::zero(), |acc, next| acc + next) } fn unsigned_area(&self) -> T { - self.0 - .iter() + self.iter() .map(|g| g.unsigned_area()) .fold(T::zero(), |acc, next| acc + next) } diff --git a/geo/src/algorithm/bounding_rect.rs b/geo/src/algorithm/bounding_rect.rs index 949a14cc9d..f749530d39 100644 --- a/geo/src/algorithm/bounding_rect.rs +++ b/geo/src/algorithm/bounding_rect.rs @@ -25,10 +25,10 @@ pub trait BoundingRect { /// /// let bounding_rect = line_string.bounding_rect().unwrap(); /// - /// assert_eq!(40.02f64, bounding_rect.min().x); - /// assert_eq!(42.02f64, bounding_rect.max().x); - /// assert_eq!(116.34, bounding_rect.min().y); - /// assert_eq!(118.34, bounding_rect.max().y); + /// assert_eq!(40.02f64, bounding_rect.min().x()); + /// assert_eq!(42.02f64, bounding_rect.max().x()); + /// assert_eq!(116.34, bounding_rect.min().y()); + /// assert_eq!(118.34, bounding_rect.max().y()); /// ``` fn bounding_rect(&self) -> Self::Output; } @@ -42,7 +42,7 @@ where /// Return the bounding rectangle for a `Point`. It will have zero width /// and zero height. fn bounding_rect(&self) -> Self::Output { - Rect::new(self.0, self.0) + Rect::new(self.coord(), self.coord()) } } @@ -55,7 +55,7 @@ where /// /// Return the BoundingRect for a MultiPoint fn bounding_rect(&self) -> Self::Output { - get_bounding_rect(self.0.iter().map(|p| p.0)) + get_bounding_rect(self.iter().map(|p| p.coord())) } } @@ -66,7 +66,7 @@ where type Output = Rect; fn bounding_rect(&self) -> Self::Output { - Rect::new(self.start, self.end) + Rect::new(self.start(), self.end()) } } @@ -92,7 +92,7 @@ where /// /// Return the BoundingRect for a MultiLineString fn bounding_rect(&self) -> Self::Output { - get_bounding_rect(self.iter().flat_map(|line| line.0.iter().cloned())) + get_bounding_rect(self.iter().flat_map(|line| line.coords().cloned())) } } @@ -106,7 +106,7 @@ where /// Return the BoundingRect for a Polygon fn bounding_rect(&self) -> Self::Output { let line = self.exterior(); - get_bounding_rect(line.0.iter().cloned()) + get_bounding_rect(line.coords().cloned()) } } @@ -121,7 +121,7 @@ where fn bounding_rect(&self) -> Self::Output { get_bounding_rect( self.iter() - .flat_map(|poly| poly.exterior().0.iter().cloned()), + .flat_map(|poly| poly.exterior().coords().cloned()), ) } } @@ -193,12 +193,12 @@ where fn bounding_rect_merge(a: Rect, b: Rect) -> Rect { Rect::new( coord! { - x: partial_min(a.min().x, b.min().x), - y: partial_min(a.min().y, b.min().y), + x: partial_min(a.min().x(), b.min().x()), + y: partial_min(a.min().y(), b.min().y()), }, coord! { - x: partial_max(a.max().x, b.max().x), - y: partial_max(a.max().y, b.max().y), + x: partial_max(a.max().x(), b.max().x()), + y: partial_max(a.max().y(), b.max().y()), }, ) } diff --git a/geo/src/algorithm/centroid.rs b/geo/src/algorithm/centroid.rs index b4867d2da6..11ee2fb9e8 100644 --- a/geo/src/algorithm/centroid.rs +++ b/geo/src/algorithm/centroid.rs @@ -238,10 +238,12 @@ impl CentroidOperation { fn add_line(&mut self, line: &Line) { match line.dimensions() { - ZeroDimensional => self.add_coord(line.start), - OneDimensional => { - self.add_centroid(OneDimensional, line.centroid().0, line.euclidean_length()) - } + ZeroDimensional => self.add_coord(line.start()), + OneDimensional => self.add_centroid( + OneDimensional, + line.centroid().coord(), + line.euclidean_length(), + ), _ => unreachable!("Line must be zero or one dimensional"), } } @@ -251,8 +253,8 @@ impl CentroidOperation { return; } - if line_string.0.len() == 1 { - self.add_coord(line_string.0[0]); + if line_string.inner().len() == 1 { + self.add_coord(line_string[0]); return; } @@ -266,7 +268,7 @@ impl CentroidOperation { return; } - for element in &multi_line_string.0 { + for element in multi_line_string { self.add_line_string(element); } } @@ -304,19 +306,19 @@ impl CentroidOperation { return; } - for element in &multi_point.0 { - self.add_coord(element.0); + for element in multi_point { + self.add_coord(element.coord()); } } fn add_multi_polygon(&mut self, multi_polygon: &MultiPolygon) { - for element in &multi_polygon.0 { + for element in multi_polygon { self.add_polygon(element); } } fn add_geometry_collection(&mut self, geometry_collection: &GeometryCollection) { - for element in &geometry_collection.0 { + for element in geometry_collection { self.add_geometry(element); } } @@ -331,28 +333,31 @@ impl CentroidOperation { self.add_line(&Line::new(rect.max(), rect.max())); self.add_line(&Line::new(rect.max(), rect.min())); } - TwoDimensional => { - self.add_centroid(TwoDimensional, rect.centroid().0, rect.unsigned_area()) - } + TwoDimensional => self.add_centroid( + TwoDimensional, + rect.centroid().coord(), + rect.unsigned_area(), + ), Empty => unreachable!("Rect dimensions cannot be empty"), } } fn add_triangle(&mut self, triangle: &Triangle) { match triangle.dimensions() { - ZeroDimensional => self.add_coord(triangle.0), + ZeroDimensional => self.add_coord(triangle.vertex_0()), OneDimensional => { // Degenerate triangle is a line, treat it the same way we treat flat // polygons - let l0_1 = Line::new(triangle.0, triangle.1); - let l1_2 = Line::new(triangle.1, triangle.2); - let l2_0 = Line::new(triangle.2, triangle.0); + let l0_1 = Line::new(triangle.vertex_0(), triangle.vertex_1()); + let l1_2 = Line::new(triangle.vertex_1(), triangle.vertex_2()); + let l2_0 = Line::new(triangle.vertex_2(), triangle.vertex_0()); self.add_line(&l0_1); self.add_line(&l1_2); self.add_line(&l2_0); } TwoDimensional => { - let centroid = (triangle.0 + triangle.1 + triangle.2) / T::from(3).unwrap(); + let centroid = (triangle.vertex_0() + triangle.vertex_1() + triangle.vertex_2()) + / T::from(3).unwrap(); self.add_centroid(TwoDimensional, centroid, triangle.unsigned_area()); } Empty => unreachable!("Rect dimensions cannot be empty"), @@ -361,7 +366,7 @@ impl CentroidOperation { fn add_geometry(&mut self, geometry: &Geometry) { match geometry { - Geometry::Point(g) => self.add_coord(g.0), + Geometry::Point(g) => self.add_coord(g.coord()), Geometry::Line(g) => self.add_line(g), Geometry::LineString(g) => self.add_line_string(g), Geometry::Polygon(g) => self.add_polygon(g), @@ -391,13 +396,13 @@ impl CentroidOperation { } // Since area is non-zero, we know the ring has at least one point - let shift = ring.0[0]; + let shift = ring[0]; let accumulated_coord = ring.lines().fold(Coordinate::zero(), |accum, line| { use crate::algorithm::map_coords::MapCoords; - let line = line.map_coords(|(x, y)| (x - shift.x, y - shift.y)); + let line = line.map_coords(|(x, y)| (x - shift.x(), y - shift.y())); let tmp = line.determinant(); - accum + (line.end + line.start) * tmp + accum + (line.end() + line.start()) * tmp }); let six = T::from(6).unwrap(); let centroid = accumulated_coord / (six * area) + shift; @@ -576,7 +581,7 @@ mod test { fn polygon_one_point_test() { let p = point![ x: 2., y: 1. ]; let v = Vec::new(); - let linestring = line_string![p.0]; + let linestring = line_string![p.coord()]; let poly = Polygon::new(linestring, v); assert_relative_eq!(poly.centroid().unwrap(), p); } @@ -615,10 +620,10 @@ mod test { .centroid() .unwrap() .map_coords(|(x, y)| (x - shift_x, y - shift_y)); - debug!("centroid {:?}", centroid.0); - debug!("new_centroid {:?}", new_centroid.0); - assert_relative_eq!(centroid.0.x, new_centroid.0.x, max_relative = 0.0001); - assert_relative_eq!(centroid.0.y, new_centroid.0.y, max_relative = 0.0001); + debug!("centroid {:?}", centroid.coord()); + debug!("new_centroid {:?}", new_centroid.coord()); + assert_relative_eq!(centroid.x(), new_centroid.x(), max_relative = 0.0001); + assert_relative_eq!(centroid.y(), new_centroid.y(), max_relative = 0.0001); } #[test] @@ -897,19 +902,17 @@ mod test { assert_eq!(collection.centroid().unwrap(), point!(x: 4., y: 2.)); // 0-d rect treated like point - collection.0.push(Rect::new(c(0., 6.), c(0., 6.)).into()); + collection.push(Rect::new(c(0., 6.), c(0., 6.)).into()); assert_eq!(collection.centroid().unwrap(), point!(x: 3., y: 3.)); // 1-d rect treated like line. Since a line has higher dimensions than the rest of the // collection, it's centroid clobbers everything else in the collection. - collection.0.push(Rect::new(c(0., 0.), c(0., 2.)).into()); + collection.push(Rect::new(c(0., 0.), c(0., 2.)).into()); assert_eq!(collection.centroid().unwrap(), point!(x: 0., y: 1.)); // 2-d has higher dimensions than the rest of the collection, so it's centroid clobbers // everything else in the collection. - collection - .0 - .push(Rect::new(c(10., 10.), c(11., 11.)).into()); + collection.push(Rect::new(c(10., 10.), c(11., 11.)).into()); assert_eq!(collection.centroid().unwrap(), point!(x: 10.5, y: 10.5)); } } diff --git a/geo/src/algorithm/chaikin_smoothing.rs b/geo/src/algorithm/chaikin_smoothing.rs index 7c2798dcb4..f8b442f5d5 100644 --- a/geo/src/algorithm/chaikin_smoothing.rs +++ b/geo/src/algorithm/chaikin_smoothing.rs @@ -46,8 +46,7 @@ where { fn chaikin_smoothing(&self, n_iterations: usize) -> Self { MultiLineString::new( - self.0 - .iter() + self.iter() .map(|ls| ls.chaikin_smoothing(n_iterations)) .collect(), ) @@ -75,8 +74,7 @@ where { fn chaikin_smoothing(&self, n_iterations: usize) -> Self { MultiPolygon::new( - self.0 - .iter() + self.iter() .map(|poly| poly.chaikin_smoothing(n_iterations)) .collect(), ) @@ -87,21 +85,21 @@ fn smoothen_linestring(linestring: &LineString) -> LineString where T: CoordFloat + Mul + FromPrimitive, { - let mut out_coords: Vec<_> = Vec::with_capacity(linestring.0.len() * 2); + let mut out_coords: Vec<_> = Vec::with_capacity(linestring.inner().len() * 2); - if let (Some(first), Some(last)) = (linestring.0.first(), linestring.0.last()) { + if let (Some(first), Some(last)) = (linestring.inner().first(), linestring.inner().last()) { if first != last { // preserve start coordinate when the linestring is open out_coords.push(*first); } } - for window_coordinates in linestring.0.windows(2) { + for window_coordinates in linestring.inner().windows(2) { let (q, r) = smoothen_coordinates(window_coordinates[0], window_coordinates[1]); out_coords.push(q); out_coords.push(r); } - if let (Some(first), Some(last)) = (linestring.0.first(), linestring.0.last()) { + if let (Some(first), Some(last)) = (linestring.inner().first(), linestring.inner().last()) { if first != last { // preserve the last coordinate of an open linestring out_coords.push(*last); @@ -121,12 +119,12 @@ where T: CoordFloat + Mul + FromPrimitive, { let q = coord! { - x: (T::from(0.75).unwrap() * c0.x) + (T::from(0.25).unwrap() * c1.x), - y: (T::from(0.75).unwrap() * c0.y) + (T::from(0.25).unwrap() * c1.y), + x: (T::from(0.75).unwrap() * c0.x()) + (T::from(0.25).unwrap() * c1.x()), + y: (T::from(0.75).unwrap() * c0.y()) + (T::from(0.25).unwrap() * c1.y()), }; let r = coord! { - x: (T::from(0.25).unwrap() * c0.x) + (T::from(0.75).unwrap() * c1.x), - y: (T::from(0.25).unwrap() * c0.y) + (T::from(0.75).unwrap() * c1.y), + x: (T::from(0.25).unwrap() * c0.x()) + (T::from(0.75).unwrap() * c1.x()), + y: (T::from(0.25).unwrap() * c0.y()) + (T::from(0.75).unwrap() * c1.y()), }; (q, r) } diff --git a/geo/src/algorithm/chamberlain_duquette_area.rs b/geo/src/algorithm/chamberlain_duquette_area.rs index 77fd1dae12..754e903d49 100644 --- a/geo/src/algorithm/chamberlain_duquette_area.rs +++ b/geo/src/algorithm/chamberlain_duquette_area.rs @@ -75,7 +75,7 @@ where T: Float + CoordNum, { let mut total = T::zero(); - let coords_len = coords.0.len(); + let coords_len = coords.inner().len(); if coords_len > 2 { for i in 0..coords_len { @@ -92,7 +92,7 @@ where let p1 = coords[lower_index]; let p2 = coords[middle_index]; let p3 = coords[upper_index]; - total = total + (p3.x.to_radians() - p1.x.to_radians()) * p2.y.to_radians().sin(); + total = total + (p3.x().to_radians() - p1.x().to_radians()) * p2.y().to_radians().sin(); } total = total diff --git a/geo/src/algorithm/closest_point.rs b/geo/src/algorithm/closest_point.rs index 7116d87c74..bc06530f62 100644 --- a/geo/src/algorithm/closest_point.rs +++ b/geo/src/algorithm/closest_point.rs @@ -64,21 +64,21 @@ impl ClosestPoint for Line { // // Line equation: P = start + t * (end - start) - let direction_vector = Point::from(self.end - self.start); - let to_p = Point::from(p.0 - self.start); + let direction_vector = Point::from(self.end() - self.start()); + let to_p = Point::from(p.coord() - self.start()); let t = to_p.dot(direction_vector) / direction_vector.dot(direction_vector); // check the cases where the closest point is "outside" the line if t < F::zero() { - return Closest::SinglePoint(self.start.into()); + return Closest::SinglePoint(self.start().into()); } else if t > F::one() { - return Closest::SinglePoint(self.end.into()); + return Closest::SinglePoint(self.end().into()); } let x = direction_vector.x(); let y = direction_vector.y(); - let c = Point::from(self.start + (t * x, t * y).into()); + let c = Point::from(self.start() + (t * x, t * y).into()); if self.intersects(p) { Closest::Intersection(c) @@ -292,7 +292,7 @@ mod tests { #[test] fn polygon_with_point_on_interior_ring() { let poly = holy_polygon(); - let p = poly.interiors()[0].0[3]; + let p = poly.interiors()[0][3]; let should_be = Closest::Intersection(p.into()); let got = poly.closest_point(&p.into()); diff --git a/geo/src/algorithm/concave_hull.rs b/geo/src/algorithm/concave_hull.rs index 73b662582f..d1af6cbaa6 100644 --- a/geo/src/algorithm/concave_hull.rs +++ b/geo/src/algorithm/concave_hull.rs @@ -55,7 +55,7 @@ where { type Scalar = T; fn concave_hull(&self, concavity: Self::Scalar) -> Polygon { - let mut points: Vec<_> = self.exterior().0.clone(); + let mut points: Vec<_> = self.exterior().inner().to_vec(); Polygon::new(concave_hull(&mut points, concavity), vec![]) } } @@ -67,9 +67,8 @@ where type Scalar = T; fn concave_hull(&self, concavity: Self::Scalar) -> Polygon { let mut aggregated: Vec> = self - .0 .iter() - .flat_map(|elem| elem.exterior().0.clone()) + .flat_map(|elem| elem.exterior().inner().to_vec()) .collect(); Polygon::new(concave_hull(&mut aggregated, concavity), vec![]) } @@ -81,7 +80,7 @@ where { type Scalar = T; fn concave_hull(&self, concavity: Self::Scalar) -> Polygon { - Polygon::new(concave_hull(&mut self.0.clone(), concavity), vec![]) + Polygon::new(concave_hull(&mut self.inner().to_vec(), concavity), vec![]) } } @@ -92,7 +91,7 @@ where type Scalar = T; fn concave_hull(&self, concavity: T) -> Polygon { let mut aggregated: Vec> = - self.iter().flat_map(|elem| elem.0.clone()).collect(); + self.iter().flat_map(|elem| elem.inner().to_vec()).collect(); Polygon::new(concave_hull(&mut aggregated, concavity), vec![]) } } @@ -103,7 +102,7 @@ where { type Scalar = T; fn concave_hull(&self, concavity: T) -> Polygon { - let mut coordinates: Vec> = self.iter().map(|point| point.0).collect(); + let mut coordinates: Vec> = self.iter().map(|point| point.coord()).collect(); Polygon::new(concave_hull(&mut coordinates, concavity), vec![]) } } @@ -136,8 +135,8 @@ where None => None, Some(&point) => { let closest_point = - candidates.fold(Point::new(point.x, point.y), |acc_point, candidate| { - let candidate_point = Point::new(candidate.x, candidate.y); + candidates.fold(Point::new(point.x(), point.y()), |acc_point, candidate| { + let candidate_point = Point::new(candidate.x(), candidate.y()); if line.euclidean_distance(&acc_point) > line.euclidean_distance(&candidate_point) { @@ -202,7 +201,7 @@ where } //Get points in overall dataset that aren't on the exterior linestring of the hull - let hull_tree: RTree> = RTree::bulk_load(hull.clone().0); + let hull_tree: RTree> = RTree::bulk_load(hull.inner().to_vec()); let interior_coords: Vec> = coords .iter() @@ -235,7 +234,7 @@ where if let Some(closest_point) = possible_closest_point { interior_points_tree.remove(&closest_point); line_tree.remove(&line); - let point = Point::new(closest_point.x, closest_point.y); + let point = Point::new(closest_point.x(), closest_point.y()); let start_line = Line::new(line.start_point(), point); let end_line = Line::new(point, line.end_point()); line_tree.insert(start_line); @@ -400,7 +399,7 @@ mod test { Coordinate::from((0.0, 0.0)), Coordinate::from((4.0, 0.0)), ]; - assert_eq!(concave.exterior().0, correct); + assert_eq!(concave.exterior().inner(), correct); } #[test] @@ -424,7 +423,7 @@ mod test { Coordinate::from((4.0, 0.0)), ]; let res = mls.concave_hull(2.0); - assert_eq!(res.exterior().0, correct); + assert_eq!(res.exterior().inner(), correct); } #[test] @@ -448,6 +447,6 @@ mod test { Coordinate::from((0.0, 0.0)), Coordinate::from((4.0, 0.0)), ]; - assert_eq!(res.exterior().0, correct); + assert_eq!(res.exterior().inner(), correct); } } diff --git a/geo/src/algorithm/contains/geometry.rs b/geo/src/algorithm/contains/geometry.rs index 1f93025814..13091f597e 100644 --- a/geo/src/algorithm/contains/geometry.rs +++ b/geo/src/algorithm/contains/geometry.rs @@ -41,6 +41,6 @@ where T: GeoNum, { fn contains(&self, point: &Point) -> bool { - self.contains(&point.0) + self.contains(&point.coord()) } } diff --git a/geo/src/algorithm/contains/line.rs b/geo/src/algorithm/contains/line.rs index d9912a83b7..898b1a8eaf 100644 --- a/geo/src/algorithm/contains/line.rs +++ b/geo/src/algorithm/contains/line.rs @@ -11,10 +11,10 @@ where T: GeoNum, { fn contains(&self, coord: &Coordinate) -> bool { - if self.start == self.end { - &self.start == coord + if self.start() == self.end() { + &self.start() == coord } else { - coord != &self.start && coord != &self.end && self.intersects(coord) + coord != &self.start() && coord != &self.end() && self.intersects(coord) } } } @@ -24,7 +24,7 @@ where T: GeoNum, { fn contains(&self, p: &Point) -> bool { - self.contains(&p.0) + self.contains(&p.coord()) } } @@ -33,10 +33,10 @@ where T: GeoNum, { fn contains(&self, line: &Line) -> bool { - if line.start == line.end { - self.contains(&line.start) + if line.start() == line.end() { + self.contains(&line.start()) } else { - self.intersects(&line.start) && self.intersects(&line.end) + self.intersects(&line.start()) && self.intersects(&line.end()) } } } @@ -48,7 +48,7 @@ where fn contains(&self, linestring: &LineString) -> bool { // Empty linestring has no interior, and not // contained in anything. - if linestring.0.is_empty() { + if linestring.inner().is_empty() { return false; } @@ -64,14 +64,14 @@ where // are the same. In this case, the interior is this // specific point, and it should be contained in the // line. - let first = linestring.0.first().unwrap(); + let first = linestring.inner().first().unwrap(); let mut all_equal = true; // If all the vertices of the linestring intersect // self, then the interior or boundary of the // linestring cannot have non-empty intersection // with the exterior. - let all_intersects = linestring.0.iter().all(|c| { + let all_intersects = linestring.coords().all(|c| { if c != first { all_equal = false; } diff --git a/geo/src/algorithm/contains/line_string.rs b/geo/src/algorithm/contains/line_string.rs index 8272208aa0..92fe1f2647 100644 --- a/geo/src/algorithm/contains/line_string.rs +++ b/geo/src/algorithm/contains/line_string.rs @@ -11,17 +11,17 @@ where T: GeoNum, { fn contains(&self, coord: &Coordinate) -> bool { - if self.0.is_empty() { + if self.inner().is_empty() { return false; } - if self.is_closed() && coord == &self.0[0] { + if self.is_closed() && coord == &self[0] { return true; } self.lines() .enumerate() - .any(|(i, line)| line.contains(coord) || (i > 0 && coord == &line.start)) + .any(|(i, line)| line.contains(coord) || (i > 0 && coord == &line.start())) } } @@ -30,7 +30,7 @@ where T: GeoNum, { fn contains(&self, p: &Point) -> bool { - self.contains(&p.0) + self.contains(&p.coord()) } } @@ -39,8 +39,8 @@ where T: GeoNum, { fn contains(&self, line: &Line) -> bool { - if line.start == line.end { - return self.contains(&line.start); + if line.start() == line.end() { + return self.contains(&line.start()); } // We copy the line as we may truncate the line as @@ -68,10 +68,10 @@ where } // Look for a segment that intersects at least // one of the end points. - let other = if segment.intersects(&line.start) { - line.end - } else if segment.intersects(&line.end) { - line.start + let other = if segment.intersects(&line.start()) { + line.end() + } else if segment.intersects(&line.end()) { + line.start() } else { continue; }; @@ -84,19 +84,19 @@ where // otoh, if the line contains one of the ends of // the segments, then we truncate the line to // the part outside. - else if line.contains(&segment.start) { - segment.start - } else if line.contains(&segment.end) { - segment.end + else if line.contains(&segment.start()) { + segment.start() + } else if line.contains(&segment.end()) { + segment.end() } else { continue; }; first_cut = first_cut.or(Some(i)); - if other == line.start { - line.end = new_inside; + if other == line.start() { + *line.end_mut() = new_inside; } else { - line.start = new_inside; + *line.start_mut() = new_inside; } } diff --git a/geo/src/algorithm/contains/point.rs b/geo/src/algorithm/contains/point.rs index 7c72abc506..9d0dd94e08 100644 --- a/geo/src/algorithm/contains/point.rs +++ b/geo/src/algorithm/contains/point.rs @@ -10,7 +10,7 @@ where T: CoordNum, { fn contains(&self, coord: &Coordinate) -> bool { - &self.0 == coord + &self.coord() == coord } } @@ -19,7 +19,7 @@ where T: CoordNum, { fn contains(&self, p: &Point) -> bool { - self.contains(&p.0) + self.contains(&p.coord()) } } diff --git a/geo/src/algorithm/contains/polygon.rs b/geo/src/algorithm/contains/polygon.rs index 7d81d9322f..1929f10da6 100644 --- a/geo/src/algorithm/contains/polygon.rs +++ b/geo/src/algorithm/contains/polygon.rs @@ -24,7 +24,7 @@ where T: GeoNum, { fn contains(&self, p: &Point) -> bool { - self.contains(&p.0) + self.contains(&p.coord()) } } @@ -73,7 +73,7 @@ where T: GeoNum, { fn contains(&self, p: &Point) -> bool { - self.contains(&p.0) + self.contains(&p.coord()) } } diff --git a/geo/src/algorithm/contains/rect.rs b/geo/src/algorithm/contains/rect.rs index 39b04b522f..63b3f085ac 100644 --- a/geo/src/algorithm/contains/rect.rs +++ b/geo/src/algorithm/contains/rect.rs @@ -10,10 +10,10 @@ where T: CoordNum, { fn contains(&self, coord: &Coordinate) -> bool { - coord.x > self.min().x - && coord.x < self.max().x - && coord.y > self.min().y - && coord.y < self.max().y + coord.x() > self.min().x() + && coord.x() < self.max().x() + && coord.y() > self.min().y() + && coord.y() < self.max().y() } } @@ -22,7 +22,7 @@ where T: CoordNum, { fn contains(&self, p: &Point) -> bool { - self.contains(&p.0) + self.contains(&p.coord()) } } @@ -33,9 +33,9 @@ where fn contains(&self, other: &Rect) -> bool { // TODO: check for degenerate rectangle (which is a line or a point) // All points of LineString must be in the polygon ? - self.min().x <= other.min().x - && self.max().x >= other.max().x - && self.min().y <= other.min().y - && self.max().y >= other.max().y + self.min().x() <= other.min().x() + && self.max().x() >= other.max().x() + && self.min().y() <= other.min().y() + && self.max().y() >= other.max().y() } } diff --git a/geo/src/algorithm/contains/triangle.rs b/geo/src/algorithm/contains/triangle.rs index 489a672eff..48c97aa496 100644 --- a/geo/src/algorithm/contains/triangle.rs +++ b/geo/src/algorithm/contains/triangle.rs @@ -10,7 +10,12 @@ where T: GeoNum, { fn contains(&self, coord: &Coordinate) -> bool { - let ls = LineString::new(vec![self.0, self.1, self.2, self.0]); + let ls = LineString::new(vec![ + self.vertex_0(), + self.vertex_1(), + self.vertex_2(), + self.vertex_0(), + ]); use crate::utils::{coord_pos_relative_to_ring, CoordPos}; coord_pos_relative_to_ring(*coord, &ls) == CoordPos::Inside } @@ -21,6 +26,6 @@ where T: GeoNum, { fn contains(&self, point: &Point) -> bool { - self.contains(&point.0) + self.contains(&point.coord()) } } diff --git a/geo/src/algorithm/convex_hull/graham.rs b/geo/src/algorithm/convex_hull/graham.rs index 6d990fe34a..3fb25ffaec 100644 --- a/geo/src/algorithm/convex_hull/graham.rs +++ b/geo/src/algorithm/convex_hull/graham.rs @@ -139,11 +139,11 @@ mod test { #[test] fn graham_test_complex() { - test_convexity(geo_test_fixtures::poly1::().0); + test_convexity(geo_test_fixtures::poly1::().into_inner()); } #[test] fn quick_hull_test_complex_2() { - test_convexity(geo_test_fixtures::poly2::().0); + test_convexity(geo_test_fixtures::poly2::().into_inner()); } } diff --git a/geo/src/algorithm/convex_hull/mod.rs b/geo/src/algorithm/convex_hull/mod.rs index b497095b96..d0a48f8985 100644 --- a/geo/src/algorithm/convex_hull/mod.rs +++ b/geo/src/algorithm/convex_hull/mod.rs @@ -47,7 +47,7 @@ where { type Scalar = T; fn convex_hull(&self) -> Polygon { - Polygon::new(quick_hull(&mut self.exterior().0.clone()), vec![]) + Polygon::new(quick_hull(&mut self.exterior().inner().to_vec()), vec![]) } } @@ -58,9 +58,8 @@ where type Scalar = T; fn convex_hull(&self) -> Polygon { let mut aggregated: Vec<_> = self - .0 .iter() - .flat_map(|elem| elem.exterior().0.iter().copied()) + .flat_map(|elem| elem.exterior().coords().copied()) .collect(); Polygon::new(quick_hull(&mut aggregated), vec![]) } @@ -72,7 +71,7 @@ where { type Scalar = T; fn convex_hull(&self) -> Polygon { - Polygon::new(quick_hull(&mut self.0.clone()), vec![]) + Polygon::new(quick_hull(&mut self.inner().to_vec()), vec![]) } } @@ -82,7 +81,7 @@ where { type Scalar = T; fn convex_hull(&self) -> Polygon { - let mut aggregated: Vec<_> = self.iter().flat_map(|elem| elem.clone().0).collect(); + let mut aggregated: Vec<_> = self.iter().flat_map(|elem| elem.inner().to_vec()).collect(); Polygon::new(quick_hull(&mut aggregated), vec![]) } } @@ -93,7 +92,7 @@ where { type Scalar = T; fn convex_hull(&self) -> Polygon { - let mut aggregated: Vec<_> = self.iter().map(|p| p.0).collect(); + let mut aggregated: Vec<_> = self.iter().map(|p| p.coord()).collect(); Polygon::new(quick_hull(&mut aggregated), vec![]) } } diff --git a/geo/src/algorithm/convex_hull/qhull.rs b/geo/src/algorithm/convex_hull/qhull.rs index 54723f0a60..acd6f8da48 100644 --- a/geo/src/algorithm/convex_hull/qhull.rs +++ b/geo/src/algorithm/convex_hull/qhull.rs @@ -84,18 +84,18 @@ fn hull_set( // compute inner product of this with `v` - `p_a` to // find the farthest point from the line segment a-b. let p_orth = coord! { - x: p_a.y - p_b.y, - y: p_b.x - p_a.x, + x: p_a.y() - p_b.y(), + y: p_b.x() - p_a.x(), }; let furthest_idx = set .iter() .map(|pt| { let p_diff = coord! { - x: pt.x - p_a.x, - y: pt.y - p_a.y, + x: pt.x() - p_a.x(), + y: pt.y() - p_a.y(), }; - p_orth.x * p_diff.x + p_orth.y * p_diff.y + p_orth.x() * p_diff.x() + p_orth.y() * p_diff.y() }) .enumerate() .max_by(|(_, a), (_, b)| a.partial_cmp(b).unwrap()) @@ -156,7 +156,7 @@ mod test { coord! { x: 0, y: -10 }, ]; let res = quick_hull(&mut v); - assert_eq!(res.0, correct); + assert_eq!(res.inner(), correct); } #[test] @@ -174,7 +174,7 @@ mod test { let correct = vec![(1.0, 0.0), (2.0, 1.0), (1.0, 2.0), (0.0, 1.0), (1.0, 0.0)]; let v_correct: Vec<_> = correct.iter().map(|e| coord! { x: e.0, y: e.1 }).collect(); let res = quick_hull(&mut v); - assert_eq!(res.0, v_correct); + assert_eq!(res.inner(), v_correct); } #[test] @@ -197,18 +197,18 @@ mod test { #[test] fn quick_hull_test_complex() { - let mut coords = geo_test_fixtures::poly1::().0; - let correct = geo_test_fixtures::poly1_hull::().0; + let mut coords = geo_test_fixtures::poly1::().into_inner(); + let correct = geo_test_fixtures::poly1_hull::().into_inner(); let res = quick_hull(&mut coords); - assert_eq!(res.0, correct); + assert_eq!(res.inner(), correct); } #[test] fn quick_hull_test_complex_2() { - let mut coords = geo_test_fixtures::poly2::().0; - let correct = geo_test_fixtures::poly2_hull::().0; + let mut coords = geo_test_fixtures::poly2::().into_inner(); + let correct = geo_test_fixtures::poly2_hull::().into_inner(); let res = quick_hull(&mut coords); - assert_eq!(res.0, correct); + assert_eq!(res.inner(), correct); } #[test] diff --git a/geo/src/algorithm/convex_hull/test.rs b/geo/src/algorithm/convex_hull/test.rs index 1f05f35b0b..b8b8fba011 100644 --- a/geo/src/algorithm/convex_hull/test.rs +++ b/geo/src/algorithm/convex_hull/test.rs @@ -23,7 +23,7 @@ fn convex_hull_multipoint_test() { Coordinate::from((0, -10)), ]; let res = mp.convex_hull(); - assert_eq!(res.exterior().0, correct); + assert_eq!(res.exterior().inner(), correct); } #[test] fn convex_hull_linestring_test() { @@ -46,7 +46,7 @@ fn convex_hull_linestring_test() { Coordinate::from((0.0, -10.0)), ]; let res = mp.convex_hull(); - assert_eq!(res.exterior().0, correct); + assert_eq!(res.exterior().inner(), correct); } #[test] fn convex_hull_multilinestring_test() { @@ -61,7 +61,7 @@ fn convex_hull_multilinestring_test() { Coordinate::from((2.0, 0.0)), ]; let res = mls.convex_hull(); - assert_eq!(res.exterior().0, correct); + assert_eq!(res.exterior().inner(), correct); } #[test] fn convex_hull_multipolygon_test() { @@ -76,5 +76,5 @@ fn convex_hull_multipolygon_test() { Coordinate::from((5.0, 0.0)), ]; let res = mp.convex_hull(); - assert_eq!(res.exterior().0, correct); + assert_eq!(res.exterior().inner(), correct); } diff --git a/geo/src/algorithm/coordinate_position.rs b/geo/src/algorithm/coordinate_position.rs index c36303d3d7..70e2ed58f6 100644 --- a/geo/src/algorithm/coordinate_position.rs +++ b/geo/src/algorithm/coordinate_position.rs @@ -94,7 +94,7 @@ where is_inside: &mut bool, _boundary_count: &mut usize, ) { - if &self.0 == coord { + if &self.coord() == coord { *is_inside = true; } } @@ -112,13 +112,13 @@ where boundary_count: &mut usize, ) { // degenerate line is a point - if self.start == self.end { - self.start + if self.start() == self.end() { + self.start() .calculate_coordinate_position(coord, is_inside, boundary_count); return; } - if coord == &self.start || coord == &self.end { + if coord == &self.start() || coord == &self.end() { *boundary_count += 1; } else if self.intersects(coord) { *is_inside = true; @@ -137,14 +137,14 @@ where is_inside: &mut bool, boundary_count: &mut usize, ) { - if self.0.len() < 2 { + if self.inner().len() < 2 { debug_assert!(false, "invalid line string with less than 2 coords"); return; } - if self.0.len() == 2 { + if self.inner().len() == 2 { // line string with two coords is just a line - Line::new(self.0[0], self.0[1]).calculate_coordinate_position( + Line::new(self[0], self[1]).calculate_coordinate_position( coord, is_inside, boundary_count, @@ -161,7 +161,7 @@ where // A closed linestring has no boundary, per SFS if !self.is_closed() { // since self.0 is non-empty, safe to `unwrap` - if coord == self.0.first().unwrap() || coord == self.0.last().unwrap() { + if coord == self.inner().first().unwrap() || coord == self.inner().last().unwrap() { *boundary_count += 1; return; } @@ -220,7 +220,7 @@ where is_inside: &mut bool, _boundary_count: &mut usize, ) { - if self.0.iter().any(|p| &p.0 == coord) { + if self.iter().any(|p| &p.coord() == coord) { *is_inside = true; } } @@ -282,7 +282,7 @@ where is_inside: &mut bool, boundary_count: &mut usize, ) { - for line_string in &self.0 { + for line_string in self { line_string.calculate_coordinate_position(coord, is_inside, boundary_count); } } @@ -299,7 +299,7 @@ where is_inside: &mut bool, boundary_count: &mut usize, ) { - for polygon in &self.0 { + for polygon in self { polygon.calculate_coordinate_position(coord, is_inside, boundary_count); } } @@ -361,13 +361,13 @@ where debug_assert!(linestring.is_closed()); // LineString without points - if linestring.0.is_empty() { + if linestring.inner().is_empty() { return CoordPos::Outside; } - if linestring.0.len() == 1 { + if linestring.inner().len() == 1 { // If LineString has one point, it will not generate // any lines. So, we handle this edge case separately. - return if coord == linestring.0[0] { + return if coord == linestring[0] { CoordPos::OnBoundary } else { CoordPos::Outside @@ -382,12 +382,12 @@ where } // Ignore if the line is strictly to the left of the coord. - let max_x = if line.start.x < line.end.x { - line.end.x + let max_x = if line.start().x() < line.end().x() { + line.end().x() } else { - line.start.x + line.start().x() }; - if max_x < coord.x { + if max_x < coord.x() { continue; } @@ -395,7 +395,7 @@ where // edge case where the ray would intersect a // horizontal segment of the ring infinitely many // times, and is irrelevant for the calculation. - if line.start.y == line.end.y { + if line.start().y() == line.end().y() { continue; } @@ -410,8 +410,8 @@ where // at the point of intersection // 2. if the ray touches a vertex, // but doesn't enter/exit at that point - if (line.start.y == coord.y && line.end.y < coord.y) - || (line.end.y == coord.y && line.start.y < coord.y) + if (line.start().y() == coord.y() && line.end().y() < coord.y()) + || (line.end().y() == coord.y() && line.start().y() < coord.y()) { continue; } @@ -423,7 +423,7 @@ where coord, coord! { x: max_x, - y: coord.y, + y: coord.y(), }, ); if ray.intersects(&line) { diff --git a/geo/src/algorithm/coords_iter.rs b/geo/src/algorithm/coords_iter.rs index ff75fe6978..b413fbc45e 100644 --- a/geo/src/algorithm/coords_iter.rs +++ b/geo/src/algorithm/coords_iter.rs @@ -103,7 +103,7 @@ impl<'a, T: CoordNum> CoordsIter<'a> for Point { type Scalar = T; fn coords_iter(&'a self) -> Self::Iter { - iter::once(self.0) + iter::once(self.coord()) } /// Return the number of coordinates in the `Point`. @@ -126,7 +126,7 @@ impl<'a, T: CoordNum> CoordsIter<'a> for Line { type Scalar = T; fn coords_iter(&'a self) -> Self::Iter { - iter::once(self.start).chain(iter::once(self.end)) + iter::once(self.start()).chain(iter::once(self.end())) } /// Return the number of coordinates in the `Line`. @@ -151,12 +151,12 @@ impl<'a, T: CoordNum + 'a> CoordsIter<'a> for LineString { type Scalar = T; fn coords_iter(&'a self) -> Self::Iter { - self.0.iter().copied() + self.inner().iter().copied() } /// Return the number of coordinates in the `LineString`. fn coords_count(&'a self) -> usize { - self.0.len() + self.inner().len() } fn exterior_coords_iter(&'a self) -> Self::ExteriorIter { @@ -209,12 +209,12 @@ impl<'a, T: CoordNum + 'a> CoordsIter<'a> for MultiPoint { type Scalar = T; fn coords_iter(&'a self) -> Self::Iter { - MapCoordsIter(self.0.iter(), marker::PhantomData).flatten() + MapCoordsIter(self.points().iter(), marker::PhantomData).flatten() } /// Return the number of coordinates in the `MultiPoint`. fn coords_count(&'a self) -> usize { - self.0.len() + self.points().len() } fn exterior_coords_iter(&'a self) -> Self::ExteriorIter { @@ -232,13 +232,12 @@ impl<'a, T: CoordNum + 'a> CoordsIter<'a> for MultiLineString { type Scalar = T; fn coords_iter(&'a self) -> Self::Iter { - MapCoordsIter(self.0.iter(), marker::PhantomData).flatten() + MapCoordsIter(self.line_strings().iter(), marker::PhantomData).flatten() } /// Return the number of coordinates in the `MultiLineString`. fn coords_count(&'a self) -> usize { - self.0 - .iter() + self.iter() .map(|line_string| line_string.coords_count()) .sum() } @@ -259,16 +258,19 @@ impl<'a, T: CoordNum + 'a> CoordsIter<'a> for MultiPolygon { type Scalar = T; fn coords_iter(&'a self) -> Self::Iter { - MapCoordsIter(self.0.iter(), marker::PhantomData).flatten() + MapCoordsIter(self.polygons().iter(), marker::PhantomData).flatten() } /// Return the number of coordinates in the `MultiPolygon`. fn coords_count(&'a self) -> usize { - self.0.iter().map(|polygon| polygon.coords_count()).sum() + self.polygons() + .iter() + .map(|polygon| polygon.coords_count()) + .sum() } fn exterior_coords_iter(&'a self) -> Self::ExteriorIter { - MapExteriorCoordsIter(self.0.iter(), marker::PhantomData).flatten() + MapExteriorCoordsIter(self.polygons().iter(), marker::PhantomData).flatten() } } @@ -282,17 +284,21 @@ impl<'a, T: CoordNum + 'a> CoordsIter<'a> for GeometryCollection { type Scalar = T; fn coords_iter(&'a self) -> Self::Iter { - Box::new(self.0.iter().flat_map(|geometry| geometry.coords_iter())) + Box::new( + self.geometries() + .iter() + .flat_map(|geometry| geometry.coords_iter()), + ) } /// Return the number of coordinates in the `GeometryCollection`. fn coords_count(&'a self) -> usize { - self.0.iter().map(|geometry| geometry.coords_count()).sum() + self.iter().map(|geometry| geometry.coords_count()).sum() } fn exterior_coords_iter(&'a self) -> Self::ExteriorIter { Box::new( - self.0 + self.geometries() .iter() .flat_map(|geometry| geometry.exterior_coords_iter()), ) @@ -315,20 +321,20 @@ impl<'a, T: CoordNum + 'a> CoordsIter<'a> for Rect { fn coords_iter(&'a self) -> Self::Iter { iter::once(coord! { - x: self.min().x, - y: self.min().y, + x: self.min().x(), + y: self.min().y(), }) .chain(iter::once(coord! { - x: self.min().x, - y: self.max().y, + x: self.min().x(), + y: self.max().y(), })) .chain(iter::once(coord! { - x: self.max().x, - y: self.max().y, + x: self.max().x(), + y: self.max().y(), })) .chain(iter::once(coord! { - x: self.max().x, - y: self.min().y, + x: self.max().x(), + y: self.min().y(), })) } @@ -355,9 +361,9 @@ impl<'a, T: CoordNum + 'a> CoordsIter<'a> for Triangle { type Scalar = T; fn coords_iter(&'a self) -> Self::Iter { - iter::once(self.0) - .chain(iter::once(self.1)) - .chain(iter::once(self.2)) + iter::once(self.vertex_0()) + .chain(iter::once(self.vertex_1())) + .chain(iter::once(self.vertex_2())) } /// Return the number of coordinates in the `Triangle`. diff --git a/geo/src/algorithm/dimensions.rs b/geo/src/algorithm/dimensions.rs index d051b7fc77..67a3d2a1bf 100644 --- a/geo/src/algorithm/dimensions.rs +++ b/geo/src/algorithm/dimensions.rs @@ -168,7 +168,7 @@ impl HasDimensions for Line { } fn dimensions(&self) -> Dimensions { - if self.start == self.end { + if self.start() == self.end() { // degenerate line is a point Dimensions::ZeroDimensional } else { @@ -177,7 +177,7 @@ impl HasDimensions for Line { } fn boundary_dimensions(&self) -> Dimensions { - if self.start == self.end { + if self.start() == self.end() { // degenerate line is a point, which has no boundary Dimensions::Empty } else { @@ -188,16 +188,16 @@ impl HasDimensions for Line { impl HasDimensions for LineString { fn is_empty(&self) -> bool { - self.0.is_empty() + self.inner().is_empty() } fn dimensions(&self) -> Dimensions { - if self.0.is_empty() { + if self.inner().is_empty() { return Dimensions::Empty; } - let first = self.0[0]; - if self.0.iter().any(|&coord| first != coord) { + let first = self[0]; + if self.coords().any(|&coord| first != coord) { Dimensions::OneDimensional } else { // all coords are the same - i.e. a point @@ -256,11 +256,11 @@ impl HasDimensions for Polygon { impl HasDimensions for MultiPoint { fn is_empty(&self) -> bool { - self.0.is_empty() + self.points().is_empty() } fn dimensions(&self) -> Dimensions { - if self.0.is_empty() { + if self.points().is_empty() { return Dimensions::Empty; } @@ -279,7 +279,7 @@ impl HasDimensions for MultiLineString { fn dimensions(&self) -> Dimensions { let mut max = Dimensions::Empty; - for line in &self.0 { + for line in self { match line.dimensions() { Dimensions::Empty => {} Dimensions::ZeroDimensional => max = Dimensions::ZeroDimensional, @@ -313,7 +313,7 @@ impl HasDimensions for MultiPolygon { } fn dimensions(&self) -> Dimensions { - if self.0.is_empty() { + if self.polygons().is_empty() { return Dimensions::Empty; } @@ -321,7 +321,7 @@ impl HasDimensions for MultiPolygon { } fn boundary_dimensions(&self) -> Dimensions { - if self.0.is_empty() { + if self.polygons().is_empty() { return Dimensions::Empty; } @@ -331,7 +331,7 @@ impl HasDimensions for MultiPolygon { impl HasDimensions for GeometryCollection { fn is_empty(&self) -> bool { - if self.0.is_empty() { + if self.geometries().is_empty() { true } else { self.iter().all(Geometry::is_empty) @@ -375,7 +375,7 @@ impl HasDimensions for Rect { if self.min() == self.max() { // degenerate rectangle is a point Dimensions::ZeroDimensional - } else if self.min().x == self.max().x || self.min().y == self.max().y { + } else if self.min().x() == self.max().x() || self.min().y() == self.max().y() { // degenerate rectangle is a line Dimensions::OneDimensional } else { @@ -402,8 +402,8 @@ impl HasDimensions for Triangle { fn dimensions(&self) -> Dimensions { use crate::algorithm::kernels::Kernel; - if Collinear == C::Ker::orient2d(self.0, self.1, self.2) { - if self.0 == self.1 && self.1 == self.2 { + if Collinear == C::Ker::orient2d(self.vertex_0(), self.vertex_1(), self.vertex_2()) { + if self.vertex_0() == self.vertex_1() && self.vertex_1() == self.vertex_2() { // degenerate triangle is a point Dimensions::ZeroDimensional } else { diff --git a/geo/src/algorithm/euclidean_distance.rs b/geo/src/algorithm/euclidean_distance.rs index df5a13281f..bfb83163ee 100644 --- a/geo/src/algorithm/euclidean_distance.rs +++ b/geo/src/algorithm/euclidean_distance.rs @@ -129,7 +129,7 @@ where { /// Minimum distance between two Points fn euclidean_distance(&self, p: &Point) -> T { - self.0.euclidean_distance(&p.0) + self.coord().euclidean_distance(&p.coord()) } } @@ -140,7 +140,6 @@ where /// Minimum distance from a Point to a MultiPoint fn euclidean_distance(&self, points: &MultiPoint) -> T { points - .0 .iter() .map(|p| self.euclidean_distance(p)) .fold(T::max_value(), |accum, val| accum.min(val)) @@ -153,7 +152,7 @@ where { /// Minimum distance from a Line to a Point fn euclidean_distance(&self, line: &Line) -> T { - self.0.euclidean_distance(line) + self.coord().euclidean_distance(line) } } @@ -173,8 +172,7 @@ where { /// Minimum distance from a Point to a MultiLineString fn euclidean_distance(&self, mls: &MultiLineString) -> T { - mls.0 - .iter() + mls.iter() .map(|ls| self.euclidean_distance(ls)) .fold(T::max_value(), |accum, val| accum.min(val)) } @@ -187,7 +185,7 @@ where /// Minimum distance from a Point to a Polygon fn euclidean_distance(&self, polygon: &Polygon) -> T { // No need to continue if the polygon contains the point, or is zero-length - if polygon.contains(self) || polygon.exterior().0.is_empty() { + if polygon.contains(self) || polygon.exterior().inner().is_empty() { return T::zero(); } // fold the minimum interior ring distance if any, followed by the exterior @@ -203,7 +201,9 @@ where .lines() .map(|line| { ::geo_types::private_utils::line_segment_distance( - self.0, line.start, line.end, + self.coord(), + line.start(), + line.end(), ) }) .fold(T::max_value(), |accum, val| accum.min(val)), @@ -218,7 +218,6 @@ where /// Minimum distance from a Point to a MultiPolygon fn euclidean_distance(&self, mpolygon: &MultiPolygon) -> T { mpolygon - .0 .iter() .map(|p| self.euclidean_distance(p)) .fold(T::max_value(), |accum, val| accum.min(val)) @@ -259,7 +258,7 @@ where { /// Minimum distance from a Line to a Point fn euclidean_distance(&self, point: &Point) -> T { - self.euclidean_distance(&point.0) + self.euclidean_distance(&point.coord()) } } @@ -332,7 +331,6 @@ where { fn euclidean_distance(&self, mpolygon: &MultiPolygon) -> T { mpolygon - .0 .iter() .map(|p| self.euclidean_distance(p)) .fold(Bounded::max_value(), |accum, val| accum.min(val)) @@ -387,8 +385,7 @@ where fn euclidean_distance(&self, other: &Polygon) -> T { if self.intersects(other) || other.contains(self) { T::zero() - } else if !other.interiors().is_empty() - && ring_contains_point(other, Point::from(self.0[0])) + } else if !other.interiors().is_empty() && ring_contains_point(other, Point::from(self[0])) { // check each ring distance, returning the minimum let mut mindist: T = Float::max_value(); @@ -464,7 +461,7 @@ where } // Containment check if !self.interiors().is_empty() - && ring_contains_point(self, Point::from(poly2.exterior().0[0])) + && ring_contains_point(self, Point::from(poly2.exterior()[0])) { // check each ring distance, returning the minimum let mut mindist: T = Float::max_value(); @@ -473,7 +470,7 @@ where } return mindist; } else if !poly2.interiors().is_empty() - && ring_contains_point(poly2, Point::from(self.exterior().0[0])) + && ring_contains_point(poly2, Point::from(self.exterior()[0])) { let mut mindist: T = Float::max_value(); for ring in poly2.interiors() { @@ -528,10 +525,16 @@ where return T::zero(); } - [(self.0, self.1), (self.1, self.2), (self.2, self.0)] - .iter() - .map(|edge| ::geo_types::private_utils::line_segment_distance(point.0, edge.0, edge.1)) - .fold(T::max_value(), |accum, val| accum.min(val)) + [ + (self.vertex_0(), self.vertex_1()), + (self.vertex_1(), self.vertex_2()), + (self.vertex_2(), self.vertex_0()), + ] + .iter() + .map(|edge| { + ::geo_types::private_utils::line_segment_distance(point.coord(), edge.0, edge.1) + }) + .fold(T::max_value(), |accum, val| accum.min(val)) } } @@ -547,7 +550,7 @@ fn ring_contains_point(poly: &Polygon, p: Point) -> bool where T: GeoNum, { - match coord_pos_relative_to_ring(p.0, poly.exterior()) { + match coord_pos_relative_to_ring(p.coord(), poly.exterior()) { CoordPos::Inside => true, CoordPos::OnBoundary | CoordPos::Outside => false, } @@ -760,7 +763,7 @@ mod test { let mp = MultiPolygon::new(vec![pol1.clone(), pol2, pol3]); let pnt1 = Point::new(0.0, 15.0); let pnt2 = Point::new(10.0, 20.0); - let ln = Line::new(pnt1.0, pnt2.0); + let ln = Line::new(pnt1.coord(), pnt2.coord()); let dist_mp_ln = ln.euclidean_distance(&mp); let dist_pol1_ln = ln.euclidean_distance(&pol1); assert_relative_eq!(dist_mp_ln, dist_pol1_ln); diff --git a/geo/src/algorithm/euclidean_length.rs b/geo/src/algorithm/euclidean_length.rs index 83d1b1406a..4dc5aa4338 100644 --- a/geo/src/algorithm/euclidean_length.rs +++ b/geo/src/algorithm/euclidean_length.rs @@ -49,8 +49,7 @@ where T: CoordFloat + Sum, { fn euclidean_length(&self) -> T { - self.0 - .iter() + self.iter() .fold(T::zero(), |total, line| total + line.euclidean_length()) } } diff --git a/geo/src/algorithm/extremes.rs b/geo/src/algorithm/extremes.rs index 867073ce55..e5c0beafa2 100644 --- a/geo/src/algorithm/extremes.rs +++ b/geo/src/algorithm/extremes.rs @@ -21,8 +21,8 @@ use crate::{CoordNum, Coordinate}; /// let extremes = polygon.extremes().unwrap(); /// /// assert_eq!(extremes.y_max.index, 2); -/// assert_eq!(extremes.y_max.coord.x, 1.); -/// assert_eq!(extremes.y_max.coord.y, 2.); +/// assert_eq!(extremes.y_max.coord.x(), 1.); +/// assert_eq!(extremes.y_max.coord.y(), 2.); /// ``` pub trait Extremes<'a, T: CoordNum> { fn extremes(&'a self) -> Option>; @@ -58,19 +58,19 @@ where })?; for (index, coord) in iter { - if coord.x < outcome.x_min.coord.x { + if coord.x() < outcome.x_min.coord.x() { outcome.x_min = Extreme { coord, index }; } - if coord.y < outcome.y_min.coord.y { + if coord.y() < outcome.y_min.coord.y() { outcome.y_min = Extreme { coord, index }; } - if coord.x > outcome.x_max.coord.x { + if coord.x() > outcome.x_max.coord.x() { outcome.x_max = Extreme { coord, index }; } - if coord.y > outcome.y_max.coord.y { + if coord.y() > outcome.y_max.coord.y() { outcome.y_max = Extreme { coord, index }; } } diff --git a/geo/src/algorithm/geodesic_length.rs b/geo/src/algorithm/geodesic_length.rs index f1a2da97d0..4602caa7cf 100644 --- a/geo/src/algorithm/geodesic_length.rs +++ b/geo/src/algorithm/geodesic_length.rs @@ -66,7 +66,7 @@ impl GeodesicLength for LineString { impl GeodesicLength for MultiLineString { fn geodesic_length(&self) -> f64 { let mut length = 0.0; - for line_string in &self.0 { + for line_string in self { length += line_string.geodesic_length(); } length diff --git a/geo/src/algorithm/haversine_length.rs b/geo/src/algorithm/haversine_length.rs index 3b0ee385ba..029e45280c 100644 --- a/geo/src/algorithm/haversine_length.rs +++ b/geo/src/algorithm/haversine_length.rs @@ -67,8 +67,7 @@ where T: CoordFloat + FromPrimitive, { fn haversine_length(&self) -> T { - self.0 - .iter() + self.iter() .fold(T::zero(), |total, line| total + line.haversine_length()) } } diff --git a/geo/src/algorithm/intersects/coordinate.rs b/geo/src/algorithm/intersects/coordinate.rs index d80075f6ae..bc34ce80c2 100644 --- a/geo/src/algorithm/intersects/coordinate.rs +++ b/geo/src/algorithm/intersects/coordinate.rs @@ -16,6 +16,6 @@ where T: CoordNum, { fn intersects(&self, rhs: &Point) -> bool { - self == &rhs.0 + self == &rhs.coord() } } diff --git a/geo/src/algorithm/intersects/line.rs b/geo/src/algorithm/intersects/line.rs index c8b765065b..cc032b867e 100644 --- a/geo/src/algorithm/intersects/line.rs +++ b/geo/src/algorithm/intersects/line.rs @@ -8,10 +8,10 @@ where { fn intersects(&self, rhs: &Coordinate) -> bool { // First we check if the point is collinear with the line. - T::Ker::orient2d(self.start, self.end, *rhs) == Orientation::Collinear + T::Ker::orient2d(self.start(), self.end(), *rhs) == Orientation::Collinear // In addition, the point must have _both_ coordinates // within the start and end bounds. - && point_in_rect(*rhs, self.start, self.end) + && point_in_rect(*rhs, self.start(), self.end()) } } symmetric_intersects_impl!(Coordinate, Line); @@ -23,16 +23,16 @@ where { fn intersects(&self, line: &Line) -> bool { // Special case: self is equiv. to a point. - if self.start == self.end { - return line.intersects(&self.start); + if self.start() == self.end() { + return line.intersects(&self.start()); } // Precondition: start and end are distinct. // Check if orientation of rhs.{start,end} are different // with respect to self.{start,end}. - let check_1_1 = T::Ker::orient2d(self.start, self.end, line.start); - let check_1_2 = T::Ker::orient2d(self.start, self.end, line.end); + let check_1_1 = T::Ker::orient2d(self.start(), self.end(), line.start()); + let check_1_2 = T::Ker::orient2d(self.start(), self.end(), line.end()); if check_1_1 != check_1_2 { // Since the checks are different, @@ -45,8 +45,8 @@ where // exterior of rhs. Now, check the same with // self, rhs swapped. - let check_2_1 = T::Ker::orient2d(line.start, line.end, self.start); - let check_2_2 = T::Ker::orient2d(line.start, line.end, self.end); + let check_2_1 = T::Ker::orient2d(line.start(), line.end(), self.start()); + let check_2_2 = T::Ker::orient2d(line.start(), line.end(), self.end()); // By similar argument, there is (exactly) one // point on self, collinear with rhs. Thus, @@ -59,10 +59,10 @@ where // Equivalent to 4 point-line intersection // checks, but removes the calls to the kernel // predicates. - point_in_rect(line.start, self.start, self.end) - || point_in_rect(line.end, self.start, self.end) - || point_in_rect(self.end, line.start, line.end) - || point_in_rect(self.end, line.start, line.end) + point_in_rect(line.start(), self.start(), self.end()) + || point_in_rect(line.end(), self.start(), self.end()) + || point_in_rect(self.end(), line.start(), line.end()) + || point_in_rect(self.end(), line.start(), line.end()) } else { false } diff --git a/geo/src/algorithm/intersects/mod.rs b/geo/src/algorithm/intersects/mod.rs index d1b64767fd..fa4bf2b872 100644 --- a/geo/src/algorithm/intersects/mod.rs +++ b/geo/src/algorithm/intersects/mod.rs @@ -103,8 +103,8 @@ fn point_in_rect(value: Coordinate, bound_1: Coordinate, bound_2: Coord where T: CoordNum, { - value_in_between(value.x, bound_1.x, bound_2.x) - && value_in_between(value.y, bound_1.y, bound_2.y) + value_in_between(value.x(), bound_1.x(), bound_2.x()) + && value_in_between(value.y(), bound_1.y(), bound_2.y()) } #[cfg(test)] diff --git a/geo/src/algorithm/intersects/point.rs b/geo/src/algorithm/intersects/point.rs index d5947f82d4..257f4619bf 100644 --- a/geo/src/algorithm/intersects/point.rs +++ b/geo/src/algorithm/intersects/point.rs @@ -8,7 +8,7 @@ where Coordinate: Intersects, { fn intersects(&self, rhs: &G) -> bool { - self.0.intersects(rhs) + self.coord().intersects(rhs) } } diff --git a/geo/src/algorithm/intersects/polygon.rs b/geo/src/algorithm/intersects/polygon.rs index 1ee7eedc9b..ba0e6af3b3 100644 --- a/geo/src/algorithm/intersects/polygon.rs +++ b/geo/src/algorithm/intersects/polygon.rs @@ -27,8 +27,8 @@ where fn intersects(&self, line: &Line) -> bool { self.exterior().intersects(line) || self.interiors().iter().any(|inner| inner.intersects(line)) - || self.intersects(&line.start) - || self.intersects(&line.end) + || self.intersects(&line.start()) + || self.intersects(&line.end()) } } symmetric_intersects_impl!(Line, Polygon); diff --git a/geo/src/algorithm/intersects/rect.rs b/geo/src/algorithm/intersects/rect.rs index 4d91821306..d1dc44ba50 100644 --- a/geo/src/algorithm/intersects/rect.rs +++ b/geo/src/algorithm/intersects/rect.rs @@ -10,7 +10,8 @@ where // self.min <= self.max. let bound_1 = self.min(); let bound_2 = self.max(); - value_in_range(rhs.x, bound_1.x, bound_2.x) && value_in_range(rhs.y, bound_1.y, bound_2.y) + value_in_range(rhs.x(), bound_1.x(), bound_2.x()) + && value_in_range(rhs.y(), bound_1.y(), bound_2.y()) } } symmetric_intersects_impl!(Coordinate, Rect); @@ -22,11 +23,11 @@ where T: CoordNum, { fn intersects(&self, other: &Rect) -> bool { - let x_overlap = value_in_range(self.min().x, other.min().x, other.max().x) - || value_in_range(other.min().x, self.min().x, self.max().x); + let x_overlap = value_in_range(self.min().x(), other.min().x(), other.max().x()) + || value_in_range(other.min().x(), self.min().x(), self.max().x()); - let y_overlap = value_in_range(self.min().y, other.min().y, other.max().y) - || value_in_range(other.min().y, self.min().y, self.max().y); + let y_overlap = value_in_range(self.min().y(), other.min().y(), other.max().y()) + || value_in_range(other.min().y(), self.min().y(), self.max().y()); x_overlap && y_overlap } @@ -41,11 +42,11 @@ where fn intersects(&self, rhs: &Line) -> bool { let lt = self.min(); let rb = self.max(); - let lb = Coordinate::from((lt.x, rb.y)); - let rt = Coordinate::from((rb.x, lt.y)); + let lb = Coordinate::from((lt.x(), rb.y())); + let rt = Coordinate::from((rb.x(), lt.y())); // If either rhs.{start,end} lies inside Rect, then true - self.intersects(&rhs.start) - || self.intersects(&rhs.end) + self.intersects(&rhs.start()) + || self.intersects(&rhs.end()) || Line::new(lt, rt).intersects(rhs) || Line::new(rt, rb).intersects(rhs) || Line::new(lb, rb).intersects(rhs) diff --git a/geo/src/algorithm/is_convex.rs b/geo/src/algorithm/is_convex.rs index 068721618c..5a04f5db50 100644 --- a/geo/src/algorithm/is_convex.rs +++ b/geo/src/algorithm/is_convex.rs @@ -114,16 +114,16 @@ impl IsConvex for LineString { allow_collinear: bool, specific_orientation: Option, ) -> Option { - if !self.is_closed() || self.0.is_empty() { + if !self.is_closed() || self.inner().is_empty() { None } else { - is_convex_shaped(&self.0[1..], allow_collinear, specific_orientation) + is_convex_shaped(&self[1..], allow_collinear, specific_orientation) } } fn is_collinear(&self) -> bool { - self.0.is_empty() - || is_convex_shaped(&self.0[1..], true, Some(Orientation::Collinear)).is_some() + self.inner().is_empty() + || is_convex_shaped(&self[1..], true, Some(Orientation::Collinear)).is_some() } } diff --git a/geo/src/algorithm/k_nearest_concave_hull.rs b/geo/src/algorithm/k_nearest_concave_hull.rs index 62cb42240c..1a7bd5aba2 100644 --- a/geo/src/algorithm/k_nearest_concave_hull.rs +++ b/geo/src/algorithm/k_nearest_concave_hull.rs @@ -44,7 +44,7 @@ where { type Scalar = T; fn k_nearest_concave_hull(&self, k: u32) -> Polygon { - concave_hull(self.iter().map(|point| &point.0), k) + concave_hull(self.iter().map(|point| point.coord()), k) } } @@ -54,7 +54,7 @@ where { type Scalar = T; fn k_nearest_concave_hull(&self, k: u32) -> Polygon { - concave_hull(self.iter().map(|point| &point.0), k) + concave_hull(self.iter().map(|point| point.coord()), k) } } @@ -64,7 +64,7 @@ where { type Scalar = T; fn k_nearest_concave_hull(&self, k: u32) -> Polygon { - concave_hull(self.iter(), k) + concave_hull(self.iter().copied(), k) } } @@ -74,7 +74,7 @@ where { type Scalar = T; fn k_nearest_concave_hull(&self, k: u32) -> Polygon { - concave_hull(self.iter(), k) + concave_hull(self.iter().copied(), k) } } @@ -84,11 +84,11 @@ where { type Scalar = T; fn k_nearest_concave_hull(&self, k: u32) -> Polygon { - concave_hull(self.iter().map(|point| &point.0), k) + concave_hull(self.iter().map(|point| point.coord()), k) } } -fn concave_hull<'a, T: 'a>(coords: impl Iterator>, k: u32) -> Polygon +fn concave_hull(coords: impl Iterator>, k: u32) -> Polygon where T: GeoFloat + RTreeNum, { @@ -99,22 +99,20 @@ where const DELTA: f32 = 0.000000001; /// Removes duplicate coords from the dataset. -fn prepare_dataset<'a, T: 'a>( - coords: impl Iterator>, -) -> rstar::RTree> +fn prepare_dataset(coords: impl Iterator>) -> rstar::RTree> where T: GeoFloat + RTreeNum, { let mut dataset: rstar::RTree> = rstar::RTree::new(); for coord in coords { - let closest = dataset.nearest_neighbor(coord); + let closest = dataset.nearest_neighbor(&coord); if let Some(closest) = closest { - if coords_are_equal(coord, closest) { + if coords_are_equal(&coord, closest) { continue; } } - dataset.insert(*coord) + dataset.insert(coord) } dataset @@ -126,7 +124,7 @@ fn coords_are_equal(c1: &Coordinate, c2: &Coordinate) -> bool where T: GeoFloat + RTreeNum, { - float_equal(c1.x, c2.x) && float_equal(c1.y, c2.y) + float_equal(c1.x(), c2.x()) && float_equal(c1.y(), c2.y()) } fn float_equal(a: T, b: T) -> bool @@ -240,8 +238,8 @@ where .expect("We checked that there are more then 3 coords in the set before."); for coord in coord_set.iter() { - if coord.y < min_y { - min_y = coord.y; + if coord.y() < min_y { + min_y = coord.y(); result = coord; } } @@ -269,14 +267,17 @@ fn sort_by_angle( ) where T: GeoFloat, { - let base_angle = pseudo_angle(prev_coord.x - curr_coord.x, prev_coord.y - curr_coord.y); + let base_angle = pseudo_angle( + prev_coord.x() - curr_coord.x(), + prev_coord.y() - curr_coord.y(), + ); coords.sort_by(|a, b| { - let mut angle_a = pseudo_angle(a.x - curr_coord.x, a.y - curr_coord.y) - base_angle; + let mut angle_a = pseudo_angle(a.x() - curr_coord.x(), a.y() - curr_coord.y()) - base_angle; if angle_a < T::zero() { angle_a = angle_a + T::from(4.0).unwrap(); } - let mut angle_b = pseudo_angle(b.x - curr_coord.x, b.y - curr_coord.y) - base_angle; + let mut angle_b = pseudo_angle(b.x() - curr_coord.x(), b.y() - curr_coord.y()) - base_angle; if angle_b < T::zero() { angle_b = angle_b + T::from(4.0).unwrap(); } @@ -388,7 +389,7 @@ mod tests { coord!(x: 3.0, y: 3.0), ]; - let poly = concave_hull(coords.iter(), 3); + let poly = concave_hull(coords.iter().copied(), 3); assert_eq!(poly.exterior().coords_count(), 12); let must_not_be_in = vec![&coords[6]]; @@ -401,7 +402,7 @@ mod tests { #[test] fn empty_hull() { - let actual: Polygon = concave_hull(vec![].iter(), 3); + let actual: Polygon = concave_hull(vec![].iter().copied(), 3); let expected = Polygon::new(LineString::new(vec![]), vec![]); assert_eq!(actual, expected); } diff --git a/geo/src/algorithm/kernels/mod.rs b/geo/src/algorithm/kernels/mod.rs index 59040cf993..cc0dcbb1ef 100644 --- a/geo/src/algorithm/kernels/mod.rs +++ b/geo/src/algorithm/kernels/mod.rs @@ -14,7 +14,7 @@ pub trait Kernel { /// Gives the orientation of 3 2-dimensional points: /// ccw, cw or collinear (None) fn orient2d(p: Coordinate, q: Coordinate, r: Coordinate) -> Orientation { - let res = (q.x - p.x) * (r.y - q.y) - (q.y - p.y) * (r.x - q.x); + let res = (q.x() - p.x()) * (r.y() - q.y()) - (q.y() - p.y()) * (r.x() - q.x()); if res > Zero::zero() { Orientation::CounterClockwise } else if res < Zero::zero() { @@ -25,7 +25,7 @@ pub trait Kernel { } fn square_euclidean_distance(p: Coordinate, q: Coordinate) -> T { - (p.x - q.x) * (p.x - q.x) + (p.y - q.y) * (p.y - q.y) + (p.x() - q.x()) * (p.x() - q.x()) + (p.y() - q.y()) * (p.y() - q.y()) } /// Compute the sign of the dot product of `u` and `v` using @@ -35,8 +35,8 @@ pub trait Kernel { fn dot_product_sign(u: Coordinate, v: Coordinate) -> Orientation { let zero = Coordinate::zero(); let vdash = coord! { - x: T::zero() - v.y, - y: v.x, + x: T::zero() - v.y(), + y: v.x(), }; Self::orient2d(zero, u, vdash) } diff --git a/geo/src/algorithm/kernels/robust.rs b/geo/src/algorithm/kernels/robust.rs index d628ee4858..55cae72b97 100644 --- a/geo/src/algorithm/kernels/robust.rs +++ b/geo/src/algorithm/kernels/robust.rs @@ -20,16 +20,16 @@ where let orientation = orient2d( Coord { - x: ::from(p.x).unwrap(), - y: ::from(p.y).unwrap(), + x: ::from(p.x()).unwrap(), + y: ::from(p.y()).unwrap(), }, Coord { - x: ::from(q.x).unwrap(), - y: ::from(q.y).unwrap(), + x: ::from(q.x()).unwrap(), + y: ::from(q.y()).unwrap(), }, Coord { - x: ::from(r.x).unwrap(), - y: ::from(r.y).unwrap(), + x: ::from(r.x()).unwrap(), + y: ::from(r.y()).unwrap(), }, ); diff --git a/geo/src/algorithm/line_interpolate_point.rs b/geo/src/algorithm/line_interpolate_point.rs index d2443046a2..7c631aa880 100644 --- a/geo/src/algorithm/line_interpolate_point.rs +++ b/geo/src/algorithm/line_interpolate_point.rs @@ -46,9 +46,9 @@ where fn line_interpolate_point(&self, fraction: T) -> Self::Output { if (fraction >= T::zero()) && (fraction <= T::one()) { // fraction between 0 and 1, return a point between start and end - let diff = self.end - self.start; - let r = self.start + diff * (fraction); - if r.x.is_finite() && r.y.is_finite() { + let diff = self.end() - self.start(); + let r = self.start() + diff * (fraction); + if r.x().is_finite() && r.y().is_finite() { Some(r.into()) } else { None diff --git a/geo/src/algorithm/line_intersection.rs b/geo/src/algorithm/line_intersection.rs index 49a7dae4e8..756498f392 100644 --- a/geo/src/algorithm/line_intersection.rs +++ b/geo/src/algorithm/line_intersection.rs @@ -69,8 +69,8 @@ where } use crate::kernels::{Kernel, Orientation::*, RobustKernel}; - let p_q1 = RobustKernel::orient2d(p.start, p.end, q.start); - let p_q2 = RobustKernel::orient2d(p.start, p.end, q.end); + let p_q1 = RobustKernel::orient2d(p.start(), p.end(), q.start()); + let p_q2 = RobustKernel::orient2d(p.start(), p.end(), q.end()); if matches!( (p_q1, p_q2), (Clockwise, Clockwise) | (CounterClockwise, CounterClockwise) @@ -78,8 +78,8 @@ where return None; } - let q_p1 = RobustKernel::orient2d(q.start, q.end, p.start); - let q_p2 = RobustKernel::orient2d(q.start, q.end, p.end); + let q_p1 = RobustKernel::orient2d(q.start(), q.end(), p.start()); + let q_p2 = RobustKernel::orient2d(q.start(), q.end(), p.end()); if matches!( (q_p1, q_p2), (Clockwise, Clockwise) | (CounterClockwise, CounterClockwise) @@ -120,20 +120,20 @@ where let intersection: Coordinate; // false positives for this overzealous clippy https://github.com/rust-lang/rust-clippy/issues/6747 #[allow(clippy::suspicious_operation_groupings)] - if p.start == q.start || p.start == q.end { - intersection = p.start; - } else if p.end == q.start || p.end == q.end { - intersection = p.end; + if p.start() == q.start() || p.start() == q.end() { + intersection = p.start(); + } else if p.end() == q.start() || p.end() == q.end() { + intersection = p.end(); // Now check to see if any endpoint lies on the interior of the other segment. } else if p_q1 == Collinear { - intersection = q.start; + intersection = q.start(); } else if p_q2 == Collinear { - intersection = q.end; + intersection = q.end(); } else if q_p1 == Collinear { - intersection = p.start; + intersection = p.start(); } else { assert_eq!(q_p2, Collinear); - intersection = p.end; + intersection = p.end(); } Some(LineIntersection::SinglePoint { intersection, @@ -164,21 +164,21 @@ fn collinear_intersection(p: Line, q: Line) -> Option collinear(q), (_, _, true, true) => collinear(p), - (true, false, true, false) if q.start == p.start => improper(q.start), - (true, _, true, _) => collinear(Line::new(q.start, p.start)), - (true, false, false, true) if q.start == p.end => improper(q.start), - (true, _, _, true) => collinear(Line::new(q.start, p.end)), - (false, true, true, false) if q.end == p.start => improper(q.end), - (_, true, true, _) => collinear(Line::new(q.end, p.start)), - (false, true, false, true) if q.end == p.end => improper(q.end), - (_, true, _, true) => collinear(Line::new(q.end, p.end)), + (true, false, true, false) if q.start() == p.start() => improper(q.start()), + (true, _, true, _) => collinear(Line::new(q.start(), p.start())), + (true, false, false, true) if q.start() == p.end() => improper(q.start()), + (true, _, _, true) => collinear(Line::new(q.start(), p.end())), + (false, true, true, false) if q.end() == p.start() => improper(q.end()), + (_, true, true, _) => collinear(Line::new(q.end(), p.start())), + (false, true, false, true) if q.end() == p.end() => improper(q.end()), + (_, true, _, true) => collinear(Line::new(q.end(), p.end())), _ => return None, }, ) @@ -197,36 +197,36 @@ fn collinear_intersection(p: Line, q: Line) -> Option(p: Line, q: Line) -> Coordinate { use geo_types::private_utils::point_line_euclidean_distance; - let mut nearest_pt = p.start; - let mut min_dist = point_line_euclidean_distance(p.start, q); + let mut nearest_pt = p.start(); + let mut min_dist = point_line_euclidean_distance(p.start(), q); - let dist = point_line_euclidean_distance(p.end, q); + let dist = point_line_euclidean_distance(p.end(), q); if dist < min_dist { min_dist = dist; - nearest_pt = p.end; + nearest_pt = p.end(); } - let dist = point_line_euclidean_distance(q.start, p); + let dist = point_line_euclidean_distance(q.start(), p); if dist < min_dist { min_dist = dist; - nearest_pt = q.start; + nearest_pt = q.start(); } - let dist = point_line_euclidean_distance(q.end, p); + let dist = point_line_euclidean_distance(q.end(), p); if dist < min_dist { - nearest_pt = q.end; + nearest_pt = q.end(); } nearest_pt } fn raw_line_intersection(p: Line, q: Line) -> Option> { - let p_min_x = p.start.x.min(p.end.x); - let p_min_y = p.start.y.min(p.end.y); - let p_max_x = p.start.x.max(p.end.x); - let p_max_y = p.start.y.max(p.end.y); + let p_min_x = p.start().x().min(p.end().x()); + let p_min_y = p.start().y().min(p.end().y()); + let p_max_x = p.start().x().max(p.end().x()); + let p_max_y = p.start().y().max(p.end().y()); - let q_min_x = q.start.x.min(q.end.x); - let q_min_y = q.start.y.min(q.end.y); - let q_max_x = q.start.x.max(q.end.x); - let q_max_y = q.start.y.max(q.end.y); + let q_min_x = q.start().x().min(q.end().x()); + let q_min_y = q.start().y().min(q.end().y()); + let q_max_x = q.start().x().max(q.end().x()); + let q_max_y = q.start().y().max(q.end().y()); let int_min_x = p_min_x.max(q_min_x); let int_max_x = p_max_x.min(q_max_x); @@ -238,14 +238,14 @@ fn raw_line_intersection(p: Line, q: Line) -> Option = *p - self.start_point(); // direction vector of line, $v$ - let v: Point<_> = (self.end - self.start).into(); + let v: Point<_> = (self.end() - self.start()).into(); // $v \cdot v$ let v_sq = v.dot(v); diff --git a/geo/src/algorithm/lines_iter.rs b/geo/src/algorithm/lines_iter.rs index 1d5df89ba4..574af89367 100644 --- a/geo/src/algorithm/lines_iter.rs +++ b/geo/src/algorithm/lines_iter.rs @@ -69,7 +69,7 @@ pub struct LineStringIter<'a, T: CoordNum>(slice::Windows<'a, Coordinate>); impl<'a, T: CoordNum> LineStringIter<'a, T> { fn new(line_string: &'a LineString) -> Self { - Self(line_string.0.windows(2)) + Self(line_string.inner().windows(2)) } } @@ -96,7 +96,7 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for MultiLineString { type Iter = MultiLineStringIter<'a, Self::Scalar>; fn lines_iter(&'a self) -> Self::Iter { - MapLinesIter(self.0.iter()).flatten() + MapLinesIter(self.line_strings().iter()).flatten() } } @@ -124,7 +124,7 @@ impl<'a, T: CoordNum + 'a> LinesIter<'a> for MultiPolygon { type Iter = MultiPolygonIter<'a, Self::Scalar>; fn lines_iter(&'a self) -> Self::Iter { - MapLinesIter(self.0.iter()).flatten() + MapLinesIter(self.polygons().iter()).flatten() } } diff --git a/geo/src/algorithm/map_coords.rs b/geo/src/algorithm/map_coords.rs index 264e454f7d..d4648f38e1 100644 --- a/geo/src/algorithm/map_coords.rs +++ b/geo/src/algorithm/map_coords.rs @@ -179,7 +179,7 @@ mod modern { type Output = Point; fn map_coords(&self, func: impl Fn((T, T)) -> (NT, NT) + Copy) -> Self::Output { - let new_point = func((self.0.x, self.0.y)); + let new_point = func((self.x(), self.y())); Point::new(new_point.0, new_point.1) } @@ -187,25 +187,25 @@ mod modern { &self, func: impl Fn((T, T)) -> Result<(NT, NT), E>, ) -> Result { - let new_point = func((self.0.x, self.0.y))?; + let new_point = func((self.x(), self.y()))?; Ok(Point::new(new_point.0, new_point.1)) } } impl MapCoordsInPlace for Point { fn map_coords_in_place(&mut self, func: impl Fn((T, T)) -> (T, T)) { - let new_point = func((self.0.x, self.0.y)); - self.0.x = new_point.0; - self.0.y = new_point.1; + let new_point = func((self.x(), self.y())); + *self.x_mut() = new_point.0; + *self.y_mut() = new_point.1; } fn try_map_coords_in_place( &mut self, func: impl Fn((T, T)) -> Result<(T, T), E>, ) -> Result<(), E> { - let new_point = func((self.0.x, self.0.y))?; - self.0.x = new_point.0; - self.0.y = new_point.1; + let new_point = func((self.x(), self.y()))?; + *self.x_mut() = new_point.0; + *self.y_mut() = new_point.1; Ok(()) } @@ -220,8 +220,8 @@ mod modern { fn map_coords(&self, func: impl Fn((T, T)) -> (NT, NT) + Copy) -> Self::Output { Line::new( - self.start_point().map_coords(func).0, - self.end_point().map_coords(func).0, + self.start_point().map_coords(func).coord(), + self.end_point().map_coords(func).coord(), ) } @@ -230,34 +230,34 @@ mod modern { func: impl Fn((T, T)) -> Result<(NT, NT), E> + Copy, ) -> Result { Ok(Line::new( - self.start_point().try_map_coords(func)?.0, - self.end_point().try_map_coords(func)?.0, + self.start_point().try_map_coords(func)?.coord(), + self.end_point().try_map_coords(func)?.coord(), )) } } impl MapCoordsInPlace for Line { fn map_coords_in_place(&mut self, func: impl Fn((T, T)) -> (T, T)) { - let new_start = func((self.start.x, self.start.y)); - self.start.x = new_start.0; - self.start.y = new_start.1; + let new_start = func((self.start().x(), self.start().y())); + *self.start().x_mut() = new_start.0; + *self.start().y_mut() = new_start.1; - let new_end = func((self.end.x, self.end.y)); - self.end.x = new_end.0; - self.end.y = new_end.1; + let new_end = func((self.end().x(), self.end().y())); + *self.end().x_mut() = new_end.0; + *self.end().y_mut() = new_end.1; } fn try_map_coords_in_place( &mut self, func: impl Fn((T, T)) -> Result<(T, T), E>, ) -> Result<(), E> { - let new_start = func((self.start.x, self.start.y))?; - self.start.x = new_start.0; - self.start.y = new_start.1; + let new_start = func((self.start().x(), self.start().y()))?; + *self.start().x_mut() = new_start.0; + *self.start().y_mut() = new_start.1; - let new_end = func((self.end.x, self.end.y))?; - self.end.x = new_end.0; - self.end.y = new_end.1; + let new_end = func((self.end().x(), self.end().y()))?; + *self.end().x_mut() = new_end.0; + *self.end().y_mut() = new_end.1; Ok(()) } @@ -292,10 +292,10 @@ mod modern { impl MapCoordsInPlace for LineString { fn map_coords_in_place(&mut self, func: impl Fn((T, T)) -> (T, T)) { - for p in &mut self.0 { - let new_coords = func((p.x, p.y)); - p.x = new_coords.0; - p.y = new_coords.1; + for p in &mut self.coords_mut() { + let new_coords = func((p.x(), p.y())); + *p.x_mut() = new_coords.0; + *p.y_mut() = new_coords.1; } } @@ -303,10 +303,10 @@ mod modern { &mut self, func: impl Fn((T, T)) -> Result<(T, T), E>, ) -> Result<(), E> { - for p in &mut self.0 { - let new_coords = func((p.x, p.y))?; - p.x = new_coords.0; - p.y = new_coords.1; + for p in &mut self.coords_mut() { + let new_coords = func((p.x(), p.y()))?; + *p.x_mut() = new_coords.0; + *p.y_mut() = new_coords.1; } Ok(()) } @@ -399,8 +399,7 @@ mod modern { func: impl Fn((T, T)) -> Result<(NT, NT), E> + Copy, ) -> Result { Ok(MultiPoint::new( - self.0 - .iter() + self.iter() .map(|p| p.try_map_coords(func)) .collect::, E>>()?, )) @@ -409,7 +408,7 @@ mod modern { impl MapCoordsInPlace for MultiPoint { fn map_coords_in_place(&mut self, func: impl Fn((T, T)) -> (T, T) + Copy) { - for p in &mut self.0 { + for p in self { p.map_coords_in_place(func); } } @@ -418,7 +417,7 @@ mod modern { &mut self, func: impl Fn((T, T)) -> Result<(T, T), E>, ) -> Result<(), E> { - for p in &mut self.0 { + for p in self { p.try_map_coords_in_place(&func)?; } Ok(()) @@ -441,8 +440,7 @@ mod modern { func: impl Fn((T, T)) -> Result<(NT, NT), E> + Copy, ) -> Result { Ok(MultiLineString::new( - self.0 - .iter() + self.iter() .map(|l| l.try_map_coords(func)) .collect::, E>>()?, )) @@ -451,8 +449,8 @@ mod modern { impl MapCoordsInPlace for MultiLineString { fn map_coords_in_place(&mut self, func: impl Fn((T, T)) -> (T, T) + Copy) { - for p in &mut self.0 { - p.map_coords_in_place(func); + for line_string in self { + line_string.map_coords_in_place(func); } } @@ -460,8 +458,8 @@ mod modern { &mut self, func: impl Fn((T, T)) -> Result<(T, T), E>, ) -> Result<(), E> { - for p in &mut self.0 { - p.try_map_coords_in_place(&func)?; + for line_string in self { + line_string.try_map_coords_in_place(&func)?; } Ok(()) } @@ -483,8 +481,7 @@ mod modern { func: impl Fn((T, T)) -> Result<(NT, NT), E> + Copy, ) -> Result { Ok(MultiPolygon::new( - self.0 - .iter() + self.iter() .map(|p| p.try_map_coords(func)) .collect::, E>>()?, )) @@ -493,7 +490,7 @@ mod modern { impl MapCoordsInPlace for MultiPolygon { fn map_coords_in_place(&mut self, func: impl Fn((T, T)) -> (T, T) + Copy) { - for p in &mut self.0 { + for p in self { p.map_coords_in_place(func); } } @@ -502,7 +499,7 @@ mod modern { &mut self, func: impl Fn((T, T)) -> Result<(T, T), E>, ) -> Result<(), E> { - for p in &mut self.0 { + for p in self { p.try_map_coords_in_place(&func)?; } Ok(()) @@ -609,8 +606,7 @@ mod modern { func: impl Fn((T, T)) -> Result<(NT, NT), E> + Copy, ) -> Result { Ok(GeometryCollection::new_from( - self.0 - .iter() + self.iter() .map(|g| g.try_map_coords(func)) .collect::, E>>()?, )) @@ -619,7 +615,7 @@ mod modern { impl MapCoordsInPlace for GeometryCollection { fn map_coords_in_place(&mut self, func: impl Fn((T, T)) -> (T, T) + Copy) { - for p in &mut self.0 { + for p in self { p.map_coords_in_place(func); } } @@ -628,7 +624,7 @@ mod modern { &mut self, func: impl Fn((T, T)) -> Result<(T, T), E>, ) -> Result<(), E> { - for p in &mut self.0 { + for p in self { p.try_map_coords_in_place(&func)?; } Ok(()) @@ -678,9 +674,9 @@ mod modern { type Output = Triangle; fn map_coords(&self, func: impl Fn((T, T)) -> (NT, NT) + Copy) -> Self::Output { - let p1 = func(self.0.x_y()); - let p2 = func(self.1.x_y()); - let p3 = func(self.2.x_y()); + let p1 = func(self.vertex_0().x_y()); + let p2 = func(self.vertex_1().x_y()); + let p3 = func(self.vertex_2().x_y()); Triangle::new( coord! { x: p1.0, y: p1.1 }, @@ -693,9 +689,9 @@ mod modern { &self, func: impl Fn((T, T)) -> Result<(NT, NT), E>, ) -> Result { - let p1 = func(self.0.x_y())?; - let p2 = func(self.1.x_y())?; - let p3 = func(self.2.x_y())?; + let p1 = func(self.vertex_0().x_y())?; + let p2 = func(self.vertex_1().x_y())?; + let p3 = func(self.vertex_2().x_y())?; Ok(Triangle::new( coord! { x: p1.0, y: p1.1 }, @@ -707,9 +703,9 @@ mod modern { impl MapCoordsInPlace for Triangle { fn map_coords_in_place(&mut self, func: impl Fn((T, T)) -> (T, T)) { - let p1 = func(self.0.x_y()); - let p2 = func(self.1.x_y()); - let p3 = func(self.2.x_y()); + let p1 = func(self.vertex_0().x_y()); + let p2 = func(self.vertex_1().x_y()); + let p3 = func(self.vertex_2().x_y()); let mut new_triangle = Triangle::new( coord! { x: p1.0, y: p1.1 }, @@ -724,9 +720,9 @@ mod modern { &mut self, func: impl Fn((T, T)) -> Result<(T, T), E>, ) -> Result<(), E> { - let p1 = func(self.0.x_y())?; - let p2 = func(self.1.x_y())?; - let p3 = func(self.2.x_y())?; + let p1 = func(self.vertex_0().x_y())?; + let p2 = func(self.vertex_1().x_y())?; + let p3 = func(self.vertex_2().x_y())?; let mut new_triangle = Triangle::new( coord! { x: p1.0, y: p1.1 }, @@ -1042,8 +1038,8 @@ mod test { fn linestring() { let line1: LineString = LineString::from(vec![(0., 0.), (1., 2.)]); let line2 = line1.map_coords(|(x, y)| (x + 10., y - 100.)); - assert_relative_eq!(line2.0[0], Coordinate::from((10., -100.)), epsilon = 1e-6); - assert_relative_eq!(line2.0[1], Coordinate::from((11., -98.)), epsilon = 1e-6); + assert_relative_eq!(line2[0], Coordinate::from((10., -100.)), epsilon = 1e-6); + assert_relative_eq!(line2[1], Coordinate::from((11., -98.)), epsilon = 1e-6); } #[test] @@ -1130,9 +1126,9 @@ mod test { let mp = MultiPolygon::new(vec![poly1, poly2]); let mp2 = mp.map_coords(|(x, y)| (x * 2., y + 100.)); - assert_eq!(mp2.0.len(), 2); + assert_eq!(mp2.polygons().len(), 2); assert_relative_eq!( - mp2.0[0], + mp2.polygons()[0], polygon![ (x: 0., y: 100.), (x: 20., y: 100.), @@ -1142,7 +1138,7 @@ mod test { ], ); assert_relative_eq!( - mp2.0[1], + mp2.polygons()[1], polygon![ exterior: [ (x: 22., y: 111.), diff --git a/geo/src/algorithm/orient.rs b/geo/src/algorithm/orient.rs index 4914041b80..1f24ddf930 100644 --- a/geo/src/algorithm/orient.rs +++ b/geo/src/algorithm/orient.rs @@ -142,7 +142,7 @@ mod test { let oriented_int_ls = LineString::from(oriented_int_raw); // build corrected Polygon let oriented = orient(&poly1, Direction::Default); - assert_eq!(oriented.exterior().0, oriented_ext_ls.0); - assert_eq!(oriented.interiors()[0].0, oriented_int_ls.0); + assert_eq!(oriented.exterior(), &oriented_ext_ls); + assert_eq!(oriented.interiors()[0], oriented_int_ls); } } diff --git a/geo/src/algorithm/polygon_distance_fast_path.rs b/geo/src/algorithm/polygon_distance_fast_path.rs index 15734e4a0c..4201fcdbe9 100644 --- a/geo/src/algorithm/polygon_distance_fast_path.rs +++ b/geo/src/algorithm/polygon_distance_fast_path.rs @@ -16,8 +16,8 @@ where { let poly1_extremes = poly1.extremes().unwrap(); let poly2_extremes = poly2.extremes().unwrap(); - let ymin1 = Point::from(poly1.exterior().0[poly1_extremes.y_min.index]); - let ymax2 = Point::from(poly2.exterior().0[poly2_extremes.y_max.index]); + let ymin1 = Point::from(poly1.exterior()[poly1_extremes.y_min.index]); + let ymax2 = Point::from(poly2.exterior()[poly2_extremes.y_max.index]); let mut state = Polydist { poly1, @@ -45,7 +45,7 @@ where // minimum distance can be calculated in at most this many iterations // we only need to spin the calipers equal to the total number of vertices in both polygons // alternatively, we could accumulate the total rotation angle and stop when it exceeds 2pi - max_iterations: poly1.exterior().0.len() + poly2.exterior().0.len(), + max_iterations: poly1.exterior().inner().len() + poly2.exterior().inner().len(), }; let mut iterations = 0usize; while iterations <= state.max_iterations { @@ -61,7 +61,7 @@ fn vertex_line_distance(v: Point, p: Point, q: Point) -> T where T: GeoFloat, { - v.euclidean_distance(&Line::new(p.0, q.0)) + v.euclidean_distance(&Line::new(p.coord(), q.coord())) } /// Wrap-around previous Polygon index @@ -69,7 +69,7 @@ fn prev_vertex(poly: &Polygon, current_vertex: usize) -> usize where T: GeoFloat, { - (current_vertex + (poly.exterior().0.len() - 1) - 1) % (poly.exterior().0.len() - 1) + (current_vertex + (poly.exterior().inner().len() - 1) - 1) % (poly.exterior().inner().len() - 1) } /// Wrap-around next Polygon index @@ -77,7 +77,7 @@ fn next_vertex(poly: &Polygon, current_vertex: usize) -> usize where T: GeoFloat, { - (current_vertex + 1) % (poly.exterior().0.len() - 1) + (current_vertex + 1) % (poly.exterior().inner().len() - 1) } #[derive(Debug)] @@ -127,20 +127,21 @@ where let sinsq = T::one() - cossq; let mut cos = T::zero(); let mut sin; - let pnext = poly.exterior().0[next_vertex(poly, idx)]; - let pprev = poly.exterior().0[prev_vertex(poly, idx)]; - let clockwise = Point::from(pprev).cross_prod(Point::from(p.0), Point::from(pnext)) < T::zero(); + let pnext = poly.exterior()[next_vertex(poly, idx)]; + let pprev = poly.exterior()[prev_vertex(poly, idx)]; + let clockwise = + Point::from(pprev).cross_prod(Point::from(p.coord()), Point::from(pnext)) < T::zero(); let slope_prev; let slope_next; // Slope isn't 0, things are complicated if *slope != T::zero() { cos = cossq.sqrt(); sin = sinsq.sqrt(); - if pnext.x > p.x() { - if pprev.x > p.x() { - if pprev.y >= p.y() && pnext.y >= p.y() { + if pnext.x() > p.x() { + if pprev.x() > p.x() { + if pprev.y() >= p.y() && pnext.y() >= p.y() { if *slope > T::zero() { - slope_prev = Line::new(p.0, pprev).slope(); + slope_prev = Line::new(p.coord(), pprev).slope(); if clockwise && *slope <= slope_prev || !clockwise && *slope >= slope_prev { cos = -cos; sin = -sin; @@ -150,15 +151,15 @@ where sin = -sin; } } - } else if pprev.y <= p.y() && pnext.y <= p.y() { + } else if pprev.y() <= p.y() && pnext.y() <= p.y() { if *slope > T::zero() { if !clockwise { cos = -cos; sin = -sin; } } else { - slope_prev = Line::new(p.0, pprev).slope(); - slope_next = Line::new(p.0, pnext).slope(); + slope_prev = Line::new(p.coord(), pprev).slope(); + slope_next = Line::new(p.coord(), pnext).slope(); if clockwise { if *slope <= slope_prev { cos = -cos; @@ -184,17 +185,17 @@ where } else if *slope < T::zero() { sin = -sin; } - } else if pnext.x < p.x() { - if pprev.x < p.x() { - if pprev.y >= p.y() && pnext.y >= p.y() { + } else if pnext.x() < p.x() { + if pprev.x() < p.x() { + if pprev.y() >= p.y() && pnext.y() >= p.y() { if *slope > T::zero() { if clockwise { cos = -cos; sin = -sin; } } else { - slope_prev = Line::new(p.0, pprev).slope(); - slope_next = Line::new(p.0, pnext).slope(); + slope_prev = Line::new(p.coord(), pprev).slope(); + slope_next = Line::new(p.coord(), pnext).slope(); if clockwise { if *slope <= slope_prev { sin = -sin; @@ -207,9 +208,9 @@ where sin = -sin; } } - } else if pprev.y <= p.y() && pnext.y <= p.y() { + } else if pprev.y() <= p.y() && pnext.y() <= p.y() { if *slope > T::zero() { - slope_next = Line::new(p.0, pnext).slope(); + slope_next = Line::new(p.coord(), pnext).slope(); if *slope >= slope_next { cos = -cos; sin = -sin; @@ -236,7 +237,7 @@ where sin = -sin; } } - } else if pprev.x > p.x() { + } else if pprev.x() > p.x() { cos = -cos; if *slope > T::zero() { sin = -sin; @@ -247,12 +248,12 @@ where } else { // Slope is 0, things are fairly simple sin = T::zero(); - if pnext.x > p.x() { + if pnext.x() > p.x() { cos = T::one(); - } else if pnext.x < p.x() { + } else if pnext.x() < p.x() { cos = -T::one(); - } else if pnext.x == p.x() { - if pprev.x < p.x() { + } else if pnext.x() == p.x() { + if pprev.x() < p.x() { cos = T::one(); } else { cos = -T::one(); @@ -321,17 +322,18 @@ where T: GeoFloat + FloatConst + Signed, { let hundred = T::from(100).unwrap(); - let pnext = poly.exterior().0[next_vertex(poly, idx)]; - let pprev = poly.exterior().0[prev_vertex(poly, idx)]; - let clockwise = Point::from(pprev).cross_prod(Point::from(p.0), Point::from(pnext)) < T::zero(); + let pnext = poly.exterior()[next_vertex(poly, idx)]; + let pprev = poly.exterior()[prev_vertex(poly, idx)]; + let clockwise = + Point::from(pprev).cross_prod(Point::from(p.coord()), Point::from(pnext)) < T::zero(); let punit; if !vertical { punit = unitvector(m, poly, p, idx); } else if clockwise { - if p.x() > pprev.x { + if p.x() > pprev.x() { punit = Point::new(p.x(), p.y() - hundred); - } else if p.x() == pprev.x { - if p.y() > pprev.y { + } else if p.x() == pprev.x() { + if p.y() > pprev.y() { punit = Point::new(p.x(), p.y() + hundred); } else { // implies p.y() < pprev.y() @@ -344,10 +346,10 @@ where // implies p.x() < pprev.x() punit = Point::new(p.x(), p.y() + hundred); } - } else if p.x() > pprev.x { + } else if p.x() > pprev.x() { punit = Point::new(p.x(), p.y() + hundred); - } else if p.x() == pprev.x { - if p.y() > pprev.y { + } else if p.x() == pprev.x() { + if p.y() > pprev.y() { punit = Point::new(p.x(), p.y() + hundred); } else { // implies p.y() < pprev.y() @@ -453,14 +455,14 @@ where if (state.ap1 - minangle).abs() < T::from(0.002).unwrap() { state.ip1 = true; let p1next = next_vertex(state.poly1, state.p1_idx); - state.p1next = Point::from(state.poly1.exterior().0[p1next]); + state.p1next = Point::from(state.poly1.exterior()[p1next]); state.p1_idx = p1next; state.alignment = Some(AlignedEdge::VertexP); } if (state.aq2 - minangle).abs() < T::from(0.002).unwrap() { state.iq2 = true; let q2next = next_vertex(state.poly2, state.q2_idx); - state.q2next = Point::from(state.poly2.exterior().0[q2next]); + state.q2next = Point::from(state.poly2.exterior()[q2next]); state.q2_idx = q2next; state.alignment = match state.alignment { None => Some(AlignedEdge::VertexQ), diff --git a/geo/src/algorithm/relate/geomgraph/edge.rs b/geo/src/algorithm/relate/geomgraph/edge.rs index 9932f8d266..a6b21dbdef 100644 --- a/geo/src/algorithm/relate/geomgraph/edge.rs +++ b/geo/src/algorithm/relate/geomgraph/edge.rs @@ -97,8 +97,8 @@ impl Edge { self.add_intersection(intersection, line, segment_index); } LineIntersection::Collinear { intersection } => { - self.add_intersection(intersection.start, line, segment_index); - self.add_intersection(intersection.end, line, segment_index); + self.add_intersection(intersection.start(), line, segment_index); + self.add_intersection(intersection.end(), line, segment_index); } } } diff --git a/geo/src/algorithm/relate/geomgraph/edge_end.rs b/geo/src/algorithm/relate/geomgraph/edge_end.rs index d4c35d2974..03ee10dce8 100644 --- a/geo/src/algorithm/relate/geomgraph/edge_end.rs +++ b/geo/src/algorithm/relate/geomgraph/edge_end.rs @@ -53,7 +53,7 @@ where { pub fn new(coord_0: Coordinate, coord_1: Coordinate, label: Label) -> EdgeEnd { let delta = coord_1 - coord_0; - let quadrant = Quadrant::new(delta.x, delta.y); + let quadrant = Quadrant::new(delta.x(), delta.y()); EdgeEnd { label, key: EdgeEndKey { diff --git a/geo/src/algorithm/relate/geomgraph/geometry_graph.rs b/geo/src/algorithm/relate/geomgraph/geometry_graph.rs index a699c06ea2..edd110f834 100644 --- a/geo/src/algorithm/relate/geomgraph/geometry_graph.rs +++ b/geo/src/algorithm/relate/geomgraph/geometry_graph.rs @@ -124,7 +124,7 @@ where } GeometryCow::LineString(line_string) => self.add_line_string(line_string), GeometryCow::MultiPoint(multi_point) => { - for point in &multi_point.0 { + for point in multi_point.points() { self.add_point(point); } } @@ -132,12 +132,12 @@ where // check if this Geometry should obey the Boundary Determination Rule // all collections except MultiPolygons obey the rule self.use_boundary_determination_rule = false; - for polygon in &multi_polygon.0 { + for polygon in multi_polygon.polygons() { self.add_polygon(polygon); } } GeometryCow::MultiLineString(multi_line_string) => { - for line_string in &multi_line_string.0 { + for line_string in multi_line_string.line_strings() { self.add_line_string(line_string); } } @@ -160,9 +160,9 @@ where return; } - let mut coords: Vec> = Vec::with_capacity(linear_ring.0.len()); + let mut coords: Vec> = Vec::with_capacity(linear_ring.inner().len()); // remove repeated coords - for coord in &linear_ring.0 { + for coord in linear_ring.coords() { if coords.last() != Some(coord) { coords.push(*coord) } @@ -214,8 +214,8 @@ where return; } - let mut coords: Vec> = Vec::with_capacity(line_string.0.len()); - for coord in &line_string.0 { + let mut coords: Vec> = Vec::with_capacity(line_string.inner().len()); + for coord in line_string.coords() { if coords.last() != Some(coord) { coords.push(*coord) } @@ -241,11 +241,11 @@ where } fn add_line(&mut self, line: &Line) { - self.insert_boundary_point(line.start); - self.insert_boundary_point(line.end); + self.insert_boundary_point(line.start()); + self.insert_boundary_point(line.end()); let edge = Edge::new( - vec![line.start, line.end], + vec![line.start(), line.end()], Label::new( self.arg_index, TopologyPosition::line_or_point(CoordPos::Inside), diff --git a/geo/src/algorithm/relate/geomgraph/node_map.rs b/geo/src/algorithm/relate/geomgraph/node_map.rs index 885c64cfc2..b23bd4d189 100644 --- a/geo/src/algorithm/relate/geomgraph/node_map.rs +++ b/geo/src/algorithm/relate/geomgraph/node_map.rs @@ -38,10 +38,10 @@ struct NodeKey(Coordinate); impl std::cmp::Ord for NodeKey { fn cmp(&self, other: &NodeKey) -> std::cmp::Ordering { - debug_assert!(!self.0.x.is_nan()); - debug_assert!(!self.0.y.is_nan()); - debug_assert!(!other.0.x.is_nan()); - debug_assert!(!other.0.y.is_nan()); + debug_assert!(!self.0.x().is_nan()); + debug_assert!(!self.0.y().is_nan()); + debug_assert!(!other.0.x().is_nan()); + debug_assert!(!other.0.y().is_nan()); crate::utils::lex_cmp(&self.0, &other.0) } } @@ -54,10 +54,10 @@ impl std::cmp::PartialOrd for NodeKey { impl std::cmp::PartialEq for NodeKey { fn eq(&self, other: &NodeKey) -> bool { - debug_assert!(!self.0.x.is_nan()); - debug_assert!(!self.0.y.is_nan()); - debug_assert!(!other.0.x.is_nan()); - debug_assert!(!other.0.y.is_nan()); + debug_assert!(!self.0.x().is_nan()); + debug_assert!(!self.0.y().is_nan()); + debug_assert!(!other.0.x().is_nan()); + debug_assert!(!other.0.y().is_nan()); self.0 == other.0 } } @@ -80,7 +80,7 @@ where /// Note: Coordinates must be non-NaN. pub fn insert_node_with_coordinate(&mut self, coord: Coordinate) -> &mut NF::Node { debug_assert!( - !coord.x.is_nan() && !coord.y.is_nan(), + !coord.x().is_nan() && !coord.y().is_nan(), "NaN coordinates are not supported" ); let key = NodeKey(coord); diff --git a/geo/src/algorithm/relate/geomgraph/robust_line_intersector.rs b/geo/src/algorithm/relate/geomgraph/robust_line_intersector.rs index 28c1f8ddd9..edd5236303 100644 --- a/geo/src/algorithm/relate/geomgraph/robust_line_intersector.rs +++ b/geo/src/algorithm/relate/geomgraph/robust_line_intersector.rs @@ -40,33 +40,33 @@ impl RobustLineIntersector { /// result of _rounding_ points which lie on the line, /// but not safe to use for _truncated_ points. pub fn compute_edge_distance(intersection: Coordinate, line: Line) -> F { - let dx = (line.end.x - line.start.x).abs(); - let dy = (line.end.y - line.start.y).abs(); + let dx = (line.end().x() - line.start().x()).abs(); + let dy = (line.end().y() - line.start().y()).abs(); let mut dist: F; - if intersection == line.start { + if intersection == line.start() { dist = F::zero(); - } else if intersection == line.end { + } else if intersection == line.end() { if dx > dy { dist = dx; } else { dist = dy; } } else { - let intersection_dx = (intersection.x - line.start.x).abs(); - let intersection_dy = (intersection.y - line.start.y).abs(); + let intersection_dx = (intersection.x() - line.start().x()).abs(); + let intersection_dy = (intersection.y() - line.start().y()).abs(); if dx > dy { dist = intersection_dx; } else { dist = intersection_dy; } // hack to ensure that non-endpoints always have a non-zero distance - if dist == F::zero() && intersection != line.start { + if dist == F::zero() && intersection != line.start() { dist = intersection_dx.max(intersection_dy); } } debug_assert!( - !(dist == F::zero() && intersection != line.start), + !(dist == F::zero() && intersection != line.start()), "Bad distance calculation" ); dist diff --git a/geo/src/algorithm/rotate.rs b/geo/src/algorithm/rotate.rs index e03ea7bab8..30dea3e201 100644 --- a/geo/src/algorithm/rotate.rs +++ b/geo/src/algorithm/rotate.rs @@ -491,8 +491,8 @@ mod test { Coordinate::from((5.672380059021509, 1.2114794859018578)), Coordinate::from((4.706454232732441, 1.4702985310043786)), ]; - assert_eq!(rotated.exterior().0, correct_outside); - assert_eq!(rotated.interiors()[0].0, correct_inside); + assert_eq!(rotated.exterior().inner(), correct_outside); + assert_eq!(rotated.interiors()[0].inner(), correct_inside); // now rotate around center let center_expected = polygon![ diff --git a/geo/src/algorithm/simplify.rs b/geo/src/algorithm/simplify.rs index d04d6ec40a..537d51fb75 100644 --- a/geo/src/algorithm/simplify.rs +++ b/geo/src/algorithm/simplify.rs @@ -197,8 +197,7 @@ where fn simplify_idx(&self, epsilon: &T) -> Vec { calculate_rdp_indices( &self - .0 - .iter() + .coords() .enumerate() .map(|(idx, coord)| RdpIndex { index: idx, diff --git a/geo/src/algorithm/simplifyvw.rs b/geo/src/algorithm/simplifyvw.rs index 9fe1bfa704..3cdfd154d7 100644 --- a/geo/src/algorithm/simplifyvw.rs +++ b/geo/src/algorithm/simplifyvw.rs @@ -88,16 +88,16 @@ where T: CoordFloat, { // No need to continue without at least three points - if orig.0.len() < 3 { - return orig.0.iter().enumerate().map(|(idx, _)| idx).collect(); + if orig.inner().len() < 3 { + return orig.coords().enumerate().map(|(idx, _)| idx).collect(); } - let max = orig.0.len(); + let max = orig.inner().len(); // Adjacent retained points. Simulating the points in a // linked list with indices into `orig`. Big number (larger than or equal to // `max`) means no next element, and (0, 0) means deleted element. - let mut adjacent: Vec<_> = (0..orig.0.len()) + let mut adjacent: Vec<_> = (0..orig.inner().len()) .map(|i| { if i == 0 { (-1_i32, 1_i32) @@ -155,9 +155,9 @@ where continue; } let area = Triangle::new( - orig.0[ai as usize], - orig.0[current_point as usize], - orig.0[bi as usize], + orig[ai as usize], + orig[current_point as usize], + orig[bi as usize], ) .unsigned_area(); pq.push(VScore { @@ -170,8 +170,7 @@ where } } // Filter out the points that have been deleted, returning remaining point indices - orig.0 - .iter() + orig.coords() .enumerate() .zip(adjacent.iter()) .filter_map(|(tup, adj)| if *adj != (0, 0) { Some(tup.0) } else { None }) @@ -185,13 +184,12 @@ where { // Epsilon must be greater than zero for any meaningful simplification to happen if *epsilon <= T::zero() { - return orig.0.to_vec(); + return orig.inner().to_vec(); } let subset = visvalingam_indices(orig, epsilon); // filter orig using the indices // using get would be more robust here, but the input subset is guaranteed to be valid in this case - orig.0 - .iter() + orig.coords() .zip(subset.iter()) .map(|(_, s)| orig[*s]) .collect() @@ -245,16 +243,16 @@ fn visvalingam_preserve( where T: CoordFloat + RTreeNum, { - if orig.0.len() < 3 || *epsilon <= T::zero() { - return orig.0.to_vec(); + if orig.inner().len() < 3 || *epsilon <= T::zero() { + return orig.inner().to_vec(); } - let max = orig.0.len(); - let mut counter = orig.0.len(); + let max = orig.inner().len(); + let mut counter = orig.inner().len(); // Adjacent retained points. Simulating the points in a // linked list with indices into `orig`. Big number (larger than or equal to // `max`) means no next element, and (0, 0) means deleted element. - let mut adjacent: Vec<_> = (0..orig.0.len()) + let mut adjacent: Vec<_> = (0..orig.inner().len()) .map(|i| { if i == 0 { (-1_i32, 1_i32) @@ -303,7 +301,7 @@ where // HOWEVER if we're within 2 points of the absolute minimum, we can't remove this point or the next // because we could then no longer form a valid geometry if removal of next also caused an intersection. // The simplification process is thus over. - smallest.intersector = tree_intersect(tree, &smallest, &orig.0); + smallest.intersector = tree_intersect(tree, &smallest, orig.inner()); if smallest.intersector && counter <= geomtype.min_points { break; } @@ -312,9 +310,9 @@ where adjacent[smallest.current as usize] = (0, 0); counter -= 1; // Remove stale segments from R* tree - let left_point = Point::from(orig.0[left as usize]); - let middle_point = Point::from(orig.0[smallest.current]); - let right_point = Point::from(orig.0[right as usize]); + let left_point = Point::from(orig[left as usize]); + let middle_point = Point::from(orig[smallest.current]); + let right_point = Point::from(orig[right as usize]); let line_1 = Line::new(left_point, middle_point); let line_2 = Line::new(middle_point, right_point); @@ -336,9 +334,9 @@ where continue; } let new = Triangle::new( - orig.0[ai as usize], - orig.0[current_point as usize], - orig.0[bi as usize], + orig[ai as usize], + orig[current_point as usize], + orig[bi as usize], ); // The current point causes a self-intersection, and this point precedes it // we ensure it gets removed next by demoting its area to negative epsilon @@ -360,8 +358,7 @@ where } } // Filter out the points that have been deleted, returning remaining points - orig.0 - .iter() + orig.coords() .zip(adjacent.iter()) .filter_map(|(tup, adj)| if *adj != (0, 0) { Some(*tup) } else { None }) .collect() @@ -400,16 +397,16 @@ where orig[triangle.right], ) .bounding_rect(); - let br = Point::new(bounding_rect.min().x, bounding_rect.min().y); - let tl = Point::new(bounding_rect.max().x, bounding_rect.max().y); + let br = Point::new(bounding_rect.min().x(), bounding_rect.min().y()); + let tl = Point::new(bounding_rect.max().x(), bounding_rect.max().y()); tree.locate_in_envelope_intersecting(&rstar::AABB::from_corners(br, tl)) .any(|c| { // triangle start point, end point let (ca, cb) = c.points(); - ca.0 != point_a - && ca.0 != point_c - && cb.0 != point_a - && cb.0 != point_c + ca.coord() != point_a + && ca.coord() != point_c + && cb.coord() != point_a + && cb.coord() != point_c && cartesian_intersect(ca, cb, Point::from(point_a), Point::from(point_c)) }) } @@ -577,8 +574,7 @@ where { fn simplifyvw_preserve(&self, epsilon: &T) -> MultiLineString { MultiLineString::new( - self.0 - .iter() + self.iter() .map(|l| l.simplifyvw_preserve(epsilon)) .collect(), ) @@ -607,8 +603,7 @@ where { fn simplifyvw_preserve(&self, epsilon: &T) -> MultiPolygon { MultiPolygon::new( - self.0 - .iter() + self.iter() .map(|p| p.simplifyvw_preserve(epsilon)) .collect(), ) @@ -824,7 +819,7 @@ mod test { let points_ls = geo_test_fixtures::vw_orig::(); let correct_ls = geo_test_fixtures::vw_simplified::(); let simplified = visvalingam(&points_ls, &0.0005); - assert_eq!(simplified, correct_ls.0); + assert_eq!(simplified, correct_ls.inner()); } #[test] fn visvalingam_preserve_test_long() { diff --git a/geo/src/algorithm/translate.rs b/geo/src/algorithm/translate.rs index 1774f7084a..c7e6ba4e15 100644 --- a/geo/src/algorithm/translate.rs +++ b/geo/src/algorithm/translate.rs @@ -155,7 +155,7 @@ mod test { Coordinate::from((23.0, 19.3)), Coordinate::from((22.0, 19.3)), ]; - assert_eq!(rotated.exterior().0, correct_outside); - assert_eq!(rotated.interiors()[0].0, correct_inside); + assert_eq!(rotated.exterior().inner(), correct_outside); + assert_eq!(rotated.interiors()[0].inner(), correct_inside); } } diff --git a/geo/src/algorithm/vincenty_length.rs b/geo/src/algorithm/vincenty_length.rs index 8c65ab62c0..27d52dc273 100644 --- a/geo/src/algorithm/vincenty_length.rs +++ b/geo/src/algorithm/vincenty_length.rs @@ -70,7 +70,7 @@ where { fn vincenty_length(&self) -> Result { let mut length = T::zero(); - for line_string in &self.0 { + for line_string in self { length = length + line_string.vincenty_length()?; } Ok(length) diff --git a/geo/src/algorithm/winding_order.rs b/geo/src/algorithm/winding_order.rs index 89e3a214eb..45c6aa844e 100644 --- a/geo/src/algorithm/winding_order.rs +++ b/geo/src/algorithm/winding_order.rs @@ -122,11 +122,11 @@ where }; use crate::utils::least_index; - let i = least_index(&self.0); + let i = least_index(self.inner()); let mut next = i; increment(&mut next); - while self.0[next] == self.0[i] { + while self[next] == self[i] { if next == i { // We've looped too much. There aren't // enough unique coords to compute orientation. @@ -137,14 +137,14 @@ where let mut prev = i; decrement(&mut prev); - while self.0[prev] == self.0[i] { + while self[prev] == self[i] { // Note: we don't need to check if prev == i as // the previous loop succeeded, and so we have // at least two distinct elements in the list decrement(&mut prev); } - match K::orient2d(self.0[prev], self.0[i], self.0[next]) { + match K::orient2d(self[prev], self[i], self[next]) { Orientation::CounterClockwise => Some(WindingOrder::CounterClockwise), Orientation::Clockwise => Some(WindingOrder::Clockwise), _ => None, @@ -176,14 +176,14 @@ where /// Change this line's points so they are in clockwise winding order fn make_cw_winding(&mut self) { if let Some(WindingOrder::CounterClockwise) = self.winding_order() { - self.0.reverse(); + self.inner_mut().reverse(); } } /// Change this line's points so they are in counterclockwise winding order fn make_ccw_winding(&mut self) { if let Some(WindingOrder::Clockwise) = self.winding_order() { - self.0.reverse(); + self.inner_mut().reverse(); } } } @@ -201,10 +201,10 @@ mod test { let c = Point::new(1., 2.); // Verify open linestrings return None - let mut ls = LineString::from(vec![a.0, b.0, c.0]); + let mut ls = LineString::from(vec![a.coord(), b.coord(), c.coord()]); assert!(ls.winding_order().is_none()); - ls.0.push(ls.0[0]); + ls.push(ls[0]); assert_eq!(ls.winding_order(), Some(WindingOrder::CounterClockwise)); ls.make_cw_winding(); @@ -219,10 +219,10 @@ mod test { let c = Point::new(1, 2); // Verify open linestrings return None - let mut ls = LineString::from(vec![a.0, b.0, c.0]); + let mut ls = LineString::from(vec![a.coord(), b.coord(), c.coord()]); assert!(ls.winding_order().is_none()); - ls.0.push(ls.0[0]); + ls.push(ls[0]); assert!(ls.is_ccw()); let ccw_ls: Vec<_> = ls.points_ccw().collect(); diff --git a/geo/src/utils.rs b/geo/src/utils.rs index c9f4d9bd8f..9df88c72d6 100644 --- a/geo/src/utils.rs +++ b/geo/src/utils.rs @@ -84,9 +84,10 @@ use std::cmp::Ordering; /// Expects none of coordinates to be uncomparable (eg. nan) #[inline] pub fn lex_cmp(p: &Coordinate, q: &Coordinate) -> Ordering { - p.x.partial_cmp(&q.x) + p.x() + .partial_cmp(&q.x()) .unwrap() - .then(p.y.partial_cmp(&q.y).unwrap()) + .then(p.y().partial_cmp(&q.y()).unwrap()) } /// Compute index of the least point in slice. Comparison is diff --git a/jts-test-runner/src/runner.rs b/jts-test-runner/src/runner.rs index e3b1d2cd9a..8a7ed16a6e 100644 --- a/jts-test-runner/src/runner.rs +++ b/jts-test-runner/src/runner.rs @@ -535,12 +535,12 @@ where { assert!(r1.is_closed(), "r1 is not closed"); assert!(r2.is_closed(), "r2 is not closed"); - if r1.0.len() != r2.0.len() { + if r1.inner().len() != r2.inner().len() { return false; } - let len = r1.0.len() - 1; + let len = r1.inner().len() - 1; (0..len).any(|shift| { - (0..len).all(|i| coord_matcher(&r1.0[i], &r2.0[(i + shift) % len])) - || (0..len).all(|i| coord_matcher(&r1.0[len - i], &r2.0[(i + shift) % len])) + (0..len).all(|i| coord_matcher(&r1[i], &r2[(i + shift) % len])) + || (0..len).all(|i| coord_matcher(&r1[len - i], &r2[(i + shift) % len])) }) }