1use crate::def::grib2::template::param_set::EarthShape;
2
3impl EarthShape {
4 pub fn radii(&self) -> Option<(f64, f64)> {
5 let radii = match self.shape {
6 0 => (6367470.0, 6367470.0),
7 1 => {
8 let radius = f64::from(self.spherical_earth_radius_scaled_value)
9 * f64::powf(10., f64::from(self.spherical_earth_radius_scale_factor));
10 (radius, radius)
11 }
12 2 => (6378160.0, 6356775.0),
13 3 => {
14 let (major, minor) = self.radii_defined();
15 (major * 1000., minor * 1000.)
16 }
17 4 => (6378137.0, 6356752.314),
18 5 => (6378137.0, 6356752.3142), 6 => (6371229.0, 6371229.0),
20 7 => self.radii_defined(),
21 8 => (6371200.0, 6371200.0),
22 9.. => return None,
23 };
24 Some(radii)
25 }
26
27 fn radii_defined(&self) -> (f64, f64) {
28 let major = f64::from(self.major_axis_scaled_value)
29 * f64::powf(10., f64::from(self.major_axis_scale_factor));
30 let minor = f64::from(self.minor_axis_scaled_value)
31 * f64::powf(10., f64::from(self.minor_axis_scale_factor));
32 (major, minor)
33 }
34}
35
36#[cfg(test)]
37mod tests {
38 use super::*;
39 use crate::{TryFromSlice, test_utils::decompress_to_vec};
40
41 #[test]
42 fn radii_for_shape_1() -> Result<(), Box<dyn std::error::Error>> {
43 let buf = decompress_to_vec(crate::test_utils::data::grib2::NOAA_NDFD_CRITFIREO)?;
44 let mut pos = 0x83;
45 let earth_actual = EarthShape::try_from_slice(&buf, &mut pos)?;
46 let earth_expected = EarthShape {
47 shape: 1,
48 spherical_earth_radius_scale_factor: 0,
49 spherical_earth_radius_scaled_value: 6371200,
50 major_axis_scale_factor: 0,
51 major_axis_scaled_value: 0,
52 minor_axis_scale_factor: 0,
53 minor_axis_scaled_value: 0,
54 };
55 assert_eq!(earth_actual, earth_expected);
56 assert_eq!(earth_actual.radii(), Some((6_371_200., 6_371_200.)));
57
58 Ok(())
59 }
60
61 #[test]
62 fn radii_for_shape_2() -> Result<(), Box<dyn std::error::Error>> {
63 let buf = decompress_to_vec(crate::test_utils::data::grib2::NOAA_MRMS_REFLECTIVITY)?;
64 let mut pos = 0x33;
65 let earth_actual = EarthShape::try_from_slice(&buf, &mut pos)?;
66 let earth_expected = EarthShape {
67 shape: 2,
68 spherical_earth_radius_scale_factor: 1,
69 spherical_earth_radius_scaled_value: 6367470,
70 major_axis_scale_factor: 1,
71 major_axis_scaled_value: 6378160,
72 minor_axis_scale_factor: 1,
73 minor_axis_scaled_value: 6356775,
74 };
75 assert_eq!(earth_actual, earth_expected);
76 assert_eq!(earth_actual.radii(), Some((6_378_160.0, 6_356_775.0)));
77
78 Ok(())
79 }
80
81 #[test]
82 fn radii_for_shape_4() -> Result<(), Box<dyn std::error::Error>> {
83 let buf = decompress_to_vec(crate::test_utils::data::grib2::JMA_TORNADO_NOWCAST)?;
84 let mut pos = 0x33;
85 let earth_actual = EarthShape::try_from_slice(&buf, &mut pos)?;
86 let earth_expected = EarthShape {
87 shape: 4,
88 spherical_earth_radius_scale_factor: 0xff,
89 spherical_earth_radius_scaled_value: 0xffffffff,
90 major_axis_scale_factor: 1,
91 major_axis_scaled_value: 63781370,
92 minor_axis_scale_factor: 1,
93 minor_axis_scaled_value: 63567523,
94 };
95 assert_eq!(earth_actual, earth_expected);
96 assert_eq!(earth_actual.radii(), Some((6_378_137.0, 6_356_752.314)));
97
98 Ok(())
99 }
100
101 #[test]
102 fn radii_for_shape_6() -> Result<(), Box<dyn std::error::Error>> {
103 let buf = decompress_to_vec(crate::test_utils::data::grib2::NOAA_GDAS_0_10)?;
104 let mut pos = 0x33;
105 let earth_actual = EarthShape::try_from_slice(&buf, &mut pos)?;
106 let earth_expected = EarthShape {
107 shape: 6,
108 spherical_earth_radius_scale_factor: 0,
109 spherical_earth_radius_scaled_value: 0,
110 major_axis_scale_factor: 0,
111 major_axis_scaled_value: 0,
112 minor_axis_scale_factor: 0,
113 minor_axis_scaled_value: 0,
114 };
115 assert_eq!(earth_actual, earth_expected);
116 assert_eq!(earth_actual.radii(), Some((6_371_229.0, 6_371_229.0)));
117
118 Ok(())
119 }
120}