## ----include = FALSE----------------------------------------------------------
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)

## ----setup--------------------------------------------------------------------
library(geographiclib)

## ----locations----------------------------------------------------------------
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-basic---------------------------------------------------------------
# Convert all locations to MGRS
pts <- cbind(locations$lon, locations$lat)
codes <- mgrs_fwd(pts)
data.frame(name = locations$name, mgrs = codes)

## ----mgrs-structure-----------------------------------------------------------
# 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-----------------------------------------------------------
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

## ----mgrs-polar---------------------------------------------------------------
# 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)

## ----mgrs-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-basic------------------------------------------------------------
codes <- geohash_fwd(pts, len = 8)
data.frame(name = locations$name, geohash = codes)

## ----geohash-truncation-------------------------------------------------------
# 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-------------------------------------------------------
geohash_resolution(1:12)

## ----geohash-length-----------------------------------------------------------
# What length for ~1km precision?
geohash_length(resolution = 1/111)  # ~1 degree / 111 km

# What length for ~10m precision?
geohash_length(resolution = 10/111000)

## ----geohash-southern---------------------------------------------------------
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-basic---------------------------------------------------------------
codes <- gars_fwd(pts, precision = 2)  # 5-minute precision
data.frame(name = locations$name, gars = codes)

## ----gars-precision-----------------------------------------------------------
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

## ----gars-antarctic-----------------------------------------------------------
antarctic_pts <- cbind(
  lon = c(166.67, 0, 77.85),
  lat = c(-77.85, -85, -82)
)

gars_fwd(antarctic_pts, precision = 2)

## ----georef-basic-------------------------------------------------------------
codes <- georef_fwd(pts, precision = 2)
data.frame(name = locations$name, georef = codes)

## ----georef-precision---------------------------------------------------------
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-flight------------------------------------------------------------
# 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)

## ----comparison---------------------------------------------------------------
# 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")
    )
  )
)

## ----geocoords-parse----------------------------------------------------------
# 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")

## ----geocoords-batch----------------------------------------------------------
# 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")]

## ----geocoords-integration----------------------------------------------------
# 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)
)

## ----dms-decode---------------------------------------------------------------
# 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
))

## ----dms-latlon---------------------------------------------------------------
# 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\"")
)

## ----dms-angle-azimuth--------------------------------------------------------
# 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"))

## ----dms-encode---------------------------------------------------------------
# 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)

## ----dms-format---------------------------------------------------------------
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)

## ----dms-split-combine--------------------------------------------------------
# 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-roundtrip------------------------------------------------------------
# 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-geocoords------------------------------------------------------------
# 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)
  )
)

