grid_cell/
coordinate.rs

1use crate::{First, Fourth, GridCell, Second, Third};
2
3#[derive(Clone, Copy)]
4pub struct Coordinate {
5    pub longitude: f64,
6    pub latitude: f64,
7}
8
9impl Coordinate {
10    pub fn first_cell(&self) -> GridCell<First> {
11        // lat difference of 1st cell is 40 minutes, base point is 0 degrees north-lat.
12        let degree_y = 40.0 / 60.0;
13        let y = (self.latitude / degree_y).floor();
14
15        // lon difference of 1st cell is 1 degree, base point is 0 degrees east-lon.
16        let east = self.longitude.floor();
17        let x = east - 100.0;
18        GridCell {
19            code: (x + 100.0 * y) as u64,
20            west_longitude: east,
21            south_latitude: y * degree_y,
22            phantom: Default::default(),
23        }
24    }
25
26    pub fn second_cell(&self, first: &GridCell<First>) -> GridCell<Second> {
27        // lat difference of 2nd cell is 5 minutes, base point is south-lat of 1st cell.
28        let degree_y = 5.0 / 60.0;
29        let y = ((self.latitude - first.south_latitude) / degree_y).floor();
30
31        // lon difference of 2nd cell is 7 minutes 30 seconds, base point is west-lon of 1st cell.
32        let degree_x = 7.5 / 60.0;
33        let x = ((self.longitude - first.west_longitude) / degree_x).floor();
34
35        GridCell {
36            code: first.code * 100 + (y * 10.0 + x) as u64,
37            west_longitude: first.west_longitude + x * degree_x,
38            south_latitude: first.south_latitude + y * degree_y,
39            phantom: Default::default(),
40        }
41    }
42
43    pub fn third_cell(&self, second: &GridCell<Second>) -> GridCell<Third> {
44        // lat difference of 3rd cell is 30 seconds, base point is south-lat of 2nd cell.
45        let degree_y = 30.0 / 60.0 / 60.0;
46        let y = ((self.latitude - second.south_latitude) / degree_y).floor();
47
48        // lon difference of 3rd cell is 45 seconds, base point is west-lon of 2nd cell.
49        let degree_x = 45.0 / 60.0 / 60.0;
50        let x = ((self.longitude - second.west_longitude) / degree_x).floor();
51
52        GridCell {
53            code: second.code * 100 + (y * 10.0 + x) as u64,
54            west_longitude: second.west_longitude + x * degree_x,
55            south_latitude: second.south_latitude + y * degree_y,
56            phantom: Default::default(),
57        }
58    }
59
60    pub fn fourth_cell(&self, third: &GridCell<Third>) -> GridCell<Fourth> {
61        // lat difference of 4th cell is 15 seconds, base point is south-lat of 3rd cell.
62        let degree_y = 15.0 / 60.0 / 60.0;
63        let y = ((self.latitude - third.south_latitude) / degree_y).floor();
64
65        // lon difference of 4th cell is 22.5 seconds, base point is west-lon of 3rd cell.
66        let degree_x = 22.5 / 60.0 / 60.0;
67        let x = ((self.longitude - third.west_longitude) / degree_x).floor();
68
69        // suffix of 4th cell is (SW:1, SE:2, NW:3, NE:4).
70        let code = (x + 1.0) + y * 2.0;
71        GridCell {
72            code: third.code * 10 + (code as u64),
73            west_longitude: third.west_longitude + x * degree_x,
74            south_latitude: third.south_latitude + y * degree_y,
75            phantom: Default::default(),
76        }
77    }
78}