A global visualization of UTM zones, showcasing latitudinal bands labeled from C to X and longitudinal strips numbered 1 to 60, forming a precise grid for geospatial reference.
Geocomputation
CRS
Maps
Author
Aditya Dahiya
Published
January 22, 2025
Figure 1: A global visualization of UTM zones, showcasing latitudinal bands labeled from C to X and longitudinal strips numbered 1 to 60, forming a precise grid for geospatial reference.
How I made this graphic?
Loading required libraries, data import & creating custom functions.
Code
# Data Wrangling & Plotting Toolslibrary(tidyverse) # All things tidylibrary(sf) # Simple Features in R# Plot touch-up toolslibrary(scales) # Nice Scales for ggplot2library(fontawesome) # Icons display in ggplot2library(ggtext) # Markdown text support for ggplot2library(showtext) # Display fonts in ggplot2library(colorspace) # Lighten and Darken colourslibrary(patchwork) # Compiling Plots
Visualization Parameters
Code
# Font for titlesfont_add_google("Bree Serif",family ="title_font") # Font for the captionfont_add_google("Stint Ultra Condensed",family ="caption_font") # Font for plot textfont_add_google("Copse",family ="body_font") showtext_auto()mypal <- paletteer::paletteer_d("lisa::C_M_Coolidge")# A base Colourbg_col <-"white"seecolor::print_color(bg_col)land_col <- mypal[4]seecolor::print_color(land_col)# Colour for highlighted text - 1text_hil1 <- mypal[2]seecolor::print_color(text_hil1)# Colour for the text - 1text_col1 <- mypal[1]seecolor::print_color(text_col1)# Colour for highlighted text - 2text_hil2 <- mypal[4]seecolor::print_color(text_hil2)# Colour for the text - 2text_col2 <- mypal[5]seecolor::print_color(text_col2)# Define Base Text Sizebts <-80# Caption stuff for the plotsysfonts::font_add(family ="Font Awesome 6 Brands",regular = here::here("docs", "Font Awesome 6 Brands-Regular-400.otf"))github <-""github_username <-"aditya-dahiya"xtwitter <-""xtwitter_username <-"@adityadahiyaias"social_caption_1 <- glue::glue("<span style='font-family:\"Font Awesome 6 Brands\";'>{github};</span> <span style='color: {text_hil1}'>{github_username} </span>")social_caption_2 <- glue::glue("<span style='font-family:\"Font Awesome 6 Brands\";'>{xtwitter};</span> <span style='color: {text_hil1}'>{xtwitter_username}</span>")plot_caption <-paste0("**Data:** Open Street Maps; Census of India", " | **Code:** ", social_caption_1, " | **Graphics:** ", social_caption_2 )rm(github, github_username, xtwitter, xtwitter_username, social_caption_1, social_caption_2)# Add text to plot-------------------------------------------------plot_title <-"UTM Grid Zones of the World"plot_subtitle <-"The Universal Transverse Mercator (UTM) grid zones, which divide the Earth into 60 longitudinal strips (6° wide) and 20 latitudinal bands (8° high). Each zone employs a unique coordinate system to ensure accurate mapping with minimal distortion."
Create data for the UTM Zones
Code
india_map <-read_sf( here::here("data", "india_map", "India_Country_Boundary.shp")) |>st_simplify(dTolerance =2000)world_map <- rnaturalearth::ne_countries(scale ="large",returnclass ="sf") |>select(name, geometry)object.size(world_map) |>print(units ="Mb")# Create a tibble for the UTM Zone breaks# First, the longitude breaks -------------------------------------------------utm_long_breaks <-tibble(Longitude_Start =seq(-180, 174, by =6),Longitude_End =seq(-174, 180, by =6),Zone_Number =seq(1, 60)) |> janitor::clean_names() |>mutate(mid_point_long = (longitude_start + longitude_end)/2 )vlines <-tibble(vline_values =unique(c(utm_long_breaks$longitude_end, utm_long_breaks$longitude_start) ) |>sort())# Then, the latitude breaks ---------------------------------------------------utm_lat_breaks <-tibble(Latitude_Start =c(seq(-80, 72, by =8)),Latitude_End =c(seq(-72, 72, by =8), 84),Zone_Letter = LETTERS[!(LETTERS %in%c("A", "B", "I", "O", "Y", "Z"))]) |> janitor::clean_names() |>mutate(mid_point_lat = (latitude_start + latitude_end)/2 )hlines <-tibble(hline_values =unique(c(utm_lat_breaks$latitude_end, utm_lat_breaks$latitude_start) ) |>sort())# Using the power of tidyr::crossing() to generate all zone nameszone_names <-crossing( utm_lat_breaks |>select(zone_letter, mid_point_lat) |>rename(lat_zone = zone_letter, lat = mid_point_lat), utm_long_breaks |>select(zone_number, mid_point_long) |>rename(long_zone = zone_number, long = mid_point_long))
The Base Plot - an inaccurate approximation of the Zone Lines
A global visualization of UTM zones, showcasing latitudinal bands labeled from C to X and longitudinal strips numbered 1 to 60, forming a precise grid for geospatial reference.
Another more accurate attempt: the Final Visualization
# Saving a thumbnaillibrary(magick)# Saving a thumbnail for the webpageimage_read(here::here("data_vizs", "viz_utm_zones.png")) |>image_resize(geometry ="x400") |>image_write( here::here("data_vizs", "thumbnails", "viz_utm_zones.png" ) )
Session Info
Code
# Data Wrangling & Plotting Toolslibrary(tidyverse) # All things tidylibrary(sf) # Simple Features in R# Plot touch-up toolslibrary(scales) # Nice Scales for ggplot2library(fontawesome) # Icons display in ggplot2library(ggtext) # Markdown text support for ggplot2library(showtext) # Display fonts in ggplot2library(colorspace) # Lighten and Darken colourslibrary(patchwork) # Compiling Plotssessioninfo::session_info()$packages |>as_tibble() |>select(package, version = loadedversion, date, source) |>arrange(package) |> janitor::clean_names(case ="title" ) |> gt::gt() |> gt::opt_interactive(use_search =TRUE ) |> gtExtras::gt_theme_espn()
Table 1: R Packages and their versions used in the creation of this page and graphics
An attempt at an Interactive Version
Code
# A map with utm zones and countries falling in itworld_map <- rnaturalearth::ne_countries(scale ="small",returnclass ="sf") |>select(name, geometry) |>st_transform("EPSG:4326")utm_zones <-read_sf( here::here("data","world_utm_grid_arcgis.gpkg" )) |> janitor::clean_names() |>mutate(id =row_number()) |>st_transform("EPSG:4326")utm_zones |>slice_head(n =5)