Skip to content

Commit

Permalink
Merge branch 'master' of github.com:georust/geo
Browse files Browse the repository at this point in the history
  • Loading branch information
frewsxcv committed May 8, 2020
2 parents 0f030e5 + 2b741ae commit 9125aed
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 5 deletions.
48 changes: 48 additions & 0 deletions geo-types/src/coordinate.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::{CoordinateType, Point};
#[cfg(test)]
use approx::{AbsDiffEq, RelativeEq, UlpsEq};

/// A lightweight struct used to store coordinates on the 2-dimensional
/// Cartesian plane.
Expand Down Expand Up @@ -68,3 +70,49 @@ where
(self.x, self.y)
}
}

#[cfg(test)]
impl<T: CoordinateType + AbsDiffEq> AbsDiffEq for Coordinate<T>
where
T::Epsilon: Copy,
{
type Epsilon = T::Epsilon;

fn default_epsilon() -> T::Epsilon {
T::default_epsilon()
}

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)
}
}

#[cfg(test)]
impl<T: CoordinateType + RelativeEq> RelativeEq for Coordinate<T>
where
T::Epsilon: Copy,
{
fn default_max_relative() -> T::Epsilon {
T::default_max_relative()
}

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)
}
}

#[cfg(test)]
impl<T: CoordinateType + UlpsEq> UlpsEq for Coordinate<T>
where
T::Epsilon: Copy,
{
fn default_max_ulps() -> u32 {
T::default_max_ulps()
}

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)
}
}
105 changes: 105 additions & 0 deletions geo-types/src/rect.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::{polygon, Coordinate, CoordinateType, Polygon};
use num_traits::Float;

/// A bounded 2D quadrilateral whose area is defined by minimum and maximum `Coordinate`s.
///
Expand All @@ -18,6 +19,10 @@ use crate::{polygon, Coordinate, CoordinateType, Polygon};
///
/// assert_eq!(3., rect.width());
/// assert_eq!(6., rect.height());
/// assert_eq!(
/// Coordinate { x: 1.5, y: 7. },
/// rect.center()
/// );
/// ```
#[derive(Eq, PartialEq, Clone, Copy, Debug, Hash)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
Expand Down Expand Up @@ -71,6 +76,20 @@ impl<T: CoordinateType> Rect<T> {
}
}

/// Returns the minimum `Coordinate` (bottom-left corner) of the `Rect`.
///
/// # Examples
///
/// ```rust
/// use geo_types::{Coordinate, Rect};
///
/// let rect = Rect::new(
/// Coordinate { x: 5., y: 5. },
/// Coordinate { x: 15., y: 15. },
/// );
///
/// assert_eq!(rect.min(), Coordinate { x: 5., y: 5. });
/// ```
pub fn min(self) -> Coordinate<T> {
self.min
}
Expand All @@ -88,6 +107,20 @@ impl<T: CoordinateType> Rect<T> {
self.assert_valid_bounds();
}

/// Returns the maximum `Coordinate` (top-right corner) of the `Rect`.
///
/// # Examples
///
/// ```rust
/// use geo_types::{Coordinate, Rect};
///
/// let rect = Rect::new(
/// Coordinate { x: 5., y: 5. },
/// Coordinate { x: 15., y: 15. },
/// );
///
/// assert_eq!(rect.max(), Coordinate { x: 15., y: 15. });
/// ```
pub fn max(self) -> Coordinate<T> {
self.max
}
Expand All @@ -105,10 +138,38 @@ impl<T: CoordinateType> Rect<T> {
self.assert_valid_bounds();
}

/// Returns the width of the `Rect`.
///
/// # Examples
///
/// ```rust
/// use geo_types::{Coordinate, Rect};
///
/// let rect = Rect::new(
/// Coordinate { x: 5., y: 5. },
/// Coordinate { x: 15., y: 15. },
/// );
///
/// assert_eq!(rect.width(), 10.);
/// ```
pub fn width(self) -> T {
self.max().x - self.min().x
}

/// Returns the height of the `Rect`.
///
/// # Examples
///
/// ```rust
/// use geo_types::{Coordinate, Rect};
///
/// let rect = Rect::new(
/// Coordinate { x: 5., y: 5. },
/// Coordinate { x: 15., y: 15. },
/// );
///
/// assert_eq!(rect.height(), 10.);
/// ```
pub fn height(self) -> T {
self.max().y - self.min().y
}
Expand Down Expand Up @@ -157,6 +218,34 @@ impl<T: CoordinateType> Rect<T> {
}
}

impl<T: CoordinateType + Float> Rect<T> {
/// Returns the center `Coordinate` of the `Rect`.
///
/// # Examples
///
/// ```rust
/// use geo_types::{Coordinate, Rect};
///
/// let rect = Rect::new(
/// Coordinate { x: 5., y: 5. },
/// Coordinate { x: 15., y: 15. },
/// );
///
/// assert_eq!(
/// rect.center(),
/// Coordinate { x: 10., y: 10. }
/// );
/// ```
pub fn center(self) -> Coordinate<T> {
let two = T::one() + T::one();
(
(self.max.x + self.min.x) / two,
(self.max.y + self.min.y) / two,
)
.into()
}
}

static RECT_INVALID_BOUNDS_ERROR: &str = "Failed to create Rect: 'min' coordinate's x/y value must be smaller or equal to the 'max' x/y value";

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
Expand Down Expand Up @@ -199,4 +288,20 @@ mod test {
let rect = Rect::new((10., 10.), (20., 20.));
assert_relative_eq!(rect.height(), 10.);
}

#[test]
fn rect_center() {
assert_relative_eq!(
Rect::new((0., 10.), (10., 90.)).center(),
Coordinate::from((5., 50.))
);
assert_relative_eq!(
Rect::new((-42., -42.), (42., 42.)).center(),
Coordinate::from((0., 0.))
);
assert_relative_eq!(
Rect::new((0., 0.), (0., 0.)).center(),
Coordinate::from((0., 0.))
);
}
}
6 changes: 1 addition & 5 deletions geo/src/algorithm/centroid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,7 @@ where
type Output = Point<T>;

fn centroid(&self) -> Self::Output {
let two = T::one() + T::one();
Point::new(
(self.max().x + self.min().x) / two,
(self.max().y + self.min().y) / two,
)
self.center().into()
}
}

Expand Down

0 comments on commit 9125aed

Please sign in to comment.