solverforge_maps/routing/
coord.rs1use serde::{Deserialize, Serialize};
4
5use super::error::CoordError;
6
7#[derive(Debug, Clone, Copy, PartialEq, Default, Serialize, Deserialize)]
8pub struct Coord {
9 pub lat: f64,
10 pub lng: f64,
11}
12
13impl Coord {
14 #[inline]
24 pub fn new(lat: f64, lng: f64) -> Self {
25 match Self::try_new(lat, lng) {
26 Ok(coord) => coord,
27 Err(e) => panic!("invalid coordinate: {}", e),
28 }
29 }
30
31 #[inline]
39 pub fn try_new(lat: f64, lng: f64) -> Result<Self, CoordError> {
40 if lat.is_nan() {
41 return Err(CoordError::LatNaN);
42 }
43
44 if lng.is_nan() {
45 return Err(CoordError::LngNaN);
46 }
47
48 if lat.is_infinite() {
49 return Err(CoordError::LatInfinite { value: lat });
50 }
51
52 if lng.is_infinite() {
53 return Err(CoordError::LngInfinite { value: lng });
54 }
55
56 if !(-90.0..=90.0).contains(&lat) {
57 return Err(CoordError::LatOutOfRange { value: lat });
58 }
59
60 if !(-180.0..=180.0).contains(&lng) {
61 return Err(CoordError::LngOutOfRange { value: lng });
62 }
63
64 Ok(Self { lat, lng })
65 }
66
67 #[inline]
68 pub fn distance_to(self, other: Coord) -> f64 {
69 super::geo::haversine_distance(self, other)
70 }
71}
72
73impl TryFrom<(f64, f64)> for Coord {
74 type Error = CoordError;
75
76 #[inline]
77 fn try_from((lat, lng): (f64, f64)) -> Result<Self, Self::Error> {
78 Self::try_new(lat, lng)
79 }
80}
81
82impl From<Coord> for (f64, f64) {
83 #[inline]
84 fn from(coord: Coord) -> Self {
85 (coord.lat, coord.lng)
86 }
87}