mgrs-convert
Convert WGS84 latitude-longitude to and from UTM, UPS, and MGRS grid references, forward and reverse. UTM covers latitudes -80 to 84 and UPS covers the polar caps, so the whole globe has a representation. MGRS precision runs from 0 digit pairs, a 100 km cell, through 11, a 1 um cell, and every valid reference names a cell with a well defined center. Zero runtime dependencies.
[]
= "0.1.0"
Use
use ;
let position = new?;
assert_eq!;
let cell: Mgrs = "18TWL8566411315".parse?;
let center = cell.to_latlon;
assert!;
# Ok::
Four types, one error enum, nothing else. LatLon and UtmUps are
constructor-validated coordinates. Mgrs is a grid cell whose Display and
FromStr are the string round trip, and Precision is the validated
digit-pair count. LatLon::to_mgrs is infallible. UtmUps::to_mgrs returns
Err(OutsideMgrsExtent) for coordinates in the transfer slop outside the grid,
because the accepted transfer ranges extend 100 km past the MGRS coverage on
every side.
Accuracy
The projection core is the Krueger series to order n^6 from Karney,
"Transverse Mercator with an accuracy of a few nanometers" (J. Geodesy 85(8),
2011). The grid follows NGA TM 8358.1. Differentially tested at build time
against GeographicLib's GeoConvert and its extended-precision TMcoords.dat
set: worst observed forward and reverse errors are under 5 nm, the round trip
through the crate closes under 4 nm, and MGRS strings match GeoConvert
exactly at every precision across 100,000 random points, the full 100 km
letter lattice, and both polar grids. The checked-in test suite pins those
vectors.
Boundary behavior
- Latitude 0 and
-0.0are identical on every path: northern, band N (the first recorded divergence:GeoConvertreads the sign of-0.0and formats the southern equator cell). - The UTM latitude interval is [-80, 84), matching
GeoConvert: -80 exactly is UTM band C, 84 exactly is UPS north, and the last UTM latitude is one ulp below 84 (band X). - A coordinate exactly on an excluded upper grid edge is nudged inside by 2^-28 m before truncation, so it formats as the last cell of its own square.
- Parsing folds case, trims outer ASCII whitespace, accepts a leading zero in
the zone, and derives precision from the digit count. Grid-zone-only
references such as
"18T"are rejected with a named error (the second recorded divergence:GeoConvertaccepts them). - The Norway and Svalbard zone exceptions apply, pinned by tests.
Migrating from geoconvert
This crate replaces geoconvert 1.0, which panics or returns wrong coordinates
on several of these paths (precision 8-11 parses, the polar formatting ring,
precision validation, upper-edge formatting, latitude 0).
geoconvert call |
replacement |
|---|---|
LatLon::create(lat, lon) |
LatLon::new(lat, lon) |
latlon.to_mgrs(6) |
latlon.to_mgrs(Precision::new(6)?) |
Mgrs::parse_str(s) |
s.parse::<Mgrs>() |
mgrs.to_string() |
unchanged |
mgrs.to_latlon() |
unchanged |
UtmUps::create(z, north, e, n) |
UtmUps::utm(z, north, e, n) or UtmUps::ups(north, e, n) |
utmups.to_mgrs(p) |
utmups.to_mgrs(Precision::new(p)?)? |
Mgrs::create(...) |
removed, construct via to_mgrs or parse |
The two new ?s are the point: precision validation and the grid-extent check
now return errors instead of panicking.
Scope
WGS84 only, since MGRS is defined on it. Datum transformations, zone forcing,
USNG datum suffixes, geodesic problems, and a CLI are all out of scope
(geographiclib-rs covers the geodesic problems well). The crate is std:
the projection core needs the f64 math functions.
The declared minimum supported Rust version is 1.81. The CI floor job builds the library and runs the doctests on 1.81.0 with the dev-dependencies table stripped, a check anyone can rerun from the manifest.
License
MIT or Apache-2.0, at your option.