├── revdep ├── .gitignore ├── checks.rds ├── check.R └── summary.md ├── .gitignore ├── data ├── wind.rda ├── zips.rda ├── crime.rda └── hadley.rda ├── tests ├── testthat.R └── testthat │ ├── test-data.R │ ├── test-calc_zoom.R │ ├── util.R │ ├── test-ggmap.R │ └── test-LonLat2XY.R ├── tools ├── README-europe-1.png ├── README-europe-2.png ├── README-qmplot-1.png ├── README-qmplot-2.png ├── README-faceting-1.png ├── README-maptypes-1.png ├── README-maptypes-2.png ├── README-qmplot2-1.png ├── README-styling-1.png ├── README-google_maps-1.png ├── README-route_trek-1.png ├── README-google_styles-1.png ├── README-google_styles-2.png └── README-google_styles-3.png ├── R ├── hadley.R ├── helpers.R ├── crime.R ├── zips.R ├── ggplot2.R ├── wind.R ├── zzz.R ├── ggmap-package.R ├── make_bbox.R ├── print.R ├── ggmap_credentials.R ├── mutate_geocode.R ├── LonLat2XY.R ├── bb2bbox.R ├── XY2LonLat.R ├── theme_inset.R ├── coord_map.R ├── file_drawer.R ├── theme_nothing.R ├── inset.R ├── ggimage.R ├── calc_zoom.r ├── get_navermap.R ├── OSM_scale_lookup.R ├── inset_raster.R ├── geom_leg.R ├── gglocator.R ├── revgeocode.R ├── qmap.R ├── register_google.R ├── get_openstreetmap.R ├── trek.R ├── mapdist.R ├── get_map.R └── get_cloudmademap.R ├── .github ├── PULL_REQUEST_TEMPLATE.md └── ISSUE_TEMPLATE.md ├── .Rbuildignore ├── man ├── hadley.Rd ├── crime.Rd ├── zips.Rd ├── distQueryCheck.Rd ├── print.ggmap.Rd ├── routeQueryCheck.Rd ├── wind.Rd ├── ggmap_credentials.Rd ├── make_bbox.Rd ├── inset.Rd ├── file_drawer.Rd ├── ggmapplot.Rd ├── LonLat2XY.Rd ├── mutate_geocode.Rd ├── inset_raster.Rd ├── theme_inset.Rd ├── XY2LonLat.Rd ├── calc_zoom.Rd ├── theme_nothing.Rd ├── bb2bbox.Rd ├── revgeocode.Rd ├── qmap.Rd ├── ggimage.Rd ├── legs2route.Rd ├── gglocator.Rd ├── register_google.Rd ├── get_cloudmademap.Rd ├── mapdist.Rd ├── route.Rd ├── OSM_scale_lookup.Rd ├── get_navermap.Rd ├── get_openstreetmap.Rd ├── get_map.Rd ├── trek.Rd ├── geocode.Rd ├── geom_leg.Rd ├── get_googlemap.Rd ├── get_stamenmap.Rd └── qmplot.Rd ├── ggmap.Rproj ├── inst └── CITATION ├── cran-comments.md ├── DESCRIPTION ├── NAMESPACE ├── README.Rmd └── README.md /revdep/.gitignore: -------------------------------------------------------------------------------- 1 | **/ 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | README_cache/ 5 | -------------------------------------------------------------------------------- /data/wind.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/data/wind.rda -------------------------------------------------------------------------------- /data/zips.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/data/zips.rda -------------------------------------------------------------------------------- /data/crime.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/data/crime.rda -------------------------------------------------------------------------------- /data/hadley.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/data/hadley.rda -------------------------------------------------------------------------------- /revdep/checks.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/revdep/checks.rds -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(ggmap) 3 | 4 | test_check("ggmap") 5 | -------------------------------------------------------------------------------- /tools/README-europe-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/tools/README-europe-1.png -------------------------------------------------------------------------------- /tools/README-europe-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/tools/README-europe-2.png -------------------------------------------------------------------------------- /tools/README-qmplot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/tools/README-qmplot-1.png -------------------------------------------------------------------------------- /tools/README-qmplot-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/tools/README-qmplot-2.png -------------------------------------------------------------------------------- /tools/README-faceting-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/tools/README-faceting-1.png -------------------------------------------------------------------------------- /tools/README-maptypes-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/tools/README-maptypes-1.png -------------------------------------------------------------------------------- /tools/README-maptypes-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/tools/README-maptypes-2.png -------------------------------------------------------------------------------- /tools/README-qmplot2-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/tools/README-qmplot2-1.png -------------------------------------------------------------------------------- /tools/README-styling-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/tools/README-styling-1.png -------------------------------------------------------------------------------- /tools/README-google_maps-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/tools/README-google_maps-1.png -------------------------------------------------------------------------------- /tools/README-route_trek-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/tools/README-route_trek-1.png -------------------------------------------------------------------------------- /tools/README-google_styles-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/tools/README-google_styles-1.png -------------------------------------------------------------------------------- /tools/README-google_styles-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/tools/README-google_styles-2.png -------------------------------------------------------------------------------- /tools/README-google_styles-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datacamp/ggmap/master/tools/README-google_styles-3.png -------------------------------------------------------------------------------- /revdep/check.R: -------------------------------------------------------------------------------- 1 | library("devtools") 2 | 3 | res <- revdep_check() 4 | revdep_check_save_summary(res) 5 | revdep_check_save_logs(res) 6 | -------------------------------------------------------------------------------- /R/hadley.R: -------------------------------------------------------------------------------- 1 | #' Highly unofficial ggplot2 image 2 | #' 3 | #' @name hadley 4 | #' @docType data 5 | #' @author Garrett Grolemund \email{grolemund@@gmail.com} 6 | NULL -------------------------------------------------------------------------------- /tests/testthat/test-data.R: -------------------------------------------------------------------------------- 1 | test_that("crime data classes look right", { 2 | data(crime) 3 | expect_equal(class(crime$time), c("POSIXct", "POSIXt")) 4 | }) 5 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Before you open your PR 2 | 3 | - [ ] Did you run R CMD CHECK? 4 | - [ ] Did you run `roxygen2::roxygenise(".")`? 5 | 6 | Thanks for contributing! 7 | 8 | -------------------------------------------------------------------------------- /tests/testthat/test-calc_zoom.R: -------------------------------------------------------------------------------- 1 | context("calc_zoom") 2 | 3 | test_that("calc_zoom example works", { 4 | zoom <- calc_zoom( 5 | c(-94, -95), 6 | c(56, 57) 7 | ) 8 | expect_equal(zoom, 10) 9 | }) -------------------------------------------------------------------------------- /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^\.Rproj\.user$ 3 | ^README\.Rmd$ 4 | ^revdep$ 5 | ^cran-comments.md$ 6 | ^cran-comments\.md$ 7 | README_cache 8 | ^\.github/ISSUE_TEMPLATE\.md$ 9 | ^\.github/PULL_REQUEST_TEMPLATE\.md$ 10 | -------------------------------------------------------------------------------- /R/helpers.R: -------------------------------------------------------------------------------- 1 | `%notin%` <- function(elem, set){ 2 | !(elem %in% set) 3 | } 4 | 5 | 6 | # key <- "aBc" 7 | # fmteq(key) 8 | # fmteq(key, tolower) 9 | # fmteq(key, toupper) 10 | fmteq <- function (x, f = function(.) ., ...) { 11 | paste0(deparse(substitute(x)), "=", f(x, ...)) 12 | } 13 | -------------------------------------------------------------------------------- /R/crime.R: -------------------------------------------------------------------------------- 1 | #' Crime data 2 | #' 3 | #' Lightly cleaned Houston crime from January 2010 to August 2010 4 | #' geocoded with Google Maps 5 | #' 6 | #' @name crime 7 | #' @docType data 8 | #' @author Houston Police Department, City of Houston 9 | #' @references \url{http://www.houstontx.gov/police/cs/stats2.htm} 10 | NULL 11 | -------------------------------------------------------------------------------- /man/hadley.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/hadley.R 3 | \docType{data} 4 | \name{hadley} 5 | \alias{hadley} 6 | \title{Highly unofficial ggplot2 image} 7 | \description{ 8 | Highly unofficial ggplot2 image 9 | } 10 | \author{ 11 | Garrett Grolemund \email{grolemund@gmail.com} 12 | } 13 | -------------------------------------------------------------------------------- /tests/testthat/util.R: -------------------------------------------------------------------------------- 1 | getFakeMap <- function() { 2 | map <- character() 3 | class(map) <- c('ggmap','raster') 4 | attr(map, "source") <- "osm" 5 | attr(map, "maptype") <- "openstreetmap" 6 | attr(map, "scale") <- 606250 7 | attr(map, 'bb') <- data.frame( 8 | ll.lat = 1, ll.lon = 2, 9 | ur.lat = 3, ur.lon = 4 10 | ) 11 | map 12 | } -------------------------------------------------------------------------------- /R/zips.R: -------------------------------------------------------------------------------- 1 | #' Zip code data for the Greater Houston Metropolitan Area from the 2 | #' 2000 census 3 | #' 4 | #' @name zips 5 | #' @docType data 6 | #' @author U.S. Census Bureau, Geography Division, Cartographic 7 | #' Products Management Branch 8 | #' @references Downloaded from 9 | #' http://www.census.gov/geo/www/cob/z52000.html (now defunct). 10 | NULL 11 | -------------------------------------------------------------------------------- /man/crime.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/crime.R 3 | \docType{data} 4 | \name{crime} 5 | \alias{crime} 6 | \title{Crime data} 7 | \description{ 8 | Lightly cleaned Houston crime from January 2010 to August 2010 9 | geocoded with Google Maps 10 | } 11 | \references{ 12 | \url{http://www.houstontx.gov/police/cs/stats2.htm} 13 | } 14 | \author{ 15 | Houston Police Department, City of Houston 16 | } 17 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | ## Reproducible Example 2 | 3 | Feel free to delete and replace with a description of the feature you'd like if this is not a bug. 4 | 5 | Paste a [reprex](https://github.com/tidyverse/reprex) here. This helps the maintainers reproduce the bug you encountered. Ensure that the `si` option is `TRUE`. 6 | 7 | Example: 8 | 9 | ```r 10 | reprex::reprex({ 11 | library(ggmap) 12 | ggmap(get_map()) 13 | }, si = TRUE) 14 | ``` 15 | -------------------------------------------------------------------------------- /tests/testthat/test-ggmap.R: -------------------------------------------------------------------------------- 1 | context("ggmap") 2 | source("util.R") 3 | 4 | test_that("ggmap example works", { 5 | map <- getFakeMap() 6 | ggmap(map) 7 | expect_true(TRUE) # didn't stop: good! 8 | }) 9 | 10 | test_that("ggmapplot example works", { 11 | map <- getFakeMap() 12 | expect_warning( 13 | # deprecated, and uses deprecated syntax 14 | # warns twice 15 | ggmapplot(map) 16 | ) 17 | expect_true(TRUE) # didn't stop: good! 18 | }) 19 | -------------------------------------------------------------------------------- /ggmap.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: No 4 | SaveWorkspace: No 5 | AlwaysSaveHistory: No 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | StripTrailingWhitespace: Yes 17 | 18 | BuildType: Package 19 | PackageUseDevtools: Yes 20 | PackageInstallArgs: --no-multiarch --with-keep.source 21 | PackageRoxygenize: rd,collate,namespace 22 | -------------------------------------------------------------------------------- /tests/testthat/test-LonLat2XY.R: -------------------------------------------------------------------------------- 1 | context("LonLat2XY") 2 | 3 | test_that("LonLat2XY example works", { 4 | # gc <- geocode('baylor university') 5 | gc <- list(lon = -97.11431, lat = 31.54984) 6 | ll2xy <- LonLat2XY(gc$lon, gc$lat, 10) 7 | expect_equal( 8 | ll2xy$X, 9 | 235 10 | ) 11 | expect_equal( 12 | ll2xy$Y, 13 | 417 14 | ) 15 | expect_true( 16 | abs(ll2xy$x - 195.5142) < 0.01 # float math is hard 17 | ) 18 | expect_true( 19 | abs(ll2xy$y - 88.52267) < 0.01 # float math is hard 20 | ) 21 | }) -------------------------------------------------------------------------------- /man/zips.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/zips.R 3 | \docType{data} 4 | \name{zips} 5 | \alias{zips} 6 | \title{Zip code data for the Greater Houston Metropolitan Area from the 7 | 2000 census} 8 | \description{ 9 | Zip code data for the Greater Houston Metropolitan Area from the 10 | 2000 census 11 | } 12 | \references{ 13 | Downloaded from 14 | http://www.census.gov/geo/www/cob/z52000.html (now defunct). 15 | } 16 | \author{ 17 | U.S. Census Bureau, Geography Division, Cartographic 18 | Products Management Branch 19 | } 20 | -------------------------------------------------------------------------------- /man/distQueryCheck.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mapdist.R 3 | \name{distQueryCheck} 4 | \alias{distQueryCheck} 5 | \title{Check Google Maps Distance Matrix API query limit} 6 | \usage{ 7 | distQueryCheck() 8 | } 9 | \value{ 10 | a data frame 11 | } 12 | \description{ 13 | Check Google Maps Distance Matrix API query limit 14 | } 15 | \examples{ 16 | distQueryCheck() 17 | } 18 | \seealso{ 19 | \url{http://code.google.com/apis/maps/documentation/distancematrix/} 20 | } 21 | \author{ 22 | David Kahle \email{david.kahle@gmail.com} 23 | } 24 | -------------------------------------------------------------------------------- /man/print.ggmap.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/print.R 3 | \name{print.ggmap} 4 | \alias{print.ggmap} 5 | \title{Print a map} 6 | \usage{ 7 | \method{print}{ggmap}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{an object of class elicit} 11 | 12 | \item{...}{additional parameters} 13 | } 14 | \value{ 15 | Invisibly returns \code{x}. 16 | } 17 | \description{ 18 | Print a console description of a map 19 | } 20 | \examples{ 21 | 22 | \dontrun{ to diminish run check time 23 | 24 | get_map() 25 | ggmap(get_map()) 26 | 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /R/ggplot2.R: -------------------------------------------------------------------------------- 1 | # Geom <- get("Geom", envir = asNamespace("ggplot2")) 2 | # GeomRaster <- get("GeomRaster", envir = asNamespace("ggplot2")) 3 | # Position <- get("Position", envir = asNamespace("ggplot2")) 4 | # Stat <- get("Stat", envir = asNamespace("ggplot2")) 5 | is.constant <- get("is.constant", envir = asNamespace("ggplot2")) 6 | rename_aes <- get("rename_aes", envir = asNamespace("ggplot2")) 7 | .all_aesthetics <- get(".all_aesthetics", envir = asNamespace("ggplot2")) 8 | 9 | list_to_dataframe <- get("list_to_dataframe", envir = asNamespace("plyr")) 10 | 11 | -------------------------------------------------------------------------------- /R/wind.R: -------------------------------------------------------------------------------- 1 | #' Wind data from Hurricane Ike 2 | #' 3 | #' 4 | #' 5 | #' @name wind 6 | #' @details Powell, M. D., S. H. Houston, L. R. Amat, and N 7 | #' Morisseau-Leroy, 1998: The HRD real-time hurricane wind 8 | #' analysis system. J. Wind Engineer. and Indust. Aerodyn. 77&78, 9 | #' 53-64 10 | #' @docType data 11 | #' @author Atlantic Oceanographic and Meteorological Laboratory 12 | #' (AOML), a division of the National Oceanic and Atmospheric 13 | #' Administration (NOAA) 14 | #' @references 15 | #' \url{http://www.aoml.noaa.gov/hrd/Storm_pages/ike2008/wind.html} 16 | #' 17 | NULL 18 | -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | citHeader("To cite ggmap in publications, please use:") 2 | 3 | citEntry(entry = "article", 4 | author = "David Kahle and Hadley Wickham", 5 | title = "ggmap: Spatial Visualization with ggplot2", 6 | journal = "The R Journal", 7 | year = "2013", 8 | volume = "5", 9 | number = "1", 10 | pages = "144--161", 11 | url = "http://journal.r-project.org/archive/2013-1/kahle-wickham.pdf", 12 | textVersion = "D. Kahle and H. Wickham. ggmap: Spatial Visualization with ggplot2. The R Journal, 5(1), 144-161. URL http://journal.r-project.org/archive/2013-1/kahle-wickham.pdf" 13 | ) -------------------------------------------------------------------------------- /man/routeQueryCheck.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/route.R 3 | \name{routeQueryCheck} 4 | \alias{routeQueryCheck} 5 | \title{Check Google Maps Directions API query limit} 6 | \usage{ 7 | routeQueryCheck() 8 | } 9 | \value{ 10 | a data frame 11 | } 12 | \description{ 13 | Check Google Maps Directions API query limit 14 | } 15 | \examples{ 16 | \dontrun{ 17 | routeQueryCheck() 18 | } 19 | } 20 | \seealso{ 21 | \url{https://developers.google.com/maps/documentation/directions/} 22 | } 23 | \author{ 24 | David Kahle \email{david.kahle@gmail.com} 25 | } 26 | -------------------------------------------------------------------------------- /man/wind.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/wind.R 3 | \docType{data} 4 | \name{wind} 5 | \alias{wind} 6 | \title{Wind data from Hurricane Ike} 7 | \description{ 8 | Wind data from Hurricane Ike 9 | } 10 | \details{ 11 | Powell, M. D., S. H. Houston, L. R. Amat, and N 12 | Morisseau-Leroy, 1998: The HRD real-time hurricane wind 13 | analysis system. J. Wind Engineer. and Indust. Aerodyn. 77&78, 14 | 53-64 15 | } 16 | \references{ 17 | \url{http://www.aoml.noaa.gov/hrd/Storm_pages/ike2008/wind.html} 18 | } 19 | \author{ 20 | Atlantic Oceanographic and Meteorological Laboratory 21 | (AOML), a division of the National Oceanic and Atmospheric 22 | Administration (NOAA) 23 | } 24 | -------------------------------------------------------------------------------- /man/ggmap_credentials.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggmap_credentials.R 3 | \name{ggmap_credentials} 4 | \alias{ggmap_credentials} 5 | \alias{print.ggmap_credentials} 6 | \title{ggmap Credentials} 7 | \usage{ 8 | ggmap_credentials() 9 | 10 | \method{print}{ggmap_credentials}(x, ...) 11 | } 12 | \arguments{ 13 | \item{x}{the ggmap credentials object; getOption("ggmap")} 14 | 15 | \item{...}{... (dumped)} 16 | } 17 | \description{ 18 | Get ggmap's credentials; these are all Google credentials at this 19 | point. 20 | } 21 | \examples{ 22 | 23 | ggmap_credentials() 24 | 25 | } 26 | \seealso{ 27 | \code{\link{register_google}} 28 | } 29 | \author{ 30 | David Kahle \email{david.kahle@gmail.com} 31 | } 32 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | .onAttach <- function(...) { 2 | # if (!interactive()) return() 3 | 4 | packageStartupMessage("Google Maps API Terms of Service: http://developers.google.com/maps/terms.") 5 | packageStartupMessage("Please cite ggmap if you use it: see citation(\"ggmap\") for details.") 6 | 7 | # define initial credentials for ggmap 8 | if ( is.null(getOption("ggmap")) ) { 9 | 10 | options <- list( 11 | google = list( 12 | key = NA, 13 | account_type = "standard", 14 | day_limit = 2500, 15 | second_limit = 50, 16 | client = NA, 17 | signature = NA 18 | ) 19 | ) 20 | class(options) <- "ggmap_credentials" 21 | options(ggmap = options) 22 | 23 | } 24 | 25 | } 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | ## Submission summary 2 | 3 | This is a resubmission. 4 | 5 | ---- 6 | 7 | This is a small update that fixes some minor bugs in the check and updates some geocoding features. This should mainly only affect the internal operation of the package. I notified all reverse dependencies authors on July 31, giving them two weeks to fix any problems; it has now been nearly three weeks with no responses. 8 | 9 | ## Test environments 10 | * local OS X install, R 3.2.2 11 | * win-builder (devel and release) 12 | 13 | ## R CMD check results 14 | There were no ERRORs, WARNINGs, or NOTEs. 15 | 16 | ## Downstream dependencies 17 | I ran `R CMD check` on all 9 reverse dependencies (https://github.com/dkahle/ggmap/blob/master/revdep/summary.md). 18 | 19 | None appeared to fail due to changes in ggmap. 20 | -------------------------------------------------------------------------------- /R/ggmap-package.R: -------------------------------------------------------------------------------- 1 | #' @import ggplot2 2 | #' @docType package 3 | #' @name ggmap 4 | #' @importFrom RgoogleMaps XY2LatLon 5 | #' @importFrom png readPNG 6 | #' @importFrom jpeg readJPEG 7 | #' @importFrom plyr arrange compact ddply desc dlply is.discrete is.formula join 8 | #' ldply llply . 9 | #' @importFrom rjson fromJSON 10 | #' @importFrom bitops bitOr bitShiftL bitShiftR bitAnd 11 | #' @importFrom grDevices as.raster extendrange gray rgb 12 | #' @importFrom stats time asOneSidedFormula 13 | #' @importFrom utils URLencode download.file tail 14 | #' @importFrom grid rasterGrob seekViewport grid.locator upViewport downViewport 15 | #' current.vpTree current.vpPath viewport 16 | #' @importFrom scales expand_range 17 | #' @importFrom dplyr bind_cols filter bind_rows 18 | #' @aliases ggmap package-ggmap 19 | NULL 20 | -------------------------------------------------------------------------------- /man/make_bbox.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/make_bbox.R 3 | \name{make_bbox} 4 | \alias{make_bbox} 5 | \title{Compute a bounding box} 6 | \usage{ 7 | make_bbox(lon, lat, data, f = 0.05) 8 | } 9 | \arguments{ 10 | \item{lon}{longitude} 11 | 12 | \item{lat}{latitude} 13 | 14 | \item{data}{(optional) a data frame containing lon and lat as 15 | variables} 16 | 17 | \item{f}{number specifying the fraction by which the range should 18 | be extended} 19 | } 20 | \description{ 21 | Compute a bounding box for a given longitude / latitude 22 | collection. 23 | } 24 | \examples{ 25 | 26 | make_bbox(lon, lat, data = crime) 27 | 28 | (lon <- sample(crime$lon, 10)) 29 | (lat <- sample(crime$lat, 10)) 30 | make_bbox(lon, lat) 31 | make_bbox(lon, lat, f = .10) # bigger box 32 | 33 | 34 | } 35 | -------------------------------------------------------------------------------- /man/inset.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/inset.R 3 | \name{inset} 4 | \alias{inset} 5 | \title{Add ggplot2 insets to a map} 6 | \usage{ 7 | inset(grob, xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf) 8 | } 9 | \arguments{ 10 | \item{grob}{grob to display} 11 | 12 | \item{xmin, xmax}{x location (in data coordinates) giving 13 | horizontal location of raster} 14 | 15 | \item{ymin, ymax}{y location (in data coordinates) giving vertical 16 | location of raster} 17 | } 18 | \description{ 19 | This is identical to ggplot2::annotation_custom for use with 20 | ggmap 21 | } 22 | \details{ 23 | Most useful for adding tables, inset plots, and other grid-based 24 | decorations 25 | } 26 | \note{ 27 | \code{annotation_custom} expects the grob to fill the 28 | entire viewport defined by xmin, xmax, ymin, ymax. Grobs with a 29 | different (absolute) size will be center-justified in that 30 | region. Inf values can be used to fill the full plot panel 31 | } 32 | -------------------------------------------------------------------------------- /man/file_drawer.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/file_drawer.R 3 | \name{file_drawer} 4 | \alias{file_drawer} 5 | \title{Manage the ggmap file drawer.} 6 | \usage{ 7 | file_drawer(...) 8 | } 9 | \description{ 10 | To avoid downloading the same maps again and again, ggmap uses a 11 | "file drawer" to store the maps you've downloaded. By default, 12 | they will be stored in a session specific temporary directory 13 | which will be deleted each time you quit R. If you want them to 14 | persist across sessions, set the global option 15 | "ggmap.file_drawer". 16 | } 17 | \examples{ 18 | 19 | \dontrun{# if server is unresponsive, R check will fail 20 | 21 | file_drawer() 22 | dir(file_drawer()) 23 | 24 | # The first time you run this, the tiles are downloaded from the server 25 | map <- get_stamenmap() 26 | # The second time, the local cache is used so it's much faster 27 | map <- get_stamenmap() 28 | 29 | dir(file_drawer()) 30 | 31 | } 32 | 33 | } 34 | \keyword{internal} 35 | -------------------------------------------------------------------------------- /R/make_bbox.R: -------------------------------------------------------------------------------- 1 | #' Compute a bounding box 2 | #' 3 | #' Compute a bounding box for a given longitude / latitude 4 | #' collection. 5 | #' 6 | #' @param lon longitude 7 | #' @param lat latitude 8 | #' @param data (optional) a data frame containing lon and lat as 9 | #' variables 10 | #' @param f number specifying the fraction by which the range should 11 | #' be extended 12 | #' @export 13 | #' @examples 14 | #' 15 | #' make_bbox(lon, lat, data = crime) 16 | #' 17 | #' (lon <- sample(crime$lon, 10)) 18 | #' (lat <- sample(crime$lat, 10)) 19 | #' make_bbox(lon, lat) 20 | #' make_bbox(lon, lat, f = .10) # bigger box 21 | #' 22 | #' 23 | make_bbox <- function(lon, lat, data, f = 0.05){ 24 | 25 | if(!missing(data)){ 26 | lon <- data[,deparse(substitute(lon))] 27 | lat <- data[,deparse(substitute(lat))] 28 | } 29 | 30 | lon_range <- extendrange(range(lon, na.rm = TRUE), f = f) 31 | lat_range <- extendrange(range(lat, na.rm = TRUE), f = f) 32 | c(left = lon_range[1], bottom = lat_range[1], 33 | right = lon_range[2], top = lat_range[2]) 34 | } 35 | -------------------------------------------------------------------------------- /R/print.R: -------------------------------------------------------------------------------- 1 | #' Print a map 2 | #' 3 | #' Print a console description of a map 4 | #' 5 | #' @param x an object of class elicit 6 | #' @param ... additional parameters 7 | #' @usage \method{print}{ggmap}(x, ...) 8 | #' @return Invisibly returns \code{x}. 9 | #' @export 10 | #' @examples 11 | #' 12 | #' \dontrun{ to diminish run check time 13 | #' 14 | #' get_map() 15 | #' ggmap(get_map()) 16 | #' 17 | #' } 18 | #' 19 | print.ggmap <- function(x, ...){ 20 | 21 | r <- nrow(x) 22 | c <- ncol(x) 23 | 24 | source <- attr(x, "source") 25 | if(source == "google"){ 26 | source <- "Google Maps" 27 | } else if(source == "stamen"){ 28 | source <- "Stamen Maps" 29 | } else if(source == "osm"){ 30 | source <- "OpenStreetMap" 31 | } else if(source == "cloudmade"){ 32 | source <- "Cloudmade" 33 | } else if(source == "naver"){ 34 | source <- "Naver Map" 35 | } 36 | 37 | cat(paste0(r, "x", c, " ", attr(x, "maptype"), " map image from ", source, ".", 38 | " see ?ggmap to plot it.\n"), ...) 39 | 40 | invisible(x) 41 | } 42 | 43 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: ggmap 2 | Version: 2.7.900 3 | Title: Spatial Visualization with ggplot2 4 | Description: A collection of functions to visualize spatial data and models 5 | on top of static maps from various online sources (e.g Google Maps and Stamen 6 | Maps). It includes tools common to those tasks, including functions for 7 | geolocation and routing. 8 | URL: https://github.com/dkahle/ggmap 9 | BugReports: https://github.com/dkahle/ggmap/issues 10 | Authors@R: c(person("David", "Kahle", email = "david.kahle@gmail.com", role = c("aut", "cre"), comment = c(ORCID = "0000-0002-9999-1558")), 11 | person("Hadley", "Wickham", email = "h.wickham@gmail.com", role = "aut", comment = c(ORCID = "0000-0003-4757-117X"))) 12 | Depends: 13 | R (>= 3.1.0), 14 | ggplot2 (>= 2.2.0) 15 | Imports: 16 | RgoogleMaps, 17 | png, 18 | plyr, 19 | rjson, 20 | jpeg, 21 | digest, 22 | scales, 23 | dplyr, 24 | bitops, 25 | grid 26 | Suggests: 27 | MASS, 28 | stringr, 29 | hexbin, 30 | tibble, 31 | testthat 32 | License: GPL-2 33 | LazyData: true 34 | RoxygenNote: 6.0.1 35 | -------------------------------------------------------------------------------- /R/ggmap_credentials.R: -------------------------------------------------------------------------------- 1 | #' ggmap Credentials 2 | #' 3 | #' Get ggmap's credentials; these are all Google credentials at this 4 | #' point. 5 | #' 6 | #' @param x the ggmap credentials object; getOption("ggmap") 7 | #' @param ... ... (dumped) 8 | #' @return NULL 9 | #' @name ggmap_credentials 10 | #' @author David Kahle \email{david.kahle@@gmail.com} 11 | #' @seealso \code{\link{register_google}} 12 | #' @examples 13 | #' 14 | #' ggmap_credentials() 15 | #' 16 | 17 | 18 | 19 | 20 | 21 | 22 | #' @rdname ggmap_credentials 23 | #' @export 24 | ggmap_credentials <- function () { 25 | 26 | getOption("ggmap") 27 | 28 | } 29 | 30 | 31 | 32 | 33 | 34 | #' @rdname ggmap_credentials 35 | #' @export 36 | print.ggmap_credentials <- function (x, ...) { 37 | 38 | for (k in 1:length(x)) { 39 | cat(capitalize(names(x)[k]), "- \n") 40 | for (i in 1:length(x[[k]])) { 41 | cat(" ", names(x[[k]])[i], ": ") 42 | val <- x[[k]][[i]] 43 | cat(ifelse(is.na(val), "", val), "\n") 44 | } 45 | } 46 | 47 | } 48 | 49 | 50 | 51 | capitalize <- function(s) { 52 | paste0(toupper(substr(s, 1, 1)), substr(s, 2, nchar(s))) 53 | } 54 | -------------------------------------------------------------------------------- /man/ggmapplot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggmap.R 3 | \name{ggmapplot} 4 | \alias{ggmapplot} 5 | \title{Don't use this function, use ggmap.} 6 | \usage{ 7 | ggmapplot(ggmap, fullpage = FALSE, base_layer, maprange = FALSE, 8 | expand = FALSE, ...) 9 | } 10 | \arguments{ 11 | \item{ggmap}{an object of class ggmap (from function get_map)} 12 | 13 | \item{fullpage}{logical; should the map take up the entire viewport?} 14 | 15 | \item{base_layer}{a ggplot(aes(...), ...) call; see examples} 16 | 17 | \item{maprange}{logical for use with base_layer; should the map define the x and y limits?} 18 | 19 | \item{expand}{should the map extend to the edge of the panel? used with base_layer and maprange=TRUE.} 20 | 21 | \item{...}{...} 22 | } 23 | \value{ 24 | a ggplot object 25 | } 26 | \description{ 27 | ggmap plots the raster object produced by \code{\link{get_map}}. 28 | } 29 | \examples{ 30 | \dontrun{ 31 | this is a deprecated function, use ggmap. 32 | } 33 | } 34 | \seealso{ 35 | \code{\link{get_map}}, \code{\link{qmap}} 36 | } 37 | \author{ 38 | David Kahle \email{david.kahle@gmail.com} 39 | } 40 | -------------------------------------------------------------------------------- /man/LonLat2XY.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/LonLat2XY.R 3 | \name{LonLat2XY} 4 | \alias{LonLat2XY} 5 | \title{Convert a lon/lat coordinate to a tile coordinate} 6 | \usage{ 7 | LonLat2XY(lon_deg, lat_deg, zoom, xpix = 256, ypix = 256) 8 | } 9 | \arguments{ 10 | \item{lon_deg}{longitude in degrees} 11 | 12 | \item{lat_deg}{latitude in degrees} 13 | 14 | \item{zoom}{zoom} 15 | 16 | \item{xpix}{width of tile in pixels} 17 | 18 | \item{ypix}{length of tile in pixels} 19 | } 20 | \value{ 21 | a data frame with columns X, Y, x, y 22 | } 23 | \description{ 24 | Convert a lon/lat coordinate to a tile coordinate for a given 25 | zoom. Decimal tile coordinates (x, y) are reported. 26 | } 27 | \examples{ 28 | 29 | 30 | \dontrun{ 31 | gc <- geocode('baylor university') 32 | LonLat2XY(gc$lon, gc$lat, 10) 33 | 34 | } 35 | 36 | } 37 | \seealso{ 38 | \url{http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames} 39 | } 40 | \author{ 41 | David Kahle \email{david.kahle@gmail.com}, based on 42 | function LatLon2XY by Markus Loecher, Sense Networks 43 | \email{markus@sensenetworks.com} in package RgoogleMaps 44 | } 45 | -------------------------------------------------------------------------------- /man/mutate_geocode.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mutate_geocode.R 3 | \name{mutate_geocode} 4 | \alias{mutate_geocode} 5 | \title{Geocode a dataset} 6 | \usage{ 7 | mutate_geocode(data, location, ...) 8 | } 9 | \arguments{ 10 | \item{data}{a data frame} 11 | 12 | \item{location}{a character string specifying a location of 13 | interest (e.g. "Baylor University")} 14 | 15 | \item{...}{arguments to pass to \code{\link{geocode}}} 16 | } 17 | \value{ 18 | data with geocoded information appended as columns 19 | } 20 | \description{ 21 | \code{mutate_geocode} geocodes a data frame and appends the new 22 | information to the data frame provided. 23 | } 24 | \examples{ 25 | 26 | 27 | df <- data.frame( 28 | address = c("1600 Pennsylvania Avenue, Washington DC", "", "houston texas"), 29 | stringsAsFactors = FALSE 30 | ) 31 | 32 | \dontrun{ # Server response can be slow; this cuts down check time. 33 | mutate_geocode(df, address) 34 | 35 | 36 | library(dplyr) 37 | df \%>\% mutate_geocode(address) 38 | 39 | tbl_df(df) \%>\% mutate_geocode(address) 40 | } 41 | 42 | } 43 | \seealso{ 44 | \code{\link{geocode}} 45 | } 46 | \author{ 47 | David Kahle \email{david.kahle@gmail.com} 48 | } 49 | -------------------------------------------------------------------------------- /R/mutate_geocode.R: -------------------------------------------------------------------------------- 1 | #' Geocode a dataset 2 | #' 3 | #' \code{mutate_geocode} geocodes a data frame and appends the new 4 | #' information to the data frame provided. 5 | #' 6 | #' @param data a data frame 7 | #' @param location a character string specifying a location of 8 | #' interest (e.g. "Baylor University") 9 | #' @param ... arguments to pass to \code{\link{geocode}} 10 | #' @return data with geocoded information appended as columns 11 | #' @author David Kahle \email{david.kahle@@gmail.com} 12 | #' @seealso \code{\link{geocode}} 13 | #' @export 14 | #' @examples 15 | #' 16 | #' 17 | #' df <- data.frame( 18 | #' address = c("1600 Pennsylvania Avenue, Washington DC", "", "houston texas"), 19 | #' stringsAsFactors = FALSE 20 | #' ) 21 | #' 22 | #' \dontrun{ # Server response can be slow; this cuts down check time. 23 | #' mutate_geocode(df, address) 24 | #' 25 | #' 26 | #' library(dplyr) 27 | #' df %>% mutate_geocode(address) 28 | #' 29 | #' tbl_df(df) %>% mutate_geocode(address) 30 | #' } 31 | #' 32 | mutate_geocode <- function(data, location, ...){ 33 | locs <- data[[deparse(substitute(location))]] 34 | gcdf <- geocode(locs, ...) 35 | dplyr::bind_cols(data, gcdf) 36 | } 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /man/inset_raster.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/inset_raster.R 3 | \name{inset_raster} 4 | \alias{inset_raster} 5 | \alias{inset_ggmap} 6 | \title{Create a (ggplot2) raster layer} 7 | \usage{ 8 | inset_raster(raster, xmin, xmax, ymin, ymax, interpolate = TRUE) 9 | 10 | inset_ggmap(ggmap) 11 | } 12 | \arguments{ 13 | \item{raster}{raster object to display} 14 | 15 | \item{xmin, xmax}{x location (in data coordinates) giving 16 | horizontal location of raster} 17 | 18 | \item{ymin, ymax}{y location (in data coordinates) giving vertical 19 | location of raster} 20 | 21 | \item{interpolate}{interpolate the raster? (i.e. antialiasing)} 22 | 23 | \item{ggmap}{a ggmap object, see \code{\link{get_map}}} 24 | } 25 | \description{ 26 | This is a special version of ggplot2::annotation_raster for use 27 | with ggmap. (It simply removes the requirement for cartesian 28 | coordinates.) The only difference between \code{inset_raster} 29 | and \code{inset_ggmap} is their arguments. \code{inset_ggmap} is 30 | simply a wrapper of \code{inset_raster} with \code{xmin}, ..., 31 | \code{ymax} arguments equal to the map's bounding box. 32 | } 33 | \examples{ 34 | 35 | # see ?bb2bbox 36 | 37 | 38 | 39 | } 40 | -------------------------------------------------------------------------------- /man/theme_inset.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/theme_inset.R 3 | \name{theme_inset} 4 | \alias{theme_inset} 5 | \title{Make a ggplot2 inset theme.} 6 | \usage{ 7 | theme_inset(base_size = 12) 8 | } 9 | \arguments{ 10 | \item{base_size}{base size, not used.} 11 | } 12 | \value{ 13 | a ggplot2 theme (i.e., a list of class options). 14 | } 15 | \description{ 16 | theme_inset is a ggplot2 theme geared towards making inset plots. 17 | } 18 | \examples{ 19 | library(ggplot2) 20 | \dontrun{ 21 | 22 | 23 | n <- 50 24 | df <- expand.grid(x = 1:n,y = 1:n)[sample(n^2,.5*n^2),] 25 | qplot(x, y, data = df, geom = 'tile') 26 | qplot(x, y, data = df, geom = 'tile') + theme_nothing() 27 | 28 | qplot(1:10, 1:10) + 29 | annotation_custom( 30 | grob = ggplotGrob(qplot(1:10,1:10)), 31 | 8, Inf, -Inf, 2 32 | ) 33 | 34 | qplot(1:10, 1:10) + 35 | annotation_custom( 36 | grob = ggplotGrob(qplot(1:10,1:10) + theme_nothing()), 37 | 8, Inf, -Inf, 2 38 | ) 39 | 40 | qplot(1:10, 1:10) + 41 | annotation_custom( 42 | grob = ggplotGrob(qplot(1:10,1:10) + theme_inset()), 43 | 8, Inf, -Inf, 2 44 | ) 45 | 46 | } 47 | 48 | } 49 | \author{ 50 | David Kahle \email{david.kahle@gmail.com} 51 | } 52 | -------------------------------------------------------------------------------- /R/LonLat2XY.R: -------------------------------------------------------------------------------- 1 | #' Convert a lon/lat coordinate to a tile coordinate 2 | #' 3 | #' Convert a lon/lat coordinate to a tile coordinate for a given 4 | #' zoom. Decimal tile coordinates (x, y) are reported. 5 | #' 6 | #' @param lon_deg longitude in degrees 7 | #' @param lat_deg latitude in degrees 8 | #' @param zoom zoom 9 | #' @param xpix width of tile in pixels 10 | #' @param ypix length of tile in pixels 11 | #' @return a data frame with columns X, Y, x, y 12 | #' @author David Kahle \email{david.kahle@@gmail.com}, based on 13 | #' function LatLon2XY by Markus Loecher, Sense Networks 14 | #' \email{markus@@sensenetworks.com} in package RgoogleMaps 15 | #' @seealso 16 | #' \url{http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames} 17 | #' @export 18 | #' @examples 19 | #' 20 | #' 21 | #' \dontrun{ 22 | #' gc <- geocode('baylor university') 23 | #' LonLat2XY(gc$lon, gc$lat, 10) 24 | #' 25 | #' } 26 | #' 27 | LonLat2XY <- function(lon_deg, lat_deg, zoom, xpix=256, ypix=256){ 28 | n <- 2^zoom 29 | X <- ((lon_deg + 180) / 360) * n 30 | sec <- function(x) 1/cos(x) 31 | lat_rad <- lat_deg * pi/180 32 | Y <- (1 - (log(tan(lat_rad) + sec(lat_rad)) / pi)) / 2 * n 33 | df <- data.frame( 34 | X = floor(X), 35 | Y = floor(Y), 36 | x = xpix*(X - floor(X)), 37 | y = ypix*(Y - floor(Y)) 38 | ) 39 | row.names(df) <- NULL 40 | df 41 | } 42 | -------------------------------------------------------------------------------- /man/XY2LonLat.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/XY2LonLat.R 3 | \name{XY2LonLat} 4 | \alias{XY2LonLat} 5 | \title{Convert a tile coordinate to a lon/lat coordinate} 6 | \usage{ 7 | XY2LonLat(X, Y, zoom, x = 0, y = 0, xpix = 255, ypix = 255) 8 | } 9 | \arguments{ 10 | \item{X}{horizontal map-tile coordinate (0 is map-left)} 11 | 12 | \item{Y}{vertical map-tile coordinate (0 is map-top)} 13 | 14 | \item{zoom}{zoom} 15 | 16 | \item{x}{within tile x (0 is tile-left)} 17 | 18 | \item{y}{within tile y (0 it tile-top)} 19 | 20 | \item{xpix}{width of tile in pixels} 21 | 22 | \item{ypix}{length of tile in pixels} 23 | } 24 | \value{ 25 | a data frame with columns lon and lat (in degrees) 26 | } 27 | \description{ 28 | Convert a tile coordinate to a lon/lat coordinate for a given 29 | zoom. Decimal tile coordinates are accepted. 30 | } 31 | \examples{ 32 | 33 | 34 | \dontrun{ 35 | XY2LonLat(480, 845, zoom = 11) 36 | XY2LonLat(0, 0, zoom = 1) 37 | XY2LonLat(0, 0, 255, 255, zoom = 1) 38 | XY2LonLat(0, 0, 255, 255, zoom = 1) 39 | 40 | } 41 | 42 | } 43 | \seealso{ 44 | \url{http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames} 45 | } 46 | \author{ 47 | David Kahle \email{david.kahle@gmail.com}, based on 48 | function XY2LatLon by Markus Loecher, Sense Networks 49 | \email{markus@sensenetworks.com} in package RgoogleMaps 50 | } 51 | -------------------------------------------------------------------------------- /man/calc_zoom.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/calc_zoom.r 3 | \name{calc_zoom} 4 | \alias{calc_zoom} 5 | \title{Calculate a zoom given a bounding box} 6 | \usage{ 7 | calc_zoom(lon, lat, data, adjust = 0, f = 0.05) 8 | } 9 | \arguments{ 10 | \item{lon}{longitude, see details} 11 | 12 | \item{lat}{latitude, see details} 13 | 14 | \item{data}{(optional) a data frame containing lon and lat as 15 | variables} 16 | 17 | \item{adjust}{number to add to the calculated zoom} 18 | 19 | \item{f}{argument to pass to make_bbox} 20 | } 21 | \description{ 22 | calc_zoom can calculate a zoom based on either (1) a data frame 23 | with longitude and latitude variables, (2) a longitude range and 24 | latitude range, or (3) a bounding box (bbox specification). The 25 | specification for (1) is identical to that of most R functions, 26 | for (2) simply put in a longitude range into lon and a latitude 27 | range into lat, and for (3) put the bounding box in for the lon 28 | argument. 29 | } 30 | \examples{ 31 | # From data 32 | calc_zoom(lon, lat, wind) 33 | 34 | # From range 35 | lon_range <- extendrange( wind$lon ) 36 | lat_range <- extendrange( wind$lat ) 37 | calc_zoom(lon_range, lat_range) 38 | 39 | # From bounding box 40 | box <- make_bbox(lon, lat, data = crime) 41 | calc_zoom(box) 42 | } 43 | \seealso{ 44 | \code{\link{make_bbox}}, \code{\link{bb2bbox}} 45 | } 46 | -------------------------------------------------------------------------------- /man/theme_nothing.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/theme_nothing.R 3 | \name{theme_nothing} 4 | \alias{theme_nothing} 5 | \title{Make a blank ggplot2 theme.} 6 | \usage{ 7 | theme_nothing(base_size = 12, legend = FALSE) 8 | } 9 | \arguments{ 10 | \item{base_size}{base size, not used.} 11 | 12 | \item{legend}{should the legend be included?} 13 | } 14 | \value{ 15 | a ggplot2 theme (i.e., a list of class options). 16 | } 17 | \description{ 18 | theme_nothing simply strips all thematic element in ggplot2. 19 | } 20 | \examples{ 21 | 22 | 23 | # no legend example 24 | n <- 50 25 | df <- expand.grid(x = 1:n,y = 1:n)[sample(n^2,.5*n^2),] 26 | p <- qplot(x, y, data = df, geom = 'tile') 27 | p 28 | p + theme_nothing() 29 | p + theme_nothing(legend = TRUE) # no difference 30 | p + 31 | scale_x_continuous(expand = c(0,0)) + 32 | scale_y_continuous(expand = c(0,0)) + 33 | theme_nothing() 34 | 35 | 36 | 37 | # legend example 38 | df$class <- factor(sample(0:1, .5*n^2, replace = TRUE)) 39 | p <- qplot(x, y, data = df, geom = "tile", fill = class) 40 | p 41 | p + theme_nothing() 42 | p + theme_nothing(legend = TRUE) 43 | 44 | p <- p + 45 | scale_x_continuous(expand = c(0,0)) + 46 | scale_y_continuous(expand = c(0,0)) 47 | p 48 | p + theme_nothing() 49 | p + theme_nothing(legend = TRUE) 50 | 51 | 52 | 53 | } 54 | \author{ 55 | David Kahle \email{david.kahle@gmail.com} 56 | } 57 | -------------------------------------------------------------------------------- /man/bb2bbox.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/bb2bbox.R 3 | \name{bb2bbox} 4 | \alias{bb2bbox} 5 | \title{Convert a bb specification to a bbox specification} 6 | \usage{ 7 | bb2bbox(bb) 8 | } 9 | \arguments{ 10 | \item{bb}{a bounding box in bb format (see examples)} 11 | } 12 | \value{ 13 | a bounding box in bbox format (see examples) 14 | } 15 | \description{ 16 | In ggmap, all maps (class ggmap) have the bb attribute, a data 17 | frame bounding box specification in terms of the bottom left and 18 | top right points of the spatial extent. This function converts 19 | this specification to a named double vector (with names left, 20 | bottom, right, top) specification that is used in some querying 21 | functions (e.g. get_stamenmap). 22 | } 23 | \examples{ 24 | 25 | \dontrun{# cut down on R CMD check time 26 | 27 | # grab a center/zoom map and compute its bounding box 28 | gc <- geocode("white house, washington dc") 29 | map <- get_map(gc) 30 | (bb <- attr(map, "bb")) 31 | (bbox <- bb2bbox(bb)) 32 | 33 | # use the bounding box to get a stamen map 34 | stamMap <- get_stamenmap(bbox) 35 | 36 | ggmap(map) + 37 | geom_point( 38 | aes(x = lon, y = lat), 39 | data = gc, colour = "red", size = 3 40 | ) 41 | 42 | ggmap(stamMap) + 43 | geom_point( 44 | aes(x = lon, y = lat), 45 | data = gc, colour = "red", size = 3 46 | ) 47 | 48 | 49 | } 50 | 51 | 52 | } 53 | \author{ 54 | David Kahle \email{david.kahle@gmail.com} 55 | } 56 | -------------------------------------------------------------------------------- /R/bb2bbox.R: -------------------------------------------------------------------------------- 1 | #' Convert a bb specification to a bbox specification 2 | #' 3 | #' In ggmap, all maps (class ggmap) have the bb attribute, a data 4 | #' frame bounding box specification in terms of the bottom left and 5 | #' top right points of the spatial extent. This function converts 6 | #' this specification to a named double vector (with names left, 7 | #' bottom, right, top) specification that is used in some querying 8 | #' functions (e.g. get_stamenmap). 9 | #' 10 | #' @param bb a bounding box in bb format (see examples) 11 | #' @return a bounding box in bbox format (see examples) 12 | #' @author David Kahle \email{david.kahle@@gmail.com} 13 | #' @export 14 | #' @examples 15 | #' 16 | #' \dontrun{# cut down on R CMD check time 17 | #' 18 | #' # grab a center/zoom map and compute its bounding box 19 | #' gc <- geocode("white house, washington dc") 20 | #' map <- get_map(gc) 21 | #' (bb <- attr(map, "bb")) 22 | #' (bbox <- bb2bbox(bb)) 23 | #' 24 | #' # use the bounding box to get a stamen map 25 | #' stamMap <- get_stamenmap(bbox) 26 | #' 27 | #' ggmap(map) + 28 | #' geom_point( 29 | #' aes(x = lon, y = lat), 30 | #' data = gc, colour = "red", size = 3 31 | #' ) 32 | #' 33 | #' ggmap(stamMap) + 34 | #' geom_point( 35 | #' aes(x = lon, y = lat), 36 | #' data = gc, colour = "red", size = 3 37 | #' ) 38 | #' 39 | #' 40 | #' } 41 | #' 42 | #' 43 | bb2bbox <- function(bb){ 44 | with(bb, 45 | c( 46 | left = ll.lon, bottom = ll.lat, 47 | right = ur.lon, top = ur.lat 48 | ) 49 | ) 50 | } 51 | -------------------------------------------------------------------------------- /R/XY2LonLat.R: -------------------------------------------------------------------------------- 1 | #' Convert a tile coordinate to a lon/lat coordinate 2 | #' 3 | #' Convert a tile coordinate to a lon/lat coordinate for a given 4 | #' zoom. Decimal tile coordinates are accepted. 5 | #' 6 | #' @param X horizontal map-tile coordinate (0 is map-left) 7 | #' @param Y vertical map-tile coordinate (0 is map-top) 8 | #' @param zoom zoom 9 | #' @param x within tile x (0 is tile-left) 10 | #' @param y within tile y (0 it tile-top) 11 | #' @param xpix width of tile in pixels 12 | #' @param ypix length of tile in pixels 13 | #' @return a data frame with columns lon and lat (in degrees) 14 | #' @author David Kahle \email{david.kahle@@gmail.com}, based on 15 | #' function XY2LatLon by Markus Loecher, Sense Networks 16 | #' \email{markus@@sensenetworks.com} in package RgoogleMaps 17 | #' @seealso 18 | #' \url{http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames} 19 | #' @export 20 | #' @examples 21 | #' 22 | #' 23 | #' \dontrun{ 24 | #' XY2LonLat(480, 845, zoom = 11) 25 | #' XY2LonLat(0, 0, zoom = 1) 26 | #' XY2LonLat(0, 0, 255, 255, zoom = 1) 27 | #' XY2LonLat(0, 0, 255, 255, zoom = 1) 28 | #' 29 | #' } 30 | #' 31 | XY2LonLat <- function(X, Y, zoom, x = 0, y = 0, xpix=255, ypix=255){ 32 | n <- 2^zoom 33 | lon_deg <- (X+x/xpix) / n * 360.0 - 180.0 34 | tmp <- tanh( pi * (1 - 2 * (Y+y/ypix) / n)) 35 | ShiftLat <- function(tmp) { 36 | lat <- 2 * pi * (-1:1) + asin(tmp) 37 | lat[which(-pi/2 < lat & lat <= pi/2)] * 180/pi 38 | } 39 | lat_deg <- ShiftLat(tmp) 40 | data.frame(lon = lon_deg, lat = lat_deg) 41 | } 42 | -------------------------------------------------------------------------------- /R/theme_inset.R: -------------------------------------------------------------------------------- 1 | #' Make a ggplot2 inset theme. 2 | #' 3 | #' theme_inset is a ggplot2 theme geared towards making inset plots. 4 | #' 5 | #' @param base_size base size, not used. 6 | #' @return a ggplot2 theme (i.e., a list of class options). 7 | #' @author David Kahle \email{david.kahle@@gmail.com} 8 | #' @export 9 | #' @examples 10 | #' library(ggplot2) 11 | #' \dontrun{ 12 | #' 13 | #' 14 | #' n <- 50 15 | #' df <- expand.grid(x = 1:n,y = 1:n)[sample(n^2,.5*n^2),] 16 | #' qplot(x, y, data = df, geom = 'tile') 17 | #' qplot(x, y, data = df, geom = 'tile') + theme_nothing() 18 | #' 19 | #' qplot(1:10, 1:10) + 20 | #' annotation_custom( 21 | #' grob = ggplotGrob(qplot(1:10,1:10)), 22 | #' 8, Inf, -Inf, 2 23 | #' ) 24 | #' 25 | #' qplot(1:10, 1:10) + 26 | #' annotation_custom( 27 | #' grob = ggplotGrob(qplot(1:10,1:10) + theme_nothing()), 28 | #' 8, Inf, -Inf, 2 29 | #' ) 30 | #' 31 | #' qplot(1:10, 1:10) + 32 | #' annotation_custom( 33 | #' grob = ggplotGrob(qplot(1:10,1:10) + theme_inset()), 34 | #' 8, Inf, -Inf, 2 35 | #' ) 36 | #' 37 | #' } 38 | #' 39 | theme_inset <- function (base_size = 12){ 40 | theme(axis.line = element_blank(), 41 | axis.text = element_blank(), 42 | axis.ticks = element_blank(), 43 | axis.title = element_blank(), 44 | axis.ticks.length = unit(0, "lines"), 45 | panel.spacing = unit(0, "lines"), 46 | plot.margin = unit(c(0, 0, 0, 0), "lines"), 47 | legend.position = 'none') 48 | } 49 | -------------------------------------------------------------------------------- /man/revgeocode.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/revgeocode.R 3 | \name{revgeocode} 4 | \alias{revgeocode} 5 | \title{Reverse geocode} 6 | \usage{ 7 | revgeocode(location, output = c("address", "more", "all"), 8 | messaging = FALSE, urlonly = FALSE, override_limit = FALSE, 9 | ext = "com", inject = "", ...) 10 | } 11 | \arguments{ 12 | \item{location}{a location in longitude/latitude format} 13 | 14 | \item{output}{amount of output} 15 | 16 | \item{messaging}{turn messaging on/off} 17 | 18 | \item{urlonly}{return only the url?} 19 | 20 | \item{override_limit}{override the current query count 21 | (.GoogleGeocodeQueryCount)} 22 | 23 | \item{ext}{domain extension (e.g. "com", "co.nz")} 24 | 25 | \item{inject}{character string to add to the url} 26 | 27 | \item{...}{...} 28 | } 29 | \value{ 30 | depends (at least an address) 31 | } 32 | \description{ 33 | reverse geocodes a longitude/latitude location using Google Maps. 34 | Note that in most cases by using this function you are agreeing 35 | to the Google Maps API Terms of Service at 36 | https://developers.google.com/maps/terms. 37 | } 38 | \examples{ 39 | 40 | \dontrun{ # Server response can be slow; this cuts down check time. 41 | 42 | ( gc <- as.numeric(geocode("the white house")) ) 43 | revgeocode(gc) 44 | revgeocode(gc, output = "more") 45 | revgeocode(gc, output = "all") 46 | geocodeQueryCheck() 47 | 48 | } 49 | 50 | } 51 | \seealso{ 52 | \url{http://code.google.com/apis/maps/documentation/geocoding/} 53 | } 54 | \author{ 55 | David Kahle \email{david.kahle@gmail.com} 56 | } 57 | -------------------------------------------------------------------------------- /man/qmap.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/qmap.R 3 | \name{qmap} 4 | \alias{qmap} 5 | \title{Quick map plot} 6 | \usage{ 7 | qmap(location = "houston", ...) 8 | } 9 | \arguments{ 10 | \item{location}{character; location of interest} 11 | 12 | \item{...}{stuff to pass to \code{\link{ggmap}} and 13 | \code{\link{get_map}}.} 14 | } 15 | \value{ 16 | a ggplot object 17 | } 18 | \description{ 19 | qmap is a wrapper for \code{\link{ggmap}} and 20 | \code{\link{get_map}}. 21 | } 22 | \examples{ 23 | 24 | \dontrun{ 25 | # these examples have been excluded for checking efficiency 26 | 27 | location <- "marrs mclean science, waco, texas" 28 | qmap(location) 29 | qmap(location, zoom = 14) 30 | qmap(location, zoom = 14, source = "osm") 31 | qmap(location, zoom = 14, source = "osm", scale = 20000) 32 | qmap(location, zoom = 14, maptype = "satellite") 33 | qmap(location, zoom = 14, maptype = "hybrid") 34 | qmap(location, zoom = 14, maptype = "toner", source = "stamen") 35 | qmap(location, zoom = 14, maptype = "watercolor", source = "stamen") 36 | qmap(location, zoom = 14, maptype = "terrain-background", source = "stamen") 37 | qmap(location, zoom = 14, maptype = "toner-lite", source = "stamen") 38 | 39 | where <- "the white house, washington dc" 40 | wh <- geocode(where) 41 | qmap(where, maprange = TRUE, zoom = 15, 42 | base_layer = ggplot(aes(x=lon, y=lat), data = wh)) + 43 | geom_point() 44 | 45 | 46 | 47 | } 48 | 49 | } 50 | \seealso{ 51 | \code{\link{ggmap}} and \code{\link{get_map}}. 52 | } 53 | \author{ 54 | David Kahle \email{david.kahle@gmail.com} 55 | } 56 | -------------------------------------------------------------------------------- /man/ggimage.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggimage.R 3 | \name{ggimage} 4 | \alias{ggimage} 5 | \title{Plot an image using ggplot2} 6 | \usage{ 7 | ggimage(mat, fullpage = TRUE, coord_equal = TRUE, scale_axes = FALSE) 8 | } 9 | \arguments{ 10 | \item{mat}{a matrix, imagematrix, array, or raster (something 11 | that can be coerced by as.raster)} 12 | 13 | \item{fullpage}{should the image take up the entire viewport?} 14 | 15 | \item{coord_equal}{should the axes units be equal?} 16 | 17 | \item{scale_axes}{should the axes be 18 | [0,ncol(mat)-1]x[0,nrow(mat)-1] (F) or [0,1]x[0,1] (T)} 19 | } 20 | \value{ 21 | a ggplot object 22 | } 23 | \description{ 24 | ggimage is the near ggplot2 equivalent of image. 25 | } 26 | \examples{ 27 | 28 | img <- matrix(1:16, 4, 4) 29 | image(img) 30 | ggimage(t(img[,4:1]), fullpage = FALSE, scale_axes = TRUE) 31 | ggimage(t(img[,4:1]), fullpage = FALSE) 32 | 33 | 34 | \dontrun{ 35 | # not run due to slow performance 36 | 37 | data(hadley) 38 | ggimage(hadley) 39 | ggimage(hadley, coord_equal = FALSE) 40 | 41 | x <- seq(1, 438, 15); n <- length(x) 42 | df <- data.frame(x = x, y = -(120*(scale((x - 219)^3 - 25000*x) + rnorm(n)/2 - 3))) 43 | qplot(x, y, data = df, geom = c('smooth','point')) 44 | ggimage(hadley, fullpage = FALSE) + 45 | geom_smooth(aes(x = x, y = y), fill = I('gray60'), data = df, 46 | colour = I('green'), size = I(1)) + 47 | geom_point(aes(x = x, y = y), data = df, 48 | colour = I('green'), size = I(3), fill = NA) 49 | 50 | } 51 | } 52 | \author{ 53 | David Kahle \email{david.kahle@gmail.com} 54 | } 55 | -------------------------------------------------------------------------------- /man/legs2route.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/route.R 3 | \name{legs2route} 4 | \alias{legs2route} 5 | \title{Convert a leg-structured route to a route-structured route} 6 | \usage{ 7 | legs2route(legsdf) 8 | } 9 | \arguments{ 10 | \item{legsdf}{a legs-structured route, see \code{\link{route}}} 11 | } 12 | \description{ 13 | Convert a leg-structured route to a route-structured route 14 | } 15 | \examples{ 16 | 17 | \dontrun{ 18 | 19 | (legs_df <- route("houston","galveston")) 20 | legs2route(legs_df) 21 | (legs_df <- route( 22 | "marrs mclean science, baylor university", 23 | "220 south 3rd street, waco, tx 76701", # ninfa"s 24 | alternatives = TRUE)) 25 | 26 | legs2route(legs_df) 27 | 28 | 29 | 30 | 31 | from <- "houston, texas" 32 | to <- "waco, texas" 33 | legs_df <- route(from, to) 34 | 35 | 36 | qmap("college station, texas", zoom = 8) + 37 | geom_segment( 38 | aes(x = startLon, y = startLat, xend = endLon, yend = endLat), 39 | colour = "red", size = 1.5, data = legs_df 40 | ) 41 | # notice boxy ends 42 | 43 | qmap("college station, texas", zoom = 8) + 44 | geom_leg( 45 | aes(x = startLon, y = startLat, xend = endLon, yend = endLat), 46 | colour = "red", size = 1.5, data = legs_df 47 | ) 48 | # notice overshooting ends 49 | 50 | route_df <- legs2route(legs_df) 51 | qmap("college station, texas", zoom = 8) + 52 | geom_path( 53 | aes(x = lon, y = lat), 54 | colour = "red", size = 1.5, data = route_df, lineend = "round" 55 | ) 56 | 57 | 58 | 59 | } 60 | 61 | } 62 | \seealso{ 63 | geom_path in ggplot2 64 | } 65 | -------------------------------------------------------------------------------- /R/coord_map.R: -------------------------------------------------------------------------------- 1 | # Replacement for ggplot2:::mproject when using "mercator" projection 2 | mproject2 <- function(coord, x, y, orientation){ 3 | npix <- 2 * pi 4 | xXyY <- suppressWarnings(LonLat2XY(x, y, zoom = 0, 5 | xpix = npix, ypix = npix)) 6 | x2 <- (npix * xXyY$X + xXyY$x) - pi 7 | x2[is.nan(x2)] <- NA_real_ 8 | y2 <- pi - (npix * xXyY$Y + xXyY$y) 9 | y2[is.nan(y2)] <- NA_real_ 10 | list(x = x2, y = y2, 11 | range = c(range(x2, na.rm = TRUE), range(y2, na.rm = TRUE)), 12 | error = 0) 13 | } 14 | 15 | # Modified ggplot2::coord_map, replaces uses of ggplot2:::mproject 16 | # with mproject2. Dependence on ggplot2 (version >= 2.2.0) internals is 17 | # unfortunate. 18 | coord_map2 <- function(){ 19 | trans_fun <- get("f", environment(CoordMap$transform)) 20 | trans_env <- new.env(parent = environment(trans_fun)) 21 | assign("mproject", mproject2, trans_env) 22 | environment(trans_fun) <- trans_env 23 | name_is_setup <- "setup_panel_params" %in% names(CoordMap) 24 | if (name_is_setup) { 25 | train_fun <- get("f", environment(CoordMap$setup_panel_params)) 26 | } else { 27 | train_fun <- get("f", environment(CoordMap$train)) 28 | } 29 | train_env <- new.env(parent = environment(train_fun)) 30 | assign("mproject", mproject2, train_env) 31 | environment(train_fun) <- train_env 32 | ggargs <- alist(NULL, CoordMap, projection = "mercator", orientation = NULL, 33 | limits = list(x = NULL, y = NULL), params = list(), 34 | transform = trans_fun) 35 | if (name_is_setup) { 36 | ggargs <- c(ggargs, alist(setup_panel_params = train_fun)) 37 | } else { 38 | ggargs <- c(ggargs, alist(train = train_fun)) 39 | } 40 | do.call("ggproto", ggargs) 41 | } 42 | -------------------------------------------------------------------------------- /man/gglocator.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/gglocator.R 3 | \name{gglocator} 4 | \alias{gglocator} 5 | \title{Locator for ggplots.} 6 | \usage{ 7 | gglocator(n = 1, message = FALSE, xexpand = c(0, 0), yexpand = c(0, 0), 8 | mercator = TRUE) 9 | } 10 | \arguments{ 11 | \item{n}{number of points to locate.} 12 | 13 | \item{message}{unused} 14 | 15 | \item{xexpand}{expand argument in scale_x_continuous} 16 | 17 | \item{yexpand}{expand argument in scale_y_continuous} 18 | 19 | \item{mercator}{logical flag; should the plot be treated as using 20 | the projection common to most web map services? Set to FALSE if 21 | the axes on the plot use a linear scale.} 22 | } 23 | \value{ 24 | a data frame with columns according to the x and y 25 | aesthetics 26 | } 27 | \description{ 28 | Locator for ggplots. (Note : only accurate when extent = "normal" 29 | when using ggmap.) 30 | } 31 | \examples{ 32 | 33 | if(interactive()){ 34 | 35 | # only run for interactive sessions 36 | df <- expand.grid(x = 0:-5, y = 0:-5) 37 | p <- qplot(x, y, data = df) + 38 | annotate(geom = "point", x = -2, y = -2, colour = "red") 39 | print(p) 40 | cat("click red point\\n") 41 | print(pt <- gglocator(mercator = FALSE)) 42 | p2 <- last_plot() + 43 | annotate("point", pt$x, pt$y, color = "blue", size = 3, alpha = .5) 44 | cat("a blue point should appear where you clicked\\n") 45 | print(p2) 46 | 47 | p3 <- p + 48 | scale_x_continuous(expand = c(0,0)) + 49 | scale_y_continuous(expand = c(0,0)) 50 | print(p3) 51 | cat("click any point\\n") 52 | print(gglocator(1, xexpand = c(0,0), yexpand = c(0,0), 53 | mercator = FALSE)) 54 | 55 | 56 | } 57 | 58 | 59 | } 60 | \author{ 61 | Tyler Rinker with help from Baptiste Auguie and 62 | StackOverflow user DWin with additions and canning by David 63 | Kahle \email{david.kahle@gmail.com}. Updated by 64 | \@Nikolai-Hlubek and \@mvkorpel. 65 | } 66 | -------------------------------------------------------------------------------- /man/register_google.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/register_google.R 3 | \name{register_google} 4 | \alias{register_google} 5 | \alias{goog_key} 6 | \alias{has_goog_key} 7 | \alias{has_goog_account} 8 | \alias{goog_account} 9 | \alias{goog_client} 10 | \alias{has_goog_client} 11 | \alias{goog_signature} 12 | \alias{has_goog_signature} 13 | \alias{goog_second_limit} 14 | \alias{goog_day_limit} 15 | \alias{check_google_for_error} 16 | \title{Register a Google API} 17 | \usage{ 18 | register_google(key, account_type, client, signature, second_limit, day_limit) 19 | 20 | goog_key() 21 | 22 | has_goog_key() 23 | 24 | has_goog_account() 25 | 26 | goog_account() 27 | 28 | goog_client() 29 | 30 | has_goog_client() 31 | 32 | goog_signature() 33 | 34 | has_goog_signature() 35 | 36 | goog_second_limit() 37 | 38 | goog_day_limit() 39 | 40 | check_google_for_error(tree) 41 | } 42 | \arguments{ 43 | \item{key}{an api key} 44 | 45 | \item{account_type}{\code{"standard"} or \code{"premium"}} 46 | 47 | \item{client}{client code} 48 | 49 | \item{signature}{signature code} 50 | 51 | \item{second_limit}{query limit per second (default 50)} 52 | 53 | \item{day_limit}{query limit per day (default 2500 for standard 54 | accounts, 100000 for premium accounts)} 55 | 56 | \item{tree}{a json tree from \code{\link{fromJSON}}} 57 | } 58 | \description{ 59 | Many features of the Google web mapping services can be improved 60 | by using standard or premium credentials, such as usage limits 61 | and query rates. This function allows users to input this 62 | information into R as a global option to be retained for the 63 | entire session. 64 | } 65 | \examples{ 66 | 67 | 68 | has_goog_key() 69 | goog_key() 70 | has_goog_client() 71 | has_goog_signature() 72 | register_google(key = "[your key here]") 73 | 74 | } 75 | \seealso{ 76 | \url{http://code.google.com/apis/maps/documentation/geocoding/}, 77 | \url{https://developers.google.com/maps/documentation/geocoding/usage-limits} 78 | } 79 | \author{ 80 | David Kahle \email{david.kahle@gmail.com} 81 | } 82 | -------------------------------------------------------------------------------- /R/file_drawer.R: -------------------------------------------------------------------------------- 1 | #' Manage the ggmap file drawer. 2 | #' 3 | #' To avoid downloading the same maps again and again, ggmap uses a 4 | #' "file drawer" to store the maps you've downloaded. By default, 5 | #' they will be stored in a session specific temporary directory 6 | #' which will be deleted each time you quit R. If you want them to 7 | #' persist across sessions, set the global option 8 | #' "ggmap.file_drawer". 9 | #' 10 | #' @export 11 | #' @keywords internal 12 | #' @examples 13 | #' 14 | #' \dontrun{# if server is unresponsive, R check will fail 15 | #' 16 | #' file_drawer() 17 | #' dir(file_drawer()) 18 | #' 19 | #' # The first time you run this, the tiles are downloaded from the server 20 | #' map <- get_stamenmap() 21 | #' # The second time, the local cache is used so it's much faster 22 | #' map <- get_stamenmap() 23 | #' 24 | #' dir(file_drawer()) 25 | #' 26 | #' } 27 | #' 28 | file_drawer <- function(...) { 29 | fd <- getOption("ggmap.file_drawer", file.path(tempdir(), "ggmap")) 30 | file.path(fd, ...) 31 | } 32 | 33 | file_drawer_exists <- function() { 34 | file.exists(file_drawer()) 35 | } 36 | 37 | file_drawer_create <- function() { 38 | if (file_drawer_exists()) return() 39 | 40 | dir.create(file_drawer(), recursive = TRUE, showWarnings = FALSE) 41 | saveRDS(list(), file_drawer("index.rds")) 42 | 43 | invisible(TRUE) 44 | } 45 | 46 | file_drawer_index <- function() { 47 | file_drawer_create() 48 | readRDS(file_drawer("index.rds")) 49 | } 50 | 51 | file_drawer_set <- function(url, map, name = NULL) { 52 | if (is.null(name)) { 53 | name <- paste0(digest::digest(url), '.rds') 54 | } 55 | 56 | index <- file_drawer_index() 57 | 58 | if (url %in% names(index)) { 59 | file.remove(file_drawer(index[[url]])) 60 | } 61 | index[[url]] <- name 62 | saveRDS(index, file_drawer("index.rds")) 63 | saveRDS(map, file_drawer(name)) 64 | 65 | invisible(TRUE) 66 | } 67 | 68 | file_drawer_get <- function(url) { 69 | index <- file_drawer_index() 70 | name <- index[[url]] 71 | 72 | if (is.null(name)) return(NULL) 73 | readRDS(file_drawer(name)) 74 | } 75 | -------------------------------------------------------------------------------- /R/theme_nothing.R: -------------------------------------------------------------------------------- 1 | #' Make a blank ggplot2 theme. 2 | #' 3 | #' theme_nothing simply strips all thematic element in ggplot2. 4 | #' 5 | #' @param base_size base size, not used. 6 | #' @param legend should the legend be included? 7 | #' @return a ggplot2 theme (i.e., a list of class options). 8 | #' @author David Kahle \email{david.kahle@@gmail.com} 9 | #' @export 10 | #' @examples 11 | #' 12 | #' 13 | #' # no legend example 14 | #' n <- 50 15 | #' df <- expand.grid(x = 1:n,y = 1:n)[sample(n^2,.5*n^2),] 16 | #' p <- qplot(x, y, data = df, geom = 'tile') 17 | #' p 18 | #' p + theme_nothing() 19 | #' p + theme_nothing(legend = TRUE) # no difference 20 | #' p + 21 | #' scale_x_continuous(expand = c(0,0)) + 22 | #' scale_y_continuous(expand = c(0,0)) + 23 | #' theme_nothing() 24 | #' 25 | #' 26 | #' 27 | #' # legend example 28 | #' df$class <- factor(sample(0:1, .5*n^2, replace = TRUE)) 29 | #' p <- qplot(x, y, data = df, geom = "tile", fill = class) 30 | #' p 31 | #' p + theme_nothing() 32 | #' p + theme_nothing(legend = TRUE) 33 | #' 34 | #' p <- p + 35 | #' scale_x_continuous(expand = c(0,0)) + 36 | #' scale_y_continuous(expand = c(0,0)) 37 | #' p 38 | #' p + theme_nothing() 39 | #' p + theme_nothing(legend = TRUE) 40 | #' 41 | #' 42 | #' 43 | theme_nothing <- function(base_size = 12, legend = FALSE){ 44 | if(legend){ 45 | theme( 46 | axis.text = element_blank(), 47 | axis.title = element_blank(), 48 | panel.background = element_blank(), 49 | panel.grid.major = element_blank(), 50 | panel.grid.minor = element_blank(), 51 | axis.ticks.length = unit(0, "cm"), 52 | panel.spacing = unit(0, "lines"), 53 | plot.margin = unit(c(0, 0, 0, 0), "lines") 54 | ) 55 | } else { 56 | theme( 57 | line = element_blank(), 58 | rect = element_blank(), 59 | text = element_blank(), 60 | axis.ticks.length = unit(0, "cm"), 61 | legend.position = "none", 62 | panel.spacing = unit(0, "lines"), 63 | plot.margin = unit(c(0, 0, 0, 0), "lines") 64 | ) 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /man/get_cloudmademap.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_cloudmademap.R 3 | \name{get_cloudmademap} 4 | \alias{get_cloudmademap} 5 | \title{Get a CloudMade map.} 6 | \usage{ 7 | get_cloudmademap(bbox = c(left = -95.80204, bottom = 29.38048, right = 8 | -94.92313, top = 30.14344), zoom = 10, api_key, maptype = 1, 9 | highres = TRUE, crop = TRUE, messaging = FALSE, urlonly = FALSE, 10 | filename = NULL, color = c("color", "bw"), ...) 11 | } 12 | \arguments{ 13 | \item{bbox}{a bounding box in the format c(lowerleftlon, 14 | lowerleftlat, upperrightlon, upperrightlat).} 15 | 16 | \item{zoom}{a zoom level} 17 | 18 | \item{api_key}{character string containing cloud made api key, 19 | see details} 20 | 21 | \item{maptype}{an integer of what cloud made calls style, see 22 | details} 23 | 24 | \item{highres}{double resolution} 25 | 26 | \item{crop}{crop raw map tiles to specified bounding box} 27 | 28 | \item{messaging}{turn messaging on/off} 29 | 30 | \item{urlonly}{return url only} 31 | 32 | \item{filename}{destination file for download (file extension 33 | added according to format). Default \code{NULL} means a random 34 | \code{\link{tempfile}}.} 35 | 36 | \item{color}{color or black-and-white} 37 | 38 | \item{...}{...} 39 | } 40 | \value{ 41 | a ggmap object (a classed raster object with a bounding 42 | box attribute) 43 | } 44 | \description{ 45 | \code{get_cloudmademap} accesses a tile server for Stamen Maps 46 | and downloads/stitches map tiles/formats a map image. This 47 | function requires an api key which can be obtained for free from 48 | http://cloudmade.com/user/show (defunct?). Thousands of maptypes 49 | ("styles"), including create-your-own options, are available from 50 | http://maps.cloudmade.com/editor (defunct). 51 | } 52 | \examples{ 53 | \dontrun{ # in what follows, enter your own api key 54 | 55 | api_key <- '' 56 | api_key <- 'b23b0358e87c4ff99f81029eda25c903' 57 | 58 | map <- get_cloudmademap(api_key = api_key) 59 | ggmap(map) 60 | 61 | map <- get_cloudmademap(maptype = 997, api_key = api_key) 62 | ggmap(map) 63 | } 64 | } 65 | \seealso{ 66 | http://maps.cloudmade.com/ (defunct), 67 | \code{\link{ggmap}} 68 | } 69 | \author{ 70 | David Kahle \email{david.kahle@gmail.com} 71 | } 72 | -------------------------------------------------------------------------------- /R/inset.R: -------------------------------------------------------------------------------- 1 | #' Add ggplot2 insets to a map 2 | #' 3 | #' This is identical to ggplot2::annotation_custom for use with 4 | #' ggmap 5 | #' 6 | #' Most useful for adding tables, inset plots, and other grid-based 7 | #' decorations 8 | #' 9 | #' @param grob grob to display 10 | #' @param xmin,xmax x location (in data coordinates) giving 11 | #' horizontal location of raster 12 | #' @param ymin,ymax y location (in data coordinates) giving vertical 13 | #' location of raster 14 | #' @export inset 15 | #' @note \code{annotation_custom} expects the grob to fill the 16 | #' entire viewport defined by xmin, xmax, ymin, ymax. Grobs with a 17 | #' different (absolute) size will be center-justified in that 18 | #' region. Inf values can be used to fill the full plot panel 19 | inset <- annotation_custom <- function(grob, xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf) { 20 | layer( 21 | data = NULL, 22 | stat = ggplot2::StatIdentity, 23 | position = ggplot2::PositionIdentity, 24 | geom = GeomCustomAnn, 25 | inherit.aes = TRUE, 26 | params = list( 27 | grob = grob, 28 | xmin = xmin, 29 | xmax = xmax, 30 | ymin = ymin, 31 | ymax = ymax 32 | ) 33 | ) 34 | } 35 | 36 | 37 | GeomCustomAnn <- ggproto("GeomCustomAnn", Geom, 38 | extra_params = "", 39 | handle_na = function(data, params) { 40 | data 41 | }, 42 | 43 | draw_panel = function(data, panel_scales, coord, grob, xmin, xmax, 44 | ymin, ymax) { 45 | # if (!inherits(coord, "CoordCartesian")) { 46 | # stop("annotation_custom only works with Cartesian coordinates", 47 | # call. = FALSE) 48 | # } 49 | corners <- data.frame(x = c(xmin, xmax), y = c(ymin, ymax)) 50 | data <- coord$transform(corners, panel_scales) 51 | 52 | x_rng <- range(data$x, na.rm = TRUE) 53 | y_rng <- range(data$y, na.rm = TRUE) 54 | 55 | vp <- viewport(x = mean(x_rng), y = mean(y_rng), 56 | width = diff(x_rng), height = diff(y_rng), 57 | just = c("center","center")) 58 | editGrob(grob, vp = vp, name = paste(grob$name, annotation_id())) 59 | }, 60 | 61 | default_aes = aes_(xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf) 62 | ) 63 | 64 | 65 | 66 | 67 | 68 | annotation_id <- local({ 69 | i <- 1 70 | function() { 71 | i <<- i + 1 72 | i 73 | } 74 | }) 75 | -------------------------------------------------------------------------------- /R/ggimage.R: -------------------------------------------------------------------------------- 1 | #' Plot an image using ggplot2 2 | #' 3 | #' ggimage is the near ggplot2 equivalent of image. 4 | #' 5 | #' @param mat a matrix, imagematrix, array, or raster (something 6 | #' that can be coerced by as.raster) 7 | #' @param fullpage should the image take up the entire viewport? 8 | #' @param coord_equal should the axes units be equal? 9 | #' @param scale_axes should the axes be 10 | #' [0,ncol(mat)-1]x[0,nrow(mat)-1] (F) or [0,1]x[0,1] (T) 11 | #' @return a ggplot object 12 | #' @author David Kahle \email{david.kahle@@gmail.com} 13 | #' @export 14 | #' @examples 15 | #' 16 | #' img <- matrix(1:16, 4, 4) 17 | #' image(img) 18 | #' ggimage(t(img[,4:1]), fullpage = FALSE, scale_axes = TRUE) 19 | #' ggimage(t(img[,4:1]), fullpage = FALSE) 20 | #' 21 | #' 22 | #' \dontrun{ 23 | #' # not run due to slow performance 24 | #' 25 | #' data(hadley) 26 | #' ggimage(hadley) 27 | #' ggimage(hadley, coord_equal = FALSE) 28 | #' 29 | #' x <- seq(1, 438, 15); n <- length(x) 30 | #' df <- data.frame(x = x, y = -(120*(scale((x - 219)^3 - 25000*x) + rnorm(n)/2 - 3))) 31 | #' qplot(x, y, data = df, geom = c('smooth','point')) 32 | #' ggimage(hadley, fullpage = FALSE) + 33 | #' geom_smooth(aes(x = x, y = y), fill = I('gray60'), data = df, 34 | #' colour = I('green'), size = I(1)) + 35 | #' geom_point(aes(x = x, y = y), data = df, 36 | #' colour = I('green'), size = I(3), fill = NA) 37 | #' 38 | #' } 39 | ggimage <- function(mat, fullpage = TRUE, coord_equal = TRUE, scale_axes = FALSE){ 40 | 41 | x <- NULL; rm(x); y <- NULL; rm(y); 42 | 43 | if(!any(class(mat) %in% c('matrix','imagematrix','array','raster'))){ 44 | stop('mat should be a matrix or an array.') 45 | } 46 | 47 | n <- nrow(mat) 48 | p <- ncol(mat) 49 | 50 | if(scale_axes) n <- p <- 2 51 | 52 | fourCorners <- expand.grid(x = 0:(p-1), y = 0:(n-1)) 53 | 54 | if(max(mat) > 1 || min(mat) < 0){ 55 | message('rescaling mat to [0,1]...') 56 | mat <- (mat - min(mat)) / (max(mat) - min(mat)) 57 | } 58 | 59 | raster <- as.raster(mat) 60 | 61 | plot <- ggplot(aes(x, y), data = fourCorners) + geom_blank() + 62 | #ggmap:::annotation_raster(raster, 0, p-1, 0, n-1) + 63 | annotation_raster(raster, 0, p-1, 0, n-1) + 64 | scale_x_continuous(expand = c(0,0)) + 65 | scale_y_continuous(expand = c(0,0)) 66 | 67 | if(fullpage) plot <- plot + theme_nothing() 68 | 69 | if(coord_equal) plot <- plot + coord_equal() 70 | 71 | plot 72 | } 73 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(print,ggmap) 4 | S3method(print,ggmap_credentials) 5 | export(LonLat2XY) 6 | export(OSM_scale_lookup) 7 | export(XY2LonLat) 8 | export(bb2bbox) 9 | export(calc_zoom) 10 | export(check_google_for_error) 11 | export(distQueryCheck) 12 | export(file_drawer) 13 | export(geocode) 14 | export(geocodeQueryCheck) 15 | export(geom_leg) 16 | export(get_cloudmademap) 17 | export(get_googlemap) 18 | export(get_map) 19 | export(get_navermap) 20 | export(get_openstreetmap) 21 | export(get_stamenmap) 22 | export(ggimage) 23 | export(gglocator) 24 | export(ggmap) 25 | export(ggmap_credentials) 26 | export(ggmapplot) 27 | export(goog_account) 28 | export(goog_client) 29 | export(goog_day_limit) 30 | export(goog_key) 31 | export(goog_second_limit) 32 | export(goog_signature) 33 | export(has_goog_account) 34 | export(has_goog_client) 35 | export(has_goog_key) 36 | export(has_goog_signature) 37 | export(inset) 38 | export(inset_ggmap) 39 | export(inset_raster) 40 | export(legs2route) 41 | export(make_bbox) 42 | export(mapdist) 43 | export(mutate_geocode) 44 | export(qmap) 45 | export(qmplot) 46 | export(register_google) 47 | export(revgeocode) 48 | export(route) 49 | export(routeQueryCheck) 50 | export(theme_inset) 51 | export(theme_nothing) 52 | export(trek) 53 | import(ggplot2) 54 | importFrom(RgoogleMaps,XY2LatLon) 55 | importFrom(bitops,bitAnd) 56 | importFrom(bitops,bitOr) 57 | importFrom(bitops,bitShiftL) 58 | importFrom(bitops,bitShiftR) 59 | importFrom(dplyr,bind_cols) 60 | importFrom(dplyr,bind_rows) 61 | importFrom(dplyr,filter) 62 | importFrom(grDevices,as.raster) 63 | importFrom(grDevices,extendrange) 64 | importFrom(grDevices,gray) 65 | importFrom(grDevices,rgb) 66 | importFrom(grid,current.vpPath) 67 | importFrom(grid,current.vpTree) 68 | importFrom(grid,downViewport) 69 | importFrom(grid,grid.locator) 70 | importFrom(grid,rasterGrob) 71 | importFrom(grid,seekViewport) 72 | importFrom(grid,upViewport) 73 | importFrom(grid,viewport) 74 | importFrom(jpeg,readJPEG) 75 | importFrom(plyr,.) 76 | importFrom(plyr,arrange) 77 | importFrom(plyr,compact) 78 | importFrom(plyr,ddply) 79 | importFrom(plyr,desc) 80 | importFrom(plyr,dlply) 81 | importFrom(plyr,is.discrete) 82 | importFrom(plyr,is.formula) 83 | importFrom(plyr,join) 84 | importFrom(plyr,ldply) 85 | importFrom(plyr,llply) 86 | importFrom(png,readPNG) 87 | importFrom(rjson,fromJSON) 88 | importFrom(scales,expand_range) 89 | importFrom(stats,asOneSidedFormula) 90 | importFrom(stats,time) 91 | importFrom(utils,URLencode) 92 | importFrom(utils,download.file) 93 | importFrom(utils,tail) 94 | -------------------------------------------------------------------------------- /R/calc_zoom.r: -------------------------------------------------------------------------------- 1 | #' Calculate a zoom given a bounding box 2 | #' 3 | #' calc_zoom can calculate a zoom based on either (1) a data frame 4 | #' with longitude and latitude variables, (2) a longitude range and 5 | #' latitude range, or (3) a bounding box (bbox specification). The 6 | #' specification for (1) is identical to that of most R functions, 7 | #' for (2) simply put in a longitude range into lon and a latitude 8 | #' range into lat, and for (3) put the bounding box in for the lon 9 | #' argument. 10 | #' 11 | #' @param lon longitude, see details 12 | #' @param lat latitude, see details 13 | #' @param data (optional) a data frame containing lon and lat as 14 | #' variables 15 | #' @param adjust number to add to the calculated zoom 16 | #' @param f argument to pass to make_bbox 17 | #' @export 18 | #' @seealso \code{\link{make_bbox}}, \code{\link{bb2bbox}} 19 | #' @examples 20 | #' # From data 21 | #' calc_zoom(lon, lat, wind) 22 | #' 23 | #' # From range 24 | #' lon_range <- extendrange( wind$lon ) 25 | #' lat_range <- extendrange( wind$lat ) 26 | #' calc_zoom(lon_range, lat_range) 27 | #' 28 | #' # From bounding box 29 | #' box <- make_bbox(lon, lat, data = crime) 30 | #' calc_zoom(box) 31 | calc_zoom <- function(lon, lat, data, adjust = 0, f = .05){ 32 | 33 | if(!missing(adjust)) stopifnot(is.integer(adjust)) 34 | 35 | # compute lon_range and lat_range for all specifications 36 | if(missing(data)){ # either ranges or a box 37 | 38 | if(missing(lat)){ # a box 39 | bbox <- lon 40 | errorString <- 41 | "if specifying a bounding box, the format should match that of make_bbox." 42 | if(length(bbox) != 4) stop(errorString, call. = FALSE) 43 | if(!all(names(bbox) == c("left", "bottom", "right", "top"))) 44 | stop(errorString, call. = FALSE) 45 | lon_range <- bbox[c("left", "right")] 46 | lat_range <- bbox[c("bottom", "top")] 47 | 48 | } else { # ranges 49 | if(length(lon) != 2 || length(lat) != 2 || !is.numeric(lon) || !is.numeric(lat)) 50 | stop("if specifying ranges, they both must be of length 2 and numeric.") 51 | 52 | lon_range <- sort(lon) 53 | lat_range <- sort(lat) 54 | } 55 | 56 | } else { # data argument is specified 57 | lon <- data[,deparse(substitute(lon))] 58 | lat <- data[,deparse(substitute(lat))] 59 | bbox <- make_bbox(lon, lat, f = f) 60 | lon_range <- bbox[c("left", "right")] 61 | lat_range <- bbox[c("bottom", "top")] 62 | } 63 | 64 | 65 | 66 | lonlength <- diff(lon_range) 67 | latlength <- diff(lat_range) 68 | zoomlon <- ceiling(log2(360 * 2/lonlength)) 69 | zoomlat <- ceiling(log2(180 * 2/latlength)) 70 | zoom <- max(zoomlon, zoomlat) 71 | 72 | zoom + adjust 73 | } 74 | -------------------------------------------------------------------------------- /man/mapdist.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mapdist.R 3 | \name{mapdist} 4 | \alias{mapdist} 5 | \title{Compute map distances using Google} 6 | \usage{ 7 | mapdist(from, to, mode = c("driving", "walking", "bicycling", "transit"), 8 | output = c("simple", "all"), messaging = FALSE, language = "en-EN", 9 | urlonly = FALSE, override_limit = FALSE, ext = "com", inject = "", 10 | ...) 11 | } 12 | \arguments{ 13 | \item{from}{name of origin addresses in a data frame (vector 14 | accepted)} 15 | 16 | \item{to}{name of destination addresses in a data frame (vector 17 | accepted)} 18 | 19 | \item{mode}{driving, bicycling, or walking} 20 | 21 | \item{output}{amount of output} 22 | 23 | \item{messaging}{turn messaging on/off} 24 | 25 | \item{language}{language} 26 | 27 | \item{urlonly}{return only the url?} 28 | 29 | \item{override_limit}{override the current query count 30 | (.GoogleDistQueryCount)} 31 | 32 | \item{ext}{domain extension (e.g. "com", "co.nz")} 33 | 34 | \item{inject}{character string to add to the url} 35 | 36 | \item{...}{...} 37 | } 38 | \value{ 39 | a data frame (output="simple") or all of the geocoded 40 | information (output="all") 41 | } 42 | \description{ 43 | Compute map distances using Google Maps. Note that in most cases 44 | by using this function you are agreeing to the Google Maps API 45 | Terms of Service at https://developers.google.com/maps/terms. 46 | } 47 | \details{ 48 | if parameters from and to are specified as geographic 49 | coordinates, they are reverse geocoded with revgeocode. note 50 | that the google maps api limits to 2500 element queries a day. 51 | } 52 | \examples{ 53 | 54 | \dontrun{# online queries draw R CMD check times 55 | 56 | mapdist("waco, texas", "houston, texas") 57 | 58 | from <- c("houston, texas", "dallas") 59 | to <- "waco, texas" 60 | mapdist(from, to) 61 | mapdist(from, to, mode = "bicycling") 62 | mapdist(from, to, mode = "walking") 63 | 64 | # google requires a key for mode="transit" 65 | register_google(key = "[your key here]") 66 | from <- "city hall houston texas" 67 | to <- "nrg stadium houston texas" 68 | mapdist(from, to, mode = "transit") 69 | 70 | from <- c("houston", "houston", "dallas") 71 | to <- c("waco, texas", "san antonio", "houston") 72 | mapdist(from, to) 73 | 74 | 75 | # geographic coordinates are accepted as well 76 | (wh <- as.numeric(geocode("the white house, dc"))) 77 | (lm <- as.numeric(geocode("lincoln memorial washington dc"))) 78 | mapdist(wh, lm, mode = "walking") 79 | distQueryCheck() 80 | 81 | } 82 | 83 | } 84 | \seealso{ 85 | \url{http://code.google.com/apis/maps/documentation/distancematrix/} 86 | } 87 | \author{ 88 | David Kahle \email{david.kahle@gmail.com} 89 | } 90 | -------------------------------------------------------------------------------- /man/route.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/route.R 3 | \name{route} 4 | \alias{route} 5 | \title{Grab a route from Google} 6 | \usage{ 7 | route(from, to, mode = c("driving", "walking", "bicycling", "transit"), 8 | structure = c("legs", "route"), output = c("simple", "all"), 9 | alternatives = FALSE, units = "metric", messaging = FALSE, 10 | urlonly = FALSE, override_limit = FALSE, ext = "com", inject = "", 11 | ...) 12 | } 13 | \arguments{ 14 | \item{from}{name of origin addresses in a data frame (vector 15 | accepted)} 16 | 17 | \item{to}{name of destination addresses in a data frame (vector 18 | accepted)} 19 | 20 | \item{mode}{driving, bicycling, walking, or transit} 21 | 22 | \item{structure}{structure of output, see examples} 23 | 24 | \item{output}{amount of output} 25 | 26 | \item{alternatives}{should more than one route be provided?} 27 | 28 | \item{units}{"metric"} 29 | 30 | \item{messaging}{turn messaging on/off} 31 | 32 | \item{urlonly}{return only the url?} 33 | 34 | \item{override_limit}{override the current query count 35 | (.GoogleRouteQueryCount)} 36 | 37 | \item{ext}{domain extension (e.g. "com", "co.nz")} 38 | 39 | \item{inject}{character string to add to the url} 40 | 41 | \item{...}{...} 42 | } 43 | \value{ 44 | a data frame (output="simple") or all of the geocoded 45 | information (output="all") 46 | } 47 | \description{ 48 | Grab a route from Google. Note that in most cases by using this 49 | function you are agreeing to the Google Maps API Terms of Service 50 | at https://developers.google.com/maps/terms. 51 | } 52 | \examples{ 53 | 54 | \dontrun{ # to cut down on check time 55 | 56 | from <- "houston, texas" 57 | to <- "waco, texas" 58 | route_df <- route(from, to, structure = "route") 59 | trek_df <- trek(from, to, structure = "route") 60 | qmap("college station, texas", zoom = 8) + 61 | geom_path( 62 | aes(x = lon, y = lat), colour = "red", 63 | size = 1.5, alpha = .5, 64 | data = route_df, lineend = "round" 65 | ) + 66 | geom_path( 67 | aes(x = lon, y = lat), colour = "blue", 68 | size = 1.5, alpha = .5, 69 | data = trek_df, lineend = "round" 70 | ) 71 | 72 | qmap("college station, texas", zoom = 6) + 73 | geom_path( 74 | aes(x = lon, y = lat), colour = "red", size = 1.5, 75 | data = route_df, lineend = "round" 76 | ) 77 | 78 | routeQueryCheck() 79 | 80 | 81 | 82 | } 83 | 84 | } 85 | \seealso{ 86 | \url{https://developers.google.com/maps/documentation/directions/}, 87 | \code{\link{trek}}, \code{\link{legs2route}}, 88 | \code{\link{routeQueryCheck}}, \code{\link{geom_leg}}, 89 | \code{\link{register_google}} 90 | } 91 | \author{ 92 | David Kahle \email{david.kahle@gmail.com} 93 | } 94 | -------------------------------------------------------------------------------- /man/OSM_scale_lookup.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/OSM_scale_lookup.R 3 | \name{OSM_scale_lookup} 4 | \alias{OSM_scale_lookup} 5 | \title{Look up OpenStreetMap scale for a given zoom level.} 6 | \usage{ 7 | OSM_scale_lookup(zoom = 10) 8 | } 9 | \arguments{ 10 | \item{zoom}{google zoom} 11 | } 12 | \value{ 13 | scale 14 | } 15 | \description{ 16 | Look up OpenStreetMap scale for a given zoom level. 17 | } 18 | \details{ 19 | The calculation of an appropriate OSM scale value for a 20 | given zoom level is a complicated task. For details, see 21 | \url{http://wiki.openstreetmap.org/wiki/FAQ} or 22 | \url{http://almien.co.uk/OSM/Tools/Scale/}. 23 | } 24 | \examples{ 25 | 26 | OSM_scale_lookup(zoom = 3) 27 | OSM_scale_lookup(zoom = 10) 28 | 29 | \dontrun{ 30 | # these can take a long time or are prone to crashing 31 | # if the osm server load is too high 32 | 33 | # these maps are were the ones used to tailor fit the scale 34 | # the zooms were fixed 35 | ggmap(get_map(zoom = 3, source = 'osm', scale = 47500000), extent = "device") 36 | ggmap(get_map(zoom = 4, source = 'osm', scale = 32500000), extent = "device") 37 | ggmap(get_map(zoom = 5, source = 'osm', scale = 15000000), extent = "device") 38 | ggmap(get_map(zoom = 6, source = 'osm', scale = 10000000), extent = "device") 39 | ggmap(get_map(zoom = 7, source = 'osm', scale = 5000000), extent = "device") 40 | ggmap(get_map(zoom = 8, source = 'osm', scale = 2800000), extent = "device") 41 | ggmap(get_map(zoom = 9, source = 'osm', scale = 1200000), extent = "device") 42 | ggmap(get_map(zoom = 10, source = 'osm', scale = 575000), extent = "device") 43 | ggmap(get_map(zoom = 11, source = 'osm', scale = 220000), extent = "device") 44 | ggmap(get_map(zoom = 12, source = 'osm', scale = 110000), extent = "device") 45 | ggmap(get_map(zoom = 13, source = 'osm', scale = 70000), extent = "device") 46 | ggmap(get_map(zoom = 14, source = 'osm', scale = 31000), extent = "device") 47 | ggmap(get_map(zoom = 15, source = 'osm', scale = 15000), extent = "device") 48 | ggmap(get_map(zoom = 16, source = 'osm', scale = 7500), extent = "device") 49 | ggmap(get_map(zoom = 17, source = 'osm', scale = 4000), extent = "device") 50 | ggmap(get_map(zoom = 18, source = 'osm', scale = 2500), extent = "device") 51 | ggmap(get_map(zoom = 19, source = 'osm', scale = 1750), extent = "device") 52 | ggmap(get_map(zoom = 20, source = 'osm', scale = 1000), extent = "device") 53 | 54 | # the USA 55 | lonR <- c(1.01,.99)*c(-124.73,-66.95) 56 | latR <- c(.99,1.01)*c(24.52, 49.38) 57 | qmap(lonR = lonR, latR = latR, source = 'osm', scale = 325E5) 58 | 59 | } 60 | 61 | 62 | } 63 | \author{ 64 | David Kahle \email{david.kahle@gmail.com} 65 | } 66 | -------------------------------------------------------------------------------- /R/get_navermap.R: -------------------------------------------------------------------------------- 1 | #' Get a Naver Map 2 | #' 3 | #' This is (at least) temporarily unavailable as the Naver API changed. 4 | #' 5 | #' \code{get_navermap} accesses the Naver Static Maps API version 1.1 to 6 | #' download a static map. Note that in most cases by using this function you are 7 | #' agreeing to the Naver Maps API Terms of Service at 8 | #' \url{http://dev.naver.com/openapi/apis/map/staticmap}. 9 | #' 10 | #' @param center the center of the map. this can be longitude/latitude numeric 11 | #' vector. 12 | #' @param zoom map zoom, an integer from 1 to 14 (building), default value 10 13 | #' @param size rectangular dimensions of map in pixels - horizontal x vertical - 14 | #' with a max of c(640, 640). 15 | #' @param format character string providing image format - png, jpeg(jpg) 16 | #' formats available in various flavors 17 | #' @param crs Coordinate system, this currently supports EPSG:4326 18 | #' @param baselayer base layer, this can be either "default", "satellite". 19 | #' @param color color or black-and-white 20 | #' @param overlayers overlay layers, this can be "anno_satellite","bicycle", 21 | #' "roadview", "traffic". 22 | #' @param markers data.frame with first column longitude, second column 23 | #' latitude, for which naver markers should be embedded in the map image, or 24 | #' character string to be passed directly to api 25 | #' @param key key code from naver api center 26 | #' @param uri registered host url 27 | #' @param filename destination file for download (file extension added according 28 | #' to format). Default \code{NULL} means a random \code{\link{tempfile}}. 29 | #' @param messaging turn messaging on/off 30 | #' @param urlonly return url only 31 | #' @param force if the map is on file, should a new map be looked up? 32 | #' @param where where should the file drawer be located (without terminating 33 | #' "/") 34 | #' @param archiving use archived maps. note: by changing to TRUE you agree to 35 | #' abide by any of the rules governing caching naver maps 36 | #' @param ... ... 37 | #' @author Heewon Jeon \email{madjakarta@@gmail.com} 38 | #' @seealso \url{http://dev.naver.com/openapi/apis/map/staticmap/}, 39 | #' \code{\link{ggmap}} 40 | #' @export 41 | get_navermap <- function( 42 | center = c(lon = 126.9849208, lat = 37.5664519), zoom = 4, 43 | size = c(640,640), format = c("png", "jpeg", "jpg"), 44 | crs = c("EPSG:4326", "NHN:2048", "NHN:128", "EPSG:4258", "EPSG:4162", "EPSG:2096", "EPSG:2097", "EPSG:2098", "EPSG:900913"), 45 | baselayer = c("default", "satellite"), color = c("color","bw"), 46 | overlayers = c("anno_satellite", "bicycle", "roadview", "traffic"), 47 | markers, key, uri, filename = NULL, messaging = FALSE, urlonly = FALSE, 48 | force = FALSE, where = tempdir(), archiving = TRUE, ... 49 | ){ 50 | 51 | stop("Naver is temporarily not supported, as it's API has changed.", call. = FALSE) 52 | 53 | } 54 | 55 | 56 | -------------------------------------------------------------------------------- /R/OSM_scale_lookup.R: -------------------------------------------------------------------------------- 1 | #' Look up OpenStreetMap scale for a given zoom level. 2 | #' 3 | #' Look up OpenStreetMap scale for a given zoom level. 4 | #' 5 | #' @param zoom google zoom 6 | #' @return scale 7 | #' @details The calculation of an appropriate OSM scale value for a 8 | #' given zoom level is a complicated task. For details, see 9 | #' \url{http://wiki.openstreetmap.org/wiki/FAQ} or 10 | #' \url{http://almien.co.uk/OSM/Tools/Scale/}. 11 | #' @author David Kahle \email{david.kahle@@gmail.com} 12 | #' @export 13 | #' @examples 14 | #' 15 | #' OSM_scale_lookup(zoom = 3) 16 | #' OSM_scale_lookup(zoom = 10) 17 | #' 18 | #' \dontrun{ 19 | #' # these can take a long time or are prone to crashing 20 | #' # if the osm server load is too high 21 | #' 22 | #' # these maps are were the ones used to tailor fit the scale 23 | #' # the zooms were fixed 24 | #' ggmap(get_map(zoom = 3, source = 'osm', scale = 47500000), extent = "device") 25 | #' ggmap(get_map(zoom = 4, source = 'osm', scale = 32500000), extent = "device") 26 | #' ggmap(get_map(zoom = 5, source = 'osm', scale = 15000000), extent = "device") 27 | #' ggmap(get_map(zoom = 6, source = 'osm', scale = 10000000), extent = "device") 28 | #' ggmap(get_map(zoom = 7, source = 'osm', scale = 5000000), extent = "device") 29 | #' ggmap(get_map(zoom = 8, source = 'osm', scale = 2800000), extent = "device") 30 | #' ggmap(get_map(zoom = 9, source = 'osm', scale = 1200000), extent = "device") 31 | #' ggmap(get_map(zoom = 10, source = 'osm', scale = 575000), extent = "device") 32 | #' ggmap(get_map(zoom = 11, source = 'osm', scale = 220000), extent = "device") 33 | #' ggmap(get_map(zoom = 12, source = 'osm', scale = 110000), extent = "device") 34 | #' ggmap(get_map(zoom = 13, source = 'osm', scale = 70000), extent = "device") 35 | #' ggmap(get_map(zoom = 14, source = 'osm', scale = 31000), extent = "device") 36 | #' ggmap(get_map(zoom = 15, source = 'osm', scale = 15000), extent = "device") 37 | #' ggmap(get_map(zoom = 16, source = 'osm', scale = 7500), extent = "device") 38 | #' ggmap(get_map(zoom = 17, source = 'osm', scale = 4000), extent = "device") 39 | #' ggmap(get_map(zoom = 18, source = 'osm', scale = 2500), extent = "device") 40 | #' ggmap(get_map(zoom = 19, source = 'osm', scale = 1750), extent = "device") 41 | #' ggmap(get_map(zoom = 20, source = 'osm', scale = 1000), extent = "device") 42 | #' 43 | #' # the USA 44 | #' lonR <- c(1.01,.99)*c(-124.73,-66.95) 45 | #' latR <- c(.99,1.01)*c(24.52, 49.38) 46 | #' qmap(lonR = lonR, latR = latR, source = 'osm', scale = 325E5) 47 | #' 48 | #' } 49 | #' 50 | #' 51 | OSM_scale_lookup <- function (zoom = 10){ 52 | df <- data.frame( 53 | z = 2:20, 54 | s = c(175000000, 47500000, 32500000, 15000000, 10000000, 5000000, 55 | 2800000, 1200000, 575000, 220000, 110000, 70000, 31000, 15000, 56 | 7500, 4000, 2500, 1750, 1000) 57 | ) 58 | with(df, s[z == zoom]) 59 | } 60 | 61 | -------------------------------------------------------------------------------- /R/inset_raster.R: -------------------------------------------------------------------------------- 1 | #' Create a (ggplot2) raster layer 2 | #' 3 | #' This is a special version of ggplot2::annotation_raster for use 4 | #' with ggmap. (It simply removes the requirement for cartesian 5 | #' coordinates.) The only difference between \code{inset_raster} 6 | #' and \code{inset_ggmap} is their arguments. \code{inset_ggmap} is 7 | #' simply a wrapper of \code{inset_raster} with \code{xmin}, ..., 8 | #' \code{ymax} arguments equal to the map's bounding box. 9 | #' 10 | #' @param raster raster object to display 11 | #' @param xmin,xmax x location (in data coordinates) giving 12 | #' horizontal location of raster 13 | #' @param ymin,ymax y location (in data coordinates) giving vertical 14 | #' location of raster 15 | #' @param interpolate interpolate the raster? (i.e. antialiasing) 16 | #' @param ggmap a ggmap object, see \code{\link{get_map}} 17 | #' @export 18 | #' @name inset_raster 19 | #' @examples 20 | #' 21 | #' # see ?bb2bbox 22 | #' 23 | #' 24 | #' 25 | inset_raster <- annotation_raster <- function(raster, xmin, xmax, ymin, ymax, interpolate = TRUE) { 26 | raster <- grDevices::as.raster(raster) 27 | 28 | # add possibility that xmin is c(xmin, xmax, ymin, ymax) 29 | if(length(xmin) == 4 && missing(xmax)){ 30 | xmax <- xmin[2] 31 | ymin <- xmin[3] 32 | ymax <- xmin[4] 33 | xmin <- xmin[1] 34 | } 35 | 36 | layer( 37 | data = NULL, 38 | mapping = NULL, 39 | stat = ggplot2::StatIdentity, 40 | position = ggplot2::PositionIdentity, 41 | geom = GeomRasterAnn, 42 | inherit.aes = TRUE, 43 | params = list( 44 | raster = raster, 45 | xmin = xmin, 46 | xmax = xmax, 47 | ymin = ymin, 48 | ymax = ymax, 49 | interpolate = interpolate 50 | ) 51 | ) 52 | 53 | } 54 | 55 | 56 | #' @rdname inset_raster 57 | #' @export 58 | inset_ggmap <- function(ggmap){ 59 | stopifnot(inherits(ggmap, "ggmap")) 60 | bb <- attr(ggmap, "bb") 61 | bbox <- bb2bbox(bb) 62 | 63 | inset_raster(ggmap, bbox[c("left", "right", "bottom", "top")]) 64 | } 65 | 66 | 67 | 68 | GeomRasterAnn <- ggproto("GeomRasterAnn", Geom, 69 | extra_params = "", 70 | handle_na = function(data, params) { 71 | data 72 | }, 73 | 74 | draw_panel = function(data, panel_scales, coord, raster, xmin, xmax, 75 | ymin, ymax, interpolate = FALSE) { 76 | # if (!inherits(coord, "CoordCartesian")) { 77 | # stop("annotation_raster only works with Cartesian coordinates", 78 | # call. = FALSE) 79 | # } 80 | corners <- data.frame(x = c(xmin, xmax), y = c(ymin, ymax)) 81 | data <- coord$transform(corners, panel_scales) 82 | 83 | x_rng <- range(data$x, na.rm = TRUE) 84 | y_rng <- range(data$y, na.rm = TRUE) 85 | 86 | rasterGrob(raster, x_rng[1], y_rng[1], 87 | diff(x_rng), diff(y_rng), default.units = "native", 88 | just = c("left","bottom"), interpolate = interpolate) 89 | } 90 | ) 91 | -------------------------------------------------------------------------------- /R/geom_leg.R: -------------------------------------------------------------------------------- 1 | #' Single line segments with rounded ends 2 | #' 3 | #' This is ggplot2's segment with rounded ends. It's mainly 4 | #' included in ggmap for historical reasons. 5 | #' 6 | #' @inheritParams ggplot2::geom_segment 7 | #' @seealso geom_segment in ggplot2, inspired by 8 | #' \url{http://spatialanalysis.co.uk/2012/02/great-maps-ggplot2/}, 9 | #' \code{\link{route}} 10 | #' @details only intended for use in ggmap package. only designed 11 | #' for mercator projection. 12 | #' @export 13 | #' @examples 14 | #' 15 | #' \dontrun{ # removed for R CMD check speed 16 | #' 17 | #' map <- get_map( 18 | #' location = c(-77.0425, 38.8925), # painfully picked by hand 19 | #' source = "google", zoom = 14, maptype = "satellite" 20 | #' ) 21 | #' ggmap(map) 22 | #' 23 | #' 24 | #' (legs_df <- route( 25 | #' "the white house, dc", 26 | #' "lincoln memorial washington dc", 27 | #' alternatives = TRUE 28 | #' )) 29 | #' 30 | #' ggplot(data = legs_df) + 31 | #' geom_leg(aes( 32 | #' x = startLon, xend = endLon, 33 | #' y = startLat, yend = endLat 34 | #' )) + 35 | #' coord_map() 36 | #' 37 | #' ggplot(data = legs_df) + 38 | #' geom_leg(aes( 39 | #' x = startLon, xend = endLon, 40 | #' y = startLat, yend = endLat, 41 | #' color = route 42 | #' )) + 43 | #' coord_map() 44 | #' 45 | #' 46 | #' ggmap(map) + 47 | #' geom_leg( 48 | #' aes( 49 | #' x = startLon, xend = endLon, 50 | #' y = startLat, yend = endLat 51 | #' ), 52 | #' data = legs_df, color = "red" 53 | #' ) 54 | #' 55 | #' # adding a color aesthetic errors because of a base-layer problem 56 | #' # ggmap(map) + 57 | #' # geom_leg( 58 | #' # aes( 59 | #' # x = startLon, xend = endLon, 60 | #' # y = startLat, yend = endLat, 61 | #' # color = route 62 | #' # ) 63 | #' # ) 64 | #' 65 | #' 66 | #' # this is probably the easiest hack to fix it 67 | #' ggplot(data = legs_df) + 68 | #' inset_ggmap(map) + 69 | #' geom_leg( 70 | #' aes( 71 | #' x = startLon, xend = endLon, 72 | #' y = startLat, yend = endLat, 73 | #' color = route 74 | #' ), 75 | #' data = legs_df 76 | #' ) + 77 | #' coord_map() 78 | #' 79 | #' } 80 | #' 81 | geom_leg <- function(mapping = NULL, data = NULL, stat = "identity", 82 | position = "identity", arrow = NULL, lineend = "round", 83 | na.rm = FALSE, show.legend = NA, inherit.aes = TRUE, 84 | ...) { 85 | layer( 86 | data = data, 87 | mapping = mapping, 88 | stat = stat, 89 | geom = ggplot2::GeomSegment, 90 | position = position, 91 | show.legend = show.legend, 92 | inherit.aes = inherit.aes, 93 | params = list( 94 | arrow = arrow, 95 | lineend = lineend, 96 | na.rm = na.rm, 97 | ... 98 | ) 99 | ) 100 | } 101 | -------------------------------------------------------------------------------- /man/get_navermap.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_navermap.R 3 | \name{get_navermap} 4 | \alias{get_navermap} 5 | \title{Get a Naver Map} 6 | \usage{ 7 | get_navermap(center = c(lon = 126.9849208, lat = 37.5664519), zoom = 4, 8 | size = c(640, 640), format = c("png", "jpeg", "jpg"), 9 | crs = c("EPSG:4326", "NHN:2048", "NHN:128", "EPSG:4258", "EPSG:4162", 10 | "EPSG:2096", "EPSG:2097", "EPSG:2098", "EPSG:900913"), 11 | baselayer = c("default", "satellite"), color = c("color", "bw"), 12 | overlayers = c("anno_satellite", "bicycle", "roadview", "traffic"), markers, 13 | key, uri, filename = NULL, messaging = FALSE, urlonly = FALSE, 14 | force = FALSE, where = tempdir(), archiving = TRUE, ...) 15 | } 16 | \arguments{ 17 | \item{center}{the center of the map. this can be longitude/latitude numeric 18 | vector.} 19 | 20 | \item{zoom}{map zoom, an integer from 1 to 14 (building), default value 10} 21 | 22 | \item{size}{rectangular dimensions of map in pixels - horizontal x vertical - 23 | with a max of c(640, 640).} 24 | 25 | \item{format}{character string providing image format - png, jpeg(jpg) 26 | formats available in various flavors} 27 | 28 | \item{crs}{Coordinate system, this currently supports EPSG:4326} 29 | 30 | \item{baselayer}{base layer, this can be either "default", "satellite".} 31 | 32 | \item{color}{color or black-and-white} 33 | 34 | \item{overlayers}{overlay layers, this can be "anno_satellite","bicycle", 35 | "roadview", "traffic".} 36 | 37 | \item{markers}{data.frame with first column longitude, second column 38 | latitude, for which naver markers should be embedded in the map image, or 39 | character string to be passed directly to api} 40 | 41 | \item{key}{key code from naver api center} 42 | 43 | \item{uri}{registered host url} 44 | 45 | \item{filename}{destination file for download (file extension added according 46 | to format). Default \code{NULL} means a random \code{\link{tempfile}}.} 47 | 48 | \item{messaging}{turn messaging on/off} 49 | 50 | \item{urlonly}{return url only} 51 | 52 | \item{force}{if the map is on file, should a new map be looked up?} 53 | 54 | \item{where}{where should the file drawer be located (without terminating 55 | "/")} 56 | 57 | \item{archiving}{use archived maps. note: by changing to TRUE you agree to 58 | abide by any of the rules governing caching naver maps} 59 | 60 | \item{...}{...} 61 | } 62 | \description{ 63 | This is (at least) temporarily unavailable as the Naver API changed. 64 | } 65 | \details{ 66 | \code{get_navermap} accesses the Naver Static Maps API version 1.1 to 67 | download a static map. Note that in most cases by using this function you are 68 | agreeing to the Naver Maps API Terms of Service at 69 | \url{http://dev.naver.com/openapi/apis/map/staticmap}. 70 | } 71 | \seealso{ 72 | \url{http://dev.naver.com/openapi/apis/map/staticmap/}, 73 | \code{\link{ggmap}} 74 | } 75 | \author{ 76 | Heewon Jeon \email{madjakarta@gmail.com} 77 | } 78 | -------------------------------------------------------------------------------- /man/get_openstreetmap.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_openstreetmap.R 3 | \name{get_openstreetmap} 4 | \alias{get_openstreetmap} 5 | \title{Get an OpenStreetMap} 6 | \usage{ 7 | get_openstreetmap(bbox = c(left = -95.80204, bottom = 29.38048, right = 8 | -94.92313, top = 30.14344), scale = 606250, format = c("png", "jpeg", 9 | "svg", "pdf", "ps"), messaging = FALSE, urlonly = FALSE, 10 | filename = NULL, color = c("color", "bw"), ...) 11 | } 12 | \arguments{ 13 | \item{bbox}{a bounding box in the format c(lowerleftlon, lowerleftlat, 14 | upperrightlon, upperrightlat)} 15 | 16 | \item{scale}{scale parameter, see 17 | \url{http://wiki.openstreetmap.org/wiki/MinScaleDenominator}. smaller 18 | scales provide a finer degree of detail, where larger scales produce more 19 | coarse detail. 20 | 21 | The scale argument is a tricky number to correctly specify. In most cases, 22 | if you get an error when downloading an openstreetmap the error is 23 | attributable to an improper scale specification. 24 | \code{\link{OSM_scale_lookup}} can help; but the best way to get in the 25 | correct range is to go to \url{http://www.openstreetmap.org/}, navigate to 26 | the map of interest, click export at the top of the page, click 'map image' 27 | and then copy down the scale listed.} 28 | 29 | \item{format}{character string providing image format - png, jpeg, svg, pdf, 30 | and ps formats} 31 | 32 | \item{messaging}{turn messaging on/off} 33 | 34 | \item{urlonly}{return url only} 35 | 36 | \item{filename}{destination file for download (file extension added according 37 | to format). Default \code{NULL} means a random \code{\link{tempfile}}.} 38 | 39 | \item{color}{color or black-and-white} 40 | 41 | \item{...}{...} 42 | } 43 | \value{ 44 | a ggmap object (a classed raster object with a bounding box attribute) 45 | } 46 | \description{ 47 | \code{get_openstreetmap} accesses a tile server for OpenStreetMap and 48 | downloads/formats a map image. This is simply a wrapper for the web-based 49 | version at \url{http://www.openstreetmap.org/}. If you don't know how to 50 | get the map you want, go there, navigate to the map extent that you want, 51 | click the export tab at the top of the page, and copy the information into 52 | this function. 53 | } 54 | \details{ 55 | receive an error message from \code{download.file} with the message HTTP status 56 | '503 Service Unavailable'. You can confirm this by setting urlonly = TRUE, 57 | and then entering the URL in a web browser. the solution is either (1) 58 | change sources or (2) wait for the OSM servers to come back up. 59 | 60 | See \url{http://www.openstreetmap.org/copyright} for license and copyright 61 | information. 62 | } 63 | \examples{ 64 | 65 | get_openstreetmap(urlonly = TRUE) 66 | \dontrun{ 67 | # osm servers get overloaded, which can result in 68 | # erroneous failed checks 69 | 70 | osm <- get_openstreetmap() 71 | ggmap(osm) 72 | 73 | } 74 | 75 | } 76 | \seealso{ 77 | \url{http://www.openstreetmap.org/}, \code{\link{ggmap}} 78 | } 79 | \author{ 80 | David Kahle \email{david.kahle@gmail.com} 81 | } 82 | -------------------------------------------------------------------------------- /revdep/summary.md: -------------------------------------------------------------------------------- 1 | # Setup 2 | 3 | ## Platform 4 | 5 | |setting |value | 6 | |:--------|:----------------------------| 7 | |version |R version 3.2.2 (2015-08-14) | 8 | |system |x86_64, darwin13.4.0 | 9 | |ui |RStudio (0.99.441) | 10 | |language |(EN) | 11 | |collate |en_US.UTF-8 | 12 | |tz |America/Chicago | 13 | 14 | ## Packages 15 | 16 | |package |* |version |date |source | 17 | |:-----------|:--|:-------|:----------|:--------------| 18 | |geosphere | |1.4-3 |2015-07-02 |CRAN (R 3.2.0) | 19 | |jpeg | |0.1-8 |2014-01-23 |CRAN (R 3.2.0) | 20 | |mapproj | |1.2-4 |2015-08-03 |CRAN (R 3.2.0) | 21 | |png | |0.1-7 |2013-12-03 |CRAN (R 3.2.0) | 22 | |RgoogleMaps | |1.2.0.7 |2015-01-21 |CRAN (R 3.2.0) | 23 | 24 | # Check results 25 | 9 checked out of 9 dependencies 26 | 27 | ## clifro (2.4-0) 28 | Maintainer: Blake Seers 29 | Bug reports: https://github.com/ropensci/clifro/issues 30 | 31 | ``` 32 | checking R code for possible problems ... NOTE 33 | speed_plot,cfWind-missing : .local: no visible binding for global 34 | variable ‘speed’ 35 | speed_plot,cfWind-missing : .local: no visible binding for global 36 | variable ‘spd.sd’ 37 | ``` 38 | ``` 39 | DONE 40 | Status: 1 NOTE 41 | ``` 42 | 43 | ## move (1.5.514) 44 | Maintainer: Bart Kranstauber 45 | 46 | __OK__ 47 | 48 | ## OutbreakTools (0.1-13) 49 | Maintainer: Thibaut Jombart 50 | 51 | __OK__ 52 | 53 | ## RAM (1.2.1) 54 | Maintainer: Wen Chen 55 | 56 | __OK__ 57 | 58 | ## sidier (3.0.1) 59 | Maintainer: A.J. Muñoz-Pajares 60 | 61 | __OK__ 62 | 63 | ## spoccutils (0.1.0) 64 | Maintainer: Scott Chamberlain 65 | Bug reports: https://github.com/ropensci/spoccutils/issues 66 | 67 | ``` 68 | checking tests ... ERROR 69 | Running the tests in ‘tests/testthat.R’ failed. 70 | Last 13 lines of output: 71 | 8: gist_POST(paste0(ghbase(), "/gists"), gist_auth(), ghead(), body, ...) 72 | 9: POST(url, auth, headers, body = body, encode = "json", ...) 73 | 10: request_build("POST", hu$url, body_config(body, encode), config, ...) 74 | 11: gist_auth() 75 | 12: stop("In non-interactive environments, please set GITHUB_PAT env to a GitHub", " access token (https://help.github.com/articles/creating-an-access-token-for-command-line-use)", 76 | call. = FALSE) 77 | 78 | testthat results ================================================================ 79 | OK: 6 SKIPPED: 0 FAILED: 1 80 | 1. Error: map_gist works as expected 81 | 82 | Error: testthat unit tests failed 83 | Execution halted 84 | ``` 85 | ``` 86 | DONE 87 | Status: 1 ERROR 88 | ``` 89 | 90 | ## SWMPr (2.1.0) 91 | Maintainer: Marcus W. Beck 92 | Bug reports: https://github.com/fawda123/SWMPr/issues 93 | 94 | __OK__ 95 | 96 | ## vmsbase (2.0) 97 | Maintainer: Lorenzo D'Andrea 98 | 99 | __OK__ 100 | 101 | ## weatherr (0.1) 102 | Maintainer: Stan Yip 103 | 104 | __OK__ 105 | 106 | -------------------------------------------------------------------------------- /man/get_map.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_map.R 3 | \name{get_map} 4 | \alias{get_map} 5 | \title{Grab a map.} 6 | \usage{ 7 | get_map(location = c(lon = -95.3632715, lat = 29.7632836), zoom = "auto", 8 | scale = "auto", maptype = c("terrain", "terrain-background", "satellite", 9 | "roadmap", "hybrid", "toner", "watercolor", "terrain-labels", "terrain-lines", 10 | "toner-2010", "toner-2011", "toner-background", "toner-hybrid", 11 | "toner-labels", "toner-lines", "toner-lite"), source = c("google", "osm", 12 | "stamen", "cloudmade"), force = ifelse(source == "google", TRUE, TRUE), 13 | messaging = FALSE, urlonly = FALSE, filename = NULL, crop = TRUE, 14 | color = c("color", "bw"), language = "en-EN", api_key) 15 | } 16 | \arguments{ 17 | \item{location}{an address, longitude/latitude pair (in that 18 | order), or left/bottom/right/top bounding box} 19 | 20 | \item{zoom}{map zoom, an integer from 3 (continent) to 21 21 | (building), default value 10 (city). openstreetmaps limits a 22 | zoom of 18, and the limit on stamen maps depends on the 23 | maptype. "auto" automatically determines the zoom for bounding 24 | box specifications, and is defaulted to 10 with center/zoom 25 | specifications. maps of the whole world currently not 26 | supported.} 27 | 28 | \item{scale}{scale argument of \code{\link{get_googlemap}} or 29 | \code{\link{get_openstreetmap}}} 30 | 31 | \item{maptype}{character string providing map theme. options 32 | available are "terrain", "terrain-background", "satellite", 33 | "roadmap", and "hybrid" (google maps), "terrain", "watercolor", 34 | and "toner" (stamen maps), or a positive integer for cloudmade 35 | maps (see ?get_cloudmademap)} 36 | 37 | \item{source}{Google Maps ("google"), OpenStreetMap ("osm"), 38 | Stamen Maps ("stamen"), or CloudMade maps ("cloudmade")} 39 | 40 | \item{force}{force new map (don't use archived version)} 41 | 42 | \item{messaging}{turn messaging on/off} 43 | 44 | \item{urlonly}{return url only} 45 | 46 | \item{filename}{destination file for download (file extension 47 | added according to format). Default \code{NULL} means a random 48 | \code{\link{tempfile}}.} 49 | 50 | \item{crop}{(stamen and cloudmade maps) crop tiles to bounding 51 | box} 52 | 53 | \item{color}{color ("color") or black-and-white ("bw")} 54 | 55 | \item{language}{language for google maps} 56 | 57 | \item{api_key}{an api key for cloudmade maps} 58 | } 59 | \value{ 60 | a ggmap object (a classed raster object with a bounding 61 | box attribute) 62 | } 63 | \description{ 64 | \code{get_map} is a smart wrapper that queries the Google Maps, 65 | OpenStreetMap, Stamen Maps or Naver Map servers for a map. 66 | } 67 | \examples{ 68 | 69 | \dontrun{ 70 | # not run by check to reduce time; also, 71 | # osm may error due to server overload 72 | 73 | map <- get_map() 74 | map 75 | str(map) 76 | ggmap(map) 77 | 78 | (map <- get_map(maptype = "roadmap")) 79 | (map <- get_map(source = "osm")) 80 | (map <- get_map(source = "stamen", maptype = "watercolor")) 81 | 82 | map <- get_map(location = "texas", zoom = 6, source = "stamen") 83 | ggmap(map, fullpage = TRUE) 84 | 85 | } 86 | } 87 | \seealso{ 88 | \code{\link{ggmap}}, \code{\link{GetMap}} in package 89 | RgoogleMaps 90 | } 91 | \author{ 92 | David Kahle \email{david.kahle@gmail.com} 93 | } 94 | -------------------------------------------------------------------------------- /man/trek.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/trek.R 3 | \name{trek} 4 | \alias{trek} 5 | \title{Grab a trek from Google} 6 | \usage{ 7 | trek(from, to, mode = c("driving", "walking", "bicycling", "transit"), 8 | output = c("simple", "all"), alternatives = FALSE, units = "metric", 9 | messaging = FALSE, urlonly = FALSE, override_limit = FALSE, 10 | ext = "com", inject = "", ...) 11 | } 12 | \arguments{ 13 | \item{from}{name of origin addresses in a data frame (vector 14 | accepted)} 15 | 16 | \item{to}{name of destination addresses in a data frame (vector 17 | accepted)} 18 | 19 | \item{mode}{driving, bicycling, walking, or transit} 20 | 21 | \item{output}{amount of output} 22 | 23 | \item{alternatives}{should more than one route be provided?} 24 | 25 | \item{units}{"metric"} 26 | 27 | \item{messaging}{turn messaging on/off} 28 | 29 | \item{urlonly}{return only the url?} 30 | 31 | \item{override_limit}{override the current query count 32 | (.GoogleRouteQueryCount)} 33 | 34 | \item{ext}{domain extension (e.g. "com", "co.nz")} 35 | 36 | \item{inject}{character string to add to the url} 37 | 38 | \item{...}{...} 39 | } 40 | \value{ 41 | a data frame (output="simple") or all of the geocoded 42 | information (output="all") 43 | } 44 | \description{ 45 | Grab a trek from Google that will plot over the roadways. Note 46 | that in most cases by using this function you are agreeing to the 47 | Google Maps API Terms of Service at 48 | https://developers.google.com/maps/terms. 49 | } 50 | \examples{ 51 | 52 | \dontrun{ # to cut down on check time 53 | 54 | from <- "houston, texas" 55 | to <- "waco, texas" 56 | route_df <- route(from, to, structure = "route") 57 | trek_df <- trek(from, to, structure = "route") 58 | qmap("college station, texas", zoom = 8) + 59 | geom_path( 60 | aes(x = lon, y = lat), colour = "red", 61 | size = 1.5, alpha = .5, 62 | data = route_df, lineend = "round" 63 | ) + 64 | geom_path( 65 | aes(x = lon, y = lat), colour = "blue", 66 | size = 1.5, alpha = .5, 67 | data = trek_df, lineend = "round" 68 | ) 69 | 70 | 71 | 72 | from <- "rice university houston texas" 73 | to <- "1001 Bissonnet St, Houston, TX 77005" 74 | trek_df <- trek(from, to) 75 | qmplot(lon, lat, data = trek_df, geom = "path", maptype = "terrain", 76 | color = I("red"), size = I(2), alpha = I(.5) 77 | ) 78 | 79 | trek_df <- trek(from, to, mode = "walking") 80 | qmplot(lon, lat, data = trek_df, geom = "path", maptype = "terrain", 81 | color = I("red"), size = I(2), alpha = I(.5) 82 | ) 83 | 84 | trek_df <- trek(from, to, mode = "transit") 85 | qmplot(lon, lat, data = trek_df, geom = "path", maptype = "terrain", 86 | color = I("red"), size = I(2), alpha = I(.5) 87 | ) 88 | 89 | 90 | from <- "houston, texas"; to <- "waco, texas" 91 | trek_df <- trek(from, to, alternatives = TRUE) 92 | qmplot(lon, lat, data = trek_df, geom = "path", 93 | color = route, size = I(2), alpha = I(.5) 94 | ) 95 | 96 | 97 | from <- "los angeles, california"; to <- "new york, new york" 98 | trek_df <- trek(from, to, alternatives = TRUE) 99 | qmplot(lon, lat, data = trek_df, geom = "path", 100 | color = route, size = I(2), maptype = "terrain", 101 | zoom = 5 102 | ) + facet_wrap(~ route, ncol = 1) 103 | 104 | 105 | 106 | 107 | } 108 | 109 | } 110 | \seealso{ 111 | \url{https://developers.google.com/maps/documentation/directions/}, 112 | \url{http://stackoverflow.com/questions/30270011/ggmap-route-finding-doesnt-stay-on-roads}, 113 | \code{\link{route}}, \code{\link{routeQueryCheck}} 114 | \code{\link{register_google}} 115 | } 116 | \author{ 117 | David Kahle \email{david.kahle@gmail.com} with the key 118 | decoding algorithm due to stackoverflow user akhmed 119 | } 120 | -------------------------------------------------------------------------------- /man/geocode.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geocode.R 3 | \name{geocode} 4 | \alias{geocode} 5 | \alias{geocodeQueryCheck} 6 | \title{Geocode} 7 | \usage{ 8 | geocode(location, output = c("latlon", "latlona", "more", "all"), 9 | source = c("google", "dsk"), messaging = FALSE, force = ifelse(source == 10 | "dsk", FALSE, TRUE), urlonly = FALSE, override_limit = FALSE, 11 | nameType = c("long", "short"), ext = "com", inject = "", ...) 12 | 13 | geocodeQueryCheck() 14 | } 15 | \arguments{ 16 | \item{location}{a character vector of street addresses or place 17 | names (e.g. "1600 pennsylvania avenue, washington dc" or 18 | "Baylor University")} 19 | 20 | \item{output}{amount of output, "latlon", "latlona", "more", or 21 | "all"} 22 | 23 | \item{source}{"dsk" for Data Science Toolkit or "google" for 24 | Google} 25 | 26 | \item{messaging}{turn messaging on/off} 27 | 28 | \item{force}{force online query, even if previously downloaded} 29 | 30 | \item{urlonly}{return only the url?} 31 | 32 | \item{override_limit}{override the current query count 33 | (.GoogleGeocodeQueryCount)} 34 | 35 | \item{nameType}{in some cases, Google returns both a long name 36 | and a short name. this parameter allows the user to specify 37 | which to grab.} 38 | 39 | \item{ext}{domain extension (e.g. "com", "co.nz")} 40 | 41 | \item{inject}{character string to add to the url} 42 | 43 | \item{...}{...} 44 | } 45 | \value{ 46 | If \code{output} is "latlon", "latlona", or "more", a 47 | data frame. If all, a list. 48 | } 49 | \description{ 50 | Geocodes a location (find latitude and longitude) using either 51 | (1) the Data Science Toolkit 52 | (\url{http://www.datasciencetoolkit.org/about}) or (2) Google 53 | Maps. Note that when using Google you are agreeing to the Google 54 | Maps API Terms of Service at 55 | \url{https://developers.google.com/maps/terms}. 56 | } 57 | \details{ 58 | Note that the Google Maps API limits to 2500 queries a day. Use 59 | \code{geocodeQueryCheck} to determine how many queries remain. 60 | } 61 | \examples{ 62 | 63 | \dontrun{ # Server response can be slow; this cuts down check time. 64 | 65 | ##### basic usage 66 | ######################################## 67 | 68 | geocode("houston texas") 69 | geocode("1600 pennsylvania avenue, washington dc") 70 | geocode("the white house") 71 | geocode(c("the white house", "washington dc")) 72 | # see also mutate_geocode() 73 | geocode("ninos", inject = "region=es", urlonly = TRUE) 74 | 75 | 76 | ##### types of output 77 | ######################################## 78 | 79 | # types of output 80 | geocode("houston texas", output = "latlona") 81 | geocode("houston texas", output = "more") 82 | geocode("Baylor University", output = "more") 83 | str(geocode("Baylor University", output = "all")) 84 | 85 | 86 | ##### interfacing with the google geocoding api 87 | ######################################## 88 | 89 | register_google(key = "your code here") 90 | geocode("houston texas") 91 | 92 | 93 | # see how many requests we have left with google 94 | geocodeQueryCheck() 95 | geocode("one bear place, waco, texas") 96 | geocode("houston texas", force = TRUE) 97 | 98 | 99 | 100 | ##### known issues 101 | ######################################## 102 | # sources often have a hard time reliably geocoding colloquial place names 103 | geocode("city hall houston") 104 | geocode("city hall houston texas") 105 | geocode("rice university") 106 | geocode("rice university houston texas") 107 | 108 | 109 | } 110 | 111 | } 112 | \seealso{ 113 | \code{\link{mutate_geocode}}, 114 | \url{http://code.google.com/apis/maps/documentation/geocoding/}, 115 | \url{https://developers.google.com/maps/documentation/geocoding/usage-limits} 116 | } 117 | \author{ 118 | David Kahle \email{david.kahle@gmail.com} 119 | } 120 | -------------------------------------------------------------------------------- /R/gglocator.R: -------------------------------------------------------------------------------- 1 | #' Locator for ggplots. 2 | #' 3 | #' Locator for ggplots. (Note : only accurate when extent = "normal" 4 | #' when using ggmap.) 5 | #' 6 | #' @param n number of points to locate. 7 | #' @param message unused 8 | #' @param xexpand expand argument in scale_x_continuous 9 | #' @param yexpand expand argument in scale_y_continuous 10 | #' @param mercator logical flag; should the plot be treated as using 11 | #' the projection common to most web map services? Set to FALSE if 12 | #' the axes on the plot use a linear scale. 13 | #' @return a data frame with columns according to the x and y 14 | #' aesthetics 15 | #' @author Tyler Rinker with help from Baptiste Auguie and 16 | #' StackOverflow user DWin with additions and canning by David 17 | #' Kahle \email{david.kahle@@gmail.com}. Updated by 18 | #' \@Nikolai-Hlubek and \@mvkorpel. 19 | #' @export 20 | #' @examples 21 | #' 22 | #' if(interactive()){ 23 | #' 24 | #' # only run for interactive sessions 25 | #' df <- expand.grid(x = 0:-5, y = 0:-5) 26 | #' p <- qplot(x, y, data = df) + 27 | #' annotate(geom = "point", x = -2, y = -2, colour = "red") 28 | #' print(p) 29 | #' cat("click red point\n") 30 | #' print(pt <- gglocator(mercator = FALSE)) 31 | #' p2 <- last_plot() + 32 | #' annotate("point", pt$x, pt$y, color = "blue", size = 3, alpha = .5) 33 | #' cat("a blue point should appear where you clicked\n") 34 | #' print(p2) 35 | #' 36 | #' p3 <- p + 37 | #' scale_x_continuous(expand = c(0,0)) + 38 | #' scale_y_continuous(expand = c(0,0)) 39 | #' print(p3) 40 | #' cat("click any point\n") 41 | #' print(gglocator(1, xexpand = c(0,0), yexpand = c(0,0), 42 | #' mercator = FALSE)) 43 | #' 44 | #' 45 | #' } 46 | #' 47 | #' 48 | gglocator <- function(n = 1, message = FALSE, 49 | xexpand = c(.0, 0), yexpand = c(.0, 0), mercator = TRUE 50 | ){ 51 | 52 | if(n > 1){ 53 | df <- NULL 54 | for(k in 1:n){ 55 | df <- rbind(df, gglocator(message = message, 56 | xexpand = xexpand, yexpand = yexpand, mercator = mercator)) 57 | } 58 | return(df) 59 | } 60 | 61 | object <- last_plot() 62 | if(is.null(object)){ 63 | stop("no plots available") 64 | } 65 | 66 | # find the correct viewport for the npc coordinates 67 | x <- unlist(current.vpTree()) 68 | x <- unname(x[grep("\\.name$", names(x))]) 69 | x <- grep("panel", x, fixed = TRUE, value = TRUE) 70 | n_panels <- length(x) 71 | if(n_panels == 0){ 72 | stop("ggmap plot not detected in current device") 73 | } 74 | if(n_panels > 1){ 75 | x <- x[1] 76 | warning(gettextf("multiple plots detected, choosing one (\"%s\")", 77 | x), domain = NA) 78 | } 79 | previous_viewport <- current.vpPath() 80 | seekViewport(x, recording = FALSE) 81 | 82 | # when exiting function, return to previous position in viewport tree 83 | on.exit(upViewport(0, recording = FALSE)) 84 | if(!is.null(previous_viewport)){ 85 | on.exit(downViewport(previous_viewport, strict = TRUE, recording = FALSE), 86 | add = TRUE) 87 | } 88 | 89 | # get the position relative to that viewport 90 | loc <- as.numeric(grid.locator("npc")) 91 | 92 | # scale the position to the plot 93 | 94 | # get the x.range and y.range from ggplot 95 | plot_info <- ggplot_build(object) 96 | if("layout" %in% names(plot_info)){ 97 | ranges <- plot_info$layout$panel_ranges[[1]] 98 | } else{ 99 | ranges <- plot_info$panel$ranges[[1]] 100 | } 101 | xrng <- ranges$x.range 102 | yrng <- ranges$y.range 103 | 104 | xrng <- expand_range(range = xrng, mul = xexpand[1], add = xexpand[2]) 105 | yrng <- expand_range(range = yrng, mul = yexpand[1], add = yexpand[2]) 106 | 107 | # format and return 108 | point <- data.frame(xrng[1] + loc[1]*diff(xrng), 109 | yrng[1] + loc[2]*diff(yrng)) 110 | if(isTRUE(mercator)){ 111 | yrng2 <- LonLat2XY(0, yrng, zoom = 0, ypix = 256)$y 112 | point[[2]] <- XY2LonLat(y = yrng2[1] + loc[2] * diff(yrng2), 113 | x = 0, X = 0, Y = 0, zoom = 0, ypix = 256)[[2]] 114 | } 115 | names(point) <- with(object, c(deparse(mapping$x), deparse(mapping$y))) 116 | point 117 | } 118 | -------------------------------------------------------------------------------- /R/revgeocode.R: -------------------------------------------------------------------------------- 1 | #' Reverse geocode 2 | #' 3 | #' reverse geocodes a longitude/latitude location using Google Maps. 4 | #' Note that in most cases by using this function you are agreeing 5 | #' to the Google Maps API Terms of Service at 6 | #' https://developers.google.com/maps/terms. 7 | #' 8 | #' @param location a location in longitude/latitude format 9 | #' @param output amount of output 10 | #' @param messaging turn messaging on/off 11 | #' @param urlonly return only the url? 12 | #' @param override_limit override the current query count 13 | #' (.GoogleGeocodeQueryCount) 14 | #' @param ext domain extension (e.g. "com", "co.nz") 15 | #' @param inject character string to add to the url 16 | #' @param ... ... 17 | #' @return depends (at least an address) 18 | #' @author David Kahle \email{david.kahle@@gmail.com} 19 | #' @seealso 20 | #' \url{http://code.google.com/apis/maps/documentation/geocoding/} 21 | #' @export 22 | #' @examples 23 | #' 24 | #' \dontrun{ # Server response can be slow; this cuts down check time. 25 | #' 26 | #' ( gc <- as.numeric(geocode("the white house")) ) 27 | #' revgeocode(gc) 28 | #' revgeocode(gc, output = "more") 29 | #' revgeocode(gc, output = "all") 30 | #' geocodeQueryCheck() 31 | #' 32 | #' } 33 | #' 34 | revgeocode <- function(location, output = c("address","more","all"), 35 | messaging = FALSE, urlonly = FALSE, override_limit = FALSE, 36 | ext = "com", inject = "", ... 37 | ){ 38 | 39 | # check parameters 40 | stopifnot(is.numeric(location) && length(location) == 2) 41 | output <- match.arg(output) 42 | stopifnot(is.logical(messaging)) 43 | 44 | 45 | # format url 46 | latlng <- paste(rev(location), collapse = ',') 47 | posturl <- fmteq(latlng) 48 | url_string <- paste0( 49 | sprintf("https://maps.googleapis.%s/maps/api/geocode/json?", ext), 50 | posturl 51 | ) 52 | 53 | # do google credentials 54 | if (has_goog_client() && has_goog_signature()) { 55 | client <- goog_client() 56 | signature <- goog_signature() 57 | url_string <- paste(url_string, fmteq(client), fmteq(signature), sep = "&") 58 | } else if (has_goog_key()) { 59 | key <- goog_key() 60 | url_string <- paste(url_string, fmteq(key), sep = "&") 61 | } 62 | 63 | # inject any remaining stuff 64 | if(inject != "") url_string <- paste(url_string, inject, sep = "&") 65 | 66 | # encode 67 | url_string <- URLencode( enc2utf8(url_string) ) 68 | if(urlonly) return(url_string) 69 | 70 | # check/update google query limit 71 | check <- checkGeocodeQueryLimit(url_string, elems = 1, override = override_limit, messaging = messaging) 72 | 73 | if(check == "stop"){ 74 | if(output == "address"){ 75 | return(NA) 76 | } else if(output == "more") { 77 | return(c(address = NA, street_number = NA, route = NA, 78 | locality = NA, administrative_area_level_2 = NA, 79 | administrative_area_level_1 = NA, country = NA, postal_code = NA) 80 | ) 81 | } else { 82 | return(NA) 83 | } 84 | } 85 | 86 | # geocode 87 | connect <- url(url_string); on.exit(close(connect), add = TRUE) 88 | rgc <- fromJSON(paste(readLines(connect), collapse = '')) 89 | if(output == "all") return(rgc) 90 | 91 | # did geocode fail? 92 | if(rgc$status != 'OK'){ 93 | warning(paste('reverse geocode failed - bad location? location = "', 94 | location, '"', sep = '')) 95 | return(data.frame(address = NA)) 96 | } 97 | 98 | # message user 99 | message(paste0('Information from URL : ', url_string)) 100 | 101 | # more than one location found? 102 | if(length(rgc$results) > 1 && messaging){ 103 | message("more than one location found for \"", location, "\", reverse geocoding first...\n") 104 | } 105 | 106 | # format 107 | rgc <- rgc$results[[1]] 108 | if(output == 'address') return(rgc$formatted_address) 109 | 110 | with(rgc, { 111 | rgcdf <<- data.frame(address = formatted_address) 112 | }) 113 | 114 | for(k in seq_along(rgc$address_components)){ 115 | rgcdf <- cbind(rgcdf, rgc$address_components[[k]]$long_name) 116 | } 117 | names(rgcdf) <- c("address", sapply(rgc$address_components, function(l) l$types[1])) 118 | 119 | # return 'more' output 120 | rgcdf 121 | } 122 | -------------------------------------------------------------------------------- /R/qmap.R: -------------------------------------------------------------------------------- 1 | #' Quick map plot 2 | #' 3 | #' qmap is a wrapper for \code{\link{ggmap}} and 4 | #' \code{\link{get_map}}. 5 | #' 6 | #' @param location character; location of interest 7 | #' @param ... stuff to pass to \code{\link{ggmap}} and 8 | #' \code{\link{get_map}}. 9 | #' @return a ggplot object 10 | #' @author David Kahle \email{david.kahle@@gmail.com} 11 | #' @seealso \code{\link{ggmap}} and \code{\link{get_map}}. 12 | #' @export 13 | #' @examples 14 | #' 15 | #' \dontrun{ 16 | #' # these examples have been excluded for checking efficiency 17 | #' 18 | #' location <- "marrs mclean science, waco, texas" 19 | #' qmap(location) 20 | #' qmap(location, zoom = 14) 21 | #' qmap(location, zoom = 14, source = "osm") 22 | #' qmap(location, zoom = 14, source = "osm", scale = 20000) 23 | #' qmap(location, zoom = 14, maptype = "satellite") 24 | #' qmap(location, zoom = 14, maptype = "hybrid") 25 | #' qmap(location, zoom = 14, maptype = "toner", source = "stamen") 26 | #' qmap(location, zoom = 14, maptype = "watercolor", source = "stamen") 27 | #' qmap(location, zoom = 14, maptype = "terrain-background", source = "stamen") 28 | #' qmap(location, zoom = 14, maptype = "toner-lite", source = "stamen") 29 | #' 30 | #' where <- "the white house, washington dc" 31 | #' wh <- geocode(where) 32 | #' qmap(where, maprange = TRUE, zoom = 15, 33 | #' base_layer = ggplot(aes(x=lon, y=lat), data = wh)) + 34 | #' geom_point() 35 | #' 36 | #' 37 | #' 38 | #' } 39 | #' 40 | qmap <- function(location = "houston", ...){ 41 | 42 | # location formatting 43 | location_stop <- TRUE 44 | if(is.character(location) && length(location) == 1){ 45 | # address 46 | location_stop <- FALSE 47 | } 48 | if(is.numeric(location) && length(location) == 2){ 49 | # lonlat 50 | location_stop <- FALSE 51 | } 52 | if(is.numeric(location) && length(location) == 4){ 53 | # bbox 54 | location_stop <- FALSE 55 | } 56 | if(location_stop){ 57 | stop("improper location specification, see ?get_map.", call. = F) 58 | } 59 | 60 | args <- as.list(match.call(expand.dots = TRUE)[-1]) 61 | 62 | # get_map args 63 | ################## 64 | 65 | if("zoom" %in% names(args)){ 66 | zoom <- eval(args$zoom) 67 | } else { 68 | zoom <- 10 69 | } 70 | 71 | if("scale" %in% names(args)){ 72 | scale <- eval(args$scale) 73 | } else { 74 | scale <- "auto" 75 | } 76 | 77 | if("color" %in% names(args)){ 78 | color <- eval(args$color) 79 | } else { 80 | color <- "color" 81 | } 82 | 83 | if("source" %in% names(args)){ 84 | source <- eval(args$source) 85 | } else { 86 | source <- "google" 87 | } 88 | 89 | if("force" %in% names(args)){ 90 | force <- eval(args$force) 91 | } else { 92 | if(source == "google"){ 93 | force <- FALSE #TRUE 94 | } else { 95 | force <- FALSE 96 | } 97 | } 98 | 99 | if("maptype" %in% names(args)){ 100 | maptype <- eval(args$maptype) 101 | } else { 102 | if(source != "cloudmade"){ 103 | maptype <- "terrain" 104 | } else { 105 | maptype <- 1 106 | } 107 | } 108 | 109 | # ggmap args 110 | ################## 111 | 112 | if("extent" %in% names(args)){ 113 | extent <- eval(args$extent) 114 | } else { 115 | extent <- "device" 116 | } 117 | 118 | if("maprange" %in% names(args)){ 119 | maprange <- eval(args$maprange) 120 | } else { 121 | maprange <- FALSE 122 | } 123 | 124 | if("base_layer" %in% names(args)){ 125 | base_layer <- args$base_layer 126 | } else { 127 | base_layer <- "auto" 128 | } 129 | 130 | if("legend" %in% names(args)){ 131 | legend <- args$legend 132 | } else { 133 | legend <- "right" 134 | } 135 | 136 | if("padding" %in% names(args)){ 137 | padding <- args$padding 138 | } else { 139 | padding <- .02 140 | } 141 | 142 | if("darken" %in% names(args)){ 143 | darken <- eval(args$darken) 144 | } else { 145 | darken <- c(0, "black") 146 | } 147 | 148 | if("language" %in% names(args)){ 149 | language <- eval(args$language) 150 | } else { 151 | language <- "en-EN" 152 | } 153 | 154 | 155 | 156 | #ggmap(get_map(location = location, ...), ...) 157 | # return 158 | ggmap( 159 | get_map(location = location, zoom = zoom, scale = scale, source = source, 160 | color = color, maptype = maptype, language = language, force = force), 161 | maprange = maprange, extent = extent, base_layer = base_layer, legend = legend, 162 | padding = padding, darken = darken 163 | ) 164 | } 165 | -------------------------------------------------------------------------------- /R/register_google.R: -------------------------------------------------------------------------------- 1 | #' Register a Google API 2 | #' 3 | #' Many features of the Google web mapping services can be improved 4 | #' by using standard or premium credentials, such as usage limits 5 | #' and query rates. This function allows users to input this 6 | #' information into R as a global option to be retained for the 7 | #' entire session. 8 | #' 9 | #' @param key an api key 10 | #' @param account_type \code{"standard"} or \code{"premium"} 11 | #' @param client client code 12 | #' @param signature signature code 13 | #' @param second_limit query limit per second (default 50) 14 | #' @param day_limit query limit per day (default 2500 for standard 15 | #' accounts, 100000 for premium accounts) 16 | #' @return NULL 17 | #' @name register_google 18 | #' @author David Kahle \email{david.kahle@@gmail.com} 19 | #' @seealso 20 | #' \url{http://code.google.com/apis/maps/documentation/geocoding/}, 21 | #' \url{https://developers.google.com/maps/documentation/geocoding/usage-limits} 22 | #' @examples 23 | #' 24 | #' 25 | #' has_goog_key() 26 | #' goog_key() 27 | #' has_goog_client() 28 | #' has_goog_signature() 29 | #' register_google(key = "[your key here]") 30 | #' 31 | 32 | 33 | 34 | 35 | #' @rdname register_google 36 | #' @export 37 | register_google <- function (key, account_type, client, signature, second_limit, day_limit) { 38 | 39 | # get current options 40 | options <- getOption("ggmap") 41 | 42 | # check for client/sig specs 43 | if (!missing(client) && missing(signature) ) { 44 | stop("if client is specified, signature must be also.") 45 | } 46 | if ( missing(client) && !missing(signature) ) { 47 | stop("if signature is specified, client must be also.") 48 | } 49 | if (!missing(client) && !missing(signature) ) { 50 | if (goog_account() == "standard" && missing(account_type)) { 51 | stop("if providing client and signature, the account type must be premium.") 52 | } 53 | } 54 | 55 | # construct new ones 56 | if(!missing(key)) options$google$key <- key 57 | if(!missing(account_type)) options$google$account_type <- account_type 58 | if(!missing(day_limit)) options$google$day_limit <- day_limit 59 | if(!missing(second_limit)) options$google$second_limit <- second_limit 60 | if(!missing(client)) options$google$client <- client 61 | if(!missing(signature)) options$google$signature <- signature 62 | 63 | # # set premium defaults 64 | if (!missing(account_type) && account_type == "premium") { 65 | if(missing(day_limit)) options$google$day_limit <- 100000 66 | } 67 | 68 | # class 69 | class(options) <- "ggmap_credentials" 70 | 71 | # set new options 72 | options(ggmap = options) 73 | 74 | # return 75 | invisible(NULL) 76 | } 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | #' @rdname register_google 85 | #' @export 86 | goog_key <- function () { 87 | 88 | getOption("ggmap")$google$key 89 | 90 | } 91 | 92 | #' @rdname register_google 93 | #' @export 94 | has_goog_key <- function () { 95 | 96 | if(is.null(getOption("ggmap"))) return(FALSE) 97 | 98 | !is.na(goog_key()) 99 | 100 | } 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | #' @rdname register_google 109 | #' @export 110 | has_goog_account <- function () { 111 | 112 | if(is.null(getOption("ggmap"))) return(FALSE) 113 | 114 | !is.na(goog_account()) 115 | 116 | } 117 | 118 | #' @rdname register_google 119 | #' @export 120 | goog_account <- function () { 121 | 122 | getOption("ggmap")$google$account_type 123 | 124 | } 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | #' @rdname register_google 134 | #' @export 135 | goog_client <- function () { 136 | 137 | getOption("ggmap")$google$client 138 | 139 | } 140 | 141 | #' @rdname register_google 142 | #' @export 143 | has_goog_client <- function () { 144 | 145 | if(is.null(getOption("ggmap"))) return(FALSE) 146 | 147 | !is.na(goog_client()) 148 | 149 | } 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | #' @rdname register_google 159 | #' @export 160 | goog_signature <- function () { 161 | 162 | getOption("ggmap")$google$signature 163 | 164 | } 165 | 166 | #' @rdname register_google 167 | #' @export 168 | has_goog_signature <- function () { 169 | 170 | if(is.null(getOption("ggmap"))) return(FALSE) 171 | 172 | !is.na(goog_signature()) 173 | 174 | } 175 | 176 | 177 | 178 | 179 | 180 | #' @rdname register_google 181 | #' @export 182 | goog_second_limit <- function () { 183 | 184 | # set to 50 if no key present (ggmap not loaded) 185 | if(!has_goog_key()) return(50) 186 | 187 | getOption("ggmap")$google$second_limit 188 | 189 | } 190 | 191 | 192 | 193 | #' @rdname register_google 194 | #' @export 195 | goog_day_limit <- function () { 196 | 197 | # set to 2500 if no key present (ggmap not loaded) 198 | if(!has_goog_key()) return(2500) 199 | 200 | getOption("ggmap")$google$day_limit 201 | 202 | } 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | #' @rdname register_google 211 | #' @param tree a json tree from \code{\link{fromJSON}} 212 | #' @export 213 | check_google_for_error <- function (tree) { 214 | 215 | if (tree$status == "REQUEST_DENIED") { 216 | warning("REQUEST_DENIED : ", tree$error_message) 217 | } 218 | 219 | } 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | -------------------------------------------------------------------------------- /man/geom_leg.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geom_leg.R, R/route.R 3 | \name{geom_leg} 4 | \alias{geom_leg} 5 | \alias{geom_leg} 6 | \title{Single line segments with rounded ends} 7 | \usage{ 8 | geom_leg(mapping = NULL, data = NULL, stat = "identity", 9 | position = "identity", arrow = NULL, lineend = "round", na.rm = FALSE, 10 | show.legend = NA, inherit.aes = TRUE, ...) 11 | 12 | geom_leg(mapping = NULL, data = NULL, stat = "identity", 13 | position = "identity", arrow = NULL, lineend = "round", na.rm = FALSE, 14 | show.legend = NA, inherit.aes = TRUE, ...) 15 | } 16 | \arguments{ 17 | \item{mapping}{mapping} 18 | 19 | \item{data}{data} 20 | 21 | \item{stat}{stat} 22 | 23 | \item{position}{position} 24 | 25 | \item{arrow}{arrow} 26 | 27 | \item{lineend}{Line end style (round, butt, square).} 28 | 29 | \item{na.rm}{If \code{FALSE}, the default, missing values are removed with 30 | a warning. If \code{TRUE}, missing values are silently removed.} 31 | 32 | \item{show.legend}{logical. Should this layer be included in the legends? 33 | \code{NA}, the default, includes if any aesthetics are mapped. 34 | \code{FALSE} never includes, and \code{TRUE} always includes. 35 | It can also be a named logical vector to finely select the aesthetics to 36 | display.} 37 | 38 | \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, 39 | rather than combining with them. This is most useful for helper functions 40 | that define both data and aesthetics and shouldn't inherit behaviour from 41 | the default plot specification, e.g. \code{\link[=borders]{borders()}}.} 42 | 43 | \item{...}{...} 44 | } 45 | \description{ 46 | This is ggplot2's segment with rounded ends. It's mainly 47 | included in ggmap for historical reasons. 48 | 49 | Single line segments with rounded ends 50 | } 51 | \details{ 52 | only intended for use in ggmap package. only designed 53 | for mercator projection. 54 | 55 | only intended for use in ggmap package. only designed 56 | for mercator projection. 57 | } 58 | \examples{ 59 | 60 | \dontrun{ # removed for R CMD check speed 61 | 62 | map <- get_map( 63 | location = c(-77.0425, 38.8925), # painfully picked by hand 64 | source = "google", zoom = 14, maptype = "satellite" 65 | ) 66 | ggmap(map) 67 | 68 | 69 | (legs_df <- route( 70 | "the white house, dc", 71 | "lincoln memorial washington dc", 72 | alternatives = TRUE 73 | )) 74 | 75 | ggplot(data = legs_df) + 76 | geom_leg(aes( 77 | x = startLon, xend = endLon, 78 | y = startLat, yend = endLat 79 | )) + 80 | coord_map() 81 | 82 | ggplot(data = legs_df) + 83 | geom_leg(aes( 84 | x = startLon, xend = endLon, 85 | y = startLat, yend = endLat, 86 | color = route 87 | )) + 88 | coord_map() 89 | 90 | 91 | ggmap(map) + 92 | geom_leg( 93 | aes( 94 | x = startLon, xend = endLon, 95 | y = startLat, yend = endLat 96 | ), 97 | data = legs_df, color = "red" 98 | ) 99 | 100 | # adding a color aesthetic errors because of a base-layer problem 101 | # ggmap(map) + 102 | # geom_leg( 103 | # aes( 104 | # x = startLon, xend = endLon, 105 | # y = startLat, yend = endLat, 106 | # color = route 107 | # ) 108 | # ) 109 | 110 | 111 | # this is probably the easiest hack to fix it 112 | ggplot(data = legs_df) + 113 | inset_ggmap(map) + 114 | geom_leg( 115 | aes( 116 | x = startLon, xend = endLon, 117 | y = startLat, yend = endLat, 118 | color = route 119 | ), 120 | data = legs_df 121 | ) + 122 | coord_map() 123 | 124 | } 125 | 126 | 127 | \dontrun{ # removed for R CMD check speed 128 | 129 | map <- get_map( 130 | location = c(-77.0425, 38.8925), # painfully picked by hand 131 | source = "google", zoom = 14, maptype = "satellite" 132 | ) 133 | ggmap(map) 134 | 135 | 136 | (legs_df <- route( 137 | "the white house, dc", 138 | "lincoln memorial washington dc", 139 | alternatives = TRUE 140 | )) 141 | 142 | ggplot(data = legs_df) + 143 | geom_leg(aes( 144 | x = startLon, xend = endLon, 145 | y = startLat, yend = endLat 146 | )) + 147 | coord_map() 148 | 149 | ggplot(data = legs_df) + 150 | geom_leg(aes( 151 | x = startLon, xend = endLon, 152 | y = startLat, yend = endLat, 153 | color = route 154 | )) + 155 | coord_map() 156 | 157 | 158 | ggmap(map) + 159 | geom_leg( 160 | aes( 161 | x = startLon, xend = endLon, 162 | y = startLat, yend = endLat 163 | ), 164 | data = legs_df, color = "red" 165 | ) 166 | 167 | # adding a color aesthetic errors because of a base-layer problem 168 | # ggmap(map) + 169 | # geom_leg( 170 | # aes( 171 | # x = startLon, xend = endLon, 172 | # y = startLat, yend = endLat, 173 | # color = route 174 | # ) 175 | # ) 176 | 177 | 178 | # this is probably the easiest hack to fix it 179 | ggplot(data = legs_df) + 180 | inset_ggmap(map) + 181 | geom_leg( 182 | aes( 183 | x = startLon, xend = endLon, 184 | y = startLat, yend = endLat, 185 | color = route 186 | ), 187 | data = legs_df 188 | ) + 189 | coord_map() 190 | 191 | } 192 | 193 | } 194 | \seealso{ 195 | geom_segment in ggplot2, inspired by 196 | \url{http://spatialanalysis.co.uk/2012/02/great-maps-ggplot2/}, 197 | \code{\link{route}} 198 | 199 | geom_segment in ggplot2, inspired by 200 | \url{http://spatialanalysis.co.uk/2012/02/great-maps-ggplot2/}, 201 | \code{\link{route}} 202 | } 203 | -------------------------------------------------------------------------------- /man/get_googlemap.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_googlemap.R 3 | \name{get_googlemap} 4 | \alias{get_googlemap} 5 | \title{Get a Google Map.} 6 | \usage{ 7 | get_googlemap(center = c(lon = -95.3632715, lat = 29.7632836), zoom = 10, 8 | size = c(640, 640), scale = 2, format = c("png8", "gif", "jpg", 9 | "jpg-baseline", "png32"), maptype = c("terrain", "satellite", "roadmap", 10 | "hybrid"), language = "en-EN", messaging = FALSE, urlonly = FALSE, 11 | filename = NULL, color = c("color", "bw"), force = FALSE, 12 | where = tempdir(), archiving = FALSE, ext = "com", inject = "", 13 | region, markers, path, visible, style, ...) 14 | } 15 | \arguments{ 16 | \item{center}{the center of the map. Either a longitude/latitude 17 | numeric vector, a string address (note that the latter uses 18 | \code{geocode} with \code{source = "google"}).} 19 | 20 | \item{zoom}{map zoom, an integer from 3 (continent) to 21 21 | (building), default value 10 (city)} 22 | 23 | \item{size}{rectangular dimensions of map in pixels - horizontal 24 | x vertical - with a max of c(640, 640). this parameter is 25 | affected in a multiplicative way by scale.} 26 | 27 | \item{scale}{multiplicative factor for the number of pixels 28 | returned possible values are 1, 2, or 4 (e.g. size = c(640,640) 29 | and scale = 2 returns an image with 1280x1280 pixels). 4 is 30 | reserved for google business users only. scale also affects 31 | the size of labels as well.} 32 | 33 | \item{format}{character string providing image format - png, 34 | jpeg, and gif formats available in various flavors} 35 | 36 | \item{maptype}{character string providing google map theme. 37 | options available are "terrain", "satellite", "roadmap", and 38 | "hybrid"} 39 | 40 | \item{language}{character string providing language of map labels 41 | (for themes with them) in the format "en-EN". not all 42 | languages are supported; for those which aren't the default 43 | language is used} 44 | 45 | \item{messaging}{turn messaging on/off} 46 | 47 | \item{urlonly}{return url only} 48 | 49 | \item{filename}{destination file for download (file extension added 50 | according to format). Default \code{NULL} means a random 51 | \code{\link{tempfile}}.} 52 | 53 | \item{color}{color or black-and-white} 54 | 55 | \item{force}{if the map is on file, should a new map be looked 56 | up?} 57 | 58 | \item{where}{where should the file drawer be located (without 59 | terminating "/")} 60 | 61 | \item{archiving}{use archived maps. note: by changing to TRUE 62 | you agree to the one of the approved uses listed in the Google 63 | Maps API Terms of Service : 64 | http://developers.google.com/maps/terms.} 65 | 66 | \item{ext}{domain extension (e.g. "com", "co.nz")} 67 | 68 | \item{inject}{character string to add to the url} 69 | 70 | \item{region}{borders to display as a region code specified as a 71 | two-character ccTLD ("top-level domain") value, see 72 | \url{http://en.wikipedia.org/wiki/List_of_Internet_top-level_domains#Country_code_top-level_domains}} 73 | 74 | \item{markers}{data.frame with first column longitude, second 75 | column latitude, for which google markers should be embedded in 76 | the map image, or character string to be passed directly to api} 77 | 78 | \item{path}{data.frame (or list of data.frames) with first column 79 | longitude, second column latitude, for which a single path 80 | should be embedded in the map image, or character string to be 81 | passed directly to api} 82 | 83 | \item{visible}{a location as a longitude/latitude numeric vector 84 | (or data frame with first column longitude, second latitude) or 85 | vector of character string addresses which should be visible in 86 | map extent} 87 | 88 | \item{style}{character string to be supplied directly to the api 89 | for the style argument or a named vector (see examples). this 90 | is a powerful complex specification, see 91 | \url{https://developers.google.com/maps/documentation/staticmaps/}} 92 | 93 | \item{...}{...} 94 | } 95 | \value{ 96 | a ggmap object (a classed raster object with a bounding 97 | box attribute) 98 | } 99 | \description{ 100 | \code{get_googlemap} accesses the Google Static Maps API version 101 | 2 to download a static map. Note that in most cases by using 102 | this function you are agreeing to the Google Maps API Terms of 103 | Service at \url{https://developers.google.com/maps/terms}. 104 | } 105 | \examples{ 106 | 107 | \dontrun{ # to diminish run check time 108 | 109 | 110 | get_googlemap(urlonly = TRUE) 111 | ggmap(get_googlemap()) 112 | 113 | 114 | # markers and paths are easy to access 115 | d <- function(x=-95.36, y=29.76, n,r,a){ 116 | round(data.frame( 117 | lon = jitter(rep(x,n), amount = a), 118 | lat = jitter(rep(y,n), amount = a) 119 | ), digits = r) 120 | } 121 | df <- d(n=50,r=3,a=.3) 122 | map <- get_googlemap(markers = df, path = df, scale = 2) 123 | ggmap(map) 124 | ggmap(map, extent = "device") + 125 | geom_point(aes(x = lon, y = lat), data = df, size = 3, colour = "black") + 126 | geom_path(aes(x = lon, y = lat), data = df) 127 | 128 | gc <- geocode("waco, texas", source = "google") 129 | center <- as.numeric(gc) 130 | ggmap(get_googlemap(center = center, color = "bw", scale = 2), extent = "device") 131 | 132 | # the scale argument can be seen in the following 133 | # (make your graphics device as large as possible) 134 | ggmap(get_googlemap(center, scale = 1), extent = "panel") # pixelated 135 | ggmap(get_googlemap(center, scale = 2), extent = "panel") # fine 136 | 137 | # archiving; note that you must meet google's terms for this condition 138 | map <- get_googlemap(archiving = TRUE) 139 | map <- get_googlemap() 140 | ggmap(map) 141 | 142 | 143 | # style 144 | map <- get_googlemap( 145 | maptype = "roadmap", 146 | style = c(feature = "all", element = "labels", visibility = "off"), 147 | color = "bw" 148 | ) 149 | ggmap(map) 150 | 151 | 152 | 153 | 154 | } 155 | 156 | } 157 | \seealso{ 158 | \url{https://developers.google.com/maps/documentation/staticmaps/}, 159 | \code{\link{ggmap}}, \code{\link{register_google}} 160 | } 161 | \author{ 162 | David Kahle \email{david.kahle@gmail.com} 163 | } 164 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | output: 3 | md_document: 4 | variant: markdown_github 5 | --- 6 | 7 | 8 | 9 | ```{r, echo = FALSE} 10 | knitr::opts_chunk$set( 11 | collapse = TRUE, cache = TRUE, 12 | comment = "# ", 13 | fig.path = "tools/README-" 14 | ) 15 | ``` 16 | 17 | # ggmap 18 | 19 | __ggmap__ makes it easy to retrieve raster map tiles from popular online mapping services like [Google Maps](https://developers.google.com/maps/documentation/static-maps/?hl=en), [OpenStreetMap](https://www.openstreetmap.org), [Stamen Maps](http://maps.stamen.com), and plot them using the [__ggplot2__](https://github.com/tidyverse/ggplot2) framework: 20 | 21 | ```{r maptypes, message = FALSE} 22 | library("ggmap") 23 | 24 | us <- c(left = -125, bottom = 25.75, right = -67, top = 49) 25 | map <- get_stamenmap(us, zoom = 5, maptype = "toner-lite") 26 | ggmap(map) 27 | ggmap(map, extent = "device") 28 | ``` 29 | 30 | Use `qmplot()` in the same way you'd use `qplot()`, but with a map automatically added in the background: 31 | 32 | ```{r qmplot, message=FALSE} 33 | library("dplyr") 34 | library("forcats") 35 | 36 | # define helper 37 | `%notin%` <- function(lhs, rhs) !(lhs %in% rhs) 38 | 39 | # reduce crime to violent crimes in downtown houston 40 | violent_crimes <- crime %>% 41 | filter( 42 | offense %notin% c("auto theft", "theft", "burglary"), 43 | -95.39681 <= lon & lon <= -95.34188, 44 | 29.73631 <= lat & lat <= 29.78400 45 | ) %>% 46 | mutate( 47 | offense = fct_drop(offense), 48 | offense = fct_relevel(offense, 49 | c("robbery", "aggravated assault", "rape", "murder") 50 | ) 51 | ) 52 | 53 | # use qmplot to make a scatterplot on a map 54 | qmplot(lon, lat, data = violent_crimes, maptype = "toner-lite", color = I("red")) 55 | ``` 56 | 57 | All the __ggplot2__ geom's are available. For example, you can make a contour plot with `geom = "density2d"`: 58 | 59 | ```{r qmplot2} 60 | qmplot(lon, lat, data = violent_crimes, maptype = "toner-lite", geom = "density2d", color = I("red")) 61 | ``` 62 | 63 | In fact, since __ggmap__'s built on top of __ggplot2__, all your usual __ggplot2__ stuff (geoms, polishing, etc.) will work, and there are some unique graphing perks __ggmap__ brings to the table, too. 64 | 65 | ```{r styling, message=FALSE} 66 | robberies <- violent_crimes %>% filter(offense == "robbery") 67 | 68 | qmplot(lon, lat, data = violent_crimes, geom = "blank", 69 | zoom = 15, maptype = "toner-background", darken = .7, legend = "topleft" 70 | ) + 71 | stat_density_2d(aes(fill = ..level..), geom = "polygon", alpha = .3, color = NA) + 72 | scale_fill_gradient2("Robbery\nPropensity", low = "white", mid = "yellow", high = "red", midpoint = 650) 73 | ``` 74 | 75 | Faceting works, too: 76 | 77 | ```{r faceting, message=FALSE} 78 | qmplot(lon, lat, data = violent_crimes, maptype = "toner-background", color = offense) + 79 | facet_wrap(~ offense) 80 | ``` 81 | 82 | For convenience, here are a few maps of Europe: 83 | 84 | ```{r europe, message=FALSE} 85 | europe <- c(left = -12, bottom = 35, right = 30, top = 63) 86 | get_stamenmap(europe, zoom = 5) %>% ggmap() 87 | get_stamenmap(europe, zoom = 5, maptype = "toner-lite") %>% ggmap() 88 | ``` 89 | 90 | 91 | 92 | 93 | 94 | ## Google Maps and Credentials 95 | 96 | [Google Maps](http://developers.google.com/maps/terms) can be used just as easily. However, since Google Maps use a center/zoom specification, their input is a bit different: 97 | ```{r google_maps} 98 | get_googlemap("waco texas", zoom = 12) %>% ggmap() 99 | ``` 100 | 101 | Moreover, you can get various different styles of Google Maps with __ggmap__ (just like Stamen Maps): 102 | ```{r google_styles} 103 | get_googlemap("waco texas", zoom = 12, maptype = "satellite") %>% ggmap() 104 | get_googlemap("waco texas", zoom = 12, maptype = "roadmap") %>% ggmap() 105 | get_googlemap("waco texas", zoom = 12, maptype = "hybrid") %>% ggmap() 106 | ``` 107 | 108 | Google's geocoding and reverse geocoding API's are available through `geocode()` and `revgeocode()`, respectively: 109 | ```{r geocode} 110 | geocode("1301 S University Parks Dr, Waco, TX 76798") 111 | revgeocode(c(lon = -97.1161, lat = 31.55098)) 112 | ``` 113 | 114 | There is also a `mutate_geocode()` that works similarly to [__dplyr__](https://github.com/hadley/dplyr)'s `mutate()` function: 115 | ```{r mutate_geocode, messages = FALSE} 116 | df <- data.frame( 117 | address = c("1600 Pennsylvania Avenue, Washington DC", "", "waco texas"), 118 | stringsAsFactors = FALSE 119 | ) 120 | df %>% mutate_geocode(address) 121 | ``` 122 | 123 | 124 | Treks use Google's routing API to give you routes (`route()` and `trek()` give slightly different results; the latter hugs roads): 125 | ```{r route_trek} 126 | trek_df <- trek("houson, texas", "waco, texas", structure = "route") 127 | qmap("college station, texas", zoom = 8) + 128 | geom_path( 129 | aes(x = lon, y = lat), colour = "blue", 130 | size = 1.5, alpha = .5, 131 | data = trek_df, lineend = "round" 132 | ) 133 | ``` 134 | 135 | (They also provide information on how long it takes to get from point A to point B.) 136 | 137 | 138 | Map distances, in both length and anticipated time, can be computed with `mapdist()`). Moreover the function is vectorized: 139 | ```{r mapdist} 140 | mapdist(c("houston, texas", "dallas"), "waco, texas") 141 | ``` 142 | 143 | 144 | 145 | ### Google credentialing 146 | 147 | If you have a Google API key, you can exceed the standard limits Google places on queries. By default, when __ggmap__ is loaded it will set the following credentials and limits: 148 | ```{r basic_credentials} 149 | ggmap_credentials() 150 | ``` 151 | Look at the documentation of `?register_google()` to learn more. If you do have an API key, you set it with: 152 | ```{r google_api} 153 | register_google(key = "[your key here]", account_type = "premium", day_limit = 100000) 154 | ggmap_credentials() 155 | ``` 156 | These will then be used and checked when creating the query URL: 157 | ```{r key} 158 | register_google(key = "AbCdEfGhIjKlMnOpQrStUvWxYz") 159 | get_googlemap("waco texas", urlonly = TRUE) 160 | ``` 161 | 162 | For anything that hasn't been implemente (URL-wise), you can inject code into the query usin g `inject`: 163 | ```{r otherStuff} 164 | get_googlemap("waco texas", urlonly = TRUE, inject = "otherItem = Stuff") 165 | ``` 166 | 167 | 168 | 169 | 170 | 171 | 172 | ## Installation 173 | 174 | * From CRAN: `install.packages("ggmap")` 175 | 176 | * From Github: `devtools::install_github("dkahle/ggmap")` 177 | 178 | -------------------------------------------------------------------------------- /R/get_openstreetmap.R: -------------------------------------------------------------------------------- 1 | #' Get an OpenStreetMap 2 | #' 3 | #' \code{get_openstreetmap} accesses a tile server for OpenStreetMap and 4 | #' downloads/formats a map image. This is simply a wrapper for the web-based 5 | #' version at \url{http://www.openstreetmap.org/}. If you don't know how to 6 | #' get the map you want, go there, navigate to the map extent that you want, 7 | #' click the export tab at the top of the page, and copy the information into 8 | #' this function. 9 | #' 10 | # In some cases the OSM server is unavailable, in these cases you will 11 | #' receive an error message from \code{download.file} with the message HTTP status 12 | #' '503 Service Unavailable'. You can confirm this by setting urlonly = TRUE, 13 | #' and then entering the URL in a web browser. the solution is either (1) 14 | #' change sources or (2) wait for the OSM servers to come back up. 15 | #' 16 | #' See \url{http://www.openstreetmap.org/copyright} for license and copyright 17 | #' information. 18 | #' 19 | #' @param bbox a bounding box in the format c(lowerleftlon, lowerleftlat, 20 | #' upperrightlon, upperrightlat) 21 | #' @param scale scale parameter, see 22 | #' \url{http://wiki.openstreetmap.org/wiki/MinScaleDenominator}. smaller 23 | #' scales provide a finer degree of detail, where larger scales produce more 24 | #' coarse detail. 25 | #' 26 | #' The scale argument is a tricky number to correctly specify. In most cases, 27 | #' if you get an error when downloading an openstreetmap the error is 28 | #' attributable to an improper scale specification. 29 | #' \code{\link{OSM_scale_lookup}} can help; but the best way to get in the 30 | #' correct range is to go to \url{http://www.openstreetmap.org/}, navigate to 31 | #' the map of interest, click export at the top of the page, click 'map image' 32 | #' and then copy down the scale listed. 33 | #' @param format character string providing image format - png, jpeg, svg, pdf, 34 | #' and ps formats 35 | #' @param messaging turn messaging on/off 36 | #' @param urlonly return url only 37 | #' @param filename destination file for download (file extension added according 38 | #' to format). Default \code{NULL} means a random \code{\link{tempfile}}. 39 | #' @param color color or black-and-white 40 | #' @param ... ... 41 | #' @return a ggmap object (a classed raster object with a bounding box attribute) 42 | #' @author David Kahle \email{david.kahle@@gmail.com} 43 | #' @seealso \url{http://www.openstreetmap.org/}, \code{\link{ggmap}} 44 | #' @export 45 | #' @examples 46 | #' 47 | #' get_openstreetmap(urlonly = TRUE) 48 | #' \dontrun{ 49 | #' # osm servers get overloaded, which can result in 50 | #' # erroneous failed checks 51 | #' 52 | #' osm <- get_openstreetmap() 53 | #' ggmap(osm) 54 | #' 55 | #' } 56 | #' 57 | get_openstreetmap <- function( 58 | bbox = c(left = -95.80204, bottom = 29.38048, right = -94.92313, top = 30.14344), 59 | scale = 606250, format = c('png', 'jpeg', 'svg', 'pdf', 'ps'), messaging = FALSE, 60 | urlonly = FALSE, filename = NULL, color = c('color','bw'), ... 61 | ){ 62 | 63 | # enumerate argument checking (added in lieu of checkargs function) 64 | args <- as.list(match.call(expand.dots = TRUE)[-1]) 65 | argsgiven <- names(args) 66 | 67 | # argument checking (no checks for language, region, markers, path, visible, style) 68 | #if(checkargs) get_openstreetmap_checkargs(args) 69 | 70 | if('bbox' %in% argsgiven){ 71 | if(!(is.numeric(bbox) && length(bbox) == 4)){ 72 | stop('bounding box improperly specified. see ?get_openstreetmap', call. = F) 73 | } 74 | } 75 | 76 | if('scale' %in% argsgiven){ 77 | if(!(is.numeric(scale) && length(scale) == 1 && 78 | scale == round(scale) && scale > 0)){ 79 | stop('scale must be a positive integer.', call. = F) 80 | } 81 | } 82 | 83 | if('messaging' %in% argsgiven) stopifnot(is.logical(messaging)) 84 | 85 | if('urlonly' %in% argsgiven) stopifnot(is.logical(urlonly)) 86 | 87 | format <- match.arg(format) 88 | if(format != 'png') stop('currently only the png format is supported.', call. = F) 89 | 90 | if(is.null(filename)){ 91 | destfile <- tempfile(fileext = paste(".", format, sep = "")) 92 | } else{ 93 | filename_stop <- TRUE 94 | if(is.character(filename) && length(filename) == 1) filename_stop <- FALSE 95 | if(filename_stop) stop('improper filename specification, see ?get_openstreetmap.', call. = F) 96 | destfile <- paste(filename, format, sep = '.') 97 | } 98 | 99 | # color arg checked by match.arg 100 | color <- match.arg(color) 101 | 102 | if('checkargs' %in% argsgiven){ 103 | .Deprecated(msg = 'checkargs argument deprecated, args are always checked after v2.1.') 104 | } 105 | 106 | 107 | 108 | 109 | 110 | # url segments 111 | base_url <- 'http://tile.openstreetmap.org/cgi-bin/export?' 112 | bbox_url <- paste('bbox=', paste(bbox, collapse = ','), sep = '') 113 | scale_url <- paste('scale=', as.integer(scale), sep = '') 114 | format_url <- paste('format=', format, sep = '') 115 | 116 | 117 | # format url proper 118 | post_url <- paste(bbox_url, scale_url, format_url, sep = '&') 119 | url <- paste(base_url, post_url, sep = '') 120 | url <- URLencode(url) 121 | if(urlonly) return(url) 122 | 123 | # read in file 124 | m <- try(download.file(url, destfile = destfile, quiet = !messaging, mode = 'wb'), silent = T) 125 | if(class(m) == 'try-error'){ 126 | stop('map grabbing failed - see details in ?get_openstreetmap.', 127 | call. = FALSE) 128 | } 129 | map <- try(readPNG(destfile), silent = T) 130 | if(class(map) == 'try-error'){ 131 | stop('map grabbing failed - see details in ?get_openstreetmap.', 132 | call. = FALSE) 133 | } 134 | 135 | # format file 136 | if(color == 'color'){ 137 | map <- as.raster(apply(map, 2, rgb)) 138 | } else if(color == 'bw'){ 139 | mapd <- dim(map) 140 | map <- gray(.30 * map[,,1] + .59 * map[,,2] + .11 * map[,,3]) 141 | dim(map) <- mapd[1:2] 142 | map <- as.raster(map) 143 | } 144 | class(map) <- c('ggmap','raster') 145 | 146 | # map spatial info 147 | attr(map, 'bb') <- data.frame( 148 | ll.lat = bbox[2], ll.lon = bbox[1], 149 | ur.lat = bbox[4], ur.lon = bbox[3] 150 | ) 151 | 152 | # additional map meta-data 153 | attr(map, "source") <- "osm" 154 | attr(map, "maptype") <- "openstreetmap" 155 | attr(map, "scale") <- scale 156 | 157 | # return 158 | map 159 | } 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | get_openstreetmap_checkargs <- function(args){ 179 | eargs <- lapply(args, eval) 180 | argsgiven <- names(args) 181 | 182 | with(eargs,{ 183 | 184 | # bbox arg 185 | if('bbox' %in% argsgiven){ 186 | if(!(is.numeric(bbox) && length(bbox) == 4)){ 187 | stop('bounding box improperly specified. see ?get_openstreetmap', call. = F) 188 | } 189 | } 190 | 191 | # scale arg 192 | if('scale' %in% argsgiven){ 193 | if(!(is.numeric(scale) && length(scale) == 1 && 194 | scale == round(scale) && scale > 0)){ 195 | stop('scale must be a positive integer.', call. = F) 196 | } 197 | } 198 | 199 | # messaging arg 200 | if('messaging' %in% argsgiven){ 201 | stopifnot(is.logical(messaging)) 202 | } 203 | 204 | # urlonly arg 205 | if('urlonly' %in% argsgiven){ 206 | stopifnot(is.logical(urlonly)) 207 | } 208 | 209 | # filename arg 210 | if('filename' %in% argsgiven){ 211 | filename_stop <- TRUE 212 | if(is.character(filename) && length(filename) == 1) style_stop <- FALSE 213 | if(filename_stop) stop('improper filename specification, see ?get_googlemap.', call. = F) 214 | } 215 | 216 | # color arg checked by match.arg 217 | 218 | 219 | }) # end with 220 | } 221 | -------------------------------------------------------------------------------- /man/get_stamenmap.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_stamenmap.R 3 | \name{get_stamenmap} 4 | \alias{get_stamenmap} 5 | \title{Get a Stamen Map} 6 | \usage{ 7 | get_stamenmap(bbox = c(left = -95.80204, bottom = 29.38048, right = -94.92313, 8 | top = 30.14344), zoom = 10, maptype = c("terrain", "terrain-background", 9 | "terrain-labels", "terrain-lines", "toner", "toner-2010", "toner-2011", 10 | "toner-background", "toner-hybrid", "toner-labels", "toner-lines", 11 | "toner-lite", "watercolor"), crop = TRUE, messaging = FALSE, 12 | urlonly = FALSE, color = c("color", "bw"), force = FALSE, 13 | where = tempdir(), ...) 14 | } 15 | \arguments{ 16 | \item{bbox}{a bounding box in the format c(lowerleftlon, 17 | lowerleftlat, upperrightlon, upperrightlat).} 18 | 19 | \item{zoom}{a zoom level} 20 | 21 | \item{maptype}{terrain, terrain-background, terrain-labels, 22 | terrain-lines, toner, toner-2010, toner-2011, toner-background, 23 | toner-hybrid, toner-labels, toner-lines, toner-lite, or 24 | watercolor.} 25 | 26 | \item{crop}{crop raw map tiles to specified bounding box} 27 | 28 | \item{messaging}{turn messaging on/off} 29 | 30 | \item{urlonly}{return url only} 31 | 32 | \item{color}{color or black-and-white (use force = TRUE if you've 33 | already downloaded the images)} 34 | 35 | \item{force}{if the map is on file, should a new map be looked 36 | up?} 37 | 38 | \item{where}{where should the file drawer be located (without 39 | terminating "/")} 40 | 41 | \item{...}{...} 42 | } 43 | \value{ 44 | a ggmap object (a classed raster object with a bounding 45 | box attribute) 46 | } 47 | \description{ 48 | \code{get_stamenmap} accesses a tile server for Stamen Maps and 49 | downloads/stitches map tiles/formats a map image. Note that 50 | Stamen maps don't cover the entire world, e.g. 51 | \url{http://tile.stamen.com/terrain/#4/30.28/-87.21} 52 | } 53 | \examples{ 54 | 55 | \dontrun{ # to diminish run check time 56 | 57 | 58 | ##### basic usage 59 | ######################################## 60 | 61 | place <- "baylor science building" 62 | google <- get_googlemap(place, zoom = 15) 63 | ggmap(google) 64 | 65 | # grab the bounding box 66 | bbox <- bb2bbox(attr(google, "bb")) 67 | 68 | # and pull stamen map tiles 69 | ggmap(get_stamenmap(bbox, zoom = 13)) 70 | ggmap(get_stamenmap(bbox, zoom = 14)) 71 | ggmap(get_stamenmap(bbox, zoom = 15)) 72 | # ggmap(get_stamenmap(bbox, zoom = 16)) 73 | # ggmap(get_stamenmap(bbox, zoom = 17)) 74 | 75 | 76 | 77 | # since mid-2016, stamen's terrain tileset is available for 78 | # the entire globe 79 | place <- "mount everest" 80 | (google <- get_googlemap(place, zoom = 9)) 81 | ggmap(google) 82 | bbox_everest <- c(left = 86.05, bottom = 27.21, right = 87.81, top = 28.76) 83 | ggmap(get_stamenmap(bbox_everest, zoom = 9)) 84 | 85 | 86 | # note that the osm code may not run due to overloaded 87 | # servers. 88 | 89 | ##### maptypes 90 | ######################################## 91 | 92 | place <- "rio de janeiro" 93 | google <- get_googlemap(place, zoom = 10) 94 | ggmap(google) 95 | bbox <- bb2bbox(attr(google, "bb")) 96 | 97 | 98 | ggmap(get_stamenmap(bbox, maptype = "terrain")) 99 | ggmap(get_stamenmap(bbox, maptype = "terrain-background")) 100 | ggmap(get_stamenmap(bbox, maptype = "terrain-labels")) 101 | ggmap(get_stamenmap(bbox, maptype = "terrain-lines")) 102 | ggmap(get_stamenmap(bbox, maptype = "toner")) 103 | ggmap(get_stamenmap(bbox, maptype = "toner-2010")) 104 | ggmap(get_stamenmap(bbox, maptype = "toner-2011")) 105 | ggmap(get_stamenmap(bbox, maptype = "toner-background")) 106 | ggmap(get_stamenmap(bbox, maptype = "toner-hybrid")) 107 | ggmap(get_stamenmap(bbox, maptype = "toner-labels")) 108 | ggmap(get_stamenmap(bbox, maptype = "toner-lines")) 109 | ggmap(get_stamenmap(bbox, maptype = "toner-lite")) 110 | ggmap(get_stamenmap(bbox, maptype = "watercolor")) 111 | 112 | ggmap(get_stamenmap(bbox, maptype = "watercolor", zoom = 11), extent = "device") 113 | ggmap(get_stamenmap(bbox, maptype = "watercolor", zoom = 12), extent = "device") 114 | ggmap(get_stamenmap(bbox, maptype = "watercolor", zoom = 13), extent = "device") 115 | ggmap(get_stamenmap(bbox, maptype = "watercolor", zoom = 14), extent = "device") 116 | ggmap(get_stamenmap(bbox, maptype = "watercolor", zoom = 15), extent = "device") 117 | # ggmap(get_stamenmap(bbox, maptype = "watercolor", zoom = 16), extent = "device") 118 | # ggmap(get_stamenmap(bbox, maptype = "watercolor", zoom = 17), extent = "device") 119 | # ggmap(get_stamenmap(bbox, maptype = "watercolor", zoom = 18), extent = "device") 120 | 121 | stamen <- get_stamenmap(bbox, zoom = 15) 122 | ggmap(stamen) + 123 | geom_point(aes(x = lon, y = lat), data = gc, colour = "red", size = 2) 124 | 125 | stamen <- get_stamenmap(bbox, zoom = 15, crop = FALSE) 126 | ggmap(stamen) + 127 | geom_point(aes(x = lon, y = lat), data = gc, colour = "red", size = 2) 128 | 129 | 130 | 131 | ggmap(get_stamenmap(bbox, zoom = 15, maptype = "watercolor"))+ 132 | geom_point(aes(x = lon, y = lat), data = gc, colour = "red", size = 2) 133 | 134 | ggmap(get_stamenmap(bbox, zoom = 15, maptype = "toner"))+ 135 | geom_point(aes(x = lon, y = lat), data = gc, colour = "red", size = 2) 136 | 137 | 138 | # here's an interesting example: 139 | us <- c(left = -125, bottom = 25.75, right = -67, top = 49) 140 | map <- get_stamenmap(us, zoom = 5, maptype = "toner-labels") 141 | ggmap(map) 142 | 143 | 144 | 145 | # accuracy check - white house 146 | gc <- geocode("the white house") 147 | 148 | qmap("the white house", zoom = 16) + 149 | geom_point(aes(x = lon, y = lat), data = gc, colour = "red", size = 3) 150 | 151 | qmap("the white house", zoom = 16, source = "stamen", maptype = "terrain") + 152 | geom_point(aes(x = lon, y = lat), data = gc, colour = "red", size = 3) 153 | 154 | 155 | 156 | 157 | 158 | # accuracy check - statue of liberty 159 | # see https://github.com/dkahle/ggmap/issues/32 160 | 161 | gc <- geocode("statue of liberty") 162 | 163 | googMapZ10 <- get_googlemap(center = as.numeric(gc)) 164 | bbZ10 <- attr(googMapZ10, "bb") 165 | stamMapZ10 <- get_stamenmap(bb2bbox(bbZ10)) 166 | 167 | ggmap(googMapZ10) + 168 | geom_point( 169 | aes(x = lon, y = lat), 170 | data = gc, colour = "red", size = 3 171 | ) 172 | 173 | ggmap(stamMapZ10) + 174 | geom_point( 175 | aes(x = lon, y = lat), 176 | data = gc, colour = "red", size = 3 177 | ) 178 | 179 | 180 | # using a higher zoom 181 | googMapZ15 <- get_googlemap(center = as.numeric(gc), zoom = 15) 182 | bbZ15 <- attr(googMapZ15, "bb") 183 | stamMapZ15 <- get_stamenmap(bb2bbox(bbZ15), 184 | zoom = calc_zoom(bb2bbox(bbZ15)) 185 | ) 186 | 187 | ggmap(googMapZ15) + 188 | geom_point( 189 | aes(x = lon, y = lat), 190 | data = gc, colour = "red", size = 3 191 | ) 192 | 193 | ggmap(stamMapZ15) + 194 | geom_point( 195 | aes(x = lon, y = lat), 196 | data = gc, colour = "red", size = 3 197 | ) 198 | 199 | 200 | # using a lower zoom 201 | googMapZ5 <- get_googlemap(center = as.numeric(gc), zoom = 4) 202 | bbZ5 <- attr(googMapZ5, "bb") 203 | stamMapZ5 <- get_stamenmap(bb2bbox(bbZ5), 204 | zoom = calc_zoom(bb2bbox(bbZ5)) 205 | ) 206 | 207 | ggmap(googMapZ5) + 208 | geom_point( 209 | aes(x = lon, y = lat), 210 | data = gc, colour = "red", size = 3 211 | ) 212 | 213 | ggmap(stamMapZ5) + 214 | geom_point( 215 | aes(x = lon, y = lat), 216 | data = gc, colour = "red", size = 3 217 | ) 218 | 219 | 220 | stamMapZ5unCropped <- get_stamenmap(bb2bbox(bbZ5), 221 | zoom = calc_zoom(bb2bbox(bbZ5)), 222 | crop = FALSE) 223 | 224 | ggmap(stamMapZ5unCropped) + 225 | geom_point( 226 | aes(x = lon, y = lat), 227 | data = gc, colour = "red", size = 3 228 | ) 229 | 230 | qmap(location = c(lon = -74.0445, lat = 40.68925), 231 | zoom = 16, source = "stamen") + 232 | geom_point(aes(x = lon, y = lat), data = gc, colour = "red", size = 3) 233 | 234 | } # end dontrun 235 | 236 | } 237 | \seealso{ 238 | \url{http://maps.stamen.com/#watercolor}, 239 | \code{\link{ggmap}} 240 | } 241 | -------------------------------------------------------------------------------- /R/trek.R: -------------------------------------------------------------------------------- 1 | #' Grab a trek from Google 2 | #' 3 | #' Grab a trek from Google that will plot over the roadways. Note 4 | #' that in most cases by using this function you are agreeing to the 5 | #' Google Maps API Terms of Service at 6 | #' https://developers.google.com/maps/terms. 7 | #' 8 | #' @param from name of origin addresses in a data frame (vector 9 | #' accepted) 10 | #' @param to name of destination addresses in a data frame (vector 11 | #' accepted) 12 | #' @param output amount of output 13 | #' @param mode driving, bicycling, walking, or transit 14 | #' @param alternatives should more than one route be provided? 15 | #' @param units "metric" 16 | #' @param messaging turn messaging on/off 17 | #' @param urlonly return only the url? 18 | #' @param override_limit override the current query count 19 | #' (.GoogleRouteQueryCount) 20 | #' @param ext domain extension (e.g. "com", "co.nz") 21 | #' @param inject character string to add to the url 22 | #' @param ... ... 23 | #' @return a data frame (output="simple") or all of the geocoded 24 | #' information (output="all") 25 | #' @author David Kahle \email{david.kahle@@gmail.com} with the key 26 | #' decoding algorithm due to stackoverflow user akhmed 27 | #' @seealso 28 | #' \url{https://developers.google.com/maps/documentation/directions/}, 29 | #' \url{http://stackoverflow.com/questions/30270011/ggmap-route-finding-doesnt-stay-on-roads}, 30 | #' \code{\link{route}}, \code{\link{routeQueryCheck}} 31 | #' \code{\link{register_google}} 32 | #' @export 33 | #' @examples 34 | #' 35 | #' \dontrun{ # to cut down on check time 36 | #' 37 | #' from <- "houston, texas" 38 | #' to <- "waco, texas" 39 | #' route_df <- route(from, to, structure = "route") 40 | #' trek_df <- trek(from, to, structure = "route") 41 | #' qmap("college station, texas", zoom = 8) + 42 | #' geom_path( 43 | #' aes(x = lon, y = lat), colour = "red", 44 | #' size = 1.5, alpha = .5, 45 | #' data = route_df, lineend = "round" 46 | #' ) + 47 | #' geom_path( 48 | #' aes(x = lon, y = lat), colour = "blue", 49 | #' size = 1.5, alpha = .5, 50 | #' data = trek_df, lineend = "round" 51 | #' ) 52 | #' 53 | #' 54 | #' 55 | #' from <- "rice university houston texas" 56 | #' to <- "1001 Bissonnet St, Houston, TX 77005" 57 | #' trek_df <- trek(from, to) 58 | #' qmplot(lon, lat, data = trek_df, geom = "path", maptype = "terrain", 59 | #' color = I("red"), size = I(2), alpha = I(.5) 60 | #' ) 61 | #' 62 | #' trek_df <- trek(from, to, mode = "walking") 63 | #' qmplot(lon, lat, data = trek_df, geom = "path", maptype = "terrain", 64 | #' color = I("red"), size = I(2), alpha = I(.5) 65 | #' ) 66 | #' 67 | #' trek_df <- trek(from, to, mode = "transit") 68 | #' qmplot(lon, lat, data = trek_df, geom = "path", maptype = "terrain", 69 | #' color = I("red"), size = I(2), alpha = I(.5) 70 | #' ) 71 | #' 72 | #' 73 | #' from <- "houston, texas"; to <- "waco, texas" 74 | #' trek_df <- trek(from, to, alternatives = TRUE) 75 | #' qmplot(lon, lat, data = trek_df, geom = "path", 76 | #' color = route, size = I(2), alpha = I(.5) 77 | #' ) 78 | #' 79 | #' 80 | #' from <- "los angeles, california"; to <- "new york, new york" 81 | #' trek_df <- trek(from, to, alternatives = TRUE) 82 | #' qmplot(lon, lat, data = trek_df, geom = "path", 83 | #' color = route, size = I(2), maptype = "terrain", 84 | #' zoom = 5 85 | #' ) + facet_wrap(~ route, ncol = 1) 86 | #' 87 | #' 88 | #' 89 | #' 90 | #' } 91 | #' 92 | trek <- function(from, to, mode = c("driving","walking","bicycling", "transit"), 93 | output = c("simple","all"), alternatives = FALSE, units = "metric", 94 | messaging = FALSE, urlonly = FALSE, override_limit = FALSE, 95 | ext = "com", inject = "", ...) 96 | { 97 | 98 | # check parameters 99 | if(is.numeric(from) && length(from) == 2) from <- revgeocode(from) 100 | stopifnot(is.character(from)) 101 | if(is.numeric(to) && length(to) == 2) to <- revgeocode(to) 102 | stopifnot(is.character(to)) 103 | mode <- match.arg(mode) 104 | output <- match.arg(output) 105 | stopifnot(is.logical(alternatives)) 106 | stopifnot(is.logical(messaging)) 107 | 108 | 109 | # format url 110 | origin <- URLencode(from, reserved = TRUE) 111 | destination <- URLencode(to, reserved = TRUE) 112 | posturl <- paste(fmteq(origin), fmteq(destination), fmteq(mode), fmteq(units), 113 | fmteq(alternatives, tolower), sep = "&" 114 | ) 115 | 116 | # add google account stuff 117 | if (has_goog_client() && has_goog_signature()) { 118 | client <- goog_client() 119 | signature <- goog_signature() 120 | posturl <- paste(posturl, fmteq(client), fmteq(signature), sep = "&") 121 | } else if (has_goog_key()) { 122 | key <- goog_key() 123 | posturl <- paste(posturl, fmteq(key), sep = "&") 124 | } 125 | 126 | # construct url 127 | url_string <- paste0( 128 | sprintf("https://maps.googleapis.%s/maps/api/directions/json?", ext), 129 | posturl 130 | ) 131 | 132 | # inject any remaining stuff 133 | if(inject != "") url_string <- paste(url_string, inject, sep = "&") 134 | 135 | # encode 136 | url_string <- URLencode( enc2utf8(url_string) ) 137 | if(urlonly) return(url_string) 138 | 139 | 140 | # check/update google query limit 141 | check_route_query_limit(url_string, elems = 1, 142 | override = override_limit, messaging = messaging) 143 | 144 | 145 | # distance lookup 146 | if(messaging) message("trying url ", url_string) 147 | connect <- url(url_string) 148 | tree <- fromJSON(paste(readLines(connect), collapse = "")) 149 | close(connect) 150 | 151 | # return output = "all" 152 | if(output == "all") return(tree) 153 | 154 | # return NA if zero results are found 155 | if (tree$status == "ZERO_RESULTS") { 156 | warning("No route was returned from Google.") 157 | return(NA) 158 | } 159 | 160 | # message user 161 | message("Source : ", url_string) 162 | 163 | # extract output from tree and format 164 | treks <- llply(tree$routes, function(route){ 165 | decode_google_route( route$overview_polyline$points ) 166 | }) 167 | 168 | # label routes 169 | for (k in seq_along(treks)) { 170 | treks[[k]]$route <- LETTERS[k] 171 | } 172 | 173 | # bind and return 174 | dplyr::bind_rows(treks) 175 | } 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | # the following is from @akmed (stackoverflow) 212 | # see http://stackoverflow.com/questions/30270011/ggmap-route-finding-doesnt-stay-on-roads 213 | decode_google_route <- function(encoded){ 214 | 215 | vlen <- nchar(encoded) 216 | vindex <- 0 217 | varray <- NULL 218 | vlat <- 0 219 | vlng <- 0 220 | 221 | while(vindex < vlen){ 222 | vb <- NULL 223 | vshift <- 0 224 | vresult <- 0 225 | repeat{ 226 | if(vindex + 1 <= vlen){ 227 | vindex <- vindex + 1 228 | vb <- as.integer(charToRaw(substr(encoded, vindex, vindex))) - 63 229 | } 230 | 231 | vresult <- bitOr(vresult, bitShiftL(bitAnd(vb, 31), vshift)) 232 | vshift <- vshift + 5 233 | if(vb < 32) break 234 | } 235 | 236 | dlat <- ifelse(bitAnd(vresult, 1), -(bitShiftR(vresult, 1)+1), bitShiftR(vresult, 1)) 237 | vlat <- vlat + dlat 238 | 239 | vshift <- 0 240 | vresult <- 0 241 | repeat{ 242 | if(vindex + 1 <= vlen) { 243 | vindex <- vindex+1 244 | vb <- as.integer(charToRaw(substr(encoded, vindex, vindex))) - 63 245 | } 246 | 247 | vresult <- bitOr(vresult, bitShiftL(bitAnd(vb, 31), vshift)) 248 | vshift <- vshift + 5 249 | if(vb < 32) break 250 | } 251 | 252 | dlng <- ifelse(bitAnd(vresult, 1), -(bitShiftR(vresult, 1)+1), bitShiftR(vresult, 1)) 253 | vlng <- vlng + dlng 254 | 255 | varray <- rbind(varray, c(vlat * 1e-5, vlng * 1e-5)) 256 | } 257 | coords <- data.frame(varray) 258 | names(coords) <- c("lat", "lon") 259 | coords 260 | } 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | -------------------------------------------------------------------------------- /R/mapdist.R: -------------------------------------------------------------------------------- 1 | #' Compute map distances using Google 2 | #' 3 | #' Compute map distances using Google Maps. Note that in most cases 4 | #' by using this function you are agreeing to the Google Maps API 5 | #' Terms of Service at https://developers.google.com/maps/terms. 6 | #' 7 | #' @param from name of origin addresses in a data frame (vector 8 | #' accepted) 9 | #' @param to name of destination addresses in a data frame (vector 10 | #' accepted) 11 | #' @param output amount of output 12 | #' @param mode driving, bicycling, or walking 13 | #' @param messaging turn messaging on/off 14 | #' @param language language 15 | #' @param urlonly return only the url? 16 | #' @param override_limit override the current query count 17 | #' (.GoogleDistQueryCount) 18 | #' @param ext domain extension (e.g. "com", "co.nz") 19 | #' @param inject character string to add to the url 20 | #' @param ... ... 21 | #' @return a data frame (output="simple") or all of the geocoded 22 | #' information (output="all") 23 | #' @author David Kahle \email{david.kahle@@gmail.com} 24 | #' @details if parameters from and to are specified as geographic 25 | #' coordinates, they are reverse geocoded with revgeocode. note 26 | #' that the google maps api limits to 2500 element queries a day. 27 | #' @seealso 28 | #' \url{http://code.google.com/apis/maps/documentation/distancematrix/} 29 | #' @export 30 | #' @examples 31 | #' 32 | #' \dontrun{# online queries draw R CMD check times 33 | #' 34 | #' mapdist("waco, texas", "houston, texas") 35 | #' 36 | #' from <- c("houston, texas", "dallas") 37 | #' to <- "waco, texas" 38 | #' mapdist(from, to) 39 | #' mapdist(from, to, mode = "bicycling") 40 | #' mapdist(from, to, mode = "walking") 41 | #' 42 | #' # google requires a key for mode="transit" 43 | #' register_google(key = "[your key here]") 44 | #' from <- "city hall houston texas" 45 | #' to <- "nrg stadium houston texas" 46 | #' mapdist(from, to, mode = "transit") 47 | #' 48 | #' from <- c("houston", "houston", "dallas") 49 | #' to <- c("waco, texas", "san antonio", "houston") 50 | #' mapdist(from, to) 51 | #' 52 | #' 53 | #' # geographic coordinates are accepted as well 54 | #' (wh <- as.numeric(geocode("the white house, dc"))) 55 | #' (lm <- as.numeric(geocode("lincoln memorial washington dc"))) 56 | #' mapdist(wh, lm, mode = "walking") 57 | #' distQueryCheck() 58 | #' 59 | #' } 60 | #' 61 | mapdist <- function(from, to, mode = c("driving","walking","bicycling","transit"), 62 | output = c("simple","all"), messaging = FALSE, 63 | language = "en-EN", urlonly = FALSE, override_limit = FALSE, 64 | ext = "com", inject = "", ...) 65 | { 66 | 67 | # check parameters 68 | if(is.numeric(from) && length(from) == 2) from <- revgeocode(from) 69 | stopifnot(is.character(from)) 70 | if(is.numeric(to) && length(to) == 2) to <- revgeocode(to) 71 | stopifnot(is.character(to)) 72 | from_to_df <- data.frame(from = from, to = to, stringsAsFactors = FALSE) 73 | mode <- match.arg(mode) 74 | output <- match.arg(output) 75 | stopifnot(is.logical(messaging)) 76 | 77 | 78 | getdists <- function(df){ 79 | 80 | # format basic url 81 | origins <- URLencode(df$from[1], reserved = TRUE) 82 | destinations <- URLencode(df$to, reserved = TRUE) 83 | posturl <- paste( 84 | fmteq(origins), fmteq(destinations, paste, collapse = "|"), 85 | fmteq(mode), fmteq(language), 86 | sep = "&" 87 | ) 88 | 89 | # add google account stuff 90 | if (has_goog_client() && has_goog_signature()) { 91 | client <- goog_client() 92 | signature <- goog_signature() 93 | posturl <- paste(posturl, fmteq(client), fmteq(signature), sep = "&") 94 | } else if (has_goog_key()) { 95 | key <- goog_key() 96 | posturl <- paste(posturl, fmteq(key), sep = "&") 97 | } 98 | 99 | # join base url to posturl 100 | url_string <- paste0( 101 | sprintf("https://maps.googleapis.%s/maps/api/distancematrix/json?", ext), 102 | posturl 103 | ) 104 | 105 | # inject 106 | if(inject != "") url_string <- paste(url_string, inject, sep = "&") 107 | 108 | # encode 109 | url_string <- URLencode( enc2utf8(url_string) ) 110 | if(urlonly) return(url_string) 111 | 112 | # check if query is too long 113 | if(nchar(url_string) >= 2048){ 114 | n <- nrow(df) 115 | half_df <- floor(n/2) 116 | return( 117 | rbind( 118 | getdists(df[half_df,]), 119 | getdists(df[(half_df+1):n,]) 120 | ) 121 | ) 122 | } 123 | 124 | # check/update google query limit 125 | check_dist_query_limit(url_string, elems = nrow(df), 126 | override = override_limit, messaging = messaging) 127 | 128 | 129 | # distance lookup 130 | if(messaging) message("trying url ", url_string) 131 | connect <- url(url_string); on.exit(close(connect), add = TRUE) 132 | tree <- fromJSON(paste(readLines(connect), collapse = "")) 133 | check_google_for_error(tree) 134 | 135 | 136 | # message user 137 | message(paste0("Source : ", url_string)) 138 | 139 | # label destinations - first check if all were found 140 | if(length(df$to) != length(tree$destination_addresses)){ 141 | message("matching was not perfect, returning what was found.") 142 | names( tree$rows[[c(1,1)]] ) <- tree$destination_addresses 143 | output <<- "all" 144 | # stringdist::amatch(df$to, tree$destination_addresses, maxDist = 10) 145 | } else { 146 | names( tree$rows[[c(1,1)]] ) <- df$to 147 | } 148 | 149 | # return 150 | tree$rows[[c(1,1)]] 151 | } 152 | 153 | out <- dlply(from_to_df, "from", getdists) 154 | 155 | # return all 156 | if(output == "all") return(out) 157 | 158 | 159 | 160 | # format output 161 | out <- 162 | ldply(out, function(oneFromList){ 163 | ldply(oneFromList, function(oneToList){ 164 | data.frame( 165 | m = oneToList$distance$value, 166 | km = oneToList$distance$value/1000, 167 | miles = 0.0006214 * oneToList$distance$value, 168 | seconds = oneToList$duration$value, 169 | minutes = oneToList$duration$value / 60, 170 | hours = oneToList$duration$value / 3600 171 | ) 172 | }) 173 | }) 174 | 175 | names(out) <- c("from", "to", names(out)[3:ncol(out)]) 176 | 177 | # "simple" return 178 | suppressMessages(join(from_to_df, out)) 179 | } 180 | 181 | 182 | 183 | 184 | check_dist_query_limit <- function(url_string, elems, override, messaging){ 185 | 186 | .GoogleDistQueryCount <- NULL; rm(.GoogleDistQueryCount); # R CMD check trick 187 | 188 | if(exists(".GoogleDistQueryCount", .GlobalEnv)){ 189 | 190 | .GoogleDistQueryCount <<- dplyr::filter(.GoogleDistQueryCount, time >= Sys.time() - 24*60*60) 191 | 192 | # limit per 24 hours 193 | dayQueriesUsed <- sum(.GoogleDistQueryCount$elements) 194 | if(dayQueriesUsed + elems > goog_day_limit()){ 195 | message("query max exceeded, see ?mapdist. current total = ", dayQueriesUsed) 196 | if(!override) return("stop") 197 | } 198 | 199 | # limit per second 200 | secondQueriesUsed <- with(.GoogleDistQueryCount, sum(elements[time >= Sys.time() - 1])) 201 | if(secondQueriesUsed + elems > goog_second_limit()){ 202 | message(".", appendLF = FALSE) 203 | Sys.sleep(.2) # can do better 204 | } 205 | 206 | # append to .GoogleDistQueryCount 207 | .GoogleDistQueryCount <<- bind_rows( 208 | .GoogleDistQueryCount, 209 | data.frame( 210 | time = Sys.time(), url = url_string, 211 | elements = elems, stringsAsFactors = FALSE 212 | ) 213 | ) 214 | 215 | 216 | } else { 217 | 218 | .GoogleDistQueryCount <<- data.frame( 219 | time = Sys.time(), url = url_string, 220 | elements = elems, stringsAsFactors = FALSE 221 | ) 222 | 223 | } 224 | } 225 | 226 | 227 | 228 | #' Check Google Maps Distance Matrix API query limit 229 | #' 230 | #' Check Google Maps Distance Matrix API query limit 231 | #' 232 | #' @return a data frame 233 | #' @author David Kahle \email{david.kahle@@gmail.com} 234 | #' @seealso \url{http://code.google.com/apis/maps/documentation/distancematrix/} 235 | #' @export 236 | #' @examples 237 | #' distQueryCheck() 238 | distQueryCheck <- function(){ 239 | 240 | .GoogleDistQueryCount <- NULL; rm(.GoogleDistQueryCount); # R CMD check trick 241 | 242 | if(exists(".GoogleDistQueryCount", .GlobalEnv)){ 243 | 244 | remaining <- goog_day_limit() - sum( 245 | dplyr::filter(.GoogleDistQueryCount, time >= Sys.time() - 24*60*60)$elements 246 | ) 247 | message(remaining, " mapdist queries remaining.") 248 | 249 | } else { 250 | 251 | remaining <- goog_day_limit() 252 | message(remaining, " mapdist queries remaining.") 253 | 254 | } 255 | 256 | invisible(remaining) 257 | } 258 | -------------------------------------------------------------------------------- /man/qmplot.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/qmplot.R 3 | \name{qmplot} 4 | \alias{qmplot} 5 | \title{Quick map plot} 6 | \usage{ 7 | qmplot(x, y, ..., data, zoom, source = "stamen", maptype = "toner-lite", 8 | extent = "device", legend = "right", padding = 0.02, force = FALSE, 9 | darken = c(0, "black"), mapcolor = "color", facets = NULL, 10 | margins = FALSE, geom = "auto", stat = list(NULL), 11 | position = list(NULL), xlim = c(NA, NA), ylim = c(NA, NA), 12 | main = NULL, f = 0.05, xlab = "Longitude", ylab = "Latitude") 13 | } 14 | \arguments{ 15 | \item{x}{longitude values} 16 | 17 | \item{y}{latitude values} 18 | 19 | \item{...}{other aesthetics passed for each layer} 20 | 21 | \item{data}{data frame to use (optional). If not specified, will 22 | create one, extracting vectors from the current environment.} 23 | 24 | \item{zoom}{map zoom, see \code{\link{get_map}}} 25 | 26 | \item{source}{map source, see \code{\link{get_map}}} 27 | 28 | \item{maptype}{map type, see \code{\link{get_map}}} 29 | 30 | \item{extent}{how much of the plot should the map take up? 31 | "normal", "panel", or "device" (default)} 32 | 33 | \item{legend}{"left", "right" (default), "bottom", "top", 34 | "bottomleft", "bottomright", "topleft", "topright", "none" 35 | (used with extent = "device")} 36 | 37 | \item{padding}{distance from legend to corner of the plot (used 38 | with extent = "device")} 39 | 40 | \item{force}{force new map (don't use archived version)} 41 | 42 | \item{darken}{vector of the form c(number, color), where number 43 | is in [0, 1] and color is a character string indicating the 44 | color of the darken. 0 indicates no darkening, 1 indicates a 45 | black-out.} 46 | 47 | \item{mapcolor}{color ("color") or black-and-white ("bw")} 48 | 49 | \item{facets}{faceting formula to use. Picks 50 | \code{\link{facet_wrap}} or \code{\link{facet_grid}} depending 51 | on whether the formula is one sided or two-sided} 52 | 53 | \item{margins}{whether or not margins will be displayed} 54 | 55 | \item{geom}{character vector specifying geom to use. defaults to 56 | "point"} 57 | 58 | \item{stat}{character vector specifying statistics to use} 59 | 60 | \item{position}{character vector giving position adjustment to 61 | use} 62 | 63 | \item{xlim}{limits for x axis} 64 | 65 | \item{ylim}{limits for y axis} 66 | 67 | \item{main}{character vector or expression for plot title} 68 | 69 | \item{f}{number specifying the fraction by which the range should 70 | be extended} 71 | 72 | \item{xlab}{character vector or expression for x axis label} 73 | 74 | \item{ylab}{character vector or expression for y axis label} 75 | } 76 | \description{ 77 | \code{qmplot} is the ggmap equivalent to the ggplot2 function 78 | qplot and allows for the quick plotting of maps with 79 | data/models/etc. 80 | } 81 | \examples{ 82 | 83 | \dontrun{ # these are skipped to conserve R check time 84 | 85 | qmplot(lon, lat, data = crime) 86 | 87 | 88 | # only violent crimes 89 | violent_crimes <- subset(crime, 90 | offense != "auto theft" & 91 | offense != "theft" & 92 | offense != "burglary" 93 | ) 94 | 95 | # rank violent crimes 96 | violent_crimes$offense <- factor( 97 | violent_crimes$offense, 98 | levels = c("robbery", "aggravated assault", "rape", "murder") 99 | ) 100 | 101 | # restrict to downtown 102 | violent_crimes <- subset(violent_crimes, 103 | -95.39681 <= lon & lon <= -95.34188 & 104 | 29.73631 <= lat & lat <= 29.78400 105 | ) 106 | 107 | theme_set(theme_bw()) 108 | 109 | qmplot(lon, lat, data = violent_crimes, colour = offense, 110 | size = I(3.5), alpha = I(.6), legend = "topleft") 111 | 112 | qmplot(lon, lat, data = violent_crimes, geom = c("point","density2d")) 113 | qmplot(lon, lat, data = violent_crimes) + facet_wrap(~ offense) 114 | qmplot(lon, lat, data = violent_crimes, extent = "panel") + facet_wrap(~ offense) 115 | qmplot(lon, lat, data = violent_crimes, extent = "panel", colour = offense, darken = .4) + 116 | facet_wrap(~ month) 117 | 118 | 119 | 120 | 121 | qmplot(long, lat, xend = long + delta_long, 122 | color = I("red"), yend = lat + delta_lat, data = seals, 123 | geom = "segment", zoom = 5) 124 | 125 | qmplot(long, lat, xend = long + delta_long, maptype = "watercolor", 126 | yend = lat + delta_lat, data = seals, 127 | geom = "segment", zoom = 6) 128 | 129 | qmplot(long, lat, xend = long + delta_long, maptype = "terrain", 130 | yend = lat + delta_lat, data = seals, 131 | geom = "segment", zoom = 6) 132 | 133 | 134 | qmplot(lon, lat, data = wind, size = I(.5), alpha = I(.5)) + 135 | ggtitle("NOAA Wind Report Sites") 136 | 137 | # thin down data set... 138 | s <- seq(1, 227, 8) 139 | thinwind <- subset(wind, 140 | lon \%in\% unique(wind$lon)[s] & 141 | lat \%in\% unique(wind$lat)[s] 142 | ) 143 | 144 | # for some reason adding arrows to the following plot bugs 145 | theme_set(theme_bw(18)) 146 | 147 | qmplot(lon, lat, data = thinwind, geom = "tile", fill = spd, alpha = spd, 148 | legend = "bottomleft") + 149 | geom_leg(aes(xend = lon + delta_lon, yend = lat + delta_lat)) + 150 | scale_fill_gradient2("Wind Speed\\nand\\nDirection", 151 | low = "green", mid = scales::muted("green"), high = "red") + 152 | scale_alpha("Wind Speed\\nand\\nDirection", range = c(.1, .75)) + 153 | guides(fill = guide_legend(), alpha = guide_legend()) 154 | 155 | 156 | 157 | 158 | ## kriging 159 | ############################################################ 160 | # the below examples show kriging based on undeclared packages 161 | # to better comply with CRAN's standards, we remove it from 162 | # executing, but leave the code as a kind of case-study 163 | # they also require the rgdal library 164 | 165 | 166 | library(lattice) 167 | library(sp) 168 | library(rgdal) 169 | 170 | # load in and format the meuse dataset (see bivand, pebesma, and gomez-rubio) 171 | data(meuse) 172 | coordinates(meuse) <- c("x", "y") 173 | proj4string(meuse) <- CRS("+init=epsg:28992") 174 | meuse <- spTransform(meuse, CRS("+proj=longlat +datum=WGS84")) 175 | 176 | # plot 177 | plot(meuse) 178 | 179 | m <- data.frame(slot(meuse, "coords"), slot(meuse, "data")) 180 | names(m)[1:2] <- c("lon", "lat") 181 | 182 | qmplot(lon, lat, data = m) 183 | qmplot(lon, lat, data = m, zoom = 14) 184 | 185 | 186 | qmplot(lon, lat, data = m, size = zinc, 187 | zoom = 14, source = "google", maptype = "satellite", 188 | alpha = I(.75), color = I("green"), 189 | legend = "topleft", darken = .2 190 | ) + scale_size("Zinc (ppm)") 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | # load in the meuse.grid dataset (looking toward kriging) 200 | library(gstat) 201 | data(meuse.grid) 202 | coordinates(meuse.grid) <- c("x", "y") 203 | proj4string(meuse.grid) <- CRS("+init=epsg:28992") 204 | meuse.grid <- spTransform(meuse.grid, CRS("+proj=longlat +datum=WGS84")) 205 | 206 | # plot it 207 | plot(meuse.grid) 208 | 209 | mg <- data.frame(slot(meuse.grid, "coords"), slot(meuse.grid, "data")) 210 | names(mg)[1:2] <- c("lon", "lat") 211 | 212 | qmplot(lon, lat, data = mg, shape = I(15), zoom = 14, legend = "topleft") + 213 | geom_point(aes(size = zinc), data = m, color = "green") + 214 | scale_size("Zinc (ppm)") 215 | 216 | 217 | 218 | # interpolate at unobserved locations (i.e. at meuse.grid points) 219 | # pre-define scale for consistency 220 | scale <- scale_color_gradient("Predicted\\nZinc (ppm)", 221 | low = "green", high = "red", lim = c(100, 1850) 222 | ) 223 | 224 | 225 | 226 | # inverse distance weighting 227 | idw <- idw(log(zinc) ~ 1, meuse, meuse.grid, idp = 2.5) 228 | mg$idw <- exp(slot(idw, "data")$var1.pred) 229 | 230 | qmplot(lon, lat, data = mg, shape = I(15), color = idw, 231 | zoom = 14, legend = "topleft", alpha = I(.75), darken = .4 232 | ) + scale 233 | 234 | 235 | 236 | # linear regression 237 | lin <- krige(log(zinc) ~ 1, meuse, meuse.grid, degree = 1) 238 | mg$lin <- exp(slot(lin, "data")$var1.pred) 239 | 240 | qmplot(lon, lat, data = mg, shape = I(15), color = lin, 241 | zoom = 14, legend = "topleft", alpha = I(.75), darken = .4 242 | ) + scale 243 | 244 | 245 | 246 | # trend surface analysis 247 | tsa <- krige(log(zinc) ~ 1, meuse, meuse.grid, degree = 2) 248 | mg$tsa <- exp(slot(tsa, "data")$var1.pred) 249 | 250 | qmplot(lon, lat, data = mg, shape = I(15), color = tsa, 251 | zoom = 14, legend = "topleft", alpha = I(.75), darken = .4 252 | ) + scale 253 | 254 | 255 | 256 | # ordinary kriging 257 | vgram <- variogram(log(zinc) ~ 1, meuse) # plot(vgram) 258 | vgramFit <- fit.variogram(vgram, vgm(1, "Exp", .2, .1)) 259 | ordKrige <- krige(log(zinc) ~ 1, meuse, meuse.grid, vgramFit) 260 | mg$ordKrige <- exp(slot(ordKrige, "data")$var1.pred) 261 | 262 | qmplot(lon, lat, data = mg, shape = I(15), color = ordKrige, 263 | zoom = 14, legend = "topleft", alpha = I(.75), darken = .4 264 | ) + scale 265 | 266 | 267 | 268 | # universal kriging 269 | vgram <- variogram(log(zinc) ~ 1, meuse) # plot(vgram) 270 | vgramFit <- fit.variogram(vgram, vgm(1, "Exp", .2, .1)) 271 | univKrige <- krige(log(zinc) ~ sqrt(dist), meuse, meuse.grid, vgramFit) 272 | mg$univKrige <- exp(slot(univKrige, "data")$var1.pred) 273 | 274 | qmplot(lon, lat, data = mg, shape = I(15), color = univKrige, 275 | zoom = 14, legend = "topleft", alpha = I(.75), darken = .4 276 | ) + scale 277 | 278 | 279 | 280 | # adding observed data layer 281 | qmplot(lon, lat, data = mg, shape = I(15), color = univKrige, 282 | zoom = 14, legend = "topleft", alpha = I(.75), darken = .4 283 | ) + 284 | geom_point( 285 | aes(x = lon, y = lat, size = zinc), 286 | data = m, shape = 1, color = "black" 287 | ) + 288 | scale + 289 | scale_size("Observed\\nLog Zinc") 290 | 291 | 292 | 293 | 294 | 295 | 296 | } # end dontrun 297 | 298 | } 299 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ggmap 3 | ===== 4 | 5 | **ggmap** makes it easy to retrieve raster map tiles from popular online 6 | mapping services like [Google 7 | Maps](https://developers.google.com/maps/documentation/static-maps/?hl=en), 8 | [OpenStreetMap](https://www.openstreetmap.org), [Stamen 9 | Maps](http://maps.stamen.com), and plot them using the 10 | [**ggplot2**](https://github.com/tidyverse/ggplot2) framework: 11 | 12 | ``` r 13 | library("ggmap") 14 | 15 | us <- c(left = -125, bottom = 25.75, right = -67, top = 49) 16 | map <- get_stamenmap(us, zoom = 5, maptype = "toner-lite") 17 | ggmap(map) 18 | ``` 19 | 20 | ![](tools/README-maptypes-1.png) 21 | 22 | ``` r 23 | ggmap(map, extent = "device") 24 | ``` 25 | 26 | ![](tools/README-maptypes-2.png) 27 | 28 | Use `qmplot()` in the same way you’d use `qplot()`, but with a map 29 | automatically added in the background: 30 | 31 | ``` r 32 | library("dplyr") 33 | library("forcats") 34 | 35 | # define helper 36 | `%notin%` <- function(lhs, rhs) !(lhs %in% rhs) 37 | 38 | # reduce crime to violent crimes in downtown houston 39 | violent_crimes <- crime %>% 40 | filter( 41 | offense %notin% c("auto theft", "theft", "burglary"), 42 | -95.39681 <= lon & lon <= -95.34188, 43 | 29.73631 <= lat & lat <= 29.78400 44 | ) %>% 45 | mutate( 46 | offense = fct_drop(offense), 47 | offense = fct_relevel(offense, 48 | c("robbery", "aggravated assault", "rape", "murder") 49 | ) 50 | ) 51 | 52 | # use qmplot to make a scatterplot on a map 53 | qmplot(lon, lat, data = violent_crimes, maptype = "toner-lite", color = I("red")) 54 | ``` 55 | 56 | ![](tools/README-qmplot-1.png) 57 | 58 | All the **ggplot2** geom’s are available. For example, you can make a 59 | contour plot with `geom = "density2d"`: 60 | 61 | ``` r 62 | qmplot(lon, lat, data = violent_crimes, maptype = "toner-lite", geom = "density2d", color = I("red")) 63 | # Using zoom = 14... 64 | ``` 65 | 66 | ![](tools/README-qmplot2-1.png) 67 | 68 | In fact, since **ggmap**’s built on top of **ggplot2**, all your usual 69 | **ggplot2** stuff (geoms, polishing, etc.) will work, and there are some 70 | unique graphing perks **ggmap** brings to the table, too. 71 | 72 | ``` r 73 | robberies <- violent_crimes %>% filter(offense == "robbery") 74 | 75 | qmplot(lon, lat, data = violent_crimes, geom = "blank", 76 | zoom = 15, maptype = "toner-background", darken = .7, legend = "topleft" 77 | ) + 78 | stat_density_2d(aes(fill = ..level..), geom = "polygon", alpha = .3, color = NA) + 79 | scale_fill_gradient2("Robbery\nPropensity", low = "white", mid = "yellow", high = "red", midpoint = 650) 80 | ``` 81 | 82 | ![](tools/README-styling-1.png) 83 | 84 | Faceting works, too: 85 | 86 | ``` r 87 | qmplot(lon, lat, data = violent_crimes, maptype = "toner-background", color = offense) + 88 | facet_wrap(~ offense) 89 | ``` 90 | 91 | ![](tools/README-faceting-1.png) 92 | 93 | For convenience, here are a few maps of Europe: 94 | 95 | ``` r 96 | europe <- c(left = -12, bottom = 35, right = 30, top = 63) 97 | get_stamenmap(europe, zoom = 5) %>% ggmap() 98 | ``` 99 | 100 | ![](tools/README-europe-1.png) 101 | 102 | ``` r 103 | get_stamenmap(europe, zoom = 5, maptype = "toner-lite") %>% ggmap() 104 | ``` 105 | 106 | ![](tools/README-europe-2.png) 107 | 108 | Google Maps and Credentials 109 | --------------------------- 110 | 111 | [Google Maps](http://developers.google.com/maps/terms) can be used just 112 | as easily. However, since Google Maps use a center/zoom specification, 113 | their input is a bit different: 114 | 115 | ``` r 116 | get_googlemap("waco texas", zoom = 12) %>% ggmap() 117 | # Source : https://maps.googleapis.com/maps/api/staticmap?center=waco+texas&zoom=12&size=640x640&scale=2&maptype=terrain 118 | # Source : https://maps.googleapis.com/maps/api/geocode/json?address=waco%20texas 119 | ``` 120 | 121 | ![](tools/README-google_maps-1.png) 122 | 123 | Moreover, you can get various different styles of Google Maps with 124 | **ggmap** (just like Stamen Maps): 125 | 126 | ``` r 127 | get_googlemap("waco texas", zoom = 12, maptype = "satellite") %>% ggmap() 128 | # Source : https://maps.googleapis.com/maps/api/staticmap?center=waco+texas&zoom=12&size=640x640&scale=2&maptype=satellite 129 | # Source : https://maps.googleapis.com/maps/api/geocode/json?address=waco%20texas 130 | ``` 131 | 132 | ![](tools/README-google_styles-1.png) 133 | 134 | ``` r 135 | get_googlemap("waco texas", zoom = 12, maptype = "roadmap") %>% ggmap() 136 | # Source : https://maps.googleapis.com/maps/api/staticmap?center=waco+texas&zoom=12&size=640x640&scale=2&maptype=roadmap 137 | # Source : https://maps.googleapis.com/maps/api/geocode/json?address=waco%20texas 138 | ``` 139 | 140 | ![](tools/README-google_styles-2.png) 141 | 142 | ``` r 143 | get_googlemap("waco texas", zoom = 12, maptype = "hybrid") %>% ggmap() 144 | # Source : https://maps.googleapis.com/maps/api/staticmap?center=waco+texas&zoom=12&size=640x640&scale=2&maptype=hybrid 145 | # Source : https://maps.googleapis.com/maps/api/geocode/json?address=waco%20texas 146 | ``` 147 | 148 | ![](tools/README-google_styles-3.png) 149 | 150 | Google’s geocoding and reverse geocoding API’s are available through 151 | `geocode()` and `revgeocode()`, respectively: 152 | 153 | ``` r 154 | geocode("1301 S University Parks Dr, Waco, TX 76798") 155 | # Source : https://maps.googleapis.com/maps/api/geocode/json?address=1301%20S%20University%20Parks%20Dr%2C%20Waco%2C%20TX%2076798 156 | # lon lat 157 | # 1 -97.1161 31.55099 158 | revgeocode(c(lon = -97.1161, lat = 31.55098)) 159 | # Information from URL : https://maps.googleapis.com/maps/api/geocode/json?latlng=31.55098,-97.1161 160 | # [1] "1301 S University Parks Dr, Waco, TX 76706, USA" 161 | ``` 162 | 163 | There is also a `mutate_geocode()` that works similarly to 164 | [**dplyr**](https://github.com/hadley/dplyr)’s `mutate()` function: 165 | 166 | ``` r 167 | df <- data.frame( 168 | address = c("1600 Pennsylvania Avenue, Washington DC", "", "waco texas"), 169 | stringsAsFactors = FALSE 170 | ) 171 | df %>% mutate_geocode(address) 172 | # Source : https://maps.googleapis.com/maps/api/geocode/json?address=1600%20Pennsylvania%20Avenue%2C%20Washington%20DC 173 | # Source : https://maps.googleapis.com/maps/api/geocode/json?address=waco%20texas 174 | # address lon lat 175 | # 1 1600 Pennsylvania Avenue, Washington DC -77.03657 38.89766 176 | # 2 NA NA 177 | # 3 waco texas -97.14667 31.54933 178 | ``` 179 | 180 | Treks use Google’s routing API to give you routes (`route()` and 181 | `trek()` give slightly different results; the latter hugs roads): 182 | 183 | ``` r 184 | trek_df <- trek("houson, texas", "waco, texas", structure = "route") 185 | # Source : https://maps.googleapis.com/maps/api/directions/json?origin=houson%2C%20texas&destination=waco%2C%20texas&mode=driving&units=metric&alternatives=false 186 | qmap("college station, texas", zoom = 8) + 187 | geom_path( 188 | aes(x = lon, y = lat), colour = "blue", 189 | size = 1.5, alpha = .5, 190 | data = trek_df, lineend = "round" 191 | ) 192 | # Source : https://maps.googleapis.com/maps/api/staticmap?center=college+station,+texas&zoom=8&size=640x640&scale=2&maptype=terrain&language=en-EN 193 | # Source : https://maps.googleapis.com/maps/api/geocode/json?address=college%20station%2C%20texas 194 | ``` 195 | 196 | ![](tools/README-route_trek-1.png) 197 | 198 | (They also provide information on how long it takes to get from point A 199 | to point B.) 200 | 201 | Map distances, in both length and anticipated time, can be computed with 202 | `mapdist()`). Moreover the function is vectorized: 203 | 204 | ``` r 205 | mapdist(c("houston, texas", "dallas"), "waco, texas") 206 | # Source : https://maps.googleapis.com/maps/api/distancematrix/json?origins=dallas&destinations=waco%2C%20texas&mode=driving&language=en-EN 207 | # Source : https://maps.googleapis.com/maps/api/distancematrix/json?origins=houston%2C%20texas&destinations=waco%2C%20texas&mode=driving&language=en-EN 208 | # from to m km miles seconds minutes 209 | # 1 houston, texas waco, texas 299319 299.319 185.99683 10539 175.65000 210 | # 2 dallas waco, texas 152481 152.481 94.75169 5360 89.33333 211 | # hours 212 | # 1 2.927500 213 | # 2 1.488889 214 | ``` 215 | 216 | ### Google credentialing 217 | 218 | If you have a Google API key, you can exceed the standard limits Google 219 | places on queries. By default, when **ggmap** is loaded it will set the 220 | following credentials and limits: 221 | 222 | ``` r 223 | ggmap_credentials() 224 | # Google - 225 | # key : 226 | # account_type : standard 227 | # day_limit : 2500 228 | # second_limit : 50 229 | # client : 230 | # signature : 231 | ``` 232 | 233 | Look at the documentation of `?register_google()` to learn more. If you 234 | do have an API key, you set it with: 235 | 236 | ``` r 237 | register_google(key = "[your key here]", account_type = "premium", day_limit = 100000) 238 | ggmap_credentials() 239 | # Google - 240 | # key : [your key here] 241 | # account_type : premium 242 | # day_limit : 1e+05 243 | # second_limit : 50 244 | # client : 245 | # signature : 246 | ``` 247 | 248 | These will then be used and checked when creating the query URL: 249 | 250 | ``` r 251 | register_google(key = "AbCdEfGhIjKlMnOpQrStUvWxYz") 252 | get_googlemap("waco texas", urlonly = TRUE) 253 | # [1] "https://maps.googleapis.com/maps/api/staticmap?center=waco+texas&zoom=10&size=640x640&scale=2&maptype=terrain&key=AbCdEfGhIjKlMnOpQrStUvWxYz" 254 | ``` 255 | 256 | For anything that hasn’t been implemente (URL-wise), you can inject code 257 | into the query usin g `inject`: 258 | 259 | ``` r 260 | get_googlemap("waco texas", urlonly = TRUE, inject = "otherItem = Stuff") 261 | # [1] "https://maps.googleapis.com/maps/api/staticmap?center=waco+texas&zoom=10&size=640x640&scale=2&maptype=terrain&key=AbCdEfGhIjKlMnOpQrStUvWxYz&otherItem%20=%20Stuff" 262 | ``` 263 | 264 | Installation 265 | ------------ 266 | 267 | - From CRAN: `install.packages("ggmap")` 268 | 269 | - From Github: `devtools::install_github("dkahle/ggmap")` 270 | -------------------------------------------------------------------------------- /R/get_map.R: -------------------------------------------------------------------------------- 1 | #' Grab a map. 2 | #' 3 | #' \code{get_map} is a smart wrapper that queries the Google Maps, 4 | #' OpenStreetMap, Stamen Maps or Naver Map servers for a map. 5 | #' 6 | #' @param location an address, longitude/latitude pair (in that 7 | #' order), or left/bottom/right/top bounding box 8 | #' @param zoom map zoom, an integer from 3 (continent) to 21 9 | #' (building), default value 10 (city). openstreetmaps limits a 10 | #' zoom of 18, and the limit on stamen maps depends on the 11 | #' maptype. "auto" automatically determines the zoom for bounding 12 | #' box specifications, and is defaulted to 10 with center/zoom 13 | #' specifications. maps of the whole world currently not 14 | #' supported. 15 | #' @param scale scale argument of \code{\link{get_googlemap}} or 16 | #' \code{\link{get_openstreetmap}} 17 | #' @param maptype character string providing map theme. options 18 | #' available are "terrain", "terrain-background", "satellite", 19 | #' "roadmap", and "hybrid" (google maps), "terrain", "watercolor", 20 | #' and "toner" (stamen maps), or a positive integer for cloudmade 21 | #' maps (see ?get_cloudmademap) 22 | #' @param source Google Maps ("google"), OpenStreetMap ("osm"), 23 | #' Stamen Maps ("stamen"), or CloudMade maps ("cloudmade") 24 | #' @param force force new map (don't use archived version) 25 | #' @param messaging turn messaging on/off 26 | #' @param urlonly return url only 27 | #' @param filename destination file for download (file extension 28 | #' added according to format). Default \code{NULL} means a random 29 | #' \code{\link{tempfile}}. 30 | #' @param crop (stamen and cloudmade maps) crop tiles to bounding 31 | #' box 32 | #' @param color color ("color") or black-and-white ("bw") 33 | #' @param language language for google maps 34 | #' @param api_key an api key for cloudmade maps 35 | #' @return a ggmap object (a classed raster object with a bounding 36 | #' box attribute) 37 | #' @author David Kahle \email{david.kahle@@gmail.com} 38 | #' @seealso \code{\link{ggmap}}, \code{\link{GetMap}} in package 39 | #' RgoogleMaps 40 | #' @export 41 | #' @examples 42 | #' 43 | #' \dontrun{ 44 | #' # not run by check to reduce time; also, 45 | #' # osm may error due to server overload 46 | #' 47 | #' map <- get_map() 48 | #' map 49 | #' str(map) 50 | #' ggmap(map) 51 | #' 52 | #' (map <- get_map(maptype = "roadmap")) 53 | #' (map <- get_map(source = "osm")) 54 | #' (map <- get_map(source = "stamen", maptype = "watercolor")) 55 | #' 56 | #' map <- get_map(location = "texas", zoom = 6, source = "stamen") 57 | #' ggmap(map, fullpage = TRUE) 58 | #' 59 | #' } 60 | get_map <- function( 61 | location = c(lon = -95.3632715, lat = 29.7632836), zoom = "auto", scale = "auto", 62 | maptype = c("terrain", "terrain-background", "satellite", "roadmap", 63 | "hybrid", "toner", "watercolor", "terrain-labels", 64 | "terrain-lines", "toner-2010", "toner-2011", "toner-background", 65 | "toner-hybrid", "toner-labels", "toner-lines", "toner-lite"), 66 | source = c("google","osm","stamen","cloudmade"), 67 | force = ifelse(source == "google", TRUE, TRUE), messaging = FALSE, urlonly = FALSE, 68 | filename = NULL, 69 | crop = TRUE, color = c("color","bw"), language = "en-EN", 70 | api_key 71 | ){ 72 | 73 | # deprecated syntaxes 74 | args <- as.list(match.call(expand.dots = TRUE)[-1]) 75 | if("verbose" %in% names(args)){ 76 | .Deprecated(msg = "verbose argument deprecated, use messaging.") 77 | messaging <- eval(args$verbose) 78 | } 79 | 80 | if("center" %in% names(args)){ 81 | .Deprecated(msg = "center argument deprecated, use location.") 82 | location <- eval(args$center) 83 | } 84 | 85 | 86 | # preliminary argument checking 87 | source <- match.arg(source) 88 | color <- match.arg(color) 89 | if(missing(maptype)){ 90 | if(source != "cloudmade"){ 91 | maptype <- "terrain" 92 | } else { 93 | maptype <- 1 94 | } 95 | } 96 | if(source == "stamen"){ 97 | if(!(maptype %in% c("terrain","terrain-background","terrain-labels", 98 | "terrain-lines", "toner", "toner-2010", "toner-2011", "toner-background", 99 | "toner-hybrid", "toner-labels", "toner-lines", "toner-lite", "watercolor"))) 100 | { 101 | stop("invalid stamen maptype, see ?get_stamenmap", 102 | call. = FALSE) 103 | } 104 | } 105 | if(source == "google" & ( 106 | maptype %in% c("terrain-background","terrain-labels", 107 | "terrain-lines", "toner", "toner-2010", "toner-2011", "toner-background", 108 | "toner-hybrid", "toner-labels", "toner-lines", "toner-lite", "watercolor") 109 | )){ 110 | message(paste0("maptype = \"", maptype, "\" is only available with source = \"stamen\".")) 111 | message(paste0("resetting to source = \"stamen\"...")) 112 | source <- "stamen" 113 | } 114 | 115 | 116 | # location formatting 117 | location_stop <- TRUE 118 | 119 | if(is.character(location) && length(location) == 1){ # address 120 | location_type <- "address" 121 | location_stop <- FALSE 122 | } 123 | 124 | if(is.data.frame(location) && ncol(location) == 2){ 125 | location <- colMeans(location) # hits the next one 126 | } 127 | 128 | if(is.numeric(location) && length(location) == 2){ # center/zoom 129 | location_type <- "lonlat" 130 | location_stop <- FALSE 131 | if(!is.null(names(location))){ 132 | loc_names <- names(location) 133 | if(all(loc_names == c("long","lat"))){ 134 | names(location) <- c("lon", "lat") 135 | } else if(all(loc_names == c("lat","lon"))){ 136 | message("note : locations should be specified in the lon/lat format, not lat/lon.") 137 | location <- location[c("lon","lat")] 138 | } else if(all(loc_names == c("lat","long"))){ 139 | message("note : locations should be specified in the lon/lat format, not lat/lon.") 140 | location <- location[c("long","lat")] 141 | names(location) <- c("lon", "lat") 142 | } 143 | } else { # is missing name the elements lon/lat 144 | names(location) <- c("lon","lat") 145 | } 146 | } 147 | 148 | if(is.numeric(location) && length(location) == 4){ # bbox 149 | location_type <- "bbox" 150 | location_stop <- FALSE 151 | 152 | # check bounding box 153 | if(length(names(location)) > 0){ 154 | if(!all(names(location) %in% c("left","bottom","right","top"))){ 155 | stop("bounding boxes should have name left, bottom, right, top)", call. = FALSE) 156 | } 157 | location <- location[c("left","bottom","right","top")] 158 | } else { 159 | names(location) <- c("left","bottom","right","top") 160 | } 161 | } 162 | 163 | if(location_stop){ # if not one of the above, error 164 | stop("improper location specification, see ?get_map.", call. = F) 165 | } 166 | 167 | 168 | # compute zoom when zoom = "auto" 169 | if(zoom == "auto" && location_type == "bbox"){ 170 | if(zoom == "auto"){ 171 | lon_range <- location[c("left","right")] 172 | lat_range <- location[c("bottom","top")] 173 | 174 | # compute zoom 175 | if(missing(zoom)){ 176 | lonlength <- diff(lon_range) 177 | latlength <- diff(lat_range) 178 | zoomlon <- ceiling( log2( 360*2 / lonlength) ) 179 | zoomlat <- ceiling( log2( 180*2 / latlength) ) 180 | zoom <- max(zoomlon, zoomlat) 181 | } 182 | } 183 | } else if(zoom == "auto" && location_type != "bbox"){ 184 | zoom = 10 185 | } 186 | 187 | 188 | # compute scale when scale = "auto" (only for google/osm) 189 | if(scale == "auto"){ 190 | if(source == "google") scale <- 2 191 | if(source == "osm") scale <- OSM_scale_lookup(zoom) 192 | } 193 | 194 | 195 | 196 | # google map 197 | if(source == "google"){ 198 | 199 | # if bounding box given 200 | if(location_type == "bbox"){ 201 | warning("bounding box given to google - spatial extent only approximate.", 202 | call. = FALSE, immediate. = TRUE) 203 | message("converting bounding box to center/zoom specification. (experimental)") 204 | 205 | # computer center 206 | user_bbox <- location 207 | location <- c( 208 | lon = mean(location[c("left","right")]), 209 | lat = mean(location[c("bottom","top")]) 210 | ) 211 | } 212 | 213 | # get map 214 | map <- get_googlemap(center = location, zoom = zoom, maptype = maptype, 215 | scale = scale, messaging = messaging, urlonly = urlonly, force = force, 216 | filename = filename, color = color, language = language) 217 | 218 | # crop when bounding box is provided 219 | if(FALSE){ 220 | bb <- attr(map, "bb") 221 | mbbox <- c(left = bb$ll.lon, bottom = bb$ll.lat, right = bb$ur.lon, top = bb$ur.lat) 222 | size <- dim(map) 223 | if(location_type == "bbox"){ 224 | slon <- seq(mbbox["left"], mbbox["right"], length.out = size[1]) 225 | slat <- seq(mbbox["top"], mbbox["bottom"], length.out = size[2]) 226 | 227 | keep_x_ndcs <- which(user_bbox["left"] <= slon & slon <= user_bbox["right"]) 228 | keep_y_ndcs <- which(user_bbox["bottom"] <= slat & slat <= user_bbox["top"]) 229 | 230 | map <- map[keep_y_ndcs, keep_x_ndcs] 231 | class(map) <- c("ggmap","raster") 232 | attr(map, "bb") <- data.frame( 233 | ll.lat = user_bbox["bottom"], ll.lon = user_bbox["left"], 234 | ur.lat = user_bbox["top"], ur.lon = user_bbox["right"] 235 | ) 236 | } 237 | } 238 | 239 | # return map 240 | return(map) 241 | } 242 | 243 | 244 | 245 | # openstreetmap 246 | if(source == "osm"){ 247 | 248 | if(location_type != "bbox"){ 249 | # get bounding box 250 | gm <- get_googlemap(center = location, zoom = zoom, 251 | filename = filename) 252 | location <- as.numeric(attr(gm, "bb"))[c(2,1,4,3)] 253 | } 254 | 255 | # get map/return 256 | return( 257 | get_openstreetmap(bbox = location, scale = scale, 258 | messaging = messaging, urlonly = urlonly, filename = filename, 259 | color = color) 260 | ) 261 | } 262 | 263 | 264 | 265 | # stamen map 266 | if(source == "stamen"){ 267 | if(location_type != "bbox"){ 268 | # get bounding box 269 | gm <- get_googlemap(center = location, zoom = zoom, 270 | filename = filename) 271 | location <- as.numeric(attr(gm, "bb"))[c(2,1,4,3)] 272 | } 273 | 274 | # get map/return 275 | return( 276 | get_stamenmap(bbox = location, zoom = zoom, maptype = maptype, crop = crop, 277 | messaging = messaging, urlonly = urlonly, filename = filename, force = force, 278 | color = color) 279 | ) 280 | } 281 | 282 | 283 | 284 | # cloudmade map 285 | if(source == "cloudmade"){ 286 | if(missing(api_key)) stop("an api key must be provided for cloudmade maps, see ?get_cloudmademap.", 287 | call. = FALSE) 288 | 289 | if(location_type != "bbox"){ 290 | # get bounding box 291 | gm <- get_googlemap(center = location, zoom = zoom, 292 | filename = filename) 293 | location <- as.numeric(attr(gm, "bb"))[c(2,1,4,3)] 294 | } 295 | 296 | # get map/return 297 | return( 298 | get_cloudmademap(bbox = location, zoom = zoom, maptype = maptype, crop = crop, 299 | messaging = messaging, urlonly = urlonly, filename = filename, highres = TRUE, 300 | color = color, api_key = api_key) 301 | ) 302 | } 303 | 304 | } 305 | -------------------------------------------------------------------------------- /R/get_cloudmademap.R: -------------------------------------------------------------------------------- 1 | #' Get a CloudMade map. 2 | #' 3 | #' \code{get_cloudmademap} accesses a tile server for Stamen Maps 4 | #' and downloads/stitches map tiles/formats a map image. This 5 | #' function requires an api key which can be obtained for free from 6 | #' http://cloudmade.com/user/show (defunct?). Thousands of maptypes 7 | #' ("styles"), including create-your-own options, are available from 8 | #' http://maps.cloudmade.com/editor (defunct). 9 | #' 10 | #' @param bbox a bounding box in the format c(lowerleftlon, 11 | #' lowerleftlat, upperrightlon, upperrightlat). 12 | #' @param zoom a zoom level 13 | #' @param api_key character string containing cloud made api key, 14 | #' see details 15 | #' @param maptype an integer of what cloud made calls style, see 16 | #' details 17 | #' @param highres double resolution 18 | #' @param crop crop raw map tiles to specified bounding box 19 | #' @param messaging turn messaging on/off 20 | #' @param urlonly return url only 21 | #' @param filename destination file for download (file extension 22 | #' added according to format). Default \code{NULL} means a random 23 | #' \code{\link{tempfile}}. 24 | #' @param color color or black-and-white 25 | #' @param ... ... 26 | #' @return a ggmap object (a classed raster object with a bounding 27 | #' box attribute) 28 | #' @author David Kahle \email{david.kahle@@gmail.com} 29 | #' @seealso http://maps.cloudmade.com/ (defunct), 30 | #' \code{\link{ggmap}} 31 | #' @export 32 | #' @examples 33 | #' \dontrun{ # in what follows, enter your own api key 34 | #' 35 | #' api_key <- '' 36 | #' api_key <- 'b23b0358e87c4ff99f81029eda25c903' 37 | #' 38 | #' map <- get_cloudmademap(api_key = api_key) 39 | #' ggmap(map) 40 | #' 41 | #' map <- get_cloudmademap(maptype = 997, api_key = api_key) 42 | #' ggmap(map) 43 | #' } 44 | get_cloudmademap <- function( 45 | bbox = c(left = -95.80204, bottom = 29.38048, right = -94.92313, top = 30.14344), 46 | zoom = 10, api_key, maptype = 1, highres = TRUE, crop = TRUE, messaging = FALSE, 47 | urlonly = FALSE, filename = NULL, color = c('color','bw'), ... 48 | ){ 49 | 50 | .Deprecated(msg = "cloudmademap is deprecated.") 51 | 52 | # enumerate argument checking (added in lieu of checkargs function) 53 | args <- as.list(match.call(expand.dots = TRUE)[-1]) 54 | argsgiven <- names(args) 55 | 56 | if('bbox' %in% argsgiven){ 57 | if(!(is.numeric(bbox) && length(bbox) == 4)){ 58 | stop('bounding box improperly specified. see ?get_openstreetmap', call. = F) 59 | } 60 | } 61 | 62 | if('zoom' %in% argsgiven){ 63 | if(!(is.numeric(zoom) && length(zoom) == 1 && 64 | zoom == round(zoom) && zoom >= 0 && zoom <= 18)){ 65 | stop('scale must be a positive integer 0-18, see ?get_stamenmap.', call. = F) 66 | } 67 | } 68 | 69 | if('maptype' %in% argsgiven){ 70 | if(!(is.numeric(maptype) && length(maptype) == 1 && 71 | maptype == round(maptype) && maptype > 0)){ 72 | stop('maptype must be a positive integer, see ?get_cloudmademap.', call.=F) 73 | } 74 | } 75 | 76 | if('api_key' %in% argsgiven){ 77 | if(!(is.character(api_key) && length(api_key) == 1)){ 78 | stop('api_key improperly specified, see ?get_cloudmademap.', call.=F) 79 | } 80 | } else { 81 | stop('api_key must be specified, see ?get_cloudmademap.') 82 | } 83 | 84 | if('highres' %in% argsgiven) stopifnot(is.logical(highres)) 85 | 86 | if('messaging' %in% argsgiven) stopifnot(is.logical(messaging)) 87 | 88 | if('urlonly' %in% argsgiven) stopifnot(is.logical(urlonly)) 89 | 90 | if(is.null(filename)){ 91 | destfile <- tempfile(fileext = ".png") 92 | } else{ 93 | filename_stop <- TRUE 94 | if(is.character(filename) && length(filename) == 1) filename_stop <- FALSE 95 | if(filename_stop) stop('improper filename specification, see ?get_googlemap.', call. = F) 96 | destfile <- paste(filename, 'png', sep = '.') 97 | } 98 | 99 | # color arg checked by match.arg 100 | 101 | if('checkargs' %in% argsgiven){ 102 | .Deprecated(msg = 'checkargs argument deprecated, args are always checked after v2.1.') 103 | } 104 | 105 | 106 | # argument checking (no checks for language, region, markers, path, visible, style) 107 | #args <- as.list(match.call(expand.dots = TRUE)[-1]) 108 | #if(checkargs) get_cloudmademap_checkargs(args) 109 | color <- match.arg(color) 110 | if(is.null(names(bbox))) names(bbox) <- c('left','bottom','right','top') 111 | if(highres) maptype <- paste(maptype, '@2x', sep = '') 112 | 113 | # determine tiles to get 114 | fourCorners <- expand.grid( 115 | lon = c(bbox['left'], bbox['right']), 116 | lat = c(bbox['bottom'], bbox['top']) 117 | ) 118 | fourCorners$zoom <- zoom 119 | row.names(fourCorners) <- 120 | c('lowerleft','lowerright','upperleft','upperright') 121 | fourCornersTiles <- apply(fourCorners, 1, function(v) LonLat2XY(v[1],v[2],v[3])) 122 | 123 | xsNeeded <- Reduce(':', sort(unique(as.numeric(sapply(fourCornersTiles, function(df) df$X))))) 124 | numXTiles <- length(xsNeeded) 125 | ysNeeded <- Reduce(':', sort(unique(as.numeric(sapply(fourCornersTiles, function(df) df$Y))))) 126 | numYTiles <- length(ysNeeded) 127 | tilesNeeded <- expand.grid(x = xsNeeded, y = ysNeeded) 128 | if(nrow(tilesNeeded) > 40){ 129 | message(paste0(nrow(tilesNeeded), ' tiles needed, this may take a while ', 130 | '(try a smaller zoom).')) 131 | } 132 | xTileProgression <- rep(1:numXTiles, numYTiles) 133 | yTileProgression <- rep(1:numYTiles, each = numXTiles) 134 | 135 | 136 | # make urls 137 | base_url <- 'http://b.tile.cloudmade.com/' 138 | base_url <- paste(base_url, api_key, '/', maptype, '/', 256, '/', zoom, sep = '') 139 | urls <- paste(base_url, 140 | apply(tilesNeeded, 1, paste, collapse = '/'), sep = '/') 141 | urls <- paste(urls, '.png', sep = '') 142 | if(messaging) message(length(urls), ' tiles required.') 143 | if(urlonly) return(urls) 144 | 145 | # download and stitch 146 | size <- 256 * c(length(xsNeeded), length(ysNeeded)) 147 | map <- matrix('NA', nrow = size[2], ncol = size[1]) 148 | 149 | for(k in seq_along(urls)){ 150 | download.file(urls[[k]], destfile = destfile, quiet = !messaging, mode = 'wb') 151 | tile <- readPNG(destfile) 152 | if(color == 'color'){ 153 | tile <- apply(tile, 2, rgb) 154 | } else if(color == 'bw'){ 155 | tile_dim <- dim(tile) 156 | tile <- gray(.30 * tile[,,1] + .59 * tile[,,2] + .11 * tile[,,3]) 157 | dim(tile) <- tile_dim[1:2] 158 | } 159 | 160 | map[ 161 | (1+256*(yTileProgression[k]-1)):(256*yTileProgression[k]), 162 | (1+256*(xTileProgression[k]-1)):(256*xTileProgression[k]) 163 | ] <- tile 164 | } 165 | 166 | # determine bbox of map. note : not the same as the argument bounding box - 167 | # the map is only a covering of the bounding box extent the idea is to get 168 | # the lower left tile and the upper right tile and compute their bounding boxes 169 | # tiles are referenced by top left of tile, starting at 0,0 170 | # see http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames 171 | bboxOfTile <- function(vXY){ 172 | lonlat_upperleft <- XY2LonLat(vXY[1],vXY[2],zoom) 173 | lonlat_lowerright <- XY2LonLat(vXY[1]+1,vXY[2]+1,zoom) 174 | data.frame( 175 | left = lonlat_upperleft$lon, 176 | bottom = lonlat_lowerright$lat, 177 | right = lonlat_lowerright$lon, 178 | top = lonlat_upperleft$lat 179 | ) 180 | } 181 | tileBboxes <- ldply(split(tilesNeeded,1:nrow(tilesNeeded)), 182 | function(df) bboxOfTile(as.numeric(df))) 183 | mbbox <- c( 184 | left = min(tileBboxes$left), 185 | bottom = min(tileBboxes$bottom), 186 | right = max(tileBboxes$right), 187 | top = max(tileBboxes$top) 188 | ) 189 | 190 | 191 | # format map and return if not cropping 192 | if(!crop){ 193 | map <- as.raster(map) 194 | class(map) <- c('ggmap','raster') 195 | attr(map, 'bb') <- data.frame( 196 | ll.lat = mbbox['bottom'], ll.lon = mbbox['left'], 197 | ur.lat = mbbox['top'], ur.lon = mbbox['right'] 198 | ) 199 | 200 | # additional map meta-data 201 | attr(map, "source") <- "google" 202 | attr(map, "maptype") <- maptype 203 | attr(map, "zoom") <- zoom 204 | 205 | # return 206 | return(map) 207 | } 208 | 209 | 210 | # crop map 211 | if(crop){ 212 | slon <- seq(mbbox['left'], mbbox['right'], length.out = size[1]) 213 | slat <- seq(mbbox['top'], mbbox['bottom'], length.out = size[2]) 214 | 215 | keep_x_ndcs <- which(bbox['left'] <= slon & slon <= bbox['right']) 216 | keep_y_ndcs <- which(bbox['bottom'] <= slat & slat <= bbox['top']) 217 | 218 | croppedmap <- map[keep_y_ndcs, keep_x_ndcs] 219 | } 220 | 221 | # format map 222 | croppedmap <- as.raster(croppedmap) 223 | class(croppedmap) <- c('ggmap','raster') 224 | attr(croppedmap, 'bb') <- data.frame( 225 | ll.lat = bbox['bottom'], ll.lon = bbox['left'], 226 | ur.lat = bbox['top'], ur.lon = bbox['right'] 227 | ) 228 | 229 | # additional map meta-data 230 | attr(croppedmap, "source") <- "cloudmade" 231 | attr(croppedmap, "maptype") <- maptype 232 | attr(croppedmap, "zoom") <- zoom 233 | 234 | 235 | # return 236 | croppedmap 237 | } 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | get_cloudmademap_checkargs <- function(args){ 257 | eargs <- lapply(args, eval) 258 | argsgiven <- names(args) 259 | 260 | with(eargs,{ 261 | 262 | # bbox arg 263 | if('bbox' %in% argsgiven){ 264 | if(!(is.numeric(bbox) && length(bbox) == 4)){ 265 | stop('bounding box improperly specified. see ?get_openstreetmap', call. = F) 266 | } 267 | } 268 | 269 | # zoom arg 270 | if('zoom' %in% argsgiven){ 271 | if(!(is.numeric(zoom) && length(zoom) == 1 && 272 | zoom == round(zoom) && zoom >= 0 && zoom <= 18)){ 273 | stop('scale must be a positive integer 0-18, see ?get_stamenmap.', call. = F) 274 | } 275 | } 276 | 277 | # maptype arg 278 | if('maptype' %in% argsgiven){ 279 | if(!(is.numeric(maptype) && length(maptype) == 1 && 280 | maptype == round(maptype) && maptype > 0)){ 281 | stop('maptype must be a positive integer, see ?get_cloudmademap.', call.=F) 282 | } 283 | } 284 | 285 | # api_key arg 286 | if('api_key' %in% argsgiven){ 287 | if(!(is.character(api_key) && length(api_key) == 1)){ 288 | stop('api_key improperly specified, see ?get_cloudmademap.', call.=F) 289 | } 290 | } else { 291 | stop('api_key must be specified, see ?get_cloudmademap.') 292 | } 293 | 294 | # highres arg 295 | if('highres' %in% argsgiven){ 296 | stopifnot(is.logical(highres)) 297 | } 298 | 299 | # messaging arg 300 | if('messaging' %in% argsgiven){ 301 | stopifnot(is.logical(messaging)) 302 | } 303 | 304 | # urlonly arg 305 | if('urlonly' %in% argsgiven){ 306 | stopifnot(is.logical(urlonly)) 307 | } 308 | 309 | # filename arg 310 | if('filename' %in% argsgiven){ 311 | filename_stop <- TRUE 312 | if(is.character(filename) && length(filename) == 1) style_stop <- FALSE 313 | if(filename_stop) stop('improper filename specification, see ?get_googlemap.', call. = F) 314 | } 315 | 316 | # color arg checked by match.arg 317 | 318 | 319 | }) # end with 320 | } 321 | 322 | 323 | 324 | --------------------------------------------------------------------------------