AmyMikhail / Geomapcoder

Multilingual shiny app to find and geocode postal addresses on a map
GNU General Public License v3.0
2 stars 2 forks source link

Adapt geomapcoder to facilitate offline use #6

Open AmyMikhail opened 1 month ago

AmyMikhail commented 1 month ago

Problem statement:

Currently, the user needs to have access to the internet for the first step - selecting the country and zooming in on the map. Ideally, it would be better to be able to save the map on first use of the app and not need to have internet access thereafter. Equally, if using shapefiles, it would be better to save the column names on first use and only change them if the user uploaded a different shape file.

Proposed solution:

Create a checkbox option in the UI to save parameters. If ticked, use observeEvent(input$saveparams...) to save parameters to an .rda file, listing each of the elements to be saved (country, map, region name and region code column names) with the save() command. Then put the following at the top of the app after package loading and before the UI:

if(file.exists("geomapcoder_settings.rda")){

  load("geomapcoder_settings.rda")

}

The appropriate method for saving leaflet tiles needs to be identified.

AmyMikhail commented 1 month ago

Using leaflet.extras::addSearchOSM(options = searchOptions(zoom = 5)) is a nice alternative to zooming in on the country of interest (puts a search bar on the map itself). It is quite quick and takes any language (though selections are in English).

It should be possible to record the country selected when the user types in the search bar, then feed this into osmdata to fetch the bounding box for that country, re-render the map with that bounding box and save the map tiles within the bounding box for offline use.

AmyMikhail commented 1 month ago

The following code works to save the map but map tiles are grey when zooming in:

# Load packages
pacman::p_load(rio, 
               here, 
               osmdata, 
               sf, 
               leaflet, 
               tidyverse)

# Define country
country <- "Haiti"

# Get country bounding box in right format:
b1 <- getbb(country, format_out = "sf_polygon")
b2 <- st_as_sf(b1$multipolygon, crs = 4326)
b3 <- st_bbox(b2) %>% as.vector()

# Render leaflet map fitting to boundary box:
mymap <- leaflet() %>%
  addProviderTiles(
    providers$OpenStreetMap,
    options = tileOptions(
      minZoom = 5, 
      maxZoom = 18,
      unloadInvisibleTiles = FALSE
  )) %>% 
  fitBounds(b3[1], b3[2], b3[3], b3[4])

# Save the map as an RDS object:
rio::export(mymap, file = here("map_data", "countrymap.RDS"))

# Load the map offline:
mymap <- rio::import(here("map_data", "countrymap.RDS"))