The Google Static Maps API (https://developers.google.com/maps/documentation/static-maps/intro) lets you embed a Google Maps image on your webpage without requiring JavaScript or any dynamic page loading. The Google Static Map service creates your map based on URL parameters sent through a standard HTTP request and returns the map as an image you can display on your web page.
Note: The Google Static Maps API does NOT require a Maps API key any longer.
You can still sign up for a free API key at http://code.google.com/apis/maps/signup.html if you need e.g. a higher quota of tiles.
This package serves two purposes:
The first step naturally will be to download a static map from the Google server. A simple example is shown in this Figure:
par(pty="s")
map1 <- GetMap(markers = paste0(
"&markers=color:blue|label:S|40.702147,-74.015794",
"&markers=color:green|label:G|40.711614,-74.012318",
"&markers=color:red|color:red|label:C|40.718217,-73.998284"),
center=NULL,destfile = "MyTile1.png",size=c(640,640),
maptype = "terrain")
PlotOnStaticMap(map1)
The 2-step process from above (fetch a map -> plot) can be simplified:
par(pty="s")
mapBG1 = plotmap("Brandenburg Gate, Berlin", zoom = 15)
mapBG2 = plotmap("Brandenburg Gate, Berlin", zoom = 16, maptype="satellite")
par(pty="s")
mapBG3 = GetBingMap(center="Brandenburg Gate, Berlin", zoom=12, extraURL="&mapLayer=TrafficFlow",
apiKey=apiKey,verbose=1, destfile="BerlinTraffic.png")
## geocoding Brandenburg Gate, Berlin
## fetching http://maps.google.com/maps/api/geocode/json?sensor=false&address=Brandenburg%20Gate,%20Berlin
## [1] "http://dev.virtualearth.net/REST/v1/Imagery/Map/Road/52.5162746,13.377704/12?mapSize=640,640&format=png&mapLayer=TrafficFlow&key=%20Ar6pkFx-XidvH9KD_2LEKf2fQpcssc3gMEiIxFQYQykF17MbqOZm31yA7Z5hxB27"
PlotOnStaticMap(mapBG3)
no highways:
par(pty="s")
ManHatMap <- GetMap(center="Lower Manhattan", zoom=15,
extraURL="&style=feature:road.highway|visibility:off")
PlotOnStaticMap(ManHatMap)
data(incidents)
col=as.numeric(incidents$Category)
par(pty="s")
mapSF_Z15 = plotmap(lat, lon, zoom = 15, col = col, pch=20, data = incidents)
## Warning in if (alpha < 1 & !is.na(as.numeric(col))) plotclr =
## AddAlpha(as.numeric(col), : Bedingung hat Länge > 1 und nur das erste
## Element wird benutzt
#mapSF_Z13 = with(incidents, plotmap(lat, lon, zoom = 13, col = "Category", pch=20))
#lower zoom
mapSF_Z13 = plotmap(lat, lon, zoom = 13, col = col, pch=20, data = incidents, alpha = 0.7)
## Warning in if (alpha < 1 & !is.na(as.numeric(col))) plotclr =
## AddAlpha(as.numeric(col), : Bedingung hat Länge > 1 und nur das erste
## Element wird benutzt
It would be wasteful to have to fetch a new map from the map server for each new plot!
Instead, we pass the map object to the next calls:
par(pty="s")
SundayCrimes = subset(incidents, DayOfWeek=="Sunday")
col=as.numeric(SundayCrimes$violent)
tmp=plotmap(lat, lon, mapSF_Z13, col = col, pch=20, data = SundayCrimes, alpha = 0.5)
## Warning in if (alpha < 1 & !is.na(as.numeric(col))) plotclr =
## AddAlpha(as.numeric(col), : Bedingung hat Länge > 1 und nur das erste
## Element wird benutzt
The function qbbox() basically computes a bounding box for the given lat,lon points with a few additional options such as quantile boxes, additional buffers, etc.
The function LatLon2XY(lat,lon,zoom) computes the coordinate transformation from lat/lon to map tile coordinates.
It returns the tile coordinates as well as the pixel coordinates within the Tile itself.
We compare this projection with more standard projections used in the GIS community in the appendix.
The choice of a proper zoom value is made easy via the function \(MaxZoom()\) which finds the maximum zoom level that fits the provided lat/lon ranges obeying the max size limitation of \(640 \times 640\) pixels.
The main function that overlays points (can easily be extended to lines or any other object) is \(PlotOnStaticMap()\).
The following simple sequence of calls serves to test the coincidence of the markers placed by Google and the corresponding points overlaid by \(PlotOnStaticMap()\), see Fig below. Note that we select terrain style to make the colored points more discernible.
par(pty="s")
mymarkers = cbind.data.frame(char = c("","",""),
lat = c(38.898648,38.889112, 38.880940),
lon = c(-77.037692, -77.050273, -77.03660),
col = c("blue", "green", "red"))
#get the bounding box:
bb <- qbbox(lat = mymarkers[,"lat"], lon = mymarkers[,"lon"])
#download the map:
mapDC <- GetMap.bbox(bb$lonR, bb$latR)
PlotOnStaticMap(mapDC,lat = mymarkers[,"lat"],
lon = mymarkers[,"lon"],cex=1.5,pch=20,
col=c("blue", "green", "red"))
if (OFFLINE){
meuseMap <- ReadMapTile("data/meuseMap.png")
load("data/meuseMap2.rda")
load("data/meuse2.rda")
} else {
#RgoogleMaps
meuseMap <- GetMap(rev(rowMeans(bbox(meuse2))), zoom=13, destfile="data/meuseMap.png")
#ggmap
meuseMap2 <- get_map(location=rowMeans(bbox(meuse2)), zoom=13) # get Google map
}
LevCols = rev(heat.colors(5))[cut(meuse2$lead,breaks=c(0,100,200,300,400,Inf),labels=FALSE)]
meuseLatLon=as.data.frame(meuse2)
par(pty="s")
PlotOnStaticMap(meuseMap,lat=meuseLatLon$y,lon=meuseLatLon$x,col=LevCols,pch=20)
ggmap(meuseMap2) +
geom_point(data=meuseLatLon, aes(x,y,fill=lead),
color="grey70", size=2.5, shape=21)+
scale_fill_gradientn(colours=rev(heat.colors(5)))
#1
#2 and 3
#download the map:
ggmap:
#first we build the data set to plot:
#drop unused levels
Using the loa library and a larger crime dataset:
load("data/SFincidents2012.rda")
colnames(incidents)[10:11] = c("lon", "lat")
cols <- c("yellow", "darkred")
GoogleMap(~lat*lon|DayOfWeek, #plot conditioned
data=incidents, map=NULL,
groups=incidents$violent,
col=cols, cex=0.1, alpha=0.3,
panel=panel.loaPlot2,
key.groups=list(main="Violent",
cex=1, col=cols))
loa_mapSF <- getMapArg()
v <- ifelse(incidents$violent==TRUE, "Violent", "Non-violent")
#weekend versus weekday:
WE = ifelse(incidents$DayOfWeek %in% c("Saturday", "Sunday"),"weekend", "weekday")
useOuterStrips(GoogleMap(~lat*lon|WE+v, #plot conditioned
data=incidents, map=loa_mapSF,
panel=panel.kernelDensity, #surface plot control
col.regions=c("lightyellow", "darkred"), #
alpha.regions=0.5, #
col=1, #surface calculation
n=200, at=c(0.5,1,2.5,5,10,25,50),
scales=list(draw=FALSE), xlab="", ylab=""))
#useOuterStrips(trellis.last.object())
#remove the data outside the bounding box!