Inspired by the great Nicola Rennie of Fosstodon and her typewritten map of Scotland I have felt the need to pay her the highest form of flattery by imitating her work.

My own country felt a better start than distant Scotland, and it seemed to me as a good idea to share the code.

The first step is acquiring the raw elevation raster; I am building on the one provided by vyskopis() function of {RCzechia} package. But any DEM file read in via {terra} would do…

library(terra)   # for raster manipulation
library(ggplot2) # for plotting the plot
library(dplyr)   # for generic data frame manipulation

# raw raster - elevation of Czechia (from original DEM)
src_raster <- RCzechia::vyskopis("actual") 

# a visual overview
plot(src_raster)

The second step is downsampling the raster drastically, so that a single raster cell will be rendered as a letter, and casting it from raster to a data frame, minding the xy argument to as.data.frame method of SpatRaster. By setting it to TRUE we will keep the coordinates of the raster cells, which will be of great help in placing our letters via ggplot2::geom_text().

I discretized the elevation to three letters - l for lowlands, h for hills and capital M for Big Mountains - via base::cut().

What turned out to be a slight challenge was plot aspect ratio; my DEM file was in geographic coordinates, and since Czechia is not quite on equator the degrees of latitude and longitude do not translate to the same distance. I was able to overcome this by getting the aspect ratio from my raster reprojected to a metric CRS (Web Mercator specifically).

The remaining fun part was finding a sufficiently old fashioned monospaced font that could plausibly pass for typewritter. I settled on Special Elite from Google Fonts.

# cast elevation from raster to data frame
map_src <- src_raster %>% 
  terra::aggregate(fact = 30) %>% # downsample the raster by factor of 30
  as.data.frame(xy = T) %>% # convert raster to data frame, preserving coordinates
  mutate(category = cut(Band_1,
                        breaks = c(0, 400, 600, Inf),
                        labels = c("l", "h", "M")))

# get raster extent in meters for aspect ratio
bbox <- sf::st_bbox(project(src_raster, "EPSG:3857"))
aspect_ratio <- (bbox$ymax - bbox$ymin) / (bbox$xmax - bbox$xmin)

# now draw the rest of the map! :)
ggplot(data = map_src,
       aes(x = x, y = y, label = category)) +
  geom_text(family="Special Elite", 
            size = 1.5) +
  labs(title = "Czechia in monospace",
       caption = "Typed with love and #rstats by fosstodon.org/@jladata ") +
  theme_void() +
  theme(aspect.ratio = aspect_ratio,
        plot.title = element_text(family = "Special Elite",
                                  hjust = 1/2,
                                  size = 30,
                                  color = "black"),
        plot.caption = element_text(family = "Special Elite",
                                    size = 6,
                                    color = "grey50"))