use std::fmt::Debug;
use std::marker::PhantomData;
use geo::CoordFloat;
use geo_types::Coord;
use num_traits::float::FloatConst;
use crate::projection::builder::types::BuilderCircleResampleNoClip;
use crate::projection::ScaleSet;
use crate::stream::Stream;
use crate::Transform;
use super::azimuthal::azimuthal_invert;
use super::builder::Builder;
use super::ClipAngleSet;
use super::RawBase;
#[derive(Copy, Clone, Debug, Default)]
pub struct Stereographic<DRAIN, T> {
p_drain: PhantomData<DRAIN>,
p_t: PhantomData<T>,
}
impl<DRAIN, T> RawBase for Stereographic<DRAIN, T>
where
DRAIN: Clone + Default + Stream<EP = DRAIN, T = T>,
T: CoordFloat + Default + FloatConst,
{
type Builder = BuilderCircleResampleNoClip<DRAIN, Self, T>;
#[inline]
fn builder() -> Self::Builder {
let mut b = Builder::new(Self::default());
b.scale_set(T::from(250_f64).unwrap());
b.clip_angle_set(T::from(142_f64).unwrap())
}
}
impl<DRAIN, T> Stereographic<DRAIN, T>
where
T: CoordFloat + FloatConst,
{
#[inline]
fn z(z: T) -> T
where
T: CoordFloat + FloatConst,
{
T::from(2).unwrap() * z.atan()
}
}
impl<DRAIN, T> Transform for Stereographic<DRAIN, T>
where
T: CoordFloat + FloatConst,
{
type T = T;
fn transform(&self, p: &Coord<T>) -> Coord<T> {
let (sx, cx) = p.x.sin_cos();
let (sy, cy) = p.y.sin_cos();
let k = T::one() + cx * cy;
Coord {
x: cy * sx / k,
y: sy / k,
}
}
#[inline]
fn invert(&self, p: &Coord<T>) -> Coord<T> {
azimuthal_invert(p, Self::z)
}
}