Skip to content

Commit

Permalink
use point! instead of Point(c) ctor
Browse files Browse the repository at this point in the history
Rust does not allow tuple type aliases to be instantiated, so `Point(c)` must always be a real struct, and cannot be a type alias like `type Point<T> = GenericPoint<T,Z,M>`. To make the migration transparent, this PR adds support for a single-expression `point!` macro. Now it can be used in 3 ways:

```
point! { x: <number>, y: <number> }
point!(<x_number>, <y_number>)
point!(<coordinate>)
```

See also georust#742 (comment)

* Replace `Point(c)` with `point!(c)`
* Replace a few `format!("{}", v)` with `v.to_string()`
* Use `Self` or `Self::Output` instead of a concrete type when possible.
  • Loading branch information
nyurik committed Mar 17, 2022
1 parent b6bfff1 commit 50733eb
Show file tree
Hide file tree
Showing 15 changed files with 97 additions and 74 deletions.
2 changes: 1 addition & 1 deletion geo-types/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ mod test {

let failure = Point::try_from(rect_geometry).unwrap_err();
assert_eq!(
format!("{}", failure),
failure.to_string(),
"Expected a geo_types::point::Point<f64>, but found a geo_types::rect::Rect<f64>"
);
}
Expand Down
2 changes: 1 addition & 1 deletion geo-types/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ mod tests {
y: 116.34,
};

let p = Point(c);
let p = point!(c);

let Point(c2) = p;
assert_eq!(c, c2);
Expand Down
6 changes: 3 additions & 3 deletions geo-types/src/line.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{CoordNum, Coordinate, Point};
use crate::{point, CoordNum, Coordinate, Point};
#[cfg(any(feature = "approx", test))]
use approx::{AbsDiffEq, RelativeEq};

Expand Down Expand Up @@ -143,11 +143,11 @@ impl<T: CoordNum> Line<T> {
}

pub fn start_point(&self) -> Point<T> {
Point(self.start)
point!(self.start)
}

pub fn end_point(&self) -> Point<T> {
Point(self.end)
point!(self.end)
}

