knitr::opts_chunk$set( collapse = TRUE, comment = "#>" )
library(geographiclib)
This vignette covers the grid reference systems available in geographiclib: MGRS, Geohash, GARS, and Georef. These systems encode geographic coordinates as alphanumeric strings, useful for human communication and data storage. It also covers GeoCoords for universal coordinate parsing and conversion, and DMS functions for degrees-minutes-seconds formatting.
We'll use locations from both hemispheres throughout this vignette:
locations <- data.frame( name = c("Sydney", "Hobart", "McMurdo Station", "South Pole", "London", "New York", "Tokyo", "Ushuaia"), lon = c(151.21, 147.32, 166.67, 0, -0.13, -74.01, 139.69, -68.30), lat = c(-33.87, -42.88, -77.85, -90, 51.51, 40.71, 35.69, -54.80) ) locations
MGRS is used by NATO militaries and provides unambiguous location references worldwide. It's based on UTM zones (or UPS for polar regions).
# Convert all locations to MGRS pts <- cbind(locations$lon, locations$lat) codes <- mgrs_fwd(pts) data.frame(name = locations$name, mgrs = codes)
An MGRS code has several components:
# Sydney's MGRS code broken down sydney_mgrs <- mgrs_fwd(c(151.21, -33.87)) sydney_mgrs # Get full metadata from reverse conversion mgrs_rev(sydney_mgrs)
MGRS precision ranges from 100km (precision 0) to 1m (precision 5):
hobart <- c(147.32, -42.88) precisions <- data.frame( precision = 0:5, resolution = c("100 km", "10 km", "1 km", "100 m", "10 m", "1 m"), code = sapply(0:5, function(p) mgrs_fwd(hobart, precision = p)) ) precisions
For polar regions (>84°N or <80°S), MGRS uses Universal Polar Stereographic:
# Antarctic locations antarctic <- cbind( lon = c(166.67, 0, 77.85, -60), lat = c(-77.85, -90, -85, -82) ) antarctic_mgrs <- mgrs_fwd(antarctic) antarctic_mgrs # Note zone = 0 indicates UPS mgrs_rev(antarctic_mgrs)
All MGRS functions are fully vectorized:
# Different precisions for different points varied_precision <- mgrs_fwd(pts, precision = c(5, 4, 3, 2, 1, 0, 5, 4)) data.frame(name = locations$name, mgrs = varied_precision)
Geohash encodes locations as base-32 strings with a useful property: truncating a geohash reduces precision but still contains the original point.
codes <- geohash_fwd(pts, len = 8) data.frame(name = locations$name, geohash = codes)
This is Geohash's key feature - shorter codes are valid parent cells:
# Full precision for Sydney sydney_gh <- geohash_fwd(c(151.21, -33.87), len = 12) sydney_gh # Truncate to see parent cells data.frame( length = 12:4, geohash = substr(sydney_gh, 1, 12:4) )
geohash_resolution(1:12)
# What length for ~1km precision? geohash_length(resolution = 1/111) # ~1 degree / 111 km # What length for ~10m precision? geohash_length(resolution = 10/111000)
southern <- cbind( lon = c(151.21, 147.32, 166.67, -68.30, 77.85), lat = c(-33.87, -42.88, -77.85, -54.80, -85) ) rownames(southern) <- c("Sydney", "Hobart", "McMurdo", "Ushuaia", "Amundsen-Scott area") # Convert and reverse gh_codes <- geohash_fwd(southern, len = 8) gh_codes geohash_rev(gh_codes)
GARS is a military grid system with three precision levels: 30-minute, 15-minute, and 5-minute cells.
codes <- gars_fwd(pts, precision = 2) # 5-minute precision data.frame(name = locations$name, gars = codes)
sydney <- c(151.21, -33.87) gars_codes <- data.frame( precision = 0:2, resolution = c("30 minute", "15 minute", "5 minute"), code = sapply(0:2, function(p) gars_fwd(sydney, precision = p)) ) gars_codes
antarctic_pts <- cbind( lon = c(166.67, 0, 77.85), lat = c(-77.85, -85, -82) ) gars_fwd(antarctic_pts, precision = 2)
Georef is used primarily in aviation. It divides the world into 15° × 15° tiles then subdivides progressively.
codes <- georef_fwd(pts, precision = 2) data.frame(name = locations$name, georef = codes)
sydney <- c(151.21, -33.87) georef_codes <- data.frame( precision = c(-1, 0, 2, 3), resolution = c("15 degree", "1 degree", "0.01 minute", "0.001 minute"), code = sapply(c(-1, 0, 2, 3), function(p) georef_fwd(sydney, precision = p)) ) georef_codes
Georef is particularly useful for aviation across hemispheres:
# Flight path: Sydney to Santiago via Antarctica flight_pts <- cbind( lon = c(151.21, 166.67, -70, -70.67), lat = c(-33.87, -77.85, -85, -33.45) ) rownames(flight_pts) <- c("Sydney", "McMurdo", "Over Antarctica", "Santiago") georef_fwd(flight_pts, precision = 2)
Each system has different strengths:
| System | Best For | Precision Range | Key Feature | |--------|----------|-----------------|-------------| | MGRS | Military, hiking | 100km - 1m | Unambiguous worldwide | | Geohash | Databases, URLs | ~5000km - 1mm | Truncation preserves containment | | GARS | Military aviation | 30min - 5min | Simple, easy to read | | Georef | Aviation | 15° - 0.001min | Used in flight planning | | GeoCoords | Format conversion | N/A | Parses multiple input formats | | DMS | Human-readable | Variable | Degrees, minutes, seconds notation |
# Same location in all systems pt <- c(147.32, -42.88) # Hobart data.frame( system = c("MGRS", "Geohash", "GARS", "Georef", "DMS"), code = c( mgrs_fwd(pt, precision = 3), geohash_fwd(pt, len = 8), gars_fwd(pt, precision = 2), georef_fwd(pt, precision = 2), paste( dms_encode(pt[2], prec = 4, indicator = "latitude"), dms_encode(pt[1], prec = 4, indicator = "longitude") ) ) )
The geocoords_parse() function provides a flexible way to parse coordinate
strings in multiple formats. This is particularly useful when working with
data from different sources that may use different coordinate formats.
geocoords_parse() accepts coordinates in many formats:
# Parse MGRS codes geocoords_parse("33TWN0500049000") # Parse UTM strings geocoords_parse("33N 505000 4900000") # Parse DMS (degrees, minutes, seconds) geocoords_parse("44d 0' 0\" N 33d 0' 0\" E") # Parse decimal degrees (lat lon format) geocoords_parse("44.0 33.0")
The function is vectorized for batch processing:
# Mixed format inputs inputs <- c( "56HLU1060372300", # MGRS (Sydney area) "55G 530000 5250000", # UTM (Hobart area) "-33.87 151.21", # Decimal degrees "51d 30' 0\" N 0d 7' 0\" W" # DMS (London) ) parsed <- geocoords_parse(inputs) parsed[, c("lat", "lon", "zone", "northp")]
Once parsed, coordinates can be used with any grid reference or projection function:
# Parse any input format input <- "33TWN0500049000" coords <- geocoords_parse(input) # Then use with any system pt <- c(coords$lon, coords$lat) data.frame( input = input, lat = coords$lat, lon = coords$lon, mgrs = mgrs_fwd(pt, precision = 5), geohash = geohash_fwd(pt, len = 8), gars = gars_fwd(pt, precision = 2), georef = georef_fwd(pt, precision = 2) )
The DMS functions provide flexible parsing and formatting of angles in degrees-minutes-seconds notation. This is useful for working with coordinate data from various sources that use different formats.
dms_decode() parses DMS strings and returns the angle in decimal degrees:
# Parse with hemisphere indicator dms_decode("40d26'47\"N") # Parse various formats dms_decode(c( "40:26:47", # Colon-separated "-74d0'21.5\"", # Negative with d-'-" separators "51d30'N", # Degrees and minutes only "40.446S" # Decimal with hemisphere ))
The function returns both the angle and an indicator showing whether a hemisphere designator was present (0=none, 1=latitude N/S, 2=longitude E/W).
For latitude/longitude pairs, dms_decode_latlon() handles the hemisphere
logic automatically:
# Parse a coordinate pair dms_decode_latlon("40d26'47\"N", "74d0'21.5\"W") # Vectorized for multiple coordinates dms_decode_latlon( c("40d26'47\"N", "51d30'0\"N", "-33d52'10\""), c("74d0'21.5\"W", "0d7'0\"W", "151d12'30\"") )
For angles without coordinates (like bearings or field-of-view):
# Parse angles (no hemisphere designators allowed) dms_decode_angle(c("45:30:0", "123d45'6\"", "90.5")) # Parse azimuths (E/W allowed, result in [-180, 180]) dms_decode_azimuth(c("45:30:0", "90W", "135E"))
Convert decimal degrees to formatted DMS strings:
# Basic encoding with automatic component selection dms_encode(40.446195, prec = 5) dms_encode(c(40.446, -74.006), prec = 3) # With hemisphere indicators dms_encode(40.446195, prec = 5, indicator = "latitude") dms_encode(-74.006328, prec = 5, indicator = "longitude") # Azimuth format (always positive, 0-360) dms_encode(-45.5, indicator = "azimuth", prec = 4)
Control the output format with precision and separator options:
angle <- 40.446195 # Different precisions data.frame( prec = 0:6, output = sapply(0:6, function(p) dms_encode(angle, prec = p)) ) # Colon separator (ISO 6709 style) dms_encode(angle, prec = 5, sep = ":") # Force specific trailing component dms_encode(angle, component = "minute", prec = 4) dms_encode(angle, component = "second", prec = 2)
Work with individual degree, minute, second components:
# Split into degrees and minutes dms_split(c(40.446, -74.256)) # Split into degrees, minutes, and seconds dms_split(c(40.446195, -74.006328), seconds = TRUE) # Combine components back to decimal dms_combine(40, 26, 47) dms_combine( d = c(40, -74, 51), m = c(26, 0, 30), s = c(47, 21.5, 0) )
DMS encoding and decoding are inverses (within precision limits):
# Original coordinates original <- c(40.446195, -74.006328, 51.507351) # Encode to DMS encoded <- dms_encode(original, prec = 6, indicator = "latitude") encoded # Decode back decoded <- dms_decode(encoded) data.frame( original = original, encoded = encoded, decoded = decoded$angle, diff = abs(original - decoded$angle) )
DMS functions complement GeoCoords for complete coordinate handling:
# Parse mixed-format input with GeoCoords input <- "40d26'47\"N 74d0'21.5\"W" coords <- geocoords_parse(input) # Format output in different styles data.frame( format = c("decimal", "DMS", "DMS-colon", "MGRS"), value = c( sprintf("%.6f, %.6f", coords$lat, coords$lon), paste( dms_encode(coords$lat, prec = 5, indicator = "latitude"), dms_encode(coords$lon, prec = 5, indicator = "longitude") ), paste( dms_encode(coords$lat, prec = 5, sep = ":"), dms_encode(coords$lon, prec = 5, sep = ":") ), mgrs_fwd(c(coords$lon, coords$lat), precision = 4) ) )
vignette("projections") for map projections (UTM/UPS, LCC, etc.)vignette("geodesics") for distance and bearing calculationsAny scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.