Skip to content

Commit

Permalink
un-genericify CrossTrackDistance to avoid the breaking change for now
Browse files Browse the repository at this point in the history
  • Loading branch information
michaelkirk committed Oct 31, 2024
1 parent 36086ab commit 9f1de76
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 26 deletions.
2 changes: 1 addition & 1 deletion geo/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

## Unreleased

* BREAKING: Make `CrossTrackDistance` generic both to clarify when it is using Haversine, but also implement it for Euclidean.
* Add `Haversine:distance` for Line vs. Point (same as CrossTrackDistance)

## 0.29.0 - 2024.10.30

Expand Down
35 changes: 10 additions & 25 deletions geo/src/algorithm/cross_track_distance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ use num_traits::FromPrimitive;

/// Determine the cross track distance (also known as the cross track error) which is the shortest
/// distance between a point and a continuous line.
///
/// Distance is measured in meters, using the Haversine formula.
pub trait CrossTrackDistance<T, Rhs = Self>
where
T: CoordFloat + FromPrimitive,
Expand Down Expand Up @@ -37,24 +39,15 @@ where
/// distance.round()
/// );
/// ```
fn cross_track_distance<MetricSpace>(&self, line_point_a: &Rhs, line_point_b: &Rhs) -> T
where
MetricSpace: for<'a> Distance<T, &'a Line<T>, &'a Point<T>>;
fn cross_track_distance(&self, line_point_a: &Rhs, line_point_b: &Rhs) -> T;
}

impl<T> CrossTrackDistance<T, Point<T>> for Point<T>
where
T: CoordFloat + FromPrimitive,
{
fn cross_track_distance<MetricSpace>(
&self,
line_point_a: &Point<T>,
line_point_b: &Point<T>,
) -> T
where
MetricSpace: for<'a> Distance<T, &'a Line<T>, &'a Point<T>>,
{
MetricSpace::distance(&Line::new(*line_point_a, *line_point_b), self)
fn cross_track_distance(&self, line_point_a: &Point<T>, line_point_b: &Point<T>) -> T {
crate::Haversine::distance(&Line::new(*line_point_a, *line_point_b), self)
}
}

Expand All @@ -69,7 +62,7 @@ mod test {
let line_point_a = Point::new(-1.7297, 53.3206);
let line_point_b = Point::new(0.1334, 53.1887);
assert_relative_eq!(
p.cross_track_distance::<Haversine>(&line_point_a, &line_point_b),
p.cross_track_distance(&line_point_a, &line_point_b),
307.549995,
epsilon = 1.0e-6
);
Expand All @@ -82,7 +75,7 @@ mod test {
let line_point_b = Point::new(2., 0.);

assert_relative_eq!(
p.cross_track_distance::<Haversine>(&line_point_a, &line_point_b),
p.cross_track_distance(&line_point_a, &line_point_b),
0.,
epsilon = 1.0e-6
);
Expand All @@ -95,13 +88,13 @@ mod test {
let line_point_b = Point::new(1., 1.);

assert_relative_eq!(
p.cross_track_distance::<Haversine>(&line_point_a, &line_point_b),
p.cross_track_distance(&line_point_a, &line_point_b),
Haversine::distance(p, Point::new(1., 0.)),
epsilon = 1.0e-6
);

assert_relative_eq!(
p.cross_track_distance::<Haversine>(&line_point_b, &line_point_a),
p.cross_track_distance(&line_point_b, &line_point_a),
Haversine::distance(p, Point::new(1., 0.)),
epsilon = 1.0e-6
);
Expand All @@ -113,15 +106,7 @@ mod test {
let line_point_a = Point::new(-80.1918f64, 25.7617f64);
let line_point_b = Point::new(-120.7401f64, 47.7511f64);

let haversine_distance = p1.cross_track_distance::<Haversine>(&line_point_a, &line_point_b);
let haversine_distance = p1.cross_track_distance(&line_point_a, &line_point_b);
assert_relative_eq!(haversine_distance, 1_547_104., epsilon = 1.0);

// Same as above, but projected to EPSG:5070 to test Euclidean
let p1 = Point::new(1826303.9422258963, 2179112.0732980534);
let line_point_a = Point::new(1594077.349564382, 434470.0414052719);
let line_point_b = Point::new(-1847681.2454118263, 2992574.0850278544);

let euclidean_distance = p1.cross_track_distance::<Euclidean>(&line_point_a, &line_point_b);
assert_relative_eq!(euclidean_distance, 1_538_764., epsilon = 1.0);
}
}

0 comments on commit 9f1de76

Please sign in to comment.