Geolocation and Maps in Rust: Tool Overview and Code Examples
Rust is a systems programming language increasingly used for building high-load services that work with spatial data. Thanks to its performance, memory safety, and active community, the Rust ecosystem offers several mature libraries for working with geolocation, maps, and geodata formats. In this article, we will review the key tools: geo, georust (including gpx and geojson), as well as integration with mapping libraries via WebAssembly.
1. Core Library: geo
The geo library is the core of the geospatial computing ecosystem in Rust. It provides data types (points, lines, polygons), algorithms (distance calculation, area, intersections), and support for popular coordinate systems (WGS84, UTM).
Installation
# Cargo.toml[dependencies]geo = "0.27"Example: Calculating Distance Between Two Points
use geo::{point, Distance};
fn main() { let moscow = point!(x: 37.6173, y: 55.7558); let london = point!(x: -0.1276, y: 51.5074);
// Spherical distance (Haversine algorithm) let distance = moscow.distance_haversine(&london); println!("Distance from Moscow to London: {:.2} km", distance / 1000.0);}The library supports:
- Geometry types:
Point,LineString,Polygon,MultiPoint, and others. - Algorithms: buffering, line simplification (Ramer-Douglas-Peucker), centroid calculation.
- CRS handling via the
projcrate.
2. Working with Formats: GeoJSON and GPX
For reading and writing geodata, separate crates from the georust ecosystem are used.
GeoJSON
The geojson crate allows serializing/deserializing GeoJSON — the standard format for exchanging geodata.
use geojson::{Feature, GeoJson, Geometry, Value};use serde_json;
fn main() { let geojson_str = r#"{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [37.6173, 55.7558] }, "properties": { "name": "Moscow" } }"#;
let geojson: GeoJson = geojson_str.parse().unwrap(); if let GeoJson::Feature(feature) = geojson { println!("Geometry: {:?}", feature.geometry); }}GPX (GPS Exchange Format)
The gpx crate is designed for working with tracks and waypoints recorded by GPS devices.
use gpx::read;use std::fs::File;
fn main() { let file = File::open("track.gpx").unwrap(); let gpx = read(file).unwrap();
for track in gpx.tracks { println!("Track name: {:?}", track.name); for segment in track.segments { for point in segment.points { println!("Point: ({:.4}, {:.4})", point.point().x(), point.point().y()); } } }}3. Map Visualization: Leaflet.js via WASM
To display maps on a web page, you can use Leaflet.js in conjunction with Rust via WebAssembly. A popular approach is generating HTML/JavaScript on the Rust side using the wasm-bindgen crate and embedding the map via leaflet.js.
Example: Creating a Map with a Marker
// cargo.toml[dependencies]wasm-bindgen = "0.2"
// main.rsuse wasm_bindgen::prelude::*;
#[wasm_bindgen]pub fn init_map() { let window = web_sys::window().unwrap(); let document = window.document().unwrap();
// Create a div for the map let map_div = document.create_element("div").unwrap(); map_div.set_attribute("id", "map").u