mod bearing;
mod destination;
mod distance;
#[cfg(test)]
mod distance_fast_tests;
use super::super::{Distance, InterpolatePoint};
use crate::line_measures::densify::densify_between;
use crate::{CoordFloat, Point};
use num_traits::FromPrimitive;
pub struct Euclidean;
impl<F: CoordFloat + FromPrimitive> InterpolatePoint<F> for Euclidean {
fn point_at_distance_between(
&self,
start: Point<F>,
end: Point<F>,
distance_from_start: F,
) -> Point<F> {
let diff = end - start;
let total_distance = diff.x().hypot(diff.y());
let offset = diff * distance_from_start / total_distance;
start + offset
}
fn point_at_ratio_between(
&self,
start: Point<F>,
end: Point<F>,
ratio_from_start: F,
) -> Point<F> {
let diff = end - start;
start + diff * ratio_from_start
}
fn points_along_line(
&self,
start: Point<F>,
end: Point<F>,
max_distance: F,
include_ends: bool,
) -> impl Iterator<Item = Point<F>> {
let mut container = vec![];
if include_ends {
container.push(start);
}
densify_between(self, start, end, &mut container, max_distance);
if include_ends {
container.push(end);
}
container.into_iter()
}
}
#[cfg(test)]
mod tests {
use super::*;
mod distance {
use super::*;
#[test]
fn new_york_to_london() {
let new_york_city = Point::new(-8238310.24, 4942194.78);
let london = Point::new(-14226.63, 6678077.70);
let distance: f64 = Euclidean.distance(new_york_city, london);
assert_relative_eq!(
8_405_286., distance.round()
);
}
#[test]
fn test_point_at_distance_between() {
let new_york_city = Point::new(-8_238_310.24, 4_942_194.78);
let london = Point::new(-14_226.63, 6_678_077.70);
let start = Euclidean.point_at_distance_between(new_york_city, london, 0.0);
assert_relative_eq!(new_york_city, start);
let midway =
Euclidean.point_at_distance_between(new_york_city, london, 8_405_286.0 / 2.0);
assert_relative_eq!(Point::new(-4_126_268., 5_810_136.), midway, epsilon = 1.0);
let end = Euclidean.point_at_distance_between(new_york_city, london, 8_405_286.0);
assert_relative_eq!(london, end, epsilon = 1.0);
}
}
}