1mod haversine;
22mod postgis;
23pub mod batch;
24mod error;
25
26#[cfg(feature = "wasm")]
27mod wasm;
28
29pub use haversine::{haversine_distance, haversine_distance_meters, EARTH_RADIUS_KM, EARTH_RADIUS_M};
30pub use postgis::{parse_postgis_point, PostGISPoint};
31pub use batch::{calculate_distances, DistanceResult};
32pub use error::{GeoError, Result};
33
34#[derive(Debug, Clone, Copy, PartialEq, serde::Serialize, serde::Deserialize)]
36pub struct Coordinate {
37 pub latitude: f64,
39 pub longitude: f64,
41}
42
43impl Coordinate {
44 #[inline]
50 pub fn new(latitude: f64, longitude: f64) -> Self {
51 Self { latitude, longitude }
52 }
53
54 #[inline]
56 pub fn is_valid(&self) -> bool {
57 self.latitude >= -90.0
58 && self.latitude <= 90.0
59 && self.longitude >= -180.0
60 && self.longitude <= 180.0
61 }
62
63 #[inline]
65 pub(crate) fn to_radians(&self) -> (f64, f64) {
66 (self.latitude.to_radians(), self.longitude.to_radians())
67 }
68}
69
70impl From<(f64, f64)> for Coordinate {
71 fn from((lat, lng): (f64, f64)) -> Self {
72 Self::new(lat, lng)
73 }
74}
75
76#[cfg(test)]
77mod tests {
78 use super::*;
79
80 #[test]
81 fn test_coordinate_creation() {
82 let coord = Coordinate::new(52.5200, 13.4050);
83 assert_eq!(coord.latitude, 52.5200);
84 assert_eq!(coord.longitude, 13.4050);
85 }
86
87 #[test]
88 fn test_coordinate_validation() {
89 assert!(Coordinate::new(0.0, 0.0).is_valid());
90 assert!(Coordinate::new(90.0, 180.0).is_valid());
91 assert!(Coordinate::new(-90.0, -180.0).is_valid());
92 assert!(!Coordinate::new(91.0, 0.0).is_valid());
93 assert!(!Coordinate::new(0.0, 181.0).is_valid());
94 }
95
96 #[test]
97 fn test_coordinate_from_tuple() {
98 let coord: Coordinate = (52.5200, 13.4050).into();
99 assert_eq!(coord.latitude, 52.5200);
100 }
101}