geo/lib.rs
1#![doc(html_logo_url = "https://raw.githubusercontent.com/georust/meta/master/logo/logo.png")]
2
3//! The `geo` crate provides geospatial primitive types and algorithms.
4//!
5//! # Types
6//!
7//! - **[`Coord`]**: A two-dimensional coordinate. All geometry types are composed of [`Coord`]s, though [`Coord`] itself is not a [`Geometry`] type.
8//! - **[`Point`]**: A single point represented by one [`Coord`]
9//! - **[`MultiPoint`]**: A collection of [`Point`]s
10//! - **[`Line`]**: A line segment represented by two [`Coord`]s
11//! - **[`LineString`]**: A series of contiguous line segments represented by two or more
12//! [`Coord`]s
13//! - **[`MultiLineString`]**: A collection of [`LineString`]s
14//! - **[`Polygon`]**: A bounded area represented by one [`LineString`] exterior ring, and zero or
15//! more [`LineString`] interior rings
16//! - **[`MultiPolygon`]**: A collection of [`Polygon`]s
17//! - **[`Rect`]**: An axis-aligned bounded rectangle represented by minimum and maximum
18//! [`Coord`]s
19//! - **[`Triangle`]**: A bounded area represented by three [`Coord`] vertices
20//! - **[`GeometryCollection`]**: A collection of [`Geometry`]s
21//! - **[`Geometry`]**: An enumeration of all geometry types, excluding [`Coord`]
22//!
23//! The preceding types are reexported from the [`geo-types`] crate. Consider using that crate
24//! if you only need access to these types and no other `geo` functionality.
25//!
26//! ## Semantics
27//!
28//! The geospatial types provided here aim to adhere to the [OpenGIS Simple feature access][OGC-SFA]
29//! standards. Thus, the types here are inter-operable with other implementations of the standards:
30//! [JTS], [GEOS], etc.
31//!
32//! # Algorithms
33//!
34//! ## Area
35//!
36//! - **[`Area`](Area)**: Calculate the planar area of a geometry
37//! - **[`ChamberlainDuquetteArea`](ChamberlainDuquetteArea)**: Calculate the geodesic area of a geometry on a sphere using the algorithm presented in _Some Algorithms for Polygons on a Sphere_ by Chamberlain and Duquette (2007)
38//! - **[`GeodesicArea`](GeodesicArea)**: Calculate the geodesic area and perimeter of a geometry on an ellipsoid using the algorithm presented in _Algorithms for geodesics_ by Charles Karney (2013)
39//!
40//! ## Boolean Operations
41//!
42//! - **[`BooleanOps`](BooleanOps)**: combine or split (Multi)Polygons using intersecton, union, xor, or difference operations
43//!
44//! ## Distance
45//!
46//! - **[`EuclideanDistance`](EuclideanDistance)**: Calculate the minimum euclidean distance between geometries
47//! - **[`GeodesicDistance`](GeodesicDistance)**: Calculate the minimum geodesic distance between geometries using the algorithm presented in _Algorithms for geodesics_ by Charles Karney (2013)
48//! - **[`HaversineDistance`](HaversineDistance)**: Calculate the minimum geodesic distance between geometries using the haversine formula
49//! - **[`VincentyDistance`](VincentyDistance)**: Calculate the minimum geodesic distance between geometries using Vincenty’s formula
50//!
51//! ## Length
52//!
53//! - **[`EuclideanLength`](EuclideanLength)**: Calculate the euclidean length of a geometry
54//! - **[`GeodesicLength`](GeodesicLength)**: Calculate the geodesic length of a geometry using the algorithm presented in _Algorithms for geodesics_ by Charles Karney (2013)
55//! - **[`HaversineLength`](HaversineLength)**: Calculate the geodesic length of a geometry using the haversine formula
56//! - **[`VincentyLength`](VincentyLength)**: Calculate the geodesic length of a geometry using Vincenty’s formula
57//!
58//! ## Outlier Detection
59//!
60//! - **[`OutlierDetection`](OutlierDetection)**: Detect outliers in a group of points using [LOF](https://en.wikipedia.org/wiki/Local_outlier_factor)
61//!
62//! ## Simplification
63//!
64//! - **[`Simplify`](Simplify)**: Simplify a geometry using the Ramer–Douglas–Peucker algorithm
65//! - **[`SimplifyIdx`](SimplifyIdx)**: Calculate a simplified geometry using the Ramer–Douglas–Peucker algorithm, returning coordinate indices
66//! - **[`SimplifyVw`](SimplifyVw)**: Simplify a geometry using the Visvalingam-Whyatt algorithm
67//! - **[`SimplifyVwPreserve`](SimplifyVwPreserve)**: Simplify a geometry using a topology-preserving variant of the Visvalingam-Whyatt algorithm
68//! - **[`SimplifyVwIdx`](SimplifyVwIdx)**: Calculate a simplified geometry using a topology-preserving variant of the Visvalingam-Whyatt algorithm, returning coordinate indices
69//!
70//! ## Query
71//!
72//! - **[`HaversineBearing`]**: Calculate the bearing between points using great circle calculations.
73//! - **[`GeodesicBearing`](GeodesicBearing)**: Calculate the bearing between points on a [geodesic](https://en.wikipedia.org/wiki/Geodesics_on_an_ellipsoid)
74//! - **[`ClosestPoint`](ClosestPoint)**: Find the point on a geometry
75//! closest to a given point
76//! - **[`IsConvex`](IsConvex)**: Calculate the convexity of a
77//! [`LineString`]
78//! - **[`LineInterpolatePoint`](LineInterpolatePoint)**:
79//! Generates a point that lies a given fraction along the line
80//! - **[`LineLocatePoint`](LineLocatePoint)**: Calculate the
81//! fraction of a line’s total length representing the location of the closest point on the
82//! line to the given point
83//!
84//! ## Similarity
85//!
86//! - **[`FrechetDistance`](FrechetDistance)**: Calculate the similarity between [`LineString`]s using the Fréchet distance
87//!
88//! ## Topology
89//!
90//! - **[`Contains`](Contains)**: Calculate if a geometry contains another
91//! geometry
92//! - **[`CoordinatePosition`](CoordinatePosition)**: Calculate
93//! the position of a coordinate relative to a geometry
94//! - **[`HasDimensions`](HasDimensions)**: Determine the dimensions of a geometry
95//! - **[`Intersects`](Intersects)**: Calculate if a geometry intersects
96//! another geometry
97//! - **[`line_intersection`](line_intersection::line_intersection)**: Calculates the
98//! intersection, if any, between two lines.
99//! - **[`Relate`](Relate)**: Topologically relate two geometries based on
100//! [DE-9IM](https://en.wikipedia.org/wiki/DE-9IM) semantics.
101//! - **[`Within`]**: Calculate if a geometry lies completely within another geometry.
102//!
103//! ## Winding
104//!
105//! - **[`Orient`](Orient)**: Apply a specified winding [`Direction`](orient::Direction) to a [`Polygon`]’s interior and exterior rings
106//! - **[`Winding`](Winding)**: Calculate and manipulate the [`WindingOrder`](winding_order::WindingOrder) of a [`LineString`]
107//!
108//! ## Iteration
109//!
110//! - **[`CoordsIter`]**: Iterate over the coordinates of a geometry
111//! - **[`MapCoords`]**: Map a function over all the coordinates
112//! in a geometry, returning a new geometry
113//! - **[`MapCoordsInPlace`]**: Map a function over all the
114//! coordinates in a geometry in-place
115//! - **[`LinesIter`]**: Iterate over lines of a geometry
116//!
117//! ## Boundary
118//!
119//! - **[`BoundingRect`](BoundingRect)**: Calculate the axis-aligned
120//! bounding rectangle of a geometry
121//! - **[`MinimumRotatedRect`](MinimumRotatedRect)**: Calculate the
122//! minimum bounding box of a geometry
123//! - **[`ConcaveHull`](ConcaveHull)**: Calculate the concave hull of a
124//! geometry
125//! - **[`ConvexHull`](ConvexHull)**: Calculate the convex hull of a
126//! geometry
127//! - **[`Extremes`](Extremes)**: Calculate the extreme coordinates and
128//! indices of a geometry
129//!
130//! ## Affine transformations
131//!
132//! - **[`Rotate`](Rotate)**: Rotate a geometry around its centroid
133//! - **[`Scale`](Scale)**: Scale a geometry up or down by a factor
134//! - **[`Skew`](Skew)**: Skew a geometry by shearing angles along the `x` and `y` dimension
135//! - **[`Translate`](Translate)**: Translate a geometry along its axis
136//! - **[`AffineOps`](AffineOps)**: generalised composable affine operations
137//!
138//! ## Conversion
139//!
140//! - **[`Convert`]**: Convert (infalliby) the type of a geometry’s coordinate value
141//! - **[`TryConvert`]**: Convert (falliby) the type of a geometry’s coordinate value
142//!
143//! ## Miscellaneous
144//!
145//! - **[`Centroid`](Centroid)**: Calculate the centroid of a geometry
146//! - **[`GeodesicDestination`](GeodesicDestination)**: Given a start point, bearing, and distance, calculate the destination point on a [geodesic](https://en.wikipedia.org/wiki/Geodesics_on_an_ellipsoid)
147//! - **[`GeodesicIntermediate`](GeodesicIntermediate)**: Calculate intermediate points on a [geodesic](https://en.wikipedia.org/wiki/Geodesics_on_an_ellipsoid)
148//! - **[`HaversineDestination`]**: Given a start point, bearing, and distance, calculate the destination point on a sphere
149//! - **[`HaversineIntermediate`](HaversineIntermediate)**: Calculate intermediate points on a sphere
150//! - **[`proj`](proj)**: Project geometries with the `proj` crate (requires the `use-proj` feature)
151//! - **[`ChaikinSmoothing`](ChaikinSmoothing)**: Smoothen `LineString`, `Polygon`, `MultiLineString` and `MultiPolygon` using Chaikins algorithm.
152//! - **[`Densify`](Densify)**: Densify linear geometry components by interpolating points
153//! - **[`Transform`](Transform)**: Transform a geometry using Proj.
154//! - **[`RemoveRepeatedPoints`](RemoveRepeatedPoints)**: Remove repeated points from a geometry.
155//!
156//! # Features
157//!
158//! The following optional [Cargo features] are available:
159//!
160//! - `proj-network`: Enables [network grid] support for the [`proj` crate]. After enabling this feature, [further configuration][proj crate file download] is required to use the network grid
161//! - `use-proj`: Enables coordinate conversion and transformation of `Point` geometries using the [`proj` crate]
162//! - `use-serde`: Allows geometry types to be serialized and deserialized with [Serde]
163//!
164//! # Ecosystem
165//!
166//! There’s a wide variety of `geo`-compatible crates in the ecosystem that offer functionality not
167//! included in the `geo` crate, including:
168//!
169//! * Reading and writing file formats (e.g. [GeoJSON][geojson crate], [WKT][wkt crate],
170//! [shapefile][shapefile crate])
171//! * [Latitude and longitude parsing][latlng crate]
172//! * [Label placement][polylabel crate]
173//! * [Geocoding][geocoding crate]
174//! * [and much more...][georust website]
175//!
176//! [`geo-types`]: https://crates.io/crates/geo-types
177//! [`proj` crate]: https://github.com/georust/proj
178//! [geojson crate]: https://crates.io/crates/geojson
179//! [wkt crate]: https://crates.io/crates/wkt
180//! [shapefile crate]: https://crates.io/crates/shapefile
181//! [latlng crate]: https://crates.io/crates/latlon
182//! [polylabel crate]: https://crates.io/crates/polylabel
183//! [geocoding crate]: https://crates.io/crates/geocoding
184//! [georust website]: https://georust.org
185//! [Cargo features]: https://doc.rust-lang.org/cargo/reference/features.html
186//! [GEOS]: https://trac.osgeo.org/geos
187//! [JTS]: https://github.com/locationtech/jts
188//! [network grid]: https://proj.org/usage/network.html
189//! [OGC-SFA]: https://www.ogc.org/standards/sfa
190//! [proj crate file download]: https://docs.rs/proj/*/proj/#grid-file-download
191//! [Serde]: https://serde.rs/
192
193extern crate geo_types;
194extern crate num_traits;
195#[cfg(feature = "use-serde")]
196#[macro_use]
197extern crate serde;
198#[cfg(feature = "use-proj")]
199extern crate proj;
200extern crate rstar;
201
202pub use crate::algorithm::*;
203pub use crate::types::Closest;
204
205pub use geo_types::{coord, line_string, point, polygon, CoordFloat, CoordNum};
206
207pub mod geometry;
208pub use geometry::*;
209
210/// This module includes all the functions of geometric calculations
211pub mod algorithm;
212mod geometry_cow;
213mod types;
214mod utils;
215pub(crate) use geometry_cow::GeometryCow;
216
217#[cfg(test)]
218#[macro_use]
219extern crate approx;
220
221#[macro_use]
222extern crate log;
223
224/// Mean radius of Earth in meters
225/// This is the value recommended by the IUGG:
226/// Moritz, H. (2000). Geodetic Reference System 1980. Journal of Geodesy, 74(1), 128–133. doi:10.1007/s001900050278
227/// "Derived Geometric Constants: mean radius" (p133)
228/// https://link.springer.com/article/10.1007%2Fs001900050278
229/// https://sci-hub.se/https://doi.org/10.1007/s001900050278
230/// https://en.wikipedia.org/wiki/Earth_radius#Mean_radius
231const MEAN_EARTH_RADIUS: f64 = 6371008.8;
232
233// Radius of Earth at the equator in meters (derived from the WGS-84 ellipsoid)
234const EQUATORIAL_EARTH_RADIUS: f64 = 6_378_137.0;
235
236// Radius of Earth at the poles in meters (derived from the WGS-84 ellipsoid)
237const POLAR_EARTH_RADIUS: f64 = 6_356_752.314_245;
238
239// Flattening of the WGS-84 ellipsoid - https://en.wikipedia.org/wiki/Flattening
240const EARTH_FLATTENING: f64 =
241 (EQUATORIAL_EARTH_RADIUS - POLAR_EARTH_RADIUS) / EQUATORIAL_EARTH_RADIUS;
242
243/// A prelude which re-exports the traits for manipulating objects in this
244/// crate. Typically imported with `use geo::prelude::*`.
245pub mod prelude {
246 pub use crate::algorithm::*;
247}
248
249/// A common numeric trait used for geo algorithms
250///
251/// Different numeric types have different tradeoffs. `geo` strives to utilize generics to allow
252/// users to choose their numeric types. If you are writing a function which you'd like to be
253/// generic over all the numeric types supported by geo, you probably want to constrain
254/// your function input to `GeoFloat`. For methods which work for integers, and not just floating
255/// point, see [`GeoNum`].
256///
257/// # Examples
258///
259/// ```
260/// use geo::{GeoFloat, MultiPolygon, Polygon, Point};
261///
262/// // An admittedly silly method implementation, but the signature shows how to use the GeoFloat trait
263/// fn farthest_from<'a, T: GeoFloat>(point: &Point<T>, polygons: &'a MultiPolygon<T>) -> Option<&'a Polygon<T>> {
264/// polygons.iter().fold(None, |accum, next| {
265/// match accum {
266/// None => Some(next),
267/// Some(farthest) => {
268/// use geo::{euclidean_distance::EuclideanDistance};
269/// if next.euclidean_distance(point) > farthest.euclidean_distance(point) {
270/// Some(next)
271/// } else {
272/// Some(farthest)
273/// }
274/// }
275/// }
276/// })
277/// }
278/// ```
279pub trait GeoFloat:
280 GeoNum + num_traits::Float + num_traits::Signed + num_traits::Bounded + float_next_after::NextAfter
281{
282}
283impl<T> GeoFloat for T where
284 T: GeoNum
285 + num_traits::Float
286 + num_traits::Signed
287 + num_traits::Bounded
288 + float_next_after::NextAfter
289{
290}
291
292/// A trait for methods which work for both integers **and** floating point
293pub trait GeoNum: CoordNum + HasKernel {}
294impl<T> GeoNum for T where T: CoordNum + HasKernel {}