I haven't done this in a while, but I found my old code, edited it slightly and it still seems to work. It requires the RgoogleMaps
package as well as jpeg
and png
.
Essentially, I took the code from RgoogleMaps::GetMapTiles
and just modified it some to work with https://services.arcgisonline.com/ArcGIS/rest/services/World_Topo_Map/MapServer. Like I said, I did this a while ago so the code in RgoogleMaps::GetMapTiles
now, might be slightly different. But, if you have questions about the function arguments, that's where you should look (?RgoogleMaps::GetMapTiles
).
Here is the code for the function (make sure you have the three required packages).
library(RgoogleMaps)
getmaptiles <- function (center = c(lat = 52.431635, lon = 13.194773),
lonR, latR,
nTiles = c(3, 3), zoom = 13,
urlBase = "http://services.arcgisonline.com/arcgis/rest/services/World_Topo_Map/MapServer",
CheckExistingFiles = TRUE,
TotalSleep = NULL, tileExt = ".png",
tileDir= "~/mapTiles/WorldTopoMap/",
returnTiles = FALSE, verbose = 1)
{
require(png)
require(jpeg)
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")
fakeZoom = zoom
if (!missing(lonR) & !missing(latR)) {
XYmin = RgoogleMaps::LatLon2XY(lat = latR[1], lon = lonR[1], zoom = zoom)
XYmax = RgoogleMaps::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
center = c(lat = mean(latR), lon = mean(lonR))
if (verbose) {
cat("nTiles=", nTiles, ", center=", round(center,
3), "\n")
}
}
XY = RgoogleMaps::LatLon2XY(lat = center["lat"], lon = center["lon"],
zoom = zoom)
tileXY = XY$Tile + as.numeric(XY$Coords > 256)
if (nTiles[1]%%2 == 0) {
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) {
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")
DOWNLOAD = TRUE
k = 1
tiles = list()
for (x in X) {
for (y in Y) {
if(is.null(urlBase)){
cat("Not downloading any tiles. No url provided. \n")
}
else if (grepl("ESRI", urlBase)) {
url <- paste0(urlBase, zoom, "/", x, "/", y, ".jpeg")
}
else if (grepl("openstreetmap", urlBase)) {
url <- paste0(urlBase, zoom, "/", x, "/", y, ".png")
}
else if (grepl("google", urlBase)) {
url <- paste0(urlBase, "&x=", x, "&y=", y, "&z=", zoom)
}
else if (grepl("arcgis", urlBase)) {
url <- paste0(urlBase, "/tile/", zoom, "/", x, "/", 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))
}
if(is.null(urlBase)){ ######################################
NULL
} else {
download.file(url, mapFile, mode = "wb", quiet = TRUE)
}###########################################################
}
if (returnTiles) {
res = try(readPNG(mapFile, native = TRUE))
if (class(res) == "try-error") {
res = try(readJPEG(mapFile, native = TRUE))
}
else if (class(res) == "try-error") {
download.file(url, mapFile, mode = "w", quiet = TRUE)
}
else tiles[[k]] = res
}
k = k + 1
}
}
mt = list(X = X, Y = Y, zoom = zoom, tileDir = tileDir, tileExt = tileExt,
tiles = tiles)
class(mt) = "mapTiles"
invisible(mt)
}
Here's an example of downloading some map tiles from the given urlBase
into my working directory, in the tileDir
subfolders.
getmaptiles(center = c(lat = 52.431635, lon = 13.194773),
#lonR, latR,
nTiles = c(3, 3), zoom = 13,
urlBase = "http://services.arcgisonline.com/arcgis/rest/services/World_Topo_Map/MapServer",
CheckExistingFiles = FALSE,
TotalSleep = NULL, tileExt = ".jpg",
tileDir= "~/mapTiles/WorldTopoMap/",
returnTiles = FALSE, verbose = 1)
If you wanted to directly download a specific map tile, something like this might work.
download.file("http://services.arcgisonline.com/arcgis/rest/services/World_Topo_Map/MapServer/tile/13/4397/2690",
"~/mapTiles/WorldTopoMap//13_4397_2690.jpg", mode = "wb")