d3_geo_rs/projection/
azimuthal_equidistant.rs1use 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#[derive(Copy, Clone, Debug, Default)]
21pub struct AzimuthalEquiDistant<T> {
22 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}