1`GetMap` <- structure(function# download a static map from the Google server 2### Query the Google server for a static map tile, defined primarily by its 3### center and zoom. Many additional arguments allow the user to customize 4### the map tile. 5### documentation at https://developers.google.com/maps/documentation/staticmaps/ 6( 7 center=c(lat=42, lon=-76), ##<< optional center (lat first,lon second ) 8 size = c(640,640), ##<< desired size of the map tile image. defaults to maximum size returned by the Gogle server, which is 640x640 pixels 9 destfile = tempfile("staticMap",fileext = ".png"), ##<< File to load the map image from or save to, depending on \code{NEWMAP}. 10 zoom =12, ##<< Google maps zoom level. 11 markers, ##<< (optional) defines one or more markers to attach to the image at specified locations. This parameter takes a string of marker definitions separated by the pipe character (|) 12 path="", ##<< (optional) defines a single path of two or more connected points to overlay on the image at specified locations. This parameter takes a string of point definitions separated by the pipe character (|) 13 span, ##<< (optional) defines a minimum viewport for the map image expressed as a latitude and longitude pair. The static map service takes this value and produces a map of the proper zoom level to include the entire provided span value from the map`s center point. Note that the resulting map may include larger bounds for either latitude or longitude depending on the rectangular dimensions of the map. If zoom is specified, span is ignored 14 frame, ##<< (optional) specifies that the resulting image should be framed with a colored blue border. The frame consists of a 5 pixel, 55 % opacity blue border. 15 hl, ##<< (optional) defines the language to use for display of labels on map tiles. Note that this paramater is only supported for some country tiles; if the specific language requested is not supported for the tile set, then the default language for that tile set will be used. 16 sensor = "true", ##<< specifies whether the application requesting the static map is using a sensor to determine the user`s location. This parameter is now required for all static map requests. 17 maptype = c("roadmap","mobile","satellite","terrain","hybrid","mapmaker-roadmap","mapmaker-hybrid")[2], ##<< defines the type of map to construct. There are several possible maptype values, including satellite, terrain, hybrid, and mobile. 18 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. 19 extraURL="", ##<< custom URL suffix 20 RETURNIMAGE = TRUE, ##<< return image yes/no default: TRUE 21 GRAYSCALE =FALSE, ##<< Boolean toggle; if TRUE the colored map tile is rendered into a black & white image, see \link{RGB2GRAY} 22 NEWMAP = TRUE, ##<< if TRUE, query the Google server and save to \code{destfile}, if FALSE load from destfile. 23 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 24 API_console_key, ##<< API key (formerly optional, now mandatory). If missing, the function "stitches" a static map from map tiles 25 type = c("google", "google-m","google-s","osm", "osm-hot", "stamen-toner", "stamen-terrain", "stamen-watercolor")[1], ##<< choice of tile server 26 urlBase = "http://mt1.google.com/vt/lyrs=m" , ##<< tileserver URL, alternatives would be "http://a.tile.openstreetmap.org/", "http://tile.stamen.com/toner/","http://tile.stamen.com/watercolor/" 27 tileDir= "/tmp/", ##<< map tiles can be stored in a local directory, e.g. "~/mapTiles/Google/" 28 verbose=0 ##<< level of verbosity 29){ 30 ##note<<Note that size is in order (lon, lat) 31 32 if (!NEWMAP) { 33 #no new map download 34 myMap <- ReadMapTile(destfile); 35 return(myMap); 36 } 37 38 if (is.character(center)) { 39 if (verbose) cat("geocoding ", center, "\n") 40 center = getGeoCode(center,verbose) 41 } 42 if (all(c("lat","lon") %in% names(center))) center = center[c("lat","lon")] 43 ##seealso<< \link{GetMap.bbox} 44 45# if (is.null(names(center))) { 46# names(center) = c("lat", "lon"); 47# } else stopifnot( all(names(center) %in% c("lat", "lon")) ) 48# 49 if (!is.null(center)) { 50 centerNum = center 51 center <- paste(center,collapse=",") 52 } 53 54 if (!missing(API_console_key)){ 55 print("API key provided") 56 57 stopifnot(all(size <=640)); 58 59 if (length(size) < 2) {s <- paste(size,size,sep="x")} else {s <- paste(size,collapse="x");} 60 61 # if (missing(format)){ 62 # if ( fileExt == "png") format <- "png32" 63 # } 64 65 googleurl <- "https://maps.googleapis.com/maps/api/staticmap?"# "http://maps.google.com/maps/api/staticmap?"; # googleurl <- 'http://maps.google.com/staticmap?'; 66 67 if (!missing(span)){#Images may specify a viewport (defined by latitude and longitude values expressed as degrees) to display around a provided center point by passing a span parameter. Defining a minimum viewport in this manner obviates the need to specify an exact zoom level. The static map service uses the span parameter in conjunction with the size parameter to construct a map of the proper zoom level which includes at least the given viewport constraints. 68 span <- paste(span,collapse=",") 69 urlStr <- paste(googleurl, "center=", center, "&span=", span, "&size=", s, "&maptype=", maptype, "&format=", format, "&sensor=", sensor, sep="") 70 71 } else if (is.null(center) & missing(zoom)) {#let the Static Maps API determine the correct center and zoom level implicitly, based on evaluation of the position of the markers: 72 stopifnot(!missing(markers) | path != ""); 73 urlStr <- paste(googleurl, "size=", s, "&maptype=", maptype, "&format=", format, "&sensor=", sensor, sep="") 74 } else { 75 stopifnot(!is.null(center), !missing(zoom)); 76 urlStr <- paste(googleurl, "center=", center, "&zoom=", zoom, "&size=", s, "&maptype=", maptype, "&format=", format, "&sensor=", sensor, sep="") 77 } 78 if (!is.null(API_console_key)) 79 urlStr <- paste0(urlStr,"&key=", API_console_key); 80 urlStr <- paste(urlStr, path, sep=""); 81 urlStr <- paste(urlStr, extraURL, sep=""); 82 83 if (!missing(hl)) urlStr <- paste0(urlStr, "&language=",hl); 84 if (SCALE == 2) urlStr <- paste(urlStr, "&scale=", SCALE, sep=""); 85 86 if (!missing(markers)) { 87 #assumes markers is a list with names lat, lon, size (optional), color (optional), char (optional) 88 #if(is.data.frame(markers)) markers<-as.matrix(markers) 89 if ( is.matrix(markers) | is.data.frame(markers)) { 90 stopifnot(all(c("lat","lon") %in% colnames(markers))) 91 latlon = which(colnames(markers) %in% c("lat","lon")) 92 for (i in 1:nrow(markers)){ 93 m1 <- paste(markers[i,c("lat","lon")], collapse=","); 94 if (any(c("size","color","label") %in% colnames(markers) ) ) { 95 m2 <- paste(colnames(markers)[-latlon], markers[i,-latlon], collapse="|",sep=":"); 96 m <- paste(m2,m1,sep="|") 97 } else { 98 m <- m1 99 } 100 #m <- paste("&markers=",m,sep="") 101 #print(m) 102 if (i==1){ 103 markers.string <- paste0("&markers=",m); 104 } else { 105 markers.string <- paste(markers.string,paste0("&markers=",m), sep=""); 106 } 107 #if (verbose) print(markers.string); 108 } 109 #browser() 110 #markers.string <- paste("&markers=", markers.string,sep="") 111 } else if (is.character(markers)) {#already in the correct string format: 112 markers.string <- markers; 113 } 114 115 urlStr <- paste(urlStr, markers.string, sep=""); 116 117 } 118 119 if (verbose) print(urlStr); 120 if (is.null(center)) { 121 if (verbose) print("Note that when center and zoom are not specified, no meta information on the map tile can be stored. This basically means that R cannot compute proper coordinates. You can still download the map tile and view it in R but overlays are not possible."); 122 #ans <- readLines(n=1); 123 #if (ans != "y") return(); 124 MetaInfo <- list(lat.center = NULL, lon.center = NULL, zoom = zoom, 125 url = "google", BBOX = NULL, size=size, SCALE = SCALE); 126 127 } else if ( is.numeric(centerNum) & !missing(zoom)) { 128 myMap <- list(lat.center = centerNum[1], lon.center = centerNum[2], zoom = zoom, SCALE = SCALE); 129 BBOX <- list(ll = XY2LatLon(myMap, -size[1]/2 + 0.5, -size[2]/2 - 0.5), ur = XY2LatLon(myMap, size[1]/2 + 0.5, size[2]/2 - 0.5) ); 130 MetaInfo <- list(lat.center = centerNum[1], lon.center = centerNum[2], zoom = zoom, 131 url = "google", BBOX = BBOX, size=size, SCALE = SCALE); 132 } 133 if (missing(destfile)) destfile=file.path(tempdir(),"mapTile.png") 134 if (verbose == -1) browser(); 135 136 if (NEWMAP) { 137 if (!missing(destfile)){ # destfile=file.path(tempdir(),"mapTile.png") 138 fileBase <- substring(destfile,1, nchar(destfile)-4); 139 fileExt <- substring(destfile,nchar(destfile)-2,nchar(destfile)); 140 #save meta information about the image: 141 save(MetaInfo, file = paste(destfile,"rda",sep=".")); 142 download.file(urlStr, destfile, mode="wb", quiet = TRUE); 143 myTile <- readPNG(destfile, native=TRUE); 144 } else { #do not save to file, read direcly from connection 145 #o new dependency on curl package: static maps are not saved to file by default any longer, instead read directly from connection 146 #connectStr=enc2utf8(gsub(' ','%20',"http://maps.google.com/maps/api/staticmap?center=42,-76&zoom=16&size=640x640&maptype=mobile&format=png32&sensor=true")) #Encode URL Parameters 147 #connectStr=enc2utf8(gsub(' ','%20', urlStr)) 148 #does not work in RStudio, see http://stackoverflow.com/questions/18407177/load-image-from-website !! 149 # con <- curl(urlStr, "rb") 150 # binMap=readBin(con,raw(), 1E5) 151 # 152 # myTile <- readPNG(binMap, native=FALSE); 153 # close(con) 154 } 155 } else { #no new map download 156 myMap <- ReadMapTile(destfile); 157 } 158 } else {# end of missing API key 159 160 f=genStaticMap(center=centerNum, destfile = destfile, type=type, urlBase=urlBase, tileDir=tileDir, zoom=zoom, size=size,verbose=verbose) 161 162 myMap <- list(lat.center = centerNum[1], lon.center = centerNum[2], zoom = zoom, SCALE = SCALE); 163 BBOX <- list(ll = XY2LatLon(myMap, -size[1]/2 + 0.5, -size[2]/2 - 0.5), ur = XY2LatLon(myMap, size[1]/2 + 0.5, size[2]/2 - 0.5) ); 164 url = "google" 165 if (grepl("google", urlBase)) url = "google" 166 if (grepl("stamen", urlBase)) url = "stamen" 167 if (grepl("openstreetmap", urlBase)) url = "OSM" 168 169 MetaInfo <- list(lat.center = centerNum[1], lon.center = centerNum[2], zoom = zoom, 170 url = url, BBOX = BBOX, size=size, SCALE = SCALE); 171 172 173 fileBase <- substring(destfile,1, nchar(destfile)-4); 174 fileExt <- substring(destfile,nchar(destfile)-2,nchar(destfile)); 175 #save meta information about the image: 176 save(MetaInfo, file = paste(destfile,"rda",sep=".")); 177 myTile <- readPNG(destfile, native=TRUE); 178 } 179 180 181 if (GRAYSCALE) { 182 #browser() 183 myTile <- RGB2GRAY(myTile); 184 if (!missing(destfile)) writePNG(myTile, destfile) 185 } 186 187 if (RETURNIMAGE){ 188 #myMap <- ReadMapTile(destfile); 189 myMap <- list(lat.center= MetaInfo$lat.center, lon.center=MetaInfo$lon.center, zoom=MetaInfo$zoom, 190 myTile=myTile, BBOX = MetaInfo$BBOX, url = MetaInfo$url, size=size, SCALE=MetaInfo$SCALE); 191 class(myMap) = "staticMap" 192 return(myMap); 193 } 194 195 invisible(urlStr) 196### map structure or URL used to download the tile. 197}, ex = function(){ 198 if (0){#takes too long to run for CRAN check 199 200 lat = c(40.702147,40.718217,40.711614); 201 lon = c(-74.012318,-74.015794,-73.998284); 202 center = c(mean(lat), mean(lon)); 203 zoom <- min(MaxZoom(range(lat), range(lon))); 204 #this overhead is taken care of implicitly by GetMap.bbox(); 205 markers = paste0("&markers=color:blue|label:S|40.702147,-74.015794&markers=color:", 206 "green|label:G|40.711614,-74.012318&markers=color:red|color:red|", 207 "label:C|40.718217,-73.998284") 208 myMap <- GetMap(center=center, zoom=zoom,markers=markers); 209 #Note that in the presence of markers one often needs to add some extra padding to the 210 #latitude range to accomodate the extent of the top most marker 211 212 #add a path, i.e. polyline: 213 myMap <- GetMap(center=center, zoom=zoom, 214 path = paste0("&path=color:0x0000ff|weight:5|40.737102,-73.990318|", 215 "40.749825,-73.987963|40.752946,-73.987384|40.755823,-73.986397")); 216 #use implicit geo coding 217 BrooklynMap <- GetMap(center="Brooklyn", zoom=13) 218 PlotOnStaticMap(BrooklynMap) 219 220 #use implicit geo coding and display labels in Korean: 221 BrooklynMap <- GetMap(center="Brooklyn", zoom=13, hl="ko") 222 PlotOnStaticMap(BrooklynMap) 223 224 #no highways 225 ManHatMap <- GetMap(center="Lower Manhattan", zoom=14, 226 extraURL="&style=feature:road.highway|visibility:off", 227 destfile = "LowerManhattan.png") 228 PlotOnStaticMap(ManHatMap) 229 230 #reload the map without a new download: 231 ManHatMap <- GetMap(destfile = "LowerManhattan.png",NEWMAP=FALSE) 232 PlotOnStaticMap(ManHatMap) 233 234 #The example below defines a polygonal area within Manhattan, passed a series of 235 #intersections as locations: 236 #myMap <- GetMap(path = paste0("&path=color:0x00000000|weight:5|fillcolor:0xFFFF0033|", 237 # "8th+Avenue+%26+34th+St,New+York,NY|8th+Avenue+%26+42nd+St,New+York,NY|", 238 # "Park+Ave+%26+42nd+St,New+York,NY,NY|Park+Ave+%26+34th+St,New+York,NY,NY"), 239 # destfile = "MyTile3a.png"); 240 241 #note that since the path string is just appended to the URL you can "abuse" the path 242 #argument to pass anything to the query, e.g. the style parameter: 243 #The following example displays a map of Brooklyn where local roads have been changed 244 #to bright green and the residential areas have been changed to black: 245 # myMap <- GetMap(center="Brooklyn", zoom=12, maptype = "roadmap", 246 #path = paste0("&style=feature:road.local|element:geometry|hue:0x00ff00|", 247 # "saturation:100&style=feature:landscape|element:geometry|lightness:-100"), 248 # sensor='false', destfile = "MyTile4.png", RETURNIMAGE = FALSE); 249 250 #In the last example we set RETURNIMAGE to FALSE which is a useful feature in general 251 #if png is not installed. In that cases, the images can still be fetched 252 #and saved but not read into R. 253 254 #In the following example we let the Static Maps API determine the correct center and 255 #zoom level implicitly, based on evaluation of the position of the markers. 256 #However, to be of use within R we do need to know the values for zoom and 257 #center explicitly, so it is better practice to compute them ourselves and 258 #pass them as arguments, in which case meta information on the map tile can be saved as well. 259 260 #myMap <- GetMap(markers = paste0("&markers=color:blue|label:S|40.702147,-74.015794&", 261 # "markers=color:green|label:G|40.711614,-74.012318&markers=color:red|", 262 # "color:red|label:C|40.718217,-73.998284"), 263 # destfile = "MyTile1.png", RETURNIMAGE = FALSE); 264 } 265}) 266 267