grib/def/grib2/template3.rs
1use grib_template_derive::{Dump, TryFromSlice};
2
3/// Grid definition template 3.0 - latitude/longitude (or equidistant
4/// cylindrical, or Plate Carrée).
5#[derive(Debug, PartialEq, TryFromSlice, Dump)]
6pub struct Template3_0 {
7 pub earth: param_set::EarthShape,
8 pub lat_lon: param_set::LatLonGrid,
9}
10
11/// Grid definition template 3.1 - rotated latitude/longitude (or equidistant
12/// cylindrical, or Plate Carrée).
13///
14/// # Examples
15///
16/// ```
17/// use std::io::Read;
18///
19/// use grib::def::grib2::template::{Template3_1, param_set};
20/// use grib_template_helpers::TryFromSlice;
21///
22/// fn main() -> Result<(), Box<dyn std::error::Error>> {
23/// let mut buf = Vec::new();
24///
25/// let f = std::fs::File::open(
26/// "testdata/20260219T00Z_MSC_HRDPS_CAPE_Sfc_RLatLon0.0225_PT000H.grib2",
27/// )?;
28/// let mut f = std::io::BufReader::new(f);
29/// f.read_to_end(&mut buf)?;
30///
31/// let mut pos = 0x33;
32/// let actual = Template3_1::try_from_slice(&buf, &mut pos)?;
33/// let expected = Template3_1 {
34/// earth: param_set::EarthShape {
35/// shape: 6,
36/// spherical_earth_radius_scale_factor: 0xff,
37/// spherical_earth_radius_scaled_value: 0xffffffff,
38/// major_axis_scale_factor: 0xff,
39/// major_axis_scaled_value: 0xffffffff,
40/// minor_axis_scale_factor: 0xff,
41/// minor_axis_scaled_value: 0xffffffff,
42/// },
43/// rotated: param_set::LatLonGrid {
44/// grid: param_set::Grid {
45/// ni: 2540,
46/// nj: 1290,
47/// initial_production_domain_basic_angle: 0,
48/// basic_angle_subdivisions: 0xffffffff,
49/// first_point_lat: -12302501,
50/// first_point_lon: 345178780,
51/// resolution_and_component_flags: param_set::ResolutionAndComponentFlags(
52/// 0b00111000,
53/// ),
54/// last_point_lat: 16700001,
55/// last_point_lon: 42306283,
56/// },
57/// scanning_mode: param_set::ScanningMode(0b01000000),
58/// i_direction_inc: 22500,
59/// j_direction_inc: 22500,
60/// },
61/// rotation: param_set::Rotation {
62/// south_pole_lat: -36088520,
63/// south_pole_lon: 245305142,
64/// rot_angle: 0.,
65/// },
66/// };
67/// assert_eq!(actual, expected);
68///
69/// Ok(())
70/// }
71/// ```
72#[derive(Debug, PartialEq, TryFromSlice, Dump)]
73pub struct Template3_1 {
74 pub earth: param_set::EarthShape,
75 pub rotated: param_set::LatLonGrid,
76 pub rotation: param_set::Rotation,
77}
78
79/// Grid definition template 3.20 - polar stereographic projection.
80///
81/// # Examples
82///
83/// ```
84/// use std::io::{BufReader, Read};
85///
86/// use grib::def::grib2::template::{Template3_20, param_set};
87/// use grib_template_helpers::TryFromSlice;
88///
89/// fn main() -> Result<(), Box<dyn std::error::Error>> {
90/// let mut buf = Vec::new();
91///
92/// let f = std::fs::File::open(
93/// "testdata/CMC_RDPA_APCP-024-0100cutoff_SFC_0_ps10km_2023121806_000.grib2.xz",
94/// )?;
95/// let f = BufReader::new(f);
96/// let mut f = xz2::bufread::XzDecoder::new(f);
97/// f.read_to_end(&mut buf)?;
98///
99/// let mut pos = 0x33;
100/// let actual = Template3_20::try_from_slice(&buf, &mut pos)?;
101/// let expected = Template3_20 {
102/// earth_shape: param_set::EarthShape {
103/// shape: 6,
104/// spherical_earth_radius_scale_factor: 0xff,
105/// spherical_earth_radius_scaled_value: 0xffffffff,
106/// major_axis_scale_factor: 0xff,
107/// major_axis_scaled_value: 0xffffffff,
108/// minor_axis_scale_factor: 0xff,
109/// minor_axis_scaled_value: 0xffffffff,
110/// },
111/// ni: 935,
112/// nj: 824,
113/// first_point_lat: 18145030,
114/// first_point_lon: 217107456,
115/// resolution_and_component_flags: param_set::ResolutionAndComponentFlags(0b00001000),
116/// lad: 60000000,
117/// lov: 249000000,
118/// dx: 10000000,
119/// dy: 10000000,
120/// projection_centre: param_set::ProjectionCentreFlag(0b00000000),
121/// scanning_mode: param_set::ScanningMode(0b01000000),
122/// };
123/// assert_eq!(actual, expected);
124///
125/// Ok(())
126/// }
127/// ```
128#[derive(Debug, PartialEq, Eq, TryFromSlice, Dump)]
129pub struct Template3_20 {
130 pub earth_shape: param_set::EarthShape,
131 /// Nx - number of points along the x-axis.
132 pub ni: u32,
133 /// Ny - number of points along the y-axis.
134 pub nj: u32,
135 /// La1 - latitude of first grid point.
136 pub first_point_lat: i32,
137 /// Lo1 - longitude of first grid point.
138 pub first_point_lon: i32,
139 pub resolution_and_component_flags: param_set::ResolutionAndComponentFlags,
140 /// LaD - latitude where Dx and Dy are specified.
141 pub lad: i32,
142 /// LoV - orientation of the grid (see Note 2).
143 pub lov: i32,
144 /// Dx - x-direction grid length (see Note 3).
145 pub dx: u32,
146 /// Dy - y-direction grid length (see Note 3).
147 pub dy: u32,
148 pub projection_centre: param_set::ProjectionCentreFlag,
149 pub scanning_mode: param_set::ScanningMode,
150}
151
152/// Grid definition template 3.30 - Lambert conformal.
153///
154/// # Examples
155///
156/// ```
157/// use std::io::{BufReader, Read};
158///
159/// use grib::def::grib2::template::{Template3_30, param_set};
160/// use grib_template_helpers::TryFromSlice;
161///
162/// fn main() -> Result<(), Box<dyn std::error::Error>> {
163/// let mut buf = Vec::new();
164///
165/// let f = std::fs::File::open("testdata/ds.critfireo.bin.xz")?;
166/// let f = BufReader::new(f);
167/// let mut f = xz2::bufread::XzDecoder::new(f);
168/// f.read_to_end(&mut buf)?;
169///
170/// let mut pos = 0x83;
171/// let actual = Template3_30::try_from_slice(&buf, &mut pos)?;
172/// let expected = Template3_30 {
173/// earth_shape: param_set::EarthShape {
174/// shape: 1,
175/// spherical_earth_radius_scale_factor: 0,
176/// spherical_earth_radius_scaled_value: 6371200,
177/// major_axis_scale_factor: 0,
178/// major_axis_scaled_value: 0,
179/// minor_axis_scale_factor: 0,
180/// minor_axis_scaled_value: 0,
181/// },
182/// ni: 2145,
183/// nj: 1377,
184/// first_point_lat: 20190000,
185/// first_point_lon: 238449996,
186/// resolution_and_component_flags: param_set::ResolutionAndComponentFlags(0b00000000),
187/// lad: 25000000,
188/// lov: 265000000,
189/// dx: 2539703,
190/// dy: 2539703,
191/// projection_centre: param_set::ProjectionCentreFlag(0b00000000),
192/// scanning_mode: param_set::ScanningMode(0b01010000),
193/// latin1: 25000000,
194/// latin2: 25000000,
195/// south_pole_lat: -90000000,
196/// south_pole_lon: 0,
197/// };
198/// assert_eq!(actual, expected);
199///
200/// Ok(())
201/// }
202/// ```
203#[derive(Debug, PartialEq, Eq, TryFromSlice, Dump)]
204pub struct Template3_30 {
205 pub earth_shape: param_set::EarthShape,
206 /// Nx - number of points along the x-axis.
207 pub ni: u32,
208 /// Ny - number of points along the y-axis.
209 pub nj: u32,
210 /// La1 - latitude of first grid point.
211 pub first_point_lat: i32,
212 /// Lo1 - longitude of first grid point.
213 pub first_point_lon: i32,
214 pub resolution_and_component_flags: param_set::ResolutionAndComponentFlags,
215 /// LaD - latitude where Dx and Dy are specified.
216 pub lad: i32,
217 /// LoV - longitude of meridian parallel to y-axis along which latitude
218 /// increases as the y-coordinate increases.
219 pub lov: i32,
220 /// Dx - x-direction grid length (see Note 1).
221 pub dx: u32,
222 /// Dy - y-direction grid length (see Note 1).
223 pub dy: u32,
224 pub projection_centre: param_set::ProjectionCentreFlag,
225 pub scanning_mode: param_set::ScanningMode,
226 /// Latin 1 - first latitude from the pole at which the secant cone cuts the
227 /// sphere.
228 pub latin1: i32,
229 /// Latin 2 - second latitude from the pole at which the secant cone cuts
230 /// the sphere.
231 pub latin2: i32,
232 /// Latitude of the southern pole of projection.
233 pub south_pole_lat: i32,
234 /// Longitude of the southern pole of projection.
235 pub south_pole_lon: i32,
236}
237
238/// Grid definition template 3.40 - Gaussian latitude/longitude.
239#[derive(Debug, PartialEq, TryFromSlice, Dump)]
240pub struct Template3_40 {
241 pub earth: param_set::EarthShape,
242 pub gaussian: param_set::GaussianGrid,
243}
244
245pub(crate) mod param_set {
246 use grib_template_derive::{Dump, TryFromSlice};
247
248 #[derive(Debug, PartialEq, Eq, TryFromSlice, Dump)]
249 pub struct EarthShape {
250 /// Shape of the Earth (see Code table 3.2).
251 pub shape: u8,
252 /// Scale factor of radius of spherical Earth.
253 pub spherical_earth_radius_scale_factor: u8,
254 /// Scaled value of radius of spherical Earth.
255 pub spherical_earth_radius_scaled_value: u32,
256 /// Scale factor of major axis of oblate spheroid Earth.
257 pub major_axis_scale_factor: u8,
258 /// Scaled value of major axis of oblate spheroid Earth.
259 pub major_axis_scaled_value: u32,
260 /// Scale factor of minor axis of oblate spheroid Earth.
261 pub minor_axis_scale_factor: u8,
262 /// Scaled value of minor axis of oblate spheroid Earth.
263 pub minor_axis_scaled_value: u32,
264 }
265
266 #[derive(Debug, PartialEq, Eq, TryFromSlice, Dump)]
267 pub struct LatLonGrid {
268 pub grid: Grid,
269 /// Di - i direction increment (see Notes 1 and 5).
270 pub i_direction_inc: u32,
271 /// Dj - j direction increment (see Notes 1 and 5).
272 pub j_direction_inc: u32,
273 pub scanning_mode: ScanningMode,
274 }
275
276 #[derive(Debug, PartialEq, Eq, TryFromSlice, Dump)]
277 pub struct GaussianGrid {
278 pub grid: Grid,
279 /// Di - i direction increment (see Notes 1 and 5).
280 pub i_direction_inc: u32,
281 /// N - number of parallels between a pole and the Equator (see Note 2).
282 pub n: u32,
283 pub scanning_mode: ScanningMode,
284 }
285
286 #[derive(Debug, PartialEq, Eq, TryFromSlice, Dump)]
287 pub struct Grid {
288 /// Ni - number of points along a parallel.
289 pub ni: u32,
290 /// Nj - number of points along a meridian.
291 pub nj: u32,
292 /// Basic angle of the initial production domain (see Note 1).
293 pub initial_production_domain_basic_angle: u32,
294 /// Subdivisions of basic angle used to define extreme longitudes and
295 /// latitudes, and direction increments (see Note 1).
296 pub basic_angle_subdivisions: u32,
297 /// La1 - latitude of first grid point (see Note 1).
298 pub first_point_lat: i32,
299 /// Lo1 - longitude of first grid point (see Note 1).
300 pub first_point_lon: i32,
301 pub resolution_and_component_flags: ResolutionAndComponentFlags,
302 /// La2 - latitude of last grid point (see Note 1).
303 pub last_point_lat: i32,
304 /// Lo2 - longitude of last grid point (see Note 1).
305 pub last_point_lon: i32,
306 }
307
308 #[derive(Debug, PartialEq, Eq, Clone, Copy, TryFromSlice, Dump)]
309 pub struct ProjectionCentreFlag(
310 /// Projection centre flag (see Flag table 3.5).
311 pub u8,
312 );
313
314 #[derive(Debug, PartialEq, Eq, Clone, Copy, TryFromSlice, Dump)]
315 pub struct ResolutionAndComponentFlags(
316 /// Resolution and component flags (see Flag table 3.3).
317 pub u8,
318 );
319
320 #[derive(Debug, PartialEq, TryFromSlice, Dump)]
321 pub struct Rotation {
322 /// Latitude of the southern pole of projection.
323 pub south_pole_lat: i32,
324 /// Longitude of the southern pole of projection.
325 pub south_pole_lon: i32,
326 /// Angle of rotation of projection.
327 pub rot_angle: f32,
328 }
329
330 #[derive(Debug, PartialEq, Eq, Clone, Copy, TryFromSlice, Dump)]
331 pub struct ScanningMode(
332 /// Scanning mode (flags - see Flag table 3.4).
333 pub u8,
334 );
335}