#coordinates #maps #mapping

longitude

在 Rust 中处理现实世界坐标!

3 个不稳定版本

0.2.1 2024年4月14日
0.2.0 2024年4月14日
0.1.0 2023年8月14日

#273 in 数学

Download history 4/week @ 2024-05-17 4/week @ 2024-05-24 6/week @ 2024-06-28 15/week @ 2024-07-05 99/week @ 2024-07-19 303/week @ 2024-07-26 77/week @ 2024-08-02 77/week @ 2024-08-09

556 每月下载量

MIT 许可证

15KB
288

Longitude crates.io

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