pub fn points(&self) -> (Point<T>, Point<T>) {
Expand Down
6 changes: 3 additions & 3 deletions geo-types/src/line_string.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#[cfg(any(feature = "approx", test))]
use approx::{AbsDiffEq, RelativeEq};

use crate::{CoordNum, Coordinate, Line, Point, Triangle};
use crate::{point, CoordNum, Coordinate, Line, Point, Triangle};
use std::iter::FromIterator;
use std::ops::{Index, IndexMut};

Expand Down Expand Up @@ -142,7 +142,7 @@ impl<'a, T: CoordNum> Iterator for PointsIter<'a, T> {
type Item = Point<T>;

fn next(&mut self) -> Option<Self::Item> {
self.0.next().map(|c| Point(*c))
self.0.next().map(|c| point!(*c))
}

fn size_hint(&self) -> (usize, Option<usize>) {
Expand All @@ -158,7 +158,7 @@ impl<'a, T: CoordNum> ExactSizeIterator for PointsIter<'a, T> {

impl<'a, T: CoordNum> DoubleEndedIterator for PointsIter<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
self.0.next_back().map(|c| Point(*c))
self.0.next_back().map(|c| point!(*c))
}
}

Expand Down
34 changes: 28 additions & 6 deletions geo-types/src/macros.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
/// Creates a [`Point`] from the given coordinates.
///
/// ```txt
/// point!(x: <number>, y: <number>)
/// point!(<x_number>, <y_number>)
/// point! { x: <number>, y: <number> }
/// point!(<coordinate>)
/// ```
///
/// # Examples
Expand All @@ -13,17 +15,21 @@
///
/// let p = point! { x: 181.2, y: 51.79 };
///
/// assert_eq!(p, geo_types::Point(geo_types::coord! {
/// x: 181.2,
/// y: 51.79,
/// }));
/// assert_eq!(p.x(), 181.2);
/// assert_eq!(p.y(), 51.79);
/// ```
///
/// [`Point`]: ./struct.Point.html
#[macro_export]
macro_rules! point {
( $($tag:tt : $val:expr),* $(,)? ) => {
$crate::Point ( $crate::coord! { $( $tag: $val , )* } )
$crate::point! ( $crate::coord! { $( $tag: $val , )* } )
};
( $x:expr, $y:expr $(,)? ) => {
$crate::point! { x: $x, y: $y }
};
( $coord:expr $(,)? ) => {
$crate::Point($coord)
};
}

Expand Down Expand Up @@ -299,6 +305,22 @@ mod test {
};
assert_eq!(p.x(), 1.2);
assert_eq!(p.y(), 3.4);

let p = point!(1.2, 3.4);
assert_eq!(p.x(), 1.2);
assert_eq!(p.y(), 3.4);

let p = point!(1.2, 3.4,);
assert_eq!(p.x(), 1.2);
assert_eq!(p.y(), 3.4);

let p = point!(coord! { x: 1.2, y: 3.4 });
assert_eq!(p.x(), 1.2);
assert_eq!(p.y(), 3.4);

let p = point!(coord! { x: 1.2, y: 3.4 },);
assert_eq!(p.x(), 1.2);
assert_eq!(p.y(), 3.4);
}

#[test]
Expand Down
38 changes: 19 additions & 19 deletions geo-types/src/point.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ pub struct Point<T: CoordNum>(pub Coordinate<T>);

impl<T: CoordNum> From<Coordinate<T>> for Point<T> {
fn from(x: Coordinate<T>) -> Point<T> {
Point(x)
point!(x)
}
}

Expand Down Expand Up @@ -73,7 +73,7 @@ impl<T: CoordNum> Point<T> {
/// assert_eq!(p.x(), 1.234);
/// assert_eq!(p.y(), 2.345);
/// ```
pub fn new(x: T, y: T) -> Point<T> {
pub fn new(x: T, y: T) -> Self {
point! { x: x, y: y }
}

Expand Down Expand Up @@ -104,7 +104,7 @@ impl<T: CoordNum> Point<T> {
///
/// assert_eq!(p.x(), 9.876);
/// ```
pub fn set_x(&mut self, x: T) -> &mut Point<T> {
pub fn set_x(&mut self, x: T) -> &mut Self {
self.0.x = x;
self
}
Expand Down Expand Up @@ -136,7 +136,7 @@ impl<T: CoordNum> Point<T> {
///
/// assert_eq!(p.y(), 9.876);
/// ```
pub fn set_y(&mut self, y: T) -> &mut Point<T> {
pub fn set_y(&mut self, y: T) -> &mut Self {
self.0.y = y;
self
}
Expand Down Expand Up @@ -187,7 +187,7 @@ impl<T: CoordNum> Point<T> {
/// assert_eq!(p.x(), 9.876);
/// ```
#[deprecated = "use `Point::set_x` instead, it's less ambiguous"]
pub fn set_lng(&mut self, lng: T) -> &mut Point<T> {
pub fn set_lng(&mut self, lng: T) -> &mut Self {
self.set_x(lng)
}

Expand Down Expand Up @@ -220,7 +220,7 @@ impl<T: CoordNum> Point<T> {
/// assert_eq!(p.y(), 9.876);
/// ```
#[deprecated = "use `Point::set_y` instead, it's less ambiguous"]
pub fn set_lat(&mut self, lat: T) -> &mut Point<T> {
pub fn set_lat(&mut self, lat: T) -> &mut Self {
self.set_y(lat)
}
}
Expand All @@ -239,7 +239,7 @@ impl<T: CoordNum> Point<T> {
///
/// assert_eq!(dot, 5.25);
/// ```
pub fn dot(self, other: Point<T>) -> T {
pub fn dot(self, other: Self) -> T {
self.x() * other.x() + self.y() * other.y()
}

Expand All @@ -260,7 +260,7 @@ impl<T: CoordNum> Point<T> {
///
/// assert_eq!(cross, 2.0)
/// ```
pub fn cross_prod(self, point_b: Point<T>, point_c: Point<T>) -> T {
pub fn cross_prod(self, point_b: Self, point_c: Self) -> T {
(point_b.x() - self.x()) * (point_c.y() - self.y())
- (point_b.y() - self.y()) * (point_c.x() - self.x())
}
Expand All @@ -278,7 +278,7 @@ impl<T: CoordFloat> Point<T> {
/// assert_eq!(x.round(), 71.0);
/// assert_eq!(y.round(), 134.0);
/// ```
pub fn to_degrees(self) -> Point<T> {
pub fn to_degrees(self) -> Self {
let (x, y) = self.x_y();
let x = x.to_degrees();
let y = y.to_degrees();
Expand All @@ -296,7 +296,7 @@ impl<T: CoordFloat> Point<T> {
/// assert_eq!(x.round(), 3.0);
/// assert_eq!(y.round(), 6.0);
/// ```
pub fn to_radians(self) -> Point<T> {
pub fn to_radians(self) -> Self {
let (x, y) = self.x_y();
let x = x.to_radians();
let y = y.to_radians();
Expand All @@ -322,8 +322,8 @@ where
/// assert_eq!(p.x(), 1.25);
/// assert_eq!(p.y(), -2.5);
/// ```
fn neg(self) -> Point<T> {
Point(-self.0)
fn neg(self) -> Self::Output {
point!(-self.0)
}
}

Expand All @@ -342,8 +342,8 @@ impl<T: CoordNum> Add for Point<T> {
/// assert_eq!(p.x(), 2.75);
/// assert_eq!(p.y(), 5.0);
/// ```
fn add(self, rhs: Point<T>) -> Point<T> {
Point(self.0 + rhs.0)
fn add(self, rhs: Self) -> Self::Output {
point!(self.0 + rhs.0)
}
}

Expand Down Expand Up @@ -382,7 +382,7 @@ impl<T: CoordNum> Sub for Point<T> {
/// assert_eq!(p.y(), 0.5);
/// ```
fn sub(self, rhs: Point<T>) -> Point<T> {
Point(self.0 - rhs.0)
point!(self.0 - rhs.0)
}
}

Expand Down Expand Up @@ -420,8 +420,8 @@ impl<T: CoordNum> Mul<T> for Point<T> {
/// assert_eq!(p.x(), 4.0);
/// assert_eq!(p.y(), 6.0);
/// ```
fn mul(self, rhs: T) -> Point<T> {
Point(self.0 * rhs)
fn mul(self, rhs: T) -> Self::Output {
point!(self.0 * rhs)
}
}

Expand Down Expand Up @@ -459,8 +459,8 @@ impl<T: CoordNum> Div<T> for Point<T> {
/// assert_eq!(p.x(), 1.0);
/// assert_eq!(p.y(), 1.5);
/// ```
fn div(self, rhs: T) -> Point<T> {
Point(self.0 / rhs)
fn div(self, rhs: T) -> Self::Output {
point!(self.0 / rhs)
}
}

Expand Down
6 changes: 3 additions & 3 deletions geo-types/src/polygon.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{CoordFloat, CoordNum, LineString, Point, Rect, Triangle};
use crate::{point, CoordFloat, CoordNum, LineString, Rect, Triangle};
use num_traits::{Float, Signed};

#[cfg(any(feature = "approx", test))]
Expand Down Expand Up @@ -424,8 +424,8 @@ impl<T: CoordFloat + Signed> Polygon<T> {
.map(|(idx, _)| {
let prev_1 = self.previous_vertex(idx);
let prev_2 = self.previous_vertex(prev_1);
Point(self.exterior[prev_2])
.cross_prod(Point(self.exterior[prev_1]), Point(self.exterior[idx]))
point!(self.exterior[prev_2])
.cross_prod(point!(self.exterior[prev_1]), point!(self.exterior[idx]))
})
// accumulate and check cross-product result signs in a single pass
// positive implies ccw convexity, negative implies cw convexity
Expand Down
4 changes: 2 additions & 2 deletions geo-types/src/private_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// hidden module is public so the geo crate can reuse these algorithms to
// prevent duplication. These functions are _not_ meant for public consumption.

use crate::{CoordFloat, CoordNum, Coordinate, Line, LineString, Point, Rect};
use crate::{point, CoordFloat, CoordNum, Coordinate, Line, LineString, Point, Rect};

pub fn line_string_bounding_rect<T>(line_string: &LineString<T>) -> Option<Rect<T>>
where
Expand Down Expand Up @@ -132,7 +132,7 @@ where
}
// LineString with one point equal p
if line_string.0.len() == 1 {
return point_contains_point(Point(line_string[0]), point);
return point_contains_point(point!(line_string[0]), point);
}
// check if point is a vertex
if line_string.0.contains(&point.0) {
Expand Down
8 changes: 4 additions & 4 deletions geo/src/algorithm/centroid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use crate::algorithm::area::{get_linestring_area, Area};
use crate::algorithm::dimensions::{Dimensions, Dimensions::*, HasDimensions};
use crate::algorithm::euclidean_length::EuclideanLength;
use crate::{
Coordinate, GeoFloat, Geometry, GeometryCollection, Line, LineString, MultiLineString,
point, Coordinate, GeoFloat, Geometry, GeometryCollection, Line, LineString, MultiLineString,
MultiPoint, MultiPolygon, Point, Polygon, Rect, Triangle,
};

Expand Down Expand Up @@ -221,7 +221,7 @@ impl<T: GeoFloat> CentroidOperation<T> {

fn centroid(&self) -> Option<Point<T>> {
self.0.as_ref().map(|weighted_centroid| {
Point(weighted_centroid.accumulated / weighted_centroid.weight)
point!(weighted_centroid.accumulated / weighted_centroid.weight)
})
}

Expand Down Expand Up @@ -493,7 +493,7 @@ mod test {
};
let linestring = line_string![coord];
let centroid = linestring.centroid();
assert_eq!(centroid, Some(Point(coord)));
assert_eq!(centroid, Some(point!(coord)));
}
#[test]
fn linestring_test() {
Expand Down Expand Up @@ -540,7 +540,7 @@ mod test {
line_string![coord],
line_string![coord],
]);
assert_relative_eq!(mls.centroid().unwrap(), Point(coord));
assert_relative_eq!(mls.centroid().unwrap(), point!(coord));
}
#[test]
fn multilinestring_one_line_test() {
Expand Down
12 changes: 6 additions & 6 deletions geo/src/algorithm/closest_point.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::prelude::*;
use crate::{
Closest, Coordinate, GeoFloat, Geometry, GeometryCollection, Line, LineString, MultiLineString,
MultiPoint, MultiPolygon, Point, Polygon, Rect, Triangle,
point, Closest, Coordinate, GeoFloat, Geometry, GeometryCollection, Line, LineString,
MultiLineString, MultiPoint, MultiPolygon, Point, Polygon, Rect, Triangle,
};
use std::iter;

Expand Down Expand Up @@ -64,8 +64,8 @@ impl<F: GeoFloat> ClosestPoint<F> for Line<F> {
//
// Line equation: P = start + t * (end - start)

let direction_vector = Point(self.end - self.start);
let to_p = Point(p.0 - self.start);
let direction_vector = point!(self.end - self.start);
let to_p = point!(p.0 - self.start);

let t = to_p.dot(direction_vector) / direction_vector.dot(direction_vector);

Expand All @@ -78,7 +78,7 @@ impl<F: GeoFloat> ClosestPoint<F> for Line<F> {

let x = direction_vector.x();
let y = direction_vector.y();
let c = Point(self.start + (t * x, t * y).into());
let c = point!(self.start + (t * x, t * y).into());

if self.intersects(p) {
Closest::Intersection(c)
Expand Down Expand Up @@ -131,7 +131,7 @@ impl<F: GeoFloat> ClosestPoint<F> for Polygon<F> {

impl<F: GeoFloat> ClosestPoint<F> for Coordinate<F> {
fn closest_point(&self, p: &Point<F>) -> Closest<F> {
Point(*self).closest_point(p)
point!(*self).closest_point(p)
}
}

Expand Down
Loading

0 comments on commit 50733eb

Please sign in to comment.