├── .Rbuildignore ├── .gitignore ├── .travis.yml ├── CRAN-SUBMISSION ├── DESCRIPTION ├── LICENSE ├── NAMESPACE ├── NEWS.md ├── R ├── as-sf.R ├── as-sp.R ├── collapse-properties.R ├── costing-models.R ├── data.R ├── geocode.R ├── isochrone.R ├── matrix-helpers.R ├── matrix-main.R ├── mz-autocomplete.R ├── mz-bbox.R ├── mz-coordinates.R ├── mz-key.R ├── mz-place.R ├── mz-references.R ├── mz-reverse.R ├── mz-search-main.R ├── mz-search.R ├── mz-tile-coordinates.R ├── print-mapzen-geo-list.R ├── print-vector-tiles.R ├── providers.R ├── rmapzen-package.R ├── string-array.R ├── structured-search.R ├── tidy.R ├── unwrap.R ├── usage-statistics.R ├── vector-tiles.R └── zzz.R ├── README.Rmd ├── README.md ├── codecov.yml ├── cran-comments.md ├── data ├── ca_tiles.rda ├── marina_walks.rda ├── marina_walks_polygons.rda └── oakland_public.rda ├── fig └── mz-countries.png ├── index.Rmd ├── index.html ├── index_files ├── bootstrap-3.3.5 │ ├── css │ │ ├── bootstrap-theme.css │ │ ├── bootstrap-theme.css.map │ │ ├── bootstrap-theme.min.css │ │ ├── bootstrap.css │ │ ├── bootstrap.css.map │ │ ├── bootstrap.min.css │ │ ├── cerulean.min.css │ │ ├── cosmo.min.css │ │ ├── darkly.min.css │ │ ├── flatly.min.css │ │ ├── fonts │ │ │ ├── Lato.ttf │ │ │ ├── LatoBold.ttf │ │ │ ├── LatoItalic.ttf │ │ │ ├── NewsCycle.ttf │ │ │ ├── NewsCycleBold.ttf │ │ │ ├── OpenSans.ttf │ │ │ ├── OpenSansBold.ttf │ │ │ ├── OpenSansBoldItalic.ttf │ │ │ ├── OpenSansItalic.ttf │ │ │ ├── OpenSansLight.ttf │ │ │ ├── OpenSansLightItalic.ttf │ │ │ ├── Raleway.ttf │ │ │ ├── RalewayBold.ttf │ │ │ ├── Roboto.ttf │ │ │ ├── RobotoBold.ttf │ │ │ ├── RobotoLight.ttf │ │ │ ├── RobotoMedium.ttf │ │ │ ├── SourceSansPro.ttf │ │ │ ├── SourceSansProBold.ttf │ │ │ ├── SourceSansProItalic.ttf │ │ │ ├── SourceSansProLight.ttf │ │ │ └── Ubuntu.ttf │ │ ├── journal.min.css │ │ ├── lumen.min.css │ │ ├── paper.min.css │ │ ├── readable.min.css │ │ ├── sandstone.min.css │ │ ├── simplex.min.css │ │ ├── spacelab.min.css │ │ ├── united.min.css │ │ └── yeti.min.css │ ├── fonts │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ └── glyphicons-halflings-regular.woff2 │ ├── js │ │ ├── bootstrap.js │ │ ├── bootstrap.min.js │ │ └── npm.js │ └── shim │ │ ├── html5shiv.min.js │ │ └── respond.min.js ├── figure-html │ └── vector-tile-example-1.png ├── header-attrs-2.8 │ └── header-attrs.js ├── highlightjs-9.12.0 │ ├── default.css │ ├── highlight.js │ └── textmate.css ├── jquery-1.11.3 │ └── jquery.min.js ├── jqueryui-1.11.4 │ ├── README │ ├── images │ │ ├── ui-icons_444444_256x240.png │ │ ├── ui-icons_555555_256x240.png │ │ ├── ui-icons_777620_256x240.png │ │ ├── ui-icons_777777_256x240.png │ │ ├── ui-icons_cc0000_256x240.png │ │ └── ui-icons_ffffff_256x240.png │ ├── index.html │ ├── jquery-ui.css │ ├── jquery-ui.js │ ├── jquery-ui.min.css │ ├── jquery-ui.min.js │ ├── jquery-ui.structure.css │ ├── jquery-ui.structure.min.css │ ├── jquery-ui.theme.css │ └── jquery-ui.theme.min.css ├── navigation-1.1 │ ├── codefolding.js │ ├── sourceembed.js │ └── tabsets.js └── tocify-1.9.1 │ ├── jquery.tocify.css │ └── jquery.tocify.js ├── man ├── as_sf.Rd ├── ca_tiles.Rd ├── costing_models.Rd ├── mapzen_references.Rd ├── marina_walks.Rd ├── marina_walks_polygons.Rd ├── mz_bbox.Rd ├── mz_check_usage.Rd ├── mz_contours.Rd ├── mz_coordinates.Rd ├── mz_date_time.Rd ├── mz_geocode.Rd ├── mz_geocode_structured.Rd ├── mz_isochrone.Rd ├── mz_location.Rd ├── mz_place.Rd ├── mz_provider.Rd ├── mz_set_host.Rd ├── mz_structured_search.Rd ├── mz_tile_coordinates.Rd ├── mz_vector_tiles.Rd ├── oakland_public.Rd ├── rmapzen-package.Rd └── search.Rd ├── revdep ├── .gitignore ├── README.md ├── cran.md ├── failures.md └── problems.md ├── rmapzen.Rproj ├── tests ├── testthat.R └── testthat │ ├── helpers.R │ ├── test-as-data-frame.R │ ├── test-as-sf.R │ ├── test-mz-autocomplete.R │ ├── test-mz-bbox.R │ ├── test-mz-isochrone.R │ ├── test-mz-place.R │ ├── test-mz-reverse.R │ ├── test-mz-search.R │ ├── test-mz-structured-search.R │ ├── test-mz-vector-tiles.R │ ├── test-tile-coordinates.R │ └── test-usage-statistics.R └── vignettes └── rmapzen-introduction.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^CRAN-RELEASE$ 2 | ^.*\.Rproj$ 3 | ^\.Rproj\.user$ 4 | ^README\.Rmd$ 5 | ^README-.*\.png$ 6 | fig/.* 7 | ^\.travis\.yml$ 8 | ^codecov\.yml$ 9 | .*_cache/.* 10 | index\.Rmd 11 | index\.html 12 | index_files/.* 13 | ^cran-comments\.md$ 14 | ^doc$ 15 | ^Meta$ 16 | ^CRAN-SUBMISSION$ 17 | ^revdep$ 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | README_cache/* 6 | index_cache/* 7 | inst/doc 8 | /doc/ 9 | /Meta/ 10 | revdep/checks 11 | revdep/library.noindex 12 | revdep/checks.noindex 13 | revdep/data.sqlite 14 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | # R for travis: see documentation at https://docs.travis-ci.com/user/languages/r 2 | 3 | language: r 4 | cache: packages 5 | 6 | sudo: required 7 | dist: trusty 8 | 9 | before_install: 10 | - sudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable --yes 11 | - sudo apt-get --yes --force-yes update -qq 12 | - sudo apt-get install --yes libudunits2-dev libproj-dev libgeos-dev libgdal-dev 13 | - sudo add-apt-repository -y ppa:opencpu/jq 14 | - sudo apt-get --yes --force-yes update -qq 15 | - sudo apt-get install libjq-dev 16 | - sudo apt-get install --yes libprotobuf-dev protobuf-compiler libv8-3.14-dev 17 | 18 | addons: 19 | apt: 20 | packages: 21 | - libv8-dev 22 | 23 | r_packages: 24 | - devtools 25 | 26 | matrix: 27 | include: 28 | - r: release 29 | after_success: 30 | - Rscript -e 'covr::codecov()' 31 | - r: release 32 | name: tidyr-devel 33 | before_script: Rscript -e "remotes::install_github('tidyverse/tidyr')" 34 | -------------------------------------------------------------------------------- /CRAN-SUBMISSION: -------------------------------------------------------------------------------- 1 | Version: 0.5.1 2 | Date: 2023-10-17 16:17:19 UTC 3 | SHA: dedbd25ca03a99375b026d57aafa7945356e8b49 4 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: rmapzen 2 | Type: Package 3 | Title: Client for 'Mapzen' and Related Map APIs 4 | Version: 0.5.1 5 | Authors@R: c( 6 | person("Tarak", "Shah", email = "tarak.shah@gmail.com", role = c("aut", "cre")), 7 | person("Daniel","Possenriede", role = "ctb")) 8 | Maintainer: Tarak Shah 9 | Description: Provides an interface to 'Mapzen'-based APIs (including 10 | geocode.earth, Nextzen, and NYC GeoSearch) for geographic search 11 | and geocoding, isochrone calculation, and vector data to draw map tiles. 12 | See for more information. The original 13 | Mapzen has gone out of business, but 'rmapzen' can be set up to work with 14 | any provider who implements the Mapzen API. 15 | License: MIT + file LICENSE 16 | LazyData: TRUE 17 | Depends: R (>= 2.10) 18 | Imports: 19 | tibble, 20 | httr, 21 | jsonlite, 22 | ISOcodes, 23 | dplyr, 24 | assertthat, 25 | geojsonio, 26 | tidyr, 27 | purrr, 28 | digest, 29 | sf (>= 1.0.0), 30 | utils 31 | RoxygenNote: 7.2.3 32 | Suggests: testthat, 33 | covr, 34 | knitr, 35 | rmarkdown, 36 | rlang 37 | URL: https://tarakc02.github.io/rmapzen/ 38 | BugReports: https://github.com/tarakc02/rmapzen/issues 39 | VignetteBuilder: knitr 40 | Encoding: UTF-8 41 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | YEAR: 2016 2 | COPYRIGHT HOLDER: Tarak Shah 3 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(as.data.frame,mapzen_geo_list) 4 | S3method(as.data.frame,mapzen_isochrone_list) 5 | S3method(as.mz_location,default) 6 | S3method(as.mz_location,mz_geocode_result) 7 | S3method(as.mz_tile_coordinates,mz_bbox) 8 | S3method(as.mz_tile_coordinates,mz_geocode_result) 9 | S3method(as.mz_tile_coordinates,mz_location) 10 | S3method(as.mz_tile_coordinates,mz_tile_coordinates) 11 | S3method(as_sf,geo_list) 12 | S3method(as_sf,mapzen_vector_layer) 13 | S3method(mz_bbox,default) 14 | S3method(mz_bbox,mapzen_geo_list) 15 | S3method(mz_bbox,mapzen_isochrone_list) 16 | S3method(mz_bbox,mapzen_vector_layer) 17 | S3method(mz_bbox,mapzen_vector_tiles) 18 | S3method(mz_coordinates,mapzen_geo_list) 19 | S3method(mz_place,character) 20 | S3method(mz_place,mapzen_geo_list) 21 | S3method(print,mapzen_geo_list) 22 | S3method(print,mapzen_isochrone_list) 23 | S3method(print,mapzen_vector_layer) 24 | S3method(print,mapzen_vector_tiles) 25 | S3method(print,mz_usage_statistics) 26 | export(as.mz_location) 27 | export(as.mz_tile_coordinates) 28 | export(as_sf) 29 | export(mz_autocomplete) 30 | export(mz_bbox) 31 | export(mz_check_usage) 32 | export(mz_contours) 33 | export(mz_coordinates) 34 | export(mz_costing) 35 | export(mz_costing_options) 36 | export(mz_countries) 37 | export(mz_geocode) 38 | export(mz_geocode_structured) 39 | export(mz_isochrone) 40 | export(mz_layers) 41 | export(mz_location) 42 | export(mz_place) 43 | export(mz_provider) 44 | export(mz_rect) 45 | export(mz_reverse_geocode) 46 | export(mz_search) 47 | export(mz_set_host) 48 | export(mz_set_search_host_geocode.earth) 49 | export(mz_set_search_host_nyc_geosearch) 50 | export(mz_set_tile_host_nextzen) 51 | export(mz_sources) 52 | export(mz_structured_search) 53 | export(mz_tile_coordinates) 54 | export(mz_vector_tiles) 55 | import(assertthat) 56 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # rmapzen 0.5.1 2 | * updated providers for v2 of nyc geosearch, thanks to @mtreg 3 | * fixed documentation bug, see issue #24 4 | 5 | # rmapzen 0.5.0 6 | * removed `as_sp`, see issues #22 and #23. Use `as_sf` instead. 7 | 8 | # rmapzen 0.4.4 9 | * deprecated `as_sp`, see issue #22 10 | 11 | # rmapzen 0.4.3 12 | * fixed for sf switching to s2 backend, see issue #21 13 | 14 | # rmapzen 0.4.2 15 | * added optional `Origin` argument to `mz_vector_tiles`, see issue #17 16 | * minor modifications to code to avoid using deprecated tidyverse functions 17 | 18 | # rmapzen 0.4.1 19 | * updated maintainer email address 20 | 21 | # rmapzen 0.4.0 22 | * added `mz_geocode_structured` for geocoding structured address data 23 | * added additional ways to specify tile coordinates for vector tiles. Vector tile coordinates can now be specified using: 24 | - the x, y, z tile coordinate system, 25 | - a lat/lon bounding box with a zoom level, 26 | - a bounding box with height/width in pixels, and 27 | - a point location plus a zoom level 28 | * added additional methods for `mz_bbox` 29 | 30 | # rmapzen 0.3.5 31 | * Updated `as_sf` and `as_sp` methods for vector tile data, previous versions used functions that are no longer exported from the `sf` package (as of version 0.6-2) 32 | 33 | # rmapzen 0.3.4 34 | * Made service host configurable, since Mapzen is no more :(. See `?mz_set_host` for how to set up a specific API provider. Thanks to @dpprdan for the initial update. 35 | 36 | # rmapzen 0.3.3 37 | * Added additional documentation and updated DESCRIPTION 38 | 39 | # rmapzen 0.3.2 40 | * Added ability to convert to `sf` 41 | * All objects returned from the Mapzen API now include the header from the response as an attribute called "header" 42 | * conversion functions now error on empty inputs (e.g. a search with 0 results) 43 | * request functions are no longer rate-limited, because Mapzen's service has been updated and only has monthly (not per-second or per-minute) limits 44 | 45 | # rmapzen 0.3.1 46 | * Added support for [structured geocoding](https://github.com/pelias/documentation) 47 | * Simple print methods for vector tiles and individual vector tile layers 48 | 49 | # rmapzen 0.3.0.9007 50 | * new function `mz_rect` for directly creating a bounding box 51 | * `mz_vector_tiles` gained a `...` argument to pass height/width/zoom specifications to `as.mz_tile_coordinates`. 52 | 53 | # rmapzen 0.3.0.9006 54 | 55 | * Included tracking of vector tile service to `mz_check_usage()` 56 | * Added `mz_bbox()` method for vector tiles 57 | * Bugfix on converting vector tiles to Spatial* - re-calculate IDs (to avoid issue where features with the same ID on separate tiles got messed up when stitching tiles) and merge polygons (so polygons spanning multiple tiles don't appear as multiple polygons when tiles are stitched). 58 | * Added example data from each of the three services: `oakland_public` (`mz_search`), `marina_walks` (`mz_isochrone`), `ca_tiles` (`mz_vector_tiles`) 59 | 60 | # rmapzen 0.3.0.9005 61 | 62 | * Added a `NEWS.md` file to track changes to the package. 63 | * Added support for vector tile service, see `?mz_vector_tiles` 64 | 65 | 66 | -------------------------------------------------------------------------------- /R/as-sf.R: -------------------------------------------------------------------------------- 1 | #' Coerce a Mapzen response to a simple features object 2 | #' 3 | #' Coerces responses to class sf. See \code{vignette("sf1", package = "sf")} for 4 | #' more information about Simple Features for R. 5 | #' 6 | #' @param geo The object to be converted 7 | #' @param ... not currently used 8 | #' 9 | #' @name as_sf 10 | #' @export 11 | as_sf <- function(geo, ...) UseMethod("as_sf") 12 | 13 | #' @rdname as_sf 14 | #' @export 15 | as_sf.geo_list <- function(geo, ...) { 16 | if (length(geo$features) == 0L) 17 | stop("Cannot convert to sf: no data") 18 | sfread_(as_json(geo), stringsAsFactors = FALSE) 19 | } 20 | 21 | #' @rdname as_sf 22 | #' @export 23 | as_sf.mapzen_vector_layer <- function(geo, ...) { 24 | if (length(geo$features) == 0L) 25 | stop("Cannot convert to sf: empty layer") 26 | 27 | geo <- recalculate_ids(geo) 28 | geo <- collapse_properties(geo) 29 | res <- sfread_(as_json(geo), stringsAsFactors = FALSE) 30 | 31 | # polygons that were separated by tile divisions will have the same ids 32 | # b/c of recalculate_ids. need to union them into a single polygon and 33 | # then bring back feature data 34 | res <- dplyr::group_by_at( 35 | res, 36 | setdiff(names(res), "geometry")) 37 | res <- sf::st_as_sf(res) 38 | res <- sf::st_make_valid(res) 39 | res <- dplyr::summarise(res) 40 | dplyr::ungroup(res) 41 | } 42 | 43 | # note: this is more reliable than counting on sf to recognize that the input 44 | # string is not a filename 45 | sfread_ <- function(charstring, ...) { 46 | tmp <- tempfile(pattern = "geojson", fileext = ".json") 47 | td <- dirname(tmp) 48 | if (!dir.exists(td)) dir.create(td) 49 | writeLines(charstring, tmp) 50 | sf::read_sf(tmp, ...) 51 | } 52 | -------------------------------------------------------------------------------- /R/as-sp.R: -------------------------------------------------------------------------------- 1 | recalculate_ids <- function(features) { 2 | features$features <- lapply(features$features, function(feature) { 3 | feature$properties$id <- NULL 4 | feature$properties$id <- digest::digest(feature$properties) 5 | return(feature) 6 | }) 7 | features 8 | } 9 | 10 | as_json <- function(geo) { 11 | geojsonio::as.json(geo) 12 | } 13 | -------------------------------------------------------------------------------- /R/collapse-properties.R: -------------------------------------------------------------------------------- 1 | collapse_properties <- function(geo) { 2 | 3 | collapser <- function(feature) { 4 | feature$properties <- lapply( 5 | feature$properties, 6 | function(x) paste0(x, collapse = ";") 7 | ) 8 | feature 9 | } 10 | 11 | geo$features <- lapply(geo$features, collapser) 12 | geo 13 | } 14 | -------------------------------------------------------------------------------- /R/costing-models.R: -------------------------------------------------------------------------------- 1 | costing_model <- function(type, ...) { 2 | costing <- jsonlite::unbox(type) 3 | costing_options <- list(...) 4 | costing_options <- Filter(function(df) nrow(df) > 0L, costing_options) 5 | 6 | if (length(costing_options) == 0L) 7 | return(list(costing = costing)) 8 | 9 | costing_options <- lapply( 10 | costing_options, 11 | jsonlite::unbox 12 | ) 13 | 14 | structure( 15 | list( 16 | costing = costing, 17 | costing_options = costing_options), 18 | class = "mz_costing_model" 19 | ) 20 | } 21 | 22 | #' Costing model constructors and helpers 23 | #' 24 | #' Mapzen's Isochrone service (\code{\link{mz_isochrone}}) as well as other 25 | #' mobility services (currently not implemented in this package, read more at 26 | #' \url{https://valhalla.readthedocs.io/en/latest/}) require users to specify a 27 | #' "costing model." See \url{https://valhalla.readthedocs.io/en/latest/} 28 | #' for details. These can be difficult to construct correctly, so the objects 29 | #' \code{mz_costing} and \code{mz_costing_options} exist to make that process 30 | #' less error-prone and more convenient. 31 | #' 32 | #' @examples 33 | #' ## creates a pedestrian costing model with walking speed of 2 km/hr 34 | #' ## that also avoids alleys. 35 | #' ## non-multimodal costing models will accept 0 or more options from the 36 | #' ## appropriate list. 37 | #' mz_costing$pedestrian( 38 | #' mz_costing_options$pedestrian$walking_speed(2.0), 39 | #' mz_costing_options$pedestrian$alley_factor(0) 40 | #' ) 41 | #' 42 | #' ## creates a multimodal costing model that favors buses over rails, and 43 | #' ## has a slower than default walking speed 44 | #' ## (note multimodal has named arguments requiring list inputs) 45 | #' mz_costing$multimodal( 46 | #' transit = list( 47 | #' mz_costing_options$transit$use_bus(1.0), 48 | #' mz_costing_options$transit$use_rail(5) 49 | #' ), 50 | #' pedestrian = list( 51 | #' mz_costing_options$pedestrian$walking_speed(4.1) 52 | #' ) 53 | #' ) 54 | #' @seealso \code{\link{mz_isochrone}} 55 | #' @name costing_models 56 | #' @export 57 | mz_costing <- list( 58 | pedestrian = function(...) { 59 | costing_model("pedestrian", pedestrian = data.frame(...))}, 60 | auto = function(...) { 61 | costing_model("auto", auto = data.frame(...))}, 62 | bicycle = function(...) { 63 | costing_model("bicycle", bicycle = data.frame(...))}, 64 | multimodal = function(transit = NULL, pedestrian = NULL) { 65 | transit <- data.frame(transit) 66 | pedestrian <- data.frame(pedestrian) 67 | costing_model("multimodal", transit = transit, pedestrian = pedestrian) 68 | } 69 | 70 | ) 71 | 72 | costopt <- function(x, validate = assertthat::is.number) { 73 | assertthat::assert_that(validate(x)) 74 | jsonlite::unbox(x) 75 | } 76 | 77 | #' @rdname costing_models 78 | #' @export 79 | mz_costing_options <- list( 80 | pedestrian = list( 81 | walking_speed = function(speed) list(walking_speed = costopt(speed)), 82 | walkway_factor = function(factor) list(walkway_factor = costopt(factor)), 83 | alley_factor = function(factor) list(alley_factor = costopt(factor)), 84 | driveway_factor = function(factor) list(driveway_factor = costopt(factor)), 85 | step_penalty = function(seconds) list(step_penalty = costopt(seconds)) 86 | ), 87 | 88 | auto = list( 89 | maneuver_penalty = function(penalty) list(maneuver_penalty = costopt(penalty)), 90 | gate_cost = function(cost) list(gate_cost = costopt(cost)), 91 | toll_booth_cost = function(cost) list(toll_booth_cost = costopt(cost)), 92 | toll_booth_penalty = function(penalty) list(toll_booth_penalty = costopt(penalty)), 93 | ferry_cost = function(cost) list(ferry_cost = costopt(cost)), 94 | use_ferry = function(value) list(use_ferry = costopt(value)), 95 | country_crossing_cost = function(cost) list(country_crossing_cost = costopt(cost)), 96 | country_crossing_penalty = function(penalty) list(country_crossing_penalty = costopt(penalty)) 97 | ), 98 | 99 | bicycle = list( 100 | maneuver_penalty = function(penalty) list(maneuver_penalty = costopt(penalty)), 101 | gate_cost = function(cost) list(gate_cost = costopt(cost)), 102 | country_crossing_cost = function(cost) list(country_crossing_cost = costopt(cost)), 103 | country_crossing_penalty = function(penalty) list(country_crossing_penalty = costopt(penalty)), 104 | bicycle_type = function(type) list(bicycle_type = costopt(bicycle_type, assertthat::is.string)), 105 | cycling_speed = function(speed) list(cycling_speed = costopt(speed)), 106 | use_roads = function(propensity) list(use_roads = costopt(propensity)), 107 | use_hills = function(propensity) list(use_hills = costopt(propensity)) 108 | ), 109 | 110 | transit = list( 111 | use_bus = function(value) list(use_bus = costopt(value)), 112 | use_rail = function(value) list(use_rail = costopt(value)), 113 | use_transfers = function(value) list(use_transfers = costopt(value)), 114 | transit_start_end_max_distance = function(distance) list(transit_start_end_max_distance = costopt(distance)), 115 | transit_transfer_max_distance = function(distance) list(transit_transfer_max_distance = costopt(distance)) 116 | ) 117 | ) 118 | -------------------------------------------------------------------------------- /R/data.R: -------------------------------------------------------------------------------- 1 | #' 25 search results for "Oakland Public library branch" 2 | #' 3 | #' Contains the search results from Mapzen's search service for the query 4 | #' "Oakland public library branch" as of January 8, 2017. 5 | #' 6 | #' @format A \code{mapzen_geo_list} with 25 locations 7 | #' 8 | #' @source Mapzen, OpenStreetMap, OpenAddresses, GeoNames, WhosOnFirst, 9 | #' see \url{https://www.mapzen.com/rights/} 10 | "oakland_public" 11 | 12 | #' Pedestrian isochrones from the Berkeley Marina for 10 and 15 minutes 13 | #' 14 | #' Isochrone results from Mapzen as of January 8, 2017. The location for the 15 | #' isochrones is the Berkeley Marina, lat 37.86613, lon -122.3151 16 | #' 17 | #' @source Mapzen, OpenStreetMap, British Oceanographic Data Centre, 18 | #' NASA, USGS, and Transitland. 19 | "marina_walks" 20 | 21 | #' Vector tiles the contain California 22 | #' 23 | #' @source Mapzen, OpenStreetMap contributors, Who's On First, Natural Earth, 24 | #' and openstreetmapdata.com 25 | "ca_tiles" 26 | 27 | #' Pedestrian isochrones from the Berkeley Marina for 10 and 15 minutes, as polygons 28 | #' 29 | #' Polygon Isochrone results (using \code{polygons = TRUE}) from Mapzen as of 30 | #' January 10, 2017. The location for the isochrones is the Berkeley Marina, 31 | #' lat 37.86613, lon -122.3151, and the contours are 10 and 15 minutes for a 32 | #' pedestrian costing model. 33 | #' 34 | #' @source Mapzen, OpenStreetMap, British Oceanographic Data Centre, 35 | #' NASA, USGS, and Transitland. 36 | "marina_walks_polygons" 37 | -------------------------------------------------------------------------------- /R/geocode.R: -------------------------------------------------------------------------------- 1 | search_results_to_geocodes <- function(result, location) { 2 | if (is.null(result$features) || length(result$features) <= 0L) 3 | stop("Tried to geocode '", location, "' but there were no results", 4 | call. = FALSE) 5 | confidence <- as.numeric(result$features[[1]]$properties$confidence[[1]]) 6 | longitude <- as.numeric(result$features[[1]]$geometry$coordinates[[1]]) 7 | latitude <- as.numeric(result$features[[1]]$geometry$coordinates[[2]]) 8 | res <- tibble::tibble( 9 | geocode_address = result$features[[1]]$properties$label, 10 | geocode_longitude = longitude, 11 | geocode_latitude = latitude, 12 | geocode_confidence = confidence 13 | ) 14 | if (nrow(res) > 1) 15 | stop("There was an error while geocoding") 16 | structure(res, class = c("mz_geocode_result", class(res))) 17 | } 18 | 19 | #' Geocode an address or other location 20 | #' 21 | #' This is a convenience function that calls \code{\link{mz_search}} to retrieve 22 | #' latitude and longitude. 23 | #' 24 | #' @param location An address or other suitably specific search string 25 | #' @param ... Additional arguments passed on to \code{\link{mz_search}} 26 | #' 27 | #' @return A tibble, with the parsed address used to retrieve the geocode, lat/lon, 28 | #' and the confidence (between 0 and 1) 29 | #' 30 | #' @examples 31 | #' \dontrun{ 32 | #' mz_geocode("1600 Pennsylvania Ave., Washington DC") 33 | #' 34 | #' # can also be a landmark 35 | #' mz_geocode("Statue of Liberty, New York") 36 | #' } 37 | #' 38 | #' @seealso \code{\link{mz_search}}, \code{\link{mz_reverse_geocode}} 39 | #' @export 40 | mz_geocode <- function(location, ...) { 41 | search_results_to_geocodes(mz_search(location, size = 10, ...), 42 | location = location) 43 | } 44 | 45 | #' Geocode a structured address 46 | #' 47 | #' \code{\link{mz_geocode}} allows you to search using an unstructured string of 48 | #' text, but if your address data has more structure (eg separate columns for 49 | #' address, city, state, zip), then using the structured search service may 50 | #' provide more precision. For more information, see 51 | #' \url{https://github.com/pelias/documentation/}. Note that 52 | #' all of the arguments are optional, but at least one of them must be non-NULL. 53 | #' Furthermore, \code{postalcode} can not be used by itself. 54 | #' 55 | #' @inheritParams mz_structured_search 56 | #' @param ... Arguments passed on to \code{\link{mz_structured_search}} 57 | #' 58 | #' @return A tibble, with the parsed address used to retrieve the geocode, lat/lon, 59 | #' and the confidence (between 0 and 1) 60 | #' 61 | #' @seealso \code{\link{mz_geocode}}, \code{\link{mz_structured_search}} 62 | #' @export 63 | mz_geocode_structured <- function(address = NULL, 64 | neighbourhood = NULL, 65 | borough = NULL, 66 | locality = NULL, 67 | county = NULL, 68 | region = NULL, 69 | postalcode = NULL, 70 | country = NULL, ...) { 71 | # get info for error message if necessary: 72 | info <- list(address, neighbourhood, borough, 73 | locality, county, region, postalcode, country) 74 | info <- Filter(function(x) !is.null(x), info) 75 | info <- paste(info, collapse = ", ") 76 | 77 | search_results_to_geocodes(mz_structured_search( 78 | address = address, 79 | neighbourhood = neighbourhood, 80 | borough = borough, 81 | locality = locality, 82 | county = county, 83 | region = region, 84 | postalcode = postalcode, 85 | size = 10), location = info) 86 | } 87 | -------------------------------------------------------------------------------- /R/isochrone.R: -------------------------------------------------------------------------------- 1 | build_isochrone_url <- function( 2 | locations, 3 | costing_model, 4 | contours, 5 | date_time, 6 | polygons, 7 | denoise, 8 | generalize, 9 | id, 10 | api_key = NULL 11 | ) { 12 | costing <- costing_model$costing 13 | costing_options <- costing_model$costing_options 14 | 15 | json <- build_isochrone_json( 16 | locations = locations, 17 | costing = costing, 18 | costing_options = costing_options, 19 | date_time = date_time, 20 | contours = contours, 21 | polygons = polygons, 22 | denoise = denoise, 23 | generalize = generalize 24 | ) 25 | 26 | matrix_url( 27 | endpoint = "isochrone", 28 | json = json, 29 | id = id, 30 | api_key = api_key) 31 | } 32 | 33 | build_isochrone_json <- function( 34 | locations, 35 | costing, 36 | costing_options, 37 | date_time, 38 | contours, 39 | polygons, 40 | denoise, 41 | generalize) { 42 | 43 | # locations should have lon/lat. for now, only one location 44 | # is supported 45 | locations <- as.mz_location(locations) 46 | 47 | assert_that(is.null(polygons) || is.flag(polygons)) 48 | assert_that(is.null(denoise) || is.number(denoise)) 49 | assert_that(is.null(generalize) || is.number(generalize)) 50 | 51 | locations <- data.frame( 52 | lon = locations[["lon"]], 53 | lat = locations[["lat"]] 54 | ) 55 | 56 | res <- list(locations = locations) 57 | 58 | costing_model <- jsonlite::unbox(costing) 59 | 60 | res <- c(res, list(costing = costing_model)) 61 | 62 | if (length(costing_options) > 0L) 63 | res <- c(res, costing_options = list(costing_options)) 64 | 65 | if (!is.null(date_time)) { 66 | assert_that(inherits(date_time, "mz_date_time")) 67 | res <- c(res, date_time = list(jsonlite::unbox(date_time))) 68 | } 69 | 70 | res <- c(res, contours = list(contours)) 71 | 72 | if (!is.null(polygons)) 73 | res <- c(res, polygons = list(jsonlite::unbox(polygons))) 74 | 75 | if (!is.null(denoise)) { 76 | assert_that(denoise >= 0, denoise <= 1) 77 | res <- c(res, 78 | denoise = list(jsonlite::unbox(denoise))) 79 | } 80 | 81 | if (!is.null(generalize)) 82 | res <- c(res, generalize = list(jsonlite::unbox(generalize))) 83 | 84 | jsonlite::toJSON(res) 85 | } 86 | 87 | 88 | iso_process <- function(response) { 89 | tryCatch( 90 | httr::stop_for_status(response), 91 | http_400 = function(e) { 92 | txt <- httr::content(response, as = "text") 93 | lst <- jsonlite::fromJSON(txt, simplifyVector = FALSE) 94 | stop(e$message, "\n", lst$error, " (", lst$error_code, ")", 95 | call. = FALSE) 96 | } 97 | ) 98 | header <- httr::headers(response) 99 | mz_update_usage(header, "matrix") 100 | txt <- httr::content(response, as = "text") 101 | lst <- jsonlite::fromJSON(txt, simplifyVector = FALSE) 102 | structure(lst, 103 | header = header, 104 | class = c("mapzen_isochrone_list", "geo_list")) 105 | } 106 | 107 | #' @import assertthat 108 | isochrone_get <- function(url) { 109 | response <- matrix_GET(httr::build_url(url)) 110 | iso_process(response) 111 | } 112 | 113 | #' Retrieve isochrones 114 | #' 115 | #' From \url{https://valhalla.readthedocs.io/en/latest/}: 116 | #' "An isochrone is a line that connects points of equal travel time about a 117 | #' given location, from the Greek roots of 'iso' for equal and 'chrone' for time. 118 | #' The Mapzen Isochrone service computes areas that are reachable within 119 | #' specified time intervals from a location, and returns the reachable regions 120 | #' as contours of polygons or lines that you can display on a map." 121 | #' 122 | #' @param locations An \code{mz_location}, or something that can be coerced to an 123 | #' \code{\link{mz_location}}, as the departure point for the isochrone. This can be the 124 | #' result of \code{\link{mz_geocode}}. Despite the argument name, the isochrone 125 | #' service currently can only accept a single location 126 | #' @param costing_model The costing model, see \code{\link{mz_costing}} 127 | #' @param contours Up to 4 contours, see \code{\link{mz_contours}} 128 | #' @param date_time The local date and time at the location, and whether it is 129 | #' the departure or arrival time. See \code{\link{mz_date_time}} 130 | #' @param polygons Whether to return polygons (TRUE) or linestrings (FALSE, default) 131 | #' @param denoise A value between 0 and 1 (default 1) to remove smaller contours. 132 | #' A value of 1 will only return the largest contour for a given time value. A 133 | #' value of 0.5 drops any contours that are less than half the area of the 134 | #' largest contour. 135 | #' @param generalize Tolerance in meters for the Douglas-Peucker generalization. 136 | #' @param id A descriptive identifier, the response will contain the id as an element. 137 | #' @param api_key Your Mapzen API key. The default is to look for the key within 138 | #' the provider information that was set up with `mz_set_host`. 139 | #' 140 | #' @return A \code{mapzen_isochrone_list}, which can be converted to \code{sf} 141 | #' using \code{\link{as_sf}}. 142 | #' 143 | #' @seealso \code{\link{mz_costing}} 144 | #' 145 | #' @examples 146 | #' \dontrun{ 147 | #' mz_isochrone( 148 | #' mz_location(lat = 37.87416, lon = -122.2544), 149 | #' costing_model = mz_costing$auto(), 150 | #' contours = mz_contours(c(10, 20, 30)) 151 | #' ) 152 | #' 153 | #' # departure point can be specified as a geocode result 154 | #' mz_isochrone( 155 | #' mz_geocode("UC Berkeley"), 156 | #' costing_model = mz_costing$pedestrian(), 157 | #' contours = mz_contours(c(10, 20, 30)) 158 | #' ) 159 | #' } 160 | #' 161 | #' @name mz_isochrone 162 | #' @export 163 | mz_isochrone <- function( 164 | locations, 165 | costing_model, 166 | contours, 167 | date_time = NULL, 168 | polygons = NULL, 169 | denoise = NULL, 170 | generalize = NULL, 171 | id = "my-iso", 172 | api_key = NULL 173 | ) { 174 | costing_options <- costing_model$costing_options 175 | url <- build_isochrone_url( 176 | locations = locations, 177 | costing_model = costing_model, 178 | contours = contours, 179 | date_time = date_time, 180 | polygons = polygons, 181 | denoise = denoise, 182 | generalize = generalize, 183 | id = id, 184 | api_key = api_key) 185 | isochrone_get(url) 186 | } 187 | 188 | #' @export 189 | print.mapzen_isochrone_list <- function(x, ...) { 190 | cat("GeoJSON response from Mapzen\n") 191 | cat("Isochrones: ", length(x$features), sep = "") 192 | } 193 | -------------------------------------------------------------------------------- /R/matrix-helpers.R: -------------------------------------------------------------------------------- 1 | #' Create/extract lat/lon location information 2 | #' 3 | #' \code{mz_location} constructs a new \code{mz_location} object, which can be 4 | #' used with functions such as \code{\link{mz_isochrone}} or 5 | #' \code{\link{mz_reverse_geocode}}. \code{as.mz_location} coerces eligible 6 | #' objects to \code{mz_location}s. 7 | #' 8 | #' @param lat Latitude 9 | #' @param lon Longitude 10 | #' @param x An object that has location information 11 | #' @param ... Not currently used 12 | #' 13 | #' @name mz_location 14 | #' @seealso 15 | #' \code{\link{mz_isochrone}} For using the Mapzen isochrone service 16 | #' \code{\link{mz_contours}}, \code{\link{mz_costing}}, and 17 | #' \code{\link{mz_costing_options}} for other argument constructors 18 | #' @export 19 | mz_location <- function(lat, lon) { 20 | assert_that( 21 | is.number(lat), 22 | is.number(lon) 23 | ) 24 | 25 | structure( 26 | data.frame(lat = lat, lon = lon), 27 | class = c("mz_location", "data.frame") 28 | ) 29 | } 30 | 31 | #' @rdname mz_location 32 | #' @export 33 | as.mz_location <- function(x, ...) UseMethod("as.mz_location") 34 | 35 | #' @rdname mz_location 36 | #' @export 37 | as.mz_location.default <- function(x, ...) { 38 | lat <- x[["lat"]] 39 | lon = x[["lon"]] 40 | mz_location(lat = lat, lon = lon) 41 | } 42 | 43 | #' @rdname mz_location 44 | #' @export 45 | as.mz_location.mz_geocode_result <- function(x, ...) { 46 | lat <- x[["geocode_latitude"]] 47 | lon <- x[["geocode_longitude"]] 48 | mz_location(lat = lat, lon = lon) 49 | } 50 | 51 | #' Create an mz_contours object 52 | #' 53 | #' Contours are given as inputs to \code{\link{mz_isochrone}}. This function 54 | #' makes it convenient to construct them. 55 | #' 56 | #' @param times Times in minutes for the contour. Up to a maximum of 4 numbers. 57 | #' @param colors Colors for the contours. By default, a palette will be constructed 58 | #' from the Colorbrewer 4-class oranges palette. 59 | #' @export 60 | mz_contours <- function(times, colors = NULL) { 61 | assert_that(is.numeric(times), 62 | length(times) <= 4L) 63 | 64 | if (is.null(colors)) { 65 | times <- sort(times) 66 | colors <- c('feedde','fdbe85','fd8d3c','d94701') 67 | colors <- colors[1:length(times)] 68 | } 69 | 70 | assert_that( 71 | is.character(colors), 72 | length(colors) == length(times) 73 | ) 74 | 75 | structure( 76 | data.frame( 77 | time = times, color = colors, 78 | stringsAsFactors = FALSE 79 | ), 80 | class = c("mz_contours", "data.frame") 81 | ) 82 | } 83 | 84 | #' Create mz_date_time objects 85 | #' 86 | #' Mobility services (such as \code{mz_isochrone}) take, optionally, a date_time 87 | #' argument that specifies the date and time along with type (departure/arrival). 88 | #' This function constructs the appropriate objects to use as date_time arguments. 89 | #' 90 | #' @param date_time A POSIXt date-time object 91 | #' @param type "departure" or "arrival" 92 | mz_date_time <- function(date_time, type = "departure") { 93 | assert_that(is.time(date_time), is.string(type)) 94 | types <- c("current", "departure", "arrival") 95 | typenum <- match(type, types) - 1 96 | 97 | if (is.na(typenum)) stop( 98 | "type '", type, "'", 99 | " not recognized. type should be one of: ", 100 | paste0("'", types, "'", collapse = ", ") 101 | ) 102 | 103 | date_time <- format(date_time, "%Y-%m-%dT%H:%M") 104 | 105 | structure( 106 | data.frame( 107 | type = typenum, 108 | value = date_time, 109 | stringsAsFactors = FALSE 110 | ), 111 | class = c("mz_date_time", "data.frame") 112 | ) 113 | } 114 | -------------------------------------------------------------------------------- /R/matrix-main.R: -------------------------------------------------------------------------------- 1 | matrix_path <- function(endpoint) { 2 | matpath <- mz_get_host("matrix")$path 3 | if (is.null(matpath)) { 4 | res <- endpoint 5 | } else { 6 | res <- paste(matpath, endpoint, sep = "/") 7 | } 8 | res 9 | } 10 | matrix_url <- function(endpoint, ..., api_key) { 11 | if (is.null(api_key)) api_key <- mz_key(which = "matrix") 12 | query <- list(...) 13 | query <- c(api_key = api_key, query) 14 | structure( 15 | list( 16 | scheme = mz_get_host("matrix")$scheme, 17 | hostname = mz_get_host("matrix")$hostname, 18 | path = matrix_path(endpoint), 19 | query = query), 20 | class = "url" 21 | ) 22 | } 23 | 24 | matrix_GET <- httr::GET 25 | -------------------------------------------------------------------------------- /R/mz-autocomplete.R: -------------------------------------------------------------------------------- 1 | #' @import assertthat 2 | build_autocomplete_url <- function( 3 | text, 4 | boundary.country = NULL, 5 | boundary.rect = NULL, 6 | focus.point = NULL, 7 | sources = NULL, 8 | layers = NULL, 9 | api_key = NULL) 10 | { 11 | assert_that(is.string(text)) 12 | assert_that(is.null(boundary.country) || is.string(boundary.country)) 13 | if (!is.null(boundary.rect)) 14 | boundary.rect <- unwrap(boundary.rect, "boundary.rect", 15 | c("min.lat", "min.lon", "max.lat", "max.lon")) 16 | 17 | if (!is.null(focus.point)) { 18 | focus.point <- as.mz_location(focus.point) 19 | focus.point <- unwrap(focus.point, "focus.point", c("lat", "lon")) 20 | } 21 | 22 | if (!is.null(sources)) sources <- string_array(sources) 23 | if (!is.null(layers)) layers <- string_array(layers) 24 | 25 | query <- list() 26 | 27 | query <- c( 28 | query, 29 | text = text, 30 | boundary.country = boundary.country, 31 | boundary.rect, 32 | focus.point, 33 | sources = sources, 34 | layers = layers, 35 | list(api_key = api_key) 36 | ) 37 | query <- query[!is.null(query)] 38 | 39 | do.call(search_url, c(endpoint = "autocomplete", query)) 40 | } 41 | 42 | #' @rdname search 43 | #' @export 44 | mz_autocomplete <- function( 45 | text, 46 | boundary.country = NULL, 47 | boundary.rect = NULL, 48 | focus.point = NULL, 49 | sources = NULL, 50 | layers = NULL, 51 | api_key = NULL) 52 | { 53 | url <- build_autocomplete_url( 54 | text = text, 55 | boundary.country = boundary.country, 56 | boundary.rect = boundary.rect, 57 | focus.point = focus.point, 58 | sources = sources, 59 | layers = layers, 60 | api_key = api_key 61 | ) 62 | 63 | search_get(url) 64 | } 65 | -------------------------------------------------------------------------------- /R/mz-bbox.R: -------------------------------------------------------------------------------- 1 | #' Get the bounding box 2 | #' 3 | #' Returns the bottom left and top right corners of the box that contains a 4 | #' mapzen object (\code{mz_geo_list}, \code{mz_isochrone_list}, 5 | #' or \code{mapzen_vector_tiles}). 6 | #' In the case of \code{mz_rect}, creates such a box from the specified 7 | #' coordinates. The returned value can be used directly as the 8 | #' \code{boundary.rect} parameter for \code{\link{search}} functions, as well as 9 | #' converted to x, y, zoom coordinates to use with \code{\link{mz_vector_tiles}}. 10 | #' 11 | #' @param geo A mapzen geo list or isochrone list 12 | #' @param min_lon,min_lat,max_lon,max_lat The bottom left and top right corners, 13 | #' expressed as latitude and longitude, of a rectangle. 14 | #' 15 | #' @return A single-row tibble with columns \code{min_lon}, \code{min_lat}, 16 | #' \code{max_lon}, \code{max_lat}. 17 | #' 18 | #' @name mz_bbox 19 | #' 20 | #' @examples 21 | #' mz_rect(min_lon = -122.2856, min_lat = 37.73742, max_lon = -122.1749, max_lat = 37.84632) 22 | #' mz_bbox(oakland_public) 23 | #' 24 | #' @export 25 | mz_bbox <- function(geo) UseMethod("mz_bbox") 26 | 27 | #' @rdname mz_bbox 28 | #' @export 29 | mz_bbox.mapzen_geo_list <- function(geo) { 30 | bbox <- geo$bbox 31 | if (is.null(bbox) || length(bbox) != 4L) { 32 | warning("Unable to read bounding box, returning NA") 33 | return( 34 | tibble::tibble( 35 | min_lon = NA_real_, 36 | min_lat = NA_real_, 37 | max_lon = NA_real_, 38 | max_lat = NA_real_ 39 | ) 40 | ) 41 | } 42 | 43 | res <- tibble::tibble( 44 | min_lon = as.numeric(bbox[[1]]), 45 | min_lat = as.numeric(bbox[[2]]), 46 | max_lon = as.numeric(bbox[[3]]), 47 | max_lat = as.numeric(bbox[[4]]) 48 | ) 49 | 50 | class(res) <- c("mz_bbox", class(res)) 51 | res 52 | } 53 | 54 | #' @rdname mz_bbox 55 | #' @export 56 | mz_bbox.mapzen_isochrone_list <- function(geo) mz_bbox(as_sf(geo)) 57 | 58 | layer_coords <- function(layer) { 59 | feature_type <- function(feature) { 60 | known_types <- c( 61 | "Point", "MultiPoint", 62 | "LineString", "MultiLineString", 63 | "Polygon", "MultiPolygon" 64 | ) 65 | res <- feature$geometry$type 66 | if (is.null(res)) 67 | stop("Found a feature without a geometry type") 68 | if (!res %in% known_types) 69 | stop("Feature type not recognized: ", feature_type, "\n", 70 | "expected one of: ", paste(known_types, collapse = ", ")) 71 | res 72 | } 73 | 74 | position <- function(coords) { 75 | data.frame(lon = as.numeric(coords[[1]]), 76 | lat = as.numeric(coords[[2]])) 77 | } 78 | 79 | positions <- function(coords) { 80 | res <- lapply(coords, position) 81 | do.call("rbind", res) 82 | } 83 | 84 | positions_array <- function(coords) { 85 | res <- lapply(coords, positions) 86 | do.call("rbind", res) 87 | } 88 | 89 | point_coords <- function(feature) 90 | position(feature$geometry$coordinates) 91 | 92 | multipoint_coords <- function(feature) { 93 | positions(feature$geometry$coordinates) 94 | } 95 | 96 | line_coords <- function(feature) multipoint_coords(feature) 97 | 98 | multiline_coords <- function(feature) { 99 | positions_array(feature$geometry$coordinates) 100 | } 101 | 102 | polygon_coords <- function(feature) multiline_coords(feature) 103 | multipolygon_coords <- function(feature) { 104 | res <- lapply(feature$geometry$coordinates, positions_array) 105 | do.call("rbind", res) 106 | } 107 | 108 | coords <- function(feature) 109 | switch(feature_type(feature), 110 | Point = point_coords(feature), 111 | MultiPoint = multipoint_coords(feature), 112 | LineString = line_coords(feature), 113 | MultiLineString = multiline_coords(feature), 114 | Polygon = polygon_coords(feature), 115 | MultiPolygon = multipolygon_coords(feature), 116 | default = stop("Unrecognized feature")) 117 | 118 | res <- lapply(layer$features, coords) 119 | do.call("rbind", res) 120 | } 121 | 122 | #' @export 123 | mz_bbox.mapzen_vector_layer <- function(geo) { 124 | res <- layer_coords(geo) 125 | mz_rect(min_lon = min(res$lon), 126 | min_lat = min(res$lat), 127 | max_lon = max(res$lon), 128 | max_lat = max(res$lat)) 129 | } 130 | 131 | #' @export 132 | mz_bbox.mapzen_vector_tiles <- function(geo) { 133 | res <- lapply(geo, layer_coords) 134 | res <- do.call("rbind", res) 135 | structure( 136 | data.frame( 137 | min_lon = min(res$lon), 138 | min_lat = min(res$lat), 139 | max_lon = max(res$lon), 140 | max_lat = max(res$lat) 141 | ), class = c("mz_bbox", "tbl_df", "tbl", "data.frame") 142 | ) 143 | } 144 | 145 | #' @rdname mz_bbox 146 | #' @export 147 | mz_rect <- function(min_lon, min_lat, max_lon, max_lat) { 148 | assert_that(is.number(min_lon), 149 | is.number(min_lat), 150 | is.number(max_lon), 151 | is.number(max_lat)) 152 | structure( 153 | data.frame( 154 | min_lon = min_lon, 155 | min_lat = min_lat, 156 | max_lon = max_lon, 157 | max_lat = max_lat 158 | ), class = c("mz_bbox", "tbl_df", "tbl", "data.frame") 159 | ) 160 | } 161 | 162 | #' @export 163 | mz_bbox.default <- function(geo) { 164 | bbox <- sf::st_bbox(geo) 165 | mz_rect( 166 | min_lon = bbox[["xmin"]], 167 | min_lat = bbox[["ymin"]], 168 | max_lon = bbox[["xmax"]], 169 | max_lat = bbox[["ymax"]] 170 | ) 171 | } 172 | -------------------------------------------------------------------------------- /R/mz-coordinates.R: -------------------------------------------------------------------------------- 1 | #' Extract a data frame of coordinates from a \code{mapzen_geo_list} 2 | #' 3 | #' @param geo A mapzen geo list 4 | #' 5 | #' @return A tibble, with columns \code{lon} and \code{lat}. 6 | #' 7 | #' @examples 8 | #' mz_coordinates(oakland_public) 9 | #' 10 | #' @name mz_coordinates 11 | #' @export 12 | mz_coordinates <- function(geo) UseMethod("mz_coordinates") 13 | 14 | #' @rdname mz_coordinates 15 | #' @export 16 | mz_coordinates.mapzen_geo_list <- function(geo) { 17 | features <- geo$features 18 | lon <- vapply(features, 19 | function(feature) { 20 | feature$geometry$coordinates[[1]] 21 | }, FUN.VALUE = numeric(1)) 22 | 23 | lat <- vapply(features, 24 | function(feature) { 25 | feature$geometry$coordinates[[2]] 26 | }, FUN.VALUE = numeric(1)) 27 | 28 | tibble::tibble(lon = lon, lat = lat) 29 | } 30 | -------------------------------------------------------------------------------- /R/mz-key.R: -------------------------------------------------------------------------------- 1 | mz_key <- function(which) { 2 | getOption(paste0("RMAPZEN_", toupper(which), "_HOST"))$key 3 | } 4 | -------------------------------------------------------------------------------- /R/mz-place.R: -------------------------------------------------------------------------------- 1 | #' Get details on a place 2 | #' 3 | #' Search functions (e.g. \code{\link{mz_search}}) return identification numbers, 4 | #' or \code{gid}s. Use \code{mz_place} to retrieve more details about the place. 5 | #' See \url{https://github.com/pelias/documentation/} for details. This 6 | #' function is generic, and can take a character vector of IDs, or a 7 | #' \code{mapzen_geo_list} as returned by \code{\link{mz_search}} and friends. 8 | #' 9 | #' @param ids A character vector of gids (see details), or a \code{mapzen_geo_list} 10 | #' @param ... Arguments passed on to methods 11 | #' @param gid The name of the \code{gid} field to use. Search results may include, 12 | #' in addition to the \code{gid} for the search result itself (the default), the 13 | #' \code{gid}s for the country, region, county, locality and neighborhood. 14 | #' @param api_key Your Mapzen API key. The default is to look for the key within 15 | #' the provider information that was set up with `mz_set_host`. 16 | #' @name mz_place 17 | #' @export 18 | mz_place <- function(ids, ..., api_key = NULL) UseMethod("mz_place") 19 | 20 | build_place_url <- function(ids, api_key = NULL) { 21 | ids <- string_array(ids) 22 | 23 | query <- list( 24 | ids = ids, 25 | api_key = api_key 26 | ) 27 | 28 | do.call(search_url, c(endpoint = "place", query)) 29 | } 30 | 31 | #' @rdname mz_place 32 | #' @export 33 | mz_place.character <- function(ids, ..., api_key = NULL) { 34 | search_get(build_place_url(ids, api_key = api_key)) 35 | } 36 | 37 | #' @rdname mz_place 38 | #' @export 39 | mz_place.mapzen_geo_list <- function(ids, ..., gid = "gid", api_key = NULL) { 40 | geolist <- ids 41 | getgid <- function(feature) { 42 | feature$properties[[gid]] 43 | } 44 | 45 | ids <- vapply(geolist$features, getgid, FUN.VALUE = character(1)) 46 | search_get(build_place_url(ids, api_key)) 47 | } 48 | 49 | -------------------------------------------------------------------------------- /R/mz-references.R: -------------------------------------------------------------------------------- 1 | #' Reference lists 2 | #' 3 | #' Lists of sources, layers, and countries, as they are expected to appear in 4 | #' the \code{\link{mz_search}} functions. These data objects are provided as a 5 | #' convenience, to be able to quickly and easily look up acceptable values for 6 | #' the optional arguments of search functions. Object names match the argument 7 | #' names for which they are appropriate. So \code{mz_sources} provide acceptable 8 | #' arguments for the \code{source} argument in \code{\link{mz_search}}, 9 | #' \code{mz_layers} for the \code{layer} argument, and \code{\link{mz_countries}} 10 | #' for the \code{boundary.country} argument. Mapzen's documentation 11 | #' (\url{https://github.com/pelias/documentation/}) explains more about 12 | #' each of these arguments. 13 | #' 14 | #' @examples 15 | #' \dontrun{ 16 | #' # look for YMCAs in Jamaica: 17 | #' # Note that boundary.country is supplied via ISO3166 code, 18 | #' # but mz_countries will look up the code 19 | #' mz_search("YMCA", 20 | #' boundary.country = mz_countries$Jamaica, 21 | #' layers = c(mz_layers$venue, mz_layers$address)) 22 | #' } 23 | #' 24 | #' @name mapzen_references 25 | NULL 26 | 27 | #' @rdname mapzen_references 28 | #' @export 29 | mz_sources <- list( 30 | openstreetmap = "osm", 31 | osm = "osm", 32 | openaddresses = "oa", 33 | oa = "oa", 34 | whosonfirst = "wof", 35 | wof = "wof", 36 | geonames = "gn", 37 | gn = "gn" 38 | ) 39 | 40 | #' @rdname mapzen_references 41 | #' @export 42 | mz_layers <- list( 43 | venue = "venue", 44 | address = "address", 45 | street = "street", 46 | country = "country", 47 | macroregion = "macroregion", 48 | region = "region", 49 | macrocounty = "macrocounty", 50 | county = "county", 51 | locality = "locality", 52 | local_admin = "local_admin", 53 | borough = "borough", 54 | neighbourhood = "neighbourhood", 55 | coarse = "coarse" 56 | ) 57 | 58 | make_mz_countries <- function() { 59 | iso3166 <- ISOcodes::ISO_3166_1 60 | ind <- grepl("^[A-Z]+$", iso3166$Alpha_2) 61 | iso3166 <- iso3166[ind, , drop = FALSE] 62 | 63 | v1 <- data.frame(desc = iso3166$Alpha_2, code = iso3166$Alpha_2, stringsAsFactors = FALSE) 64 | v2 <- data.frame(desc = iso3166$Alpha_3, code = iso3166$Alpha_2, stringsAsFactors = FALSE) 65 | v3 <- data.frame(desc = iso3166$Name, code = iso3166$Alpha_2, stringsAsFactors = FALSE) 66 | 67 | v <- dplyr::distinct(dplyr::bind_rows(v1, v2, v3)) 68 | structure(as.list(v$code), names = v$desc) 69 | } 70 | 71 | #' @rdname mapzen_references 72 | #' @export 73 | mz_countries <- make_mz_countries() 74 | -------------------------------------------------------------------------------- /R/mz-reverse.R: -------------------------------------------------------------------------------- 1 | #' @import assertthat 2 | build_reverse_url <- function( 3 | point, size = NULL, layers = NULL, sources = NULL, 4 | boundary.country = NULL, 5 | api_key = NULL 6 | ) { 7 | assert_that(is.null(boundary.country) || is.string(boundary.country)) 8 | point <- as.mz_location(point) 9 | point <- unwrap(point, "point", c("lat", "lon")) 10 | 11 | if (!is.null(sources)) sources <- string_array(sources) 12 | if (!is.null(layers)) layers <- string_array(layers) 13 | 14 | query <- c( 15 | point, size = size, 16 | sources = sources, layers = layers, 17 | boundary.country = boundary.country, 18 | list(api_key = api_key) 19 | ) 20 | query <- query[!is.null(query)] 21 | 22 | do.call(search_url, c(endpoint = "reverse", query)) 23 | } 24 | 25 | #' @rdname search 26 | #' @export 27 | mz_reverse_geocode <- function( 28 | point, size = NULL, layers = NULL, sources = NULL, 29 | boundary.country = NULL, 30 | api_key = NULL 31 | ) { 32 | url <- build_reverse_url( 33 | point = point, 34 | size = size, 35 | layers = layers, 36 | sources = sources, 37 | boundary.country = boundary.country, 38 | api_key = api_key 39 | ) 40 | 41 | search_get(url) 42 | } 43 | -------------------------------------------------------------------------------- /R/mz-search-main.R: -------------------------------------------------------------------------------- 1 | search_path <- function(endpoint) { 2 | spath <- mz_get_host("search")$path 3 | if (is.null(spath)) { 4 | res <- endpoint 5 | } else { 6 | res <- paste(spath, endpoint, sep = "/") 7 | } 8 | res 9 | } 10 | 11 | search_url <- function(endpoint, ..., api_key) { 12 | if (is.null(api_key)) api_key <- mz_key(which = "search") 13 | query <- list(...) 14 | 15 | query <- c( 16 | api_key = api_key, 17 | query 18 | ) 19 | 20 | structure( 21 | list( 22 | scheme = mz_get_host("search")$scheme, 23 | hostname = mz_get_host("search")$hostname, 24 | path = search_path(endpoint), 25 | query = query), 26 | class = "url" 27 | ) 28 | } 29 | 30 | search_GET <- httr::GET 31 | 32 | #' @import assertthat 33 | search_get <- function(url) { 34 | response <- search_GET(httr::build_url(url)) 35 | search_process(response) 36 | } 37 | 38 | search_process <- function(response) { 39 | httr::stop_for_status(response) 40 | 41 | # update the usage statistics 42 | header <- httr::headers(response) 43 | mz_update_usage(header, "search") 44 | 45 | txt <- httr::content(response, as = "text") 46 | lst <- jsonlite::fromJSON(txt, simplifyVector = FALSE) 47 | structure(lst, header = header, class = c("mapzen_geo_list", "geo_list")) 48 | } 49 | -------------------------------------------------------------------------------- /R/mz-search.R: -------------------------------------------------------------------------------- 1 | search_query_parameters <- function( 2 | size = 10, 3 | boundary.country = NULL, boundary.rect = NULL, 4 | boundary.circle = NULL, focus.point = NULL, 5 | sources = NULL, layers = NULL 6 | ) { 7 | assert_that(is.count(size)) 8 | assert_that(is.null(boundary.country) || is.string(boundary.country)) 9 | 10 | if (!is.null(boundary.rect)) 11 | boundary.rect <- unwrap(boundary.rect, "boundary.rect", 12 | c("min_lat", "min_lon", "max_lat", "max_lon")) 13 | if (!is.null(boundary.circle)) 14 | boundary.circle <- unwrap(boundary.circle, "boundary.circle", 15 | c("lat", "lon", "radius")) 16 | if (!is.null(focus.point)) { 17 | focus.point <- as.mz_location(focus.point) 18 | focus.point <- unwrap(focus.point, "focus.point", c("lat", "lon")) 19 | } 20 | 21 | if (!is.null(sources)) sources <- string_array(sources) 22 | if (!is.null(layers)) layers <- string_array(layers) 23 | 24 | query <- list() 25 | query <- c( 26 | query, 27 | size = size, 28 | boundary.country = boundary.country, 29 | boundary.rect, boundary.circle, focus.point, 30 | sources = sources, layers = layers 31 | ) 32 | query[!is.null(query)] 33 | } 34 | 35 | #' @import assertthat 36 | build_search_url <- function( 37 | text, size = 10, 38 | boundary.country = NULL, boundary.rect = NULL, 39 | boundary.circle = NULL, focus.point = NULL, 40 | sources = NULL, layers = NULL, api_key = NULL) 41 | { 42 | assert_that(is.string(text)) 43 | 44 | query <- search_query_parameters( 45 | size = size, boundary.country = boundary.country, 46 | boundary.rect = boundary.rect, 47 | boundary.circle = boundary.circle, 48 | focus.point = focus.point, 49 | sources = sources, layers = layers 50 | ) 51 | 52 | query <- c( 53 | text = text, 54 | query, 55 | list(api_key = api_key) 56 | ) 57 | query <- query[!is.null(query)] 58 | 59 | do.call(search_url, c(endpoint = "search", query)) 60 | } 61 | 62 | #' Mapzen search API 63 | #' 64 | #' Functions to access the various endpoints from the Mapzen Search API. 65 | #' For more details, see \url{https://github.com/pelias/documentation/}. If your 66 | #' data is already split up by street, city, state, zip, etc., then you might 67 | #' find \code{\link{mz_structured_search}} to be more precise. All arguments 68 | #' besides \code{text} (\code{point} in the case of \code{mz_reverse_geocode}) are 69 | #' optional. If you have parsed addresses (e.g. for geocoding), use \code{\link{mz_structured_search}} 70 | #' 71 | #' @param text Search string 72 | #' @param point For reverse geocoding, the location to reverse geocode. Can be 73 | #' created with \code{\link{mz_location}} or \code{\link{mz_geocode}}, 74 | #' otherwise should have names "lat" and "lon" 75 | #' @param size Number of search results requested 76 | #' @param boundary.country ISO-3166 country code to narrow the search. 77 | #' See \code{\link{mz_countries}} 78 | #' @param boundary.rect 4 corners that define a box to narrow the search. Can 79 | #' be the result of \code{\link{mz_bbox}}. Should have named elements with names 80 | #' "min_lon", "min_lat", "max_lon", "max_lat" -- can be created using \code{\link{mz_rect}}. 81 | #' @param boundary.circle A circle to narrow the search. Should have named elements 82 | #' with names "lon", "lat", and "radius" 83 | #' @param focus.point A point to "focus" the search. Can be created with 84 | #' \code{\link{mz_location}} or \code{\link{mz_geocode}}, otherwise should have 85 | #' names "lat" and "lon" 86 | #' @param sources The originating source of the data (to filter/narrow search 87 | #' results). See \code{\link{mz_sources}} 88 | #' @param layers Which layers (types of places) to search. See 89 | #' \url{https://github.com/pelias/documentation/} 90 | #' for definitions, and use \code{\link{mz_layers}} for convenience 91 | #' @param api_key Your Mapzen API key. The default is to look for the key within 92 | #' the provider information that was set up with `mz_set_host`. 93 | #' @name search 94 | #' @seealso \code{\link{mz_place}}, \code{\link{mz_structured_search}}, 95 | #' \code{\link{mz_countries}}, \code{\link{mz_sources}}, \code{\link{mz_layers}} 96 | #' 97 | #' @examples 98 | #' \dontrun{ 99 | #' # hard rock cafes in sweden: 100 | #' mz_search("Hard Rock Cafe", boundary.country = "SE") 101 | #' 102 | #' # autocompletions when the user types in "Union Square" 103 | #' # prioritizing San Francisco results first: 104 | #' mz_autocomplete("Union Square", 105 | #' focus.point = mz_geocode("San Francisco, CA")) 106 | #' } 107 | #' 108 | #' @export 109 | mz_search <- function( 110 | text, size = 10, 111 | boundary.country = NULL, boundary.rect = NULL, 112 | boundary.circle = NULL, focus.point = NULL, 113 | sources = NULL, layers = NULL, api_key = NULL) 114 | { 115 | url <- build_search_url( 116 | text = text, 117 | size = size, 118 | boundary.country = boundary.country, 119 | boundary.rect = boundary.rect, 120 | boundary.circle = boundary.circle, 121 | focus.point = focus.point, 122 | sources = sources, 123 | layers = layers, 124 | api_key = api_key 125 | ) 126 | 127 | search_get(url) 128 | } 129 | -------------------------------------------------------------------------------- /R/mz-tile-coordinates.R: -------------------------------------------------------------------------------- 1 | deg2num <- function(pt, zoom){ 2 | # http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames#R 3 | lat_deg <- pt[["lat"]] 4 | lon_deg <- pt[["lon"]] 5 | lat_rad <- lat_deg * pi /180 6 | n <- 2.0 ^ zoom 7 | xtile <- floor((lon_deg + 180.0) / 360.0 * n) 8 | ytile = floor((1.0 - log(tan(lat_rad) + (1 / cos(lat_rad))) / pi) / 2.0 * n) 9 | return( c(xtile, ytile)) 10 | } 11 | 12 | #' Specify tile coordinates 13 | #' 14 | #' \code{\link{mz_vector_tiles}} requires tile coordinates or some other 15 | #' specification of the region that is to be drawn. \code{\link{mz_vector_tiles}} 16 | #' will automatically convert its inputs to vector tiles, so you generally won't 17 | #' need to use this function directly. 18 | #' 19 | #' @param x integer vector of x-coordinates 20 | #' @param y integer vector of y-coordinates 21 | #' @param z integer between 0 and 19 specifying the zoom level 22 | #' @param obj An object that can be converted to tile coordinates 23 | #' @param ... Other arguments passed on to methods 24 | #' @param height Height in pixels 25 | #' @param width Width in pixels 26 | #' 27 | #' @examples 28 | #' mz_tile_coordinates(19293, 24641, 16) 29 | #' 30 | #' ## can specify multiple contiguous tiles: 31 | #' mz_tile_coordinates(19293:19294, 24641:24642, 16) 32 | #' 33 | #' ## a rectangular bounding box can be converted to tile coordinates: 34 | #' as.mz_tile_coordinates(mz_rect(min_lon = -122.2856, 35 | #' min_lat = 37.73742, 36 | #' max_lon = -122.1749, 37 | #' max_lat = 37.84632)) 38 | #' 39 | #' ## zoom level is calculated based on desired pixel dimensions of the map: 40 | #' as.mz_tile_coordinates(mz_rect(min_lon = -122.2856, 41 | #' min_lat = 37.73742, 42 | #' max_lon = -122.1749, 43 | #' max_lat = 37.84632), height = 750, width = 1000) 44 | #' 45 | #' ## a bounding box can also be calculated: 46 | #' as.mz_tile_coordinates(mz_bbox(oakland_public)) 47 | #' 48 | #' @seealso \code{\link{mz_vector_tiles}}, \code{\link{mz_bbox}} 49 | #' 50 | #' @name mz_tile_coordinates 51 | #' @export 52 | mz_tile_coordinates <- function(x, y, z) { 53 | assert_that(is.numeric(x), is.numeric(y), is.count(z)) 54 | x <- seq(from = min(x), to = max(x), by = 1) 55 | y <- seq(from = min(y), to = max(y), by = 1) 56 | 57 | df <- expand.grid(x = x, y = y, z = z) 58 | 59 | res <- Map(function(.x, .y, .z) { 60 | list(x = .x, y = .y, z = .z) 61 | }, df$x, df$y, df$z) 62 | 63 | structure( 64 | res, 65 | class = c("mz_tile_coordinates", "list") 66 | ) 67 | } 68 | 69 | #' @rdname mz_tile_coordinates 70 | #' @export 71 | as.mz_tile_coordinates <- function(obj, ...) UseMethod("as.mz_tile_coordinates") 72 | 73 | #' @rdname mz_tile_coordinates 74 | #' @export 75 | as.mz_tile_coordinates.mz_tile_coordinates <- function(obj, ...) obj 76 | 77 | validate_dims <- function(height, width, zoom) { 78 | # default 79 | if (is.null(height) && is.null(width) && is.null(zoom)) 80 | return(list(height = 375, width = 500, z = NULL)) 81 | 82 | if (!is.null(height) && !is.null(width) && !is.null(zoom)) 83 | stop("`height`, `width`, and `z` cannot all be non-NULL.", 84 | call. = FALSE) 85 | 86 | if (!is.null(zoom)) { 87 | if (!is.null(height)) 88 | warning("`height` will be ignored because `z` was provided.") 89 | if (!is.null(width)) 90 | warning("`width` will be ignored because `z` was provided.") 91 | return(list(height = NULL, width = NULL, z = zoom)) 92 | } 93 | 94 | if (is.null(height) || is.null(width)) 95 | stop("`height` and `width` must both be non-NULL.", call. = FALSE) 96 | 97 | list(height = height, width = width, z = NULL) 98 | } 99 | 100 | #' @rdname mz_tile_coordinates 101 | #' @export 102 | as.mz_tile_coordinates.mz_bbox <- function(obj, ..., z = NULL, 103 | height = NULL, width = NULL) { 104 | # given a bounding box defined by bottom left and top right corners, 105 | # convert to vector tile coordinates (x, y, zoom) 106 | dims <- validate_dims(height, width, zoom = z) 107 | 108 | # http://stackoverflow.com/a/13274361 109 | getBoundsZoomLevel <- function(bounds, mapDim) { 110 | WORLD_DIM <- list( height = 256, width= 256 ) 111 | ZOOM_MAX <- 20; 112 | 113 | latRad <- function(lat) { 114 | sin = sin(lat * pi / 180) 115 | radX2 = log((1 + sin) / (1 - sin)) / 2 116 | pmax(pmin(radX2, pi), -pi) / 2 117 | } 118 | 119 | zoom <- function(mapPx, worldPx, fraction) { 120 | floor(log(mapPx / worldPx / fraction) / log(2)) 121 | } 122 | 123 | latFraction = (latRad(bounds[["max_lat"]]) - latRad(bounds[["min_lat"]])) / pi 124 | 125 | lngDiff = bounds[["max_lon"]] - bounds[["min_lon"]] 126 | if (lngDiff < 0) 127 | lngFraction <- lngDiff + 360 128 | else lngFraction <- lngDiff 129 | lngFraction <- lngFraction / 360 130 | 131 | latZoom <- zoom(mapDim$height, WORLD_DIM$height, latFraction) 132 | lngZoom <- zoom(mapDim$width, WORLD_DIM$width, lngFraction) 133 | 134 | pmin(latZoom, lngZoom, ZOOM_MAX) 135 | } 136 | if (!is.null(dims$z)) 137 | zoom <- dims$z 138 | else zoom <- getBoundsZoomLevel(obj, list(height = dims$height, 139 | width = dims$width)) 140 | 141 | # tile for bottom left corner: 142 | ll <- deg2num(mz_location( 143 | lat = obj[["min_lat"]], 144 | lon = obj[["min_lon"]] 145 | ), zoom = zoom) 146 | 147 | # for top right: 148 | ur <- deg2num(mz_location( 149 | lat = obj[["max_lat"]], 150 | lon = obj[["max_lon"]] 151 | ), zoom = zoom) 152 | 153 | xs <- unique(c(ll[1], ur[1])) 154 | ys <- unique(c(ll[2], ur[2])) 155 | 156 | mz_tile_coordinates(x = xs, y = ys, z = zoom) 157 | } 158 | 159 | #' @rdname mz_tile_coordinates 160 | #' @export 161 | as.mz_tile_coordinates.mz_location <- function(obj, ..., 162 | z = 15L) { 163 | assert_that(is.count(z)) 164 | xy_coords <- deg2num(obj, zoom = z) 165 | mz_tile_coordinates(x = xy_coords[1], y = xy_coords[2], z = z) 166 | } 167 | 168 | #' @rdname mz_tile_coordinates 169 | #' @export 170 | as.mz_tile_coordinates.mz_geocode_result <- function(obj, ..., 171 | z = 15L) { 172 | obj <- as.mz_location(obj) 173 | as.mz_tile_coordinates.mz_location(obj, z = z) 174 | } 175 | -------------------------------------------------------------------------------- /R/print-mapzen-geo-list.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | print.mapzen_geo_list <- function(x, ..., n = 5) { 3 | geo <- x 4 | assert_that(is.count(n) && n > 0) 5 | 6 | attribution <- geo$geocoding$attribution 7 | if (is.null(attribution)) attribution <- NA_character_ 8 | if (!assertthat::is.string(attribution)) attribution <- NA_character_ 9 | 10 | cat("GeoJSON response from Mapzen\n") 11 | cat("Attribution info:", attribution, "\n") 12 | 13 | nlocs <- length(geo$features) 14 | 15 | bbox <- mz_bbox(geo) 16 | min_lat <- round(bbox$min_lat, 2) 17 | min_lon <- round(bbox$min_lon, 2) 18 | max_lat <- round(bbox$max_lat, 2) 19 | max_lon <- round(bbox$max_lon, 2) 20 | 21 | cat("Bounds (lon/lat): (", 22 | min_lon, ", ", 23 | min_lat, ") - (", 24 | max_lon, ", ", 25 | max_lat, ")\n", sep = "") 26 | 27 | cat(nlocs, "locations") 28 | if (nlocs > 0) 29 | cat(":\n") 30 | else { 31 | cat("\n") 32 | return(invisible(geo)) 33 | } 34 | 35 | getname <- function(feature) { 36 | nm <- feature$properties$name 37 | if (is.null(nm)) return("???") else return(nm) 38 | } 39 | 40 | getcoords <- function(feature) { 41 | coords <- feature$geometry$coordinates 42 | if (is.null(coords)) return("(???)") 43 | res <- paste(round(as.numeric(feature$geometry$coordinates), 2), collapse = ", ") 44 | paste("(", res, ")", sep = "") 45 | } 46 | 47 | printlen <- pmin(n, length(geo$features)) 48 | 49 | places <- vapply(geo$features[1:printlen], getname, FUN.VALUE = character(1)) 50 | coords <- vapply(geo$features[1:printlen], getcoords, FUN.VALUE = character(1)) 51 | 52 | cat(paste(" ", places, coords), sep = "\n") 53 | if (printlen < length(geo$features)) cat(" ...\n") 54 | invisible(geo) 55 | } 56 | -------------------------------------------------------------------------------- /R/print-vector-tiles.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | print.mapzen_vector_tiles <- function(x, ...) { 3 | cat("Mapzen vector tile data\n") 4 | cat("Layers: (count of features in parentheses)\n") 5 | smry <- vapply(x, function(layer) length(layer$features), integer(1)) 6 | layers <- paste0(" ", names(smry), " (", unname(smry), ")", collapse = "\n") 7 | cat(layers) 8 | invisible(x) 9 | } 10 | 11 | #' @export 12 | print.mapzen_vector_layer <- function(x, ...) { 13 | cat("Mapzen vector tile layer\n") 14 | if (length(x$features) <= 0) { 15 | cat("No data") 16 | return(invisible(x)) 17 | } 18 | cat("Geometry type(s): (counts in parentheses)\n") 19 | 20 | json_to_geom <- c( 21 | LineString = "line", 22 | MultiLineString = "line", 23 | Polygon = "polygon", 24 | MultiPolygon = "polygon", 25 | Point = "point" 26 | ) 27 | 28 | feature_types <- vapply(x$features, function(feat) feat$geometry$type, 29 | character(1)) 30 | feature_types <- json_to_geom[feature_types] 31 | feature_summary <- table(feature_types) 32 | features <- names(feature_summary) 33 | counts <- as.numeric(feature_summary) 34 | fun <- function(f, c) { 35 | cat(" ", f, " (", c, ")\n", sep = "") 36 | } 37 | Map(fun, features, counts) 38 | invisible(x) 39 | } 40 | -------------------------------------------------------------------------------- /R/providers.R: -------------------------------------------------------------------------------- 1 | #' Configure provider information 2 | #' 3 | #' rmapzen works with most implementations of PELIAS. This function defines the 4 | #' base URL for a particular API provider, and can be used to provider the 5 | #' \code{provider} argument to \code{\link{mz_set_host}}. 6 | #' 7 | #' @param hostname The hostname in the API URL, for instance \code{www.example.com} 8 | #' @param path Specific path that all API requests must include, e.g. "v1" 9 | #' @param key API key for this provider, if required 10 | #' @param scheme The scheme for the URL, should always be "https" 11 | #' 12 | #' @seealso \code{\link{mz_set_host}} 13 | #' @export 14 | mz_provider <- function(hostname, path = NULL, key = NULL, scheme = "https") { 15 | if (!assertthat::is.string(hostname)) stop("hostname must be a string") 16 | if (!is.null(path) && !assertthat::is.string(path)) 17 | stop("path must be a string") 18 | if (!assertthat::is.string(scheme)) stop("scheme must be a string") 19 | 20 | path <- gsub("/$", "", path) 21 | 22 | list(scheme = scheme, 23 | path = path, 24 | hostname = hostname, 25 | key = key) 26 | } 27 | 28 | #' Set up a host provider for a PELIAS service 29 | #' 30 | #' rmapzen works with most implementations of PELIAS. Use this function to set 31 | #' up the basic information required to connect to a particular provider. 32 | #' Provider-specific setup functions include information to set up known 33 | #' providers. 34 | #' 35 | #' @param which One of "search", "matrix", or "tile" 36 | #' @param provider A provider, created using \code{\link{mz_provider}} 37 | #' @param key API key 38 | #' 39 | #' @seealso \code{\link{mz_provider}} 40 | #' @export 41 | mz_set_host <- function(which, provider) { 42 | if (!assertthat::is.string(which)) stop("which must be a string") 43 | which <- toupper(which) 44 | if (!which %in% c("SEARCH", "MATRIX", "TILE")) 45 | stop("which must be one of: SEARCH, MATRIX, TILE") 46 | optname <- paste0("RMAPZEN_", which, "_HOST") 47 | if (!is.null(getOption(optname))) warning("Replacing existing ", which, " host") 48 | options(structure(list(provider), names = optname)) 49 | } 50 | 51 | #' @rdname mz_set_host 52 | mz_get_host <- function(which) { 53 | if (!assertthat::is.string(which)) stop("which must be a string") 54 | which <- toupper(which) 55 | if (!which %in% c("SEARCH", "MATRIX", "TILE")) 56 | stop("which must be one of: SEARCH, MATRIX, TILE") 57 | res <- getOption(paste0("RMAPZEN_", which, "_HOST")) 58 | if (is.null(res)) stop("no provider set for ", which, ". See ?mz_set_host") 59 | res 60 | } 61 | 62 | #' @rdname mz_set_host 63 | #' @export 64 | mz_set_search_host_geocode.earth <- function(key = Sys.getenv("GEOCODE.EARTH_KEY")) { 65 | if (is.null(key) || key == "") stop("mz_set_search_host_geocode.earth requires a key") 66 | p <- mz_provider(hostname = "api.geocode.earth", 67 | path = "v1", 68 | key = key) 69 | mz_set_host("search", p) 70 | } 71 | 72 | #' @rdname mz_set_host 73 | #' @export 74 | mz_set_search_host_nyc_geosearch <- function() { 75 | p <- mz_provider(hostname = "geosearch.planninglabs.nyc", 76 | path = "v2", 77 | key = NULL) 78 | mz_set_host("search", p) 79 | } 80 | 81 | #' @rdname mz_set_host 82 | #' @export 83 | mz_set_tile_host_nextzen <- function(key = Sys.getenv("NEXTZEN_KEY")) { 84 | if (is.null(key) || key == "") stop("mz_set_tile_host_nextzen requires a key") 85 | p <- mz_provider(hostname = "tile.nextzen.org", 86 | path = "tilezen/vector/v1", 87 | key = key) 88 | mz_set_host("tile", p) 89 | 90 | } 91 | -------------------------------------------------------------------------------- /R/rmapzen-package.R: -------------------------------------------------------------------------------- 1 | #' rmapzen: A client application for the 'Mapzen' API. 2 | #' 3 | #' The rmapzen package provides interfaces to the Search 4 | #' , Isochrone 5 | #' , 6 | #' and Vector Tile 7 | #' services from 'Mapzen', via the following functions: 8 | #' 9 | #' @section Search: 10 | #' All functionality described in 11 | #' are supported: 12 | #' 13 | #' \itemize{ 14 | #' \item \code{\link{mz_search}} 15 | #' \item \code{\link{mz_reverse_geocode}} 16 | #' \item \code{\link{mz_autocomplete}} 17 | #' \item \code{\link{mz_place}} 18 | #' \item \code{\link{mz_structured_search}} 19 | #' } 20 | #' 21 | #' Additionally, \code{\link{mz_geocode}} is useful for a common application of 22 | #' search, that of just obtaining latitude and longitude for a given address or place. 23 | #' 24 | #' @section Isochrone: 25 | #' Isochrones are the areas reachable from a given location within a specified 26 | #' period of time. Mapzen's Isochrone service can calculate isochrones for driving, 27 | #' walking, cycling, or multimodal forms of transport: 28 | #' 29 | #' \itemize{ 30 | #' \item \code{\link{mz_isochrone}} 31 | #' \item \code{\link{mz_costing}}: for constructing "costing models" that describe 32 | #' method of transport along with speed and other options relevant to the 33 | #' calculation of the isochrone 34 | #' \item \code{\link{mz_costing_options}}: for selecting specific options when 35 | #' constructing a costing model 36 | #' } 37 | #' 38 | #' @section Vector Tiles: 39 | #' \itemize{ 40 | #' \item \code{\link{mz_vector_tiles}}: Request one or more adjacent tiles. 41 | #' Multiple map tiles will be stitched together before being returned as a single 42 | #' object. 43 | #' \item \code{\link{mz_tile_coordinates}}: When using \code{\link{mz_vector_tiles}}, 44 | #' you must specify the geographic area for which you want tile data. One way to do so 45 | #' is using the x, y, z tile naming system (see ). 46 | #' \item \code{\link{mz_rect}}: Alternatively, you can specify the lower left 47 | #' and top-right points of a bounding box, which will automatically be converted 48 | #' to tile-coordinates when you use \code{\link{mz_vector_tiles}} 49 | #' \item \code{\link{mz_bbox}}: This is a generic function which will return 50 | #' the bounding box of any Mapzen object. In this way, you can request vector 51 | #' tiles for a region defined as the bounding box of an existing object. 52 | #' } 53 | #' 54 | #' @section Data types and conversion: 55 | #' Objects returned by rmapzen can be converted to 56 | #' simple features (sf) via the generic function 57 | #' \code{\link{as_sf}}. Search 58 | #' and Isochrone objects can additionally be converted to ordinary data.frames 59 | #' via \code{as.data.frame}. 60 | #' 61 | #' @seealso 62 | #' \itemize{ 63 | #' \item contains detailed examples 64 | #' \item 'Mapzen' documentation 65 | #' } 66 | #' 67 | "_PACKAGE" 68 | -------------------------------------------------------------------------------- /R/string-array.R: -------------------------------------------------------------------------------- 1 | #' @import assertthat 2 | string_array <- function(strings) { 3 | assert_that(is.character(strings)) 4 | paste(unique(strings), collapse = ",") 5 | } 6 | -------------------------------------------------------------------------------- /R/structured-search.R: -------------------------------------------------------------------------------- 1 | #' Structured search 2 | #' 3 | #' \code{\link{mz_search}} allows you to search using an unstructured string of 4 | #' text, but if your address data has more structure (eg separate columns for 5 | #' address, city, state, zip), then using the structured search service may 6 | #' provide more precision. For more information, see 7 | #' \url{https://github.com/pelias/documentation}. Note that 8 | #' all of the arguments are optional, but at least one of them must be non-NULL. 9 | #' Furthermore, \code{postalcode} can not be used by itself. 10 | #' 11 | #' @param address Can be a numbered street address or just the name of the street 12 | #' @param neighbourhood Neighborhood name (eg "Notting Hill" in London) 13 | #' @param borough eg "Manhattan" 14 | #' @param locality The city (eg "Oakland") 15 | #' @param county The county 16 | #' @param region States in the case of US/Canada, or state-like 17 | #' administrative division in other countries 18 | #' @param postalcode AKA the zip code. Can not be used alone, must have at least 19 | #' one other argument 20 | #' @param country The country - Can be the full name or the abbreviation from 21 | #' \code{\link{mz_countries}} 22 | #' @param api_key Your Mapzen API key. The default is to look for the key within 23 | #' the provider information that was set up with `mz_set_host`. 24 | #' @param ... Any of the parameters, other than "text", that appear in 25 | #' \code{\link{mz_search}}, can appear here, for example \code{size}, 26 | #' \code{boundary.country}, etc. 27 | #' 28 | #' @seealso \code{\link{mz_search}} 29 | #' @export 30 | mz_structured_search <- function( 31 | address = NULL, 32 | neighbourhood = NULL, 33 | borough = NULL, 34 | locality = NULL, 35 | county = NULL, 36 | region = NULL, 37 | postalcode = NULL, 38 | country = NULL, api_key = NULL, ... 39 | ) 40 | { 41 | url <- build_structured_search_url( 42 | address = address, 43 | neighbourhood = neighbourhood, 44 | borough = borough, 45 | locality = locality, 46 | county = county, 47 | region = region, 48 | postalcode = postalcode, 49 | country = country, 50 | api_key = api_key, 51 | ... 52 | ) 53 | 54 | search_get(url) 55 | } 56 | 57 | 58 | #' @import assertthat 59 | build_structured_search_url <- function( 60 | address = NULL, 61 | neighbourhood = NULL, 62 | borough = NULL, 63 | locality = NULL, 64 | county = NULL, 65 | region = NULL, 66 | postalcode = NULL, 67 | country = NULL, api_key = NULL, ... 68 | ) { 69 | assert_that( 70 | is.null(address) || is.string(address), 71 | is.null(neighbourhood) || is.string(neighbourhood), 72 | is.null(borough) || is.string(borough), 73 | is.null(locality) || is.string(locality), 74 | is.null(county) || is.string(county), 75 | is.null(region) || is.string(region), 76 | is.null(address) || is.string(address) 77 | ) 78 | 79 | query <- c( 80 | address = address, 81 | neighbourhood = neighbourhood, 82 | borough = borough, 83 | locality = locality, 84 | county = county, 85 | region = region, 86 | country = country 87 | ) 88 | 89 | if (length(query) <= 0L) 90 | stop("Structured search requires at least one of the following:\n", 91 | "(can additionally include postalcode)\n", 92 | " address\n", 93 | " neighbourhood\n", 94 | " borough\n", 95 | " locality\n", 96 | " county\n", 97 | " region\n", 98 | " country") 99 | 100 | additional_params <- search_query_parameters(...) 101 | query <- c(list(api_key = api_key), query, additional_params) 102 | if (!is.null(postalcode)) query <- c(query, postalcode = postalcode) 103 | do.call(search_url, c(endpoint = "search/structured", query)) 104 | } 105 | -------------------------------------------------------------------------------- /R/tidy.R: -------------------------------------------------------------------------------- 1 | #' @export 2 | as.data.frame.mapzen_geo_list <- function(x, ...) { 3 | if (length(x$features) == 0L) 4 | stop("Cannot convert to data.frame: no data") 5 | coords <- mz_coordinates(x) 6 | rest <- dplyr::bind_rows( 7 | lapply(x$features, 8 | function(feature) tibble::as_tibble(feature$properties)) 9 | ) 10 | dplyr::bind_cols(rest, coords) 11 | } 12 | 13 | tidyr_new_interface <- function() { 14 | utils::packageVersion("tidyr") > "0.8.99" 15 | } 16 | 17 | #' @export 18 | as.data.frame.mapzen_isochrone_list <- function(x, ...) { 19 | if (length(x$features) == 0L) 20 | stop("Cannot convert to data.frame: empty layer") 21 | coords <- function(feature) 22 | purrr::map2_df( 23 | feature$geometry$coordinates, 24 | seq_along(feature$geometry$coordinates), 25 | ~tibble::tibble(lon = .x[[1]], lat = .x[[2]], 26 | order = .y) 27 | ) 28 | 29 | res <- tibble::tibble( 30 | contours = purrr::map( 31 | x$features, 32 | ~tibble::as_tibble( 33 | .$properties 34 | ) 35 | ), 36 | coordinates = purrr::map( 37 | x$features, 38 | coords 39 | ) 40 | ) 41 | if (tidyr_new_interface()) { 42 | res <- tidyr::unnest(res, cols = tidyr::one_of("contours")) 43 | return(tidyr::unnest(res, cols = tidyr::one_of("coordinates"))) 44 | } else { 45 | res <- tidyr::unnest_(res, "contours") 46 | return(tidyr::unnest(res)) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /R/unwrap.R: -------------------------------------------------------------------------------- 1 | #' @import assertthat 2 | unwrap <- function(obj, objname, components) { 3 | assert_that(has_components(obj, components)) 4 | 5 | lengths <- vapply(obj, length, FUN.VALUE = integer(1)) 6 | if (any(lengths != 1L)) 7 | stop("The following components are invalid for ", objname, "\n", 8 | paste(names(obj[lengths != 1L]), collapse = ", "), sep = "") 9 | 10 | names(obj) <- paste0(objname, ".", names(obj)) 11 | as.list(obj) 12 | } 13 | 14 | has_components <- function(obj, components) { 15 | setequal(names(obj), components) 16 | } 17 | 18 | #' @import assertthat 19 | on_failure(has_components) <- function(call, env) { 20 | paste0( 21 | env$objname, " requires the following components:\n", 22 | paste(env$components, collapse = ", "), 23 | " (you entered: ", paste(names(env$obj), collapse = ", "), ")" 24 | ) 25 | } 26 | -------------------------------------------------------------------------------- /R/usage-statistics.R: -------------------------------------------------------------------------------- 1 | usage_recorder <- function() { 2 | search_usage <- list( 3 | last_updated = NULL, 4 | remaining_day = NULL, 5 | remaining_second = NULL 6 | ) 7 | 8 | matrix_usage <- list( 9 | last_updated = NULL, 10 | remaining_day = NULL, 11 | remaining_second = NULL 12 | ) 13 | 14 | tile_usage <- list( 15 | last_updated = NULL, 16 | remaining_day = NULL, 17 | remaining_second = NULL 18 | ) 19 | 20 | update_search <- function(header) { 21 | if (!is.null(header$`x-cache`) && header$`x-cache` == "MISS") { 22 | search_usage$last_updated <<- header$date 23 | search_usage$remaining_day <<- header$`x-apiaxleproxy-qpd-left` 24 | search_usage$remaining_second <<- header$`x-apiaxleproxy-qps-left` 25 | } 26 | } 27 | 28 | update_matrix <- function(header) { 29 | matrix_usage$last_updated <<- header$date 30 | matrix_usage$remaining_day <<- header$`x-apiaxleproxy-qpd-left` 31 | matrix_usage$remaining_second <<- header$`x-apiaxleproxy-qps-left` 32 | } 33 | 34 | update_tile <- function(header) { 35 | if (!is.null(header$`x-apiaxleproxy-qpd-left`) && 36 | !is.null(header$`x-apiaxleproxy-qps-left`)) { 37 | tile_usage$last_updated <<- header$date 38 | tile_usage$remaining_day <<- header$`x-apiaxleproxy-qpd-left` 39 | tile_usage$remaining_second <<- header$`x-apiaxleproxy-qps-left` 40 | } 41 | } 42 | 43 | query <- function() { 44 | structure( 45 | list(search = search_usage, 46 | matrix = matrix_usage, 47 | tile = tile_usage), 48 | class = c("mz_usage_statistics", "list") 49 | ) 50 | } 51 | 52 | function(r) 53 | switch( 54 | r, 55 | "update_search" = function(hdr) update_search(hdr), 56 | "update_matrix" = function(hdr) update_matrix(hdr), 57 | "update_tile" = function(hdr) update_tile(hdr), 58 | "view" = function() query() 59 | ) 60 | } 61 | 62 | #' @export 63 | print.mz_usage_statistics <- function(x, ...) { 64 | search_usage <- x$search 65 | matrix_usage <- x$matrix 66 | tile_usage <- x$tile 67 | if (!is.null(search_usage$last_updated)) { 68 | cat("for the search endpoint:\n", 69 | " updated on: ", search_usage$last_updated, "\n", 70 | " remaining queries today: ", search_usage$remaining_day, "\n", 71 | " remaining queries this second: ", search_usage$remaining_second, "\n", 72 | sep = "") 73 | } else cat("No data for the search endpoint\n") 74 | 75 | if (!is.null(matrix_usage$last_updated)) { 76 | cat("for the matrix endpoint:\n", 77 | " updated on: ", matrix_usage$last_updated, "\n", 78 | " remaining queries today: ", matrix_usage$remaining_day, "\n", 79 | " remaining queries this second: ", matrix_usage$remaining_second, "\n", 80 | sep = "") 81 | } else cat("No data for the matrix endpoint\n") 82 | 83 | if (!is.null(tile_usage$last_updated)) { 84 | cat("for the tile (vector tiles) endpoint:\n", 85 | " updated on: ", tile_usage$last_updated, "\n", 86 | " remaining queries today: ", tile_usage$remaining_day, "\n", 87 | " remaining queries this second: ", tile_usage$remaining_second, "\n", 88 | sep = "") 89 | } else cat("No data for the tile (vector tiles) endpoint\n") 90 | 91 | } 92 | 93 | usage_statistics <- usage_recorder() 94 | 95 | #' Check usage statistics 96 | #' 97 | #' Prints out remaining queries for various time periods. \code{rmapzen} manages 98 | #' rate limiting for the per-second limits, but does not keep track of the daily 99 | #' limits. 100 | #' 101 | #' This function is populated from the headers of responses to various API requests. 102 | #' If no queries have been made, or if the only queries so far have hit cache servers, 103 | #' then no information will be available. 104 | #' 105 | #' @export 106 | mz_check_usage <- function() usage_statistics("view")() 107 | 108 | mz_update_usage <- function(header, type) { 109 | switch( 110 | type, 111 | search = usage_statistics("update_search")(header), 112 | matrix = usage_statistics("update_matrix")(header), 113 | tile = usage_statistics("update_tile")(header), 114 | stop("Unable to update usage statistics for ", type) 115 | ) 116 | } 117 | -------------------------------------------------------------------------------- /R/vector-tiles.R: -------------------------------------------------------------------------------- 1 | vector_get <- function(url, ...) { 2 | response <- vector_GET(httr::build_url(url), ...) 3 | vector_process(response) 4 | } 5 | 6 | vector_process <- function(response) { 7 | httr::stop_for_status(response) 8 | header <- httr::headers(response) 9 | mz_update_usage(header, "tile") 10 | txt <- httr::content(response, as = "text", encoding = "UTF-8") 11 | lst <- jsonlite::fromJSON(txt, simplifyVector = FALSE) 12 | structure( 13 | lst, 14 | header = header, 15 | class = "mapzen_vector_tiles" 16 | ) 17 | } 18 | 19 | #' Request vector tile data 20 | #' 21 | #' From \url{https://tilezen.readthedocs.io/en/latest/}: "Vector tiles are 22 | #' square-shaped collections of geographic data that contain the map feature 23 | #' geometry, such as lines and points." 24 | #' 25 | #' Multiple tiles are stitched together and returned as one object. Individual 26 | #' layers can be converted to \code{sf} or \code{sp}, making it possible to 27 | #' draw each layer with custom styles. 28 | #' 29 | #' @param tile_coordinates an \code{\link{mz_tile_coordinates}} object, or something 30 | #' that can be coerced to one (including the output of \code{\link{mz_bbox}}) 31 | #' @param ... Arguments passed on to \code{\link{as.mz_tile_coordinates}}. 32 | #' @param Origin optional, specify Origin URL in request header 33 | #' 34 | #' @return A list of tile layers (such as "water", "buildings", "roads", etc.). 35 | #' Each layer is an object of class \code{mapzen_vector_layer}, which can be converted 36 | #' to \code{sf} using \code{\link{as_sf}} 37 | #' 38 | #' @examples 39 | #' \dontrun{ 40 | #' # vector tile at x = 19293, y = 24641, and zoom level 16 41 | #' mz_vector_tiles(mz_tile_coordinates(19293, 24641, 16)) 42 | #' 43 | #' # multiple contiguous tiles will be stitched together 44 | #' # this returns the result of stitching together 4 tiles 45 | #' mz_vector_tiles(mz_tile_coordinates(19293:19294, 24641:24642, 16)) 46 | #' 47 | #' # can also use a bounding box: 48 | #' mz_vector_tiles(mz_rect(min_lon = -122.2856, 49 | #' min_lat = 37.73742, 50 | #' max_lon = -122.1749, 51 | #' max_lat = 37.84632)) 52 | #' 53 | #' # mz_bbox returns a bounding box for any Mapzen object 54 | #' mz_vector_tiles(mz_bbox(oakland_public)) 55 | #' 56 | #' # bounding boxes are automatically converted to tile coordinates, 57 | #' # with the zoom level based on the desired size in pixels of the final map 58 | #' mz_vector_tiles(mz_bbox(oakland_public), height = 750, width = 1000) 59 | #' } 60 | #' 61 | #' @seealso \code{\link{mz_tile_coordinates}} 62 | #' @export 63 | mz_vector_tiles <- function(tile_coordinates, ..., Origin = NULL) { 64 | tile_coordinates <- as.mz_tile_coordinates(tile_coordinates, ...) 65 | 66 | get_tile <- function(tile_coordinates) { 67 | url <- vector_url( 68 | x = tile_coordinates$x, 69 | y = tile_coordinates$y, 70 | z = tile_coordinates$z, 71 | layers = "all", 72 | format = "json" 73 | ) 74 | if (is.null(Origin)) vector_get(url) 75 | else vector_get(url, httr::add_headers(Origin = Origin)) 76 | } 77 | 78 | all_tiles <- lapply(tile_coordinates, get_tile) 79 | 80 | if (length(tile_coordinates) == 1L) { 81 | all_tiles <- all_tiles[[1]] 82 | 83 | all_tiles <- lapply(all_tiles, function(x) { 84 | class(x) <- c("mapzen_vector_layer", "list") 85 | x 86 | }) 87 | 88 | return(structure( 89 | all_tiles, 90 | class = c("mapzen_vector_tiles", "list") 91 | )) 92 | } 93 | 94 | structure( 95 | Reduce(stitch, all_tiles), 96 | class = c("mapzen_vector_tiles", "list") 97 | ) 98 | } 99 | 100 | # stitches together two vector tiles 101 | # it's on the caller to make sure they are actually adjacent 102 | stitch <- function(tile1, tile2) { 103 | if (is.null(attr(tile1, "header"))) header <- attr(tile2, "header") 104 | else header <- attr(tile1, "header") 105 | 106 | layers <- unique(c(names(tile1), names(tile2))) 107 | res <- lapply(layers, function(layer) { 108 | features1 <- tile1[[layer]] 109 | features2 <- tile2[[layer]] 110 | if (is.null(features1)) tp <- features2$type 111 | else if (is.null(features2)) tp <- features1$type 112 | else { 113 | stopifnot(features1$type == features2$type) 114 | tp <- features1$type 115 | } 116 | 117 | all_features <- c(features1$features, features2$features) 118 | structure( 119 | list(type = tp, 120 | features = all_features), 121 | class = c("mapzen_vector_layer", "list")) 122 | }) 123 | names(res) <- layers 124 | structure(res, header = header) 125 | } 126 | 127 | vector_GET <- httr::GET 128 | 129 | vector_path <- function(layers, x, y, z, format) { 130 | tilepath <- mz_get_host("tile")$path 131 | if (is.null(tilepath)) { 132 | res <- paste(layers, z, x, y, sep = "/") 133 | } else { 134 | res <- paste(tilepath, layers, z, x, y, sep = "/") 135 | } 136 | paste(res, format, sep = ".") 137 | } 138 | 139 | vector_url <- function(x, y, z, layers = "all", format = "json", api_key = mz_key(which = "tile")) { 140 | structure( 141 | list( 142 | scheme = mz_get_host("tile")$scheme, 143 | hostname = mz_get_host("tile")$hostname, 144 | path = vector_path(layers, x, y, z, format), 145 | query = list( 146 | api_key = api_key 147 | ) 148 | ), 149 | class = "url" 150 | ) 151 | } 152 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | .onLoad <- function(libname, pkgname) { 2 | # rmapzen_default_options <- list( 3 | # RMAPZEN_MATRIX_HOST = "matrix.mapzen.com", 4 | # RMAPZEN_SEARCH_HOST = "search.mapzen.com", 5 | # RMAPZEN_TILE_HOST = "tile.mapzen.com" 6 | # ) 7 | # op <- options() 8 | # toset <- !(names(rmapzen_default_options) %in% names(op)) 9 | # if(any(toset)) options(rmapzen_default_options[toset]) 10 | 11 | invisible() 12 | } 13 | 14 | -------------------------------------------------------------------------------- /README.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: rmapzen 3 | output: 4 | github_document 5 | --- 6 | 7 | 8 | ```{r, echo = FALSE} 9 | knitr::opts_chunk$set( 10 | collapse = TRUE, 11 | comment = "#>", 12 | fig.path = "README-" 13 | ) 14 | ``` 15 | 16 | ## Introduction 17 | 18 | NOTE: [Mapzen has shut down](https://www.mapzen.com/blog/shutdown/). However, the rmapzen package can be used with [other PELIAS providers](https://www.mapzen.com/blog/migration/). The specific hosting service can be set up with `mz_set_host`. For known providers, `rmapzen` includes pre-configured API set up functions: 19 | 20 | - `mz_set_search_host_geocode.earth` to set up [geocode.earth](https://geocode.earth/) as a search (includes geocoding, autocomplete, etc) provider 21 | - `mz_set_search_host_nyc_geosearch()` to set up [GeoSearch from NYC Planning Labs](https://geosearch.planninglabs.nyc/) (currently in beta) as a search provider. 22 | - `mz_set_tile_host_nextzen` to set up [Nextzen](https://www.nextzen.org/) as a vector tile provider 23 | 24 | If you know of an API that uses PELIAS that is not included here, [let me know](https://github.com/tarakc02/rmapzen/issues/new). 25 | 26 | ----------------------------------- 27 | 28 | `rmapzen` is a client for the Mapzen API. For an introduction, detailed examples, and installation instructions, see: [https://tarakc02.github.io/rmapzen/](https://tarakc02.github.io/rmapzen/). The package is available [on CRAN](https://cran.r-project.org/package=rmapzen), to install: 29 | 30 | ```{r, eval = FALSE} 31 | install.packages("rmapzen") 32 | ``` 33 | 34 | For more information about the Mapzen API, see [https://www.mapzen.com/documentation/](https://www.mapzen.com/documentation/). 35 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | rmapzen 2 | ================ 3 | 4 | 5 | 6 | ## Introduction 7 | 8 | NOTE: [Mapzen has shut down](https://www.mapzen.com/blog/shutdown/). 9 | However, the rmapzen package can be used with [other PELIAS 10 | providers](https://www.mapzen.com/blog/migration/). The specific hosting 11 | service can be set up with `mz_set_host`. For known providers, `rmapzen` 12 | includes pre-configured API set up functions: 13 | 14 | - `mz_set_search_host_geocode.earth` to set up 15 | [geocode.earth](https://geocode.earth/) as a search (includes 16 | geocoding, autocomplete, etc) provider 17 | - `mz_set_search_host_nyc_geosearch()` to set up [GeoSearch from NYC 18 | Planning Labs](https://geosearch.planninglabs.nyc/) (currently in 19 | beta) as a search provider. 20 | - `mz_set_tile_host_nextzen` to set up 21 | [Nextzen](https://www.nextzen.org/) as a vector tile provider 22 | 23 | If you know of an API that uses PELIAS that is not included here, [let 24 | me know](https://github.com/tarakc02/rmapzen/issues/new). 25 | 26 | ------------------------------------------------------------------------ 27 | 28 | `rmapzen` is a client for the Mapzen API. For an introduction, detailed 29 | examples, and installation instructions, see: 30 | . The package is available [on 31 | CRAN](https://cran.r-project.org/package=rmapzen), to install: 32 | 33 | ``` r 34 | install.packages("rmapzen") 35 | ``` 36 | 37 | For more information about the Mapzen API, see 38 | . 39 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | This is a resubmission, I have added local files generated by automated reverse 2 | dependency checks, which were causing nonstandard directory/file NOTEs, to the 3 | .Rbuildignore and confirmed that the project builds without any NOTEs. 4 | 5 | ## Test environments 6 | * local Mac OS Sonoma 14.0.0, R 4.3.1 7 | * Ubuntu 20.04.1 LTS, R-release, GCC (via R-hub) 8 | * Fedora Linux, R-devel, clang, gfortran (via R-hub) 9 | * Windows Server 2022, R-devel (4.4.0 Under development) (via win-builder) 10 | 11 | ## R CMD check results 12 | 13 | 0 errors | 0 warnings | 0 notes 14 | 15 | ## Reverse dependencies 16 | 17 | There are no reverse dependencies. 18 | -------------------------------------------------------------------------------- /data/ca_tiles.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/data/ca_tiles.rda -------------------------------------------------------------------------------- /data/marina_walks.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/data/marina_walks.rda -------------------------------------------------------------------------------- /data/marina_walks_polygons.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/data/marina_walks_polygons.rda -------------------------------------------------------------------------------- /data/oakland_public.rda: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/data/oakland_public.rda -------------------------------------------------------------------------------- /fig/mz-countries.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/fig/mz-countries.png -------------------------------------------------------------------------------- /index.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "rmapzen: a Mapzen API client for R" 3 | output: 4 | html_document: 5 | self_contained: no 6 | theme: flatly 7 | toc: yes 8 | toc_float: 9 | collapsed: no 10 | smooth_scroll: yes 11 | --- 12 | [![Travis-CI Build Status](https://travis-ci.org/tarakc02/rmapzen.svg?branch=master)](https://travis-ci.org/tarakc02/rmapzen) 13 | [![Coverage Status](https://img.shields.io/codecov/c/github/tarakc02/rmapzen/master.svg)](https://codecov.io/github/tarakc02/rmapzen?branch=master) 14 | 15 | ## Introduction 16 | 17 | `rmapzen` is a client for any implementation of the Mapzen API. Though Mapzen itself has [gone out of business](https://www.mapzen.com/blog/shutdown/), `rmapzen` can be set up to work with any provider who hosts Mapzen's open-source software, including [geocode.earth](https://geocode.earth/), [Nextzen](https://www.nextzen.org/), and [NYC GeoSearch from NYC Planning Labs](https://geosearch.planninglabs.nyc/). For more information, see [https://www.mapzen.com/documentation/](https://www.mapzen.com/documentation/). The project is [available on github](https://github.com/tarakc02/rmapzen) as well as [CRAN](https://cran.r-project.org/package=rmapzen). 18 | 19 | `rmapzen` provides access to the following Mapzen API services: 20 | 21 | - [Search](https://github.com/pelias/documentation): Structured and unstructured search and geocoding, reverse geocoding, and autocomplete. 22 | - [Vector Tiles](https://tilezen.readthedocs.io/en/latest/): Basemap vector data. 23 | - [Isochrone](https://valhalla.readthedocs.io/en/latest/): Calculation of areas reachable from a specified locations. 24 | 25 | ## Installation and Set-up 26 | 27 | `rmapzen` is available [on CRAN](https://cran.r-project.org/package=rmapzen). To install: 28 | 29 | ```{r, eval = FALSE} 30 | install.packages("rmapzen") 31 | ``` 32 | 33 | You'll also need to set up options specific to the API provider you end up using. `rmapzen` works with API providers who implement the Mapzen API. In order to specify provider information (such as URL and API key), use `mz_set_host`. There are custom set-up functions for the following providers: 34 | 35 | - [geocode.earth](https://geocode.earth/), for search services. Use the function `mz_set_search_host_geocode.earth` 36 | - [Nextzen](https://www.nextzen.org/), for vector tiles. Use the function `mz_set_tile_host_nextzen`. 37 | - [NYC GeoSearch](https://geosearch.planninglabs.nyc/), for search services using New York City's Property Address Directory. Use `mz_set_search_host_nyc_geosearch`. 38 | 39 | As of this writing, there are no public providers offering the Mapzen isochrone service, but `mz_isochrone` and related functions are available. If you know of a provider not listed here, use the more general `mz_set_host` function, and [submit an issue](https://github.com/tarakc02/rmapzen/issues) so we can create a custom set up function for future users. 40 | 41 | ## Search 42 | 43 | All of the services in [Mapzen search](https://github.com/pelias/documentation) have been implemented. Search functions: 44 | 45 | * `mz_search` 46 | * `mz_reverse_geocode` 47 | * `mz_autocomplete` 48 | * `mz_place` 49 | * `mz_structured_search` ([what's this?](https://github.com/pelias/documentation/blob/master/structured-geocoding.md)) 50 | 51 | For example, to search for public library branches in Oakland, CA: 52 | 53 | ```{r loadmapzen, warning = FALSE} 54 | # load rmapzen and run provider set-up functions 55 | library(rmapzen) 56 | mz_set_tile_host_nextzen() 57 | mz_set_search_host_geocode.earth() 58 | ``` 59 | 60 | ```{r ex-search-2, eval = FALSE} 61 | oakland_public <- mz_search("Oakland Public Library Branch", 62 | size = 5, 63 | focus.point = mz_geocode("Oakland, CA"), 64 | boundary.country = mz_countries$USA) 65 | ``` 66 | ```{r ex-search-2a} 67 | oakland_public 68 | ``` 69 | 70 | Search can, optionally, be constrained to a particular country, data layer, boundary rectangle, or boundary circle. Furthermore, search can prioritize results near a given "focus" point. See `?mz_search`. 71 | 72 | Additionally, `mz_geocode` is a convenient function to geocode an address, utilizing the more general `mz_search` function. 73 | 74 | ```{r ex-geocode, cache=FALSE} 75 | mz_geocode("UC Berkeley, Berkeley, CA") 76 | ``` 77 | 78 | ## Vector tile service 79 | 80 | `rmapzen` provides an interface to Mapzen's [vector tiles service](https://tilezen.readthedocs.io/en/latest/). Tile requests can be specified using the x, y, zoom coordinates of the tile service, as well as with a lat/long bounding box. For instance, continuing the previous example: 81 | 82 | ```{r vector-tile-example, cache = TRUE, message = FALSE, warning = FALSE, dpi = 300} 83 | library(tidyverse) 84 | library(sf) 85 | 86 | # mz_bbox is a generic that returns the bounding box of an object 87 | oakland_tiles <- mz_vector_tiles(mz_bbox(oakland_public)) 88 | 89 | # vector tiles return all layers (roads, water, buildings, etc) in a list 90 | roads <- as_sf(oakland_tiles$roads) %>% 91 | filter(kind != "ferry") 92 | water <- as_sf(oakland_tiles$water) 93 | 94 | labels <- as.data.frame(oakland_public) %>% 95 | mutate(name = str_replace_all( 96 | name, 97 | "(Oakland Public Library)|(Branch)", "")) 98 | 99 | # make a quick static map that includes roads and oceans as reference 100 | ggplot() + 101 | geom_sf(data = water, 102 | fill = "lightblue", colour = NA) + 103 | geom_sf(data = roads, 104 | size = .2, colour = "gray30") + 105 | geom_sf(data = as_sf(oakland_public), 106 | colour = "black", size = 1) + 107 | ggrepel::geom_label_repel( 108 | data = labels, 109 | aes(x = lon, y = lat, label = name), size = 3, 110 | family = "Roboto Condensed", label.padding = unit(.1, "lines"), 111 | alpha = .7) + 112 | theme_void() + 113 | theme(panel.grid.major = element_line(size = 0)) 114 | ``` 115 | 116 | ## `sf` conversion 117 | 118 | As some of the above examples illustrate, any object returned by a Mapzen service can be converted to the appropriate `sf` object using the generic `as_sf`, for easy interoperability with other packages. You can also convert most objects directly to data frames, allowing for use within tidy pipelines: 119 | 120 | ```{r ex-tidy, warning = FALSE, message = FALSE} 121 | require(dplyr) 122 | as.data.frame(oakland_public) %>% 123 | select(name, confidence, region, locality, neighbourhood) 124 | ``` 125 | 126 | ## Accessor methods 127 | 128 | Currently, the following methods are available to pull out commonly used 129 | pieces of a response: 130 | 131 | * `mz_coordinates` (only available for search results): extracts lat/lon coordinates from search results, and returns them as a `data.frame`. 132 | * `mz_bbox`: returns the bounding box of an object as a `data.frame` with columns `min_lon`, `min_lat`, `max_lon`, and `max_lat`. 133 | 134 | ```{r ex-accessors, cache = TRUE} 135 | mz_coordinates(oakland_public) 136 | mz_bbox(oakland_tiles) 137 | ``` 138 | 139 | ## Convenience features 140 | 141 | Several of the search functions take, optionally, the arguments `layers`, `sources`, and `boundary.country` (the latter requires [ISO-3166](https://en.wikipedia.org/wiki/ISO_3166) codes). If you're using an IDE with auto-complete, the objects `mz_layers`, `mz_sources`, and `mz_countries` should make it easier to get the correct codes. 142 | 143 | ![Easy lookup for ISO-3166 codes](fig/mz-countries.png) 144 | 145 | Similarly, argument constructors are available for easier specifications of isochrone and search requests. 146 | 147 | * `mz_costing` 148 | * `mz_costing_options` 149 | * `mz_location` 150 | * `mz_contours` 151 | * `mz_date_time` 152 | 153 | ## Related projects 154 | 155 | The package does not yet support [other Mapzen API services](https://www.mapzen.com/documentation/). But do check out these related R packages: 156 | 157 | * [elevatr](https://github.com/jhollist/elevatr) for accessing elevation data, including Mapzen Terrain and Elevation 158 | * [postr](https://github.com/Ironholds/poster) for address parsing and normalization using the [libpostal](https://github.com/openvenues/libpostal) library 159 | -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/Lato.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/Lato.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/LatoBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/LatoBold.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/LatoItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/LatoItalic.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/NewsCycle.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/NewsCycle.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/NewsCycleBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/NewsCycleBold.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/OpenSans.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/OpenSans.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/OpenSansBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/OpenSansBold.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/OpenSansBoldItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/OpenSansBoldItalic.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/OpenSansItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/OpenSansItalic.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/OpenSansLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/OpenSansLight.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/OpenSansLightItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/OpenSansLightItalic.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/Raleway.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/Raleway.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/RalewayBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/RalewayBold.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/Roboto.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/Roboto.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/RobotoBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/RobotoBold.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/RobotoLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/RobotoLight.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/RobotoMedium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/RobotoMedium.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/SourceSansPro.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/SourceSansPro.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/SourceSansProBold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/SourceSansProBold.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/SourceSansProItalic.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/SourceSansProItalic.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/SourceSansProLight.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/SourceSansProLight.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/css/fonts/Ubuntu.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/css/fonts/Ubuntu.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/bootstrap-3.3.5/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/js/npm.js: -------------------------------------------------------------------------------- 1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment. 2 | require('../../js/transition.js') 3 | require('../../js/alert.js') 4 | require('../../js/button.js') 5 | require('../../js/carousel.js') 6 | require('../../js/collapse.js') 7 | require('../../js/dropdown.js') 8 | require('../../js/modal.js') 9 | require('../../js/tooltip.js') 10 | require('../../js/popover.js') 11 | require('../../js/scrollspy.js') 12 | require('../../js/tab.js') 13 | require('../../js/affix.js') -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/shim/html5shiv.min.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @preserve HTML5 Shiv 3.7.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed 3 | */ 4 | // Only run this code in IE 8 5 | if (!!window.navigator.userAgent.match("MSIE 8")) { 6 | !function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.2",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b)}(this,document); 7 | }; 8 | -------------------------------------------------------------------------------- /index_files/bootstrap-3.3.5/shim/respond.min.js: -------------------------------------------------------------------------------- 1 | /*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl 2 | * Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT 3 | * */ 4 | 5 | // Only run this code in IE 8 6 | if (!!window.navigator.userAgent.match("MSIE 8")) { 7 | !function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='­',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b :first-child"); 5 | var i, h, a; 6 | for (i = 0; i < hs.length; i++) { 7 | h = hs[i]; 8 | if (!/^h[1-6]$/i.test(h.tagName)) continue; // it should be a header h1-h6 9 | a = h.attributes; 10 | while (a.length > 0) h.removeAttribute(a[0].name); 11 | } 12 | }); 13 | -------------------------------------------------------------------------------- /index_files/highlightjs-9.12.0/default.css: -------------------------------------------------------------------------------- 1 | .hljs-literal { 2 | color: #990073; 3 | } 4 | 5 | .hljs-number { 6 | color: #099; 7 | } 8 | 9 | .hljs-comment { 10 | color: #998; 11 | font-style: italic; 12 | } 13 | 14 | .hljs-keyword { 15 | color: #900; 16 | font-weight: bold; 17 | } 18 | 19 | .hljs-string { 20 | color: #d14; 21 | } 22 | -------------------------------------------------------------------------------- /index_files/highlightjs-9.12.0/textmate.css: -------------------------------------------------------------------------------- 1 | .hljs-literal { 2 | color: rgb(88, 72, 246); 3 | } 4 | 5 | .hljs-number { 6 | color: rgb(0, 0, 205); 7 | } 8 | 9 | .hljs-comment { 10 | color: rgb(76, 136, 107); 11 | } 12 | 13 | .hljs-keyword { 14 | color: rgb(0, 0, 255); 15 | } 16 | 17 | .hljs-string { 18 | color: rgb(3, 106, 7); 19 | } 20 | -------------------------------------------------------------------------------- /index_files/jqueryui-1.11.4/README: -------------------------------------------------------------------------------- 1 | This a jQuery UI custom build, downloaded from: 2 | http://jqueryui.com/download/#!version=1.11.4&components=1111111111110111111111111111111111111 3 | 4 | It includes all components except the datepicker, because it conflicts with 5 | bootstrap-datepicker that is packaged with Shiny. 6 | 7 | The copy of jQuery that is bundled with the download, under external/, is not 8 | included because Shiny already has its own copy of jQuery. 9 | -------------------------------------------------------------------------------- /index_files/jqueryui-1.11.4/images/ui-icons_444444_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/jqueryui-1.11.4/images/ui-icons_444444_256x240.png -------------------------------------------------------------------------------- /index_files/jqueryui-1.11.4/images/ui-icons_555555_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/jqueryui-1.11.4/images/ui-icons_555555_256x240.png -------------------------------------------------------------------------------- /index_files/jqueryui-1.11.4/images/ui-icons_777620_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/jqueryui-1.11.4/images/ui-icons_777620_256x240.png -------------------------------------------------------------------------------- /index_files/jqueryui-1.11.4/images/ui-icons_777777_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/jqueryui-1.11.4/images/ui-icons_777777_256x240.png -------------------------------------------------------------------------------- /index_files/jqueryui-1.11.4/images/ui-icons_cc0000_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/jqueryui-1.11.4/images/ui-icons_cc0000_256x240.png -------------------------------------------------------------------------------- /index_files/jqueryui-1.11.4/images/ui-icons_ffffff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tarakc02/rmapzen/12b51b8cef121703ecde6d03512483c02d32305e/index_files/jqueryui-1.11.4/images/ui-icons_ffffff_256x240.png -------------------------------------------------------------------------------- /index_files/jqueryui-1.11.4/jquery-ui.structure.min.css: -------------------------------------------------------------------------------- 1 | /*! jQuery UI - v1.11.4 - 2016-01-05 2 | * http://jqueryui.com 3 | * Copyright jQuery Foundation and other contributors; Licensed MIT */ 4 | 5 | .ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-draggable-handle{-ms-touch-action:none;touch-action:none}.ui-resizable{position:relative}.ui-resizable-handle{position:absolute;font-size:0.1px;display:block;-ms-touch-action:none;touch-action:none}.ui-resizable-disabled .ui-resizable-handle,.ui-resizable-autohide .ui-resizable-handle{display:none}.ui-resizable-n{cursor:n-resize;height:7px;width:100%;top:-5px;left:0}.ui-resizable-s{cursor:s-resize;height:7px;width:100%;bottom:-5px;left:0}.ui-resizable-e{cursor:e-resize;width:7px;right:-5px;top:0;height:100%}.ui-resizable-w{cursor:w-resize;width:7px;left:-5px;top:0;height:100%}.ui-resizable-se{cursor:se-resize;width:12px;height:12px;right:1px;bottom:1px}.ui-resizable-sw{cursor:sw-resize;width:9px;height:9px;left:-5px;bottom:-5px}.ui-resizable-nw{cursor:nw-resize;width:9px;height:9px;left:-5px;top:-5px}.ui-resizable-ne{cursor:ne-resize;width:9px;height:9px;right:-5px;top:-5px}.ui-selectable{-ms-touch-action:none;touch-action:none}.ui-selectable-helper{position:absolute;z-index:100;border:1px dotted black}.ui-sortable-handle{-ms-touch-action:none;touch-action:none}.ui-accordion .ui-accordion-header{display:block;cursor:pointer;position:relative;margin:2px 0 0 0;padding:.5em .5em .5em .7em;min-height:0;font-size:100%}.ui-accordion .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-icons .ui-accordion-icons{padding-left:2.2em}.ui-accordion .ui-accordion-header .ui-accordion-header-icon{position:absolute;left:.5em;top:50%;margin-top:-8px}.ui-accordion .ui-accordion-content{padding:1em 2.2em;border-top:0;overflow:auto}.ui-autocomplete{position:absolute;top:0;left:0;cursor:default}.ui-button{display:inline-block;position:relative;padding:0;line-height:normal;margin-right:.1em;cursor:pointer;vertical-align:middle;text-align:center;overflow:visible}.ui-button,.ui-button:link,.ui-button:visited,.ui-button:hover,.ui-button:active{text-decoration:none}.ui-button-icon-only{width:2.2em}button.ui-button-icon-only{width:2.4em}.ui-button-icons-only{width:3.4em}button.ui-button-icons-only{width:3.7em}.ui-button .ui-button-text{display:block;line-height:normal}.ui-button-text-only .ui-button-text{padding:.4em 1em}.ui-button-icon-only .ui-button-text,.ui-button-icons-only .ui-button-text{padding:.4em;text-indent:-9999999px}.ui-button-text-icon-primary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 1em .4em 2.1em}.ui-button-text-icon-secondary .ui-button-text,.ui-button-text-icons .ui-button-text{padding:.4em 2.1em .4em 1em}.ui-button-text-icons .ui-button-text{padding-left:2.1em;padding-right:2.1em}input.ui-button{padding:.4em 1em}.ui-button-icon-only .ui-icon,.ui-button-text-icon-primary .ui-icon,.ui-button-text-icon-secondary .ui-icon,.ui-button-text-icons .ui-icon,.ui-button-icons-only .ui-icon{position:absolute;top:50%;margin-top:-8px}.ui-button-icon-only .ui-icon{left:50%;margin-left:-8px}.ui-button-text-icon-primary .ui-button-icon-primary,.ui-button-text-icons .ui-button-icon-primary,.ui-button-icons-only .ui-button-icon-primary{left:.5em}.ui-button-text-icon-secondary .ui-button-icon-secondary,.ui-button-text-icons .ui-button-icon-secondary,.ui-button-icons-only .ui-button-icon-secondary{right:.5em}.ui-buttonset{margin-right:7px}.ui-buttonset .ui-button{margin-left:0;margin-right:-.3em}input.ui-button::-moz-focus-inner,button.ui-button::-moz-focus-inner{border:0;padding:0}.ui-dialog{overflow:hidden;position:absolute;top:0;left:0;padding:.2em;outline:0}.ui-dialog .ui-dialog-titlebar{padding:.4em 1em;position:relative}.ui-dialog .ui-dialog-title{float:left;margin:.1em 0;white-space:nowrap;width:90%;overflow:hidden;text-overflow:ellipsis}.ui-dialog .ui-dialog-titlebar-close{position:absolute;right:.3em;top:50%;width:20px;margin:-10px 0 0 0;padding:1px;height:20px}.ui-dialog .ui-dialog-content{position:relative;border:0;padding:.5em 1em;background:none;overflow:auto}.ui-dialog .ui-dialog-buttonpane{text-align:left;border-width:1px 0 0 0;background-image:none;margin-top:.5em;padding:.3em 1em .5em .4em}.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset{float:right}.ui-dialog .ui-dialog-buttonpane button{margin:.5em .4em .5em 0;cursor:pointer}.ui-dialog .ui-resizable-se{width:12px;height:12px;right:-5px;bottom:-5px;background-position:16px 16px}.ui-draggable .ui-dialog-titlebar{cursor:move}.ui-menu{list-style:none;padding:0;margin:0;display:block;outline:none}.ui-menu .ui-menu{position:absolute}.ui-menu .ui-menu-item{position:relative;margin:0;padding:3px 1em 3px .4em;cursor:pointer;min-height:0;list-style-image:url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7")}.ui-menu .ui-menu-divider{margin:5px 0;height:0;font-size:0;line-height:0;border-width:1px 0 0 0}.ui-menu .ui-state-focus,.ui-menu .ui-state-active{margin:-1px}.ui-menu-icons{position:relative}.ui-menu-icons .ui-menu-item{padding-left:2em}.ui-menu .ui-icon{position:absolute;top:0;bottom:0;left:.2em;margin:auto 0}.ui-menu .ui-menu-icon{left:auto;right:0}.ui-progressbar{height:2em;text-align:left;overflow:hidden}.ui-progressbar .ui-progressbar-value{margin:-1px;height:100%}.ui-progressbar .ui-progressbar-overlay{background:url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");height:100%;filter:alpha(opacity=25);opacity:0.25}.ui-progressbar-indeterminate .ui-progressbar-value{background-image:none}.ui-selectmenu-menu{padding:0;margin:0;position:absolute;top:0;left:0;display:none}.ui-selectmenu-menu .ui-menu{overflow:auto;overflow-x:hidden;padding-bottom:1px}.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup{font-size:1em;font-weight:bold;line-height:1.5;padding:2px 0.4em;margin:0.5em 0 0 0;height:auto;border:0}.ui-selectmenu-open{display:block}.ui-selectmenu-button{display:inline-block;overflow:hidden;position:relative;text-decoration:none;cursor:pointer}.ui-selectmenu-button span.ui-icon{right:0.5em;left:auto;margin-top:-8px;position:absolute;top:50%}.ui-selectmenu-button span.ui-selectmenu-text{text-align:left;padding:0.4em 2.1em 0.4em 1em;display:block;line-height:1.4;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default;-ms-touch-action:none;touch-action:none}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-spinner{position:relative;display:inline-block;overflow:hidden;padding:0;vertical-align:middle}.ui-spinner-input{border:none;background:none;color:inherit;padding:0;margin:.2em 0;vertical-align:middle;margin-left:.4em;margin-right:22px}.ui-spinner-button{width:16px;height:50%;font-size:.5em;padding:0;margin:0;text-align:center;position:absolute;cursor:default;display:block;overflow:hidden;right:0}.ui-spinner a.ui-spinner-button{border-top:none;border-bottom:none;border-right:none}.ui-spinner .ui-icon{position:absolute;margin-top:-8px;top:50%;left:0}.ui-spinner-up{top:0}.ui-spinner-down{bottom:0}.ui-spinner .ui-icon-triangle-1-s{background-position:-65px -16px}.ui-tabs{position:relative;padding:.2em}.ui-tabs .ui-tabs-nav{margin:0;padding:.2em .2em 0}.ui-tabs .ui-tabs-nav li{list-style:none;float:left;position:relative;top:0;margin:1px .2em 0 0;border-bottom-width:0;padding:0;white-space:nowrap}.ui-tabs .ui-tabs-nav .ui-tabs-anchor{float:left;padding:.5em 1em;text-decoration:none}.ui-tabs .ui-tabs-nav li.ui-tabs-active{margin-bottom:-1px;padding-bottom:1px}.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor{cursor:text}.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor{cursor:pointer}.ui-tabs .ui-tabs-panel{display:block;border-width:0;padding:1em 1.4em;background:none}.ui-tooltip{padding:8px;position:absolute;z-index:9999;max-width:300px;-webkit-box-shadow:0 0 5px #aaa;box-shadow:0 0 5px #aaa}body .ui-tooltip{border-width:2px} -------------------------------------------------------------------------------- /index_files/navigation-1.1/codefolding.js: -------------------------------------------------------------------------------- 1 | 2 | window.initializeCodeFolding = function(show) { 3 | 4 | // handlers for show-all and hide all 5 | $("#rmd-show-all-code").click(function() { 6 | $('div.r-code-collapse').each(function() { 7 | $(this).collapse('show'); 8 | }); 9 | }); 10 | $("#rmd-hide-all-code").click(function() { 11 | $('div.r-code-collapse').each(function() { 12 | $(this).collapse('hide'); 13 | }); 14 | }); 15 | 16 | // index for unique code element ids 17 | var currentIndex = 1; 18 | 19 | // select all R code blocks 20 | var rCodeBlocks = $('pre.r, pre.python, pre.bash, pre.sql, pre.cpp, pre.stan, pre.julia, pre.foldable'); 21 | rCodeBlocks.each(function() { 22 | 23 | // create a collapsable div to wrap the code in 24 | var div = $('
'); 25 | var showThis = (show || $(this).hasClass('fold-show')) && !$(this).hasClass('fold-hide'); 26 | var id = 'rcode-643E0F36' + currentIndex++; 27 | div.attr('id', id); 28 | $(this).before(div); 29 | $(this).detach().appendTo(div); 30 | 31 | // add a show code button right above 32 | var showCodeText = $('' + (showThis ? 'Hide' : 'Code') + ''); 33 | var showCodeButton = $(''); 34 | showCodeButton.append(showCodeText); 35 | showCodeButton 36 | .attr('data-toggle', 'collapse') 37 | .attr('data-target', '#' + id) 38 | .attr('aria-expanded', showThis) 39 | .attr('aria-controls', id); 40 | 41 | var buttonRow = $('
'); 42 | var buttonCol = $('
'); 43 | 44 | buttonCol.append(showCodeButton); 45 | buttonRow.append(buttonCol); 46 | 47 | div.before(buttonRow); 48 | 49 | // show the div if necessary 50 | if (showThis) div.collapse('show'); 51 | 52 | // update state of button on show/hide 53 | // * Change text 54 | // * add a class for intermediate states styling 55 | div.on('hide.bs.collapse', function () { 56 | showCodeText.text('Code'); 57 | showCodeButton.addClass('btn-collapsing'); 58 | }); 59 | div.on('hidden.bs.collapse', function () { 60 | showCodeButton.removeClass('btn-collapsing'); 61 | }); 62 | div.on('show.bs.collapse', function () { 63 | showCodeText.text('Hide'); 64 | showCodeButton.addClass('btn-expanding'); 65 | }); 66 | div.on('shown.bs.collapse', function () { 67 | showCodeButton.removeClass('btn-expanding'); 68 | }); 69 | 70 | }); 71 | 72 | } 73 | -------------------------------------------------------------------------------- /index_files/navigation-1.1/sourceembed.js: -------------------------------------------------------------------------------- 1 | 2 | window.initializeSourceEmbed = function(filename) { 3 | $("#rmd-download-source").click(function() { 4 | var src = $("#rmd-source-code").html(); 5 | var a = document.createElement('a'); 6 | a.href = "data:text/x-r-markdown;base64," + src; 7 | a.download = filename; 8 | document.body.appendChild(a); 9 | a.click(); 10 | document.body.removeChild(a); 11 | }); 12 | }; 13 | -------------------------------------------------------------------------------- /index_files/navigation-1.1/tabsets.js: -------------------------------------------------------------------------------- 1 | 2 | 3 | /** 4 | * jQuery Plugin: Sticky Tabs 5 | * 6 | * @author Aidan Lister 7 | * adapted by Ruben Arslan to activate parent tabs too 8 | * http://www.aidanlister.com/2014/03/persisting-the-tab-state-in-bootstrap/ 9 | */ 10 | (function($) { 11 | "use strict"; 12 | $.fn.rmarkdownStickyTabs = function() { 13 | var context = this; 14 | // Show the tab corresponding with the hash in the URL, or the first tab 15 | var showStuffFromHash = function() { 16 | var hash = window.location.hash; 17 | var selector = hash ? 'a[href="' + hash + '"]' : 'li.active > a'; 18 | var $selector = $(selector, context); 19 | if($selector.data('toggle') === "tab") { 20 | $selector.tab('show'); 21 | // walk up the ancestors of this element, show any hidden tabs 22 | $selector.parents('.section.tabset').each(function(i, elm) { 23 | var link = $('a[href="#' + $(elm).attr('id') + '"]'); 24 | if(link.data('toggle') === "tab") { 25 | link.tab("show"); 26 | } 27 | }); 28 | } 29 | }; 30 | 31 | 32 | // Set the correct tab when the page loads 33 | showStuffFromHash(context); 34 | 35 | // Set the correct tab when a user uses their back/forward button 36 | $(window).on('hashchange', function() { 37 | showStuffFromHash(context); 38 | }); 39 | 40 | // Change the URL when tabs are clicked 41 | $('a', context).on('click', function(e) { 42 | history.pushState(null, null, this.href); 43 | showStuffFromHash(context); 44 | }); 45 | 46 | return this; 47 | }; 48 | }(jQuery)); 49 | 50 | window.buildTabsets = function(tocID) { 51 | 52 | // build a tabset from a section div with the .tabset class 53 | function buildTabset(tabset) { 54 | 55 | // check for fade and pills options 56 | var fade = tabset.hasClass("tabset-fade"); 57 | var pills = tabset.hasClass("tabset-pills"); 58 | var navClass = pills ? "nav-pills" : "nav-tabs"; 59 | 60 | // determine the heading level of the tabset and tabs 61 | var match = tabset.attr('class').match(/level(\d) /); 62 | if (match === null) 63 | return; 64 | var tabsetLevel = Number(match[1]); 65 | var tabLevel = tabsetLevel + 1; 66 | 67 | // find all subheadings immediately below 68 | var tabs = tabset.find("div.section.level" + tabLevel); 69 | if (!tabs.length) 70 | return; 71 | 72 | // create tablist and tab-content elements 73 | var tabList = $(''); 74 | $(tabs[0]).before(tabList); 75 | var tabContent = $('
'); 76 | $(tabs[0]).before(tabContent); 77 | 78 | // build the tabset 79 | var activeTab = 0; 80 | tabs.each(function(i) { 81 | 82 | // get the tab div 83 | var tab = $(tabs[i]); 84 | 85 | // get the id then sanitize it for use with bootstrap tabs 86 | var id = tab.attr('id'); 87 | 88 | // see if this is marked as the active tab 89 | if (tab.hasClass('active')) 90 | activeTab = i; 91 | 92 | // remove any table of contents entries associated with 93 | // this ID (since we'll be removing the heading element) 94 | $("div#" + tocID + " li a[href='#" + id + "']").parent().remove(); 95 | 96 | // sanitize the id for use with bootstrap tabs 97 | id = id.replace(/[.\/?&!#<>]/g, '').replace(/\s/g, '_'); 98 | tab.attr('id', id); 99 | 100 | // get the heading element within it, grab it's text, then remove it 101 | var heading = tab.find('h' + tabLevel + ':first'); 102 | var headingText = heading.html(); 103 | heading.remove(); 104 | 105 | // build and append the tab list item 106 | var a = $('' + headingText + ''); 107 | a.attr('href', '#' + id); 108 | a.attr('aria-controls', id); 109 | var li = $('
  • '); 110 | li.append(a); 111 | tabList.append(li); 112 | 113 | // set it's attributes 114 | tab.attr('role', 'tabpanel'); 115 | tab.addClass('tab-pane'); 116 | tab.addClass('tabbed-pane'); 117 | if (fade) 118 | tab.addClass('fade'); 119 | 120 | // move it into the tab content div 121 | tab.detach().appendTo(tabContent); 122 | }); 123 | 124 | // set active tab 125 | $(tabList.children('li')[activeTab]).addClass('active'); 126 | var active = $(tabContent.children('div.section')[activeTab]); 127 | active.addClass('active'); 128 | if (fade) 129 | active.addClass('in'); 130 | 131 | if (tabset.hasClass("tabset-sticky")) 132 | tabset.rmarkdownStickyTabs(); 133 | } 134 | 135 | // convert section divs with the .tabset class to tabsets 136 | var tabsets = $("div.section.tabset"); 137 | tabsets.each(function(i) { 138 | buildTabset($(tabsets[i])); 139 | }); 140 | }; 141 | 142 | -------------------------------------------------------------------------------- /index_files/tocify-1.9.1/jquery.tocify.css: -------------------------------------------------------------------------------- 1 | /* 2 | * jquery.tocify.css 1.9.1 3 | * Author: @gregfranko 4 | */ 5 | 6 | /* The Table of Contents container element */ 7 | .tocify { 8 | width: 20%; 9 | max-height: 90%; 10 | overflow: auto; 11 | margin-left: 2%; 12 | position: fixed; 13 | border: 1px solid #ccc; 14 | border-radius: 6px; 15 | } 16 | 17 | /* The Table of Contents is composed of multiple nested unordered lists. These styles remove the default styling of an unordered list because it is ugly. */ 18 | .tocify ul, .tocify li { 19 | list-style: none; 20 | margin: 0; 21 | padding: 0; 22 | border: none; 23 | line-height: 30px; 24 | } 25 | 26 | /* Top level header elements */ 27 | .tocify-header { 28 | text-indent: 10px; 29 | } 30 | 31 | /* Top level subheader elements. These are the first nested items underneath a header element. */ 32 | .tocify-subheader { 33 | text-indent: 20px; 34 | display: none; 35 | } 36 | 37 | /* Makes the font smaller for all subheader elements. */ 38 | .tocify-subheader li { 39 | font-size: 12px; 40 | } 41 | 42 | /* Further indents second level subheader elements. */ 43 | .tocify-subheader .tocify-subheader { 44 | text-indent: 30px; 45 | } 46 | .tocify-subheader .tocify-subheader .tocify-subheader { 47 | text-indent: 40px; 48 | } 49 | .tocify-subheader .tocify-subheader .tocify-subheader .tocify-subheader { 50 | text-indent: 50px; 51 | } 52 | .tocify-subheader .tocify-subheader .tocify-subheader .tocify-subheader .tocify-subheader { 53 | text-indent: 60px; 54 | } 55 | 56 | /* Twitter Bootstrap Override Style */ 57 | .tocify .tocify-item > a, .tocify .nav-list .nav-header { 58 | margin: 0px; 59 | } 60 | 61 | /* Twitter Bootstrap Override Styles */ 62 | .tocify .tocify-item a, .tocify .list-group-item { 63 | padding: 5px; 64 | } 65 | 66 | .tocify .nav-pills > li { 67 | float: none; 68 | } 69 | 70 | /* We don't override the bootstrap colors because this gives us the 71 | wrong selection colors when using bootstrap themes 72 | 73 | .tocify .list-group-item:hover, .tocify .list-group-item:focus { 74 | background-color: #f5f5f5; 75 | } 76 | 77 | .tocify .list-group-item.active:hover, .tocify .list-group-item.active:focus { 78 | background-color: #428bca; 79 | } 80 | */ 81 | 82 | /* End Twitter Bootstrap Override Styles */ 83 | -------------------------------------------------------------------------------- /man/as_sf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/as-sf.R 3 | \name{as_sf} 4 | \alias{as_sf} 5 | \alias{as_sf.geo_list} 6 | \alias{as_sf.mapzen_vector_layer} 7 | \title{Coerce a Mapzen response to a simple features object} 8 | \usage{ 9 | as_sf(geo, ...) 10 | 11 | \method{as_sf}{geo_list}(geo, ...) 12 | 13 | \method{as_sf}{mapzen_vector_layer}(geo, ...) 14 | } 15 | \arguments{ 16 | \item{geo}{The object to be converted} 17 | 18 | \item{...}{not currently used} 19 | } 20 | \description{ 21 | Coerces responses to class sf. See \code{vignette("sf1", package = "sf")} for 22 | more information about Simple Features for R. 23 | } 24 | -------------------------------------------------------------------------------- /man/ca_tiles.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{ca_tiles} 5 | \alias{ca_tiles} 6 | \title{Vector tiles the contain California} 7 | \format{ 8 | An object of class \code{mapzen_vector_tiles} (inherits from \code{list}) of length 9. 9 | } 10 | \source{ 11 | Mapzen, OpenStreetMap contributors, Who's On First, Natural Earth, 12 | and openstreetmapdata.com 13 | } 14 | \usage{ 15 | ca_tiles 16 | } 17 | \description{ 18 | Vector tiles the contain California 19 | } 20 | \keyword{datasets} 21 | -------------------------------------------------------------------------------- /man/costing_models.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/costing-models.R 3 | \docType{data} 4 | \name{costing_models} 5 | \alias{costing_models} 6 | \alias{mz_costing} 7 | \alias{mz_costing_options} 8 | \title{Costing model constructors and helpers} 9 | \format{ 10 | An object of class \code{list} of length 4. 11 | 12 | An object of class \code{list} of length 4. 13 | } 14 | \usage{ 15 | mz_costing 16 | 17 | mz_costing_options 18 | } 19 | \description{ 20 | Mapzen's Isochrone service (\code{\link{mz_isochrone}}) as well as other 21 | mobility services (currently not implemented in this package, read more at 22 | \url{https://valhalla.readthedocs.io/en/latest/}) require users to specify a 23 | "costing model." See \url{https://valhalla.readthedocs.io/en/latest/} 24 | for details. These can be difficult to construct correctly, so the objects 25 | \code{mz_costing} and \code{mz_costing_options} exist to make that process 26 | less error-prone and more convenient. 27 | } 28 | \examples{ 29 | ## creates a pedestrian costing model with walking speed of 2 km/hr 30 | ## that also avoids alleys. 31 | ## non-multimodal costing models will accept 0 or more options from the 32 | ## appropriate list. 33 | mz_costing$pedestrian( 34 | mz_costing_options$pedestrian$walking_speed(2.0), 35 | mz_costing_options$pedestrian$alley_factor(0) 36 | ) 37 | 38 | ## creates a multimodal costing model that favors buses over rails, and 39 | ## has a slower than default walking speed 40 | ## (note multimodal has named arguments requiring list inputs) 41 | mz_costing$multimodal( 42 | transit = list( 43 | mz_costing_options$transit$use_bus(1.0), 44 | mz_costing_options$transit$use_rail(5) 45 | ), 46 | pedestrian = list( 47 | mz_costing_options$pedestrian$walking_speed(4.1) 48 | ) 49 | ) 50 | } 51 | \seealso{ 52 | \code{\link{mz_isochrone}} 53 | } 54 | \keyword{datasets} 55 | -------------------------------------------------------------------------------- /man/mapzen_references.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mz-references.R 3 | \docType{data} 4 | \name{mapzen_references} 5 | \alias{mapzen_references} 6 | \alias{mz_sources} 7 | \alias{mz_layers} 8 | \alias{mz_countries} 9 | \title{Reference lists} 10 | \format{ 11 | An object of class \code{list} of length 8. 12 | 13 | An object of class \code{list} of length 13. 14 | 15 | An object of class \code{list} of length 747. 16 | } 17 | \usage{ 18 | mz_sources 19 | 20 | mz_layers 21 | 22 | mz_countries 23 | } 24 | \description{ 25 | Lists of sources, layers, and countries, as they are expected to appear in 26 | the \code{\link{mz_search}} functions. These data objects are provided as a 27 | convenience, to be able to quickly and easily look up acceptable values for 28 | the optional arguments of search functions. Object names match the argument 29 | names for which they are appropriate. So \code{mz_sources} provide acceptable 30 | arguments for the \code{source} argument in \code{\link{mz_search}}, 31 | \code{mz_layers} for the \code{layer} argument, and \code{\link{mz_countries}} 32 | for the \code{boundary.country} argument. Mapzen's documentation 33 | (\url{https://github.com/pelias/documentation/}) explains more about 34 | each of these arguments. 35 | } 36 | \examples{ 37 | \dontrun{ 38 | # look for YMCAs in Jamaica: 39 | # Note that boundary.country is supplied via ISO3166 code, 40 | # but mz_countries will look up the code 41 | mz_search("YMCA", 42 | boundary.country = mz_countries$Jamaica, 43 | layers = c(mz_layers$venue, mz_layers$address)) 44 | } 45 | 46 | } 47 | \keyword{datasets} 48 | -------------------------------------------------------------------------------- /man/marina_walks.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{marina_walks} 5 | \alias{marina_walks} 6 | \title{Pedestrian isochrones from the Berkeley Marina for 10 and 15 minutes} 7 | \format{ 8 | An object of class \code{mapzen_isochrone_list} (inherits from \code{geo_list}) of length 3. 9 | } 10 | \source{ 11 | Mapzen, OpenStreetMap, British Oceanographic Data Centre, 12 | NASA, USGS, and Transitland. 13 | } 14 | \usage{ 15 | marina_walks 16 | } 17 | \description{ 18 | Isochrone results from Mapzen as of January 8, 2017. The location for the 19 | isochrones is the Berkeley Marina, lat 37.86613, lon -122.3151 20 | } 21 | \keyword{datasets} 22 | -------------------------------------------------------------------------------- /man/marina_walks_polygons.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{marina_walks_polygons} 5 | \alias{marina_walks_polygons} 6 | \title{Pedestrian isochrones from the Berkeley Marina for 10 and 15 minutes, as polygons} 7 | \format{ 8 | An object of class \code{mapzen_isochrone_list} (inherits from \code{geo_list}) of length 3. 9 | } 10 | \source{ 11 | Mapzen, OpenStreetMap, British Oceanographic Data Centre, 12 | NASA, USGS, and Transitland. 13 | } 14 | \usage{ 15 | marina_walks_polygons 16 | } 17 | \description{ 18 | Polygon Isochrone results (using \code{polygons = TRUE}) from Mapzen as of 19 | January 10, 2017. The location for the isochrones is the Berkeley Marina, 20 | lat 37.86613, lon -122.3151, and the contours are 10 and 15 minutes for a 21 | pedestrian costing model. 22 | } 23 | \keyword{datasets} 24 | -------------------------------------------------------------------------------- /man/mz_bbox.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mz-bbox.R 3 | \name{mz_bbox} 4 | \alias{mz_bbox} 5 | \alias{mz_bbox.mapzen_geo_list} 6 | \alias{mz_bbox.mapzen_isochrone_list} 7 | \alias{mz_rect} 8 | \title{Get the bounding box} 9 | \usage{ 10 | mz_bbox(geo) 11 | 12 | \method{mz_bbox}{mapzen_geo_list}(geo) 13 | 14 | \method{mz_bbox}{mapzen_isochrone_list}(geo) 15 | 16 | mz_rect(min_lon, min_lat, max_lon, max_lat) 17 | } 18 | \arguments{ 19 | \item{geo}{A mapzen geo list or isochrone list} 20 | 21 | \item{min_lon, min_lat, max_lon, max_lat}{The bottom left and top right corners, 22 | expressed as latitude and longitude, of a rectangle.} 23 | } 24 | \value{ 25 | A single-row tibble with columns \code{min_lon}, \code{min_lat}, 26 | \code{max_lon}, \code{max_lat}. 27 | } 28 | \description{ 29 | Returns the bottom left and top right corners of the box that contains a 30 | mapzen object (\code{mz_geo_list}, \code{mz_isochrone_list}, 31 | or \code{mapzen_vector_tiles}). 32 | In the case of \code{mz_rect}, creates such a box from the specified 33 | coordinates. The returned value can be used directly as the 34 | \code{boundary.rect} parameter for \code{\link{search}} functions, as well as 35 | converted to x, y, zoom coordinates to use with \code{\link{mz_vector_tiles}}. 36 | } 37 | \examples{ 38 | mz_rect(min_lon = -122.2856, min_lat = 37.73742, max_lon = -122.1749, max_lat = 37.84632) 39 | mz_bbox(oakland_public) 40 | 41 | } 42 | -------------------------------------------------------------------------------- /man/mz_check_usage.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/usage-statistics.R 3 | \name{mz_check_usage} 4 | \alias{mz_check_usage} 5 | \title{Check usage statistics} 6 | \usage{ 7 | mz_check_usage() 8 | } 9 | \description{ 10 | Prints out remaining queries for various time periods. \code{rmapzen} manages 11 | rate limiting for the per-second limits, but does not keep track of the daily 12 | limits. 13 | } 14 | \details{ 15 | This function is populated from the headers of responses to various API requests. 16 | If no queries have been made, or if the only queries so far have hit cache servers, 17 | then no information will be available. 18 | } 19 | -------------------------------------------------------------------------------- /man/mz_contours.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/matrix-helpers.R 3 | \name{mz_contours} 4 | \alias{mz_contours} 5 | \title{Create an mz_contours object} 6 | \usage{ 7 | mz_contours(times, colors = NULL) 8 | } 9 | \arguments{ 10 | \item{times}{Times in minutes for the contour. Up to a maximum of 4 numbers.} 11 | 12 | \item{colors}{Colors for the contours. By default, a palette will be constructed 13 | from the Colorbrewer 4-class oranges palette.} 14 | } 15 | \description{ 16 | Contours are given as inputs to \code{\link{mz_isochrone}}. This function 17 | makes it convenient to construct them. 18 | } 19 | -------------------------------------------------------------------------------- /man/mz_coordinates.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mz-coordinates.R 3 | \name{mz_coordinates} 4 | \alias{mz_coordinates} 5 | \alias{mz_coordinates.mapzen_geo_list} 6 | \title{Extract a data frame of coordinates from a \code{mapzen_geo_list}} 7 | \usage{ 8 | mz_coordinates(geo) 9 | 10 | \method{mz_coordinates}{mapzen_geo_list}(geo) 11 | } 12 | \arguments{ 13 | \item{geo}{A mapzen geo list} 14 | } 15 | \value{ 16 | A tibble, with columns \code{lon} and \code{lat}. 17 | } 18 | \description{ 19 | Extract a data frame of coordinates from a \code{mapzen_geo_list} 20 | } 21 | \examples{ 22 | mz_coordinates(oakland_public) 23 | 24 | } 25 | -------------------------------------------------------------------------------- /man/mz_date_time.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/matrix-helpers.R 3 | \name{mz_date_time} 4 | \alias{mz_date_time} 5 | \title{Create mz_date_time objects} 6 | \usage{ 7 | mz_date_time(date_time, type = "departure") 8 | } 9 | \arguments{ 10 | \item{date_time}{A POSIXt date-time object} 11 | 12 | \item{type}{"departure" or "arrival"} 13 | } 14 | \description{ 15 | Mobility services (such as \code{mz_isochrone}) take, optionally, a date_time 16 | argument that specifies the date and time along with type (departure/arrival). 17 | This function constructs the appropriate objects to use as date_time arguments. 18 | } 19 | -------------------------------------------------------------------------------- /man/mz_geocode.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geocode.R 3 | \name{mz_geocode} 4 | \alias{mz_geocode} 5 | \title{Geocode an address or other location} 6 | \usage{ 7 | mz_geocode(location, ...) 8 | } 9 | \arguments{ 10 | \item{location}{An address or other suitably specific search string} 11 | 12 | \item{...}{Additional arguments passed on to \code{\link{mz_search}}} 13 | } 14 | \value{ 15 | A tibble, with the parsed address used to retrieve the geocode, lat/lon, 16 | and the confidence (between 0 and 1) 17 | } 18 | \description{ 19 | This is a convenience function that calls \code{\link{mz_search}} to retrieve 20 | latitude and longitude. 21 | } 22 | \examples{ 23 | \dontrun{ 24 | mz_geocode("1600 Pennsylvania Ave., Washington DC") 25 | 26 | # can also be a landmark 27 | mz_geocode("Statue of Liberty, New York") 28 | } 29 | 30 | } 31 | \seealso{ 32 | \code{\link{mz_search}}, \code{\link{mz_reverse_geocode}} 33 | } 34 | -------------------------------------------------------------------------------- /man/mz_geocode_structured.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geocode.R 3 | \name{mz_geocode_structured} 4 | \alias{mz_geocode_structured} 5 | \title{Geocode a structured address} 6 | \usage{ 7 | mz_geocode_structured( 8 | address = NULL, 9 | neighbourhood = NULL, 10 | borough = NULL, 11 | locality = NULL, 12 | county = NULL, 13 | region = NULL, 14 | postalcode = NULL, 15 | country = NULL, 16 | ... 17 | ) 18 | } 19 | \arguments{ 20 | \item{address}{Can be a numbered street address or just the name of the street} 21 | 22 | \item{neighbourhood}{Neighborhood name (eg "Notting Hill" in London)} 23 | 24 | \item{borough}{eg "Manhattan"} 25 | 26 | \item{locality}{The city (eg "Oakland")} 27 | 28 | \item{county}{The county} 29 | 30 | \item{region}{States in the case of US/Canada, or state-like 31 | administrative division in other countries} 32 | 33 | \item{postalcode}{AKA the zip code. Can not be used alone, must have at least 34 | one other argument} 35 | 36 | \item{country}{The country - Can be the full name or the abbreviation from 37 | \code{\link{mz_countries}}} 38 | 39 | \item{...}{Arguments passed on to \code{\link{mz_structured_search}}} 40 | } 41 | \value{ 42 | A tibble, with the parsed address used to retrieve the geocode, lat/lon, 43 | and the confidence (between 0 and 1) 44 | } 45 | \description{ 46 | \code{\link{mz_geocode}} allows you to search using an unstructured string of 47 | text, but if your address data has more structure (eg separate columns for 48 | address, city, state, zip), then using the structured search service may 49 | provide more precision. For more information, see 50 | \url{https://github.com/pelias/documentation/}. Note that 51 | all of the arguments are optional, but at least one of them must be non-NULL. 52 | Furthermore, \code{postalcode} can not be used by itself. 53 | } 54 | \seealso{ 55 | \code{\link{mz_geocode}}, \code{\link{mz_structured_search}} 56 | } 57 | -------------------------------------------------------------------------------- /man/mz_isochrone.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/isochrone.R 3 | \name{mz_isochrone} 4 | \alias{mz_isochrone} 5 | \title{Retrieve isochrones} 6 | \usage{ 7 | mz_isochrone( 8 | locations, 9 | costing_model, 10 | contours, 11 | date_time = NULL, 12 | polygons = NULL, 13 | denoise = NULL, 14 | generalize = NULL, 15 | id = "my-iso", 16 | api_key = NULL 17 | ) 18 | } 19 | \arguments{ 20 | \item{locations}{An \code{mz_location}, or something that can be coerced to an 21 | \code{\link{mz_location}}, as the departure point for the isochrone. This can be the 22 | result of \code{\link{mz_geocode}}. Despite the argument name, the isochrone 23 | service currently can only accept a single location} 24 | 25 | \item{costing_model}{The costing model, see \code{\link{mz_costing}}} 26 | 27 | \item{contours}{Up to 4 contours, see \code{\link{mz_contours}}} 28 | 29 | \item{date_time}{The local date and time at the location, and whether it is 30 | the departure or arrival time. See \code{\link{mz_date_time}}} 31 | 32 | \item{polygons}{Whether to return polygons (TRUE) or linestrings (FALSE, default)} 33 | 34 | \item{denoise}{A value between 0 and 1 (default 1) to remove smaller contours. 35 | A value of 1 will only return the largest contour for a given time value. A 36 | value of 0.5 drops any contours that are less than half the area of the 37 | largest contour.} 38 | 39 | \item{generalize}{Tolerance in meters for the Douglas-Peucker generalization.} 40 | 41 | \item{id}{A descriptive identifier, the response will contain the id as an element.} 42 | 43 | \item{api_key}{Your Mapzen API key. The default is to look for the key within 44 | the provider information that was set up with `mz_set_host`.} 45 | } 46 | \value{ 47 | A \code{mapzen_isochrone_list}, which can be converted to \code{sf} 48 | using \code{\link{as_sf}}. 49 | } 50 | \description{ 51 | From \url{https://valhalla.readthedocs.io/en/latest/}: 52 | "An isochrone is a line that connects points of equal travel time about a 53 | given location, from the Greek roots of 'iso' for equal and 'chrone' for time. 54 | The Mapzen Isochrone service computes areas that are reachable within 55 | specified time intervals from a location, and returns the reachable regions 56 | as contours of polygons or lines that you can display on a map." 57 | } 58 | \examples{ 59 | \dontrun{ 60 | mz_isochrone( 61 | mz_location(lat = 37.87416, lon = -122.2544), 62 | costing_model = mz_costing$auto(), 63 | contours = mz_contours(c(10, 20, 30)) 64 | ) 65 | 66 | # departure point can be specified as a geocode result 67 | mz_isochrone( 68 | mz_geocode("UC Berkeley"), 69 | costing_model = mz_costing$pedestrian(), 70 | contours = mz_contours(c(10, 20, 30)) 71 | ) 72 | } 73 | 74 | } 75 | \seealso{ 76 | \code{\link{mz_costing}} 77 | } 78 | -------------------------------------------------------------------------------- /man/mz_location.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/matrix-helpers.R 3 | \name{mz_location} 4 | \alias{mz_location} 5 | \alias{as.mz_location} 6 | \alias{as.mz_location.default} 7 | \alias{as.mz_location.mz_geocode_result} 8 | \title{Create/extract lat/lon location information} 9 | \usage{ 10 | mz_location(lat, lon) 11 | 12 | as.mz_location(x, ...) 13 | 14 | \method{as.mz_location}{default}(x, ...) 15 | 16 | \method{as.mz_location}{mz_geocode_result}(x, ...) 17 | } 18 | \arguments{ 19 | \item{lat}{Latitude} 20 | 21 | \item{lon}{Longitude} 22 | 23 | \item{x}{An object that has location information} 24 | 25 | \item{...}{Not currently used} 26 | } 27 | \description{ 28 | \code{mz_location} constructs a new \code{mz_location} object, which can be 29 | used with functions such as \code{\link{mz_isochrone}} or 30 | \code{\link{mz_reverse_geocode}}. \code{as.mz_location} coerces eligible 31 | objects to \code{mz_location}s. 32 | } 33 | \seealso{ 34 | \code{\link{mz_isochrone}} For using the Mapzen isochrone service 35 | \code{\link{mz_contours}}, \code{\link{mz_costing}}, and 36 | \code{\link{mz_costing_options}} for other argument constructors 37 | } 38 | -------------------------------------------------------------------------------- /man/mz_place.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mz-place.R 3 | \name{mz_place} 4 | \alias{mz_place} 5 | \alias{mz_place.character} 6 | \alias{mz_place.mapzen_geo_list} 7 | \title{Get details on a place} 8 | \usage{ 9 | mz_place(ids, ..., api_key = NULL) 10 | 11 | \method{mz_place}{character}(ids, ..., api_key = NULL) 12 | 13 | \method{mz_place}{mapzen_geo_list}(ids, ..., gid = "gid", api_key = NULL) 14 | } 15 | \arguments{ 16 | \item{ids}{A character vector of gids (see details), or a \code{mapzen_geo_list}} 17 | 18 | \item{...}{Arguments passed on to methods} 19 | 20 | \item{api_key}{Your Mapzen API key. The default is to look for the key within 21 | the provider information that was set up with `mz_set_host`.} 22 | 23 | \item{gid}{The name of the \code{gid} field to use. Search results may include, 24 | in addition to the \code{gid} for the search result itself (the default), the 25 | \code{gid}s for the country, region, county, locality and neighborhood.} 26 | } 27 | \description{ 28 | Search functions (e.g. \code{\link{mz_search}}) return identification numbers, 29 | or \code{gid}s. Use \code{mz_place} to retrieve more details about the place. 30 | See \url{https://github.com/pelias/documentation/} for details. This 31 | function is generic, and can take a character vector of IDs, or a 32 | \code{mapzen_geo_list} as returned by \code{\link{mz_search}} and friends. 33 | } 34 | -------------------------------------------------------------------------------- /man/mz_provider.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/providers.R 3 | \name{mz_provider} 4 | \alias{mz_provider} 5 | \title{Configure provider information} 6 | \usage{ 7 | mz_provider(hostname, path = NULL, key = NULL, scheme = "https") 8 | } 9 | \arguments{ 10 | \item{hostname}{The hostname in the API URL, for instance \code{www.example.com}} 11 | 12 | \item{path}{Specific path that all API requests must include, e.g. "v1"} 13 | 14 | \item{key}{API key for this provider, if required} 15 | 16 | \item{scheme}{The scheme for the URL, should always be "https"} 17 | } 18 | \description{ 19 | rmapzen works with most implementations of PELIAS. This function defines the 20 | base URL for a particular API provider, and can be used to provider the 21 | \code{provider} argument to \code{\link{mz_set_host}}. 22 | } 23 | \seealso{ 24 | \code{\link{mz_set_host}} 25 | } 26 | -------------------------------------------------------------------------------- /man/mz_set_host.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/providers.R 3 | \name{mz_set_host} 4 | \alias{mz_set_host} 5 | \alias{mz_get_host} 6 | \alias{mz_set_search_host_geocode.earth} 7 | \alias{mz_set_search_host_nyc_geosearch} 8 | \alias{mz_set_tile_host_nextzen} 9 | \title{Set up a host provider for a PELIAS service} 10 | \usage{ 11 | mz_set_host(which, provider) 12 | 13 | mz_get_host(which) 14 | 15 | mz_set_search_host_geocode.earth(key = Sys.getenv("GEOCODE.EARTH_KEY")) 16 | 17 | mz_set_search_host_nyc_geosearch() 18 | 19 | mz_set_tile_host_nextzen(key = Sys.getenv("NEXTZEN_KEY")) 20 | } 21 | \arguments{ 22 | \item{which}{One of "search", "matrix", or "tile"} 23 | 24 | \item{provider}{A provider, created using \code{\link{mz_provider}}} 25 | 26 | \item{key}{API key} 27 | } 28 | \description{ 29 | rmapzen works with most implementations of PELIAS. Use this function to set 30 | up the basic information required to connect to a particular provider. 31 | Provider-specific setup functions include information to set up known 32 | providers. 33 | } 34 | \seealso{ 35 | \code{\link{mz_provider}} 36 | } 37 | -------------------------------------------------------------------------------- /man/mz_structured_search.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/structured-search.R 3 | \name{mz_structured_search} 4 | \alias{mz_structured_search} 5 | \title{Structured search} 6 | \usage{ 7 | mz_structured_search( 8 | address = NULL, 9 | neighbourhood = NULL, 10 | borough = NULL, 11 | locality = NULL, 12 | county = NULL, 13 | region = NULL, 14 | postalcode = NULL, 15 | country = NULL, 16 | api_key = NULL, 17 | ... 18 | ) 19 | } 20 | \arguments{ 21 | \item{address}{Can be a numbered street address or just the name of the street} 22 | 23 | \item{neighbourhood}{Neighborhood name (eg "Notting Hill" in London)} 24 | 25 | \item{borough}{eg "Manhattan"} 26 | 27 | \item{locality}{The city (eg "Oakland")} 28 | 29 | \item{county}{The county} 30 | 31 | \item{region}{States in the case of US/Canada, or state-like 32 | administrative division in other countries} 33 | 34 | \item{postalcode}{AKA the zip code. Can not be used alone, must have at least 35 | one other argument} 36 | 37 | \item{country}{The country - Can be the full name or the abbreviation from 38 | \code{\link{mz_countries}}} 39 | 40 | \item{api_key}{Your Mapzen API key. The default is to look for the key within 41 | the provider information that was set up with `mz_set_host`.} 42 | 43 | \item{...}{Any of the parameters, other than "text", that appear in 44 | \code{\link{mz_search}}, can appear here, for example \code{size}, 45 | \code{boundary.country}, etc.} 46 | } 47 | \description{ 48 | \code{\link{mz_search}} allows you to search using an unstructured string of 49 | text, but if your address data has more structure (eg separate columns for 50 | address, city, state, zip), then using the structured search service may 51 | provide more precision. For more information, see 52 | \url{https://github.com/pelias/documentation}. Note that 53 | all of the arguments are optional, but at least one of them must be non-NULL. 54 | Furthermore, \code{postalcode} can not be used by itself. 55 | } 56 | \seealso{ 57 | \code{\link{mz_search}} 58 | } 59 | -------------------------------------------------------------------------------- /man/mz_tile_coordinates.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mz-tile-coordinates.R 3 | \name{mz_tile_coordinates} 4 | \alias{mz_tile_coordinates} 5 | \alias{as.mz_tile_coordinates} 6 | \alias{as.mz_tile_coordinates.mz_tile_coordinates} 7 | \alias{as.mz_tile_coordinates.mz_bbox} 8 | \alias{as.mz_tile_coordinates.mz_location} 9 | \alias{as.mz_tile_coordinates.mz_geocode_result} 10 | \title{Specify tile coordinates} 11 | \usage{ 12 | mz_tile_coordinates(x, y, z) 13 | 14 | as.mz_tile_coordinates(obj, ...) 15 | 16 | \method{as.mz_tile_coordinates}{mz_tile_coordinates}(obj, ...) 17 | 18 | \method{as.mz_tile_coordinates}{mz_bbox}(obj, ..., z = NULL, height = NULL, width = NULL) 19 | 20 | \method{as.mz_tile_coordinates}{mz_location}(obj, ..., z = 15L) 21 | 22 | \method{as.mz_tile_coordinates}{mz_geocode_result}(obj, ..., z = 15L) 23 | } 24 | \arguments{ 25 | \item{x}{integer vector of x-coordinates} 26 | 27 | \item{y}{integer vector of y-coordinates} 28 | 29 | \item{z}{integer between 0 and 19 specifying the zoom level} 30 | 31 | \item{obj}{An object that can be converted to tile coordinates} 32 | 33 | \item{...}{Other arguments passed on to methods} 34 | 35 | \item{height}{Height in pixels} 36 | 37 | \item{width}{Width in pixels} 38 | } 39 | \description{ 40 | \code{\link{mz_vector_tiles}} requires tile coordinates or some other 41 | specification of the region that is to be drawn. \code{\link{mz_vector_tiles}} 42 | will automatically convert its inputs to vector tiles, so you generally won't 43 | need to use this function directly. 44 | } 45 | \examples{ 46 | mz_tile_coordinates(19293, 24641, 16) 47 | 48 | ## can specify multiple contiguous tiles: 49 | mz_tile_coordinates(19293:19294, 24641:24642, 16) 50 | 51 | ## a rectangular bounding box can be converted to tile coordinates: 52 | as.mz_tile_coordinates(mz_rect(min_lon = -122.2856, 53 | min_lat = 37.73742, 54 | max_lon = -122.1749, 55 | max_lat = 37.84632)) 56 | 57 | ## zoom level is calculated based on desired pixel dimensions of the map: 58 | as.mz_tile_coordinates(mz_rect(min_lon = -122.2856, 59 | min_lat = 37.73742, 60 | max_lon = -122.1749, 61 | max_lat = 37.84632), height = 750, width = 1000) 62 | 63 | ## a bounding box can also be calculated: 64 | as.mz_tile_coordinates(mz_bbox(oakland_public)) 65 | 66 | } 67 | \seealso{ 68 | \code{\link{mz_vector_tiles}}, \code{\link{mz_bbox}} 69 | } 70 | -------------------------------------------------------------------------------- /man/mz_vector_tiles.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/vector-tiles.R 3 | \name{mz_vector_tiles} 4 | \alias{mz_vector_tiles} 5 | \title{Request vector tile data} 6 | \usage{ 7 | mz_vector_tiles(tile_coordinates, ..., Origin = NULL) 8 | } 9 | \arguments{ 10 | \item{tile_coordinates}{an \code{\link{mz_tile_coordinates}} object, or something 11 | that can be coerced to one (including the output of \code{\link{mz_bbox}})} 12 | 13 | \item{...}{Arguments passed on to \code{\link{as.mz_tile_coordinates}}.} 14 | 15 | \item{Origin}{optional, specify Origin URL in request header} 16 | } 17 | \value{ 18 | A list of tile layers (such as "water", "buildings", "roads", etc.). 19 | Each layer is an object of class \code{mapzen_vector_layer}, which can be converted 20 | to \code{sf} using \code{\link{as_sf}} 21 | } 22 | \description{ 23 | From \url{https://tilezen.readthedocs.io/en/latest/}: "Vector tiles are 24 | square-shaped collections of geographic data that contain the map feature 25 | geometry, such as lines and points." 26 | } 27 | \details{ 28 | Multiple tiles are stitched together and returned as one object. Individual 29 | layers can be converted to \code{sf} or \code{sp}, making it possible to 30 | draw each layer with custom styles. 31 | } 32 | \examples{ 33 | \dontrun{ 34 | # vector tile at x = 19293, y = 24641, and zoom level 16 35 | mz_vector_tiles(mz_tile_coordinates(19293, 24641, 16)) 36 | 37 | # multiple contiguous tiles will be stitched together 38 | # this returns the result of stitching together 4 tiles 39 | mz_vector_tiles(mz_tile_coordinates(19293:19294, 24641:24642, 16)) 40 | 41 | # can also use a bounding box: 42 | mz_vector_tiles(mz_rect(min_lon = -122.2856, 43 | min_lat = 37.73742, 44 | max_lon = -122.1749, 45 | max_lat = 37.84632)) 46 | 47 | # mz_bbox returns a bounding box for any Mapzen object 48 | mz_vector_tiles(mz_bbox(oakland_public)) 49 | 50 | # bounding boxes are automatically converted to tile coordinates, 51 | # with the zoom level based on the desired size in pixels of the final map 52 | mz_vector_tiles(mz_bbox(oakland_public), height = 750, width = 1000) 53 | } 54 | 55 | } 56 | \seealso{ 57 | \code{\link{mz_tile_coordinates}} 58 | } 59 | -------------------------------------------------------------------------------- /man/oakland_public.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/data.R 3 | \docType{data} 4 | \name{oakland_public} 5 | \alias{oakland_public} 6 | \title{25 search results for "Oakland Public library branch"} 7 | \format{ 8 | A \code{mapzen_geo_list} with 25 locations 9 | } 10 | \source{ 11 | Mapzen, OpenStreetMap, OpenAddresses, GeoNames, WhosOnFirst, 12 | see \url{https://www.mapzen.com/rights/} 13 | } 14 | \usage{ 15 | oakland_public 16 | } 17 | \description{ 18 | Contains the search results from Mapzen's search service for the query 19 | "Oakland public library branch" as of January 8, 2017. 20 | } 21 | \keyword{datasets} 22 | -------------------------------------------------------------------------------- /man/rmapzen-package.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/rmapzen-package.R 3 | \docType{package} 4 | \name{rmapzen-package} 5 | \alias{rmapzen} 6 | \alias{rmapzen-package} 7 | \title{rmapzen: A client application for the 'Mapzen' API.} 8 | \description{ 9 | The rmapzen package provides interfaces to the Search 10 | , Isochrone 11 | , 12 | and Vector Tile 13 | services from 'Mapzen', via the following functions: 14 | } 15 | \section{Search}{ 16 | 17 | All functionality described in 18 | are supported: 19 | 20 | \itemize{ 21 | \item \code{\link{mz_search}} 22 | \item \code{\link{mz_reverse_geocode}} 23 | \item \code{\link{mz_autocomplete}} 24 | \item \code{\link{mz_place}} 25 | \item \code{\link{mz_structured_search}} 26 | } 27 | 28 | Additionally, \code{\link{mz_geocode}} is useful for a common application of 29 | search, that of just obtaining latitude and longitude for a given address or place. 30 | } 31 | 32 | \section{Isochrone}{ 33 | 34 | Isochrones are the areas reachable from a given location within a specified 35 | period of time. Mapzen's Isochrone service can calculate isochrones for driving, 36 | walking, cycling, or multimodal forms of transport: 37 | 38 | \itemize{ 39 | \item \code{\link{mz_isochrone}} 40 | \item \code{\link{mz_costing}}: for constructing "costing models" that describe 41 | method of transport along with speed and other options relevant to the 42 | calculation of the isochrone 43 | \item \code{\link{mz_costing_options}}: for selecting specific options when 44 | constructing a costing model 45 | } 46 | } 47 | 48 | \section{Vector Tiles}{ 49 | 50 | \itemize{ 51 | \item \code{\link{mz_vector_tiles}}: Request one or more adjacent tiles. 52 | Multiple map tiles will be stitched together before being returned as a single 53 | object. 54 | \item \code{\link{mz_tile_coordinates}}: When using \code{\link{mz_vector_tiles}}, 55 | you must specify the geographic area for which you want tile data. One way to do so 56 | is using the x, y, z tile naming system (see ). 57 | \item \code{\link{mz_rect}}: Alternatively, you can specify the lower left 58 | and top-right points of a bounding box, which will automatically be converted 59 | to tile-coordinates when you use \code{\link{mz_vector_tiles}} 60 | \item \code{\link{mz_bbox}}: This is a generic function which will return 61 | the bounding box of any Mapzen object. In this way, you can request vector 62 | tiles for a region defined as the bounding box of an existing object. 63 | } 64 | } 65 | 66 | \section{Data types and conversion}{ 67 | 68 | Objects returned by rmapzen can be converted to 69 | simple features (sf) via the generic function 70 | \code{\link{as_sf}}. Search 71 | and Isochrone objects can additionally be converted to ordinary data.frames 72 | via \code{as.data.frame}. 73 | } 74 | 75 | \seealso{ 76 | \itemize{ 77 | \item contains detailed examples 78 | \item 'Mapzen' documentation 79 | } 80 | } 81 | \author{ 82 | \strong{Maintainer}: Tarak Shah \email{tarak.shah@gmail.com} 83 | 84 | Other contributors: 85 | \itemize{ 86 | \item Daniel Possenriede [contributor] 87 | } 88 | 89 | } 90 | -------------------------------------------------------------------------------- /man/search.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/mz-autocomplete.R, R/mz-reverse.R, 3 | % R/mz-search.R 4 | \name{mz_autocomplete} 5 | \alias{mz_autocomplete} 6 | \alias{mz_reverse_geocode} 7 | \alias{search} 8 | \alias{mz_search} 9 | \title{Mapzen search API} 10 | \usage{ 11 | mz_autocomplete( 12 | text, 13 | boundary.country = NULL, 14 | boundary.rect = NULL, 15 | focus.point = NULL, 16 | sources = NULL, 17 | layers = NULL, 18 | api_key = NULL 19 | ) 20 | 21 | mz_reverse_geocode( 22 | point, 23 | size = NULL, 24 | layers = NULL, 25 | sources = NULL, 26 | boundary.country = NULL, 27 | api_key = NULL 28 | ) 29 | 30 | mz_search( 31 | text, 32 | size = 10, 33 | boundary.country = NULL, 34 | boundary.rect = NULL, 35 | boundary.circle = NULL, 36 | focus.point = NULL, 37 | sources = NULL, 38 | layers = NULL, 39 | api_key = NULL 40 | ) 41 | } 42 | \arguments{ 43 | \item{text}{Search string} 44 | 45 | \item{boundary.country}{ISO-3166 country code to narrow the search. 46 | See \code{\link{mz_countries}}} 47 | 48 | \item{boundary.rect}{4 corners that define a box to narrow the search. Can 49 | be the result of \code{\link{mz_bbox}}. Should have named elements with names 50 | "min_lon", "min_lat", "max_lon", "max_lat" -- can be created using \code{\link{mz_rect}}.} 51 | 52 | \item{focus.point}{A point to "focus" the search. Can be created with 53 | \code{\link{mz_location}} or \code{\link{mz_geocode}}, otherwise should have 54 | names "lat" and "lon"} 55 | 56 | \item{sources}{The originating source of the data (to filter/narrow search 57 | results). See \code{\link{mz_sources}}} 58 | 59 | \item{layers}{Which layers (types of places) to search. See 60 | \url{https://github.com/pelias/documentation/} 61 | for definitions, and use \code{\link{mz_layers}} for convenience} 62 | 63 | \item{api_key}{Your Mapzen API key. The default is to look for the key within 64 | the provider information that was set up with `mz_set_host`.} 65 | 66 | \item{point}{For reverse geocoding, the location to reverse geocode. Can be 67 | created with \code{\link{mz_location}} or \code{\link{mz_geocode}}, 68 | otherwise should have names "lat" and "lon"} 69 | 70 | \item{size}{Number of search results requested} 71 | 72 | \item{boundary.circle}{A circle to narrow the search. Should have named elements 73 | with names "lon", "lat", and "radius"} 74 | } 75 | \description{ 76 | Functions to access the various endpoints from the Mapzen Search API. 77 | For more details, see \url{https://github.com/pelias/documentation/}. If your 78 | data is already split up by street, city, state, zip, etc., then you might 79 | find \code{\link{mz_structured_search}} to be more precise. All arguments 80 | besides \code{text} (\code{point} in the case of \code{mz_reverse_geocode}) are 81 | optional. If you have parsed addresses (e.g. for geocoding), use \code{\link{mz_structured_search}} 82 | } 83 | \examples{ 84 | \dontrun{ 85 | # hard rock cafes in sweden: 86 | mz_search("Hard Rock Cafe", boundary.country = "SE") 87 | 88 | # autocompletions when the user types in "Union Square" 89 | # prioritizing San Francisco results first: 90 | mz_autocomplete("Union Square", 91 | focus.point = mz_geocode("San Francisco, CA")) 92 | } 93 | 94 | } 95 | \seealso{ 96 | \code{\link{mz_place}}, \code{\link{mz_structured_search}}, 97 | \code{\link{mz_countries}}, \code{\link{mz_sources}}, \code{\link{mz_layers}} 98 | } 99 | -------------------------------------------------------------------------------- /revdep/.gitignore: -------------------------------------------------------------------------------- 1 | checks 2 | library 3 | checks.noindex 4 | library.noindex 5 | cloud.noindex 6 | data.sqlite 7 | *.html 8 | -------------------------------------------------------------------------------- /revdep/README.md: -------------------------------------------------------------------------------- 1 | # Platform 2 | 3 | |field |value | 4 | |:--------|:--------------------------------| 5 | |version |R version 4.3.1 (2023-06-16) | 6 | |os |macOS Sonoma 14.0 | 7 | |system |aarch64, darwin22.4.0 | 8 | |ui |unknown | 9 | |language |(EN) | 10 | |collate |en_US.UTF-8 | 11 | |ctype |en_US.UTF-8 | 12 | |tz |America/Los_Angeles | 13 | |date |2023-10-17 | 14 | |pandoc |3.1.8 @ /opt/homebrew/bin/pandoc | 15 | 16 | # Dependencies 17 | 18 | |package |old |new |Δ | 19 | |:-------|:-----|:-----|:--| 20 | |rmapzen |0.5.0 |0.5.1 |* | 21 | |jqr |NA |1.3.1 |* | 22 | |sp |NA |2.1-1 |* | 23 | 24 | # Revdeps 25 | 26 | -------------------------------------------------------------------------------- /revdep/cran.md: -------------------------------------------------------------------------------- 1 | ## revdepcheck results 2 | 3 | We checked 0 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/failures.md: -------------------------------------------------------------------------------- 1 | *Wow, no problems at all. :)* -------------------------------------------------------------------------------- /revdep/problems.md: -------------------------------------------------------------------------------- 1 | *Wow, no problems at all. :)* -------------------------------------------------------------------------------- /rmapzen.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 4 10 | Encoding: UTF-8 11 | 12 | RnwWeave: Sweave 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 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(rmapzen) 3 | sf::sf_use_s2(TRUE) 4 | test_check("rmapzen") 5 | -------------------------------------------------------------------------------- /tests/testthat/helpers.R: -------------------------------------------------------------------------------- 1 | expect_dict_equal <- function(x1, x2) { 2 | # test whether two lists are "equal" up to re-ordering 3 | # like setequal, but also looks at element names 4 | actual_query <- x1[sort(names(x1))] 5 | expected_query <- x2[sort(names(x2))] 6 | expect_equal(actual_query, expected_query) 7 | 8 | } 9 | 10 | mz_setup <- function() { 11 | hosts <- c("search", "matrix", "tile") 12 | gh <- function(x) tryCatch(mz_get_host(x), error = function(e) NULL) 13 | old_opts <- structure(lapply(hosts, gh), 14 | names = hosts) 15 | suppressWarnings( 16 | lapply(hosts, 17 | mz_set_host, 18 | provider = mz_provider("www.example.com", 19 | path = "not/a/real/path", 20 | key = "api-key")) 21 | ) 22 | old_opts 23 | } 24 | 25 | mz_teardown <- function(old_opts) { 26 | suppressWarnings( 27 | Map(mz_set_host, 28 | which = names(old_opts), 29 | provider = old_opts) 30 | ) 31 | } 32 | test_that <- function(...) { 33 | old_opts <- mz_setup() 34 | testthat::test_that(...) 35 | mz_teardown(old_opts) 36 | } 37 | 38 | expect_tiles_contain_xy <- function(object, x, y) { 39 | act <- quasi_label(rlang::enquo(object)) 40 | 41 | xs <- vapply(object, function(.) .[["x"]], numeric(1)) 42 | ys <- vapply(object, function(.) .[["y"]], numeric(1)) 43 | 44 | expect( 45 | x %in% xs && y %in% ys, 46 | sprintf("%s does not contain tile (%i, %i)", act$lab, x, y) 47 | ) 48 | invisible(act$val) 49 | } 50 | -------------------------------------------------------------------------------- /tests/testthat/test-as-data-frame.R: -------------------------------------------------------------------------------- 1 | context("as.data.frame") 2 | 3 | test_that("as.data.frame converts search results to data frame", { 4 | oakland_public_df <- as.data.frame(oakland_public) 5 | expect_is(oakland_public_df, "data.frame") 6 | expect_equal(nrow(oakland_public_df), length(oakland_public$features)) 7 | }) 8 | 9 | test_that("as.data.frame converts isochrone results to sf", { 10 | marina_walks_df <- as.data.frame(marina_walks) 11 | expect_is(marina_walks_df, "data.frame") 12 | expect_equal(length(unique(marina_walks_df$contour)), length(marina_walks$features)) 13 | num_features <- vapply(marina_walks$features, function(x) length(x$geometry$coordinates), FUN.VALUE = integer(1)) 14 | num_features <- sum(num_features) 15 | expect_equal(nrow(marina_walks_df), num_features) 16 | }) 17 | 18 | test_that("as.data.frame errors on empty search results", { 19 | empty_search <- oakland_public 20 | empty_search$features <- list() 21 | expect_error(as.data.frame(empty_search), "no data") 22 | }) 23 | 24 | -------------------------------------------------------------------------------- /tests/testthat/test-as-sf.R: -------------------------------------------------------------------------------- 1 | context("as_sf") 2 | 3 | test_that("as_sf converts search results to sf", { 4 | oakland_public_sf <- as_sf(oakland_public) 5 | expect_is(oakland_public_sf, "sf") 6 | }) 7 | 8 | test_that("as_sf converts isochrone results to sf", { 9 | marina_walks_sf <- as_sf(marina_walks) 10 | expect_is(marina_walks_sf, "sf") 11 | 12 | marina_walks_polygons_sf <- as_sf(marina_walks_polygons) 13 | expect_is(marina_walks_polygons_sf, "sf") 14 | }) 15 | 16 | test_that("as_sf converts vector tile layers to sf", { 17 | roadlines <- as_sf(ca_tiles$roads) 18 | expect_is(roadlines, "sf") 19 | 20 | earthpolygons <- as_sf(ca_tiles$earth) 21 | expect_is(earthpolygons, "sf") 22 | 23 | waterpoints <- as_sf(ca_tiles$water) 24 | expect_is(waterpoints, "sf") 25 | }) 26 | 27 | test_that("as_sf errors on empty search results", { 28 | empty_search <- oakland_public 29 | empty_search$features <- list() 30 | expect_error(as_sf(empty_search), "no data") 31 | }) 32 | 33 | test_that("as_sf errors on empty vector tile layers", { 34 | expect_error(as_sf(ca_tiles$buildings), "empty") 35 | }) 36 | -------------------------------------------------------------------------------- /tests/testthat/test-mz-autocomplete.R: -------------------------------------------------------------------------------- 1 | context("mz-autocomplete") 2 | 3 | test_that("autocomplete request urls built correctly", { 4 | 5 | a1 <- build_autocomplete_url( 6 | "union square", 7 | focus.point = c(lat = 37.7, lon = -122.4), 8 | api_key = "mz" 9 | ) 10 | 11 | expect_dict_equal( 12 | a1$query, list( 13 | focus.point.lat = 37.7, 14 | focus.point.lon = -122.4, 15 | text = "union square", 16 | api_key = "mz" 17 | ) 18 | ) 19 | 20 | a2 <- build_autocomplete_url( 21 | "pennsylvania", 22 | sources = "openaddresses", 23 | api_key = "m" 24 | ) 25 | 26 | expect_dict_equal( 27 | a2$query, list( 28 | text = "pennsylvania", 29 | sources = "openaddresses", 30 | api_key = "m" 31 | ) 32 | ) 33 | 34 | a3 <- build_autocomplete_url( 35 | "starbuck", 36 | layers = "coarse", 37 | api_key = "m" 38 | ) 39 | 40 | expect_dict_equal( 41 | a3$query, list( 42 | text = "starbuck", 43 | layers = "coarse", 44 | api_key = "m" 45 | ) 46 | ) 47 | }) 48 | -------------------------------------------------------------------------------- /tests/testthat/test-mz-bbox.R: -------------------------------------------------------------------------------- 1 | context("mz_bbox") 2 | 3 | test_that("mz_bbox gets bounding box for vector tiles", { 4 | # ca_tiles has all of california, so should include 5 | # san diego and sacramento 6 | bbox <- mz_bbox(ca_tiles) 7 | expect_is(bbox, "data.frame") 8 | expect_true(setequal( 9 | names(bbox), 10 | c("min_lon", "min_lat", "max_lon", "max_lat") 11 | )) 12 | 13 | sdlon <- -117.1534 14 | sdlat <- 32.80151 15 | saclon <- -121.4668 16 | saclat <- 38.57873 17 | 18 | expect_lt(bbox$min_lon, sdlon) 19 | expect_gt(bbox$max_lon, sdlon) 20 | expect_lt(bbox$min_lat, sdlat) 21 | expect_gt(bbox$max_lat, sdlat) 22 | 23 | expect_lt(bbox$min_lon, saclon) 24 | expect_gt(bbox$max_lon, saclon) 25 | expect_lt(bbox$min_lat, saclat) 26 | expect_gt(bbox$max_lat, saclat) 27 | }) 28 | 29 | test_that("mz_bbox gets bounding box for isochrones", { 30 | bbox <- mz_bbox(marina_walks) 31 | expect_is(bbox, "data.frame") 32 | expect_true(setequal( 33 | names(bbox), 34 | c("min_lon", "min_lat", "max_lon", "max_lat") 35 | )) 36 | # should at least contain the marina itself 37 | marinalon <- -122.3151 38 | marinalat <- 37.86613 39 | expect_lt(bbox$min_lon, marinalon) 40 | expect_gt(bbox$max_lon, marinalon) 41 | expect_lt(bbox$min_lat, marinalat) 42 | expect_gt(bbox$max_lat, marinalat) 43 | }) 44 | 45 | test_that("mz_bbox gets bounding box for search results", { 46 | bbox <- mz_bbox(oakland_public) 47 | coords <- mz_coordinates(oakland_public) 48 | # should contain all the points 49 | within <- function(lon, lat, bbox) { 50 | expect_lte(bbox$min_lon, lon) 51 | expect_gte(bbox$max_lon, lon) 52 | expect_lte(bbox$min_lat, lat) 53 | expect_gte(bbox$max_lat, lat) 54 | } 55 | Map(function(x, y) within(x, y, bbox), coords$lon, coords$lat) 56 | }) 57 | 58 | test_that("mz_bbox works for sf and sp objects", { 59 | oakland_sf <- as_sf(oakland_public) 60 | #oakland_sp <- as_sp(oakland_public) 61 | 62 | expect_is(mz_bbox(oakland_sf), "mz_bbox") 63 | #expect_is(mz_bbox(oakland_sp), "mz_bbox") 64 | }) 65 | -------------------------------------------------------------------------------- /tests/testthat/test-mz-isochrone.R: -------------------------------------------------------------------------------- 1 | context("mz-isochrone") 2 | 3 | test_that("isochrone urls built correctly", { 4 | test1 <- build_isochrone_url( 5 | locations = c(lat = 37, lon = -122), 6 | costing_model = mz_costing$pedestrian(), 7 | contours = mz_contours( 8 | times = seq(10, 30, 10), 9 | colors = c("440154", "21908C", "FDE725") 10 | ), 11 | date_time = NULL, 12 | polygons = NULL, 13 | denoise = NULL, 14 | generalize = NULL, 15 | id = "test1", 16 | api_key = "abc" 17 | ) 18 | 19 | expect_true(setequal( 20 | names(test1$query), 21 | c("api_key", "json", "id") 22 | )) 23 | 24 | expect_equal(test1$query$id, "test1") 25 | expect_equal(test1$query$api_key, "abc") 26 | expect_equal( 27 | as.character(test1$query$json), 28 | '{"locations":[{"lon":-122,"lat":37}],"costing":"pedestrian","contours":[{"time":10,"color":"440154"},{"time":20,"color":"21908C"},{"time":30,"color":"FDE725"}]}' 29 | ) 30 | 31 | ## 32 | 33 | test2 <- build_isochrone_url( 34 | locations = mz_location(lat = 37, lon = -122), 35 | costing_model = mz_costing$pedestrian( 36 | mz_costing_options$pedestrian$walkway_factor(.2), 37 | mz_costing_options$pedestrian$alley_factor(3) 38 | ), 39 | contours = mz_contours( 40 | times = seq(10, 30, 10), 41 | colors = c("440154", "21908C", "FDE725") 42 | ), 43 | date_time = NULL, 44 | polygons = NULL, 45 | denoise = NULL, 46 | generalize = NULL, 47 | id = "test2", 48 | api_key = "abc" 49 | ) 50 | 51 | expect_equal( 52 | as.character(test2$query$json), 53 | '{"locations":[{"lon":-122,"lat":37}],"costing":"pedestrian","costing_options":{"pedestrian":{"walkway_factor":0.2,"alley_factor":3}},"contours":[{"time":10,"color":"440154"},{"time":20,"color":"21908C"},{"time":30,"color":"FDE725"}]}' 54 | ) 55 | 56 | ## 57 | 58 | test3 <- build_isochrone_url( 59 | locations = mz_location(lat = 37, lon = -122), 60 | costing_model = mz_costing$pedestrian( 61 | mz_costing_options$pedestrian$walking_speed(7.0), 62 | mz_costing_options$pedestrian$walkway_factor(10) 63 | ), 64 | contours = mz_contours(seq(10, 40, 10)), 65 | date_time = mz_date_time(as.POSIXct("2016-12-11 17:41:51 PST"), "departure"), 66 | polygons = FALSE, 67 | denoise = .7, 68 | generalize = 4773, 69 | id = "my-id", 70 | api_key = "mz-key" 71 | ) 72 | 73 | test3 <- jsonlite::fromJSON(test3$query$json, 74 | simplifyVector = FALSE) 75 | expect_equal( 76 | test3$polygons, FALSE 77 | ) 78 | expect_equal( 79 | test3$denoise, .7 80 | ) 81 | expect_equal( 82 | test3$generalize, 4773 83 | ) 84 | expect_equal( 85 | test3$date_time, 86 | list( 87 | type = 1, value = "2016-12-11T17:41" 88 | ) 89 | ) 90 | ## 91 | 92 | test4 <- build_isochrone_url( 93 | locations = mz_location(lat = 37, lon = -122), 94 | costing_model = mz_costing$multimodal( 95 | transit = list( 96 | mz_costing_options$transit$use_bus(1.0), 97 | mz_costing_options$transit$use_rail(.7) 98 | ), 99 | pedestrian = list( 100 | mz_costing_options$pedestrian$alley_factor(3) 101 | ) 102 | ), 103 | contours = mz_contours(10, 'ffffff'), 104 | date_time = NULL, 105 | polygons = NULL, 106 | denoise = NULL, 107 | generalize = NULL, 108 | id = NULL, 109 | api_key = "abc" 110 | ) 111 | 112 | }) 113 | -------------------------------------------------------------------------------- /tests/testthat/test-mz-place.R: -------------------------------------------------------------------------------- 1 | context("mz-place") 2 | 3 | test_that("place search builds urls correctly", { 4 | tower1 <- build_place_url("openstreetmap:venue:way:5013364", api_key = "x") 5 | expect_dict_equal( 6 | tower1$query, list( 7 | api_key = "x", 8 | ids = "openstreetmap:venue:way:5013364" 9 | ) 10 | ) 11 | 12 | tower2 <- build_place_url( 13 | c("openstreetmap:venue:way:5013364", "whosonfirst:borough:421205771"), 14 | api_key = "abc" 15 | ) 16 | 17 | expect_dict_equal( 18 | tower2$query, list( 19 | api_key = "abc", 20 | ids = "openstreetmap:venue:way:5013364,whosonfirst:borough:421205771" 21 | ) 22 | ) 23 | 24 | }) 25 | -------------------------------------------------------------------------------- /tests/testthat/test-mz-reverse.R: -------------------------------------------------------------------------------- 1 | context("mz-reverse") 2 | 3 | test_that("reverse search urls built correctly", { 4 | 5 | pt1 <- build_reverse_url( 6 | point = c(lat = 48.858268, lon = 2.294471), 7 | size = 1, 8 | api_key = "mapzen-xxxx" 9 | ) 10 | 11 | expect_dict_equal( 12 | pt1$query, list( 13 | point.lat = 48.858268, 14 | point.lon = 2.294471, 15 | size = 1, 16 | api_key = "mapzen-xxxx" 17 | ) 18 | ) 19 | 20 | pt2 <- build_reverse_url( 21 | point = c(lat = 48.858268, lon = 2.294471), 22 | size = 1, 23 | api_key = "mapzen-xxxx", 24 | sources = c("osm", "oa") 25 | ) 26 | 27 | expect_dict_equal( 28 | pt2$query, list( 29 | point.lat = 48.858268, 30 | point.lon = 2.294471, 31 | size = 1, 32 | api_key = "mapzen-xxxx", 33 | sources = "osm,oa" 34 | ) 35 | ) 36 | 37 | pt3 <- build_reverse_url( 38 | point = c(lat = 48.858268, lon = 2.294471), 39 | size = 1, 40 | api_key = "mapzen-xxxx", 41 | layers = "locality" 42 | ) 43 | 44 | expect_dict_equal( 45 | pt3$query, list( 46 | point.lat = 48.858268, 47 | point.lon = 2.294471, 48 | size = 1, 49 | api_key = "mapzen-xxxx", 50 | layers = "locality" 51 | ) 52 | ) 53 | 54 | pt4 <- build_reverse_url( 55 | point = c(lat = 48.858268, lon = 2.294471), 56 | size = 1, 57 | api_key = "mapzen-xxxx", 58 | sources = c("osm", "oa"), 59 | layers = c("locality", mz_layers$macroregion) 60 | ) 61 | 62 | expect_dict_equal( 63 | pt4$query, list( 64 | point.lat = 48.858268, 65 | point.lon = 2.294471, 66 | size = 1, 67 | api_key = "mapzen-xxxx", 68 | sources = "osm,oa", 69 | layers = "locality,macroregion" 70 | ) 71 | ) 72 | 73 | pt5 <- build_reverse_url( 74 | point = c(lat = 48.858268, lon = 2.294471), 75 | size = 1, 76 | api_key = "mapzen-xxxx", 77 | boundary.country = "LIE" 78 | ) 79 | 80 | expect_dict_equal( 81 | pt5$query, list( 82 | point.lat = 48.858268, 83 | point.lon = 2.294471, 84 | size = 1, 85 | api_key = "mapzen-xxxx", 86 | boundary.country = "LIE" 87 | ) 88 | ) 89 | 90 | tower <- build_reverse_url( 91 | point = c( 92 | lat = 51.5081124, 93 | lon = -.0759493 94 | ), 95 | api_key = "mapzen-xxxx", 96 | layers = mz_layers$address, 97 | sources = "osm", 98 | size = 1 99 | ) 100 | 101 | expect_dict_equal( 102 | tower$query, list( 103 | point.lat = 51.5081124, 104 | point.lon = -.0759493, 105 | api_key = "mapzen-xxxx", 106 | layers = "address", 107 | sources = "osm", 108 | size = 1 109 | ) 110 | ) 111 | 112 | }) 113 | -------------------------------------------------------------------------------- /tests/testthat/test-mz-search.R: -------------------------------------------------------------------------------- 1 | context("mz-search") 2 | 3 | test_that("search urls built correctly", { 4 | main_st <- build_search_url("main street, usa", size = 3, api_key = "zzz") 5 | expect_dict_equal( 6 | main_st$query, list( 7 | api_key = "zzz", 8 | text = "main street, usa", 9 | size = 3) 10 | ) 11 | 12 | expect_identical(main_st$scheme, "https") 13 | 14 | eiffel <- build_search_url("eiffel tower, paris", size = 1, 15 | boundary.country = "FR", api_key = "zzz") 16 | 17 | expect_dict_equal( 18 | eiffel$query, list( 19 | api_key = "zzz", 20 | text = "eiffel tower, paris", 21 | size = 1, 22 | boundary.country = "FR" 23 | ) 24 | ) 25 | 26 | # example from mapzen documentation 27 | ymca_tx <- build_search_url(text = "YMCA", 28 | boundary.rect = c( 29 | min_lat = 25.84, 30 | min_lon = -106.65, 31 | max_lat = 36.5, 32 | max_lon = -93.51), 33 | api_key = "zzz" 34 | ) 35 | 36 | expect_dict_equal( 37 | ymca_tx$query, list( 38 | api_key = "zzz", 39 | text = "YMCA", 40 | size = 10, 41 | boundary.rect.min_lat=25.84, 42 | boundary.rect.min_lon=-106.65, 43 | boundary.rect.max_lat=36.5, 44 | boundary.rect.max_lon=-93.51 45 | ) 46 | ) 47 | 48 | ymca_circle <- build_search_url( 49 | "YMCA", 50 | size = 3, 51 | boundary.circle = c( 52 | lat = 43.818156, 53 | lon = -79.186484, 54 | radius = 35 55 | ), 56 | api_key = "abc" 57 | ) 58 | 59 | expect_dict_equal( 60 | ymca_circle$query, list( 61 | api_key = "abc", 62 | text = "YMCA", 63 | size = 3, 64 | boundary.circle.lat = 43.818156, 65 | boundary.circle.lon = -79.186484, 66 | boundary.circle.radius = 35 67 | ) 68 | ) 69 | 70 | ymca_aus <- build_search_url( 71 | "YMCA", 72 | focus.point = c( 73 | lat = -33.856680, 74 | lon = 151.215281 75 | ), 76 | boundary.country = "AUS", 77 | api_key = "abc" 78 | ) 79 | 80 | expect_dict_equal( 81 | ymca_aus$query, list( 82 | api_key = "abc", 83 | text = "YMCA", 84 | size = 10, 85 | boundary.country = "AUS", 86 | focus.point.lon = 151.215281, 87 | focus.point.lat = -33.856680 88 | ) 89 | ) 90 | 91 | ymca_oa <- build_search_url( 92 | text = "YMCA", 93 | source = "oa", 94 | api_key = "abc" 95 | ) 96 | 97 | expect_dict_equal( 98 | ymca_oa$query, list( 99 | api_key = "abc", 100 | sources = "oa", 101 | size = 10, 102 | text = "YMCA" 103 | ) 104 | ) 105 | 106 | ymca_2sources <- build_search_url( 107 | text = "YMCA", 108 | sources = c("osm", mz_sources$gn), 109 | api_key = "abc" 110 | ) 111 | 112 | expect_dict_equal( 113 | ymca_2sources$query, list( 114 | api_key = "abc", 115 | sources = "osm,gn", 116 | size = 10, 117 | text = "YMCA" 118 | ) 119 | ) 120 | 121 | ymca_2layers <- build_search_url( 122 | text = "YMCA", 123 | layers = c(mz_layers$venue, mz_layers$address), 124 | api_key = "abc" 125 | ) 126 | 127 | expect_dict_equal( 128 | ymca_2layers$query, list( 129 | api_key = "abc", 130 | layers = "venue,address", 131 | size = 10, 132 | text = "YMCA" 133 | ) 134 | ) 135 | }) 136 | -------------------------------------------------------------------------------- /tests/testthat/test-mz-structured-search.R: -------------------------------------------------------------------------------- 1 | context("structured search") 2 | 3 | test_that("Notting Hill structured search url built correctly", { 4 | url <- build_structured_search_url( 5 | neighbourhood = "Notting Hill", 6 | locality = "London", 7 | api_key = "abc" 8 | ) 9 | expect_match(url$path, "/structured$") 10 | expect_identical(url$query$neighbourhood, "Notting Hill") 11 | expect_identical(url$query$locality, "London") 12 | expect_identical(url$query$api_key, "abc") 13 | }) 14 | 15 | test_that("Bangkok structured search URL built correctly", { 16 | url <- build_structured_search_url( 17 | locality = "Bangkok", 18 | country = "Thailand", 19 | api_key = "abc" 20 | ) 21 | expect_identical(url$query$locality, "Bangkok") 22 | expect_identical(url$query$country, "Thailand") 23 | }) 24 | 25 | test_that("Structured search with postalcode and country works", { 26 | url <- build_structured_search_url( 27 | postalcode = "94609", 28 | country = "USA", 29 | api_key = "abc", 30 | size = 1 31 | ) 32 | expect_dict_equal( 33 | url$query, list( 34 | postalcode = "94609", 35 | country = "USA", 36 | api_key = "abc", 37 | size = 1 38 | ) 39 | ) 40 | }) 41 | 42 | test_that("Structured search allows general search parameters", { 43 | url <- build_structured_search_url( 44 | locality = "Berkeley", 45 | country = "USA", 46 | size = 1, 47 | focus.point = c(lat = 1, lon = 2), 48 | api_key = "abc" 49 | ) 50 | expect_dict_equal( 51 | url$query, list( 52 | api_key = "abc", 53 | locality = "Berkeley", 54 | country = "USA", 55 | size = 1, 56 | focus.point.lat = 1, 57 | focus.point.lon = 2 58 | ) 59 | ) 60 | }) 61 | 62 | test_that("Structure search gives errors when not enough info", { 63 | expect_error(build_search_url()) 64 | expect_error(build_search_url(postalcode = 12356)) 65 | }) 66 | -------------------------------------------------------------------------------- /tests/testthat/test-mz-vector-tiles.R: -------------------------------------------------------------------------------- 1 | context("vector-tiles") 2 | 3 | test_that("vector tile urls built correctly", { 4 | # 16/19293/24641.json 5 | url <- vector_url(x = 19293, y = 24641, z = 16, 6 | format = "json", api_key = "abc") 7 | 8 | expect_match(url$path, "/all/16/19293/24641.json") 9 | expect_identical(url$query$api_key, "abc") 10 | }) 11 | 12 | test_that("single tiles can be pulled", { 13 | skip("skipping single-tile test, requires access to external resource") 14 | single_tile <- mz_vector_tiles(mz_tile_coordinates(19293, 24641, 16)) 15 | expect_is(single_tile, "mapzen_vector_tiles") 16 | expect_length(single_tile, 9L) 17 | expect_is(single_tile[[1]], "mapzen_vector_layer") 18 | }) 19 | 20 | test_that("multiple contiguous tiles can be pulled", { 21 | skip("skipping multiple contiguous tiles test, requires access to external resource") 22 | multi_tile <- mz_vector_tiles(mz_tile_coordinates(19293:19294, 24641:24642, 16)) 23 | expect_is(multi_tile, "mapzen_vector_tiles") 24 | expect_length(multi_tile, 9L) 25 | expect_is(multi_tile[[1]], "mapzen_vector_layer") 26 | }) 27 | -------------------------------------------------------------------------------- /tests/testthat/test-tile-coordinates.R: -------------------------------------------------------------------------------- 1 | context("specifying tile coordinates") 2 | 3 | test_that("tile coordinates are generated for contiguous rectangular range", { 4 | ex1 <- mz_tile_coordinates(1:5, 4, 12) 5 | # should be one element per x for each y 6 | expect_length(ex1, 5) 7 | 8 | ex2 <- mz_tile_coordinates(1:5, 1:4, 12) 9 | expect_length(ex2, 20) 10 | 11 | # tiles should use range(x) and range(y) 12 | # so x should have 5 columns, 13 | # y should have 7 rows 14 | ex3 <- mz_tile_coordinates(c(1, 4, 5), c(7, 1), 10) 15 | expect_length(ex3, 35) 16 | xs <- vapply(ex3, function(.).[["x"]], FUN.VALUE = numeric(1)) 17 | ys <- vapply(ex3, function(.).[["y"]], FUN.VALUE = numeric(1)) 18 | 19 | # a random tile within the specified range should be in the spec 20 | tile43 <- intersect(which(xs == 4), which(ys == 3)) 21 | expect_length(tile43, 1L) 22 | zs <- unique(vapply(ex3, function(.).[["z"]], numeric(1))) 23 | expect_length(zs, 1L) 24 | }) 25 | 26 | test_that("error when ambiguous arguments are provided", { 27 | rect <- mz_rect( 28 | min_lon = -122.3163, 29 | min_lat = 37.86393, 30 | max_lon = -122.3093, 31 | max_lat = 37.86912 32 | ) 33 | 34 | expect_error( 35 | as.mz_tile_coordinates( 36 | rect, 37 | height = 375, width = 500, 38 | z = 17), 39 | "height.+width.+z") 40 | 41 | expect_error( 42 | as.mz_tile_coordinates( 43 | rect, 44 | height = 375), 45 | "height.+width") 46 | 47 | expect_warning( 48 | as.mz_tile_coordinates( 49 | rect, 50 | width = 500, 51 | z = 17), 52 | "width.+ignored") 53 | 54 | 55 | }) 56 | 57 | test_that("bounding box is correctly converted to tile coordinates", { 58 | marina_rect <- mz_rect( 59 | min_lon = -122.3163, 60 | min_lat = 37.86393, 61 | max_lon = -122.3093, 62 | max_lat = 37.86912 63 | ) 64 | 65 | # at zoom16, this tile should be there: 66 | # based on http://tools.geofabrik.de/calc/#type=geofabrik_standard&bbox=-122.321657,37.862023,-122.305585,37.870408&grid=1 67 | expect_tiles_contain_xy( 68 | as.mz_tile_coordinates(marina_rect), 69 | x = 10501, y = 25310 70 | ) 71 | 72 | # for zoom 10, this is the tile containing the marina rectangle 73 | expect_tiles_contain_xy( 74 | as.mz_tile_coordinates(marina_rect, z = 10), 75 | x = 164, y = 395 76 | ) 77 | }) 78 | 79 | test_that("point + zoom is correctly converted to tile coordinates", { 80 | marinalon <- -122.319080 81 | marinalat <- 37.873242 82 | 83 | marina <- mz_location(lat = marinalat, lon = marinalon) 84 | # based on: http://tools.geofabrik.de/calc/#type=geofabrik_standard&bbox=-122.321657,37.862023,-122.305585,37.870408&grid=1 85 | expect_tiles_contain_xy( 86 | as.mz_tile_coordinates(marina, z = 15), 87 | x = 5250, 88 | y = 12654 89 | ) 90 | }) 91 | -------------------------------------------------------------------------------- /tests/testthat/test-usage-statistics.R: -------------------------------------------------------------------------------- 1 | context("usage-statistics") 2 | 3 | test_that("Usage statistics are updated when header contains new information", { 4 | stats <- usage_recorder() 5 | 6 | header <- list( 7 | date = "Fri, 06 Jan 2017 19:15:25 GMT", 8 | `x-cache` = "MISS", 9 | `x-apiaxleproxy-qpd-left` = 100L, 10 | `x-apiaxleproxy-qps-left` = 5L 11 | ) 12 | 13 | stats("update_search")(header) 14 | search_miss <- stats("view")() 15 | expect_length(search_miss, 3L) 16 | search_stats <- search_miss$search 17 | expect_equal(search_stats$last_updated, "Fri, 06 Jan 2017 19:15:25 GMT") 18 | expect_equal(search_stats$remaining_day, 100) 19 | expect_equal(search_stats$remaining_second, 5) 20 | expect_true( 21 | setequal(names(search_miss), c("search", "matrix", "tile")) 22 | ) 23 | prev <- search_miss 24 | 25 | # no updates if cache hit 26 | header <- list( 27 | date = "Fri, 06 Jan 2017 19:15:25 GMT", 28 | `x-cache` = "HIT", 29 | `x-apiaxleproxy-qpd-left` = 12, 30 | `x-apiaxleproxy-qps-left` = 0 31 | ) 32 | stats("update_search")(header) 33 | # nothing should have updated 34 | expect_equal(stats("view")(), prev) 35 | 36 | newheader <- list( 37 | date = "Fri, 06 Jan 2017 19:15:25 GMT", 38 | `x-apiaxleproxy-qpd-left` = 100L, 39 | `x-apiaxleproxy-qps-left` = 5L 40 | ) 41 | 42 | stats("update_matrix")(newheader) 43 | stats("update_tile")(newheader) 44 | updated_stats <- stats("view")() 45 | expect_equal(updated_stats$matrix$last_updated, "Fri, 06 Jan 2017 19:15:25 GMT") 46 | expect_equal(updated_stats$matrix$remaining_day, 100) 47 | expect_equal(updated_stats$matrix$remaining_second, 5) 48 | 49 | expect_equal(updated_stats$tile$last_updated, "Fri, 06 Jan 2017 19:15:25 GMT") 50 | expect_equal(updated_stats$tile$remaining_day, 100) 51 | expect_equal(updated_stats$tile$remaining_second, 5) 52 | prev <- updated_stats 53 | 54 | # tiles shouldn't update unless there is a full header of info 55 | tile_cache_header <- list( 56 | `x-apiaxleproxy-qpd-left` = 18 57 | ) 58 | stats("update_tile")(tile_cache_header) 59 | expect_equal(stats("view")(), prev) 60 | 61 | }) 62 | -------------------------------------------------------------------------------- /vignettes/rmapzen-introduction.Rmd: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introduction to rmapzen" 3 | author: "Tarak Shah" 4 | date: "`r Sys.Date()`" 5 | output: rmarkdown::html_vignette 6 | vignette: > 7 | %\VignetteIndexEntry{Introduction to rmapzen} 8 | %\VignetteEncoding{UTF-8} 9 | %\VignetteEngine{knitr::rmarkdown} 10 | editor_options: 11 | chunk_output_type: console 12 | --- 13 | 14 | ```{r setup, include = FALSE} 15 | knitr::opts_chunk$set( 16 | collapse = TRUE, 17 | comment = "#>" 18 | ) 19 | ``` 20 | ## Introduction 21 | 22 | `rmapzen` is a client for any implementation of the Mapzen API. Though Mapzen itself has [gone out of business](https://www.mapzen.com/blog/shutdown/), `rmapzen` can be set up to work with any provider who hosts Mapzen's open-source software, including [geocode.earth](https://geocode.earth/), [Nextzen](https://www.nextzen.org/), and [NYC GeoSearch from NYC Planning Labs](https://geosearch.planninglabs.nyc/). For more information, see [https://www.mapzen.com/documentation/](https://www.mapzen.com/documentation/). The project is [available on github](https://github.com/tarakc02/rmapzen) as well as [CRAN](https://cran.r-project.org/package=rmapzen). 23 | 24 | `rmapzen` provides access to the following Mapzen API services: 25 | 26 | - [Search](https://github.com/pelias/documentation/): Structured and unstructured search and geocoding, reverse geocoding, and autocomplete. 27 | - [Vector Tiles](https://tilezen.readthedocs.io/en/latest/): Basemap vector data. 28 | - [Isochrone](https://valhalla.readthedocs.io/en/latest/): Calculation of areas reachable from a specified locations. 29 | 30 | ## Set-up 31 | 32 | `rmapzen` works with API providers who implement the Mapzen API. In order to specify provider information (such as URL and API key), use `mz_set_host`. There are custom set-up functions for the following providers: 33 | 34 | - [geocode.earth](https://geocode.earth/), for search services. Use the function `mz_set_search_host_geocode.earth` 35 | - [Nextzen](https://www.nextzen.org/), for vector tiles. Use the function `mz_set_tile_host_nextzen`. 36 | - [NYC GeoSearch](https://geosearch.planninglabs.nyc/), for search services using New York City's Property Address Directory. Use `mz_set_search_host_nyc_geosearch`. 37 | 38 | As of this writing, there are no public providers offering the Mapzen isochrone service. 39 | 40 | ## Search 41 | 42 | All of the services in [Mapzen search](https://github.com/pelias/documentation/) have been implemented. Search functions: 43 | 44 | * `mz_search` 45 | * `mz_reverse_geocode` 46 | * `mz_autocomplete` 47 | * `mz_place` 48 | * `mz_structured_search` ([what's this?](https://github.com/pelias/documentation/blob/master/structured-geocoding.md)) 49 | 50 | Each of those functions returns a `mapzen_geo_list`. The sample dataset `oakland_public` contains the results of `mz_search("Oakland public library branch")` on January 8, 2017: 51 | 52 | ```{r loadmapzen, echo = FALSE} 53 | library(rmapzen) 54 | oakland_public 55 | ``` 56 | 57 | ```{r} 58 | mz_bbox(oakland_public) 59 | as.data.frame(oakland_public) 60 | ``` 61 | 62 | Search can, optionally, be constrained to a particular country, data layer, boundary rectangle, or boundary circle. Furthermore, search can prioritize results near a given "focus" point. See `?mz_search`. 63 | 64 | ## Vector tile service 65 | 66 | `rmapzen` provides an interface to Mapzen's [vector tiles service](https://tilezen.readthedocs.io/en/latest/). Tile requests can be specified using the x, y, zoom coordinates of the tile service, as well as with a lat/long bounding box. Multiple tiles are stitched together and returned as an object of class `mz_vector_tiles`. See `?mz_vector_tiles`. The sample data set `ca_tiles` contains zoomed out vector tile data for all of California as well as parts of neighboring states. 67 | 68 | ```{r} 69 | ca_tiles 70 | ``` 71 | 72 | Each element of a vector tile response includes point, line, and/or polygon data for an individual map layer, and has class `mapzen_vector_layer`. Like other response types, the `mapzen_vector_layer` can be converted to `sf` objects for further processing, using the generic function `as_sf` 73 | 74 | ```{r} 75 | # points of interest 76 | as_sf(ca_tiles$pois) 77 | ``` 78 | 79 | ## `sf` conversion 80 | 81 | Any object returned by a Mapzen service can be converted to the appropriate `sf` object using the generic `as_sf`, for easy interoperability with other packages. You can also convert most objects directly to data frames, allowing for use within tidy pipelines: 82 | 83 | ```{r ex-tidy, warning = FALSE, message = FALSE} 84 | library(dplyr) 85 | library(sf) 86 | as_sf(oakland_public) %>% 87 | select(name, confidence, region, locality, neighbourhood) 88 | ``` 89 | 90 | ## Accessor methods 91 | 92 | Currently, the following methods are available to pull out commonly used 93 | pieces of a response: 94 | 95 | * `mz_coordinates` (only available for search results): extracts lat/lon coordinates from search results, and returns them as a `data.frame`. 96 | * `mz_bbox`: returns the bounding box of an object as a `data.frame` with columns `min_lon`, `min_lat`, `max_lon`, and `max_lat`. 97 | 98 | ```{r ex-accessors} 99 | mz_bbox(ca_tiles) 100 | ``` 101 | --------------------------------------------------------------------------------