Skip to content

Commit

Permalink
Add DMS support
Browse files Browse the repository at this point in the history
  • Loading branch information
p4ken committed Jun 15, 2024
1 parent f663f34 commit 02d571c
Show file tree
Hide file tree
Showing 5 changed files with 79 additions and 25 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,5 @@ patchjgd = []
[dependencies]

[dev-dependencies]
approx = "0.5.1"
geo = "0.28.0"
45 changes: 43 additions & 2 deletions src/coord.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,40 @@ use std::ops::{Add, Mul, Sub};
// impl Sealed for super::LonLat {}
// }

/// 緯度経度
/// Latitude and longitude.
/// 度単位の緯度経度
/// Latitude and longitude in degrees.
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd)]
pub struct LatLon(pub f64, pub f64);
impl LatLon {
/// 度分秒から度に変換する。
/// Convertes degrees, minutes, seconds to decimal degrees.
///
/// # Examples
///
/// 日本緯経度原点: 東経 139°44′28.8869” 北緯 35°39′29.1572”
///
/// ```
/// use jgd::LatLon;
///
/// let origin = LatLon::from_dms((35, 39, 29.1572), (139, 44, 28.8869));
/// ```
pub fn from_dms<T: Into<Dms>>(lat: T, lon: T) -> Self {
Self(lat.into().to_degrees(), lon.into().to_degrees())
}

/// 秒から度に変換する。
/// Converts seconds to degrees.
pub fn from_secs<T: Into<f64>>(lat: T, lon: T) -> Self {
let [lat, lon] = [lat, lon].map(|x| x.into() / 3_600.);
Self(lat, lon)
}

/// ミリ秒から度に変換する。
/// Converts milliseconds to degrees.
pub fn from_milli_secs<T: Into<f64>>(lat: T, lon: T) -> Self {
Self::from_secs(lat, lon) * 0.001
}

/// マイクロ秒から度に変換する。
/// Converts microseconds to degrees.
pub fn from_micro_secs<T: Into<f64>>(lat: T, lon: T) -> Self {
Expand Down Expand Up @@ -92,6 +110,29 @@ impl From<LatLon> for (f64, f64) {
}
}

/// 度分秒。
/// Degrees, minutes, seconds.
///
/// # Examples
///
/// ```
/// use jgd::Dms;
///
/// let akashi = Dms(135, 0, 0.0);
/// ```
#[derive(Debug, Clone, PartialEq, PartialOrd)]
pub struct Dms(pub i32, pub i32, pub f64);
impl Dms {
fn to_degrees(&self) -> f64 {
f64::from(self.0) + f64::from(self.1) / 60. + self.2 / 3_600.
}
}
impl<D: Into<i32>, M: Into<i32>, S: Into<f64>> From<(D, M, S)> for Dms {
fn from((d, m, s): (D, M, S)) -> Self {
Self(d.into(), m.into(), s.into())
}
}

pub struct ECEF {}
impl ECEF {
pub fn to_geodetic() {}
Expand Down
45 changes: 29 additions & 16 deletions src/crs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::TKY2JGD;
#[cfg(feature = "patchjgd")]
use crate::TOUHOKUTAIHEIYOUOKI2011;

/// 旧日本測地系からの変換を開始する
/// 度単位の旧日本測地系から別の測地系への変換を始める
/// Transform from Tokyo Datum.
///
/// 世界測地系で測量された座標の場合は、[`Tokyo97`] ...
Expand Down Expand Up @@ -41,25 +41,33 @@ pub fn from_jgd2011(lat: f64, lon: f64) -> Jgd2000 {
///
/// EPSG: 4301
pub struct Tokyo {
lat_lon: LatLon,
degree: LatLon,
}
impl Tokyo {
// Bessel楕円体

fn new(lat_lon: impl Into<LatLon>) -> Self {
let lat_lon = lat_lon.into();
Self { lat_lon }
/// 度単位の旧日本測地系から別の測地系への変換を始める。
///
/// # Examples
///
/// ```
/// use jgd::{LatLon, Tokyo};
///
/// let degree = LatLon::from_dms((35, 0, 0.0), (135, 0, 0.0));
/// let tokyo = Tokyo::new(degree);
/// ```
///
/// <br>
///
/// すでに度単位の座標が分かっている場合は [`from_tokyo`] の方が簡単に使える。
///
/// ```
/// let tokyo = jgd::from_tokyo(35.0, 135.0);
/// ```
pub fn new(degree: LatLon) -> Self {
Self { degree }
}

// pub fn with_lon_lat(degree: impl Into<LonLat>) -> Self {
// Self::new(degree.into())
// }

// pub fn with_xy(xy: impl Into<XY>) -> Self {
// let XY(x, y) = xy.into();
// Self { lat: y, lon: x }
// }

/// [`TKY2JGD`] を用いて [`Jgd2000`] へ変換する。
/// Transform to JGD2000.
///
Expand All @@ -74,8 +82,8 @@ impl Tokyo {
/// 国土地理院によるオリジナルの実装の精度は、一定条件下で「緯度, 経度の標準偏差はそれぞれ9cm, 8cm」[(飛田, 2002)](crate#references) とされている。
#[cfg(feature = "tky2jgd")]
pub fn to_jgd2000(&self) -> Jgd2000 {
match TKY2JGD.interpolate(self.lat_lon) {
Some(shift) => Jgd2000::new(self.lat_lon + shift),
match TKY2JGD.interpolate(self.degree) {
Some(shift) => Jgd2000::new(self.degree + shift),
None => self.to_tokyo97().to_jgd2000(),
}
}
Expand Down Expand Up @@ -142,6 +150,11 @@ impl Jgd2000 {
/// 3パラメータを用いて [`Tokyo97`] へ逆変換する。
/// Inverse of [`Tokyo97::to_jgd2000`].
pub fn to_tokyo97(&self) {}

/// ...
pub fn inner(&self) -> LatLon {
self.lat_lon
}
}

/// 世界測地系。Japanese Geodetic Datum 2011 (JGD2011).
Expand Down
9 changes: 4 additions & 5 deletions src/grid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ impl MicroSecond {

#[cfg(test)]
mod tests {
use approx::assert_ulps_eq;

use super::*;

#[cfg(feature = "tky2jgd")]
Expand All @@ -144,8 +146,6 @@ mod tests {
assert_eq!(r.shift.lon, -13995610);
}

const MILLI_METER_IN_DEGREES: f64 = 0.000000009;

// 45"
// (0, 0) -- (6, 6)
// | | 30"
Expand Down Expand Up @@ -182,8 +182,7 @@ mod tests {
let sut = Grid::new(&SMALLEST);
let exp = LatLon::from_micro_secs(-2, 2);
let ret = sut.interpolate(LatLon::from_secs(10., 15.)).unwrap();
let diff = (ret - exp).abs();
assert!(diff.lat() < MILLI_METER_IN_DEGREES);
assert!(diff.lon() < MILLI_METER_IN_DEGREES);
assert_ulps_eq!(exp.lat(), ret.lat());
assert_ulps_eq!(exp.lon(), ret.lon());
}
}
4 changes: 2 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
//! 異なる測地系で整備された座標同士のズレを低減できても、ズレが消滅することはない。
//! 変換メソッド毎に精度や制約が異なり、詳細はそれぞれのドキュメントに記載されている。
//!
//! 度単位の緯度経度のみ変換可能。度分秒(DMS)、平面直角座標系(XY)は未対応。
//! 緯度経度で表される地理座標のみ変換可能。平面直角座標系(XY)は未対応。
//!
//! # Features
//!
Expand All @@ -62,7 +62,7 @@ mod grid;
mod island;
mod par;

use coord::LatLon;
pub use coord::{Dms, LatLon};
pub use crs::{
from_jgd2000, from_jgd2011, from_tokyo, from_tokyo97, Jgd2000, Jgd2011, Tokyo, Tokyo97,
};
Expand Down

0 comments on commit 02d571c

Please sign in to comment.