Skip to main content

kasane_logic/geometry/point/ecef/
impls.rs

1use std::{fmt, ops::Sub};
2
3use crate::{
4    Coordinate, Ecef, Error, MAX_ZOOM_LEVEL, Point, SpatialIdError, WGS84_A, WGS84_E2, WGS84_F,
5    geometry::traits::CoverSingleIds,
6};
7
8impl fmt::Debug for Ecef {
9    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
10        f.debug_struct("Ecef")
11            .field("x", &self.x)
12            .field("y", &self.y)
13            .field("z", &self.z)
14            .finish()
15    }
16}
17
18impl TryFrom<Ecef> for Coordinate {
19    type Error = Error;
20    /// 地心直交座標系(ECEF)から地理座標(緯度・経度・高度)への変換。
21    fn try_from(value: Ecef) -> Result<Self, Self::Error> {
22        let x = value.x;
23        let y = value.y;
24        let z = value.z;
25
26        let lon = y.atan2(x);
27        let p = (x * x + y * y).sqrt();
28
29        // 緯度の初期値(Bowring)
30        let mut lat = (z / p).atan2(1.0 - WGS84_F);
31        let mut h = 0.0;
32
33        for _ in 0..10 {
34            let sin_lat = lat.sin();
35            let n = WGS84_A / (1.0 - WGS84_E2 * sin_lat * sin_lat).sqrt();
36            h = p / lat.cos() - n;
37
38            let new_lat = (z + WGS84_E2 * n * sin_lat).atan2(p);
39
40            if (new_lat - lat).abs() < 1e-12 {
41                lat = new_lat;
42                break;
43            }
44            lat = new_lat;
45        }
46
47        Coordinate::new(lat.to_degrees(), lon.to_degrees(), h)
48    }
49}
50
51impl Point for Ecef {}
52
53impl Sub for Ecef {
54    type Output = Self;
55
56    fn sub(self, other: Self) -> Self::Output {
57        Self {
58            x: self.x - other.x,
59            y: self.y - other.y,
60            z: self.z - other.z,
61        }
62    }
63}
64
65impl CoverSingleIds for Ecef {
66    fn cover_single_ids(
67        &self,
68        z: u8,
69    ) -> Result<impl Iterator<Item = crate::SingleId>, crate::Error> {
70        if z > MAX_ZOOM_LEVEL as u8 {
71            return Err(SpatialIdError::ZOutOfRange { z }.into());
72        }
73        Ok(std::iter::once(self.single_id(z)?))
74    }
75}