d3_geo_rs/projection/
azimuthal_equidistant.rs

1use core::fmt::Debug;
2use core::marker::PhantomData;
3
4use geo::CoordFloat;
5use geo_types::Coord;
6use num_traits::float::FloatConst;
7
8use crate::projection::builder::types::BuilderCircleResampleNoClip;
9use crate::projection::builder::Builder;
10use crate::projection::RawBase;
11use crate::projection::ScaleSet;
12use crate::Transform;
13
14use super::azimuthal::azimuthal_invert;
15use super::azimuthal::azimuthal_raw;
16use super::BuilderTrait;
17use super::ClipAngleSet;
18
19/// Projection definition. ``AzimuthalEquiDistant::builder()`` returns a builder.
20#[derive(Copy, Clone, Debug, Default)]
21pub struct AzimuthalEquiDistant<T> {
22    // Why the Phantom Data is required here...
23    //
24    // The Raw trait is generic ( and the trait way of dealing with generic is to have a interior type )
25    // The implementation of Transform is generic and the type MUST be stored in relation to the Struct,
26    p_t: PhantomData<T>,
27}
28
29impl<T> RawBase for AzimuthalEquiDistant<T>
30where
31    T: 'static + CoordFloat + Default + FloatConst,
32{
33    type Builder<DRAIN: Clone> = BuilderCircleResampleNoClip<DRAIN, Self, T>;
34
35    #[inline]
36    fn builder<DRAIN: Clone>() -> Self::Builder<DRAIN> {
37        let mut b = Builder::new(Self::default());
38        b.scale_set(T::from(79.4188_f64).unwrap());
39        b.clip_angle_set(T::from(180_f64 - 1e-3).unwrap())
40    }
41}
42
43impl<T> AzimuthalEquiDistant<T>
44where
45    T: CoordFloat + FloatConst,
46{
47    #[inline]
48    fn c(c: T) -> T {
49        let c = c.acos();
50        if c == T::zero() {
51            c
52        } else {
53            c / c.sin()
54        }
55    }
56
57    #[inline]
58    const fn z(z: T) -> T {
59        z
60    }
61}
62
63impl<T> Transform for AzimuthalEquiDistant<T>
64where
65    T: CoordFloat + FloatConst,
66{
67    type T = T;
68
69    #[inline]
70    fn transform(&self, p: &Coord<T>) -> Coord<T> {
71        azimuthal_raw(p, Self::c)
72    }
73
74    #[inline]
75    fn invert(&self, p: &Coord<T>) -> Coord<T> {
76        azimuthal_invert(p, Self::z)
77    }
78}