-
Notifications
You must be signed in to change notification settings - Fork 204
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
relative_eq() #567
Merged
Merged
relative_eq() #567
Changes from 15 commits
Commits
Show all changes
19 commits
Select commit
Hold shift + click to select a range
946397d
Added num_coords() method to MultiPoint. To Point, Line, LineString a…
martinfrances107 65f6100
Removed debug.
martinfrances107 4ab3599
Removed commented out code.
martinfrances107 daf5570
Removed commented out code.
martinfrances107 719c32c
line_string.rs abs_diff_eq: simplify by using .all()
martinfrances107 6c23693
multi_point.rs: Simplify using .all()
martinfrances107 3eaec49
multi_point.rs abs_diff_eq() now handles unequal sizes
martinfrances107 1dca719
point.rs Simplify RelativeEq for Point
martinfrances107 edb4ff1
lines.rs Simplify "AbsDiffEq for Line<T>" to operate of coords not po…
martinfrances107 5aa011c
line_string.rs - abs_diff_eq() Now rejects line_strings with unequal…
martinfrances107 efb112a
Removed type constraint on RelativeEq and AbsDiffEq that the type mus…
martinfrances107 8ba2b0b
ran cargo fmt
martinfrances107 26a6a2d
Added new feature relative_eq
martinfrances107 c21a552
After rebase, drop the use of the deprecated num_coords() method.
martinfrances107 bfb2746
Fixed dev-dependency issue.
martinfrances107 d347afd
Minor Tidy: Removed multipoint.rs num_coords(). Fixed doctest code an…
martinfrances107 89d4742
Rename `relative_eq` feature to `approx` and make optional
michaelkirk fde7395
changelog
michaelkirk e90ee64
Merge pull request #1 from georust/mkirk/approx-feature-juggling
martinfrances107 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,8 @@ | ||
use crate::{Coordinate, CoordinateType, Point}; | ||
#[cfg(feature = "relative_eq")] | ||
use approx::AbsDiffEq; | ||
#[cfg(feature = "relative_eq")] | ||
use approx::RelativeEq; | ||
|
||
/// A line segment made up of exactly two | ||
/// [`Coordinate`s](struct.Coordinate.html). | ||
|
@@ -164,6 +168,66 @@ impl<T: CoordinateType> From<[(T, T); 2]> for Line<T> { | |
Line::new(coord[0], coord[1]) | ||
} | ||
} | ||
#[cfg(feature = "relative_eq")] | ||
impl<T> RelativeEq for Line<T> | ||
where | ||
T: AbsDiffEq<Epsilon = T> + CoordinateType + RelativeEq, | ||
{ | ||
#[inline] | ||
fn default_max_relative() -> Self::Epsilon { | ||
T::default_max_relative() | ||
} | ||
|
||
/// Equality assertion within a relative limit. | ||
/// | ||
/// # Examples | ||
/// | ||
/// ``` | ||
/// use geo_types::{Coordinate, Line}; | ||
/// | ||
/// let a = Line::new(Coordinate { x: 0., y: 0. }, Coordinate { x: 1., y: 1. }); | ||
/// let b = Line::new(Coordinate { x: 0., y: 0. }, Coordinate { x: 1.001, y: 1. }); | ||
/// | ||
/// approx::assert_relative_eq!(a, b, max_relative=0.1) | ||
/// ``` | ||
#[inline] | ||
fn relative_eq( | ||
&self, | ||
other: &Self, | ||
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) | ||
} | ||
} | ||
|
||
#[cfg(feature = "relative_eq")] | ||
impl<T: AbsDiffEq<Epsilon = T> + CoordinateType> AbsDiffEq for Line<T> { | ||
type Epsilon = T; | ||
|
||
#[inline] | ||
fn default_epsilon() -> Self::Epsilon { | ||
T::default_epsilon() | ||
} | ||
|
||
/// Equality assertion within a relative limit. | ||
/// | ||
/// # Examples | ||
/// | ||
/// ``` | ||
/// use geo_types::{Coordinate, Line}; | ||
/// | ||
/// let a = Line::new(Coordinate { x: 0., y: 0. }, Coordinate { x: 1., y: 1. }); | ||
/// let b = Line::new(Coordinate { x: 0., y: 0. }, Coordinate { x: 1.001, y: 1. }); | ||
/// | ||
/// approx::assert_relative_eq!(a, b, epsilon=0.1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. assert_abs_diff_eq |
||
/// ``` | ||
#[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) | ||
} | ||
} | ||
|
||
#[cfg(feature = "rstar")] | ||
impl<T> ::rstar::RTreeObject for Line<T> | ||
|
@@ -188,3 +252,82 @@ where | |
d.powi(2) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use super::*; | ||
|
||
#[test] | ||
fn test_abs_diff_eq() { | ||
let delta = 1e-6; | ||
let line = Line::new(Coordinate { x: 0., y: 0. }, Coordinate { x: 1., y: 1. }); | ||
let line_start_x = Line::new( | ||
Point(Coordinate { | ||
x: 0. + delta, | ||
y: 0., | ||
}), | ||
Point(Coordinate { x: 1., y: 1. }), | ||
); | ||
assert!(line.abs_diff_eq(&line_start_x, 1e-2)); | ||
assert!(line.abs_diff_ne(&line_start_x, 1e-12)); | ||
|
||
let line_start_y = Line::new( | ||
Coordinate { | ||
x: 0., | ||
y: 0. + delta, | ||
}, | ||
Coordinate { x: 1., y: 1. }, | ||
); | ||
assert!(line.abs_diff_eq(&line_start_y, 1e-2)); | ||
assert!(line.abs_diff_ne(&line_start_y, 1e-12)); | ||
|
||
let line_end_x = Line::new( | ||
Coordinate { x: 0., y: 0. }, | ||
Coordinate { | ||
x: 1. + delta, | ||
y: 1., | ||
}, | ||
); | ||
|
||
assert!(line.abs_diff_eq(&line_end_x, 1e-2)); | ||
assert!(line.abs_diff_ne(&line_end_x, 1e-12)); | ||
|
||
let line_end_y = Line::new( | ||
Coordinate { x: 0., y: 0. }, | ||
Coordinate { | ||
x: 1., | ||
y: 1. + delta, | ||
}, | ||
); | ||
|
||
assert!(line.abs_diff_eq(&line_end_y, 1e-2)); | ||
assert!(line.abs_diff_ne(&line_end_y, 1e-12)); | ||
} | ||
|
||
#[test] | ||
fn test_relative_eq() { | ||
let delta = 1e-6; | ||
|
||
let line = Line::new(Coordinate { x: 0., y: 0. }, Coordinate { x: 1., y: 1. }); | ||
let line_start_x = Line::new( | ||
Point(Coordinate { | ||
x: 0. + delta, | ||
y: 0., | ||
}), | ||
Point(Coordinate { x: 1., y: 1. }), | ||
); | ||
let line_start_y = Line::new( | ||
Coordinate { | ||
x: 0., | ||
y: 0. + delta, | ||
}, | ||
Coordinate { x: 1., y: 1. }, | ||
); | ||
|
||
assert!(line.relative_eq(&line_start_x, 1e-2, 1e-2)); | ||
assert!(line.relative_ne(&line_start_x, 1e-12, 1e-12)); | ||
|
||
assert!(line.relative_eq(&line_start_y, 1e-2, 1e-2)); | ||
assert!(line.relative_ne(&line_start_y, 1e-12, 1e-12)); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,8 @@ | ||
#[cfg(feature = "relative_eq")] | ||
use approx::AbsDiffEq; | ||
#[cfg(feature = "relative_eq")] | ||
use approx::RelativeEq; | ||
|
||
use crate::{Coordinate, CoordinateType, Line, Point, Triangle}; | ||
use std::iter::FromIterator; | ||
use std::ops::{Index, IndexMut}; | ||
|
@@ -282,6 +287,86 @@ impl<T: CoordinateType> IndexMut<usize> for LineString<T> { | |
} | ||
} | ||
|
||
#[cfg(feature = "relative_eq")] | ||
impl<T> RelativeEq for LineString<T> | ||
where | ||
T: AbsDiffEq<Epsilon = T> + CoordinateType + RelativeEq, | ||
{ | ||
#[inline] | ||
fn default_max_relative() -> Self::Epsilon { | ||
T::default_max_relative() | ||
} | ||
|
||
/// Equality assertion within a relative limit. | ||
/// | ||
/// # Examples | ||
/// | ||
/// ``` | ||
/// use geo_types::LineString; | ||
/// | ||
/// let mut coords_a = vec![(0., 0.), (5., 0.), (7., 9.)]; | ||
/// let a: LineString<f32> = coords_a.into_iter().collect(); | ||
/// | ||
/// let mut coords_b = vec![(0., 0.), (5., 0.), (7.001, 9.)]; | ||
/// let b: LineString<f32> = coords_b.into_iter().collect(); | ||
/// | ||
/// approx::assert_relative_eq!(a, b, max_relative=0.1) | ||
/// ``` | ||
/// | ||
fn relative_eq( | ||
&self, | ||
other: &Self, | ||
epsilon: Self::Epsilon, | ||
max_relative: Self::Epsilon, | ||
) -> bool { | ||
if self.0.len() != other.0.len() { | ||
return false; | ||
} | ||
|
||
let points_zipper = self.points_iter().zip(other.points_iter()); | ||
for (lhs, rhs) in points_zipper { | ||
if lhs.relative_ne(&rhs, epsilon, max_relative) { | ||
return false; | ||
} | ||
} | ||
|
||
true | ||
} | ||
} | ||
|
||
#[cfg(feature = "relative_eq")] | ||
impl<T: AbsDiffEq<Epsilon = T> + CoordinateType> AbsDiffEq for LineString<T> { | ||
type Epsilon = T; | ||
|
||
#[inline] | ||
fn default_epsilon() -> Self::Epsilon { | ||
T::default_epsilon() | ||
} | ||
|
||
/// Equality assertion within a relative limit. | ||
/// | ||
/// # Examples | ||
/// | ||
/// ``` | ||
/// use geo_types::LineString; | ||
/// | ||
/// let mut coords_a = vec![(0., 0.), (5., 0.), (7., 9.)]; | ||
/// let a: LineString<f32> = coords_a.into_iter().collect(); | ||
/// | ||
/// let mut coords_b = vec![(0., 0.), (5., 0.), (7.001, 9.)]; | ||
/// let b: LineString<f32> = coords_b.into_iter().collect(); | ||
/// | ||
/// approx::assert_relative_eq!(a, b, epsilon=0.1) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ditto about assert_abs_diff_eq and the comment |
||
/// ``` | ||
fn abs_diff_eq(&self, other: &Self, epsilon: Self::Epsilon) -> bool { | ||
if self.0.len() != other.0.len() { | ||
return false; | ||
} | ||
let mut points_zipper = self.points_iter().zip(other.points_iter()); | ||
points_zipper.all(|(lhs, rhs)| lhs.abs_diff_eq(&rhs, epsilon)) | ||
} | ||
} | ||
|
||
#[cfg(feature = "rstar")] | ||
impl<T> ::rstar::RTreeObject for LineString<T> | ||
where | ||
|
@@ -319,3 +404,66 @@ where | |
} | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod test { | ||
use super::*; | ||
|
||
use approx::AbsDiffEq; | ||
|
||
#[test] | ||
fn test_abs_diff_eq() { | ||
let delta = 1e-6; | ||
|
||
let coords = vec![(0., 0.), (5., 0.), (10., 10.)]; | ||
let ls: LineString<f32> = coords.into_iter().collect(); | ||
|
||
let coords_x = vec![(0., 0.), (5. + delta, 0.), (10., 10.)]; | ||
let ls_x: LineString<f32> = coords_x.into_iter().collect(); | ||
assert!(ls.abs_diff_eq(&ls_x, 1e-2)); | ||
assert!(ls.abs_diff_ne(&ls_x, 1e-12)); | ||
|
||
let coords_y = vec![(0., 0.), (5., 0. + delta), (10., 10.)]; | ||
let ls_y: LineString<f32> = coords_y.into_iter().collect(); | ||
assert!(ls.abs_diff_eq(&ls_y, 1e-2)); | ||
assert!(ls.abs_diff_ne(&ls_y, 1e-12)); | ||
|
||
// Undersized, but otherwise equal. | ||
let coords_x = vec![(0., 0.), (5., 0.)]; | ||
let ls_under: LineString<f32> = coords_x.into_iter().collect(); | ||
assert!(ls.abs_diff_ne(&ls_under, 1.)); | ||
|
||
// Oversized, but otherwise equal. | ||
let coords_x = vec![(0., 0.), (5., 0.), (10., 10.), (10., 100.)]; | ||
let ls_oversized: LineString<f32> = coords_x.into_iter().collect(); | ||
assert!(ls.abs_diff_ne(&ls_oversized, 1.)); | ||
} | ||
|
||
#[test] | ||
fn test_relative_eq() { | ||
let delta = 1e-6; | ||
|
||
let coords = vec![(0., 0.), (5., 0.), (10., 10.)]; | ||
let ls: LineString<f32> = coords.into_iter().collect(); | ||
|
||
let coords_x = vec![(0., 0.), (5. + delta, 0.), (10., 10.)]; | ||
let ls_x: LineString<f32> = coords_x.into_iter().collect(); | ||
assert!(ls.relative_eq(&ls_x, 1e-2, 1e-2)); | ||
assert!(ls.relative_ne(&ls_x, 1e-12, 1e-12)); | ||
|
||
let coords_y = vec![(0., 0.), (5., 0. + delta), (10., 10.)]; | ||
let ls_y: LineString<f32> = coords_y.into_iter().collect(); | ||
assert!(ls.relative_eq(&ls_y, 1e-2, 1e-2)); | ||
assert!(ls.relative_ne(&ls_y, 1e-12, 1e-12)); | ||
|
||
// Undersized, but otherwise equal. | ||
let coords_x = vec![(0., 0.), (5., 0.)]; | ||
let ls_under: LineString<f32> = coords_x.into_iter().collect(); | ||
assert!(ls.relative_ne(&ls_under, 1., 1.)); | ||
|
||
// Oversized, but otherwise equal. | ||
let coords_x = vec![(0., 0.), (5., 0.), (10., 10.), (10., 100.)]; | ||
let ls_oversized: LineString<f32> = coords_x.into_iter().collect(); | ||
assert!(ls.relative_ne(&ls_oversized, 1., 1.)); | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Comment seems like its for relative_eq not abs_diff_eq