1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
use core::fmt::Debug;
use core::marker::PhantomData;

use geo::CoordFloat;
use geo_types::Coord;
use num_traits::FloatConst;

use crate::clip::antimeridian::gen_clip;
use crate::compose::Compose;
use crate::identity::Identity;
use crate::projection::builder::template::ResampleNoneNoPCNU;
use crate::projection::builder::template::ResampleNonePCNU;
use crate::projection::builder::types::BuilderAntimeridianResampleNoClip;
use crate::projection::builder::types::BuilderAntimeridianResampleNoneClip;
use crate::projection::builder::types::BuilderAntimeridianResampleNoneNoClip;
use crate::projection::builder::types::BuilderCircleResampleNoClip;
use crate::projection::builder::types::BuilderCircleResampleNoneNoClip;
use crate::projection::Recenter;
use crate::rot::rotate_radians;
use crate::rot::rotate_radians::RotateRadians;
use crate::rot::rotator_radians::RotatorRadians;
use crate::stream::Unconnected;
use crate::Transform;

use super::builder::template::ResampleNoPCNC;
use super::builder::template::ResampleNoPCNU;
use super::resampler::resample::Resample;
use super::transform::generate as generate_str;
use super::transform::scale_translate_rotate::ScaleTranslateRotate;
use super::BuilderTrait;

use template::ResamplePCNC;
use template::ResamplePCNU;

mod angle;
mod angle_get;
mod build;
mod center_get;
mod center_set;
mod clip_angle_adjust;
mod clip_angle_get;
mod clip_angle_reset;
mod clip_angle_set;
mod clip_extent_adjust;
mod clip_extent_clear;
mod clip_extent_get;
mod clip_extent_set;
mod fit_clip;
mod fit_no_clip;
mod precision_adjust;
mod precision_bypass;
mod precision_get;
mod precision_set;
mod recenter_no_resampling;
mod recenter_with_resampling;
mod reflect_get;
mod reflect_set;
mod rotate_get;
mod rotate_set;
mod scale_get;
mod scale_no_resampling;
mod scale_with_resampling;
mod transform;
mod translate_get;
mod translate_no_resampling;
mod translate_with_resampling;

pub mod template;
/// Builder shorthand notations.
pub mod types;

/// Projection builder state.
#[derive(Clone, Debug)]
pub struct Builder<CLIPU, DRAIN, PCNU, PR, RU, T>
where
    T: CoordFloat,
{
    p_d: PhantomData<DRAIN>,
    pub(super) projection_raw: PR,
    pub(super) clip: CLIPU,
    lambda: T,
    phi: T,
    alpha: T, // post-rotate angle
    k: T,     // scale
    sx: T,    // reflectX
    sy: T,    // reflectY

    x: T,
    y: T, // translate

    t360: T,
    delta_lambda: T,
    delta_phi: T,
    delta_gamma: T,

    delta2: T, // precision

    theta: Option<T>,

    /// Used by recenter() to build the factories.
    rotate: RotateRadians<T>,
    pub(super) rotator: RotatorRadians<Unconnected, T>, //rotate, pre-rotate
    project_transform: Compose<PR, ScaleTranslateRotate<T>>,
    /// Used by rotate_transform_factory and projections transform.
    pub(super) project_rotate_transform:
        Compose<RotateRadians<T>, Compose<PR, ScaleTranslateRotate<T>>>,

    /// Projection path stage.
    pub(super) postclip: PCNU,

    /// Projection path stage
    pub(super) resample: RU,
}

impl<DRAIN, PR, T> BuilderTrait for BuilderAntimeridianResampleNoClip<DRAIN, PR, T>
where
    PR: Clone + Transform<T = T>,
    T: 'static + CoordFloat + Default + FloatConst,
{
    type PR = PR;

    /// Given a Raw Projection and a clipping defintion create the associated
    /// Projection builder.
    ///
    /// # Panics
    /// unwrap() is used here but a panic will never happen as constants will always be converted into T.
    fn new(projection_raw: PR) -> Self {
        let x = T::from(480_f64).unwrap();
        let y = T::from(250_f64).unwrap();
        let lambda = T::zero();
        let phi = T::zero();
        let alpha = T::zero();
        let k = T::from(150_f64).unwrap();
        let sx = T::one();
        let sy = T::one();
        let t360 = T::from(360_f64).unwrap();
        let delta_lambda = T::zero();
        let delta_phi = T::zero();
        let delta_gamma = T::zero();
        let delta2 = T::from(0.5_f64).unwrap();
        let center = generate_str(&k, &T::zero(), &T::zero(), &sx, &sy, &alpha)
            .transform(&projection_raw.transform(&Coord { x: lambda, y: phi }));
        let str = generate_str(&k, &(x - center.x), &(y - center.y), &sx, &sy, &alpha);

        let rotate = rotate_radians([delta_lambda, delta_phi, delta_gamma]); // pre-rotate
        let rotator = RotatorRadians::new(rotate.clone());
        let project_transform = Compose::new(projection_raw.clone(), str);
        let project_rotate_transform = Compose::new(rotate.clone(), project_transform.clone());
        let postclip = Identity::default();
        let resample = Resample::new(project_transform.clone(), delta2);
        let mut out: Self = Self {
            p_d: PhantomData::<DRAIN>,
            clip: gen_clip(),
            /// Input passing onto Projection.
            projection_raw,

            /// Internal state.
            delta_lambda,
            delta_phi,
            delta_gamma,
            x,
            y,
            t360,

            delta2: T::from(0.5_f64).unwrap(),
            lambda,
            phi,

            alpha,
            k,
            theta: None,
            sx,
            sy,

            rotate,
            rotator,
            project_transform,
            project_rotate_transform,
            postclip,
            resample,
        };

        out.recenter();
        out
    }
}