Skip to main content

kasane_logic/geometry/point/coordinate/
impls.rs

1use crate::{
2    Coordinate, Ecef, MAX_ZOOM_LEVEL, Point, SpatialIdError, WGS84_A, WGS84_E2,
3    geometry::traits::CoverSingleIds,
4};
5use std::fmt;
6
7impl fmt::Debug for Coordinate {
8    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
9        f.debug_struct("Coordinate")
10            .field("latitude", &self.latitude)
11            .field("longitude", &self.longitude)
12            .field("altitude", &self.altitude)
13            .finish()
14    }
15}
16
17impl From<Coordinate> for Ecef {
18    /// [`Coordinate`]を[`Ecef`]への変換。
19    /// ```
20    /// # use kasane_logic::{Coordinate,Ecef};
21    /// let coord = Coordinate::new(43.068564, 41.3507138, 30.0).unwrap();
22    /// let ecef: Ecef = coord.into();
23    /// print!("{},{},{}", ecef.x(), ecef.y(), ecef.z());
24    /// assert_eq!(ecef.x(), 3503254.6369501497);
25    /// assert_eq!(ecef.y(), 3083182.6924748584);
26    /// assert_eq!(ecef.z(), 4333089.862951963);
27    /// ```
28
29    fn from(value: Coordinate) -> Self {
30        let lat = value.latitude.to_radians();
31        let lon = value.longitude.to_radians();
32        let h = value.altitude;
33
34        let sin_lat = lat.sin();
35        let cos_lat = lat.cos();
36        let sin_lon = lon.sin();
37        let cos_lon = lon.cos();
38
39        let n = WGS84_A / (1.0 - WGS84_E2 * sin_lat * sin_lat).sqrt();
40
41        let x = (n + h) * cos_lat * cos_lon;
42        let y = (n + h) * cos_lat * sin_lon;
43        let z = (n * (1.0 - WGS84_E2) + h) * sin_lat;
44
45        Ecef::new(x, y, z)
46    }
47}
48
49/// 緯度・経度・高度のすべてが `0.0` に設定された座標を返す。
50impl Default for Coordinate {
51    fn default() -> Self {
52        Self {
53            latitude: 0.0,
54            longitude: 0.0,
55            altitude: 0.0,
56        }
57    }
58}
59
60impl Point for Coordinate {}
61
62impl CoverSingleIds for Coordinate {
63    fn cover_single_ids(
64        &self,
65        z: u8,
66    ) -> Result<impl Iterator<Item = crate::SingleId>, crate::Error> {
67        if z > MAX_ZOOM_LEVEL as u8 {
68            return Err(SpatialIdError::ZOutOfRange { z }.into());
69        }
70        Ok(std::iter::once(self.single_id(z)?))
71    }
72}