Show libraries code
library(tidyverse)
library(googlesheets4)
library(mapview)
library(sf)
library(leaflet)
library(htmltools)
library(ggmap)
Isaac Bain
July 2, 2024
The Permolat Trust maintains a unique and iconic network of around 70 remote back-country huts and bivouacs in Central Westland. Before the Trust took on their care, these huts were in a dilapidated state and under threat of disappearing due to lack of use and funding. The primary reason for their disuse was the difficulty in accessing them and obtaining up-to-date route information.
These huts differ from the typical serviced DOC huts. They are all very small (typically 1 to 4 bunks), have long, challenging approaches, and are maintained by volunteer labour. Unlike the more accessible DOC huts, these remote huts offer a truly authentic and rugged back-country experience. They are nestled in some of the most untouched and pristine environments, requiring a good level of fitness, navigation skills, and a sense of adventure to reach.
The Trust relies heavily on the dedication and hard work of volunteers, who invest countless hours in maintaining and restoring these huts. Their efforts ensure that these historic and culturally significant structures are preserved for future generations to explore and enjoy.
Here’s just a couple of my favourites:
The Permolat Trust has created the Remote Huts website which is a fantastic resource for obtaining key details about each of their huts. Each individual hut page features a topographic map showing the hut and its surrounds, like so:
However, the site lacked an overview map displaying the relative location of all their huts - which would be useful for trip planning and discovering new huts to visit. After confirming with their webmaster they did not have a database of their hut listings, I scraped all the necessary data into a Google Sheet, from which my map is drawn. Using a Google Sheet is a good idea from a technical perspective because it allows for easy data manipulation, integration with various mapping and visualisation tools, and real-time collaboration and updates.
The static map provides a basic visual overview of the Permolat Trust’s network of huts across the South Island. Using the ggmap
package, a base layer of the South Island was retrieved and plotted with the hut locations overlaid. But the real magic comes next…
# bounding box for South Island
si <- c(left = 166.25, bottom = -47.5, right = 174.5, top = -40.0)
# retrieve base layer
map <- get_stadiamap(si, zoom = 8, maptype = "stamen_terrain_background")
# Define a function to fix the bbox to be in EPSG:3857
# https://stackoverflow.com/questions/47749078/how-to-put-a-geom-sf-produced-map-on-top-of-a-ggmap-produced-raster
ggmap_bbox <- function(map) {
if (!inherits(map, "ggmap")) stop("map must be a ggmap object")
# Extract the bounding box (in lat/lon) from the ggmap to a numeric vector,
# and set the names to what sf::st_bbox expects:
map_bbox <- setNames(unlist(attr(map, "bb")),
c("ymin", "xmin", "ymax", "xmax"))
# Coonvert the bbox to an sf polygon, transform it to 3857,
# and convert back to a bbox (convoluted, but it works)
bbox_3857 <- st_bbox(st_transform(st_as_sfc(st_bbox(map_bbox, crs = 4326)), 3857))
# Overwrite the bbox of the ggmap object with the transformed coordinates
attr(map, "bb")$ll.lat <- bbox_3857["ymin"]
attr(map, "bb")$ll.lon <- bbox_3857["xmin"]
attr(map, "bb")$ur.lat <- bbox_3857["ymax"]
attr(map, "bb")$ur.lon <- bbox_3857["xmax"]
map
}
# Use the function:
map <- ggmap_bbox(map)
# create the static map
ggmap(map) +
coord_sf(crs = st_crs(3857)) + # force the ggplot2 map to be in 3857
geom_sf(data = df |> st_transform(3857),
inherit.aes = FALSE,
aes(),
color = "blue",
size = 1.5)
The interactive map offers a dynamic way to explore the Permolat Trust’s huts across the South Island. It includes several user-friendly features:
Hover to View Details: Users can hover over any point to see the hut’s name and a photo, making it easy to identify and learn more about each hut.
Clickable Points: Clicking on any point takes users directly to the Remote Huts website for detailed information about the hut.
Customizable Base Maps: Users can switch between different base maps, including terrain, Topographic 1:50k and 1:250k, and satellite views. This functionality, available via a control in the upper right corner, allows users to choose the most useful map type for their needs.
The interactive map is created using the leaflet
package, which provides powerful tools for building interactive maps. Here’s a breakdown of the key steps:
Popup Content: The hover popups display the hut’s name and image, generated using HTML content.
Click Event: JavaScript is used to add click events to each point, linking to the corresponding hut page on the Remote Huts website.
Base Layers: Various base map layers are added using addProviderTiles
and addTiles
, giving users multiple perspectives of the terrain.
# column: screen-inset-shaded
# create hover popup spec
content <- paste0("<div style='text-align: center;'><b>", df$Name, "</b></div>", "<img src = '", df$Image, "', width = '175'>")
# goto url on click
jsCode <- paste0('
function(el, x, data) {
var markers = document.getElementsByClassName("leaflet-interactive");
for(var i = 0; i < markers.length; i++){
(function(){
var v = data.URL[i];
markers[i].addEventListener("click", function() { window.open(v); }, false);
}());
}
}
')
# setup xyz tiles
topo50_tiles <- paste0(
"https://tiles-cdn.koordinates.com/services;key=", Sys.getenv("koordinates_tile_api"), "/tiles/v4/layer=50767/EPSG:3857/{z}/{x}/{y}.png"
)
topo250_tiles <- paste0(
"https://tiles-cdn.koordinates.com/services;key=", Sys.getenv("koordinates_tile_api"), "/tiles/v4/layer=50798/EPSG:3857/{z}/{x}/{y}.png"
)
# create leaflet map
map <-
leaflet(df) %>%
addMapPane(name = "circles", zIndex = 410) %>%
addCircleMarkers(
color = "black",
fillColor = "blue",
radius = 5,
fillOpacity = 0.75,
stroke = T,
weight = 1,
opacity = 1,
label = lapply(content, htmltools::HTML),
) %>%
addProviderTiles(providers$CartoDB.Voyager, group = "Terrain") %>%
addTiles(topo50_tiles, group = "Topo50") %>%
addTiles(topo250_tiles, group = "Topo250") %>%
addProviderTiles(providers$Esri.WorldImagery, group = "Satellite") %>%
addLayersControl(
baseGroups = c("Terrain", "Topo250", "Topo50", "Satellite"),
options = layersControlOptions(collapsed = FALSE)
) %>%
htmlwidgets::onRender(jsCode, data = df)
map
Exploring potential remote huts to visit is now much easier than ever before, with the overview map of the South Island. This same map is also available directly via the Remote Huts website, allowing users to explore by A-Z, by river catchment, and now by map!
This is a great result for backcountry users and the Permolat Trust, which now has a web-map integrated into their existing website infrastructure at zero cost.
Which one do you plan on visiting?