1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
//! Geoutils is a evolving crate to provide several geological computations and utilities. //! Most computations are based off methods on the [Location](struct.Location.html) struct. //! //! Find the full API reference at [docs.rs](http://docs.rs/geoutils). //! //! # Examples //! //! * Get the distance between two points using [Vincenty's Inverse Formula](https://en.wikipedia.org/wiki/Vincenty%27s_formulae). //! ```rust //! use geoutils::Location; //! //! let berlin = Location::new(52.518611, 13.408056); //! let moscow = Location::new(55.751667, 37.617778); //! let distance = berlin.distance_to(&moscow).unwrap(); //! //! println!("Distance = {}", distance.meters()); //! ``` //! //! * Get the distance between two points using the [Haversine Formula](https://en.wikipedia.org/wiki/Haversine_formula). //! ```rust //! use geoutils::Location; //! //! let berlin = Location::new(52.518611, 13.408056); //! let moscow = Location::new(55.751667, 37.617778); //! let distance = berlin.haversine_distance_to(&moscow); //! //! println!("Distance = {}", distance.meters()); //! ``` //! //! * Get the center of a list of coordinates. //! ```rust //! use geoutils::Location; //! //! let berlin = Location::new(52.518611, 13.408056); //! let moscow = Location::new(55.751667, 37.617778); //! let center = Location::center(&vec![&berlin, &moscow]); //! //! println!("Center {}, {}", center.latitude(), center.longitude()); //! ``` //! //! * Check if a point falls in a certain radius of another point. //! ```rust //! use geoutils::{Location, Distance}; //! //! let berlin = Location::new(52.518611, 13.408056); //! let moscow = Location::new(55.751667, 37.617778); //! let is_in_radius = berlin.is_in_circle(&moscow, Distance::from_meters(2000.0)).unwrap(); //! //! println!("Is Berlin in 2000m of Moscow? {}", is_in_radius); //! ``` //! #![deny(missing_docs)] mod formula; pub use formula::Distance; /// Location defines a point using it's latitude and longitude. #[derive(Debug, PartialEq, Clone, Copy)] pub struct Location(f64, f64); impl Location { /// Create a new Location with it's degree values of latitude and longitude. pub fn new<T: Into<f64>>(lat: T, lon: T) -> Self { Location(lat.into(), lon.into()) } /// Get the latitude. pub fn latitude(&self) -> f64 { self.0 } /// Get the longitude. pub fn longitude(&self) -> f64 { self.1 } /// Find the distance from itself to another point. Internally uses Vincenty's inverse formula. /// For better performance and lesser accuracy, consider [haversine_distance_to](struct.Location.html#method.haversine_distance_to). /// This method returns Err if the formula fails to converge within 100 iterations. pub fn distance_to(&self, to: &Location) -> Result<Distance, String> { match formula::vincenty_inverse(self, to, 0.00001, 0.0) { Ok(res) => Ok(res.distance), Err(e) => Err(e), } } /// Find the distance from itself to another point using Haversine formula. /// This is usually computationally less intensive than [distance_to](struct.Location.html#method.distance_to) but /// is generally not as accurate. pub fn haversine_distance_to(&self, to: &Location) -> Distance { formula::haversine_distance_to(self, to) } /// Check if the point is within a fixed radius of another point. pub fn is_in_circle(&self, center: &Location, radius: Distance) -> Result<bool, String> { match formula::vincenty_inverse(self, center, 0.00001, 0.0) { Ok(res) => Ok(res.distance.meters() < radius.meters()), Err(e) => Err(e), } } /// Find the center of given locations. pub fn center(coords: &[&Location]) -> Location { formula::center_of_coords(coords) } } #[cfg(test)] mod tests { use super::*; #[test] fn test_get_distance() { let l1 = Location::new(27.740068, 85.337576); let l2 = Location::new(27.740286, 85.337059); match l1.distance_to(&l2) { Ok(distance) => { assert_eq!(distance.meters(), 56.409); } Err(e) => panic!("Failed: {:?}", e), } } #[test] fn test_get_distance_haversine() { let l1 = Location::new(27.740068, 85.337576); let l2 = Location::new(27.740286, 85.337059); let distance = l1.haversine_distance_to(&l2); assert_eq!(distance.meters(), 56.36); } #[test] fn test_get_center() { let l1 = Location::new(52.518611, 13.408056); let l2 = Location::new(55.751667, 37.617778); let l = Location::center(&[&l1, &l2]); assert_eq!(l.0, 54.743683); assert_eq!(l.1, 25.033239); } }