Skip to main content

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}