├── .Rbuildignore ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .travis.yml ├── DESCRIPTION ├── NAMESPACE ├── NEWS ├── NEWS.md ├── R ├── LonLat2XY.R ├── OSM_scale_lookup.R ├── RgoogleMaps-functions.R ├── XY2LonLat.R ├── attach.R ├── bb2bbox.R ├── calc_zoom.r ├── coord_map.R ├── crime.R ├── file_drawer.R ├── geocode.R ├── geom_leg.R ├── get_cloudmademap.R ├── get_googlemap.R ├── get_map.R ├── get_navermap.R ├── get_openstreetmap.R ├── get_stadiamap.R ├── get_stamenmap.R ├── ggimage.R ├── gglocator.R ├── ggmap-defunct.R ├── ggmap-package.R ├── ggmap.R ├── ggmap_options.R ├── hadley.R ├── helpers.R ├── inset.R ├── inset_raster.R ├── make_bbox.R ├── mapdist.R ├── not-exported-ggplot2.R ├── not-exported-plyr.R ├── print.R ├── qmap.R ├── qmplot.R ├── register_google.R ├── register_stadiamaps.R ├── revgeocode.R ├── route.R ├── theme_inset.R ├── theme_nothing.R ├── trek.R ├── wind.R └── zips.R ├── README.Rmd ├── README.md ├── appveyor.yml ├── cran-comments.md ├── data ├── crime.rda ├── hadley.rda ├── wind.rda └── zips.rda ├── ggmap.Rproj ├── inst └── CITATION ├── man ├── LonLat2XY.Rd ├── OSM_scale_lookup.Rd ├── XY2LonLat.Rd ├── bb2bbox.Rd ├── calc_zoom.Rd ├── crime.Rd ├── file_drawer.Rd ├── geocode.Rd ├── geom_leg.Rd ├── get_cloudmademap.Rd ├── get_googlemap.Rd ├── get_map.Rd ├── get_navermap.Rd ├── get_openstreetmap.Rd ├── get_stadiamap.Rd ├── get_stamenmap.Rd ├── ggimage.Rd ├── gglocator.Rd ├── ggmap-defunct.Rd ├── ggmap.Rd ├── ggmap_options.Rd ├── ggmapplot.Rd ├── hadley.Rd ├── inset.Rd ├── inset_raster.Rd ├── legs2route.Rd ├── make_bbox.Rd ├── mapdist.Rd ├── print.ggmap.Rd ├── qmap.Rd ├── qmplot.Rd ├── reexports.Rd ├── register_google.Rd ├── register_stadiamaps.Rd ├── revgeocode.Rd ├── route.Rd ├── theme_inset.Rd ├── theme_nothing.Rd ├── trek.Rd ├── wind.Rd └── zips.Rd ├── revdep ├── .gitignore ├── README.md ├── check.R ├── checks.rds ├── cran.md ├── email.yml ├── failures.md ├── problems.md └── summary.md ├── tests ├── testthat.R └── testthat │ ├── test-LonLat2XY.R │ ├── test-calc_zoom.R │ ├── test-data.R │ ├── test-encoding.R │ ├── test-ggmap.R │ └── util.R └── tools ├── README-faceting-1.png ├── README-ggmap-1.png ├── README-ggmap-layers-1.png ├── README-ggmap-patchwork-1.png ├── README-google_maps-1.png ├── README-maptypes-1.png ├── README-qmplot-1.png └── README-route_trek-1.png /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^appveyor\.yml$ 2 | ^\.travis\.yml$ 3 | ^.*\.Rproj$ 4 | ^\.Rproj\.user$ 5 | ^README\.Rmd$ 6 | ^revdep$ 7 | ^cran-comments.md$ 8 | ^cran-comments\.md$ 9 | README_cache 10 | ^\.github/ISSUE_TEMPLATE\.md$ 11 | ^\.github/PULL_REQUEST_TEMPLATE\.md$ 12 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.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 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | README_cache/ 5 | /revdep/.cache.rds 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # R for travis: see documentation at https://docs.travis-ci.com/user/languages/r 2 | 3 | language: R 4 | sudo: false 5 | cache: packages 6 | 7 | jobs: 8 | include: 9 | - r: devel 10 | - r: release 11 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: ggmap 2 | Version: 4.0.1 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.io", 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 | person("Scott", "Jackson", email = "scottmmjackson@gmail.com", role = "aut"), 13 | person("Mikko", "Korpela", email = "mvkorpel@iki.fi", role = "ctb")) 14 | Depends: 15 | R (>= 3.1.0), 16 | ggplot2 (>= 2.2.0) 17 | Imports: 18 | png, 19 | plyr, 20 | jpeg, 21 | digest, 22 | scales, 23 | dplyr, 24 | bitops, 25 | grid, 26 | glue, 27 | httr, 28 | stringr, 29 | purrr, 30 | magrittr, 31 | tibble, 32 | tidyr, 33 | rlang, 34 | cli 35 | Suggests: 36 | MASS, 37 | hexbin, 38 | testthat 39 | License: GPL-2 40 | LazyData: true 41 | RoxygenNote: 7.3.2 42 | Roxygen: list(markdown = TRUE) 43 | Encoding: UTF-8 44 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(print,ggmap) 4 | S3method(print,google_credentials) 5 | export("%>%") 6 | export(LonLat2XY) 7 | export(OSM_scale_lookup) 8 | export(XY2LonLat) 9 | export(bb2bbox) 10 | export(calc_zoom) 11 | export(clear_geocode_cache) 12 | export(distQueryCheck) 13 | export(file_drawer) 14 | export(geocode) 15 | export(geocodeQueryCheck) 16 | export(geocode_cache) 17 | export(geom_leg) 18 | export(get_cloudmademap) 19 | export(get_googlemap) 20 | export(get_map) 21 | export(get_navermap) 22 | export(get_openstreetmap) 23 | export(get_stadiamap) 24 | export(get_stamen_tile_download_fail_log) 25 | export(get_stamenmap) 26 | export(ggimage) 27 | export(gglocator) 28 | export(ggmap) 29 | export(ggmap_credentials) 30 | export(ggmap_hide_api_key) 31 | export(ggmap_show_api_key) 32 | export(ggmapplot) 33 | export(google_account) 34 | export(google_client) 35 | export(google_day_limit) 36 | export(google_key) 37 | export(google_second_limit) 38 | export(google_signature) 39 | export(has_ggmap_option) 40 | export(has_ggmap_options) 41 | export(has_google_account) 42 | export(has_google_client) 43 | export(has_google_key) 44 | export(has_google_signature) 45 | export(has_stadiamaps_key) 46 | export(inset) 47 | export(inset_ggmap) 48 | export(inset_raster) 49 | export(legs2route) 50 | export(load_geocode_cache) 51 | export(make_bbox) 52 | export(mapdist) 53 | export(mutate_geocode) 54 | export(qmap) 55 | export(qmplot) 56 | export(register_google) 57 | export(register_stadiamaps) 58 | export(retry_stamen_map_download) 59 | export(revgeocode) 60 | export(route) 61 | export(routeQueryCheck) 62 | export(scrub_key) 63 | export(set_ggmap_option) 64 | export(showing_key) 65 | export(stadiamaps_key) 66 | export(theme_inset) 67 | export(theme_nothing) 68 | export(trek) 69 | export(write_geocode_cache) 70 | import(ggplot2) 71 | importFrom(bitops,bitAnd) 72 | importFrom(bitops,bitOr) 73 | importFrom(bitops,bitShiftL) 74 | importFrom(bitops,bitShiftR) 75 | importFrom(cli,cli_abort) 76 | importFrom(cli,cli_alert_danger) 77 | importFrom(cli,cli_alert_info) 78 | importFrom(cli,cli_warn) 79 | importFrom(dplyr,bind_cols) 80 | importFrom(dplyr,bind_rows) 81 | importFrom(dplyr,filter) 82 | importFrom(dplyr,group_by) 83 | importFrom(dplyr,mutate) 84 | importFrom(dplyr,right_join) 85 | importFrom(dplyr,select) 86 | importFrom(dplyr,ungroup) 87 | importFrom(glue,glue) 88 | importFrom(grDevices,as.raster) 89 | importFrom(grDevices,extendrange) 90 | importFrom(grDevices,gray) 91 | importFrom(grDevices,rgb) 92 | importFrom(grid,current.vpPath) 93 | importFrom(grid,current.vpTree) 94 | importFrom(grid,downViewport) 95 | importFrom(grid,grid.locator) 96 | importFrom(grid,rasterGrob) 97 | importFrom(grid,seekViewport) 98 | importFrom(grid,upViewport) 99 | importFrom(grid,viewport) 100 | importFrom(httr,GET) 101 | importFrom(httr,http_status) 102 | importFrom(httr,stop_for_status) 103 | importFrom(httr,warn_for_status) 104 | importFrom(jpeg,readJPEG) 105 | importFrom(magrittr,"%>%") 106 | importFrom(plyr,.) 107 | importFrom(plyr,arrange) 108 | importFrom(plyr,compact) 109 | importFrom(plyr,ddply) 110 | importFrom(plyr,desc) 111 | importFrom(plyr,dlply) 112 | importFrom(plyr,is.discrete) 113 | importFrom(plyr,is.formula) 114 | importFrom(plyr,join) 115 | importFrom(plyr,ldply) 116 | importFrom(plyr,llply) 117 | importFrom(png,readPNG) 118 | importFrom(purrr,cross_df) 119 | importFrom(purrr,flatten) 120 | importFrom(purrr,flatten_chr) 121 | importFrom(purrr,imap) 122 | importFrom(purrr,map) 123 | importFrom(purrr,map_chr) 124 | importFrom(purrr,map_int) 125 | importFrom(purrr,pluck) 126 | importFrom(purrr,walk) 127 | importFrom(rlang,set_names) 128 | importFrom(scales,expand_range) 129 | importFrom(stats,asOneSidedFormula) 130 | importFrom(stats,time) 131 | importFrom(stringr,str_c) 132 | importFrom(stringr,str_detect) 133 | importFrom(stringr,str_extract) 134 | importFrom(stringr,str_pad) 135 | importFrom(stringr,str_replace) 136 | importFrom(stringr,str_replace_all) 137 | importFrom(stringr,str_split) 138 | importFrom(stringr,str_sub) 139 | importFrom(stringr,str_to_title) 140 | importFrom(stringr,str_trim) 141 | importFrom(stringr,str_trunc) 142 | importFrom(tibble,as_tibble) 143 | importFrom(tibble,tibble) 144 | importFrom(tidyr,nest) 145 | importFrom(tidyr,spread) 146 | importFrom(tidyr,unnest) 147 | importFrom(utils,URLencode) 148 | importFrom(utils,download.file) 149 | importFrom(utils,tail) 150 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # ggmap 4.0.1 2 | 3 | ## Minor improvements and fixes 4 | 5 | * A bug was fixed that prevented using Stamen-style watercolor maps via 6 | `get_stadiamap()` after the last release (thanks @pushing-boulders, #357). 7 | 8 | 9 | 10 | # ggmap 4.0.0 11 | 12 | ## New features 13 | 14 | * Adds support for all styles from Stadia Maps via `get_stadiamap()` (thanks 15 | @ianthetechie, #351). 16 | 17 | ## Changes 18 | 19 | * Stamen map tiles are now hosted by Stadia Maps (see http://maps.stamen.com/stadia-partnership/), 20 | which necessitates some breaking changes in ggmap. The existing URLs 21 | are expected to be shut off after October 31, 2023. This release 22 | renames the Stamen-related functions to Stadia equivalents 23 | (ex: `get_stamenmap()` is now `get_stadiamap()`). Developers will also need to make 24 | some minor changes to the style names to include a `stamen_` prefix and 25 | convert the names to `snake_case`. For example `toner-lite` becomes 26 | `stamen_toner_lite`. 27 | * Removes the toner hybrid layer group, as well as some other deprecated 28 | styles which were not in wide use. Stamen's Toner Hybrid can be 29 | recreated by layering the lines and labels on top of each other. 30 | * Adds styles from Stadia Maps: Alidade Smooth (light and dark) and 31 | Outdoors. 32 | * ggmap no longer depends on RgoogleMaps (thanks @sanjmeh, #354). 33 | 34 | 35 | 36 | # ggmap 3.0.2 37 | 38 | ## Changes 39 | 40 | * Startup messages can now be suppressed 41 | 42 | 43 | 44 | # ggmap 3.0.1 45 | 46 | ## New features 47 | 48 | * `geocode_cache()` is now exported to the user, and functions 49 | `write_geocode_cache()` and `write_geocode_cache()` exist to facilitate 50 | using the same cache across sessions. 51 | 52 | ## Changes 53 | 54 | * __ggmap__ no longer depends on __rjson__ (thanks @MichaelChirico, #317). 55 | * Most functions now use **cli**-based messaging functions, following 56 | **ggplot2**'s lead. 57 | 58 | ## Minor improvements and fixes 59 | 60 | * __ggmap__ functions can now be called even if it has not been attached to 61 | the search path (loaded) (reported by @jennybc, @lorenzwalthert, #264, 62 | #244). 63 | 64 | * Google functions now properly encode #'s (reported by @aaronrudkin, #272). 65 | 66 | * `get_stamenmap()` now only returns URLs if `messaging = TRUE` (Reported by 67 | @ikosmidis, #274). It also includes a more formal attribution to Stamen 68 | Design and OpenStreetMap. 69 | 70 | * `get_stamenmap()` now supports a SSL Stamen endpoint via the `https` 71 | argument (#276). 72 | 73 | * `mapdist()` now properly orders results (reported by @BirgerNi, #266). 74 | 75 | * `mapdist()` now properly returns URLs if `urlonly = TRUE`. 76 | 77 | * `get_map()` now (again) respects the `source = "google"` specification when 78 | given a bounding box (reported by @julovi, #267). 79 | 80 | * `geocode()` now (again) respects the `source = "dsk"` specification 81 | (reported by @alistaire47, #180). 82 | 83 | * A bug giving an error message `Error in aperm.default(map, c(2, 1, 3)) : invalid first argument, must be an array` has now been fixed. (solution by @kent37, #262). 84 | 85 | * `geocode()` now properly caches when geocoding several locations. The 86 | caching keys are now the hash values of the scrubbed url. 87 | 88 | -------------------------------------------------------------------------------- /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 zoom. Decimal 4 | #' 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.io}, based on 13 | #' `RgoogleMaps::LatLon2XY()` by Markus Loecher of Sense Networks 14 | #' \email{markus@@sensenetworks.com} 15 | #' @seealso \url{https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames} 16 | #' @export 17 | #' @examples 18 | #' 19 | #' 20 | #' \dontrun{ 21 | #' gc <- geocode('baylor university') 22 | #' LonLat2XY(gc$lon, gc$lat, 10) 23 | #' 24 | #' } 25 | #' 26 | LonLat2XY <- function(lon_deg, lat_deg, zoom, xpix=256, ypix=256){ 27 | n <- 2^zoom 28 | X <- ((lon_deg + 180) / 360) * n 29 | sec <- function(x) 1/cos(x) 30 | lat_rad <- lat_deg * pi/180 31 | Y <- (1 - (log(tan(lat_rad) + sec(lat_rad)) / pi)) / 2 * n 32 | df <- data.frame( 33 | X = floor(X), 34 | Y = floor(Y), 35 | x = xpix*(X - floor(X)), 36 | y = ypix*(Y - floor(Y)) 37 | ) 38 | row.names(df) <- NULL 39 | df 40 | } 41 | -------------------------------------------------------------------------------- /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 given zoom 8 | #' level is a complicated task. For details, see 9 | #' \url{https://wiki.openstreetmap.org/wiki/FAQ} 10 | #' @author David Kahle \email{david@@kahle.io} 11 | #' @export 12 | #' @examples 13 | #' 14 | #' OSM_scale_lookup(zoom = 3) 15 | #' OSM_scale_lookup(zoom = 10) 16 | #' 17 | #' \dontrun{ 18 | #' # these can take a long time or are prone to crashing 19 | #' # if the osm server load is too high 20 | #' 21 | #' # these maps are were the ones used to tailor fit the scale 22 | #' # the zooms were fixed 23 | #' ggmap(get_map(zoom = 3, source = 'osm', scale = 47500000), extent = "device") 24 | #' ggmap(get_map(zoom = 4, source = 'osm', scale = 32500000), extent = "device") 25 | #' ggmap(get_map(zoom = 5, source = 'osm', scale = 15000000), extent = "device") 26 | #' ggmap(get_map(zoom = 6, source = 'osm', scale = 10000000), extent = "device") 27 | #' ggmap(get_map(zoom = 7, source = 'osm', scale = 5000000), extent = "device") 28 | #' ggmap(get_map(zoom = 8, source = 'osm', scale = 2800000), extent = "device") 29 | #' ggmap(get_map(zoom = 9, source = 'osm', scale = 1200000), extent = "device") 30 | #' ggmap(get_map(zoom = 10, source = 'osm', scale = 575000), extent = "device") 31 | #' ggmap(get_map(zoom = 11, source = 'osm', scale = 220000), extent = "device") 32 | #' ggmap(get_map(zoom = 12, source = 'osm', scale = 110000), extent = "device") 33 | #' ggmap(get_map(zoom = 13, source = 'osm', scale = 70000), extent = "device") 34 | #' ggmap(get_map(zoom = 14, source = 'osm', scale = 31000), extent = "device") 35 | #' ggmap(get_map(zoom = 15, source = 'osm', scale = 15000), extent = "device") 36 | #' ggmap(get_map(zoom = 16, source = 'osm', scale = 7500), extent = "device") 37 | #' ggmap(get_map(zoom = 17, source = 'osm', scale = 4000), extent = "device") 38 | #' ggmap(get_map(zoom = 18, source = 'osm', scale = 2500), extent = "device") 39 | #' ggmap(get_map(zoom = 19, source = 'osm', scale = 1750), extent = "device") 40 | #' ggmap(get_map(zoom = 20, source = 'osm', scale = 1000), extent = "device") 41 | #' 42 | #' # the USA 43 | #' lonR <- c(1.01,.99)*c(-124.73,-66.95) 44 | #' latR <- c(.99,1.01)*c(24.52, 49.38) 45 | #' qmap(lonR = lonR, latR = latR, source = 'osm', scale = 325E5) 46 | #' 47 | #' } 48 | #' 49 | #' 50 | OSM_scale_lookup <- function (zoom = 10){ 51 | df <- data.frame( 52 | z = 2:20, 53 | s = c(175000000, 47500000, 32500000, 15000000, 10000000, 5000000, 54 | 2800000, 1200000, 575000, 220000, 110000, 70000, 31000, 15000, 55 | 7500, 4000, 2500, 1750, 1000) 56 | ) 57 | with(df, s[z == zoom]) 58 | } 59 | 60 | -------------------------------------------------------------------------------- /R/RgoogleMaps-functions.R: -------------------------------------------------------------------------------- 1 | # these functions were brought in essentially verbatim from 2 | # RgoogleMaps to avoid the problems of that package's depencency 3 | # on the deprecated sp package. 4 | 5 | 6 | XY2LatLon <- function (MyMap, X, Y, zoom) { 7 | if (!missing(MyMap)) { 8 | lat.center <- MyMap[[1]] 9 | lon.center <- MyMap[[2]] 10 | if (missing(zoom)) 11 | zoom <- MyMap[[3]] 12 | mycenter <- LatLon2XY(lat.center, lon.center, zoom) 13 | x <- mycenter$Tile[, "X"] + (X + mycenter$Coords[, "x"])/256 14 | y <- mycenter$Tile[, "Y"] - (Y - mycenter$Coords[, "y"])/256 15 | } 16 | else { 17 | x = X 18 | y = Y 19 | } 20 | ytilde <- 1 - y/2^(zoom - 1) 21 | yy = (exp(2 * pi * ytilde) - 1)/(exp(2 * pi * ytilde) + 1) 22 | ShiftLat <- function(yy) { 23 | n = c(-1, 0, 1) 24 | lat = 2 * pi * (n) + asin(yy) 25 | lat <- lat[which(lat <= pi/2 & lat > -pi/2)] 26 | lat <- 180 * lat/pi 27 | return(lat) 28 | } 29 | lat <- sapply(yy, ShiftLat) 30 | lon <- 180 * (x/2^(zoom - 1) - 1) 31 | cbind(lat = lat, lon = lon) 32 | } 33 | 34 | 35 | 36 | 37 | LatLon2XY <- function (lat, lon, zoom) { 38 | SinPhi = sin(lat * pi/180) 39 | normX = lon/180 40 | normY = (0.5 * log((1 + SinPhi)/(1 - SinPhi)))/pi 41 | Y <- (2^zoom) * ((1 - normY)/2) 42 | X <- (2^zoom) * ((normX + 1)/2) 43 | x <- 256 * (X - floor(X)) 44 | y <- 256 * (Y - floor(Y)) 45 | 46 | list( 47 | Tile = cbind(X = floor(X), Y = floor(Y)), 48 | Coords = cbind(x = x, y = y) 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 zoom. Decimal 4 | #' 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.io}, based on 15 | #' `RgoogleMaps::XY2LatLon()` by Markus Loecher of Sense Networks 16 | #' \email{markus@@sensenetworks.com} 17 | #' @seealso \url{https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames} 18 | #' @export 19 | #' @examples 20 | #' 21 | #' 22 | #' \dontrun{ 23 | #' XY2LonLat(480, 845, zoom = 11) 24 | #' XY2LonLat(0, 0, zoom = 1) 25 | #' XY2LonLat(0, 0, 255, 255, zoom = 1) 26 | #' XY2LonLat(0, 0, 255, 255, zoom = 1) 27 | #' 28 | #' } 29 | #' 30 | XY2LonLat <- function(X, Y, zoom, x = 0, y = 0, xpix=255, ypix=255){ 31 | n <- 2^zoom 32 | lon_deg <- (X+x/xpix) / n * 360.0 - 180.0 33 | tmp <- tanh( pi * (1 - 2 * (Y+y/ypix) / n)) 34 | ShiftLat <- function(tmp) { 35 | lat <- 2 * pi * (-1:1) + asin(tmp) 36 | lat[which(-pi/2 < lat & lat <= pi/2)] * 180/pi 37 | } 38 | lat_deg <- ShiftLat(tmp) 39 | data.frame(lon = lon_deg, lat = lat_deg) 40 | } 41 | -------------------------------------------------------------------------------- /R/attach.R: -------------------------------------------------------------------------------- 1 | .onAttach <- function(...) { 2 | 3 | tos <- paste0( 4 | cli::col_green(cli::symbol$info), 5 | " ", 6 | "Google's Terms of Service: ", 7 | cli::col_blue(cli::style_italic( 8 | cli::style_hyperlink("", "https://mapsplatform.google.com") 9 | )), 10 | "\n ", 11 | "Stadia Maps' Terms of Service: ", 12 | cli::col_blue(cli::style_italic( 13 | cli::style_hyperlink("", "https://stadiamaps.com/terms-of-service") 14 | )), 15 | "\n ", 16 | "OpenStreetMap's Tile Usage Policy: ", 17 | cli::col_blue(cli::style_italic( 18 | cli::style_hyperlink("", "https://operations.osmfoundation.org/policies/tiles") 19 | )) 20 | ) 21 | cite <- paste0( 22 | cli::col_green(cli::symbol$info), 23 | " ", 24 | "Please cite ", cli::col_blue("ggmap"), " if you use it! Use `citation(\"ggmap\")` for details." 25 | ) 26 | 27 | rlang::inform( 28 | paste0(tos, "\n", cite), 29 | class = "packageStartupMessage" 30 | ) 31 | 32 | bootstrap_ggmap() 33 | 34 | } 35 | 36 | 37 | 38 | 39 | 40 | bootstrap_ggmap <- function () { 41 | set_ggmap_option( 42 | "google" = structure( 43 | list( 44 | "account_type" = "standard", 45 | "day_limit" = Inf, #2500, 46 | "second_limit" = 50L 47 | ), 48 | class = "google_credentials" 49 | ), 50 | "display_api_key" = FALSE 51 | ) 52 | } 53 | 54 | 55 | 56 | ggmap_environment <- new.env(parent = emptyenv()) 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /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_stadiamap). 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.io} 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 Stadia map 25 | #' stadMap <- get_stadiamap(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(stadMap) + 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/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 [make_bbox()], [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) cli::cli_abort(errorString) 43 | if(!all(names(bbox) == c("left", "bottom", "right", "top"))) cli::cli_abort(errorString) 44 | lon_range <- bbox[c("left", "right")] 45 | lat_range <- bbox[c("bottom", "top")] 46 | 47 | } else { # ranges 48 | if(length(lon) != 2 || length(lat) != 2 || !is.numeric(lon) || !is.numeric(lat)) { 49 | cli::cli_abort("If specifying ranges, they both must be of length 2 and numeric.") 50 | } 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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /R/crime.R: -------------------------------------------------------------------------------- 1 | #' Crime data 2 | #' 3 | #' Lightly cleaned Houston crime from January 2010 to August 2010 geocoded with 4 | #' Google Maps 5 | #' 6 | #' @name crime 7 | #' @docType data 8 | #' @author Houston Police Department, City of Houston 9 | #' @references \url{https://www.houstontx.gov/police/cs/index-2.htm} 10 | NULL 11 | -------------------------------------------------------------------------------- /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_stadiamap() 21 | #' # The second time, the local cache is used so it's much faster 22 | #' map <- get_stadiamap() 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 | 34 | 35 | file_drawer_exists <- function() { 36 | file.exists(file_drawer()) 37 | } 38 | 39 | 40 | 41 | file_drawer_create <- function() { 42 | if (file_drawer_exists()) return() 43 | 44 | dir.create(file_drawer(), recursive = TRUE, showWarnings = FALSE) 45 | saveRDS(list(), file_drawer("index.rds")) 46 | 47 | invisible(TRUE) 48 | } 49 | 50 | 51 | 52 | file_drawer_index <- function() { 53 | file_drawer_create() 54 | readRDS(file_drawer("index.rds")) 55 | } 56 | 57 | 58 | 59 | file_drawer_set <- function(url, map, name = NULL) { 60 | if (is.null(name)) { 61 | name <- paste0(digest::digest(url), '.rds') 62 | } 63 | 64 | index <- file_drawer_index() 65 | 66 | if (url %in% names(index)) { 67 | file.remove(file_drawer(index[[url]])) 68 | } 69 | index[[url]] <- name 70 | saveRDS(index, file_drawer("index.rds")) 71 | saveRDS(map, file_drawer(name)) 72 | 73 | invisible(TRUE) 74 | } 75 | 76 | 77 | 78 | file_drawer_get <- function(url) { 79 | index <- file_drawer_index() 80 | name <- index[[url]] 81 | 82 | if (is.null(name)) return(NULL) 83 | readRDS(file_drawer(name)) 84 | } 85 | -------------------------------------------------------------------------------- /R/geom_leg.R: -------------------------------------------------------------------------------- 1 | #' Single line segments with rounded ends 2 | #' 3 | #' This is ggplot2's segment with rounded ends. It's mainly included in ggmap 4 | #' for historical reasons. 5 | #' 6 | #' @inheritParams ggplot2::geom_segment 7 | #' @seealso [ggplot2::geom_segment()], [route()], inspired by 8 | #' `https://spatialanalysis.co.uk/2012/02/great-maps-ggplot2`, no longer 9 | #' active 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 = start_lon, xend = end_lon, 33 | #' y = start_lat, yend = end_lat 34 | #' )) + 35 | #' coord_map() 36 | #' 37 | #' ggplot(data = legs_df) + 38 | #' geom_leg(aes( 39 | #' x = start_lon, xend = end_lon, 40 | #' y = start_lat, yend = end_lat, 41 | #' color = route 42 | #' )) + 43 | #' coord_map() 44 | #' 45 | #' 46 | #' ggmap(map) + 47 | #' geom_leg( 48 | #' aes( 49 | #' x = start_lon, xend = end_lon, 50 | #' y = start_lat, yend = end_lat 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 = start_lon, xend = end_lon, 60 | #' # y = start_lat, yend = end_lat, 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 = start_lon, xend = end_lon, 72 | #' y = start_lat, yend = end_lat, 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 | -------------------------------------------------------------------------------- /R/get_cloudmademap.R: -------------------------------------------------------------------------------- 1 | #' Get a CloudMade map. 2 | #' 3 | #' [get_cloudmademap()] accesses a tile server for Stamen Maps and 4 | #' downloads/stitches map tiles/formats a map image. This function requires an 5 | #' api key which can be obtained for free from http://cloudmade.com/user/show, 6 | #' now defunct. Thousands of maptypes ("styles"), including create-your-own 7 | #' options, are available from http://maps.cloudmade.com/editor (defunct). 8 | #' 9 | #' @param bbox a bounding box in the format c(lowerleftlon, lowerleftlat, 10 | #' upperrightlon, upperrightlat). 11 | #' @param zoom a zoom level 12 | #' @param api_key character string containing cloud made api key, see details 13 | #' @param maptype an integer of what cloud made calls style, see details 14 | #' @param highres double resolution 15 | #' @param crop crop raw map tiles to specified bounding box 16 | #' @param messaging turn messaging on/off 17 | #' @param urlonly return url only 18 | #' @param filename destination file for download (file extension added according 19 | #' to format). Default `NULL` means a random [tempfile()]. 20 | #' @param color color or black-and-white 21 | #' @param ... ... 22 | #' @return a ggmap object (a classed raster object with a bounding box 23 | #' attribute) 24 | #' @author David Kahle \email{david@@kahle.io} 25 | #' @seealso http://maps.cloudmade.com/ (defunct), [ggmap()] 26 | #' @export 27 | 28 | # 29 | # \dontrun{ discontinued service 30 | # 31 | # api_key <- '' 32 | # 33 | # map <- get_cloudmademap(api_key = api_key) 34 | # ggmap(map) 35 | # 36 | # map <- get_cloudmademap(maptype = 997, api_key = api_key) 37 | # ggmap(map) 38 | # 39 | # } 40 | # 41 | get_cloudmademap <- function( 42 | bbox = c(left = -95.80204, bottom = 29.38048, right = -94.92313, top = 30.14344), 43 | zoom = 10, api_key, maptype = 1, highres = TRUE, crop = TRUE, messaging = FALSE, 44 | urlonly = FALSE, filename = NULL, color = c('color','bw'), ... 45 | ){ 46 | 47 | .Defunct(msg = "CloudMade discontinued its static maps service; try `get_stadiamap()`.") 48 | 49 | # enumerate argument checking (added in lieu of checkargs function) 50 | args <- as.list(match.call(expand.dots = TRUE)[-1]) 51 | argsgiven <- names(args) 52 | 53 | if('bbox' %in% argsgiven){ 54 | if(!(is.numeric(bbox) && length(bbox) == 4)){ 55 | cli::cli_abort("{.arg bbox} improperly specified. See {.fn ggmap::get_openstreetmap}.") 56 | } 57 | } 58 | 59 | if('zoom' %in% argsgiven){ 60 | if(!(is.numeric(zoom) && length(zoom) == 1 && 61 | zoom == round(zoom) && zoom >= 0 && zoom <= 18)){ 62 | cli::cli_abort("{.arg scale} must be a positive integer 0-18. See {.fn ggmap::get_cloudmademap}.") 63 | } 64 | } 65 | 66 | if('maptype' %in% argsgiven){ 67 | if(!(is.numeric(maptype) && length(maptype) == 1 && 68 | maptype == round(maptype) && maptype > 0)){ 69 | cli::cli_abort("{.arg maptype} must be a positive integer. See {.fn ggmap::get_cloudmademap}.") 70 | } 71 | } 72 | 73 | if('api_key' %in% argsgiven){ 74 | if(!(is.character(api_key) && length(api_key) == 1)){ 75 | cli::cli_abort("{.arg api_key} improperly specified. See {.fn ggmap::get_cloudmademap}.") 76 | } 77 | } else { 78 | cli::cli_abort("{.arg api_key} must be specified. See {.fn ggmap::get_cloudmademap}.") 79 | } 80 | 81 | if('highres' %in% argsgiven) stopifnot(is.logical(highres)) 82 | 83 | if('messaging' %in% argsgiven) stopifnot(is.logical(messaging)) 84 | 85 | if('urlonly' %in% argsgiven) stopifnot(is.logical(urlonly)) 86 | 87 | if(is.null(filename)){ 88 | destfile <- tempfile(fileext = ".png") 89 | } else{ 90 | filename_stop <- TRUE 91 | if(is.character(filename) && length(filename) == 1) filename_stop <- FALSE 92 | if(filename_stop) cli::cli_abort("{.arg filename} improperly specified. See {.fn ggmap::get_googlemap}.") 93 | destfile <- paste(filename, 'png', sep = '.') 94 | } 95 | 96 | # color arg checked by match.arg 97 | 98 | if('checkargs' %in% argsgiven){ 99 | .Deprecated(msg = 'checkargs argument deprecated, args are always checked after v2.1.') 100 | } 101 | 102 | 103 | # argument checking (no checks for language, region, markers, path, visible, style) 104 | #args <- as.list(match.call(expand.dots = TRUE)[-1]) 105 | #if(checkargs) get_cloudmademap_checkargs(args) 106 | color <- match.arg(color) 107 | if(is.null(names(bbox))) names(bbox) <- c('left','bottom','right','top') 108 | if(highres) maptype <- paste(maptype, '@2x', sep = '') 109 | 110 | # determine tiles to get 111 | fourCorners <- expand.grid( 112 | lon = c(bbox['left'], bbox['right']), 113 | lat = c(bbox['bottom'], bbox['top']) 114 | ) 115 | fourCorners$zoom <- zoom 116 | row.names(fourCorners) <- c('lowerleft','lowerright','upperleft','upperright') 117 | fourCornersTiles <- apply(fourCorners, 1, function(v) LonLat2XY(v[1],v[2],v[3])) 118 | 119 | xsNeeded <- Reduce(':', sort(unique(as.numeric(sapply(fourCornersTiles, function(df) df$X))))) 120 | numXTiles <- length(xsNeeded) 121 | ysNeeded <- Reduce(':', sort(unique(as.numeric(sapply(fourCornersTiles, function(df) df$Y))))) 122 | numYTiles <- length(ysNeeded) 123 | tilesNeeded <- expand.grid(x = xsNeeded, y = ysNeeded) 124 | if(nrow(tilesNeeded) > 40){ 125 | cli::cli_alert_info("{nrow(tilesNeeded)} tiles needed, this may take a while (try a smaller zoom?)") 126 | } 127 | xTileProgression <- rep(1:numXTiles, numYTiles) 128 | yTileProgression <- rep(1:numYTiles, each = numXTiles) 129 | 130 | 131 | # make urls 132 | base_url <- 'http://b.tile.cloudmade.com/' 133 | base_url <- paste(base_url, api_key, '/', maptype, '/', 256, '/', zoom, sep = '') 134 | urls <- paste(base_url, apply(tilesNeeded, 1, paste, collapse = '/'), sep = '/') 135 | urls <- paste(urls, '.png', sep = '') 136 | if(messaging) cli::cli_alert_info("{length(urls)} tiles required.") 137 | if(urlonly) return(urls) 138 | 139 | # download and stitch 140 | size <- 256 * c(length(xsNeeded), length(ysNeeded)) 141 | map <- matrix('NA', nrow = size[2], ncol = size[1]) 142 | 143 | for(k in seq_along(urls)){ 144 | download.file(urls[[k]], destfile = destfile, quiet = !messaging, mode = 'wb') 145 | tile <- readPNG(destfile) 146 | if(color == 'color'){ 147 | tile <- apply(tile, 2, rgb) 148 | } else if(color == 'bw'){ 149 | tile_dim <- dim(tile) 150 | tile <- gray(.30 * tile[,,1] + .59 * tile[,,2] + .11 * tile[,,3]) 151 | dim(tile) <- tile_dim[1:2] 152 | } 153 | 154 | map[ 155 | (1+256*(yTileProgression[k]-1)):(256*yTileProgression[k]), 156 | (1+256*(xTileProgression[k]-1)):(256*xTileProgression[k]) 157 | ] <- tile 158 | } 159 | 160 | # determine bbox of map. note : not the same as the argument bounding box - 161 | # the map is only a covering of the bounding box extent the idea is to get 162 | # the lower left tile and the upper right tile and compute their bounding boxes 163 | # tiles are referenced by top left of tile, starting at 0,0 164 | # see https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames 165 | bboxOfTile <- function(vXY){ 166 | lonlat_upperleft <- XY2LonLat(vXY[1],vXY[2],zoom) 167 | lonlat_lowerright <- XY2LonLat(vXY[1]+1,vXY[2]+1,zoom) 168 | data.frame( 169 | left = lonlat_upperleft$lon, 170 | bottom = lonlat_lowerright$lat, 171 | right = lonlat_lowerright$lon, 172 | top = lonlat_upperleft$lat 173 | ) 174 | } 175 | tileBboxes <- ldply(split(tilesNeeded,1:nrow(tilesNeeded)), 176 | function(df) bboxOfTile(as.numeric(df))) 177 | mbbox <- c( 178 | left = min(tileBboxes$left), 179 | bottom = min(tileBboxes$bottom), 180 | right = max(tileBboxes$right), 181 | top = max(tileBboxes$top) 182 | ) 183 | 184 | 185 | # format map and return if not cropping 186 | if(!crop){ 187 | map <- as.raster(map) 188 | class(map) <- c('ggmap','raster') 189 | attr(map, 'bb') <- data.frame( 190 | ll.lat = mbbox['bottom'], ll.lon = mbbox['left'], 191 | ur.lat = mbbox['top'], ur.lon = mbbox['right'] 192 | ) 193 | 194 | # additional map meta-data 195 | attr(map, "source") <- "google" 196 | attr(map, "maptype") <- maptype 197 | attr(map, "zoom") <- zoom 198 | 199 | # return 200 | return(map) 201 | } 202 | 203 | 204 | # crop map 205 | if(crop){ 206 | slon <- seq(mbbox['left'], mbbox['right'], length.out = size[1]) 207 | slat <- seq(mbbox['top'], mbbox['bottom'], length.out = size[2]) 208 | 209 | keep_x_ndcs <- which(bbox['left'] <= slon & slon <= bbox['right']) 210 | keep_y_ndcs <- which(bbox['bottom'] <= slat & slat <= bbox['top']) 211 | 212 | croppedmap <- map[keep_y_ndcs, keep_x_ndcs] 213 | } 214 | 215 | # format map 216 | croppedmap <- as.raster(croppedmap) 217 | class(croppedmap) <- c('ggmap','raster') 218 | attr(croppedmap, 'bb') <- data.frame( 219 | ll.lat = bbox['bottom'], ll.lon = bbox['left'], 220 | ur.lat = bbox['top'], ur.lon = bbox['right'] 221 | ) 222 | 223 | # additional map meta-data 224 | attr(croppedmap, "source") <- "cloudmade" 225 | attr(croppedmap, "maptype") <- maptype 226 | attr(croppedmap, "zoom") <- zoom 227 | 228 | 229 | # return 230 | croppedmap 231 | } 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | -------------------------------------------------------------------------------- /R/get_navermap.R: -------------------------------------------------------------------------------- 1 | #' Get a Naver Map 2 | #' 3 | #' This is (at least) temporarily unavailable as the Naver API changed. 4 | #' 5 | #' [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. 8 | #' 9 | #' @param center the center of the map. this can be longitude/latitude numeric 10 | #' vector. 11 | #' @param zoom map zoom, an integer from 1 to 14 (building), default value 10 12 | #' @param size rectangular dimensions of map in pixels - horizontal x vertical - 13 | #' with a max of c(640, 640). 14 | #' @param format character string providing image format - png, jpeg(jpg) 15 | #' formats available in various flavors 16 | #' @param crs Coordinate system, this currently supports EPSG:4326 17 | #' @param baselayer base layer, this can be either "default", "satellite". 18 | #' @param color color or black-and-white 19 | #' @param overlayers overlay layers, this can be "anno_satellite","bicycle", 20 | #' "roadview", "traffic". 21 | #' @param markers data.frame with first column longitude, second column 22 | #' latitude, for which naver markers should be embedded in the map image, or 23 | #' character string to be passed directly to api 24 | #' @param key key code from naver api center 25 | #' @param uri registered host url 26 | #' @param filename destination file for download (file extension added according 27 | #' to format). Default `NULL` means a random [tempfile()]. 28 | #' @param messaging turn messaging on/off 29 | #' @param urlonly return url only 30 | #' @param force if the map is on file, should a new map be looked up? 31 | #' @param where where should the file drawer be located (without terminating 32 | #' "/") 33 | #' @param archiving use archived maps. note: by changing to TRUE you agree to 34 | #' abide by any of the rules governing caching naver maps 35 | #' @param ... ... 36 | #' @author Heewon Jeon \email{madjakarta@@gmail.com} 37 | #' @seealso [ggmap()] 38 | #' @export 39 | get_navermap <- function( 40 | center = c(lon = 126.9849208, lat = 37.5664519), zoom = 4, 41 | size = c(640,640), format = c("png", "jpeg", "jpg"), 42 | crs = c("EPSG:4326", "NHN:2048", "NHN:128", "EPSG:4258", "EPSG:4162", "EPSG:2096", "EPSG:2097", "EPSG:2098", "EPSG:900913"), 43 | baselayer = c("default", "satellite"), color = c("color","bw"), 44 | overlayers = c("anno_satellite", "bicycle", "roadview", "traffic"), 45 | markers, key, uri, filename = NULL, messaging = FALSE, urlonly = FALSE, 46 | force = FALSE, where = tempdir(), archiving = TRUE, ... 47 | ){ 48 | 49 | .Defunct(msg = "Naver is at least temporarily not supported, as its API has changed.") 50 | 51 | } 52 | 53 | 54 | -------------------------------------------------------------------------------- /R/get_openstreetmap.R: -------------------------------------------------------------------------------- 1 | #' Get an OpenStreetMap 2 | #' 3 | #' [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{https://www.openstreetmap.org/}. If you don't know how to get 6 | #' the map you want, go there, navigate to the map extent that you want, click 7 | #' the export tab at the top of the page, and copy the information into this 8 | #' function. 9 | #' 10 | #' In some cases the OSM server is unavailable, in these cases you will receive 11 | #' an error message from [utils::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{https://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{https://wiki.openstreetmap.org/wiki/MinScaleDenominator}. smaller 23 | #' scales provide a finer degree of detail, where larger scales produce more 24 | #' coarse detail. The scale argument is a tricky number to correctly specify. 25 | #' In most cases, if you get an error when downloading an openstreetmap the 26 | #' error is attributable to an improper scale specification. 27 | #' [OSM_scale_lookup()] can help; but the best way to get in the correct range 28 | #' is to go to \url{https://www.openstreetmap.org/}, navigate to the map of 29 | #' interest, click export at the top of the page, click 'map image' and then 30 | #' copy down the scale listed. 31 | #' @param format character string providing image format - png, jpeg, svg, pdf, 32 | #' and ps formats 33 | #' @param messaging turn messaging on/off 34 | #' @param urlonly return url only 35 | #' @param filename destination file for download (file extension added according 36 | #' to format). Default `NULL` means a random [tempfile()]. 37 | #' @param color color or black-and-white 38 | #' @param ... ... 39 | #' @return a ggmap object (a classed raster object with a bounding box 40 | #' attribute) 41 | #' @author David Kahle \email{david@@kahle.io} 42 | #' @seealso \url{https://www.openstreetmap.org/}, [ggmap()] 43 | #' @export 44 | 45 | # 46 | # # get_openstreetmap(urlonly = TRUE) 47 | # 48 | # # osm servers get overloaded, which can result in 49 | # # erroneous failed checks 50 | # 51 | # # osm <- get_openstreetmap() 52 | # # ggmap(osm) 53 | # 54 | # 55 | get_openstreetmap <- function( 56 | bbox = c(left = -95.80204, bottom = 29.38048, right = -94.92313, top = 30.14344), 57 | scale = 606250, format = c('png', 'jpeg', 'svg', 'pdf', 'ps'), messaging = FALSE, 58 | urlonly = FALSE, filename = NULL, color = c('color','bw'), ... 59 | ){ 60 | 61 | .Defunct(msg = "OSM is at least temporarily not supported, see https://github.com/dkahle/ggmap/issues/117.") 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 | cli::cli_abort("{.arg bbox} improperly specified, see {.fn ggmap::get_openstreetmap}.") 73 | } 74 | } 75 | 76 | if('scale' %in% argsgiven){ 77 | if(!(is.numeric(scale) && length(scale) == 1 && 78 | scale == round(scale) && scale > 0)){ 79 | cli::cli_abort("{.arg scale} must be a positive integer.") 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") cli::cli_abort("Only {.arg format = \"png\"} is supported.") 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) cli::cli_abort('{.arg filename} improperly specified, see {.fn get_openstreetmap}') 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 (inherits(m, "try-error")) cli::cli_abort('Map grabbing failed, see {.fn get_openstreetmap}.') 126 | 127 | map <- try(readPNG(destfile), silent = T) 128 | if (inherits(map, "try-error")) cli::cli_abort('Map grabbing failed, see {.fn get_openstreetmap}') 129 | 130 | # format file 131 | if(color == 'color'){ 132 | map <- as.raster(apply(map, 2, rgb)) 133 | } else if(color == 'bw'){ 134 | mapd <- dim(map) 135 | map <- gray(.30 * map[,,1] + .59 * map[,,2] + .11 * map[,,3]) 136 | dim(map) <- mapd[1:2] 137 | map <- as.raster(map) 138 | } 139 | class(map) <- c('ggmap','raster') 140 | 141 | # map spatial info 142 | attr(map, 'bb') <- data.frame( 143 | ll.lat = bbox[2], ll.lon = bbox[1], 144 | ur.lat = bbox[4], ur.lon = bbox[3] 145 | ) 146 | 147 | # additional map meta-data 148 | attr(map, "source") <- "osm" 149 | attr(map, "maptype") <- "openstreetmap" 150 | attr(map, "scale") <- scale 151 | 152 | # return 153 | map 154 | } 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | -------------------------------------------------------------------------------- /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.io} 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( 34 | #' aes(x = x, y = y), 35 | #' data = df, color = 'green', size = 1 36 | #' ) + 37 | #' geom_point( 38 | #' aes(x = x, y = y), 39 | #' data = df, color = 'green', size = 3 40 | #' ) 41 | #' 42 | #' } 43 | ggimage <- function(mat, fullpage = TRUE, coord_equal = TRUE, scale_axes = FALSE){ 44 | 45 | x <- NULL; rm(x); y <- NULL; rm(y); 46 | 47 | if(!inherits(mat, c('matrix','imagematrix','array','raster'))){ 48 | cli::cli_abort("{.arg mat} should be a matrix or array.") 49 | } 50 | 51 | n <- nrow(mat) 52 | p <- ncol(mat) 53 | 54 | if(scale_axes) n <- p <- 2 55 | 56 | fourCorners <- expand.grid(x = 0:(p-1), y = 0:(n-1)) 57 | 58 | if(max(mat) > 1 || min(mat) < 0){ 59 | cli::cli_alert_info("Rescaling {.arg mat} to [0,1]") 60 | mat <- (mat - min(mat)) / (max(mat) - min(mat)) 61 | } 62 | 63 | raster <- as.raster(mat) 64 | 65 | plot <- ggplot(aes(x, y), data = fourCorners) + geom_blank() + 66 | #ggmap:::annotation_raster(raster, 0, p-1, 0, n-1) + 67 | annotation_raster(raster, 0, p-1, 0, n-1) + 68 | scale_x_continuous(expand = c(0,0)) + 69 | scale_y_continuous(expand = c(0,0)) 70 | 71 | if(fullpage) plot <- plot + theme_nothing() 72 | 73 | if(coord_equal) plot <- plot + coord_equal() 74 | 75 | plot 76 | } 77 | -------------------------------------------------------------------------------- /R/gglocator.R: -------------------------------------------------------------------------------- 1 | #' Locator for ggplot objects 2 | #' 3 | #' Locator for ggplot objects (Note : only accurate when extent = "normal" when 4 | #' using ggmap.) 5 | #' 6 | #' @param n number of points to locate. 7 | #' @param message unused 8 | #' @param mercator logical flag; should the plot be treated as using the 9 | #' projection common to most web map services? Set to FALSE if the axes on the 10 | #' plot use a linear scale. 11 | #' @param ... additional arguments (including deprecated, e.g. xexpand) 12 | #' @return a data frame with columns according to the x and y aesthetics 13 | #' @author Tyler Rinker, Baptiste Auguie, DWin, David Kahle, \@Nikolai-Hlubek 14 | #' and \@mvkorpel. 15 | #' @export 16 | #' @examples 17 | #' 18 | #' if (interactive()) { 19 | #' 20 | #' # only run for interactive sessions 21 | #' df <- expand.grid(x = 0:-5, y = 0:-5) 22 | #' 23 | #' ggplot(df, aes(x, y)) + geom_point() + 24 | #' annotate(geom = "point", x = -2, y = -2, colour = "red") 25 | #' 26 | #' (pt <- gglocator(mercator = FALSE)) # click red point 27 | #' 28 | #' last_plot() + 29 | #' annotate("point", pt$x, pt$y, color = "blue", size = 3, alpha = .5) 30 | #' 31 | #' hdf <- get_map("houston, texas") 32 | #' ggmap(hdf, extent = "normal") 33 | #' (pt <- gglocator(mercator = TRUE)) 34 | #' last_plot() + 35 | #' annotate("point", pt$lon, pt$lat, color = "blue", size = 3, alpha = .5) 36 | #' 37 | #' } 38 | #' 39 | #' 40 | gglocator <- function(n = 1, message = FALSE, mercator = TRUE, ...){ 41 | 42 | if ( 43 | .Platform$GUI == "RStudio" && str_detect(.Device, "(RStudio)|(null device)") 44 | ) { 45 | cli::cli_abort( 46 | "{.fn ggmap::gglocator} is unreliable in the RStudio plot viewer. Create a different device with {.fn grDevices::x11} or {.fn grDevices::quartz}." 47 | ) 48 | } 49 | 50 | args <- as.list(match.call(expand.dots = FALSE)) 51 | if ( "..." %in% names(args) && any(c("xexpand", "yexpand") %in% names(args$`...`)) ) { 52 | cli::cli_alert_warning("{.arg xexpand} and {.arg yexpand} are no longer used in {.fn ggmap::gglocator}.") 53 | } 54 | 55 | if (n > 1) { 56 | df <- NULL 57 | for (k in 1:n) { 58 | df <- rbind(df, gglocator(message = message, mercator = mercator, ...)) 59 | } 60 | return(df) 61 | } 62 | 63 | object <- last_plot() 64 | if(is.null(object)) cli::cli_abort("No plots available.") 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) cli::cli_abort("{.pkg ggplot2} graphic not detected in current device.") 72 | if (n_panels > 1) { 73 | x <- x[1] 74 | cli::cli_alert_warning("Multiple plots detected, using the first one (\"{x}\")") 75 | } 76 | previous_viewport <- current.vpPath() 77 | seekViewport(x, recording = FALSE) 78 | 79 | # when exiting function, return to previous position in viewport tree 80 | on.exit(upViewport(0, recording = FALSE)) 81 | if (!is.null(previous_viewport)) { 82 | on.exit(downViewport(previous_viewport, strict = TRUE, recording = FALSE), add = TRUE) 83 | } 84 | 85 | # get the position relative to that viewport 86 | loc <- as.numeric(grid.locator("npc")) 87 | 88 | # scale the position to the plot 89 | 90 | # get the x.range and y.range from ggplot 91 | plot_info <- ggplot_build(object) 92 | if ("layout" %in% names(plot_info)) { 93 | xrng <- plot_info$layout$panel_params[[1]]$x.range 94 | yrng <- plot_info$layout$panel_params[[1]]$y.range 95 | } else { 96 | cli::cli_abort("No plot layout.") 97 | } 98 | 99 | # format and return 100 | point <- data.frame( 101 | xrng[1] + loc[1]*diff(xrng), 102 | yrng[1] + loc[2]*diff(yrng) 103 | ) 104 | 105 | if(isTRUE(mercator)){ 106 | yrng2 <- LonLat2XY(0, yrng, zoom = 0, ypix = 256)$y 107 | point[[2]] <- XY2LonLat( 108 | x = 0, y = yrng2[1] + loc[2] * diff(yrng2), 109 | X = 0, Y = 0, 110 | zoom = 0, ypix = 256)[[2]] 111 | } 112 | 113 | names(point) <- c(object$labels$x, object$labels$y) 114 | point 115 | } 116 | -------------------------------------------------------------------------------- /R/ggmap-defunct.R: -------------------------------------------------------------------------------- 1 | #' Defunct ggmap functions 2 | #' 3 | #' As provider services change over time, ggmap has to make corresponding 4 | #' changes. Since its inception, a few services have stopped offering their 5 | #' previous functionality, and in some cases this has required us to remove 6 | #' those functions from the package entirely. 7 | #' 8 | #' The following are defunct ggmap functions: 9 | #' \itemize{ 10 | #' \item get_cloudemademap 11 | #' \item get_navermap 12 | #' \item get_openstreetmap 13 | #' \item get_stamenmap 14 | #' } 15 | #' 16 | #' @name ggmap-defunct 17 | NULL 18 | -------------------------------------------------------------------------------- /R/ggmap-package.R: -------------------------------------------------------------------------------- 1 | #' @import ggplot2 2 | #' @name ggmap 3 | #' @importFrom png readPNG 4 | #' @importFrom jpeg readJPEG 5 | #' @importFrom plyr arrange compact ddply desc dlply is.discrete is.formula join 6 | #' ldply llply . 7 | #' @importFrom bitops bitOr bitShiftL bitShiftR bitAnd 8 | #' @importFrom grDevices as.raster extendrange gray rgb 9 | #' @importFrom stats time asOneSidedFormula 10 | #' @importFrom utils URLencode download.file tail 11 | #' @importFrom grid rasterGrob seekViewport grid.locator upViewport downViewport 12 | #' current.vpTree current.vpPath viewport 13 | #' @importFrom scales expand_range 14 | #' @importFrom dplyr bind_cols filter bind_rows mutate group_by ungroup select 15 | #' right_join 16 | #' @importFrom glue glue 17 | #' @importFrom httr GET http_status warn_for_status stop_for_status 18 | #' @importFrom tibble tibble as_tibble 19 | #' @importFrom stringr str_to_title str_c str_detect str_c str_replace_all 20 | #' str_sub str_trim str_pad str_split str_trunc str_detect str_replace 21 | #' str_extract 22 | #' @importFrom purrr map map_chr map_int walk flatten pluck imap cross_df 23 | #' flatten_chr 24 | #' @importFrom rlang set_names 25 | #' @importFrom magrittr %>% 26 | #' @importFrom tidyr nest unnest spread 27 | #' @importFrom cli cli_warn cli_abort cli_alert_info cli_alert_danger 28 | #' @aliases ggmap ggmap-package 29 | NULL 30 | -------------------------------------------------------------------------------- /R/ggmap_options.R: -------------------------------------------------------------------------------- 1 | #' ggmap Options 2 | #' 3 | #' ggmap stores options as a named list in R's global options, i.e. 4 | #' `getOption("ggmap")`. It currently stores two such options, one for Google 5 | #' credentialing and one to suppress private API information in the URLs printed 6 | #' to the screen when web queries are placed. For both of those, see 7 | #' [register_google()]. 8 | #' 9 | #' @param ... a named listing of options to set 10 | #' @param option a specific option to query, e.g. `"display_api_key"` 11 | #' @return NULL 12 | #' @name ggmap_options 13 | #' @author David Kahle \email{david@@kahle.io} 14 | #' @seealso [register_google()] 15 | #' @examples 16 | #' 17 | #' getOption("ggmap") 18 | #' has_ggmap_options() 19 | #' has_ggmap_option("display_api_key") 20 | #' 21 | #' 22 | #' 23 | 24 | 25 | 26 | 27 | 28 | #' @rdname ggmap_options 29 | #' @export 30 | set_ggmap_option <- function(...) { 31 | 32 | # if there is no ggmap option create the list with the arguments and return 33 | if (!has_ggmap_options()) { 34 | options("ggmap" = list(...)) 35 | return(invisible()) 36 | } 37 | 38 | # otherwise, go through arguments sequentially and add/update 39 | # them in the list ggmap in options 40 | ggmap <- getOption("ggmap") 41 | arg_list <- lapply(as.list(match.call())[-1], eval, envir = parent.frame()) 42 | for (k in seq_along(arg_list)) { 43 | if (names(arg_list)[k] %in% names(ggmap)) { 44 | ggmap[names(arg_list)[k]] <- arg_list[k] 45 | } else { 46 | ggmap <- c(ggmap, arg_list[k]) 47 | } 48 | } 49 | 50 | # set new ggmap 51 | options("ggmap" = ggmap) 52 | 53 | # return 54 | invisible() 55 | } 56 | 57 | 58 | 59 | #' @rdname ggmap_options 60 | #' @export 61 | has_ggmap_options <- function () !is.null(getOption("ggmap")) 62 | 63 | 64 | 65 | #' @rdname ggmap_options 66 | #' @export 67 | has_ggmap_option <- function (option) { 68 | 69 | if (has_ggmap_options()) { 70 | option %in% names(getOption("ggmap")) 71 | } else { 72 | FALSE 73 | } 74 | 75 | } 76 | 77 | 78 | 79 | #' @rdname ggmap_options 80 | #' @export 81 | ggmap_credentials <- function () { 82 | 83 | .Deprecated('getOption("ggmap")') 84 | getOption("ggmap") 85 | 86 | } 87 | 88 | 89 | 90 | 91 | 92 | # #' @rdname ggmap_options 93 | # #' @export 94 | # print.ggmap_credentials <- function (x, ...) { 95 | # 96 | # for (k in seq_along(x)) { 97 | # cat(str_to_title(names(x)[k]), "- \n") 98 | # for (i in 1:length(x[[k]])) { 99 | # cat(" ", names(x[[k]])[i], ": ") 100 | # val <- x[[k]][[i]] 101 | # cat(ifelse(is.na(val), "", val), "\n") 102 | # } 103 | # } 104 | # 105 | # } 106 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /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 -------------------------------------------------------------------------------- /R/helpers.R: -------------------------------------------------------------------------------- 1 | `%notin%` <- function (elem, set) !(elem %in% set) 2 | 3 | is.wholenumber <- function (x, tol = .Machine$double.eps^0.5) abs(x - round(x)) < tol 4 | 5 | # key <- "aBc" 6 | # fmteq(key) 7 | # fmteq(key, tolower) 8 | # fmteq(key, toupper) 9 | fmteq <- function (x, f = function(.) ., ...) { 10 | paste0(deparse(substitute(x)), "=", f(x, ...)) 11 | } 12 | 13 | 14 | 15 | #' @importFrom magrittr %>% 16 | #' @export 17 | magrittr::`%>%` 18 | 19 | 20 | 21 | 22 | 23 | source_url_msg <- function(msg, strip_http = FALSE) { 24 | if (length(msg) > 1) return(invisible(sapply(msg, source_url_msg, strip_http = strip_http))) 25 | if (strip_http) msg <- gsub("https?://", "", msg) 26 | cli::cli_alert_info("{.url {msg}}") 27 | } 28 | # source_url_msg("https://www.kahle.io") 29 | # source_url_msg("https://www.kahle.io", strip_http = FALSE) 30 | # source_url_msg(c("https://www.kahle.io", "https://www.baylor.edu")) 31 | # source_url_msg(c("https://www.kahle.io", "https://www.baylor.edu"), strip_http = FALSE) 32 | -------------------------------------------------------------------------------- /R/inset.R: -------------------------------------------------------------------------------- 1 | #' Add ggplot2 insets to a map 2 | #' 3 | #' This is identical to ggplot2::annotation_custom for use with ggmap 4 | #' 5 | #' Most useful for adding tables, inset plots, and other grid-based decorations 6 | #' 7 | #' @param grob grob to display 8 | #' @param xmin,xmax x location (in data coordinates) giving horizontal location 9 | #' of raster 10 | #' @param ymin,ymax y location (in data coordinates) giving vertical location of 11 | #' raster 12 | #' @export inset 13 | #' @note [annotation_custom()] expects the grob to fill the entire viewport 14 | #' defined by xmin, xmax, ymin, ymax. Grobs with a different (absolute) size 15 | #' will be center-justified in that region. Inf values can be used to fill the 16 | #' full plot panel 17 | inset <- annotation_custom <- function(grob, xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf) { 18 | layer( 19 | data = NULL, 20 | stat = ggplot2::StatIdentity, 21 | position = ggplot2::PositionIdentity, 22 | geom = GeomCustomAnn, 23 | inherit.aes = TRUE, 24 | params = list( 25 | grob = grob, 26 | xmin = xmin, 27 | xmax = xmax, 28 | ymin = ymin, 29 | ymax = ymax 30 | ) 31 | ) 32 | } 33 | 34 | 35 | GeomCustomAnn <- ggproto("GeomCustomAnn", Geom, 36 | extra_params = "", 37 | handle_na = function(data, params) { 38 | data 39 | }, 40 | 41 | draw_panel = function(data, panel_scales, coord, grob, xmin, xmax, 42 | ymin, ymax) { 43 | # if (!inherits(coord, "CoordCartesian")) { 44 | # stop("annotation_custom only works with Cartesian coordinates", 45 | # call. = FALSE) 46 | # } 47 | corners <- data.frame(x = c(xmin, xmax), y = c(ymin, ymax)) 48 | data <- coord$transform(corners, panel_scales) 49 | 50 | x_rng <- range(data$x, na.rm = TRUE) 51 | y_rng <- range(data$y, na.rm = TRUE) 52 | 53 | vp <- viewport(x = mean(x_rng), y = mean(y_rng), 54 | width = diff(x_rng), height = diff(y_rng), 55 | just = c("center","center")) 56 | editGrob(grob, vp = vp, name = paste(grob$name, annotation_id())) 57 | }, 58 | 59 | default_aes = aes_(xmin = -Inf, xmax = Inf, ymin = -Inf, ymax = Inf) 60 | ) 61 | 62 | 63 | 64 | 65 | 66 | annotation_id <- local({ 67 | i <- 1 68 | function() { 69 | i <<- i + 1 70 | i 71 | } 72 | }) 73 | -------------------------------------------------------------------------------- /R/inset_raster.R: -------------------------------------------------------------------------------- 1 | #' Create a (ggplot2) raster layer 2 | #' 3 | #' This is a special version of ggplot2::annotation_raster for use with ggmap. 4 | #' (It simply removes the requirement for cartesian coordinates.) The only 5 | #' difference between [inset_raster()] and [inset_ggmap()] is their arguments. 6 | #' [inset_ggmap()] is simply a wrapper of [inset_raster()] with `xmin`, `...`, 7 | #' `ymax` arguments equal to the map's bounding box. 8 | #' 9 | #' @param raster raster object to display 10 | #' @param xmin,xmax x location (in data coordinates) giving horizontal location 11 | #' of raster 12 | #' @param ymin,ymax y location (in data coordinates) giving vertical location of 13 | #' raster 14 | #' @param interpolate interpolate the raster? (i.e. antialiasing) 15 | #' @param ggmap a ggmap object, see [get_map()] 16 | #' @export 17 | #' @seealso [bb2bbox()] 18 | #' @name inset_raster 19 | #' @examples 20 | #' 21 | #' \dontrun{ # save cran check time 22 | #' 23 | #' bbox <- c(left = -97.1268, bottom = 31.536245, right = -97.099334, top = 31.559652) 24 | #' 25 | #' terrain_map <- get_stadiamap(bbox, zoom = 14, maptype = "stamen_terrain_background", color = "bw") 26 | #' ggmap(terrain_map) 27 | #' 28 | #' lines_map <- get_stadiamap(bbox, zoom = 14, maptype = "stamen_toner_lines") 29 | #' ggmap(lines_map) 30 | #' 31 | #' ggmap(terrain_map) + 32 | #' inset_ggmap(lines_map) 33 | #' 34 | #' 35 | #' } 36 | #' 37 | #' 38 | inset_raster <- annotation_raster <- function(raster, xmin, xmax, ymin, ymax, interpolate = TRUE) { 39 | raster <- grDevices::as.raster(raster) 40 | 41 | # add possibility that xmin is c(xmin, xmax, ymin, ymax) 42 | if(length(xmin) == 4 && missing(xmax)){ 43 | xmax <- xmin[2] 44 | ymin <- xmin[3] 45 | ymax <- xmin[4] 46 | xmin <- xmin[1] 47 | } 48 | 49 | layer( 50 | data = NULL, 51 | mapping = NULL, 52 | stat = ggplot2::StatIdentity, 53 | position = ggplot2::PositionIdentity, 54 | geom = GeomRasterAnn, 55 | inherit.aes = TRUE, 56 | params = list( 57 | raster = raster, 58 | xmin = xmin, 59 | xmax = xmax, 60 | ymin = ymin, 61 | ymax = ymax, 62 | interpolate = interpolate 63 | ) 64 | ) 65 | 66 | } 67 | 68 | 69 | #' @rdname inset_raster 70 | #' @export 71 | inset_ggmap <- function(ggmap){ 72 | stopifnot(inherits(ggmap, "ggmap")) 73 | bb <- attr(ggmap, "bb") 74 | bbox <- bb2bbox(bb) 75 | 76 | inset_raster(ggmap, bbox[c("left", "right", "bottom", "top")]) 77 | } 78 | 79 | 80 | 81 | GeomRasterAnn <- ggproto("GeomRasterAnn", Geom, 82 | extra_params = "", 83 | handle_na = function(data, params) { 84 | data 85 | }, 86 | 87 | draw_panel = function(data, panel_scales, coord, raster, xmin, xmax, 88 | ymin, ymax, interpolate = FALSE) { 89 | # if (!inherits(coord, "CoordCartesian")) { 90 | # stop("annotation_raster only works with Cartesian coordinates", 91 | # call. = FALSE) 92 | # } 93 | corners <- data.frame(x = c(xmin, xmax), y = c(ymin, ymax)) 94 | data <- coord$transform(corners, panel_scales) 95 | 96 | x_rng <- range(data$x, na.rm = TRUE) 97 | y_rng <- range(data$y, na.rm = TRUE) 98 | 99 | rasterGrob(raster, x_rng[1], y_rng[1], 100 | diff(x_rng), diff(y_rng), default.units = "native", 101 | just = c("left","bottom"), interpolate = interpolate) 102 | } 103 | ) 104 | 105 | -------------------------------------------------------------------------------- /R/make_bbox.R: -------------------------------------------------------------------------------- 1 | #' Compute a bounding box 2 | #' 3 | #' Compute a bounding box for a given longitude / latitude collection. 4 | #' 5 | #' @param lon longitude 6 | #' @param lat latitude 7 | #' @param data (optional) a data frame containing lon and lat as variables 8 | #' @param f number specifying the fraction by which the range should be 9 | #' extended. if length 2 vector, applies to longitude and then latitude. 10 | #' @export 11 | #' @examples 12 | #' 13 | #' make_bbox(lon, lat, data = crime) 14 | #' make_bbox(lon, lat, data = crime, f = .20) 15 | #' make_bbox(lon, lat, data = crime, f = c(.20, .05)) 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 | if (length(f) == 1L) f <- rep(f, 2) 31 | 32 | lon_range <- extendrange(range(lon, na.rm = TRUE), f = f[1]) 33 | lat_range <- extendrange(range(lat, na.rm = TRUE), f = f[2]) 34 | c(left = lon_range[1], bottom = lat_range[1], 35 | right = lon_range[2], top = lat_range[2]) 36 | } 37 | -------------------------------------------------------------------------------- /R/not-exported-ggplot2.R: -------------------------------------------------------------------------------- 1 | # is.constant <- get("is.constant", envir = asNamespace("ggplot2")) 2 | is.constant <- function (x) { 3 | is_I_call <- function(x) is.call(x) && identical(x[[1]], quote(I)) 4 | vapply(x, is_I_call, logical(1)) 5 | } 6 | 7 | 8 | 9 | 10 | 11 | 12 | # rename_aes <- get("rename_aes", envir = asNamespace("ggplot2")) 13 | rename_aes <- function (x) { 14 | names(x) <- standardise_aes_names(names(x)) 15 | duplicated_names <- names(x)[duplicated(names(x))] 16 | if (length(duplicated_names) > 0L) { 17 | cli::cli_warn("Duplicated aesthetics after name standardisation: {.field {unique0(duplicated_names)}}") 18 | } 19 | x 20 | } 21 | 22 | # rename_aes() requires standardise_aes_names() 23 | standardise_aes_names <- function(x) { 24 | x <- sub("color", "colour", x, fixed = TRUE) 25 | revalue(x, ggplot_global__base_to_ggplot) 26 | } 27 | 28 | # standardise_aes_names() requires revalue() 29 | revalue <- function (x, replace) { 30 | if (is.character(x)) { 31 | replace <- replace[names(replace) %in% x] 32 | if (length(replace) == 0) 33 | return(x) 34 | x[match(names(replace), x)] <- replace 35 | } 36 | else if (is.factor(x)) { 37 | lev <- levels(x) 38 | replace <- replace[names(replace) %in% lev] 39 | if (length(replace) == 0) return(x) 40 | lev[match(names(replace), lev)] <- replace 41 | levels(x) <- lev 42 | } 43 | else if (!is.null(x)) { 44 | cli::cli_abort("{.arg x} must be a factor or character vector") 45 | } 46 | x 47 | } 48 | 49 | # standardise_aes_names() requires ggplot_global$base_to_ggplot 50 | ggplot_global__base_to_ggplot <- c( 51 | col = "colour", 52 | color = "colour", 53 | pch = "shape", 54 | cex = "size", 55 | lty = "linetype", 56 | lwd = "size", 57 | srt = "angle", 58 | adj = "hjust", 59 | bg = "fill", 60 | fg = "colour", 61 | min = "ymin", 62 | max = "ymax" 63 | ) 64 | 65 | 66 | 67 | # .all_aesthetics <- get(".all_aesthetics", envir = asNamespace("ggplot2")) 68 | .all_aesthetics <- c("adj", "alpha", "angle", "bg", "cex", "col", "color", "colour", 69 | "fg", "fill", "group", "hjust", "label", "linetype", "lower", 70 | "lty", "lwd", "max", "middle", "min", "pch", "radius", "sample", 71 | "shape", "size", "srt", "upper", "vjust", "weight", "width", 72 | "x", "xend", "xmax", "xmin", "xintercept", "y", "yend", "ymax", 73 | "ymin", "yintercept", "z") 74 | 75 | 76 | -------------------------------------------------------------------------------- /R/not-exported-plyr.R: -------------------------------------------------------------------------------- 1 | # list_to_dataframe <- get("list_to_dataframe", envir = asNamespace("plyr")) 2 | -------------------------------------------------------------------------------- /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 `x`. 9 | #' @export 10 | #' @examples 11 | #' 12 | #'\dontrun{ requires a Stadia Maps API key. see ?register_stadiamaps 13 | #' 14 | #' get_stadiamap(zoom = 9) 15 | #' 16 | #'} 17 | #' 18 | print.ggmap <- function(x, ...){ 19 | 20 | source <- switch(attr(x, "source"), 21 | "google" = "Google Maps", 22 | "stadia" = "Stadia Maps", 23 | "osm" = "OpenStreetMap", 24 | "cloudmade" = "Cloudmade", 25 | "naver" = "Naver Map" 26 | ) 27 | 28 | cli::cli_text("{nrow(x)}x{ncol(x)} {attr(x, 'maptype')} map image from {source}; \\ 29 | use {.fn ggmap::ggmap} to plot it.") 30 | 31 | invisible(x) 32 | } 33 | 34 | -------------------------------------------------------------------------------- /R/qmap.R: -------------------------------------------------------------------------------- 1 | #' Quick map plot 2 | #' 3 | #' qmap is a wrapper for [ggmap()] and [get_map()]. 4 | #' 5 | #' @param location character; location of interest 6 | #' @param ... stuff to pass to [ggmap()] and [get_map()] 7 | #' @return a ggplot object 8 | #' @author David Kahle \email{david@@kahle.io} 9 | #' @seealso [ggmap()] and [get_map()] 10 | #' @export 11 | #' @examples 12 | #' 13 | #' \dontrun{ some requires Google API key; heavy network/time load 14 | #' 15 | #' location <- "marrs mclean science, waco, texas" 16 | #' qmap(location) 17 | #' qmap(location, zoom = 14) 18 | #' qmap(location, zoom = 14, source = "osm") 19 | #' qmap(location, zoom = 14, source = "osm", scale = 20000) 20 | #' qmap(location, zoom = 14, maptype = "satellite") 21 | #' qmap(location, zoom = 14, maptype = "hybrid") 22 | #' qmap(location, zoom = 14, maptype = "stamen_toner", source = "stadia") 23 | #' qmap(location, zoom = 14, maptype = "stamen_watercolor", source = "stadia") 24 | #' qmap(location, zoom = 14, maptype = "stamen_terrain_background", source = "stadia") 25 | #' qmap(location, zoom = 14, maptype = "stamen_toner_lite", source = "stadia") 26 | #' 27 | #' where <- "the white house, washington dc" 28 | #' wh <- geocode(where) 29 | #' qmap(where, maprange = TRUE, zoom = 15, 30 | #' base_layer = ggplot(aes(x=lon, y=lat), data = wh)) + 31 | #' geom_point() 32 | #' 33 | #' 34 | #' 35 | #' } 36 | #' 37 | qmap <- function(location = "houston", ...){ 38 | 39 | # location formatting 40 | location_stop <- TRUE 41 | if(is.character(location) && length(location) == 1){ 42 | # address 43 | location_stop <- FALSE 44 | } 45 | if(is.numeric(location) && length(location) == 2){ 46 | # lonlat 47 | location_stop <- FALSE 48 | } 49 | if(is.numeric(location) && length(location) == 4){ 50 | # bbox 51 | location_stop <- FALSE 52 | } 53 | if(location_stop){ 54 | cli::cli_abort("{.arg location} improperly specified, see {.fn ggmap::get_map}") 55 | } 56 | 57 | args <- as.list(match.call(expand.dots = TRUE)[-1]) 58 | 59 | # get_map args 60 | ################## 61 | 62 | if("zoom" %in% names(args)){ 63 | zoom <- eval(args$zoom) 64 | } else { 65 | zoom <- 10 66 | } 67 | 68 | if("scale" %in% names(args)){ 69 | scale <- eval(args$scale) 70 | } else { 71 | scale <- "auto" 72 | } 73 | 74 | if("color" %in% names(args)){ 75 | color <- eval(args$color) 76 | } else { 77 | color <- "color" 78 | } 79 | 80 | if("source" %in% names(args)){ 81 | source <- eval(args$source) 82 | } else { 83 | source <- "google" 84 | } 85 | 86 | if("force" %in% names(args)){ 87 | force <- eval(args$force) 88 | } else { 89 | if(source == "google"){ 90 | force <- FALSE #TRUE 91 | } else { 92 | force <- FALSE 93 | } 94 | } 95 | 96 | if("maptype" %in% names(args)){ 97 | maptype <- eval(args$maptype) 98 | } else { 99 | if(source == "stadia") { 100 | maptype <- "stamen_terrain" 101 | } 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_stadiamaps.R: -------------------------------------------------------------------------------- 1 | #' Register a Stadia Maps API Key 2 | #' 3 | #' This page contains documentation for tools related to enabling Stadia Maps 4 | #' services in R. See the Details section of this file for background 5 | #' information. 6 | #' 7 | #' To obtain an API key and enable services, go to 8 | #' \url{https://client.stadiamaps.com/signup/}. It is completely free for non-commercial 9 | #' and evaluation use (a license is for commercial use; see \url{https://stadiamaps.com/pricing} 10 | #' for pricing), and no credit card is required to sign up. 11 | #' 12 | #' To tell ggmap about your API key, use [register_stadiamaps()], e.g. 13 | #' `register_stadiamaps(key = "YOUR-API-KEY")` (that's a 14 | #' fake key). This will set your API key for the current session, but if you 15 | #' restart R, you'll need to do it again. You can set it permanently by setting 16 | #' `write = TRUE`, see the examples. If you set it permanently it will be stored 17 | #' in your .Renviron file, and that will be accessed by ggmap persistently 18 | #' across sessions. 19 | #' 20 | #' Users should be aware that the API key, is a PRIVATE key - it uniquely identifies and 21 | #' authenticates you to Stadia Maps' services. If anyone gets your API key, they can 22 | #' use it to masquerade as you to Stadia Maps and potentially use services that you 23 | #' have enabled. While Stadia Maps requires you to opt in to additional usage-based billing, 24 | #' this also means that anyone who obtains your key can potentially incur charges on your behalf 25 | #' or steal the quota that you have already purchased. So be 26 | #' sure to not share your API key. To mitigate against users inadvertently 27 | #' sharing their keys, by default ggmap never displays a user's key in messages 28 | #' displayed to the console. 29 | #' 30 | #' Users should also be aware that ggmap has no mechanism with which to 31 | #' safeguard the private key once registered with R. That is to say, once you 32 | #' register your API key, any function R will have access to it. As a 33 | #' consequence, ggmap will not know if another function, potentially from a 34 | #' compromised package, accesses the key and uploads it to a third party. For 35 | #' this reason, when using ggmap we recommend a heightened sense of security and 36 | #' self-awareness: only use trusted packages, do not save API keys in script 37 | #' files, routinely cycle keys (regenerate new keys and retire old ones), etc. 38 | #' 39 | #' @param key an api key 40 | #' @param write if TRUE, stores the secrets provided in the .Renviron file 41 | #' @return NULL 42 | #' @name register_stadiamaps 43 | #' @seealso \url{https://docs.stadiamaps.com/authentication/}, 44 | #' \url{https://stadiamaps.com/pricing}, 45 | #' \url{https://client.stadiamaps.com/signup/} 46 | #' 47 | #' 48 | #' 49 | #' @examples 50 | #' 51 | #' # this sets your Stadia Maps API key for this session 52 | #' # register_stadiamaps(key = "YOUR-API-KEY") 53 | #' 54 | #' # this sets your Stadia Maps API key permanently 55 | #' # register_stadiamaps(key = "YOUR-API-KEY", write = TRUE) 56 | #' 57 | #' has_stadiamaps_key() 58 | #' stadiamaps_key() 59 | 60 | #' @rdname register_stadiamaps 61 | #' @export 62 | register_stadiamaps <- function (key, write = FALSE) { 63 | # allow register_stadiamaps to work when ggmap not loaded 64 | if (!has_ggmap_options()) bootstrap_ggmap() 65 | 66 | if (write) { 67 | # grab .Renviron file path 68 | environ_file <- file.path(Sys.getenv("HOME"), ".Renviron") 69 | 70 | # create .Renviron file if it does not exist 71 | if(!file.exists(file.path(Sys.getenv("HOME"), ".Renviron"))) { 72 | cli::cli_alert_info('Creating file {environ_file}') 73 | file.create(environ_file) 74 | } 75 | 76 | # read in lines 77 | environ_lines <- readLines(environ_file) 78 | 79 | # if no key present, add; otherwise replace old one 80 | if (!any(str_detect(environ_lines, "GGMAP_STADIAMAPS_API_KEY="))) { 81 | 82 | cli::cli_alert_info('Adding key to {environ_file}') 83 | environ_lines <- c(environ_lines, glue("GGMAP_STADIAMAPS_API_KEY={key}")) 84 | writeLines(environ_lines, environ_file) 85 | 86 | } else { 87 | 88 | key_line_index <- which(str_detect(environ_lines, "GGMAP_STADIAMAPS_API_KEY=")) 89 | old_key <- str_extract(environ_lines[key_line_index], "(?<=GGMAP_STADIAMAPS_API_KEY=)\\w+") 90 | cli::cli_alert_info('Replacing old key ({old_key}) with new key in {environ_file}') 91 | environ_lines[key_line_index] <- glue("GGMAP_STADIAMAPS_API_KEY={key}") 92 | writeLines(environ_lines, environ_file) 93 | 94 | } 95 | } 96 | 97 | Sys.setenv("GGMAP_STADIAMAPS_API_KEY" = key) 98 | 99 | # return 100 | invisible(NULL) 101 | } 102 | 103 | #' @rdname register_stadiamaps 104 | #' @export 105 | stadiamaps_key <- function () { 106 | 107 | key <- Sys.getenv("GGMAP_STADIAMAPS_API_KEY") 108 | 109 | if (key == "") { 110 | return(NA_character_) 111 | } else { 112 | return(key) 113 | } 114 | 115 | } 116 | 117 | 118 | #' @rdname register_stadiamaps 119 | #' @export 120 | has_stadiamaps_key <- function () !is.na(stadiamaps_key()) 121 | -------------------------------------------------------------------------------- /R/revgeocode.R: -------------------------------------------------------------------------------- 1 | #' Reverse geocode 2 | #' 3 | #' Reverse geocodes (looks up the address of) a longitude/latitude location 4 | #' using the Google Geocoding API. Note: To use Google's Geocoding API, you must 5 | #' first enable the API in the Google Cloud Platform Console. See 6 | #' [register_google()]. 7 | #' 8 | #' @param location a location in longitude/latitude format 9 | #' @param output "address" or "all" 10 | #' @param force force online query, even if cached (previously downloaded) 11 | #' @param urlonly return only the url? 12 | #' @param override_limit override the current query rate 13 | #' @param ext top level domain extension (e.g. "com", "co.nz") 14 | #' @param inject character string to add to the url 15 | #' @param ... ... 16 | #' @return a character(1) address or a list (the parsed json output from Google) 17 | #' @author David Kahle \email{david@@kahle.io} 18 | #' @seealso \url{https://developers.google.com/maps/documentation/geocoding/} 19 | #' @export 20 | #' @examples 21 | #' 22 | #' \dontrun{ requires Google API key, see ?register_google 23 | #' 24 | #' ## basic usage 25 | #' ######################################## 26 | #' 27 | #' ( gc <- as.numeric(geocode("the white house")) ) 28 | #' revgeocode(gc) 29 | #' str(revgeocode(gc, output = "all"), 3) 30 | #' 31 | #' } 32 | #' 33 | revgeocode <- function ( 34 | location, 35 | output = c("address","all"), 36 | force = FALSE, 37 | urlonly = FALSE, 38 | override_limit = FALSE, 39 | ext = "com", 40 | inject = "", 41 | ... 42 | ) { 43 | 44 | 45 | # check parameters 46 | stopifnot(is.numeric(location) && length(location) == 2) 47 | output <- match.arg(output) 48 | stopifnot(is.logical(override_limit)) 49 | 50 | if (!has_google_key() && !urlonly) { 51 | cli::cli_abort("Google now requires an API key; see {.fn ggmap::register_google}.") 52 | } 53 | 54 | 55 | # form url base 56 | url_base <- glue("https://maps.googleapis.{ext}/maps/api/geocode/json?") 57 | 58 | 59 | # form query 60 | url_query <- c("latlng" = glue("{location[2]},{location[1]}")) 61 | 62 | 63 | # add google account stuff to query, if applicable 64 | url_query <- c(url_query, "client" = google_client(), "signature" = google_signature(), "key" = google_key()) 65 | url_query <- url_query[!is.na(url_query)] 66 | 67 | 68 | # form url 69 | url_query_inline <- str_c(names(url_query), url_query, sep = "=", collapse = "&") 70 | url <- str_c(url_base, url_query_inline) 71 | 72 | 73 | # inject any remaining stuff 74 | if (inject != "") { 75 | if (is.null(names(inject))) { 76 | url <- str_c(url, inject, sep = "&") 77 | } else { 78 | url <- str_c(url, str_c(names(inject), inject, sep = "=", collapse = "&"), sep = "&") 79 | } 80 | } 81 | 82 | # encode 83 | url <- URLencode( enc2utf8(url) ) 84 | url <- str_replace_all(url, "#", "%23") # selectively url-encode 85 | 86 | 87 | # return early if user only wants url 88 | if(urlonly) if(showing_key()) return(url) else return(scrub_key(url)) 89 | 90 | 91 | # hash for caching 92 | url_hash <- digest::digest(scrub_key(url)) 93 | 94 | 95 | # lookup info if on file 96 | if (location_is_cached(url_hash) && force == FALSE) { 97 | 98 | gc <- geocode_cache()[[url_hash]] 99 | 100 | } else { 101 | 102 | throttle_google_geocode_query_rate(url_hash, queries_sought = 1L, override = override_limit) 103 | 104 | # message url 105 | if (showing_key()) source_url_msg(url) else source_url_msg(scrub_key(url)) 106 | 107 | # query server 108 | response <- httr::GET(url) 109 | 110 | # deal with bad responses 111 | if (response$status_code != 200L) { 112 | warning( 113 | tryCatch(stop_for_status(response), 114 | "http_400" = function(c) "HTTP 400 Bad Request", 115 | "http_402" = function(c) "HTTP 402 Payment Required - May indicate over Google query limit", 116 | "http_403" = function(c) "HTTP 403 Forbidden - Server refuses, is the API enabled?", 117 | "http_404" = function(c) "HTTP 404 Not Found - Server reports page not found", 118 | "http_414" = function(c) "HTTP 414 URI Too Long - URL query too long", 119 | "http_500" = function(c) "HTTP 500 Internal Server Error", 120 | "http_503" = function(c) "HTTP 503 Service Unavailable - Server bogged down, try later" 121 | ) 122 | ) 123 | return(NA_character_) 124 | } 125 | 126 | # grab content 127 | gc <- httr::content(response) 128 | 129 | # cache it 130 | cache_geocoded_info(url_hash, gc) 131 | 132 | } 133 | 134 | 135 | # did geocode fail? 136 | if (gc$status != "OK") { 137 | warning( 138 | glue("Reverse geocoding failed with error:"), 139 | "\n", gc$error_message, "\n", 140 | call. = FALSE, immediate. = TRUE, noBreaks. = FALSE 141 | ) 142 | return(NA_character_) 143 | } 144 | 145 | 146 | # return if you want full output 147 | if (output == "all") return(gc) 148 | 149 | 150 | # more than one location found? 151 | if (length(gc$results) > 1L) { 152 | cli::cli_warn("Multiple addresses found, the first will be returned:") 153 | gc$results %>% 154 | map_chr(~ .x$formatted_address) %>% 155 | unique() %>% 156 | str_c(" ", .) %>% 157 | walk(cli::cli_alert_warning) 158 | } 159 | 160 | 161 | # return 162 | gc$results[[1]]$formatted_address 163 | } 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | -------------------------------------------------------------------------------- /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.io} 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 | -------------------------------------------------------------------------------- /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.io} 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 <- ggplot(df, aes(x, y)) + geom_raster() 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 <- ggplot(df, aes(x, y)) + geom_raster(aes(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 | -------------------------------------------------------------------------------- /R/trek.R: -------------------------------------------------------------------------------- 1 | #' Grab a trek from Google 2 | #' 3 | #' Sequence treks (latitude-longitude sequences following ordinary paths, e.g. 4 | #' roads) between two locations using the Google Directions API. Note: To use 5 | #' Google's Directions API, you must first enable the API in the Google Cloud 6 | #' Platform Console. See [register_google()]. 7 | #' 8 | #' @param from name of origin addresses in a data frame 9 | #' @param to name of destination addresses in a data frame 10 | #' @param output amount of output ("simple" or "all") 11 | #' @param mode driving, bicycling, walking, or transit 12 | #' @param alternatives should more than one route be provided? 13 | #' @param units "metric" 14 | #' @param urlonly return only the url? 15 | #' @param override_limit override the current query count 16 | #' @param ext domain extension (e.g. "com", "co.nz") 17 | #' @param inject character string to add to the url 18 | #' @param ... ... 19 | #' @return a tibble 20 | #' @author David Kahle \email{david@@kahle.io} with the key decoding algorithm 21 | #' due to Stack Overflow user akhmed 22 | #' @seealso \url{https://developers.google.com/maps/documentation/directions/}, 23 | #' \url{https://stackoverflow.com/questions/30270011/ggmap-route-finding-doesnt-stay-on-roads/}, 24 | #' [route()], [routeQueryCheck()], [register_google()] 25 | #' @export 26 | #' @examples 27 | #' 28 | #' \dontrun{ requires Google API key, see ?register_google 29 | #' 30 | #' ## basic usage 31 | #' ######################################## 32 | #' 33 | #' from <- "houston, texas" 34 | #' to <- "waco, texas" 35 | #' 36 | #' (route_df <- route(from, to, structure = "route")) 37 | #' (trek_df <- trek(from, to, structure = "route")) 38 | #' 39 | #' qmap("college station, texas", zoom = 8) + 40 | #' geom_path( 41 | #' aes(x = lon, y = lat), colour = "red", 42 | #' size = 1.5, alpha = .5, 43 | #' data = route_df, lineend = "round" 44 | #' ) + 45 | #' geom_path( 46 | #' aes(x = lon, y = lat), colour = "blue", 47 | #' size = 1.5, alpha = .5, 48 | #' data = trek_df, lineend = "round" 49 | #' ) 50 | #' 51 | #' 52 | #' 53 | #' from <- "rice university houston texas" 54 | #' to <- "1001 Bissonnet St, Houston, TX 77005" 55 | #' trek_df <- trek(from, to) 56 | #' qmplot(lon, lat, data = trek_df, geom = "path", maptype = "terrain", 57 | #' color = I("red"), size = I(2), alpha = I(.5) 58 | #' ) 59 | #' 60 | #' trek_df <- trek(from, to, mode = "walking") 61 | #' qmplot(lon, lat, data = trek_df, geom = "path", maptype = "terrain", 62 | #' color = I("red"), size = I(2), alpha = I(.5) 63 | #' ) 64 | #' 65 | #' trek_df <- trek(from, to, mode = "transit") 66 | #' qmplot(lon, lat, data = trek_df, geom = "path", maptype = "terrain", 67 | #' color = I("red"), size = I(2), alpha = I(.5) 68 | #' ) 69 | #' 70 | #' 71 | #' 72 | #' ## neat faceting example 73 | #' ######################################## 74 | #' 75 | #' from <- "houston, texas"; to <- "waco, texas" 76 | #' trek_df <- trek(from, to, alternatives = TRUE) 77 | #' 78 | #' qmplot(lon, lat, data = trek_df, geom = "path", 79 | #' color = route, size = I(2), maptype = "terrain", 80 | #' alpha = I(.5) 81 | #' ) 82 | #' 83 | #' qmplot(lon, lat, data = trek_df, geom = "path", 84 | #' color = route, size = I(2), maptype = "terrain", 85 | #' zoom = 8 86 | #' ) + facet_grid(. ~ route) 87 | #' 88 | #' 89 | #' 90 | #' 91 | #' } 92 | #' 93 | trek <- function ( 94 | from, 95 | to, 96 | mode = c("driving","walking","bicycling", "transit"), 97 | output = c("simple","all"), 98 | alternatives = FALSE, 99 | units = "metric", 100 | urlonly = FALSE, 101 | override_limit = FALSE, 102 | ext = "com", 103 | inject = "", 104 | ... 105 | ) { 106 | 107 | # check parameters 108 | if(is.numeric(from) && length(from) == 2) from <- revgeocode(from) 109 | stopifnot(is.character(from)) 110 | if(is.numeric(to) && length(to) == 2) to <- revgeocode(to) 111 | stopifnot(is.character(to)) 112 | 113 | mode <- match.arg(mode) 114 | output <- match.arg(output) 115 | stopifnot(is.logical(alternatives)) 116 | if (!has_google_key() && !urlonly) { 117 | cli::cli_abort("Google now requires an API key; see {.fn ggmap::register_google}.") 118 | } 119 | 120 | 121 | # set url base 122 | url_base <- glue("https://maps.googleapis.{ext}/maps/api/directions/json?") 123 | 124 | 125 | # initialize the url query 126 | url_query_from <- from %>% str_trim() %>% str_replace_all(" +", "+") %>% c("origin" = .) 127 | url_query_to <- to %>% str_trim() %>% str_replace_all(" +", "+") %>% c("destination" = .) 128 | url_query <- c(url_query_from, url_query_to) 129 | 130 | 131 | # add google account stuff to query, if applicable 132 | url_query <- c(url_query, "client" = google_client(), "signature" = google_signature(), "key" = google_key()) 133 | url_query <- url_query[!is.na(url_query)] 134 | 135 | 136 | # add mode and other stuff 137 | url_query <- c(url_query, "mode" = mode, "alternatives" = tolower(alternatives), "units" = units) 138 | 139 | 140 | # form url 141 | url_query_inline <- str_c(names(url_query), url_query, sep = "=", collapse = "&") 142 | url <- str_c(url_base, url_query_inline) 143 | 144 | 145 | # inject any remaining stuff 146 | if (inject != "") { 147 | if (is.null(names(inject))) { 148 | url <- str_c(url, inject, sep = "&") 149 | } else { 150 | url <- str_c(url, str_c(names(inject), inject, sep = "=", collapse = "&"), sep = "&") 151 | } 152 | } 153 | 154 | 155 | # encode 156 | url <- URLencode( enc2utf8(url) ) 157 | url <- str_replace_all(url, "#", "%23") # selectively url-encode 158 | 159 | 160 | # return early if user only wants url 161 | if(urlonly) if(showing_key()) return(url) else return(scrub_key(url)) 162 | 163 | 164 | # hash for caching 165 | url_hash <- digest::digest(scrub_key(url)) 166 | 167 | 168 | # check/update google query limit 169 | # check_route_query_limit(url_string, elems = 1, override = override_limit) 170 | 171 | 172 | # message url 173 | if (showing_key()) source_url_msg(url) else source_url_msg(scrub_key(url)) 174 | 175 | 176 | # query server 177 | response <- httr::GET(url) 178 | 179 | 180 | # deal with bad responses 181 | if (response$status_code != 200L) { 182 | warning( 183 | tryCatch(stop_for_status(response), 184 | "http_400" = function(c) "HTTP 400 Bad Request", 185 | "http_402" = function(c) "HTTP 402 Payment Required - May indicate over Google query limit", 186 | "http_403" = function(c) "HTTP 403 Forbidden - Server refuses, is the API enabled?", 187 | "http_404" = function(c) "HTTP 404 Not Found - Server reports page not found", 188 | "http_414" = function(c) "HTTP 414 URI Too Long - URL query too long", 189 | "http_500" = function(c) "HTTP 500 Internal Server Error", 190 | "http_503" = function(c) "HTTP 503 Service Unavailable - Server bogged down, try later" 191 | ) 192 | ) 193 | return(return_failed_trek(output)) 194 | } 195 | 196 | 197 | # grab content 198 | tree <- httr::content(response) 199 | 200 | 201 | # return NA if zero results are found 202 | if (tree$status == "ZERO_RESULTS") { 203 | cli::cli_warn("No route was returned from Google.") 204 | return(return_failed_trek(output)) 205 | } 206 | 207 | 208 | # return output = "all" 209 | if(output == "all") return(tree) 210 | 211 | 212 | # extract output from tree and format 213 | treks <- tree$routes %>% 214 | map(~ decode_google_route(.x$overview_polyline$points)) 215 | 216 | 217 | # label routes 218 | for (k in seq_along(treks)) treks[[k]]$route <- LETTERS[k] 219 | 220 | 221 | # bind and return 222 | dplyr::bind_rows(treks) 223 | } 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | return_failed_trek <- function (output) { 238 | if (output == "simple") { 239 | return(tibble( 240 | "lat" = NA_real_, 241 | "lon" = NA_real_, 242 | "route" = NA_character_ 243 | )) 244 | } else if (output == "all") { 245 | return(list()) 246 | } 247 | } 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | # the following is from @akmed (stackoverflow) 271 | # see https://stackoverflow.com/questions/30270011/ggmap-route-finding-doesnt-stay-on-roads 272 | # https://developers.google.com/maps/documentation/utilities/polylinealgorithm 273 | decode_google_route <- function(encoded){ 274 | 275 | vlen <- nchar(encoded) 276 | vindex <- 0 277 | varray <- NULL 278 | vlat <- 0 279 | vlng <- 0 280 | 281 | while(vindex < vlen){ 282 | vb <- NULL 283 | vshift <- 0 284 | vresult <- 0 285 | repeat{ 286 | if(vindex + 1 <= vlen){ 287 | vindex <- vindex + 1 288 | vb <- as.integer(charToRaw(substr(encoded, vindex, vindex))) - 63 289 | } 290 | 291 | vresult <- bitOr(vresult, bitShiftL(bitAnd(vb, 31), vshift)) 292 | vshift <- vshift + 5 293 | if(vb < 32) break 294 | } 295 | 296 | dlat <- ifelse(bitAnd(vresult, 1), -(bitShiftR(vresult, 1)+1), bitShiftR(vresult, 1)) 297 | vlat <- vlat + dlat 298 | 299 | vshift <- 0 300 | vresult <- 0 301 | repeat{ 302 | if(vindex + 1 <= vlen) { 303 | vindex <- vindex+1 304 | vb <- as.integer(charToRaw(substr(encoded, vindex, vindex))) - 63 305 | } 306 | 307 | vresult <- bitOr(vresult, bitShiftL(bitAnd(vb, 31), vshift)) 308 | vshift <- vshift + 5 309 | if(vb < 32) break 310 | } 311 | 312 | dlng <- ifelse(bitAnd(vresult, 1), -(bitShiftR(vresult, 1)+1), bitShiftR(vresult, 1)) 313 | vlng <- vlng + dlng 314 | 315 | varray <- rbind(varray, c(vlat * 1e-5, vlng * 1e-5)) 316 | } 317 | coords <- as_tibble(data.frame(varray)) 318 | names(coords) <- c("lat", "lon") 319 | coords 320 | } 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | -------------------------------------------------------------------------------- /R/wind.R: -------------------------------------------------------------------------------- 1 | #' Wind data from Hurricane Ike 2 | #' 3 | #' @name wind 4 | #' @details Powell, M. D., S. H. Houston, L. R. Amat, and N Morisseau-Leroy, 5 | #' 1998: The HRD real-time hurricane wind analysis system. J. Wind Engineer. 6 | #' and Indust. Aerodyn. 77&78, 53-64 7 | #' @docType data 8 | #' @author Atlantic Oceanographic and Meteorological Laboratory (AOML), a 9 | #' division of the National Oceanic and Atmospheric Administration (NOAA) 10 | #' @references \url{https://www.aoml.noaa.gov/hrd/Storm_pages/ike2008/wind.html} 11 | #' 12 | NULL 13 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /appveyor.yml: -------------------------------------------------------------------------------- 1 | # DO NOT CHANGE the "init" and "install" sections below 2 | 3 | # Download script file from GitHub 4 | init: 5 | ps: | 6 | $ErrorActionPreference = "Stop" 7 | Invoke-WebRequest http://raw.github.com/krlmlr/r-appveyor/master/scripts/appveyor-tool.ps1 -OutFile "..\appveyor-tool.ps1" 8 | Import-Module '..\appveyor-tool.ps1' 9 | 10 | install: 11 | ps: Bootstrap 12 | 13 | cache: 14 | - C:\RLibrary 15 | 16 | # Adapt as necessary starting from here 17 | 18 | build_script: 19 | - travis-tool.sh install_deps 20 | 21 | test_script: 22 | - travis-tool.sh run_tests 23 | 24 | on_failure: 25 | - 7z a failure.zip *.Rcheck\* 26 | - appveyor PushArtifact failure.zip 27 | 28 | artifacts: 29 | - path: '*.Rcheck\**\*.log' 30 | name: Logs 31 | 32 | - path: '*.Rcheck\**\*.out' 33 | name: Logs 34 | 35 | - path: '*.Rcheck\**\*.fail' 36 | name: Logs 37 | 38 | - path: '*.Rcheck\**\*.Rout' 39 | name: Logs 40 | 41 | - path: '\*_*.tar.gz' 42 | name: Bits 43 | 44 | - path: '\*_*.zip' 45 | name: Bits 46 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /data/crime.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkahle/ggmap/29ed82523e46332aa77364717bd042f8ee314337/data/crime.rda -------------------------------------------------------------------------------- /data/hadley.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkahle/ggmap/29ed82523e46332aa77364717bd042f8ee314337/data/hadley.rda -------------------------------------------------------------------------------- /data/wind.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkahle/ggmap/29ed82523e46332aa77364717bd042f8ee314337/data/wind.rda -------------------------------------------------------------------------------- /data/zips.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkahle/ggmap/29ed82523e46332aa77364717bd042f8ee314337/data/zips.rda -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | bibentry( 2 | bibtype = "article", 3 | author = "David Kahle and Hadley Wickham", 4 | title = "ggmap: Spatial Visualization with ggplot2", 5 | journal = "The R Journal", 6 | year = "2013", 7 | volume = "5", 8 | number = "1", 9 | pages = "144--161", 10 | url = "https://journal.r-project.org/archive/2013-1/kahle-wickham.pdf", 11 | 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" 12 | ) 13 | -------------------------------------------------------------------------------- /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 zoom. Decimal 25 | 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{https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames} 39 | } 40 | \author{ 41 | David Kahle \email{david@kahle.io}, based on 42 | \code{RgoogleMaps::LatLon2XY()} by Markus Loecher of Sense Networks 43 | \email{markus@sensenetworks.com} 44 | } 45 | -------------------------------------------------------------------------------- /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 given zoom 20 | level is a complicated task. For details, see 21 | \url{https://wiki.openstreetmap.org/wiki/FAQ} 22 | } 23 | \examples{ 24 | 25 | OSM_scale_lookup(zoom = 3) 26 | OSM_scale_lookup(zoom = 10) 27 | 28 | \dontrun{ 29 | # these can take a long time or are prone to crashing 30 | # if the osm server load is too high 31 | 32 | # these maps are were the ones used to tailor fit the scale 33 | # the zooms were fixed 34 | ggmap(get_map(zoom = 3, source = 'osm', scale = 47500000), extent = "device") 35 | ggmap(get_map(zoom = 4, source = 'osm', scale = 32500000), extent = "device") 36 | ggmap(get_map(zoom = 5, source = 'osm', scale = 15000000), extent = "device") 37 | ggmap(get_map(zoom = 6, source = 'osm', scale = 10000000), extent = "device") 38 | ggmap(get_map(zoom = 7, source = 'osm', scale = 5000000), extent = "device") 39 | ggmap(get_map(zoom = 8, source = 'osm', scale = 2800000), extent = "device") 40 | ggmap(get_map(zoom = 9, source = 'osm', scale = 1200000), extent = "device") 41 | ggmap(get_map(zoom = 10, source = 'osm', scale = 575000), extent = "device") 42 | ggmap(get_map(zoom = 11, source = 'osm', scale = 220000), extent = "device") 43 | ggmap(get_map(zoom = 12, source = 'osm', scale = 110000), extent = "device") 44 | ggmap(get_map(zoom = 13, source = 'osm', scale = 70000), extent = "device") 45 | ggmap(get_map(zoom = 14, source = 'osm', scale = 31000), extent = "device") 46 | ggmap(get_map(zoom = 15, source = 'osm', scale = 15000), extent = "device") 47 | ggmap(get_map(zoom = 16, source = 'osm', scale = 7500), extent = "device") 48 | ggmap(get_map(zoom = 17, source = 'osm', scale = 4000), extent = "device") 49 | ggmap(get_map(zoom = 18, source = 'osm', scale = 2500), extent = "device") 50 | ggmap(get_map(zoom = 19, source = 'osm', scale = 1750), extent = "device") 51 | ggmap(get_map(zoom = 20, source = 'osm', scale = 1000), extent = "device") 52 | 53 | # the USA 54 | lonR <- c(1.01,.99)*c(-124.73,-66.95) 55 | latR <- c(.99,1.01)*c(24.52, 49.38) 56 | qmap(lonR = lonR, latR = latR, source = 'osm', scale = 325E5) 57 | 58 | } 59 | 60 | 61 | } 62 | \author{ 63 | David Kahle \email{david@kahle.io} 64 | } 65 | -------------------------------------------------------------------------------- /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 zoom. Decimal 29 | 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{https://wiki.openstreetmap.org/wiki/Slippy_map_tilenames} 45 | } 46 | \author{ 47 | David Kahle \email{david@kahle.io}, based on 48 | \code{RgoogleMaps::XY2LatLon()} by Markus Loecher of Sense Networks 49 | \email{markus@sensenetworks.com} 50 | } 51 | -------------------------------------------------------------------------------- /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_stadiamap). 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 Stadia map 34 | stadMap <- get_stadiamap(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(stadMap) + 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.io} 55 | } 56 | -------------------------------------------------------------------------------- /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]{make_bbox()}}, \code{\link[=bb2bbox]{bb2bbox()}} 45 | } 46 | -------------------------------------------------------------------------------- /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 geocoded with 9 | Google Maps 10 | } 11 | \references{ 12 | \url{https://www.houstontx.gov/police/cs/index-2.htm} 13 | } 14 | \author{ 15 | Houston Police Department, City of Houston 16 | } 17 | -------------------------------------------------------------------------------- /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_stadiamap() 26 | # The second time, the local cache is used so it's much faster 27 | map <- get_stadiamap() 28 | 29 | dir(file_drawer()) 30 | 31 | } 32 | 33 | } 34 | \keyword{internal} 35 | -------------------------------------------------------------------------------- /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{mutate_geocode} 6 | \alias{geocodeQueryCheck} 7 | \alias{geocode_cache} 8 | \alias{write_geocode_cache} 9 | \alias{load_geocode_cache} 10 | \alias{clear_geocode_cache} 11 | \title{Geocode} 12 | \usage{ 13 | geocode( 14 | location, 15 | output = c("latlon", "latlona", "more", "all"), 16 | source = c("google", "dsk"), 17 | force = ifelse(source == "dsk", FALSE, TRUE), 18 | urlonly = FALSE, 19 | override_limit = FALSE, 20 | nameType = c("long", "short"), 21 | ext = "com", 22 | inject = "", 23 | ... 24 | ) 25 | 26 | mutate_geocode(data, location, ...) 27 | 28 | geocodeQueryCheck() 29 | 30 | geocode_cache() 31 | 32 | write_geocode_cache(path, ...) 33 | 34 | load_geocode_cache(path, overwrite = FALSE) 35 | 36 | clear_geocode_cache(path) 37 | } 38 | \arguments{ 39 | \item{location}{a character vector of street addresses or place names (e.g. 40 | \verb{"1600 pennsylvania avenue, washington dc" or "Baylor University"})} 41 | 42 | \item{output}{amount of output, \code{"latlon"}, \code{"latlona"}, \code{"more"}, or \code{"all"}} 43 | 44 | \item{source}{"google" for Google (note: "dsk" is defunct)} 45 | 46 | \item{force}{force online query even if cached.} 47 | 48 | \item{urlonly}{return only the url?} 49 | 50 | \item{override_limit}{override the current query rate} 51 | 52 | \item{nameType}{in some cases, Google returns both a long name and a short 53 | name. this parameter allows the user to specify which to grab.} 54 | 55 | \item{ext}{top level domain (e.g. "com", "co.nz"); helpful for non-US users} 56 | 57 | \item{inject}{character string to add to the url or named character vector of 58 | key-value pairs to be injected (e.g. c("a" = "b") get converted to "a=b" 59 | and appended to the query)} 60 | 61 | \item{...}{In \code{\link[=mutate_geocode]{mutate_geocode()}}, arguments to pass to \code{\link[=geocode]{geocode()}}. In 62 | \code{\link[=write_geocode_cache]{write_geocode_cache()}}, arguments to pass to \code{\link[=saveRDS]{saveRDS()}}.} 63 | 64 | \item{data}{a data frame or equivalent} 65 | 66 | \item{path}{path to file} 67 | 68 | \item{overwrite}{in \code{\link[=load_geocode_cache]{load_geocode_cache()}}, should the current cache be 69 | wholly replaced with the one on file?} 70 | } 71 | \value{ 72 | If \code{output} is \code{"latlon"}, \code{"latlona"}, or \code{"more"}, a tibble 73 | (classed data frame). If \code{"all"}, a list. 74 | } 75 | \description{ 76 | Geocodes (finds latitude and longitude of) a location using the Google 77 | Geocoding API. Note: To use Google's Geocoding API, you must first enable the 78 | API in the Google Cloud Platform Console. See \code{\link[=register_google]{register_google()}}. 79 | } 80 | \details{ 81 | Note: \code{\link[=geocode]{geocode()}} uses Google's Geocoding API to geocode addresses. Please 82 | take care not to disclose sensitive information. 83 | \url{https://pmc.ncbi.nlm.nih.gov/articles/PMC8972108/} suggest various 84 | alternative options for such data. 85 | } 86 | \examples{ 87 | 88 | \dontrun{ requires Google API key, see ?register_google 89 | 90 | ## basic usage 91 | ######################################## 92 | 93 | # geocoding is most commonly used for addresses 94 | geocode("1600 Amphitheatre Parkway, Mountain View, CA") 95 | geocode("1600 Amphitheatre Parkway, Mountain View, CA", urlonly = TRUE) 96 | 97 | # google can also geocode colloquial names of places 98 | geocode("the white house") 99 | 100 | # geocode can also accept character vectors of places 101 | geocode(c("the white house", "washington dc")) 102 | 103 | 104 | 105 | ## types of output 106 | ######################################## 107 | 108 | geocode("waco texas") 109 | geocode("waco texas", output = "latlona") 110 | geocode("waco texas", output = "more") 111 | str(geocode("waco texas", output = "all")) 112 | 113 | geocode(c("waco, texas", "houston, texas")) 114 | geocode(c("waco, texas", "houston, texas"), output = "latlona") 115 | geocode(c("waco, texas", "houston, texas"), output = "all") \%>\% str(4) 116 | 117 | 118 | 119 | ## mutate_geocode 120 | ######################################## 121 | 122 | # mutate_geocode is used to add location columns to an existing dataset 123 | # that has location information 124 | 125 | df <- data.frame( 126 | address = c("1600 Pennsylvania Avenue, Washington DC", "", "houston texas"), 127 | stringsAsFactors = FALSE 128 | ) 129 | 130 | mutate_geocode(df, address) 131 | df \%>\% mutate_geocode(address) 132 | 133 | 134 | ## known issues 135 | ######################################## 136 | 137 | # in some cases geocode finds several locations 138 | 139 | 140 | } 141 | 142 | 143 | } 144 | \seealso{ 145 | \url{https://developers.google.com/maps/documentation/geocoding}, 146 | \url{https://developers.google.com/maps/documentation/javascript/geocoding}, 147 | \url{https://developers.google.com/maps/documentation/geocoding/usage-and-billing}, 148 | \url{https://pmc.ncbi.nlm.nih.gov/articles/PMC8972108/} 149 | } 150 | \author{ 151 | David Kahle \email{david@kahle.io} 152 | } 153 | -------------------------------------------------------------------------------- /man/geom_leg.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geom_leg.R 3 | \name{geom_leg} 4 | \alias{geom_leg} 5 | \title{Single line segments with rounded ends} 6 | \usage{ 7 | geom_leg( 8 | mapping = NULL, 9 | data = NULL, 10 | stat = "identity", 11 | position = "identity", 12 | arrow = NULL, 13 | lineend = "round", 14 | na.rm = FALSE, 15 | show.legend = NA, 16 | inherit.aes = TRUE, 17 | ... 18 | ) 19 | } 20 | \arguments{ 21 | \item{mapping}{Set of aesthetic mappings created by \code{\link[ggplot2:aes]{aes()}}. If specified and 22 | \code{inherit.aes = TRUE} (the default), it is combined with the default mapping 23 | at the top level of the plot. You must supply \code{mapping} if there is no plot 24 | mapping.} 25 | 26 | \item{data}{The data to be displayed in this layer. There are three 27 | options: 28 | 29 | If \code{NULL}, the default, the data is inherited from the plot 30 | data as specified in the call to \code{\link[ggplot2:ggplot]{ggplot()}}. 31 | 32 | A \code{data.frame}, or other object, will override the plot 33 | data. All objects will be fortified to produce a data frame. See 34 | \code{\link[ggplot2:fortify]{fortify()}} for which variables will be created. 35 | 36 | A \code{function} will be called with a single argument, 37 | the plot data. The return value must be a \code{data.frame}, and 38 | will be used as the layer data. A \code{function} can be created 39 | from a \code{formula} (e.g. \code{~ head(.x, 10)}).} 40 | 41 | \item{stat}{The statistical transformation to use on the data for this layer. 42 | When using a \verb{geom_*()} function to construct a layer, the \code{stat} 43 | argument can be used the override the default coupling between geoms and 44 | stats. The \code{stat} argument accepts the following: 45 | \itemize{ 46 | \item A \code{Stat} ggproto subclass, for example \code{StatCount}. 47 | \item A string naming the stat. To give the stat as a string, strip the 48 | function name of the \code{stat_} prefix. For example, to use \code{stat_count()}, 49 | give the stat as \code{"count"}. 50 | \item For more information and other ways to specify the stat, see the 51 | \link[ggplot2:layer_stats]{layer stat} documentation. 52 | }} 53 | 54 | \item{position}{A position adjustment to use on the data for this layer. This 55 | can be used in various ways, including to prevent overplotting and 56 | improving the display. The \code{position} argument accepts the following: 57 | \itemize{ 58 | \item The result of calling a position function, such as \code{position_jitter()}. 59 | This method allows for passing extra arguments to the position. 60 | \item A string naming the position adjustment. To give the position as a 61 | string, strip the function name of the \code{position_} prefix. For example, 62 | to use \code{position_jitter()}, give the position as \code{"jitter"}. 63 | \item For more information and other ways to specify the position, see the 64 | \link[ggplot2:layer_positions]{layer position} documentation. 65 | }} 66 | 67 | \item{arrow}{specification for arrow heads, as created by \code{\link[grid:arrow]{grid::arrow()}}.} 68 | 69 | \item{lineend}{Line end style (round, butt, square).} 70 | 71 | \item{na.rm}{If \code{FALSE}, the default, missing values are removed with 72 | a warning. If \code{TRUE}, missing values are silently removed.} 73 | 74 | \item{show.legend}{logical. Should this layer be included in the legends? 75 | \code{NA}, the default, includes if any aesthetics are mapped. 76 | \code{FALSE} never includes, and \code{TRUE} always includes. 77 | It can also be a named logical vector to finely select the aesthetics to 78 | display.} 79 | 80 | \item{inherit.aes}{If \code{FALSE}, overrides the default aesthetics, 81 | rather than combining with them. This is most useful for helper functions 82 | that define both data and aesthetics and shouldn't inherit behaviour from 83 | the default plot specification, e.g. \code{\link[ggplot2:borders]{borders()}}.} 84 | 85 | \item{...}{Other arguments passed on to \code{\link[ggplot2:layer]{layer()}}'s \code{params} argument. These 86 | arguments broadly fall into one of 4 categories below. Notably, further 87 | arguments to the \code{position} argument, or aesthetics that are required 88 | can \emph{not} be passed through \code{...}. Unknown arguments that are not part 89 | of the 4 categories below are ignored. 90 | \itemize{ 91 | \item Static aesthetics that are not mapped to a scale, but are at a fixed 92 | value and apply to the layer as a whole. For example, \code{colour = "red"} 93 | or \code{linewidth = 3}. The geom's documentation has an \strong{Aesthetics} 94 | section that lists the available options. The 'required' aesthetics 95 | cannot be passed on to the \code{params}. Please note that while passing 96 | unmapped aesthetics as vectors is technically possible, the order and 97 | required length is not guaranteed to be parallel to the input data. 98 | \item When constructing a layer using 99 | a \verb{stat_*()} function, the \code{...} argument can be used to pass on 100 | parameters to the \code{geom} part of the layer. An example of this is 101 | \code{stat_density(geom = "area", outline.type = "both")}. The geom's 102 | documentation lists which parameters it can accept. 103 | \item Inversely, when constructing a layer using a 104 | \verb{geom_*()} function, the \code{...} argument can be used to pass on parameters 105 | to the \code{stat} part of the layer. An example of this is 106 | \code{geom_area(stat = "density", adjust = 0.5)}. The stat's documentation 107 | lists which parameters it can accept. 108 | \item The \code{key_glyph} argument of \code{\link[ggplot2:layer]{layer()}} may also be passed on through 109 | \code{...}. This can be one of the functions described as 110 | \link[ggplot2:draw_key]{key glyphs}, to change the display of the layer in the legend. 111 | }} 112 | } 113 | \description{ 114 | This is ggplot2's segment with rounded ends. It's mainly included in ggmap 115 | for historical reasons. 116 | } 117 | \details{ 118 | only intended for use in ggmap package. only designed 119 | for mercator projection. 120 | } 121 | \examples{ 122 | 123 | \dontrun{ # removed for R CMD check speed 124 | 125 | map <- get_map( 126 | location = c(-77.0425, 38.8925), # painfully picked by hand 127 | source = "google", zoom = 14, maptype = "satellite" 128 | ) 129 | ggmap(map) 130 | 131 | 132 | (legs_df <- route( 133 | "the white house, dc", 134 | "lincoln memorial washington dc", 135 | alternatives = TRUE 136 | )) 137 | 138 | ggplot(data = legs_df) + 139 | geom_leg(aes( 140 | x = start_lon, xend = end_lon, 141 | y = start_lat, yend = end_lat 142 | )) + 143 | coord_map() 144 | 145 | ggplot(data = legs_df) + 146 | geom_leg(aes( 147 | x = start_lon, xend = end_lon, 148 | y = start_lat, yend = end_lat, 149 | color = route 150 | )) + 151 | coord_map() 152 | 153 | 154 | ggmap(map) + 155 | geom_leg( 156 | aes( 157 | x = start_lon, xend = end_lon, 158 | y = start_lat, yend = end_lat 159 | ), 160 | data = legs_df, color = "red" 161 | ) 162 | 163 | # adding a color aesthetic errors because of a base-layer problem 164 | # ggmap(map) + 165 | # geom_leg( 166 | # aes( 167 | # x = start_lon, xend = end_lon, 168 | # y = start_lat, yend = end_lat, 169 | # color = route 170 | # ) 171 | # ) 172 | 173 | 174 | # this is probably the easiest hack to fix it 175 | ggplot(data = legs_df) + 176 | inset_ggmap(map) + 177 | geom_leg( 178 | aes( 179 | x = start_lon, xend = end_lon, 180 | y = start_lat, yend = end_lat, 181 | color = route 182 | ), 183 | data = legs_df 184 | ) + 185 | coord_map() 186 | 187 | } 188 | 189 | } 190 | \seealso{ 191 | \code{\link[ggplot2:geom_segment]{ggplot2::geom_segment()}}, \code{\link[=route]{route()}}, inspired by 192 | \verb{https://spatialanalysis.co.uk/2012/02/great-maps-ggplot2}, no longer 193 | active 194 | } 195 | -------------------------------------------------------------------------------- /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( 8 | bbox = c(left = -95.80204, bottom = 29.38048, right = -94.92313, top = 30.14344), 9 | zoom = 10, 10 | api_key, 11 | maptype = 1, 12 | highres = TRUE, 13 | crop = TRUE, 14 | messaging = FALSE, 15 | urlonly = FALSE, 16 | filename = NULL, 17 | color = c("color", "bw"), 18 | ... 19 | ) 20 | } 21 | \arguments{ 22 | \item{bbox}{a bounding box in the format c(lowerleftlon, lowerleftlat, 23 | upperrightlon, upperrightlat).} 24 | 25 | \item{zoom}{a zoom level} 26 | 27 | \item{api_key}{character string containing cloud made api key, see details} 28 | 29 | \item{maptype}{an integer of what cloud made calls style, see details} 30 | 31 | \item{highres}{double resolution} 32 | 33 | \item{crop}{crop raw map tiles to specified bounding box} 34 | 35 | \item{messaging}{turn messaging on/off} 36 | 37 | \item{urlonly}{return url only} 38 | 39 | \item{filename}{destination file for download (file extension added according 40 | to format). Default \code{NULL} means a random \code{\link[=tempfile]{tempfile()}}.} 41 | 42 | \item{color}{color or black-and-white} 43 | 44 | \item{...}{...} 45 | } 46 | \value{ 47 | a ggmap object (a classed raster object with a bounding box 48 | attribute) 49 | } 50 | \description{ 51 | \code{\link[=get_cloudmademap]{get_cloudmademap()}} accesses a tile server for Stamen Maps and 52 | downloads/stitches map tiles/formats a map image. This function requires an 53 | api key which can be obtained for free from http://cloudmade.com/user/show, 54 | now defunct. Thousands of maptypes ("styles"), including create-your-own 55 | options, are available from http://maps.cloudmade.com/editor (defunct). 56 | } 57 | \seealso{ 58 | http://maps.cloudmade.com/ (defunct), \code{\link[=ggmap]{ggmap()}} 59 | } 60 | \author{ 61 | David Kahle \email{david@kahle.io} 62 | } 63 | -------------------------------------------------------------------------------- /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( 8 | center = c(lon = -95.3632715, lat = 29.7632836), 9 | zoom = 10, 10 | size = c(640, 640), 11 | scale = 2, 12 | format = c("png8", "gif", "jpg", "jpg-baseline", "png32"), 13 | maptype = GOOGLE_VALID_MAP_TYPES, 14 | language = "en-EN", 15 | messaging = FALSE, 16 | urlonly = FALSE, 17 | filename = NULL, 18 | color = c("color", "bw"), 19 | force = FALSE, 20 | where = tempdir(), 21 | archiving = FALSE, 22 | ext = "com", 23 | inject = "", 24 | region, 25 | markers, 26 | path, 27 | visible, 28 | style, 29 | ... 30 | ) 31 | } 32 | \arguments{ 33 | \item{center}{the center of the map; either a longitude/latitude numeric 34 | vector or a string containing a location, in which case \code{\link[=geocode]{geocode()}} is 35 | called with \code{source = "google"}. (default: \code{c(lon = -95.3632715, lat = 29.7632836)}, a reference to Houston, Texas)} 36 | 37 | \item{zoom}{map zoom; an integer from 3 (continent) to 21 (building), default 38 | value 10 (city)} 39 | 40 | \item{size}{rectangular dimensions of map in pixels - horizontal x vertical - 41 | with a max of c(640, 640). this parameter is affected in a multiplicative 42 | way by scale.} 43 | 44 | \item{scale}{multiplicative factor for the number of pixels returned possible 45 | values are 1, 2, or 4 (e.g. size = c(640,640) and scale = 2 returns an 46 | image with 1280x1280 pixels). 4 is reserved for google business users 47 | only. scale also affects the size of labels as well.} 48 | 49 | \item{format}{character string providing image format - png, jpeg, and gif 50 | formats available in various flavors} 51 | 52 | \item{maptype}{character string providing google map theme. options available 53 | are \code{"terrain"}, \code{"satellite"}, \code{"roadmap"}, and \code{"hybrid"}} 54 | 55 | \item{language}{character string providing language of map labels (for themes 56 | with them) in the format \code{"en-EN"}. not all languages are supported; for 57 | those which aren't the default language is used} 58 | 59 | \item{messaging}{turn messaging on/off} 60 | 61 | \item{urlonly}{return url only} 62 | 63 | \item{filename}{destination file for download (file extension added according 64 | to format). Default \code{NULL} means a random \code{\link[=tempfile]{tempfile()}}.} 65 | 66 | \item{color}{color or black-and-white} 67 | 68 | \item{force}{if the map is on file, should a new map be looked up?} 69 | 70 | \item{where}{where should the file drawer be located (without terminating 71 | "/")} 72 | 73 | \item{archiving}{use archived maps. note: by changing to TRUE you agree to 74 | the one of the approved uses listed in the Google Maps API Terms of Service 75 | : \url{https://cloud.google.com/maps-platform/terms}.} 76 | 77 | \item{ext}{domain extension (e.g. \code{"com"}, \code{"co.nz"})} 78 | 79 | \item{inject}{character string to add to the url} 80 | 81 | \item{region}{borders to display as a region code specified as a 82 | two-character ccTLD ("top-level domain") value, see 83 | \url{https://en.wikipedia.org/wiki/List_of_Internet_top-level_domains#Country_code_top-level_domains}} 84 | 85 | \item{markers}{data.frame with first column longitude, second column 86 | latitude, for which google markers should be embedded in the map image, or 87 | character string to be passed directly to api} 88 | 89 | \item{path}{data.frame (or list of data.frames) with first column longitude, 90 | second column latitude, for which a single path should be embedded in the 91 | map image, or character string to be passed directly to api} 92 | 93 | \item{visible}{a location as a longitude/latitude numeric vector (or data 94 | frame with first column longitude, second latitude) or vector of character 95 | string addresses which should be visible in map extent} 96 | 97 | \item{style}{character string to be supplied directly to the api for the 98 | style argument or a named vector (see examples). this is a powerful complex 99 | specification, see 100 | \url{https://developers.google.com/maps/documentation/maps-static/}} 101 | 102 | \item{...}{...} 103 | } 104 | \value{ 105 | a ggmap object (a classed raster object with a bounding box 106 | attribute) 107 | } 108 | \description{ 109 | \code{\link[=get_googlemap]{get_googlemap()}} queries the Google Maps Static API version 2 to download 110 | a static map. Note that in most cases by using this function you are 111 | agreeing to the Google Maps API Terms of Service at 112 | \url{https://cloud.google.com/maps-platform/terms}. Note that as of mid-2018, 113 | registering with Google Cloud to obtain an API key is required to use any of 114 | Google's services, including \code{\link[=get_googlemap]{get_googlemap()}}. Usage and billing may apply, 115 | see the links under See Also further down in this documentation for more 116 | details. 117 | } 118 | \examples{ 119 | 120 | \dontrun{ requires Google API key, see ?register_google 121 | 122 | ## basic usage 123 | ######################################## 124 | 125 | (map <- get_googlemap(c(-97.14667, 31.5493))) 126 | ggmap(map) 127 | 128 | # plotting based on a colloquial name 129 | # this requires a geocode() call, and needs that API 130 | get_googlemap("waco, texas") \%>\% ggmap() 131 | 132 | # different maptypes are available 133 | get_googlemap("waco, texas", maptype = "satellite") \%>\% ggmap() 134 | get_googlemap("waco, texas", maptype = "hybrid") \%>\% ggmap() 135 | 136 | # you can get the url as follows 137 | # see ?register_google if you want the key printed 138 | get_googlemap(urlonly = TRUE) 139 | 140 | 141 | ## other usage 142 | ######################################## 143 | 144 | # markers and paths are easy to access 145 | d <- function(x=-95.36, y=29.76, n,r,a){ 146 | round(data.frame( 147 | lon = jitter(rep(x,n), amount = a), 148 | lat = jitter(rep(y,n), amount = a) 149 | ), digits = r) 150 | } 151 | (df <- d(n = 50, r = 3, a = .3)) 152 | map <- get_googlemap(markers = df, path = df, scale = 2) 153 | ggmap(map) 154 | ggmap(map, extent = "device") + 155 | geom_point(aes(x = lon, y = lat), data = df, size = 3, colour = "black") + 156 | geom_path(aes(x = lon, y = lat), data = df) 157 | 158 | gc <- geocode("waco, texas", source = "google") 159 | center <- as.numeric(gc) 160 | ggmap(get_googlemap(center = center, color = "bw", scale = 2), extent = "device") 161 | 162 | # the scale argument can be seen in the following 163 | # (make your graphics device as large as possible) 164 | ggmap(get_googlemap(center, scale = 1), extent = "panel") # pixelated 165 | ggmap(get_googlemap(center, scale = 2), extent = "panel") # fine 166 | 167 | # archiving; note that you must meet google's terms for this condition 168 | map <- get_googlemap(archiving = TRUE) 169 | map <- get_googlemap() 170 | map <- get_googlemap() 171 | ggmap(map) 172 | 173 | 174 | # style 175 | map <- get_googlemap( 176 | maptype = "roadmap", 177 | style = c(feature = "all", element = "labels", visibility = "off"), 178 | color = "bw" 179 | ) 180 | ggmap(map) 181 | 182 | 183 | 184 | 185 | } 186 | 187 | } 188 | \seealso{ 189 | \url{https://developers.google.com/maps/documentation/maps-static/overview/}, 190 | \url{https://developers.google.com/maps/documentation/maps-static/start/}, 191 | \url{https://developers.google.com/maps/documentation/maps-static/get-api-key/}, 192 | \url{https://developers.google.com/maps/documentation/maps-static/usage-and-billing/}, 193 | \code{\link[=ggmap]{ggmap()}}, \code{\link[=register_google]{register_google()}} 194 | } 195 | \author{ 196 | David Kahle \email{david@kahle.io} 197 | } 198 | -------------------------------------------------------------------------------- /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( 8 | location = c(lon = -95.3632715, lat = 29.7632836), 9 | zoom = "auto", 10 | scale = "auto", 11 | maptype = c(GOOGLE_VALID_MAP_TYPES, STADIA_VALID_MAP_TYPES), 12 | source = c("google", "osm", "stadia"), 13 | force = ifelse(source == "google", TRUE, FALSE), 14 | messaging = FALSE, 15 | urlonly = FALSE, 16 | filename = NULL, 17 | crop = TRUE, 18 | color = c("color", "bw"), 19 | language = "en-EN", 20 | ... 21 | ) 22 | } 23 | \arguments{ 24 | \item{location}{an address, longitude/latitude pair (in that order), or 25 | left/bottom/right/top bounding box} 26 | 27 | \item{zoom}{map zoom, an integer from 3 (continent) to 21 (building), default 28 | value 10 (city). openstreetmaps limits a zoom of 18, and the limit on 29 | Stadia Maps depends on the maptype. "auto" automatically determines the 30 | zoom for bounding box specifications, and is defaulted to 10 with 31 | center/zoom specifications. maps of the whole world currently not 32 | supported.} 33 | 34 | \item{scale}{scale argument of \code{\link[=get_googlemap]{get_googlemap()}} or \code{\link[=get_openstreetmap]{get_openstreetmap()}}} 35 | 36 | \item{maptype}{character string providing map theme. options available are 37 | "terrain", "terrain-background", "satellite", "roadmap", and "hybrid" 38 | (Google Maps), "stamen_terrain", "stamen_toner", "stamen_toner_lite", "stamen_watercolor", 39 | "stamen_terrain_background", "stamen_toner_background", 40 | "stamen_terrain_lines", "stamen_terrain_labels", 41 | "stamen_toner_lines", "stamen_toner_labels" 42 | (Stadia Maps)} 43 | 44 | \item{source}{Google Maps ("google"), OpenStreetMap ("osm"), Stadia Maps 45 | ("stadia")} 46 | 47 | \item{force}{force new map (don't use archived version)} 48 | 49 | \item{messaging}{turn messaging on/off} 50 | 51 | \item{urlonly}{return url only} 52 | 53 | \item{filename}{destination file for download (file extension added according 54 | to format). Default \code{NULL} means a random \code{\link[=tempfile]{tempfile()}}.} 55 | 56 | \item{crop}{(Stadia and cloudmade maps) crop tiles to bounding box} 57 | 58 | \item{color}{color ("color") or black-and-white ("bw")} 59 | 60 | \item{language}{language for google maps} 61 | 62 | \item{...}{...} 63 | } 64 | \value{ 65 | a ggmap object (a classed raster object with a bounding box 66 | attribute) 67 | } 68 | \description{ 69 | \code{\link[=get_map]{get_map()}} is a smart wrapper that queries the Google Maps, 70 | OpenStreetMap, and Stadia Maps servers for a map. 71 | } 72 | \examples{ 73 | 74 | \dontrun{ some requires Google API key, see ?register_google 75 | 76 | ## basic usage 77 | ######################################## 78 | 79 | # lon-lat vectors automatically use google: 80 | (map <- get_map(c(-97.14667, 31.5493))) 81 | str(map) 82 | ggmap(map) 83 | 84 | # bounding boxes default to Stadia Maps 85 | (map <- get_map(c(left = -97.1268, bottom = 31.536245, right = -97.099334, top = 31.559652))) 86 | ggmap(map) 87 | 88 | # characters default to google 89 | (map <- get_map("orlando, florida")) 90 | ggmap(map) 91 | 92 | 93 | ## basic usage 94 | ######################################## 95 | 96 | (map <- get_map(maptype = "roadmap")) 97 | (map <- get_map(source = "osm")) 98 | (map <- get_map(source = "stadia", maptype = "stamen_watercolor")) 99 | 100 | map <- get_map(location = "texas", zoom = 6, source = "stadia") 101 | ggmap(map, fullpage = TRUE) 102 | 103 | } 104 | } 105 | \seealso{ 106 | \code{\link[=ggmap]{ggmap()}} 107 | } 108 | \author{ 109 | David Kahle \email{david@kahle.io} 110 | } 111 | -------------------------------------------------------------------------------- /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( 8 | center = c(lon = 126.9849208, lat = 37.5664519), 9 | zoom = 4, 10 | size = c(640, 640), 11 | format = c("png", "jpeg", "jpg"), 12 | crs = c("EPSG:4326", "NHN:2048", "NHN:128", "EPSG:4258", "EPSG:4162", "EPSG:2096", 13 | "EPSG:2097", "EPSG:2098", "EPSG:900913"), 14 | baselayer = c("default", "satellite"), 15 | color = c("color", "bw"), 16 | overlayers = c("anno_satellite", "bicycle", "roadview", "traffic"), 17 | markers, 18 | key, 19 | uri, 20 | filename = NULL, 21 | messaging = FALSE, 22 | urlonly = FALSE, 23 | force = FALSE, 24 | where = tempdir(), 25 | archiving = TRUE, 26 | ... 27 | ) 28 | } 29 | \arguments{ 30 | \item{center}{the center of the map. this can be longitude/latitude numeric 31 | vector.} 32 | 33 | \item{zoom}{map zoom, an integer from 1 to 14 (building), default value 10} 34 | 35 | \item{size}{rectangular dimensions of map in pixels - horizontal x vertical - 36 | with a max of c(640, 640).} 37 | 38 | \item{format}{character string providing image format - png, jpeg(jpg) 39 | formats available in various flavors} 40 | 41 | \item{crs}{Coordinate system, this currently supports EPSG:4326} 42 | 43 | \item{baselayer}{base layer, this can be either "default", "satellite".} 44 | 45 | \item{color}{color or black-and-white} 46 | 47 | \item{overlayers}{overlay layers, this can be "anno_satellite","bicycle", 48 | "roadview", "traffic".} 49 | 50 | \item{markers}{data.frame with first column longitude, second column 51 | latitude, for which naver markers should be embedded in the map image, or 52 | character string to be passed directly to api} 53 | 54 | \item{key}{key code from naver api center} 55 | 56 | \item{uri}{registered host url} 57 | 58 | \item{filename}{destination file for download (file extension added according 59 | to format). Default \code{NULL} means a random \code{\link[=tempfile]{tempfile()}}.} 60 | 61 | \item{messaging}{turn messaging on/off} 62 | 63 | \item{urlonly}{return url only} 64 | 65 | \item{force}{if the map is on file, should a new map be looked up?} 66 | 67 | \item{where}{where should the file drawer be located (without terminating 68 | "/")} 69 | 70 | \item{archiving}{use archived maps. note: by changing to TRUE you agree to 71 | abide by any of the rules governing caching naver maps} 72 | 73 | \item{...}{...} 74 | } 75 | \description{ 76 | This is (at least) temporarily unavailable as the Naver API changed. 77 | } 78 | \details{ 79 | \code{\link[=get_navermap]{get_navermap()}} accesses the Naver Static Maps API version 1.1 to 80 | download a static map. Note that in most cases by using this function you are 81 | agreeing to the Naver Maps API Terms of Service. 82 | } 83 | \seealso{ 84 | \code{\link[=ggmap]{ggmap()}} 85 | } 86 | \author{ 87 | Heewon Jeon \email{madjakarta@gmail.com} 88 | } 89 | -------------------------------------------------------------------------------- /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( 8 | bbox = c(left = -95.80204, bottom = 29.38048, right = -94.92313, top = 30.14344), 9 | scale = 606250, 10 | format = c("png", "jpeg", "svg", "pdf", "ps"), 11 | messaging = FALSE, 12 | urlonly = FALSE, 13 | filename = NULL, 14 | color = c("color", "bw"), 15 | ... 16 | ) 17 | } 18 | \arguments{ 19 | \item{bbox}{a bounding box in the format c(lowerleftlon, lowerleftlat, 20 | upperrightlon, upperrightlat)} 21 | 22 | \item{scale}{scale parameter, see 23 | \url{https://wiki.openstreetmap.org/wiki/MinScaleDenominator}. smaller 24 | scales provide a finer degree of detail, where larger scales produce more 25 | coarse detail. The scale argument is a tricky number to correctly specify. 26 | In most cases, if you get an error when downloading an openstreetmap the 27 | error is attributable to an improper scale specification. 28 | \code{\link[=OSM_scale_lookup]{OSM_scale_lookup()}} can help; but the best way to get in the correct range 29 | is to go to \url{https://www.openstreetmap.org/}, navigate to the map of 30 | interest, click export at the top of the page, click 'map image' and then 31 | copy down the scale listed.} 32 | 33 | \item{format}{character string providing image format - png, jpeg, svg, pdf, 34 | and ps formats} 35 | 36 | \item{messaging}{turn messaging on/off} 37 | 38 | \item{urlonly}{return url only} 39 | 40 | \item{filename}{destination file for download (file extension added according 41 | to format). Default \code{NULL} means a random \code{\link[=tempfile]{tempfile()}}.} 42 | 43 | \item{color}{color or black-and-white} 44 | 45 | \item{...}{...} 46 | } 47 | \value{ 48 | a ggmap object (a classed raster object with a bounding box 49 | attribute) 50 | } 51 | \description{ 52 | \code{\link[=get_openstreetmap]{get_openstreetmap()}} accesses a tile server for OpenStreetMap and 53 | downloads/formats a map image. This is simply a wrapper for the web-based 54 | version at \url{https://www.openstreetmap.org/}. If you don't know how to get 55 | the map you want, go there, navigate to the map extent that you want, click 56 | the export tab at the top of the page, and copy the information into this 57 | function. 58 | } 59 | \details{ 60 | In some cases the OSM server is unavailable, in these cases you will receive 61 | an error message from \code{\link[utils:download.file]{utils::download.file()}} with the message HTTP status 62 | '503 Service Unavailable'. You can confirm this by setting \code{urlonly = TRUE}, 63 | and then entering the URL in a web browser. the solution is either (1) 64 | change sources or (2) wait for the OSM servers to come back up. 65 | 66 | See \url{https://www.openstreetmap.org/copyright/} for license and copyright 67 | information. 68 | } 69 | \seealso{ 70 | \url{https://www.openstreetmap.org/}, \code{\link[=ggmap]{ggmap()}} 71 | } 72 | \author{ 73 | David Kahle \email{david@kahle.io} 74 | } 75 | -------------------------------------------------------------------------------- /man/get_stadiamap.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get_stadiamap.R 3 | \name{get_stadiamap} 4 | \alias{get_stadiamap} 5 | \title{Get a Map from Stadia Maps} 6 | \usage{ 7 | get_stadiamap( 8 | bbox = c(left = -95.80204, bottom = 29.38048, right = -94.92313, top = 30.14344), 9 | zoom = 10, 10 | maptype = STADIA_VALID_MAP_TYPES, 11 | crop = TRUE, 12 | messaging = FALSE, 13 | urlonly = FALSE, 14 | color = c("color", "bw"), 15 | force = FALSE, 16 | where = tempdir(), 17 | ... 18 | ) 19 | } 20 | \arguments{ 21 | \item{bbox}{a bounding box in the format c(lowerleftlon, lowerleftlat, 22 | upperrightlon, upperrightlat).} 23 | 24 | \item{zoom}{a zoom level} 25 | 26 | \item{maptype}{stamen_terrain, stamen_toner, stamen_toner_lite, stamen_watercolor, 27 | stamen_terrain_background, stamen_toner_background, 28 | stamen_terrain_lines, stamen_terrain_labels, 29 | stamen_toner_lines, stamen_toner_labels.} 30 | 31 | \item{crop}{crop raw map tiles to specified bounding box. if FALSE, the 32 | resulting map will more than cover the bounding box specified.} 33 | 34 | \item{messaging}{turn messaging on/off} 35 | 36 | \item{urlonly}{return url only} 37 | 38 | \item{color}{color or black-and-white (use force = TRUE if you've already 39 | downloaded the images)} 40 | 41 | \item{force}{if the map is on file, should a new map be looked up?} 42 | 43 | \item{where}{where should the file drawer be located (without terminating 44 | "/")} 45 | 46 | \item{...}{...} 47 | } 48 | \value{ 49 | a ggmap object (a classed raster object with a bounding box 50 | attribute) 51 | } 52 | \description{ 53 | \code{\link[=get_stadiamap]{get_stadiamap()}} accesses a tile server for Stadia Maps and 54 | downloads/stitches map tiles/formats a map image. 55 | } 56 | \examples{ 57 | 58 | \dontrun{ requires a Stadia Maps API key. see ?register_stadiamaps 59 | 60 | 61 | ## basic usage 62 | ######################################## 63 | 64 | bbox <- c(left = -97.1268, bottom = 31.536245, right = -97.099334, top = 31.559652) 65 | 66 | ggmap(get_stadiamap(bbox, zoom = 13)) 67 | ggmap(get_stadiamap(bbox, zoom = 14)) 68 | ggmap(get_stadiamap(bbox, zoom = 15)) 69 | ggmap(get_stadiamap(bbox, zoom = 17, messaging = TRUE)) 70 | 71 | place <- "mount everest" 72 | (google <- get_googlemap(place, zoom = 9)) 73 | ggmap(google) 74 | bbox_everest <- c(left = 86.05, bottom = 27.21, right = 87.81, top = 28.76) 75 | ggmap(get_stadiamap(bbox_everest, zoom = 9)) 76 | 77 | 78 | 79 | ## map types 80 | ######################################## 81 | 82 | place <- "rio de janeiro" 83 | google <- get_googlemap(place, zoom = 10) 84 | ggmap(google) 85 | 86 | bbox <- bb2bbox(attr(google, "bb")) 87 | 88 | get_stadiamap(bbox, maptype = "stamen_terrain") \%>\% ggmap() 89 | get_stadiamap(bbox, maptype = "stamen_terrain_background") \%>\% ggmap() 90 | get_stadiamap(bbox, maptype = "stamen_terrain_labels") \%>\% ggmap() 91 | get_stadiamap(bbox, maptype = "stamen_terrain_lines") \%>\% ggmap() 92 | get_stadiamap(bbox, maptype = "stamen_toner") \%>\% ggmap() 93 | get_stadiamap(bbox, maptype = "stamen_toner_background") \%>\% ggmap() 94 | get_stadiamap(bbox, maptype = "stamen_toner_labels") \%>\% ggmap() 95 | get_stadiamap(bbox, maptype = "stamen_toner_lines") \%>\% ggmap() 96 | get_stadiamap(bbox, maptype = "stamen_toner_lite") \%>\% ggmap() 97 | get_stadiamap(bbox, maptype = "stamen_watercolor") \%>\% ggmap() 98 | 99 | 100 | ## zoom levels 101 | ######################################## 102 | 103 | get_stadiamap(bbox, maptype = "stamen_watercolor", zoom = 11) \%>\% ggmap(extent = "device") 104 | get_stadiamap(bbox, maptype = "stamen_watercolor", zoom = 12) \%>\% ggmap(extent = "device") 105 | get_stadiamap(bbox, maptype = "stamen_watercolor", zoom = 13) \%>\% ggmap(extent = "device") 106 | # get_stadiamap(bbox, maptype = "stamen_watercolor", zoom = 14) \%>\% ggmap(extent = "device") 107 | # get_stadiamap(bbox, maptype = "stamen_watercolor", zoom = 15) \%>\% ggmap(extent = "device") 108 | # get_stadiamap(bbox, maptype = "stamen_watercolor", zoom = 16) \%>\% ggmap(extent = "device") 109 | # get_stadiamap(bbox, maptype = "stamen_watercolor", zoom = 17) \%>\% ggmap(extent = "device") 110 | # get_stadiamap(bbox, maptype = "stamen_watercolor", zoom = 18) \%>\% ggmap(extent = "device") 111 | 112 | ## more examples 113 | ######################################## 114 | 115 | gc <- geocode("rio de janeiro") 116 | 117 | get_stadiamap(bbox, zoom = 10) \%>\% ggmap() + 118 | geom_point(aes(x = lon, y = lat), data = gc, colour = "red", size = 2) 119 | 120 | get_stadiamap(bbox, zoom = 10, crop = FALSE) \%>\% ggmap() + 121 | geom_point(aes(x = lon, y = lat), data = gc, colour = "red", size = 2) 122 | 123 | get_stadiamap(bbox, zoom = 10, maptype = "stamen_watercolor") \%>\% ggmap() + 124 | geom_point(aes(x = lon, y = lat), data = gc, colour = "red", size = 2) 125 | 126 | get_stadiamap(bbox, zoom = 10, maptype = "stamen_toner") \%>\% ggmap() + 127 | geom_point(aes(x = lon, y = lat), data = gc, colour = "red", size = 2) 128 | 129 | 130 | # continental united states labels 131 | c("left" = -125, "bottom" = 25.75, "right" = -67, "top" = 49) \%>\% 132 | get_stadiamap(zoom = 5, maptype = "stamen_toner_labels") \%>\% 133 | ggmap() 134 | 135 | 136 | 137 | 138 | # accuracy check - white house 139 | gc <- geocode("the white house") 140 | 141 | qmap("the white house", zoom = 16) + 142 | geom_point(aes(x = lon, y = lat), data = gc, colour = "red", size = 3) 143 | 144 | qmap("the white house", zoom = 16, source = "stadia", maptype = "stamen_terrain") + 145 | geom_point(aes(x = lon, y = lat), data = gc, colour = "red", size = 3) 146 | 147 | 148 | 149 | ## known issues 150 | ######################################## 151 | 152 | # Stamen's original tilesets were raster renders built up over time, but have not been 153 | # actively rendered for several years. As a consequence, some tiles simply do not exist, 154 | # particularly at high zoom levels. 155 | # 156 | # The newer styles have been redesigned and are now generated live by Stadia Maps, so 157 | # these are complete, but at the time of this writing, the Watercolor style is still incomplete. 158 | } 159 | } 160 | \seealso{ 161 | \url{https://docs.stadiamaps.com/themes/}, \code{\link[=ggmap]{ggmap()}} 162 | } 163 | -------------------------------------------------------------------------------- /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 | \alias{get_stamen_tile_download_fail_log} 6 | \alias{retry_stamen_map_download} 7 | \title{Get a Stamen Map} 8 | \usage{ 9 | get_stamenmap( 10 | bbox = c(left = -95.80204, bottom = 29.38048, right = -94.92313, top = 30.14344), 11 | zoom = 10, 12 | maptype = c("terrain", "terrain-background", "terrain-labels", "terrain-lines", 13 | "toner", "toner-2010", "toner-2011", "toner-background", "toner-hybrid", 14 | "toner-labels", "toner-lines", "toner-lite", "watercolor"), 15 | crop = TRUE, 16 | messaging = FALSE, 17 | urlonly = FALSE, 18 | color = c("color", "bw"), 19 | force = FALSE, 20 | where = tempdir(), 21 | https = FALSE, 22 | ... 23 | ) 24 | 25 | get_stamen_tile_download_fail_log() 26 | 27 | retry_stamen_map_download() 28 | } 29 | \arguments{ 30 | \item{bbox}{a bounding box in the format c(lowerleftlon, lowerleftlat, 31 | upperrightlon, upperrightlat).} 32 | 33 | \item{zoom}{a zoom level} 34 | 35 | \item{maptype}{terrain, terrain-background, terrain-labels, terrain-lines, 36 | toner, toner-2010, toner-2011, toner-background, toner-hybrid, 37 | toner-labels, toner-lines, toner-lite, or watercolor.} 38 | 39 | \item{crop}{crop raw map tiles to specified bounding box. if FALSE, the 40 | resulting map will more than cover the bounding box specified.} 41 | 42 | \item{messaging}{turn messaging on/off} 43 | 44 | \item{urlonly}{return url only} 45 | 46 | \item{color}{color or black-and-white (use force = TRUE if you've already 47 | downloaded the images)} 48 | 49 | \item{force}{if the map is on file, should a new map be looked up?} 50 | 51 | \item{where}{where should the file drawer be located (without terminating 52 | "/")} 53 | 54 | \item{https}{if TRUE, queries an https endpoint so that web traffic between 55 | you and the tile server is ecrypted using SSL.} 56 | 57 | \item{...}{...} 58 | } 59 | \value{ 60 | a ggmap object (a classed raster object with a bounding box 61 | attribute) 62 | } 63 | \description{ 64 | \code{\link[=get_stamenmap]{get_stamenmap()}} accesses a tile server for Stamen Maps and 65 | downloads/stitches map tiles/formats a map image. Note that Stamen maps don't 66 | cover the entire world. 67 | } 68 | \seealso{ 69 | \code{\link[=ggmap]{ggmap()}} 70 | } 71 | -------------------------------------------------------------------------------- /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( 46 | aes(x = x, y = y), 47 | data = df, color = 'green', size = 1 48 | ) + 49 | geom_point( 50 | aes(x = x, y = y), 51 | data = df, color = 'green', size = 3 52 | ) 53 | 54 | } 55 | } 56 | \author{ 57 | David Kahle \email{david@kahle.io} 58 | } 59 | -------------------------------------------------------------------------------- /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 ggplot objects} 6 | \usage{ 7 | gglocator(n = 1, message = FALSE, mercator = TRUE, ...) 8 | } 9 | \arguments{ 10 | \item{n}{number of points to locate.} 11 | 12 | \item{message}{unused} 13 | 14 | \item{mercator}{logical flag; should the plot be treated as using the 15 | projection common to most web map services? Set to FALSE if the axes on the 16 | plot use a linear scale.} 17 | 18 | \item{...}{additional arguments (including deprecated, e.g. xexpand)} 19 | } 20 | \value{ 21 | a data frame with columns according to the x and y aesthetics 22 | } 23 | \description{ 24 | Locator for ggplot objects (Note : only accurate when extent = "normal" when 25 | using ggmap.) 26 | } 27 | \examples{ 28 | 29 | if (interactive()) { 30 | 31 | # only run for interactive sessions 32 | df <- expand.grid(x = 0:-5, y = 0:-5) 33 | 34 | ggplot(df, aes(x, y)) + geom_point() + 35 | annotate(geom = "point", x = -2, y = -2, colour = "red") 36 | 37 | (pt <- gglocator(mercator = FALSE)) # click red point 38 | 39 | last_plot() + 40 | annotate("point", pt$x, pt$y, color = "blue", size = 3, alpha = .5) 41 | 42 | hdf <- get_map("houston, texas") 43 | ggmap(hdf, extent = "normal") 44 | (pt <- gglocator(mercator = TRUE)) 45 | last_plot() + 46 | annotate("point", pt$lon, pt$lat, color = "blue", size = 3, alpha = .5) 47 | 48 | } 49 | 50 | 51 | } 52 | \author{ 53 | Tyler Rinker, Baptiste Auguie, DWin, David Kahle, \@Nikolai-Hlubek 54 | and \@mvkorpel. 55 | } 56 | -------------------------------------------------------------------------------- /man/ggmap-defunct.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggmap-defunct.R 3 | \name{ggmap-defunct} 4 | \alias{ggmap-defunct} 5 | \title{Defunct ggmap functions} 6 | \description{ 7 | As provider services change over time, ggmap has to make corresponding 8 | changes. Since its inception, a few services have stopped offering their 9 | previous functionality, and in some cases this has required us to remove 10 | those functions from the package entirely. 11 | } 12 | \details{ 13 | The following are defunct ggmap functions: 14 | \itemize{ 15 | \item get_cloudemademap 16 | \item get_navermap 17 | \item get_openstreetmap 18 | \item get_stamenmap 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /man/ggmap_options.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/ggmap_options.R 3 | \name{ggmap_options} 4 | \alias{ggmap_options} 5 | \alias{set_ggmap_option} 6 | \alias{has_ggmap_options} 7 | \alias{has_ggmap_option} 8 | \alias{ggmap_credentials} 9 | \title{ggmap Options} 10 | \usage{ 11 | set_ggmap_option(...) 12 | 13 | has_ggmap_options() 14 | 15 | has_ggmap_option(option) 16 | 17 | ggmap_credentials() 18 | } 19 | \arguments{ 20 | \item{...}{a named listing of options to set} 21 | 22 | \item{option}{a specific option to query, e.g. \code{"display_api_key"}} 23 | } 24 | \description{ 25 | ggmap stores options as a named list in R's global options, i.e. 26 | \code{getOption("ggmap")}. It currently stores two such options, one for Google 27 | credentialing and one to suppress private API information in the URLs printed 28 | to the screen when web queries are placed. For both of those, see 29 | \code{\link[=register_google]{register_google()}}. 30 | } 31 | \examples{ 32 | 33 | getOption("ggmap") 34 | has_ggmap_options() 35 | has_ggmap_option("display_api_key") 36 | 37 | 38 | 39 | } 40 | \seealso{ 41 | \code{\link[=register_google]{register_google()}} 42 | } 43 | \author{ 44 | David Kahle \email{david@kahle.io} 45 | } 46 | -------------------------------------------------------------------------------- /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( 8 | ggmap, 9 | fullpage = FALSE, 10 | base_layer, 11 | maprange = FALSE, 12 | expand = FALSE, 13 | ... 14 | ) 15 | } 16 | \arguments{ 17 | \item{ggmap}{an object of class ggmap (from function \code{\link[=get_map]{get_map()}})} 18 | 19 | \item{fullpage}{logical; should the map take up the entire viewport?} 20 | 21 | \item{base_layer}{a ggplot(aes(...), ...) call; see examples} 22 | 23 | \item{maprange}{logical for use with base_layer; should the map define the x and y limits?} 24 | 25 | \item{expand}{should the map extend to the edge of the panel? used with base_layer and maprange=TRUE.} 26 | 27 | \item{...}{...} 28 | } 29 | \value{ 30 | a ggplot object 31 | } 32 | \description{ 33 | ggmap plots the raster object produced by \code{\link[=get_map]{get_map()}}. 34 | } 35 | \examples{ 36 | \dontrun{ 37 | this is a deprecated function, use ggmap. 38 | } 39 | } 40 | \seealso{ 41 | \code{\link[=get_map]{get_map()}}, \code{\link[=qmap]{qmap()}} 42 | } 43 | \author{ 44 | David Kahle \email{david@kahle.io} 45 | } 46 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 horizontal location 13 | of raster} 14 | 15 | \item{ymin, ymax}{y location (in data coordinates) giving vertical location of 16 | raster} 17 | } 18 | \description{ 19 | This is identical to ggplot2::annotation_custom for use with ggmap 20 | } 21 | \details{ 22 | Most useful for adding tables, inset plots, and other grid-based decorations 23 | } 24 | \note{ 25 | \code{\link[=annotation_custom]{annotation_custom()}} expects the grob to fill the entire viewport 26 | defined by xmin, xmax, ymin, ymax. Grobs with a different (absolute) size 27 | will be center-justified in that region. Inf values can be used to fill the 28 | full plot panel 29 | } 30 | -------------------------------------------------------------------------------- /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 horizontal location 16 | of raster} 17 | 18 | \item{ymin, ymax}{y location (in data coordinates) giving vertical location of 19 | raster} 20 | 21 | \item{interpolate}{interpolate the raster? (i.e. antialiasing)} 22 | 23 | \item{ggmap}{a ggmap object, see \code{\link[=get_map]{get_map()}}} 24 | } 25 | \description{ 26 | This is a special version of ggplot2::annotation_raster for use with ggmap. 27 | (It simply removes the requirement for cartesian coordinates.) The only 28 | difference between \code{\link[=inset_raster]{inset_raster()}} and \code{\link[=inset_ggmap]{inset_ggmap()}} is their arguments. 29 | \code{\link[=inset_ggmap]{inset_ggmap()}} is simply a wrapper of \code{\link[=inset_raster]{inset_raster()}} with \code{xmin}, \code{...}, 30 | \code{ymax} arguments equal to the map's bounding box. 31 | } 32 | \examples{ 33 | 34 | \dontrun{ # save cran check time 35 | 36 | bbox <- c(left = -97.1268, bottom = 31.536245, right = -97.099334, top = 31.559652) 37 | 38 | terrain_map <- get_stadiamap(bbox, zoom = 14, maptype = "stamen_terrain_background", color = "bw") 39 | ggmap(terrain_map) 40 | 41 | lines_map <- get_stadiamap(bbox, zoom = 14, maptype = "stamen_toner_lines") 42 | ggmap(lines_map) 43 | 44 | ggmap(terrain_map) + 45 | inset_ggmap(lines_map) 46 | 47 | 48 | } 49 | 50 | 51 | } 52 | \seealso{ 53 | \code{\link[=bb2bbox]{bb2bbox()}} 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]{route()}}} 11 | } 12 | \description{ 13 | Convert a leg-structured route to a route-structured route 14 | } 15 | \examples{ 16 | 17 | \dontrun{ requires Google API key, see ?register_google 18 | 19 | (legs_df <- route("houston","galveston")) 20 | legs2route(legs_df) 21 | 22 | (legs_df <- route( 23 | "marrs mclean science, baylor university", 24 | "220 south 3rd street, waco, tx 76701", # ninfa"s 25 | alternatives = TRUE)) 26 | 27 | legs2route(legs_df) 28 | 29 | 30 | 31 | 32 | from <- "houston, texas" 33 | to <- "waco, texas" 34 | legs_df <- route(from, to) 35 | 36 | 37 | qmap("college station, texas", zoom = 8) + 38 | geom_segment( 39 | aes(x = start_lon, y = start_lat, xend = end_lon, yend = end_lat), 40 | colour = "red", size = 1.5, data = legs_df 41 | ) 42 | # notice boxy ends 43 | 44 | qmap("college station, texas", zoom = 8) + 45 | geom_leg( 46 | aes(x = start_lon, y = start_lat, xend = end_lon, yend = end_lat), 47 | colour = "red", size = 1.5, data = legs_df 48 | ) 49 | # notice overshooting ends 50 | 51 | route_df <- legs2route(legs_df) 52 | qmap("college station, texas", zoom = 8) + 53 | geom_path( 54 | aes(x = lon, y = lat), 55 | colour = "red", size = 1.5, data = route_df, lineend = "round" 56 | ) 57 | 58 | 59 | 60 | } 61 | 62 | } 63 | \seealso{ 64 | \code{\link[=geom_path]{geom_path()}} 65 | } 66 | -------------------------------------------------------------------------------- /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 variables} 15 | 16 | \item{f}{number specifying the fraction by which the range should be 17 | extended. if length 2 vector, applies to longitude and then latitude.} 18 | } 19 | \description{ 20 | Compute a bounding box for a given longitude / latitude collection. 21 | } 22 | \examples{ 23 | 24 | make_bbox(lon, lat, data = crime) 25 | make_bbox(lon, lat, data = crime, f = .20) 26 | make_bbox(lon, lat, data = crime, f = c(.20, .05)) 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/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 | \alias{distQueryCheck} 6 | \title{Compute map distances using Google} 7 | \usage{ 8 | mapdist( 9 | from, 10 | to, 11 | mode = c("driving", "walking", "bicycling", "transit"), 12 | output = c("simple", "all"), 13 | urlonly = FALSE, 14 | override_limit = FALSE, 15 | ext = "com", 16 | inject = "", 17 | ... 18 | ) 19 | 20 | distQueryCheck() 21 | } 22 | \arguments{ 23 | \item{from}{name of origin addresses in a data frame (vector accepted), or a 24 | data frame with from and to columns} 25 | 26 | \item{to}{name of destination addresses in a data frame (vector accepted)} 27 | 28 | \item{mode}{driving, bicycling, walking, or transit} 29 | 30 | \item{output}{amount of output} 31 | 32 | \item{urlonly}{return only the url?} 33 | 34 | \item{override_limit}{override the current query count 35 | (.google_distance_query_times)} 36 | 37 | \item{ext}{top level domain 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 information 45 | (output="all") 46 | } 47 | \description{ 48 | Compute map distances using Google's Distance Matrix API. Note: To use 49 | Google's Distance Matrix API, you must first enable the API in the Google 50 | Cloud Platform Console. See \code{\link[=register_google]{register_google()}}. 51 | } 52 | \details{ 53 | if parameters from and to are specified as geographic coordinates, 54 | they are reverse geocoded with revgeocode. note that the google maps api 55 | limits to 2500 element queries a day. 56 | } 57 | \examples{ 58 | 59 | \dontrun{ requires Google API key, see ?register_google 60 | 61 | ## basic usage 62 | ######################################## 63 | 64 | mapdist("waco, texas", "houston, texas") 65 | 66 | 67 | # many from, single to 68 | from <- c("houston, texas", "dallas") 69 | to <- "waco, texas" 70 | mapdist(from, to) 71 | mapdist(from, to, mode = "bicycling") 72 | mapdist(from, to, mode = "walking") 73 | 74 | 75 | # tibble of from's, vector of to's 76 | # (with a data frame, remember stringsAsFactors = FALSE) 77 | tibble( 78 | "from" = c("houston", "houston", "dallas"), 79 | "to" = c("waco", "san antonio", "houston") 80 | ) \%>\% mapdist() 81 | 82 | 83 | # distance matrix 84 | library("tidyverse") 85 | c("Hamburg, Germany", "Stockholm, Sweden", "Copenhagen, Denmark") \%>\% 86 | list(., .) \%>\% 87 | set_names(c("from", "to")) \%>\% 88 | cross_df() \%>\% 89 | mapdist() -> distances 90 | 91 | distances 92 | 93 | distances \%>\% 94 | select(from, to, km) \%>\% 95 | spread(from, km) 96 | 97 | 98 | 99 | 100 | 101 | ## other examples 102 | ######################################## 103 | 104 | # many from, single to with addresses 105 | from <- c( 106 | "1600 Amphitheatre Parkway, Mountain View, CA", 107 | "3111 World Drive Walt Disney World, Orlando, FL" 108 | ) 109 | to <- "1600 Pennsylvania Avenue, Washington DC" 110 | mapdist(from, to) 111 | 112 | 113 | # mode = "transit 114 | from <- "st lukes hospital houston texas" 115 | to <- "houston zoo, houston texas" 116 | mapdist(from, to, mode = "transit") 117 | 118 | 119 | 120 | 121 | 122 | ## geographic coordinates are accepted as well 123 | ######################################## 124 | (wh <- as.numeric(geocode("the white house, dc"))) 125 | (lm <- as.numeric(geocode("lincoln memorial washington dc"))) 126 | mapdist(wh, lm, mode = "walking") 127 | 128 | } 129 | 130 | } 131 | \seealso{ 132 | \url{https://developers.google.com/maps/documentation/distance-matrix/}, 133 | \url{https://developers.google.com/maps/documentation/distance-matrix/overview/} 134 | } 135 | \author{ 136 | David Kahle \email{david@kahle.io} 137 | } 138 | -------------------------------------------------------------------------------- /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{ requires a Stadia Maps API key. see ?register_stadiamaps 23 | 24 | get_stadiamap(zoom = 9) 25 | 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /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]{ggmap()}} and \code{\link[=get_map]{get_map()}}} 13 | } 14 | \value{ 15 | a ggplot object 16 | } 17 | \description{ 18 | qmap is a wrapper for \code{\link[=ggmap]{ggmap()}} and \code{\link[=get_map]{get_map()}}. 19 | } 20 | \examples{ 21 | 22 | \dontrun{ some requires Google API key; heavy network/time load 23 | 24 | location <- "marrs mclean science, waco, texas" 25 | qmap(location) 26 | qmap(location, zoom = 14) 27 | qmap(location, zoom = 14, source = "osm") 28 | qmap(location, zoom = 14, source = "osm", scale = 20000) 29 | qmap(location, zoom = 14, maptype = "satellite") 30 | qmap(location, zoom = 14, maptype = "hybrid") 31 | qmap(location, zoom = 14, maptype = "stamen_toner", source = "stadia") 32 | qmap(location, zoom = 14, maptype = "stamen_watercolor", source = "stadia") 33 | qmap(location, zoom = 14, maptype = "stamen_terrain_background", source = "stadia") 34 | qmap(location, zoom = 14, maptype = "stamen_toner_lite", source = "stadia") 35 | 36 | where <- "the white house, washington dc" 37 | wh <- geocode(where) 38 | qmap(where, maprange = TRUE, zoom = 15, 39 | base_layer = ggplot(aes(x=lon, y=lat), data = wh)) + 40 | geom_point() 41 | 42 | 43 | 44 | } 45 | 46 | } 47 | \seealso{ 48 | \code{\link[=ggmap]{ggmap()}} and \code{\link[=get_map]{get_map()}} 49 | } 50 | \author{ 51 | David Kahle \email{david@kahle.io} 52 | } 53 | -------------------------------------------------------------------------------- /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( 8 | x, 9 | y, 10 | ..., 11 | data, 12 | zoom, 13 | source = "stadia", 14 | maptype = "stamen_toner_lite", 15 | extent = "device", 16 | legend = "right", 17 | padding = 0.02, 18 | force = FALSE, 19 | darken = c(0, "black"), 20 | mapcolor = "color", 21 | facets = NULL, 22 | margins = FALSE, 23 | geom = "auto", 24 | stat = list(NULL), 25 | position = list(NULL), 26 | xlim = c(NA, NA), 27 | ylim = c(NA, NA), 28 | main = NULL, 29 | f = 0.05, 30 | xlab = "Longitude", 31 | ylab = "Latitude" 32 | ) 33 | } 34 | \arguments{ 35 | \item{x}{longitude values} 36 | 37 | \item{y}{latitude values} 38 | 39 | \item{...}{other aesthetics passed for each layer} 40 | 41 | \item{data}{data frame to use (optional). If not specified, will create one, 42 | extracting vectors from the current environment.} 43 | 44 | \item{zoom}{map zoom, see \code{\link[=get_map]{get_map()}}} 45 | 46 | \item{source}{map source, see \code{\link[=get_map]{get_map()}}} 47 | 48 | \item{maptype}{map type, see \code{\link[=get_map]{get_map()}}} 49 | 50 | \item{extent}{how much of the plot should the map take up? "normal", "panel", 51 | or "device" (default)} 52 | 53 | \item{legend}{"left", "right" (default), "bottom", "top", "bottomleft", 54 | "bottomright", "topleft", "topright", "none" (used with extent = "device")} 55 | 56 | \item{padding}{distance from legend to corner of the plot (used with extent 57 | = "device")} 58 | 59 | \item{force}{force new map (don't use archived version)} 60 | 61 | \item{darken}{vector of the form c(number, color), where number is in (0,1) 62 | and color is a character string indicating the color of the darken. 0 63 | indicates no darkening, 1 indicates a black-out.} 64 | 65 | \item{mapcolor}{color ("color") or black-and-white ("bw")} 66 | 67 | \item{facets}{faceting formula to use. Picks \code{\link[=facet_wrap]{facet_wrap()}} or 68 | \code{\link[=facet_grid]{facet_grid()}} depending on whether the formula is one sided or two-sided} 69 | 70 | \item{margins}{whether or not margins will be displayed} 71 | 72 | \item{geom}{character vector specifying geom to use. defaults to "point"} 73 | 74 | \item{stat}{character vector specifying statistics to use} 75 | 76 | \item{position}{character vector giving position adjustment to use} 77 | 78 | \item{xlim}{limits for x axis} 79 | 80 | \item{ylim}{limits for y axis} 81 | 82 | \item{main}{character vector or expression for plot title} 83 | 84 | \item{f}{number specifying the fraction by which the range should be extended} 85 | 86 | \item{xlab}{character vector or expression for x axis label} 87 | 88 | \item{ylab}{character vector or expression for y axis label} 89 | } 90 | \description{ 91 | \code{\link[=qmplot]{qmplot()}} is the ggmap equivalent to the ggplot2 function qplot and allows 92 | for the quick plotting of maps with data/models/etc. 93 | } 94 | \examples{ 95 | 96 | \dontrun{ # these are skipped to conserve R check time 97 | 98 | qmplot(lon, lat, data = crime) 99 | 100 | 101 | # only violent crimes 102 | violent_crimes <- subset(crime, 103 | offense != "auto theft" & 104 | offense != "theft" & 105 | offense != "burglary" 106 | ) 107 | 108 | # rank violent crimes 109 | violent_crimes$offense <- factor( 110 | violent_crimes$offense, 111 | levels = c("robbery", "aggravated assault", "rape", "murder") 112 | ) 113 | 114 | # restrict to downtown 115 | violent_crimes <- subset(violent_crimes, 116 | -95.39681 <= lon & lon <= -95.34188 & 117 | 29.73631 <= lat & lat <= 29.78400 118 | ) 119 | 120 | theme_set(theme_bw()) 121 | 122 | qmplot(lon, lat, data = violent_crimes, colour = offense, 123 | size = I(3.5), alpha = I(.6), legend = "topleft") 124 | 125 | qmplot(lon, lat, data = violent_crimes, geom = c("point","density2d")) 126 | qmplot(lon, lat, data = violent_crimes) + facet_wrap(~ offense) 127 | qmplot(lon, lat, data = violent_crimes, extent = "panel") + facet_wrap(~ offense) 128 | qmplot(lon, lat, data = violent_crimes, extent = "panel", colour = offense, darken = .4) + 129 | facet_wrap(~ month) 130 | 131 | 132 | 133 | 134 | qmplot(long, lat, xend = long + delta_long, 135 | color = I("red"), yend = lat + delta_lat, data = seals, 136 | geom = "segment", zoom = 5) 137 | 138 | qmplot(long, lat, xend = long + delta_long, maptype = "stamen_watercolor", 139 | yend = lat + delta_lat, data = seals, 140 | geom = "segment", zoom = 6) 141 | 142 | qmplot(long, lat, xend = long + delta_long, maptype = "stamen_terrain", 143 | yend = lat + delta_lat, data = seals, 144 | geom = "segment", zoom = 6) 145 | 146 | 147 | qmplot(lon, lat, data = wind, size = I(.5), alpha = I(.5)) + 148 | ggtitle("NOAA Wind Report Sites") 149 | 150 | # thin down data set... 151 | s <- seq(1, 227, 8) 152 | thinwind <- subset(wind, 153 | lon \%in\% unique(wind$lon)[s] & 154 | lat \%in\% unique(wind$lat)[s] 155 | ) 156 | 157 | # for some reason adding arrows to the following plot bugs 158 | theme_set(theme_bw(18)) 159 | 160 | qmplot(lon, lat, data = thinwind, geom = "tile", fill = spd, alpha = spd, 161 | legend = "bottomleft") + 162 | geom_leg(aes(xend = lon + delta_lon, yend = lat + delta_lat)) + 163 | scale_fill_gradient2("Wind Speed\nand\nDirection", 164 | low = "green", mid = scales::muted("green"), high = "red") + 165 | scale_alpha("Wind Speed\nand\nDirection", range = c(.1, .75)) + 166 | guides(fill = guide_legend(), alpha = guide_legend()) 167 | 168 | 169 | 170 | 171 | ## kriging 172 | ############################################################ 173 | # the below examples show kriging based on undeclared packages 174 | # to better comply with CRAN's standards, we remove it from 175 | # executing, but leave the code as a kind of case-study 176 | # they also require the rgdal library 177 | 178 | 179 | library(lattice) 180 | library(sp) 181 | library(rgdal) 182 | 183 | # load in and format the meuse dataset (see bivand, pebesma, and gomez-rubio) 184 | data(meuse) 185 | coordinates(meuse) <- c("x", "y") 186 | proj4string(meuse) <- CRS("+init=epsg:28992") 187 | meuse <- spTransform(meuse, CRS("+proj=longlat +datum=WGS84")) 188 | 189 | # plot 190 | plot(meuse) 191 | 192 | m <- data.frame(slot(meuse, "coords"), slot(meuse, "data")) 193 | names(m)[1:2] <- c("lon", "lat") 194 | 195 | qmplot(lon, lat, data = m) 196 | qmplot(lon, lat, data = m, zoom = 14) 197 | 198 | 199 | qmplot(lon, lat, data = m, size = zinc, 200 | zoom = 14, source = "google", maptype = "satellite", 201 | alpha = I(.75), color = I("green"), 202 | legend = "topleft", darken = .2 203 | ) + scale_size("Zinc (ppm)") 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | # load in the meuse.grid dataset (looking toward kriging) 213 | library(gstat) 214 | data(meuse.grid) 215 | coordinates(meuse.grid) <- c("x", "y") 216 | proj4string(meuse.grid) <- CRS("+init=epsg:28992") 217 | meuse.grid <- spTransform(meuse.grid, CRS("+proj=longlat +datum=WGS84")) 218 | 219 | # plot it 220 | plot(meuse.grid) 221 | 222 | mg <- data.frame(slot(meuse.grid, "coords"), slot(meuse.grid, "data")) 223 | names(mg)[1:2] <- c("lon", "lat") 224 | 225 | qmplot(lon, lat, data = mg, shape = I(15), zoom = 14, legend = "topleft") + 226 | geom_point(aes(size = zinc), data = m, color = "green") + 227 | scale_size("Zinc (ppm)") 228 | 229 | 230 | 231 | # interpolate at unobserved locations (i.e. at meuse.grid points) 232 | # pre-define scale for consistency 233 | scale <- scale_color_gradient("Predicted\nZinc (ppm)", 234 | low = "green", high = "red", lim = c(100, 1850) 235 | ) 236 | 237 | 238 | 239 | # inverse distance weighting 240 | idw <- idw(log(zinc) ~ 1, meuse, meuse.grid, idp = 2.5) 241 | mg$idw <- exp(slot(idw, "data")$var1.pred) 242 | 243 | qmplot(lon, lat, data = mg, shape = I(15), color = idw, 244 | zoom = 14, legend = "topleft", alpha = I(.75), darken = .4 245 | ) + scale 246 | 247 | 248 | 249 | # linear regression 250 | lin <- krige(log(zinc) ~ 1, meuse, meuse.grid, degree = 1) 251 | mg$lin <- exp(slot(lin, "data")$var1.pred) 252 | 253 | qmplot(lon, lat, data = mg, shape = I(15), color = lin, 254 | zoom = 14, legend = "topleft", alpha = I(.75), darken = .4 255 | ) + scale 256 | 257 | 258 | 259 | # trend surface analysis 260 | tsa <- krige(log(zinc) ~ 1, meuse, meuse.grid, degree = 2) 261 | mg$tsa <- exp(slot(tsa, "data")$var1.pred) 262 | 263 | qmplot(lon, lat, data = mg, shape = I(15), color = tsa, 264 | zoom = 14, legend = "topleft", alpha = I(.75), darken = .4 265 | ) + scale 266 | 267 | 268 | 269 | # ordinary kriging 270 | vgram <- variogram(log(zinc) ~ 1, meuse) # plot(vgram) 271 | vgramFit <- fit.variogram(vgram, vgm(1, "Exp", .2, .1)) 272 | ordKrige <- krige(log(zinc) ~ 1, meuse, meuse.grid, vgramFit) 273 | mg$ordKrige <- exp(slot(ordKrige, "data")$var1.pred) 274 | 275 | qmplot(lon, lat, data = mg, shape = I(15), color = ordKrige, 276 | zoom = 14, legend = "topleft", alpha = I(.75), darken = .4 277 | ) + scale 278 | 279 | 280 | 281 | # universal kriging 282 | vgram <- variogram(log(zinc) ~ 1, meuse) # plot(vgram) 283 | vgramFit <- fit.variogram(vgram, vgm(1, "Exp", .2, .1)) 284 | univKrige <- krige(log(zinc) ~ sqrt(dist), meuse, meuse.grid, vgramFit) 285 | mg$univKrige <- exp(slot(univKrige, "data")$var1.pred) 286 | 287 | qmplot(lon, lat, data = mg, shape = I(15), color = univKrige, 288 | zoom = 14, legend = "topleft", alpha = I(.75), darken = .4 289 | ) + scale 290 | 291 | 292 | 293 | # adding observed data layer 294 | qmplot(lon, lat, data = mg, shape = I(15), color = univKrige, 295 | zoom = 14, legend = "topleft", alpha = I(.75), darken = .4 296 | ) + 297 | geom_point( 298 | aes(x = lon, y = lat, size = zinc), 299 | data = m, shape = 1, color = "black" 300 | ) + 301 | scale + 302 | scale_size("Observed\nLog Zinc") 303 | 304 | 305 | 306 | 307 | 308 | 309 | } # end dontrun 310 | 311 | } 312 | -------------------------------------------------------------------------------- /man/reexports.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/helpers.R 3 | \docType{import} 4 | \name{reexports} 5 | \alias{reexports} 6 | \alias{\%>\%} 7 | \title{Objects exported from other packages} 8 | \keyword{internal} 9 | \description{ 10 | These objects are imported from other packages. Follow the links 11 | below to see their documentation. 12 | 13 | \describe{ 14 | \item{magrittr}{\code{\link[magrittr:pipe]{\%>\%}}} 15 | }} 16 | 17 | -------------------------------------------------------------------------------- /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{showing_key} 6 | \alias{ggmap_show_api_key} 7 | \alias{ggmap_hide_api_key} 8 | \alias{scrub_key} 9 | \alias{print.google_credentials} 10 | \alias{google_key} 11 | \alias{has_google_key} 12 | \alias{has_google_account} 13 | \alias{google_account} 14 | \alias{google_client} 15 | \alias{has_google_client} 16 | \alias{google_signature} 17 | \alias{has_google_signature} 18 | \alias{google_second_limit} 19 | \alias{google_day_limit} 20 | \title{Register a Google API} 21 | \usage{ 22 | showing_key() 23 | 24 | ggmap_show_api_key() 25 | 26 | ggmap_hide_api_key() 27 | 28 | scrub_key(string, with = "xxx") 29 | 30 | register_google( 31 | key, 32 | account_type, 33 | client, 34 | signature, 35 | second_limit, 36 | day_limit, 37 | write = FALSE 38 | ) 39 | 40 | \method{print}{google_credentials}(x, ...) 41 | 42 | google_key() 43 | 44 | has_google_key() 45 | 46 | has_google_account() 47 | 48 | google_account() 49 | 50 | google_client() 51 | 52 | has_google_client() 53 | 54 | google_signature() 55 | 56 | has_google_signature() 57 | 58 | google_second_limit() 59 | 60 | google_day_limit() 61 | } 62 | \arguments{ 63 | \item{string}{a url string to be scrubbed. currently key, signature, and 64 | client keywords are scrubbed from the url and replace with the with 65 | argument} 66 | 67 | \item{with}{a string to replace} 68 | 69 | \item{key}{an api key} 70 | 71 | \item{account_type}{\code{"standard"} or \code{"premium"}} 72 | 73 | \item{client}{client code} 74 | 75 | \item{signature}{signature code} 76 | 77 | \item{second_limit}{query limit per second (default 50)} 78 | 79 | \item{day_limit}{query limit per day (default 2500 for standard accounts, 80 | 100000 for premium accounts)} 81 | 82 | \item{write}{if TRUE, stores the secrets provided in the .Renviron file} 83 | 84 | \item{x}{a google credentials class object} 85 | 86 | \item{...}{a dumped formal argument to the generic print method} 87 | } 88 | \description{ 89 | This page contains documentation for tools related to enabling Google 90 | services in R. See the Details section of this file for background 91 | information. 92 | } 93 | \details{ 94 | As of mid-2018, the Google Maps Platform requires a registered API key. While 95 | this alleviates previous burdens (e.g. query limits), it creates some 96 | challenges as well. The most immediate challenge for most R users is that 97 | ggmap functions that use Google's services no longer function out of the box, 98 | since the user has to setup an account with Google, enable the relevant APIs, 99 | and then tell R about the user's setup. 100 | 101 | To obtain an API key and enable services, go to 102 | \url{https://mapsplatform.google.com/}. This documentation shows you 103 | how to input the requisite information (e.g. your API key) into R, and it 104 | also shows you a few tools that can help you work with the credentialing. 105 | 106 | To tell ggmap about your API key, use \code{\link[=register_google]{register_google()}}, e.g. 107 | \code{register_google(key = "mQkzTpiaLYjPqXQBotesgif3EfGL2dbrNVOrogg")} (that's a 108 | fake key). This will set your API key for the current session, but if you 109 | restart R, you'll need to do it again. You can set it permanently by setting 110 | \code{write = TRUE}, see the examples. If you set it permanently it will be stored 111 | in your .Renviron file, and that will be accessed by ggmap persistently 112 | across sessions. 113 | 114 | Users should be aware that the API key, a string of jarbled 115 | characters/numbers/symbols, is a PRIVATE key - it uniquely identifies and 116 | authenticates you to Google's services. If anyone gets your API key, they can 117 | use it to masquerade as you to Google and potentially use services that you 118 | have enabled. Since Google requires a valid credit card to use its online 119 | cloud services, this also means that anyone who obtains your key can 120 | potentially make charges to your card in the form of Google services. So be 121 | sure to not share your API key. To mitigate against users inadvertently 122 | sharing their keys, by default ggmap never displays a user's key in messages 123 | displayed to the console. 124 | 125 | Users should also be aware that ggmap has no mechanism with which to 126 | safeguard the private key once registered with R. That is to say, once you 127 | register your API key, any function R will have access to it. As a 128 | consequence, ggmap will not know if another function, potentially from a 129 | compromised package, accesses the key and uploads it to a third party. For 130 | this reason, when using ggmap we recommend a heightened sense of security and 131 | self-awareness: only use trusted packages, do not save API keys in script 132 | files, routinely cycle keys (regenerate new keys and retire old ones), etc. 133 | Google offers features to help in securing your API key, including things 134 | like limiting queries using that key to a particular IP address, as well as 135 | guidance on security best practices. See 136 | \url{https://cloud.google.com/docs/authentication/api-keys#securing_an_api_key} 137 | for details. 138 | } 139 | \examples{ 140 | 141 | # this sets your google map for this session 142 | # register_google(key = "[your key]") 143 | 144 | # this sets your google map permanently 145 | # register_google(key = "[your key]", write = TRUE) 146 | 147 | has_google_key() 148 | google_key() 149 | has_google_client() 150 | has_google_signature() 151 | 152 | geocode("waco, texas", urlonly = TRUE) 153 | ggmap_show_api_key() 154 | geocode("waco, texas", urlonly = TRUE) 155 | ggmap_hide_api_key() 156 | geocode("waco, texas", urlonly = TRUE) 157 | 158 | scrub_key("key=d_5iD") 159 | scrub_key("key=d_5iD", "[your \\\\1]") 160 | scrub_key("signature=d_5iD") 161 | scrub_key("client=a_5sS&signature=d_5iD") 162 | 163 | } 164 | \seealso{ 165 | \url{https://mapsplatform.google.com/}, 166 | \url{https://developers.google.com/maps/documentation/maps-static/get-api-key/}, 167 | \url{https://developers.google.com/maps/documentation/maps-static/usage-and-billing/} 168 | } 169 | \author{ 170 | David Kahle \email{david@kahle.io} 171 | } 172 | -------------------------------------------------------------------------------- /man/register_stadiamaps.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/register_stadiamaps.R 3 | \name{register_stadiamaps} 4 | \alias{register_stadiamaps} 5 | \alias{stadiamaps_key} 6 | \alias{has_stadiamaps_key} 7 | \title{Register a Stadia Maps API Key} 8 | \usage{ 9 | register_stadiamaps(key, write = FALSE) 10 | 11 | stadiamaps_key() 12 | 13 | has_stadiamaps_key() 14 | } 15 | \arguments{ 16 | \item{key}{an api key} 17 | 18 | \item{write}{if TRUE, stores the secrets provided in the .Renviron file} 19 | } 20 | \description{ 21 | This page contains documentation for tools related to enabling Stadia Maps 22 | services in R. See the Details section of this file for background 23 | information. 24 | } 25 | \details{ 26 | To obtain an API key and enable services, go to 27 | \url{https://client.stadiamaps.com/signup/}. It is completely free for non-commercial 28 | and evaluation use (a license is for commercial use; see \url{https://stadiamaps.com/pricing} 29 | for pricing), and no credit card is required to sign up. 30 | 31 | To tell ggmap about your API key, use \code{\link[=register_stadiamaps]{register_stadiamaps()}}, e.g. 32 | \code{register_stadiamaps(key = "YOUR-API-KEY")} (that's a 33 | fake key). This will set your API key for the current session, but if you 34 | restart R, you'll need to do it again. You can set it permanently by setting 35 | \code{write = TRUE}, see the examples. If you set it permanently it will be stored 36 | in your .Renviron file, and that will be accessed by ggmap persistently 37 | across sessions. 38 | 39 | Users should be aware that the API key, is a PRIVATE key - it uniquely identifies and 40 | authenticates you to Stadia Maps' services. If anyone gets your API key, they can 41 | use it to masquerade as you to Stadia Maps and potentially use services that you 42 | have enabled. While Stadia Maps requires you to opt in to additional usage-based billing, 43 | this also means that anyone who obtains your key can potentially incur charges on your behalf 44 | or steal the quota that you have already purchased. So be 45 | sure to not share your API key. To mitigate against users inadvertently 46 | sharing their keys, by default ggmap never displays a user's key in messages 47 | displayed to the console. 48 | 49 | Users should also be aware that ggmap has no mechanism with which to 50 | safeguard the private key once registered with R. That is to say, once you 51 | register your API key, any function R will have access to it. As a 52 | consequence, ggmap will not know if another function, potentially from a 53 | compromised package, accesses the key and uploads it to a third party. For 54 | this reason, when using ggmap we recommend a heightened sense of security and 55 | self-awareness: only use trusted packages, do not save API keys in script 56 | files, routinely cycle keys (regenerate new keys and retire old ones), etc. 57 | } 58 | \examples{ 59 | 60 | # this sets your Stadia Maps API key for this session 61 | # register_stadiamaps(key = "YOUR-API-KEY") 62 | 63 | # this sets your Stadia Maps API key permanently 64 | # register_stadiamaps(key = "YOUR-API-KEY", write = TRUE) 65 | 66 | has_stadiamaps_key() 67 | stadiamaps_key() 68 | } 69 | \seealso{ 70 | \url{https://docs.stadiamaps.com/authentication/}, 71 | \url{https://stadiamaps.com/pricing}, 72 | \url{https://client.stadiamaps.com/signup/} 73 | } 74 | -------------------------------------------------------------------------------- /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( 8 | location, 9 | output = c("address", "all"), 10 | force = FALSE, 11 | urlonly = FALSE, 12 | override_limit = FALSE, 13 | ext = "com", 14 | inject = "", 15 | ... 16 | ) 17 | } 18 | \arguments{ 19 | \item{location}{a location in longitude/latitude format} 20 | 21 | \item{output}{"address" or "all"} 22 | 23 | \item{force}{force online query, even if cached (previously downloaded)} 24 | 25 | \item{urlonly}{return only the url?} 26 | 27 | \item{override_limit}{override the current query rate} 28 | 29 | \item{ext}{top level domain extension (e.g. "com", "co.nz")} 30 | 31 | \item{inject}{character string to add to the url} 32 | 33 | \item{...}{...} 34 | } 35 | \value{ 36 | a character(1) address or a list (the parsed json output from Google) 37 | } 38 | \description{ 39 | Reverse geocodes (looks up the address of) a longitude/latitude location 40 | using the Google Geocoding API. Note: To use Google's Geocoding API, you must 41 | first enable the API in the Google Cloud Platform Console. See 42 | \code{\link[=register_google]{register_google()}}. 43 | } 44 | \examples{ 45 | 46 | \dontrun{ requires Google API key, see ?register_google 47 | 48 | ## basic usage 49 | ######################################## 50 | 51 | ( gc <- as.numeric(geocode("the white house")) ) 52 | revgeocode(gc) 53 | str(revgeocode(gc, output = "all"), 3) 54 | 55 | } 56 | 57 | } 58 | \seealso{ 59 | \url{https://developers.google.com/maps/documentation/geocoding/} 60 | } 61 | \author{ 62 | David Kahle \email{david@kahle.io} 63 | } 64 | -------------------------------------------------------------------------------- /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 | \alias{routeQueryCheck} 6 | \title{Grab a route from Google} 7 | \usage{ 8 | route( 9 | from, 10 | to, 11 | mode = c("driving", "walking", "bicycling", "transit"), 12 | structure = c("legs", "route"), 13 | output = c("simple", "all"), 14 | alternatives = FALSE, 15 | units = "metric", 16 | urlonly = FALSE, 17 | override_limit = FALSE, 18 | ext = "com", 19 | inject = "", 20 | ... 21 | ) 22 | 23 | routeQueryCheck() 24 | } 25 | \arguments{ 26 | \item{from}{vector of origin addresses} 27 | 28 | \item{to}{vector of destination addresses} 29 | 30 | \item{mode}{driving, bicycling, walking, or transit} 31 | 32 | \item{structure}{structure of output, "legs" or "route", see examples} 33 | 34 | \item{output}{amount of output ("simple" or "all")} 35 | 36 | \item{alternatives}{should more than one route be provided?} 37 | 38 | \item{units}{"metric"} 39 | 40 | \item{urlonly}{return only the url?} 41 | 42 | \item{override_limit}{override the current query count} 43 | 44 | \item{ext}{domain extension (e.g. "com", "co.nz")} 45 | 46 | \item{inject}{character string to add to the url} 47 | 48 | \item{...}{...} 49 | } 50 | \value{ 51 | a data frame (output="simple") or all of the geocoded information 52 | (output="all") 53 | } 54 | \description{ 55 | Route two locations: determine a sequence of steps (legs) between two 56 | locations using the Google Directions API. Note: To use Google's Directions 57 | API, you must first enable the API in the Google Cloud Platform Console. See 58 | \code{\link[=register_google]{register_google()}}. 59 | } 60 | \examples{ 61 | 62 | \dontrun{ requires Google API key, see ?register_google 63 | 64 | ## basic usage 65 | ######################################## 66 | 67 | from <- "houston, texas" 68 | to <- "waco, texas" 69 | 70 | route(from, to, structure = "legs") 71 | route(from, to, structure = "route") 72 | 73 | route(from, to, alternatives = TRUE) 74 | 75 | 76 | ## comparison to trek 77 | ######################################## 78 | (route_df <- route(from, to, structure = "route")) 79 | (trek_df <- trek(from, to, structure = "route")) 80 | 81 | qmap("college station, texas", zoom = 8) + 82 | geom_path( 83 | aes(x = lon, y = lat), colour = "red", 84 | size = 1.5, alpha = .5, 85 | data = route_df, lineend = "round" 86 | ) + 87 | geom_path( 88 | aes(x = lon, y = lat), colour = "blue", 89 | size = 1.5, alpha = .5, 90 | data = trek_df, lineend = "round" 91 | ) 92 | 93 | qmap("college station, texas", zoom = 6) + 94 | geom_path( 95 | aes(x = lon, y = lat), colour = "red", size = 1.5, 96 | data = route_df, lineend = "round" 97 | ) 98 | 99 | 100 | 101 | 102 | 103 | } 104 | 105 | } 106 | \seealso{ 107 | \url{https://developers.google.com/maps/documentation/directions/}, 108 | \code{\link[=trek]{trek()}}, \code{\link[=legs2route]{legs2route()}}, \code{\link[=geom_leg]{geom_leg()}}, \code{\link[=register_google]{register_google()}} 109 | } 110 | \author{ 111 | David Kahle \email{david@kahle.io} 112 | } 113 | -------------------------------------------------------------------------------- /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.io} 51 | } 52 | -------------------------------------------------------------------------------- /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 <- ggplot(df, aes(x, y)) + geom_raster() 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 <- ggplot(df, aes(x, y)) + geom_raster(aes(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.io} 56 | } 57 | -------------------------------------------------------------------------------- /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( 8 | from, 9 | to, 10 | mode = c("driving", "walking", "bicycling", "transit"), 11 | output = c("simple", "all"), 12 | alternatives = FALSE, 13 | units = "metric", 14 | urlonly = FALSE, 15 | override_limit = FALSE, 16 | ext = "com", 17 | inject = "", 18 | ... 19 | ) 20 | } 21 | \arguments{ 22 | \item{from}{name of origin addresses in a data frame} 23 | 24 | \item{to}{name of destination addresses in a data frame} 25 | 26 | \item{mode}{driving, bicycling, walking, or transit} 27 | 28 | \item{output}{amount of output ("simple" or "all")} 29 | 30 | \item{alternatives}{should more than one route be provided?} 31 | 32 | \item{units}{"metric"} 33 | 34 | \item{urlonly}{return only the url?} 35 | 36 | \item{override_limit}{override the current query count} 37 | 38 | \item{ext}{domain extension (e.g. "com", "co.nz")} 39 | 40 | \item{inject}{character string to add to the url} 41 | 42 | \item{...}{...} 43 | } 44 | \value{ 45 | a tibble 46 | } 47 | \description{ 48 | Sequence treks (latitude-longitude sequences following ordinary paths, e.g. 49 | roads) between two locations using the Google Directions API. Note: To use 50 | Google's Directions API, you must first enable the API in the Google Cloud 51 | Platform Console. See \code{\link[=register_google]{register_google()}}. 52 | } 53 | \examples{ 54 | 55 | \dontrun{ requires Google API key, see ?register_google 56 | 57 | ## basic usage 58 | ######################################## 59 | 60 | from <- "houston, texas" 61 | to <- "waco, texas" 62 | 63 | (route_df <- route(from, to, structure = "route")) 64 | (trek_df <- trek(from, to, structure = "route")) 65 | 66 | qmap("college station, texas", zoom = 8) + 67 | geom_path( 68 | aes(x = lon, y = lat), colour = "red", 69 | size = 1.5, alpha = .5, 70 | data = route_df, lineend = "round" 71 | ) + 72 | geom_path( 73 | aes(x = lon, y = lat), colour = "blue", 74 | size = 1.5, alpha = .5, 75 | data = trek_df, lineend = "round" 76 | ) 77 | 78 | 79 | 80 | from <- "rice university houston texas" 81 | to <- "1001 Bissonnet St, Houston, TX 77005" 82 | trek_df <- trek(from, to) 83 | qmplot(lon, lat, data = trek_df, geom = "path", maptype = "terrain", 84 | color = I("red"), size = I(2), alpha = I(.5) 85 | ) 86 | 87 | trek_df <- trek(from, to, mode = "walking") 88 | qmplot(lon, lat, data = trek_df, geom = "path", maptype = "terrain", 89 | color = I("red"), size = I(2), alpha = I(.5) 90 | ) 91 | 92 | trek_df <- trek(from, to, mode = "transit") 93 | qmplot(lon, lat, data = trek_df, geom = "path", maptype = "terrain", 94 | color = I("red"), size = I(2), alpha = I(.5) 95 | ) 96 | 97 | 98 | 99 | ## neat faceting example 100 | ######################################## 101 | 102 | from <- "houston, texas"; to <- "waco, texas" 103 | trek_df <- trek(from, to, alternatives = TRUE) 104 | 105 | qmplot(lon, lat, data = trek_df, geom = "path", 106 | color = route, size = I(2), maptype = "terrain", 107 | alpha = I(.5) 108 | ) 109 | 110 | qmplot(lon, lat, data = trek_df, geom = "path", 111 | color = route, size = I(2), maptype = "terrain", 112 | zoom = 8 113 | ) + facet_grid(. ~ route) 114 | 115 | 116 | 117 | 118 | } 119 | 120 | } 121 | \seealso{ 122 | \url{https://developers.google.com/maps/documentation/directions/}, 123 | \url{https://stackoverflow.com/questions/30270011/ggmap-route-finding-doesnt-stay-on-roads/}, 124 | \code{\link[=route]{route()}}, \code{\link[=routeQueryCheck]{routeQueryCheck()}}, \code{\link[=register_google]{register_google()}} 125 | } 126 | \author{ 127 | David Kahle \email{david@kahle.io} with the key decoding algorithm 128 | due to Stack Overflow user akhmed 129 | } 130 | -------------------------------------------------------------------------------- /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 Morisseau-Leroy, 12 | 1998: The HRD real-time hurricane wind analysis system. J. Wind Engineer. 13 | and Indust. Aerodyn. 77&78, 53-64 14 | } 15 | \references{ 16 | \url{https://www.aoml.noaa.gov/hrd/Storm_pages/ike2008/wind.html} 17 | } 18 | \author{ 19 | Atlantic Oceanographic and Meteorological Laboratory (AOML), a 20 | division of the National Oceanic and Atmospheric Administration (NOAA) 21 | } 22 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /revdep/.gitignore: -------------------------------------------------------------------------------- 1 | checks 2 | library 3 | checks.noindex 4 | library.noindex 5 | data.sqlite 6 | *.html 7 | **/ 8 | cloud.noindex 9 | -------------------------------------------------------------------------------- /revdep/README.md: -------------------------------------------------------------------------------- 1 | # Platform 2 | 3 | |field |value | 4 | |:--------|:-----------------------------------------| 5 | |version |R version 4.3.2 (2023-10-31) | 6 | |os |macOS Ventura 13.6 | 7 | |system |aarch64, darwin20 | 8 | |ui |RStudio | 9 | |language |(EN) | 10 | |collate |en_US.UTF-8 | 11 | |ctype |en_US.UTF-8 | 12 | |tz |America/Chicago | 13 | |date |2023-11-03 | 14 | |rstudio |2023.12.0-daily+234 Ocean Storm (desktop) | 15 | |pandoc |NA | 16 | 17 | # Dependencies 18 | 19 | |package |old |new |Δ | 20 | |:-------|:-----|:----------|:--| 21 | |ggmap |3.0.2 |3.0.2.9002 |* | 22 | 23 | # Revdeps 24 | 25 | -------------------------------------------------------------------------------- /revdep/check.R: -------------------------------------------------------------------------------- 1 | library("devtools") 2 | 3 | revdep_check() 4 | revdep_check_save_summary() 5 | revdep_check_print_problems() 6 | -------------------------------------------------------------------------------- /revdep/checks.rds: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkahle/ggmap/29ed82523e46332aa77364717bd042f8ee314337/revdep/checks.rds -------------------------------------------------------------------------------- /revdep/cran.md: -------------------------------------------------------------------------------- 1 | ## revdepcheck results 2 | 3 | We checked 48 reverse dependencies, comparing R CMD check results across CRAN and dev versions of this package. 4 | 5 | * We saw 0 new problems 6 | * We failed to check 0 packages 7 | 8 | -------------------------------------------------------------------------------- /revdep/email.yml: -------------------------------------------------------------------------------- 1 | release_date: ??? 2 | rel_release_date: ??? 3 | my_news_url: ??? 4 | release_version: ??? 5 | release_details: ??? 6 | -------------------------------------------------------------------------------- /revdep/failures.md: -------------------------------------------------------------------------------- 1 | *Wow, no problems at all. :)* -------------------------------------------------------------------------------- /revdep/problems.md: -------------------------------------------------------------------------------- 1 | *Wow, no problems at all. :)* -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(ggmap) 3 | 4 | test_check("ggmap") 5 | -------------------------------------------------------------------------------- /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 | }) -------------------------------------------------------------------------------- /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 | }) -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /tests/testthat/test-encoding.R: -------------------------------------------------------------------------------- 1 | context("URLs are properly encoded") 2 | 3 | test_that("# encodes correctly", { 4 | 5 | Sys.setenv("GGMAP_GOOGLE_API_KEY" = "mQkzTpiaLYjP_XQBotesgif3EfGL2dbrNVOrogg") # fake key 6 | 7 | expect_equal( 8 | get_googlemap("#10 downing street, london", urlonly = TRUE), 9 | "https://maps.googleapis.com/maps/api/staticmap?center=%2310%20downing%20street,%20london&zoom=10&size=640x640&scale=2&maptype=terrain&key=xxx" 10 | ) 11 | 12 | expect_equal( 13 | geocode("10 downing street, london", urlonly = TRUE), 14 | "https://maps.googleapis.com/maps/api/geocode/json?address=10+downing+street,+london&key=xxx" 15 | ) 16 | 17 | expect_equal( 18 | route("#10 downing street, london", "buckingham palace", urlonly = TRUE), 19 | "https://maps.googleapis.com/maps/api/directions/json?origin=%2310+downing+street,+london&destination=buckingham+palace&key=xxx&mode=driving&alternatives=false&units=metric" 20 | ) 21 | 22 | expect_equal( 23 | trek("#10 downing street, london", "buckingham palace", urlonly = TRUE), 24 | "https://maps.googleapis.com/maps/api/directions/json?origin=%2310+downing+street,+london&destination=buckingham+palace&key=xxx&mode=driving&alternatives=false&units=metric" 25 | ) 26 | 27 | expect_equal( 28 | mapdist("#10 downing street, london", "buckingham palace", urlonly = TRUE), 29 | "https://maps.googleapis.com/maps/api/distancematrix/json?origins=%2310+downing+street,+london&destinations=buckingham+palace&key=xxx&mode=driving" 30 | ) 31 | 32 | 33 | }) 34 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | } -------------------------------------------------------------------------------- /tools/README-faceting-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkahle/ggmap/29ed82523e46332aa77364717bd042f8ee314337/tools/README-faceting-1.png -------------------------------------------------------------------------------- /tools/README-ggmap-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkahle/ggmap/29ed82523e46332aa77364717bd042f8ee314337/tools/README-ggmap-1.png -------------------------------------------------------------------------------- /tools/README-ggmap-layers-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkahle/ggmap/29ed82523e46332aa77364717bd042f8ee314337/tools/README-ggmap-layers-1.png -------------------------------------------------------------------------------- /tools/README-ggmap-patchwork-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkahle/ggmap/29ed82523e46332aa77364717bd042f8ee314337/tools/README-ggmap-patchwork-1.png -------------------------------------------------------------------------------- /tools/README-google_maps-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkahle/ggmap/29ed82523e46332aa77364717bd042f8ee314337/tools/README-google_maps-1.png -------------------------------------------------------------------------------- /tools/README-maptypes-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkahle/ggmap/29ed82523e46332aa77364717bd042f8ee314337/tools/README-maptypes-1.png -------------------------------------------------------------------------------- /tools/README-qmplot-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkahle/ggmap/29ed82523e46332aa77364717bd042f8ee314337/tools/README-qmplot-1.png -------------------------------------------------------------------------------- /tools/README-route_trek-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dkahle/ggmap/29ed82523e46332aa77364717bd042f8ee314337/tools/README-route_trek-1.png --------------------------------------------------------------------------------