polr

The goal of polr is to provide bindings to the OpenLayers javascript library, with a focus on polar mapping applications.

Installation

remotes::install_github("SCAR/polr")

## or

install.packages("polr", repos = c("https://scar.r-universe.dev", "https://cloud.r-project.org"))

Example usage

Shiny app

library(polr)
library(shiny)

ui <- fluidPage(
  polOutput("map", height = "80vh", width = "100%"),
  actionButton("add_cog", "Add COG"),
  actionButton("remove_cog", "Remove COG", disabled = TRUE)
)

server <- function(input, output, session) {
  output$map <- renderPol({
      polr::pol(view_options = list(extent = 6e6 * c(-1, -1, 1, 1))) %>%
          ## add a layer from a WMS server
          add_wms_tiles(url = "https://geos.polarview.aq/geoserver/wms",
                        layers = "polarview:coastS10") %>%
          ## add lines from a local file in flatgeobuf format
          add_fgb(file = system.file("extdata/fronts_park.fgb", package = "polr"),
                  style = list(`stroke-color` = "black"), zIndex = 99)
  })

  ## dynamically update the map
  prox <- pol_proxy("map")
  observeEvent(input$add_cog, {
      ## when the button is clicked, add a COG (cloud-optimised geotiff)
      prox %>% add_cog(
                   "https://data.source.coop/scar/distant/hindell_et_al-2020/Hi2023-aes_colony_weighted_cog.tif",
                   geotiff_source_options = list(interpolate = FALSE), opacity = 0.7,
                   style = list(color = pol_colormap(hcl.colors(21, "Spectral", rev = TRUE))),
                   name = "COG layer")
      updateActionButton(session, inputId = "add_cog", disabled = TRUE) ## can't add twice
      updateActionButton(session, inputId = "remove_cog", disabled = FALSE) ## but we can now remove it
  })
  observeEvent(input$remove_cog, {
      prox %>% remove_layer("COG layer")
      updateActionButton(session, inputId = "add_cog", disabled = FALSE)
      updateActionButton(session, inputId = "remove_cog", disabled = TRUE)
  })
}

shinyApp(ui = ui, server = server)

A standalone widget (e.g. for Rmarkdown)

library(htmltools)
library(lorem)

## random text formatted as HTML for popups
px <- sapply(1:100, function(i) as.character(tags$div(tags$h1(ipsum_words(3)), ipsum_words(5))))

polr::pol(view_options = list(extent = 6e6 * c(-1, -1, 1, 1))) %>%
    ## background layer
    add_wmts_from_capabilities("https://services.arcgisonline.com/arcgis/rest/services/Polar/Antarctic_Imagery/MapServer/WMTS/1.0.0/WMTSCapabilities.xml",
                               layer = "Polar_Antarctic_Imagery", zIndex = -1) %>%
    ## WMS coastline layer in polar stereographic projection
    add_wms_tiles(url = "https://geos.polarview.aq/geoserver/wms", layers = "polarview:coastS10",
                  name = "Coastline") %>%
    ## local geojson lines file
    add_geojson(file = system.file("extdata/fronts_park.geojson", package = "polr"),
                style = pol_style(stroke = list(color = "green")), data_proj = "EPSG:4326",
                name = "Fronts") %>%
    ## markers, shown as clusters
    add_clustered_points(lon = (runif(100) - 0.5) * 360, lat = runif(100) * -40 - 40,
                         cluster_options = list(distance = 50),
                         cluster_style = pol_style(text = list(fill = list(color = "blue")),
                                                   circle = list(fill = list(color = "orange"))),
                         marker_style = pol_style(text = list(text = "\uf041",
                                                              font = "normal 18px FontAwesome",
                                                              fill = list(color = "#00f"))),
                         popup = px, name = "Markers") %>%
    ## add a legend that allows layers to be turned on and off
    add_layer_switcher()

Projections

OpenLayers is quite forgiving when it comes to projections: layers will typically be reprojected automatically to the map projection. That means that you can add a layer in longitude-latitude coordinates to a polar-projected map, and the layer will be reprojected as required. However, be aware that you might still encounter issues:

Development notes

polr provides bindings to the OpenLayers javascript library, and uses the excellent packer package to facilitate the interactions between R and javascript.

Some notes:

See https://book.javascript-for-r.com/packer-adv and https://github.com/JohnCoene/packer for more information about packer.