1use helpers::RegularGridIterator;
2
3pub use self::{
4 earth::EarthShapeDefinition,
5 gaussian::{compute_gaussian_latitudes, GaussianGridDefinition},
6 lambert::LambertGridDefinition,
7 latlon::LatLonGridDefinition,
8 polar_stereographic::PolarStereographicGridDefinition,
9};
10
11#[derive(Clone)]
19pub enum GridPointIterator {
20 LatLon(RegularGridIterator),
21 Lambert(std::vec::IntoIter<(f32, f32)>),
22}
23
24impl Iterator for GridPointIterator {
25 type Item = (f32, f32);
26
27 fn next(&mut self) -> Option<Self::Item> {
28 match self {
29 Self::LatLon(iter) => iter.next(),
30 Self::Lambert(iter) => iter.next(),
31 }
32 }
33
34 fn size_hint(&self) -> (usize, Option<usize>) {
35 match self {
36 Self::LatLon(iter) => iter.size_hint(),
37 Self::Lambert(iter) => iter.size_hint(),
38 }
39 }
40}
41
42#[derive(Clone)]
49pub struct GridPointIndexIterator {
50 major_len: usize,
51 minor_len: usize,
52 scanning_mode: ScanningMode,
53 major_pos: usize,
54 minor_pos: usize,
55 increments: bool,
56}
57
58impl GridPointIndexIterator {
59 pub(crate) fn new(i_len: usize, j_len: usize, scanning_mode: ScanningMode) -> Self {
60 let (major_len, minor_len) = if scanning_mode.is_consecutive_for_i() {
61 (j_len, i_len)
62 } else {
63 (i_len, j_len)
64 };
65
66 Self {
67 major_len,
68 minor_len,
69 scanning_mode,
70 minor_pos: 0,
71 major_pos: 0,
72 increments: true,
73 }
74 }
75}
76
77impl Iterator for GridPointIndexIterator {
78 type Item = (usize, usize);
79
80 fn next(&mut self) -> Option<Self::Item> {
81 if self.major_pos == self.major_len {
82 return None;
83 }
84
85 let minor = if self.increments {
86 self.minor_pos
87 } else {
88 self.minor_len - self.minor_pos - 1
89 };
90 let major = self.major_pos;
91
92 self.minor_pos += 1;
93 if self.minor_pos == self.minor_len {
94 self.major_pos += 1;
95 self.minor_pos = 0;
96 if self.scanning_mode.scans_alternating_rows() {
97 self.increments = !self.increments;
98 }
99 }
100
101 if self.scanning_mode.is_consecutive_for_i() {
102 Some((minor, major))
103 } else {
104 Some((major, minor))
105 }
106 }
107
108 fn size_hint(&self) -> (usize, Option<usize>) {
109 let len = (self.major_len - self.major_pos) * self.minor_len - self.minor_pos;
110 (len, Some(len))
111 }
112}
113
114#[derive(Debug, PartialEq, Eq, Clone, Copy)]
115pub struct ScanningMode(pub u8);
116
117impl ScanningMode {
118 pub fn scans_positively_for_i(&self) -> bool {
130 self.0 & 0b10000000 == 0
131 }
132
133 pub fn scans_positively_for_j(&self) -> bool {
145 self.0 & 0b01000000 != 0
146 }
147
148 pub fn is_consecutive_for_i(&self) -> bool {
157 self.0 & 0b00100000 == 0
158 }
159
160 pub fn scans_alternating_rows(&self) -> bool {
171 self.0 & 0b00010000 != 0
172 }
173
174 pub(crate) fn has_unsupported_flags(&self) -> bool {
175 self.0 & 0b00001111 != 0
176 }
177}
178
179#[derive(Debug, PartialEq, Eq, Clone, Copy)]
180pub struct ProjectionCentreFlag(pub u8);
181
182impl ProjectionCentreFlag {
183 pub fn contains_north_pole_on_projection_plane(&self) -> bool {
195 self.0 & 0b10000000 == 0
196 }
197
198 pub fn is_bipolar(&self) -> bool {
207 self.0 & 0b01000000 != 0
208 }
209
210 #[allow(dead_code)]
211 pub(crate) fn has_unsupported_flags(&self) -> bool {
212 self.0 & 0b00111111 != 0
213 }
214}
215
216mod earth;
217mod gaussian;
218mod helpers;
219mod lambert;
220mod latlon;
221mod polar_stereographic;