Geolocalización y mapas en Rust: reseña de bibliotecas y ejemplos prácticos
Rust es un lenguaje de programación de sistemas que está ganando popularidad en áreas que requieren alto rendimiento y seguridad. El trabajo con datos geoespaciales no es una excepción. Si estás desarrollando un servicio de seguimiento de transporte, un sistema de información geográfica o simplemente quieres agregar un mapa interactivo a un sitio web, el ecosistema de Rust ofrece varias soluciones maduras. En este artículo, analizaremos las bibliotecas clave para geolocalización y visualización de mapas, y proporcionaremos ejemplos prácticos de código.
1. Biblioteca geo — base de cálculos geométricos
La biblioteca geo (crates geo-types y geo) proporciona tipos de datos básicos: puntos, líneas, polígonos, así como algoritmos para trabajar con ellos. Es la base de muchos otros crates geoespaciales.
// cargo add geo-types geouse geo_types::{Point, LineString, Polygon};use geo::algorithm::haversine_distance;
fn main() { let moscow = Point::new(37.6173, 55.7558); let spb = Point::new(30.3351, 60.0);
// Distancia por haversine (en metros) let dist = haversine_distance(&moscow, &spb); println!("Distancia Moscú — San Petersburgo: {:.0} km", dist / 1000.0);
// Creación de un polígono let coords = vec![ (37.0, 55.0), (38.0, 55.0), (38.0, 56.0), (37.0, 56.0), (37.0, 55.0), ]; let polygon = Polygon::new( LineString::from(coords), vec![], ); println!("Área del polígono: {:?}", polygon.unsigned_area());}Capacidades:
- Tipos: Point, Line, LineString, Polygon, MultiPoint, GeometryCollection
- Algoritmos: distancia de Haversine, Vincenty, área, centroide, buffer, intersecciones
- Serialización a través de serde (compatibilidad con GeoJSON)
2. geoutils — trabajo con GPS y formatos de datos
El crate geoutils se especializa en el análisis y validación de datos GPS. Puede leer cadenas NMEA (protocolo estándar de receptores GPS) y convertir coordenadas.
// cargo add geoutilsuse geoutils::{Location, Distance};
fn main() { // Creación de un punto a partir de latitud/longitud let point_a = Location::new(55.7558, 37.6173).unwrap(); let point_b = Location::new(59.9343, 30.3351).unwrap();
// Distancia por haversine let dist = point_a.distance_to(&point_b).unwrap(); println!("Distancia: {} km", dist.as_kilometers());
// Análisis de una cadena NMEA (ejemplo) let nmea = "$GPGGA,123519,4807.038,N,01131.000,E,1,08,0.9,545.4,M,46.9,M,,*47"; if let Ok(loc) = Location::from_nmea(nmea) { println!("Análisis NMEA: {:?}", loc); }}Características:
- Análisis de NMEA-0183 (GPGGA, GPRMC)
- Soporte de formatos: DMS (grados/minutos/segundos), grados decimales
- Conversión entre sistemas de coordenadas (WGS84, UTM)
3. mapbox-gl-native-rs — renderizado de mapas en Rust
Para mostrar mapas en aplicaciones de escritorio o integradas, se puede usar el envoltorio de Rust para Mapbox GL Native. La biblioteca permite renderizar teselas vectoriales, superponer marcadores y polígonos, y gestionar estilos.
// Ejemplo simplificado — requiere configuración del entorno// cargo add mapbox-gl-native-rsuse mapbox_gl_native_rs::{Map, MapOptions, Style};
fn main() { let opts = MapOptions::new() .size(800, 600) .center(37.6173, 55.7558) .zoom(10.0);
let mut map = Map::new(opts); map.load_style(Style::from_url("https://demotiles.mapbox.com/style.json"));
// Adición de un marcador map.add_marker(37.6173, 55.7558, "Moscú");
// Renderizado en un buffer (por ejemplo, en PNG) let img = map.render_to_image(); img.save("map.png").unwrap();}Nota: Para su funcionamiento, se requiere la instalación