geometry_algorithm/
destination.rs1use geometry_cs::CoordinateSystem;
7use geometry_strategy::{DefaultDestination, DefaultDestinationStrategy, DestinationStrategy};
8use geometry_trait::Point;
9
10type Family<P> = <<P as Point>::Cs as CoordinateSystem>::Family;
11
12#[inline]
18#[must_use]
19pub fn destination<P>(
20 origin: &P,
21 bearing: f64,
22 distance: f64,
23) -> <DefaultDestinationStrategy<P> as DestinationStrategy<P>>::Output
24where
25 P: Point,
26 Family<P>: DefaultDestination<Family<P>>,
27 DefaultDestinationStrategy<P>: DestinationStrategy<P> + Default,
28{
29 DefaultDestinationStrategy::<P>::default().destination(origin, bearing, distance)
30}
31
32#[inline]
34#[must_use]
35#[allow(
36 clippy::needless_pass_by_value,
37 reason = "direct strategies are small Copy configuration values, matching other _with entries"
38)]
39pub fn destination_with<P, S>(origin: &P, bearing: f64, distance: f64, strategy: S) -> S::Output
40where
41 P: Point,
42 S: DestinationStrategy<P>,
43{
44 strategy.destination(origin, bearing, distance)
45}
46
47#[cfg(all(test, feature = "std"))]
48mod tests {
49 use super::{destination, destination_with};
50 use geometry_cs::{Degree, Geographic, Spherical};
51 use geometry_model::Point2D;
52 use geometry_strategy::{Haversine, VincentyDirect};
53 use geometry_trait::Point as _;
54
55 #[test]
56 fn spherical_and_geographic_defaults_return_input_units() {
57 type SphericalPoint = Point2D<f64, Spherical<Degree>>;
58 type GeographicPoint = Point2D<f64, Geographic<Degree>>;
59
60 let spherical = destination(
61 &SphericalPoint::new(0.0, 0.0),
62 core::f64::consts::FRAC_PI_2,
63 Haversine::EARTH.radius,
64 );
65 assert!((spherical.get::<0>().to_radians() - 1.0).abs() < 1e-12);
66
67 let geographic = destination_with(
68 &GeographicPoint::new(0.0, 0.0),
69 core::f64::consts::FRAC_PI_2,
70 100_000.0,
71 VincentyDirect::WGS84,
72 );
73 assert!((geographic.get::<0>() - 0.898_315_284_1).abs() < 1e-6);
74 }
75}