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::{
40 TryFromSlice, def::grib2::template::param_set::ScaledValue, test_utils::decompress_to_vec,
41 };
42
43 #[test]
44 fn radii_for_shape_1() -> Result<(), Box<dyn std::error::Error>> {
45 let buf = decompress_to_vec(crate::test_utils::data::grib2::NOAA_NDFD_CRITFIREO)?;
46 let mut pos = 0x83;
47 let earth_actual = EarthShape::try_from_slice(&buf, &mut pos)?;
48 let earth_expected = EarthShape {
49 shape: 1,
50 spherical_earth_radius: ScaledValue {
51 scale_factor: 0,
52 scaled_value: 6371200,
53 },
54 major_axis: ScaledValue {
55 scale_factor: 0,
56 scaled_value: 0,
57 },
58 minor_axis: ScaledValue {
59 scale_factor: 0,
60 scaled_value: 0,
61 },
62 };
63 assert_eq!(earth_actual, earth_expected);
64 assert_eq!(earth_actual.radii(), Some((6_371_200., 6_371_200.)));
65
66 Ok(())
67 }
68
69 #[test]
70 fn radii_for_shape_2() -> Result<(), Box<dyn std::error::Error>> {
71 let buf = decompress_to_vec(crate::test_utils::data::grib2::NOAA_MRMS_REFLECTIVITY)?;
72 let mut pos = 0x33;
73 let earth_actual = EarthShape::try_from_slice(&buf, &mut pos)?;
74 let earth_expected = EarthShape {
75 shape: 2,
76 spherical_earth_radius: ScaledValue {
77 scale_factor: 1,
78 scaled_value: 6367470,
79 },
80 major_axis: ScaledValue {
81 scale_factor: 1,
82 scaled_value: 6378160,
83 },
84 minor_axis: ScaledValue {
85 scale_factor: 1,
86 scaled_value: 6356775,
87 },
88 };
89 assert_eq!(earth_actual, earth_expected);
90 assert_eq!(earth_actual.radii(), Some((6_378_160.0, 6_356_775.0)));
91
92 Ok(())
93 }
94
95 #[test]
96 fn radii_for_shape_4() -> Result<(), Box<dyn std::error::Error>> {
97 let buf = decompress_to_vec(crate::test_utils::data::grib2::JMA_TORNADO_NOWCAST)?;
98 let mut pos = 0x33;
99 let earth_actual = EarthShape::try_from_slice(&buf, &mut pos)?;
100 let earth_expected = EarthShape {
101 shape: 4,
102 spherical_earth_radius: ScaledValue {
103 scale_factor: 0xff,
104 scaled_value: 0xffffffff,
105 },
106 major_axis: ScaledValue {
107 scale_factor: 1,
108 scaled_value: 63781370,
109 },
110 minor_axis: ScaledValue {
111 scale_factor: 1,
112 scaled_value: 63567523,
113 },
114 };
115 assert_eq!(earth_actual, earth_expected);
116 assert_eq!(earth_actual.radii(), Some((6_378_137.0, 6_356_752.314)));
117
118 Ok(())
119 }
120
121 #[test]
122 fn radii_for_shape_6() -> Result<(), Box<dyn std::error::Error>> {
123 let buf = decompress_to_vec(crate::test_utils::data::grib2::NOAA_GDAS_0_10)?;
124 let mut pos = 0x33;
125 let earth_actual = EarthShape::try_from_slice(&buf, &mut pos)?;
126 let earth_expected = EarthShape {
127 shape: 6,
128 spherical_earth_radius: ScaledValue {
129 scale_factor: 0,
130 scaled_value: 0,
131 },
132 major_axis: ScaledValue {
133 scale_factor: 0,
134 scaled_value: 0,
135 },
136 minor_axis: ScaledValue {
137 scale_factor: 0,
138 scaled_value: 0,
139 },
140 };
141 assert_eq!(earth_actual, earth_expected);
142 assert_eq!(earth_actual.radii(), Some((6_371_229.0, 6_371_229.0)));
143
144 Ok(())
145 }
146}