0

I would like to add local tiles for leaflet to render them offline in a shiny application. Although there are solutions to this on SO for example here and here , I am still ending up with grey map with no tiles. It would really help me to see some reproducible example. Thanks.

My example code:

library(shiny)
library(dplyr)
library(RgoogleMaps)

#downloads tiles for a given regions, saves it to C:/Users/.../mapTiles/OSM
for (zoom in 0:16)
  GetMapTiles(center = c(lat = 52.431635, lon = 13.194773),
              zoom = zoom,
              nTiles = round(c(20,20)/(17-zoom)))
#shiny ui 
ui = fluidPage(leafletOutput("map"))

#create basic map, load tiles from directory and set view to centre of downloaded tiles
server = function(input, output, server){
  addResourcePath(prefix = "OSM", "C:/Users/.../mapTiles")
  output$map = renderLeaflet({
    leaflet() %>% 
      addTiles( urlTemplate = "/OSM/{z}_{x}_{y}.png") %>% 
      setView(52.431635, 13.194773 , zoom = 10) %>%  #set to the location with tiles
      addMarkers(52.431635, 13.194773 )
  }
  )
}

shinyApp(ui, server)
ayasugihada
  • 329
  • 1
  • 2
  • 13
  • the "OSM" in `addResourcePath` is acting similar to an object so must be the complete path, i.e. you've missed off '/OSM' from the end of the path. Under `addTiles` , OSM is translated back to the full path it represents. Also double check the tiles are present at the zoom level of 10 in the folder. – Sam Dec 04 '19 at 10:59
  • I have tried to use `addResourcePath(prefix = "OSM", "C:/Users/.../mapTiles/OSM")` before. But it is not working. In that case, you say the problem might be with tiles themselves? The example tile for zoom=10 looks like this: _10_550_336.png_ – ayasugihada Dec 04 '19 at 11:24
  • under the parent file "OSM", the folder structure should be a separate file for each zoom level (9,10,11,12,13....) and in those folders, you should have yet more folders representing the total tiled area via a system of squares at that zoom level, and in those folders the .png files. Your file structure may be wrong. – Sam Dec 04 '19 at 11:30
  • Well, you're right that I have bad folder structure. Can you please add answer with an example of proper folder structure? I am not getting the last _"yet more folders representing the total tiled area via a system of squares at that zoom level"_ . Thank you! – ayasugihada Dec 04 '19 at 11:42

2 Answers2

3

In my case, I create my own tiles via gdal2tiles, which takes your data and automatically creates a {z}/{x}/{y}.png folder structure. Please see this link for a nice tutorial and what i mean about the file structure;

+---14
|   +---8185
|     +---5460.png
|     +---5461.png
|     +---etc.png
|   \---8186

# I use the following server (see how my addTiles has a folder structure)
server <- function(input, output,session) {
   addResourcePath("mytiles", "C:/.../tiles")
   output$tilemap <- renderLeaflet({
     leaflet() %>%
       setView(lng = -4.4, lat = 52, zoom = 12) %>%
       addTiles(urlTemplate = "mytiles/{z}/{x}/{y}.png")

   })
}

Now, as you are downloading tiles from Google Maps to your hard drive, you'll want a slightly different approach as the files are downloaded in a {z}_{x}_{y}.png format, and not produced into a file structure like gdal creates;

+---11_1098_671.png etc.

so you need to adjust your addTiles code to reflect this, using underscores, like the Google filenames;

server <- function(input, output,session) {
  addResourcePath("mytiles", "C:/.../OSM")
  output$tilemap <- renderLeaflet({
    leaflet() %>%
      setView(lng = 13.194773, lat = 52.431635, zoom = 11) %>%
      addTiles(urlTemplate = "mytiles/{z}_{x}_{y}.png")

  })

}

Lastly, my setView arguments are in a different order to yours but i'm not sure whether that makes a difference or not.

Sam
  • 1,400
  • 13
  • 29
  • Thanks for your time & help. I don't want to further bother you, either of the options still haven't worked for me. Even tried to manually create structure like this _.../OSM/10/548/335.png_ (the suggested structure from reference link). I will give it some rest, before going through all reference I can get. Possibly trying to create the structure using gdal2tiles. Will post about the progress, if there's any. Thanks again! – ayasugihada Dec 04 '19 at 13:37
  • good luck, I used the exact download you gave in your example with my code in the 2nd half of my answer and it gave me some tiles in Berlin, so i'm not sure what is going wrong for yours – Sam Dec 04 '19 at 14:52
  • It works! Tried it at home and it immediately worked! Thanks a ton. – ayasugihada Dec 04 '19 at 18:04
1

i tried this solution but it could not work,the topic is old but it really helped me to achieve what i wanted to do, i found another solution for those of you in the same case by creating two ports :

  • just define two differents ports for your shiny server( 3838) and for the server hosting the tiles (8000)

servr::httd(dir="C:/TestApp/data_hydrepat/tiles_hydrepat/mapTiles/mytiles",daemon=TRUE,port=8000) options(shiny.port = 3838)

  • to close the server hosting the tiles, just put a reactive on an input or something.. and close

(servr::daemon_stop(which = daemon_list())

hope it'll help !

Anthony Ta
  • 41
  • 4