mgrs-convert 0.1.0

Convert WGS84 latitude-longitude to and from UTM, UPS, and MGRS grid references, round-tripping exactly at every precision from 100 km to 1 um
Documentation
  • Coverage
  • 100%
    34 out of 34 items documented1 out of 1 items with examples
  • Size
  • Source code size: 2.6 MB This is the summed size of all the files inside the crates.io package for this release.
  • Documentation size: 536.4 kB This is the summed size of all files generated by rustdoc for all configured targets
  • Ø build duration
  • this release: 6s Average build duration of successful builds.
  • all releases: 6s Average build duration of successful builds in releases after 2024-10-23.
  • Links
  • hey-jj/mgrs-convert
    0 0 0
  • crates.io
  • Dependencies
  • Versions
  • Owners
  • hey-jj

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.

[dependencies]
mgrs-convert = "0.1.0"

Use

use mgrs_convert::{LatLon, Mgrs, Precision};

let position = LatLon::new(40.748333, -73.985278)?;
assert_eq!(position.to_mgrs(Precision::ONE_METER).to_string(), "18TWL8566411315");

let cell: Mgrs = "18TWL8566411315".parse()?;
let center = cell.to_latlon();
assert!((center.lat() - 40.748333).abs() < 1e-5);
# Ok::<(), mgrs_convert::Error>(())

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.0 are identical on every path: northern, band N (the first recorded divergence: GeoConvert reads the sign of -0.0 and 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: GeoConvert accepts 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.