R/GetMapTiles.R

# tile2long = function(x,z){ return (x/(2^z)*360-180); }
# tile2lat= function(y,z) { n=pi-2*pi*y/(2^z);
#                           return (180/pi*atan(0.5*(exp(n)-exp(-n)))); }


`GetMapTiles` <- structure(function# download map tiles from specified map tile servers such as openstreetmap or Google
### Query the server for map tiles, defined uniquely by their 
### X and Y ID and zoom. For offline usage, these map tiles are stored in a local directory
(
  center=c(lat=52.431635, lon=13.194773), ##<< optional center (lat first,lon second  )
  lonR, ##<< longitude range
  latR, ##<< latitude range
  nTiles = c(3,3), ##<< number of tiles in x and y direction
  #size = c(640,640), ##<< desired size of the map tile image. defaults to maximum size returned by the Gogle server, which is 640x640 pixels 
 # taskfile = "Zehlendorf", ##<<  File to save the meta information to.
  zoom =13, ##<< Google maps zoom level.
 # maptype = c("roadmap","mobile","satellite","terrain","hybrid","mapmaker-roadmap","mapmaker-hybrid")[1], ##<< defines the type of map to construct. There are several possible maptype values, including satellite, terrain, hybrid, and mobile. 
  urlBase = c("http://a.tile.openstreetmap.org/", "http://mt1.google.com/vt/lyrs=m", "http://tile.stamen.com/toner","http://tile.stamen.com/watercolor")[1], ##<< tileserver URL
  CheckExistingFiles = TRUE, ##<< logical, if TRUE check if files already exist and only download if not!
  TotalSleep = NULL, ##<< overall time (in seconds) that one is willing to add in between downloads. This is intended to lower the risk of a server denial. If NULL no call to \link{Sys.sleep} is executed
  #format = c("gif","jpg","jpg-baseline","png8","png32")[5],  ##<< (optional) defines the format of the resulting image. By default, the Static Maps API creates GIF images. There are several possible formats including GIF, JPEG and PNG types. Which format you use depends on how you intend to present the image. JPEG typically provides greater compression, while GIF and PNG provide greater detail. This version supports only PNG.
  #RETURNIMAGE = TRUE, ##<< return image yes/no default: TRUE
  #GRAYSCALE =FALSE, ##<< Boolean toggle; if TRUE the colored map tile is rendered into a black & white image, see \link{RGB2GRAY}
  #NEWMAP = TRUE, ##<< if TRUE, query the Google server and save to \code{destfile}, if FALSE load from destfile. 
  #SCALE = 1, ##<< use the API's scale parameter to return higher-resolution map images. The scale value is multiplied with the size to determine the actual output size of the image in pixels, without changing the coverage area of the map
  tileExt = ".png", ##<< image type of tile
  tileDir= "~/mapTiles/OSM/", ##<< map tiles are stored in a local directory
  returnTiles = FALSE, ##<< return tiles in a list?
  verbose=0 ##<< level of verbosity
){
  ##note<<Note that size is in order (lon, lat)
  #if (missing(destfile)) destfile=file.path(tempdir(),"mapTile.png")
  #require(RgoogleMaps)
  
  if (is.character(center)) {
    if (verbose) cat("geocoding ", center, "\n")
    center = getGeoCode(center,verbose)
    if (verbose) cat("result:", center, "\n")
  }
  if (all(c("lat","lon") %in% names(center))) center = center[c("lat","lon")] else names(center) = c("lat","lon")
  ##seealso<< \link{GetMap.bbox}
  #turn out we do NOT HAVE TO cap the zoom to a fake 13 after all !!
  # We can truthfully record the correct zoom level, YES
  fakeZoom = zoom#min(zoom,13)
  #if (!is.null(center)) center <- paste(center,collapse=",")
  if (!missing(lonR) & !missing(latR)) {
    XYmin = LatLon2XY(lat=latR[1], lon=lonR[1],zoom=zoom)
    XYmax = LatLon2XY(lat=latR[2], lon=lonR[2],zoom=zoom)
    nTiles[1] = abs(XYmax$Tile[1,1]-XYmin$Tile[1,1])+1
    nTiles[2] = abs(XYmax$Tile[1,2]-XYmin$Tile[1,2])+1
    #browser()
    #if (missing(center) | is.null(center)) 
      center = c(lat=mean(latR),lon=mean(lonR))
    if (verbose){
      cat("nTiles=",nTiles,", center=", round(center,3), "\n")
    }
  } #else {
    XY = LatLon2XY(lat=center["lat"], lon=center["lon"],zoom=zoom)
    tileXY = XY$Tile + as.numeric(XY$Coords > 256)
  #}
  if (nTiles[1] %% 2 == 0) {#even
    X = (tileXY[1,1]-nTiles[1]/2):(tileXY[1,1]+nTiles[1]/2-1);
  } else {
    X = (tileXY[1,1]-(nTiles[1]-1)/2):(tileXY[1,1]+(nTiles[1]-1)/2);
  }
  if (nTiles[2] %% 2 == 0) {#even
    Y = (tileXY[1,2]-nTiles[2]/2):(tileXY[1,2]+nTiles[2]/2-1);
  } else {
    Y = (tileXY[1,2]-(nTiles[2]-1)/2):(tileXY[1,2]+(nTiles[2]-1)/2);
  }
  
  if (verbose>1) browser() 
  if (!dir.exists(tileDir)) {
    if (verbose) cat("trying to create dir",tileDir, "\n")
    dir.create(tileDir, recursive = TRUE)
  }
  if (CheckExistingFiles) ExistingFiles=list.files(path=tileDir)
  
  NumTiles = length(X)*length(Y)
  if (verbose) cat (NumTiles, "tiles to download \n")
    
  #http://a.tile.openstreetmap.org/15/9647/12321.png
  DOWNLOAD=TRUE
  k=1;tiles=list()
  for (x in X){
    for (y in Y){
      if (grepl("openstreetmap",urlBase) | grepl("stamen",urlBase)){
        url <- paste0(urlBase, zoom, "/",x , "/", y, ".png")
      } else if (grepl("google",urlBase)){
        url <- paste0(urlBase, "&x=", x, "&y=", y, "&z=", zoom)
      } 
		  #browser()
      #print(url)
      # we need to keep the x and y coords to 4 digits!
      #xFake = x
      #yFake = y
      f=paste(zoom, x, y, sep="_")
		  if (CheckExistingFiles) 
        if (paste0(f,tileExt) %in% ExistingFiles) {
          if (verbose) cat("NOT downloading existing file ",f, tileExt, "\n",sep="" )
          DOWNLOAD=FALSE
        } else {
          DOWNLOAD=TRUE
        }
      destfile = file.path(tileDir, f)
      mapFile=paste0(destfile,tileExt)
      if (DOWNLOAD){
  		  if (!is.null(TotalSleep)){
  		    Sys.sleep(round(runif(1,max=2*TotalSleep/NumTiles),1))
  		  }
  		  download.file(url, mapFile, mode="wb", quiet = TRUE);
      }
      if (returnTiles){
        res=try(readPNG(mapFile, native=TRUE))
        if (class(res)=="try-error"){#download again
          download.file(url, mapFile, mode="wb", quiet = TRUE);
        } else tiles[[k]]=res
        
      } 
      #browser()
		  k=k+1
    }
  }
  mt = list(X=X,Y=Y,zoom=zoom,tileDir=tileDir,tileExt=tileExt,tiles=tiles)
  class(mt) =  "mapTiles"
  invisible(mt)	
### list with important information
}, ex = function(){
  if (0){
  tmp=GetMapTiles("World Trade Center, NY", zoom=15,nTiles = c(5,5), verbose=1)
  PlotOnMapTiles(tmp)
  tmp=GetMapTiles("World Trade Center, NY", zoom=16,nTiles = c(20,20), verbose=1)
  
  tmp2=GetMapTiles("World Trade Center, NY", zoom=15,nTiles = c(5,5), verbose=1,
                  urlBase = "http://mt1.google.com/vt/lyrs=m", 
                  tileDir= "~/mapTiles/Google/")
  tmp=GetMapTiles("Hoboken, NJ", zoom=16,nTiles = c(30,30), verbose=1,
                  urlBase = "http://mt1.google.com/vt/lyrs=m", 
                  tileDir= "~/mapTiles/Google/")
  PlotOnMapTiles(tmp2)
  
  tmp2=GetMapTiles("Werderscher Markt 15, 10117 Berlin", zoom=15,nTiles = c(20,20), verbose=0,
                   urlBase = "http://mt1.google.com/vt/lyrs=m", 
                   tileDir= "~/mapTiles/Google/")
  
  tmp2=GetMapTiles("World Trade Center, NY", zoom=15,nTiles = c(10,10), verbose=1,
                   urlBase = "http://tile.stamen.com/toner/", 
                   tileDir= "~/mapTiles/stamenToner/")
  
  GetMapTiles("World Trade Center, NY", zoom=16,nTiles = c(10,10), verbose=1,
                   urlBase = "http://tile.stamen.com/toner/", 
                   tileDir= "~/mapTiles/stamenToner/")
  
  PlotOnMapTiles(tmp2)
  
  
  ###combine with leaflet:
  #From:http://stackoverflow.com/questions/5050851/
  #     best-lightweight-web-server-only-static-content-for-windows
  #To use Python as a simple web server just change your working 
  #directory to the folder with your static content and type 
  #python -m SimpleHTTPServer 8000, everything in the directory
  #will be available at http:/localhost:8000/
    
  library(leaflet)
  m = leaflet::leaflet() %>% 
    addTiles( urlTemplate = "http:/localhost:8000/mapTiles/OSM/{z}_{x}_{y}.png")
  m = leaflet::leaflet() %>% 
    addTiles( urlTemplate = "http:/localhost:8000/mapTiles/Google/{z}_{x}_{y}.png")
  m = m %>% leaflet::setView(-74.01312, 40.71180, zoom = 16)
  m = m %>% leaflet::addMarkers(-74.01312, 40.71180)
  
  #Quadriga:
  m = m %>% leaflet::setView(13.39780, 52.51534, zoom = 16)
  m = m %>% leaflet::addMarkers(13.39780, 52.51534)
  }
  
})

Try the RgoogleMaps package in your browser

Any scripts or data that you put into this service are public.

RgoogleMaps documentation built on May 2, 2019, 5:03 p.m.