3 个不稳定版本
0.2.1 | 2024年4月14日 |
---|---|
0.2.0 | 2024年4月14日 |
0.1.0 | 2023年8月14日 |
#273 in 数学
556 每月下载量
15KB
288 行
Longitude 
Rust 的坐标库。处理坐标数学很棘手,因为您正在尝试在球体(地球)上移动一个点。操纵经度相当直接,因为它只是从北极到南极的长度。纬度要复杂一些,因为地球的周长根据您距离赤道的远近而变化。当我需要处理交互式地图、三角测量等时,我会使用这个库。我在我的应用程序鲱鱼和另一个名为 Batch Watch 的应用程序中使用了它。
处理距离单位
创建一个与单位相关联的值。
use longitude::{Distance, DistanceUnit};
let distance_a = Distance::from_kilometers(10.);
let distance_b = Distance::from_miles(6.213712);
您现在可以对这些测量值执行操作,包括转换、加法、减法和标量乘法。
println!("{:?}", distance_a.convert_to(DistanceUnit::Kilometers));
在坐标上执行操作符
// Add a distance to a coordinate point:
let location_a = Location::from(40.7885447, -111.7656248);
let distance_a = Distance::from_kilometers(8.2);
let location_b = location_a.add(&distance_a, Direction::North);
let location_result = Location::from(40.8622065532978, -111.7656248);
assert!(location_b == location_result)
// Measure the distance between 2 coordinate points:
let location_a = Location::from(40.7885447, -111.7656248);
let location_b = Location::from(40.7945846, -111.6950349);
let distance_a = location_a.distance(&location_b);
let distance_b = Distance::from_kilometers(5.9868);
assert!(distance_a == distance_b);
它是如何工作的?
首先,它使用 Distance 结构体进行所有测量。这使得转换变得容易,并确保您永远不会对单位感到困惑。location 结构体存储经度和纬度。这是计算两点之间距离的方式
impl Location {
pub fn distance(&self, other: &Location) -> Distance {
let (lat1, lng1) = (self.latitude, self.longitude);
let (lat2, lng2) = (other.latitude, other.longitude);
let pi_180 = |x: f64| (x * PI) / 180.;
let d_lat = pi_180(lat2) - pi_180(lat1);
let d_lng = pi_180(lng2) - pi_180(lng1);
let a = (d_lat / 2.).sin().powf(2.) +
pi_180(lat2).cos().powf(2.) *
(d_lng / 2.).sin().powf(2.);
let c = 2. * atan2(a.sqrt(), (1. - a).sqrt());
RADIUS_OF_EARTH.clone() * c
}
}
此函数使用哈夫曼公式。(了解更多:https://en.wikipedia.org/wiki/Haversine_formula)
您还可以向坐标点添加一些距离。
pub fn add(&self, distance: &Distance, direction: Direction) -> Self
add 函数接受距离和方向。方向是北、南、东或西。如果是东或西,我们可以使用此公式
let d = distance.kilometers() / RADIUS_OF_EARTH.kilometers();
let c = 180. / PI;
let offset = d * c / (self.latitude * PI / 180.).cos();
let scalar = if direction == Direction::East { 1. } else { -1. };
Self {
latitude: self.latitude,
longitude: self.longitude + (offset * scalar),
}
我们需要三角函数,因为纬度将根据您距离赤道的距离而变化。
向南北方向添加要简单一些
let d = distance.kilometers() / RADIUS_OF_EARTH.kilometers();
let c = 180. / PI;
let offset = d * c;
let scalar = if direction == Direction::North { 1. } else { -1. };
Self {
latitude: self.latitude + (offset * scalar),
longitude: self.longitude,
}
依赖关系
~390–720KB
~15K SLoC