# Have you met Leaflet.JS?
library(leaflet)
# URL for the MapServer
<-
NSW_basemap_url "http://maps.six.nsw.gov.au/arcgis/rest/services/public/NSW_Base_Map/MapServer/WMTS"
# Build a request for the server
<- "&layer=public_NSW_Base_Map"
NSW_basemap_layer
<- paste0(
nsw_basemap
NSW_basemap_url,"?Request=GetTile",
"&Service=WMTS",
"&Version=1.0.0",
"&Style=default",
"&tilematrixset=default028mm",
"&Format=image/jpgpng",
NSW_basemap_layer,"&TileMatrix={z}",
"&TileRow={y}",
"&TileCol={x}"
)
# Don't forget the attribution
<-
attrib_string sprintf(" © State of New South Wales, Department of Customer Service, Spatial Services %s",
date()
)
# Create a map with this tile set
leaflet() |>
setView(lng = 151.2365, lat = -33.916, zoom = 15) |>
addTiles(urlTemplate = nsw_basemap,
attribution = attrib_string,
group = 'NSW basemap'
)
JR the (virtual) explorer!
Believe it or not, I do not spend my whole time sitting in front of my Desktop computer. Sometimes I do get out and explore this wonderful country, look:
But yeah, most of the time I am exploring the world through geospatial data. And since I am clearly obsessed with reproducible workflows, I want to code my way through the process, and make sure I can produce the building blocks for future virtual explorations.
So I asked myself this question, How do I make a good base map for exploring New South Wales (Australia) in as few lines of code as possible? Well it seems NSW Spatial Services has the data that I need!
Today I will create a minimal example for creating a dynamic map using these layers, R and the leaflet
package.
Data from Spatial NSW
If you navigate from the NSW Spatial Services to the Web services pages you will find that:
Web services are released under open access licences as part of the NSW Government Open Data Policy to support new and innovative uses of NSW Government digital information.
That is great, lets do some new and innovative uses of the digital information!
There are many data in different themes to choose from: Imagery, Land Cover, Physiography…
The documentation in their webpage focuses on two supported protocols here REST API and WMS, and the favourite GIS software of many users. But what about the few of us with different taste?. I though my use case would fall within the Advanced User Guide, but it seems I still needed to sort out many details to get it to work in R using the leaflet
package.
This is how it’s done
Short and sweet in as few lines of code as possible:
Code explained
Ok, now let’s go over the code and describe the steps in more detail. This will help you understand the process better and provide more info on how to adapt this example to your needs.
Have you met Leaflet.JS?
I have probably said this before, but Leaflet JS https://leafletjs.com/ is probably the most popular open-source JavaScript library for mobile- and web-friendly interactive maps. With an easy to use and well-documented API, many developers have contributed libraries, modules, plug-ins and interfaces to implement leaflet maps from your favourite programming languages and development platforms. Here we are using the R package https://rstudio.github.io/leaflet/ to integrate these JS functions in R.
library(leaflet)
URL for the MapServer
We need the address of the MapServer that hold the layer we want to display. This step is not as easy as it should be, but with patience you will get there. The spatial portal has so many levels of information, you can easily click around in circles without getting the info you need.
So here is one possible way NOT to get there:
- Start at https://www.spatial.nsw.gov.au
- Click on NSW Spatial Collaboration Portal
- Go to Browse Data
- Select a theme, for example Imagery and Landcover
- Within the theme, select the web map you want, for example NSW Imagery Basemap Service
- You can see this is getting silly, click on the ‘Open in Map Viewer’ and despair…
- Within the theme, select the web map you want, for example NSW Imagery Basemap Service
- Select a theme, for example Imagery and Landcover
- Go to Browse Data
- Click on NSW Spatial Collaboration Portal
So finally we have the URL:
# URL for the MapServer
<-
NSW_basemap_url "http://maps.six.nsw.gov.au/arcgis/rest/services/public/NSW_Base_Map/MapServer/WMTS"
Build a request for the server
Now we need to build a request for the server.
This starts with getting the capabilities of the server by visiting this url in a browser:
paste0(NSW_basemap_url, "?Request=GetCapabilities")
[1] "http://maps.six.nsw.gov.au/arcgis/rest/services/public/NSW_Base_Map/MapServer/WMTS?Request=GetCapabilities"
You will get a document in XML format that has the information we need for the next request.
For example the layer identifier:
Layer>
<ows:Title>public_NSW_Base_Map</ows:Title>
<ows:Identifier>public_NSW_Base_Map</ows:Identifier>
< ...
Also Style:
Style isDefault="true">
<ows:Title>Default Style</ows:Title>
<ows:Identifier>default</ows:Identifier>
<Style> </
And others…
And then we concatenate the mapserver url and the layer name with a couple of parameters needed in our WMTS GetTile
request:
<- paste0(
nsw_basemap
NSW_basemap_url,# Service (version) request
"?Service=WMTS",
"&Request=GetTile",
"&Version=1.0.0",
# the following need to match the details in the GetCapabbilities request
"&Style=default", # usually there is only one style
"&tilematrixset=default028mm", # usually default028mm or GoogleMapsCompatible
"&Format=image/png", # check the available format, sometime it is image/jpgpng
"&layer=public_NSW_Base_Map", # check the name of the layer
# The x,y,z dimensions dynamically requested
# based on the zoom and coordinates of the viewer window
"&TileMatrix={z}",
"&TileRow={y}",
"&TileCol={x}"
)
Don’t forget the attribution
<-
attrib_string sprintf(" © State of New South Wales, Department of Customer Service, Spatial Services %s",
date()
)
Create a map with this tile set
leaflet() |>
setView(lng = 151.2365, lat = -33.916, zoom = 15) |>
addTiles(urlTemplate = nsw_basemap,
attribution = attrib_string,
group = 'NSW basemap'
)
And here some bonus tips
Other layers from same base URL 😀
Now that this is working, I got curious about other layers available in the same portal.
Some of the sources have the same base url and we just need to change the name of the layer, for example we can use a function in package stringr
to replace the base map with imagery:
library(stringr)
<- str_replace_all(nsw_basemap, "NSW_Base_Map", "NSW_Imagery")
nsw_imagery leaflet() |>
setView(lng = 151.2365, lat = -33.916, zoom = 14) |>
addTiles(urlTemplate = nsw_imagery,
attribution = attrib_string
)
Other layers from other base URL 😕
I also found historical aerial photographs, but the base url is different and for some reason I have been unable to create a request that works in leaflet, this code seems to be right, but the result is blank:
<- paste0(
nsw_historical "https://portal.spatial.nsw.gov.au/tileservices/Hosted/HistoricalImagery1947/MapServer/",
"WMTS?",
"Request=GetTile",
"&Service=WMTS",
"&Version=1.0.0",
"&Style=default",
"&tilematrixset=default028mm",
"&Format=image/jpgpng",
"&layer=HistoricalImagery1947",
"&TileMatrix={z}",
"&TileRow={y}",
"&TileCol={x}"
)leaflet() |>
setView(lng = 151.2365, lat = -33.916, zoom = 14) |>
addTiles(urlTemplate = nsw_historical,
attribution = attrib_string
)
There are also some datsets using Vector tile layers, for example:
https://portal.spatial.nsw.gov.au/vectortileservices/rest/services/Hosted/NSW_BaseMap_VectorTile_Hybrid/VectorTileServer
I haven’t yet figured out how to add them in Leaflet.
Multiple layers in one map 🌐
Now we have at least two base layers, and we would like to display both in a map. We can do that with help of the addLayersControl
function using the argument baseGroups
to identify the groups of layers to choose from:
leaflet() |>
setView(lng = 151.2365, lat = -33.916, zoom = 14) |>
addTiles(urlTemplate = nsw_basemap,
attribution = attrib_string,
group = 'NSW base map'
|>
) addTiles(urlTemplate = nsw_imagery,
attribution = attrib_string,
group = 'NSW imagery'
|>
) addLayersControl(
baseGroups = c("NSW imagery", "NSW base map"))
Conclusion
Here we use R and leaflet to load geospatial layers using WMTS services. Thanks to NSW Spatial service for the awesome products!
Here the basic recipe:
- Find the WMTS server,
- Send a
GetCapabilities
request - Identify the layer of interest and other parameters,
- Build your WMTS request,
- Add the layer to your leaflet map using the
addTile
function - Optional:
- Repeat with other layers
- Add a layers control with
addLayersControl
function
- Done!
I hope this makes it easier for you to create your maps visualisations with R. Enjoy!