├── .Rbuildignore ├── .gitattributes ├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md └── workflows │ ├── R-CMD-check.yaml │ └── test-coverage.yaml ├── .gitignore ├── .hooks └── description ├── .pre-commit-config.yaml ├── CONTRIBUTING.md ├── DESCRIPTION ├── NAMESPACE ├── NEWS.md ├── R ├── RcppExports.R ├── elevation.R ├── features.R ├── get-osmdata-df.R ├── get-osmdata-sc.R ├── get-osmdata-sf.R ├── get-osmdata-sp.R ├── get-osmdata-xml.R ├── get-osmdata.R ├── getbb.R ├── opq.R ├── osm-extract.R ├── osmdata-class.R ├── osmdata-methods.R ├── osmdata-package.R ├── overpass-query.R ├── poly2line.R ├── reproj.R ├── trim-osmdata.R ├── unique-osmdata.R ├── utils.R ├── wkt4326.R └── zzz.R ├── README.Rmd ├── README.md ├── _pkgdown.yml ├── cleanup ├── codemeta.json ├── cran-comments.md ├── data-raw └── hex-script.Rmd ├── inst ├── CITATION └── httptest2 │ └── redact.R ├── makefile ├── man ├── add_osm_feature.Rd ├── add_osm_features.Rd ├── available_features.Rd ├── available_tags.Rd ├── bbox_to_string.Rd ├── figures │ ├── logo.png │ └── title.png ├── get_overpass_url.Rd ├── getbb.Rd ├── opq.Rd ├── opq_around.Rd ├── opq_csv.Rd ├── opq_enclosing.Rd ├── opq_osm_id.Rd ├── opq_string.Rd ├── osm_elevation.Rd ├── osm_lines.Rd ├── osm_multilines.Rd ├── osm_multipolygons.Rd ├── osm_points.Rd ├── osm_poly2line.Rd ├── osm_polygons.Rd ├── osmdata.Rd ├── osmdata_data_frame.Rd ├── osmdata_sc.Rd ├── osmdata_sf.Rd ├── osmdata_sp.Rd ├── osmdata_xml.Rd ├── overpass_status.Rd ├── pipe.Rd ├── set_overpass_url.Rd ├── trim_osmdata.Rd ├── unique_osmdata.Rd └── unname_osmdata_sf.Rd ├── osmdata.Rproj ├── paper.md ├── src ├── RcppExports.cpp ├── common.cpp ├── common.h ├── convert-osm-rcpp.cpp ├── convert-osm-rcpp.h ├── get-bbox.cpp ├── get-bbox.h ├── osmdata-data_frame.cpp ├── osmdata-sc.cpp ├── osmdata-sc.h ├── osmdata-sf.cpp ├── osmdata-sp.cpp ├── osmdata.h ├── osmdata_init.c ├── rapidxml.h ├── rapidxml_print.h ├── trace-osm.cpp └── trace-osm.h ├── tests ├── testthat.R ├── testthat │ ├── fixtures │ │ ├── osm-adiff2.osm │ │ ├── osm-date.osm │ │ ├── osm-empty.osm │ │ ├── osm-key_clashes.osm │ │ ├── osm-meta.osm │ │ ├── osm-meta_adiff.osm │ │ ├── osm-meta_diff.osm │ │ ├── osm-multi.osm │ │ ├── osm-tags.osm │ │ ├── osm-tags_center-adiff.osm │ │ ├── osm-tags_center.osm │ │ └── osm-ways.osm │ ├── mock_bb │ │ └── nominatim │ │ │ └── search-619814.json │ ├── mock_bb_df │ │ └── nominatim │ │ │ └── search-619814.json │ ├── mock_bb_nope │ │ └── nominatim │ │ │ └── search-619814.json │ ├── mock_bb_poly │ │ └── nominatim │ │ │ └── search-c1f6d2.json │ ├── mock_bb_sf │ │ └── nominatim │ │ │ └── search-c1f6d2.json │ ├── mock_bb_state │ │ └── nominatim │ │ │ └── search-226ae6.json │ ├── mock_bb_str │ │ └── nominatim │ │ │ └── search-619814.json │ ├── mock_bb_typo │ │ └── nominatim │ │ │ └── search-c218d5.json │ ├── mock_csv │ │ └── overpass-api.de │ │ │ └── api │ │ │ ├── interpreter-14ea8d-POST.csv │ │ │ └── status.txt │ ├── mock_csv_quotes │ │ └── overpass-api.de │ │ │ └── api │ │ │ ├── interpreter-6aa0b4-POST.csv │ │ │ └── status.txt │ ├── mock_elevation │ │ └── overpass-api.de │ │ │ └── api │ │ │ ├── interpreter-f7f678-POST.R │ │ │ └── status.txt │ ├── mock_features │ │ └── wiki │ │ │ └── Map_Features.html │ ├── mock_osm_df │ │ └── overpass-api.de │ │ │ └── api │ │ │ ├── interpreter-f7f678-POST.R │ │ │ └── status.txt │ ├── mock_osm_sc │ │ └── overpass-api.de │ │ │ └── api │ │ │ ├── interpreter-f7f678-POST.R │ │ │ └── status.txt │ ├── mock_osm_sf │ │ └── overpass-api.de │ │ │ └── api │ │ │ ├── interpreter-f7f678-POST.R │ │ │ └── status.txt │ ├── mock_osm_sp │ │ └── overpass-api.de │ │ │ └── api │ │ │ ├── interpreter-f7f678-POST.R │ │ │ └── status.txt │ ├── mock_osm_xml │ │ └── overpass-api.de │ │ │ └── api │ │ │ ├── interpreter-f7f678-POST.R │ │ │ └── status.txt │ ├── mock_osm_xml2 │ │ └── overpass-api.de │ │ │ └── api │ │ │ ├── interpreter-f7f678-POST.R │ │ │ └── status.txt │ ├── mock_tags │ │ └── wiki │ │ │ └── Map_Features.html │ ├── mock_tags_fail │ │ └── wiki │ │ │ └── Map_Features.html │ ├── mock_unname │ │ └── overpass-api.de │ │ │ └── api │ │ │ ├── interpreter-f7f678-POST.R │ │ │ └── status.txt │ ├── setup.R │ ├── test-c.R │ ├── test-data_frame-osm.R │ ├── test-elevation.R │ ├── test-extract.R │ ├── test-features.R │ ├── test-getbb.R │ ├── test-opq.R │ ├── test-osmdata.R │ ├── test-sc-osm.R │ ├── test-set_bind_key_pre.R │ ├── test-sf-construction.R │ ├── test-sf-osm.R │ ├── test-sp-osm.R │ ├── test-trim.R │ ├── test-unique.R │ └── test-unname.R ├── timing-benchmark.R └── valgrind-test.R └── vignettes ├── makefile ├── osm-sf-translation.Rmd ├── osmdata-refs.bib ├── osmdata-sc.Rmd ├── osmdata.Rmd └── query-split.Rmd /.Rbuildignore: -------------------------------------------------------------------------------- 1 | ^.*\.Rproj$ 2 | ^CODE_OF_CONDUCT\.md$ 3 | ^CONTRIBUTING.md$ 4 | ^CRAN-SUBMISSION$ 5 | ^README\.Rmd$ 6 | ^README\.html$ 7 | ^\.Rproj\.user$ 8 | ^\.github$ 9 | ^\.pre-commit-config\.yaml$ 10 | ^\.travis\.yml$ 11 | ^_pkgdown\.yml$ 12 | ^aaa\.Rmd$ 13 | ^appveyor\.yml$ 14 | ^codemeta\.json$ 15 | ^configure$ 16 | ^cran-comments.md$ 17 | ^docs/ 18 | ^fig/ 19 | ^inst/WORDLIST$ 20 | ^paper\.md$ 21 | ^revdep$ 22 | ^src/Makevars$ 23 | ^src/Makevars.in$ 24 | ^tests/timing-benchmark.R$ 25 | data-raw/ 26 | hooks/ 27 | makefile$ 28 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | data/* binary 3 | src/* text=lf 4 | R/* text=lf 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG] " 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Steps to follow in reporting a bug with `osmdata`** 11 | 12 | Please follow all of the following steps, and only submit once you've checked all boxes (where appropriate). 13 | 14 | - [ ] Download data locally via `osmdata_xml(q, filename = "myfile.xml")` (where `q` is your query) 15 | - [ ] Use the [`reprex` package](https://reprex.tidyverse.org/) to reproduce your bug, including a `setwd()` command at the start to ensure you are in the directory where you've downloaded your data 16 | - [ ] Include comparison with equivalent results from the `sf` package using the code shown below 17 | - [ ] Paste the result in the indicated section below 18 | - [ ] Delete the `setwd()` line from the pasted result 19 | - [ ] Include the output of both `packageVersion("osmdata")` and `R.Version()$version.string` 20 | - [ ] Alternatively, include the full output of `sessionInfo()` 21 | 22 | 23 | ### Paste `reprex` output here 24 | 25 | Please include the following lines: 26 | ``` r 27 | # 28 | 29 | library(sf) 30 | st_layers("myfile.xml") # give information on available layers 31 | st_read("myfile.xml", layer = ) 32 | 33 | packageVersion("osmdata") 34 | R.Version()$version.string 35 | #sessionInfo() 36 | ``` 37 | 38 | 39 | 40 | ***If you are constructing or using a specialized `overpass` query*** 41 | 42 | - [ ] I have tried my query on [overpass-turbo.eu](https://overpass-turbo.eu), and it works 43 | - [ ] I confirm that the data returned on [overpass-turbo.eu](https://overpass-turbo.eu) are identical to those returned from the equivalent call to `osmdata_xml(q, filename = "myfile.xml`)`. 44 | 45 | Thanks! :smile: 46 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Request a new or modified feature 4 | title: "[FEATURE] " 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Steps to follow in requesting a feature with `osmdata`** 11 | 12 | 1. Please ensure that what you are requesting is compatible with the underlying structure of Open Street Map (OSM) itself, for example by searching the [OSM wiki](https://wiki.openstreetmap.org/wiki/Main_Page) or the overview of the [overpass Query Language](https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL) for all relevant information. Please include links to any relevant pages in your issue. 13 | 2. Please provide reproducible code generated by the [`reprex` package](https://reprex.tidyverse.org) to demonstrate current behaviour of `osmdata` which you would like changed or improved, including the following lines in your `reprex`: 14 | ``` r 15 | # 16 | 17 | packageVersion("osmdata") 18 | R.Version()$version.string 19 | #sessionInfo() 20 | ``` 21 | 3. Please use the results of the preceding step to explain precisely what you would like modified from or added to the results as given. 22 | 23 | 24 | Thanks! :smile: 25 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | pull_request: 6 | branches: 7 | - main 8 | 9 | name: R-CMD-check.yaml 10 | 11 | permissions: read-all 12 | 13 | jobs: 14 | 15 | R-CMD-check: 16 | 17 | runs-on: ${{ matrix.config.os }} 18 | 19 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 20 | 21 | strategy: 22 | fail-fast: false 23 | matrix: 24 | config: 25 | - {os: macos-latest, r: 'release'} 26 | - {os: windows-latest, r: 'release'} 27 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 28 | - {os: ubuntu-latest, r: 'release'} 29 | - {os: ubuntu-latest, r: 'oldrel-1'} 30 | 31 | env: 32 | R_REMOTES_NO_ERRORS_FROM_WARNINGS: true 33 | R_KEEP_PKG_SOURCE: yes 34 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 35 | 36 | steps: 37 | - uses: actions/checkout@v4 38 | 39 | - uses: r-lib/actions/setup-pandoc@v2 40 | 41 | - uses: r-lib/actions/setup-r@v2 42 | with: 43 | r-version: ${{ matrix.config.r }} 44 | http-user-agent: ${{ matrix.config.http-user-agent }} 45 | use-public-rspm: true 46 | 47 | - uses: r-lib/actions/setup-r-dependencies@v2 48 | with: 49 | extra-packages: any::rcmdcheck 50 | needs: check 51 | 52 | - uses: r-lib/actions/check-r-package@v2 53 | with: 54 | upload-snapshots: true 55 | build_args: 'c("--no-manual","--compact-vignettes=gs+qpdf")' 56 | -------------------------------------------------------------------------------- /.github/workflows/test-coverage.yaml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | pull_request: 6 | branches: 7 | - main 8 | 9 | name: test-coverage.yaml 10 | 11 | permissions: read-all 12 | 13 | jobs: 14 | 15 | test-coverage: 16 | 17 | runs-on: ubuntu-latest 18 | 19 | env: 20 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 21 | 22 | steps: 23 | - uses: actions/checkout@v4 24 | 25 | - uses: r-lib/actions/setup-r@v2 26 | with: 27 | use-public-rspm: true 28 | 29 | - uses: r-lib/actions/setup-r-dependencies@v2 30 | with: 31 | extra-packages: any::covr, any::xml2 32 | needs: coverage 33 | 34 | - name: Test coverage 35 | run: | 36 | cov <- covr::package_coverage( 37 | quiet = FALSE, 38 | clean = FALSE, 39 | install_path = file.path(normalizePath(Sys.getenv("RUNNER_TEMP"), winslash = "/"), "package"), 40 | line_exclusions = list('R/overpass-query.R', 'src/rapidxml.h','src/rapidxml_print.h'),function_exclusions=c('osm_elevation','check_elev_file') 41 | ) 42 | covr::to_cobertura(cov) 43 | shell: Rscript {0} 44 | 45 | - uses: codecov/codecov-action@v4 46 | with: 47 | # Fail if error if not on PR, or if on PR and token is given 48 | fail_ci_if_error: ${{ github.event_name != 'pull_request' || secrets.CODECOV_TOKEN }} 49 | file: ./cobertura.xml 50 | plugin: noop 51 | disable_search: true 52 | token: ${{ secrets.CODECOV_TOKEN }} 53 | 54 | - name: Show testthat output 55 | if: always() 56 | run: | 57 | ## -------------------------------------------------------------------- 58 | find '${{ runner.temp }}/package' -name 'testthat.Rout*' -exec cat '{}' \; || true 59 | shell: bash 60 | 61 | - name: Upload test results 62 | if: failure() 63 | uses: actions/upload-artifact@v4 64 | with: 65 | name: coverage-test-failures 66 | path: ${{ runner.temp }}/package 67 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | inst/doc 5 | inst/WORDLIST 6 | # History files 7 | .Rhistory 8 | .Rapp.history 9 | # Session Data files 10 | .RData 11 | # Output files from R CMD build 12 | /*.tar.gz 13 | # vim files 14 | .*.un~ 15 | .*.swp 16 | src/*.o 17 | -------------------------------------------------------------------------------- /.hooks/description: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env Rscript 2 | 3 | s <- gert::git_status() 4 | chk <- ("DESCRIPTION" %in% s$file && 5 | (s$status [s$file == "DESCRIPTION"] == "modified" | 6 | s$status [s$file == "DESCRIPTION"] == "new")) 7 | if (!chk) 8 | stop ("DESCRIPTION has not been updated") 9 | 10 | f <- file.path (rprojroot::find_root("DESCRIPTION"), "DESCRIPTION") 11 | x <- system2 ("git", args = c ("diff", "--cached", "-U0", f), stdout = TRUE) 12 | if (!any (grepl ("^\\+Version", x))) 13 | stop ("Version number in DESCRIPTION has not been incremented") 14 | -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | # All available hooks: https://pre-commit.com/hooks.html 2 | # R specific hooks: https://github.com/lorenzwalthert/precommit 3 | repos: 4 | - repo: https://github.com/lorenzwalthert/precommit 5 | rev: v0.4.3.9009 6 | hooks: 7 | - id: style-files 8 | args: [--style_pkg=spaceout, --style_fun=spaceout_style] 9 | additional_dependencies: 10 | - ropensci-review-tools/spaceout 11 | # - id: roxygenize 12 | # codemeta must be above use-tidy-description when both are used 13 | # - id: codemeta-description-updated 14 | - id: use-tidy-description 15 | - id: spell-check 16 | exclude: > 17 | (?x)^( 18 | .*\.[rR]| 19 | .*\.feather| 20 | .*\.jpeg| 21 | .*\.pdf| 22 | .*\.png| 23 | .*\.py| 24 | .*\.RData| 25 | .*\.rds| 26 | .*\.Rds| 27 | .*\.Rproj| 28 | .*\.sh| 29 | (.*/|)\.gitignore| 30 | (.*/|)\.gitlab-ci\.yml| 31 | (.*/|)\.lintr| 32 | (.*/|)\.pre-commit-.*| 33 | (.*/|)\.Rbuildignore| 34 | (.*/|)\.Renviron| 35 | (.*/|)\.Rprofile| 36 | (.*/|)\.travis\.yml| 37 | (.*/|)appveyor\.yml| 38 | (.*/|)NAMESPACE| 39 | (.*/|)renv/settings\.dcf| 40 | (.*/|)renv\.lock| 41 | (.*/|)WORDLIST| 42 | \.github/workflows/.*| 43 | data/.*| 44 | )$ 45 | # - id: lintr 46 | - id: readme-rmd-rendered 47 | - id: parsable-R 48 | - id: no-browser-statement 49 | - id: no-print-statement 50 | - id: no-debug-statement 51 | - id: deps-in-desc 52 | # - id: pkgdown 53 | - repo: https://github.com/pre-commit/pre-commit-hooks 54 | rev: v5.0.0 55 | hooks: 56 | - id: check-added-large-files 57 | args: ['--maxkb=200'] 58 | - id: file-contents-sorter 59 | files: '^\.Rbuildignore$' 60 | - id: end-of-file-fixer 61 | exclude: '\.Rd' 62 | - repo: https://github.com/pre-commit-ci/pre-commit-ci-config 63 | rev: v1.6.1 64 | hooks: 65 | # Only required when https://pre-commit.ci is used for config validation 66 | - id: check-pre-commit-ci-config 67 | - repo: local 68 | hooks: 69 | - id: forbid-to-commit 70 | name: Don't commit common R artifacts 71 | entry: Cannot commit .Rhistory, .RData, .Rds or .rds. 72 | language: fail 73 | files: '\.(Rhistory|RData|Rds|rds)$' 74 | # `exclude: ` to allow committing specific files 75 | - id: description version 76 | name: Version has been incremeneted in DESCRIPTION 77 | entry: .hooks/description 78 | language: script 79 | 80 | ci: 81 | autoupdate_schedule: monthly 82 | # skip: [pkgdown] 83 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to osmdata 2 | 3 | ## Opening issues 4 | 5 | The easiest way to note any behavioural curiosities or to request any new 6 | features is by opening a [github issue](https://github.com/ropensci/osmdata/issues). 7 | 8 | 9 | ## Development guidelines 10 | 11 | If you'd like to contribute changes to `osmdata`, we use [the GitHub 12 | flow](https://guides.github.com/introduction/flow/index.html) for proposing, 13 | submitting, reviewing, and accepting changes. If you haven't done this before, 14 | there's a nice overview of git [here](http://r-pkgs.had.co.nz/git.html), as well 15 | as best practices for submitting pull requests 16 | [here](http://r-pkgs.had.co.nz/git.html#pr-make). 17 | 18 | The `osmdata` coding style diverges somewhat from [this commonly used R style 19 | guide](http://adv-r.had.co.nz/Style.html), primarily in the following two ways, 20 | both of which improve code readability: (1) All curly braces are vertically 21 | aligned: 22 | 23 | ```r 24 | this <- function () 25 | { 26 | x <- 1 27 | } 28 | ``` 29 | and **not** 30 | ```r 31 | this <- function(){ 32 | x <- 1 33 | } 34 | ``` 35 | and (2) Also highlighted in that code is the additional whitespace which 36 | permeates `osmdata` code. Words of text are separated by whitespace, and so 37 | code words should be too: 38 | ```r 39 | this <- function1 (function2 (x)) 40 | ``` 41 | and **not** 42 | ```r 43 | this <- function1(function2(x)) 44 | ``` 45 | with the natural result that one ends up writing 46 | ```r 47 | this <- function () 48 | ``` 49 | with a space between `function` and `()`. That's it. 50 | 51 | You can use `precommit::use_precommit()` to enforce this style with git commit 52 | hooks as defined in `.pre-commit-config.yaml`. The first commit can be slow 53 | because the hooks have to be compiled and installed. To commit ignoring hooks, 54 | `git commit --no-verify`, or shortened version, `git commit -n`. 55 | 56 | ## Maintenance 57 | 58 | To refresh the `README.md` file after modifying `README.Rmd`, use: 59 | ```r 60 | devtools::build_readme(output_format="md_document") 61 | ``` 62 | 63 | When updating the package dependencies in `DESCRIPTION` or other metadata, 64 | refresh `codemeta.json`: 65 | ```r 66 | codemetar::write_codemeta() 67 | ``` 68 | 69 | ## Code of Conduct 70 | 71 | We want to encourage a warm, welcoming, and safe environment for contributing to 72 | this project. See the [code of 73 | conduct](https://github.com/ropensci/.github/blob/master/CODE_OF_CONDUCT.md) for 74 | more information. 75 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: osmdata 2 | Title: Import 'OpenStreetMap' Data as Simple Features or Spatial Objects 3 | Version: 0.2.5.033 4 | Authors@R: c( 5 | person("Mark", "Padgham", , "mark.padgham@email.com", role = c("aut", "cre")), 6 | person("Bob", "Rudis", role = "aut"), 7 | person("Robin", "Lovelace", role = "aut"), 8 | person("Maëlle", "Salmon", role = "aut"), 9 | person("Joan", "Maspons", role = "aut", 10 | comment = c(ORCID="0000-0003-2286-8727")), 11 | person("Andrew", "Smith", role = "ctb"), 12 | person("James", "Smith", role = "ctb"), 13 | person("Andrea", "Gilardi", role = "ctb"), 14 | person("Enrico", "Spinielli", role = "ctb"), 15 | person("Anthony", "North", role = "ctb"), 16 | person("Martin", "Machyna", role = "ctb"), 17 | person("Marcin", "Kalicinski", role = c("ctb", "cph"), 18 | comment = "Author of included RapidXML code"), 19 | person("Eli", "Pousson", , "eli.pousson@gmail.com", role = c("ctb"), 20 | comment = c(ORCID = "0000-0001-8280-1706")) 21 | ) 22 | Maintainer: Mark Padgham 23 | Description: Download and import of 'OpenStreetMap' ('OSM') data as 'sf' 24 | or 'sp' objects. 'OSM' data are extracted from the 'Overpass' web 25 | server () and processed with very fast 'C++' 26 | routines for return to 'R'. 27 | License: GPL-3 28 | URL: https://docs.ropensci.org/osmdata/ (website) 29 | https://github.com/ropensci/osmdata/ (devel) 30 | BugReports: https://github.com/ropensci/osmdata/issues 31 | Depends: 32 | R (>= 3.2.4) 33 | Imports: 34 | curl, 35 | httr2, 36 | lubridate, 37 | magrittr, 38 | methods, 39 | Rcpp (>= 0.12.4), 40 | reproj, 41 | rvest, 42 | tibble, 43 | utils, 44 | xml2 45 | Suggests: 46 | httptest2, 47 | jsonlite, 48 | knitr, 49 | markdown, 50 | raster, 51 | rmarkdown, 52 | sf, 53 | sp, 54 | testthat 55 | LinkingTo: 56 | Rcpp 57 | VignetteBuilder: 58 | knitr 59 | Encoding: UTF-8 60 | NeedsCompilation: yes 61 | Roxygen: list(markdown = TRUE) 62 | RoxygenNote: 7.3.1 63 | X-schema.org-applicationCategory: Data Access 64 | X-schema.org-isPartOf: https://ropensci.org 65 | X-schema.org-keywords: open0street0map, openstreetmap, overpass0API, OSM 66 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(c,osmdata) 4 | S3method(c,osmdata_sc) 5 | S3method(print,osmdata) 6 | export("%>%") 7 | export(add_osm_feature) 8 | export(add_osm_features) 9 | export(available_features) 10 | export(available_tags) 11 | export(bbox_to_string) 12 | export(get_overpass_url) 13 | export(getbb) 14 | export(opq) 15 | export(opq_around) 16 | export(opq_csv) 17 | export(opq_enclosing) 18 | export(opq_osm_id) 19 | export(opq_string) 20 | export(osm_elevation) 21 | export(osm_lines) 22 | export(osm_multilines) 23 | export(osm_multipolygons) 24 | export(osm_points) 25 | export(osm_poly2line) 26 | export(osm_polygons) 27 | export(osmdata) 28 | export(osmdata_data_frame) 29 | export(osmdata_sc) 30 | export(osmdata_sf) 31 | export(osmdata_sp) 32 | export(osmdata_xml) 33 | export(overpass_status) 34 | export(set_overpass_url) 35 | export(trim_osmdata) 36 | export(unique_osmdata) 37 | export(unname_osmdata_sf) 38 | importFrom(Rcpp,evalCpp) 39 | importFrom(magrittr,"%>%") 40 | importFrom(methods,is) 41 | importFrom(methods,slot) 42 | importFrom(utils,browseURL) 43 | importFrom(utils,read.table) 44 | useDynLib(osmdata, .registration = TRUE) 45 | -------------------------------------------------------------------------------- /R/elevation.R: -------------------------------------------------------------------------------- 1 | #' osm_elevation 2 | #' 3 | #' Add elevation data to a previously-extracted OSM data set, using a 4 | #' pre-downloaded global elevation file from 5 | #' \url{https://srtm.csi.cgiar.org/srtmdata/}. Currently only works for 6 | #' `SC`-class objects returned from \link{osmdata_sc}. 7 | #' 8 | #' @param dat An `SC` object produced by \link{osmdata_sc}. 9 | #' @param elev_file A vector of one or more character strings specifying paths 10 | #' to `.tif` files containing global elevation data. 11 | #' 12 | #' @return A modified version of the input `dat` with an additional `z_` column 13 | #' appended to the vertices. 14 | #' @family transform 15 | #' @export 16 | osm_elevation <- function (dat, elev_file) { 17 | 18 | requireNamespace ("raster", quietly = TRUE) 19 | requireNamespace ("sp", quietly = TRUE) 20 | 21 | message ( 22 | "Elevation data from Consortium for Spatial Information; ", 23 | "see http://srtm.csi.cgiar.org/srtmdata/" 24 | ) 25 | 26 | elev_file <- check_elev_file (elev_file) 27 | if (length (elev_file) > 1) { 28 | stop ("not yet") 29 | } 30 | r <- raster::raster (elev_file) 31 | check_bbox (dat, r) 32 | 33 | z <- raster::extract (r, dat$vertex [, 1:2]) 34 | dat$vertex$z_ <- as.double (z) 35 | dat$vertex <- dat$vertex [, c ("x_", "y_", "z_", "vertex_")] 36 | 37 | return (dat) 38 | } 39 | 40 | check_elev_file <- function (elev_file) { 41 | 42 | if (!methods::is (elev_file, "character")) { 43 | stop ("elev_file must be one of more character strings") 44 | } 45 | 46 | base_dir <- dirname (elev_file [1]) 47 | lf <- list.files (base_dir, full.names = TRUE) 48 | ret <- NULL 49 | 50 | for (f in elev_file) { 51 | 52 | if (!file.exists (f)) { 53 | stop ("file ", f, " does not exist") 54 | } 55 | 56 | fe <- tools::file_ext (f) 57 | if (!fe %in% c ("tif", "zip")) { 58 | stop ("Unrecognised file format [.", fe, "]; must be .zip or .tif") 59 | } 60 | 61 | if (fe == "zip") { 62 | 63 | ftif <- paste0 (basename (tools::file_path_sans_ext (f)), ".tif") 64 | index <- grepl (ftif, lf, ignore.case = TRUE) 65 | if (!any (index)) { 66 | message ( 67 | "File ", f, " has not been unzipped; ", 68 | "this may take a while ... ", 69 | appendLF = FALSE 70 | ) 71 | utils::unzip (f, exdir = base_dir) 72 | message ("done.") 73 | lf <- list.files (base_dir, full.names = TRUE) 74 | index <- grepl (ftif, lf, ignore.case = TRUE) 75 | } 76 | 77 | ret <- c (ret, lf [which (index)]) 78 | } else { 79 | ret <- c (ret, f) 80 | } 81 | } 82 | 83 | return (unique (ret)) 84 | } 85 | 86 | check_bbox <- function (dat, r) { 87 | 88 | bb <- as.numeric (strsplit (dat$meta$bbox, ",") [[1]]) 89 | bb <- matrix (bb [c (2, 1, 4, 3)], ncol = 2) 90 | bbr <- sp::bbox (r) 91 | 92 | if (bb [1, 1] < bbr [1, 1] | 93 | bb [1, 2] > bbr [1, 2] | 94 | bb [2, 1] < bbr [2, 1] | 95 | bb [2, 2] > bbr [2, 2]) { 96 | message ("Elevation file does not cover OSM data file") 97 | } 98 | } 99 | 100 | # elevation tiles from http://srtm.csi.cgiar.org/srtmdata 101 | # names are srtm_XX_YY.zip 102 | # XX is 01 for (-180, -175) and 72 for (175, 180) 103 | # so xx <- 36 + floor (-175:180 / 5) 104 | # YY is 01 for (50, 55) and 25 for (-75, -70) 105 | # so yy <- 14 + floor (-65:55 / 5) 106 | get_tile_index <- function (bb) { 107 | 108 | bb <- as.numeric (strsplit (bb, ",") [[1]]) 109 | xi_min <- 36 + floor (bb [2] / 5) 110 | xi_max <- 36 + floor (bb [4] / 5) 111 | yi_min <- 14 + floor (bb [1] / 5) 112 | yi_max <- 14 + floor (bb [3] / 5) 113 | 114 | xi <- as.integer (unique (c (xi_min, xi_max))) 115 | yi <- as.integer (unique (c (yi_min, yi_max))) 116 | 117 | data.frame ( 118 | "xi" = rep (xi, each = length (yi)), 119 | "yi" = rep (yi, times = length (xi)) 120 | ) 121 | } 122 | -------------------------------------------------------------------------------- /R/features.R: -------------------------------------------------------------------------------- 1 | #' List recognized features in OSM 2 | #' 3 | #' @return character vector of all known features 4 | #' 5 | #' @note requires internet access 6 | #' @references 7 | #' 8 | #' @family osminfo 9 | #' @export 10 | #' 11 | #' @examples 12 | #' \dontrun{ 13 | #' available_features () 14 | #' } 15 | available_features <- function () { 16 | 17 | url_ftrs <- "https://wiki.openstreetmap.org/wiki/Map_Features" 18 | 19 | if (curl::has_internet ()) { 20 | 21 | req <- httr2::request (url_ftrs) 22 | resp <- httr2::req_perform (req) 23 | pg <- httr2::resp_body_html (resp) 24 | 25 | keys <- xml2::xml_attr ( 26 | rvest::html_elements (pg, "a[href^='/wiki/Key']"), # nolint 27 | "href" 28 | ) %>% 29 | strsplit ("/wiki/Key:") %>% 30 | unlist () 31 | keys [keys != ""] %>% 32 | sort () %>% 33 | unique () 34 | } else { 35 | message ("No internet connection") 36 | } 37 | } 38 | 39 | #' List tags associated with a feature 40 | #' 41 | #' @param feature feature to retrieve 42 | #' 43 | #' @return character vector of all known tags for a feature 44 | #' 45 | #' @note requires internet access 46 | #' @references 47 | #' 48 | #' @family osminfo 49 | #' @export 50 | #' 51 | #' @examples 52 | #' \dontrun{ 53 | #' available_tags ("aerialway") 54 | #' } 55 | available_tags <- function (feature) { 56 | url_ftrs <- "https://wiki.openstreetmap.org/wiki/Map_Features" 57 | 58 | ret <- NULL 59 | if (curl::has_internet ()) { 60 | 61 | if (missing (feature)) { 62 | stop ("Please specify feature") 63 | } 64 | 65 | req <- httr2::request (url_ftrs) 66 | resp <- httr2::req_perform (req) 67 | pg <- httr2::resp_body_html (resp) 68 | 69 | tags <- get_all_tags (pg) 70 | 71 | if (!feature %in% tags$Key) { 72 | stop ("feature [", feature, "] not listed as Key in ", 73 | url_ftrs, 74 | call. = FALSE 75 | ) 76 | } 77 | 78 | ret <- tags [which (tags$Key == feature), ] 79 | 80 | } else { 81 | message ("No internet connection") 82 | } 83 | return (ret) 84 | } 85 | 86 | #' Get all Key-Value pairs from wiki webpage 87 | #' 88 | #' @noRd 89 | get_all_tags <- function (pg) { 90 | 91 | tags <- rbind (tags_from_tables (pg), tags_from_taglists (pg)) 92 | 93 | tags <- tags [which (!duplicated (tags)), ] 94 | tags <- tags [which (!tags$Key == "Key"), ] 95 | # There are a couple of just entries with "Key" values beginning with "[[ ": 96 | tags <- tags [which (!grepl ("^\\[\\[", tags$Key)), ] 97 | 98 | # Then a non-dplyr group_by and arrange: 99 | tags <- tags [order (tags$Key), ] 100 | tags <- lapply ( 101 | split (tags, f = as.factor (tags$Key)), 102 | function (i) i [order (i$Value), ] 103 | ) 104 | tags <- do.call (rbind, tags) 105 | 106 | return (tags) 107 | } 108 | 109 | #' Get tags from HTML taglist structures (not tables) 110 | #' 111 | #' The wiki page at \url{https://wiki.openstreetmap.org/wiki/Map_Features} now 112 | #' has most data in tables (HTML "td"), but some is still present as older-style 113 | #' "taglist" classes. This function extracts the latter information, to be added 114 | #' to the majority of data extracted from tables. 115 | #' @noRd 116 | tags_from_taglists <- function (pg) { 117 | 118 | taglists <- rvest::html_elements (pg, "div[class='taglist']") %>% 119 | rvest::html_attr ("data-taginfo-taglist-tags") 120 | 121 | taglists <- lapply (taglists, function (i) { 122 | 123 | temp <- strsplit (i, "=") [[1]] 124 | res <- NULL 125 | 126 | if (length (temp) == 2) { 127 | res <- strsplit (temp [2], ",") 128 | names (res) <- temp [1] 129 | } 130 | 131 | return (res) 132 | }) 133 | 134 | taglists [vapply (taglists, is.null, logical (1))] <- NULL 135 | 136 | taglists <- lapply (seq_along (taglists), function (i) { 137 | data.frame ( 138 | Key = rep (names (taglists [[i]]), length (taglists [[i]])), 139 | Value = unlist (taglists [[i]]) 140 | ) 141 | }) 142 | 143 | tags_df <- do.call (rbind, taglists) 144 | rownames (tags_df) <- NULL 145 | 146 | return (tags_df) 147 | } 148 | 149 | #' Get tags from HTML table structures (not taglists) 150 | #' 151 | #' The wiki page at \url{https://wiki.openstreetmap.org/wiki/Map_Features} now 152 | #' has most data in tables (HTML "td"), but some is still present as older-style 153 | #' "taglist" classes. This function extracts the former information, to be added 154 | #' to the small remaining amount of data extracted from taglists. 155 | #' @noRd 156 | tags_from_tables <- function (pg) { 157 | 158 | tables <- rvest::html_table (pg, header = TRUE) 159 | tables <- lapply (tables, function (i) { 160 | if (identical (names (i) [1:2], c ("Key", "Value"))) { 161 | res <- i [, 1:2] 162 | } else { 163 | res <- do.call (rbind, strsplit (i [[1]], split = "=")) 164 | res <- data.frame (res) 165 | names (res) <- c ("Key", "Value") 166 | } 167 | return (res) 168 | }) 169 | 170 | tables <- do.call (rbind, tables) 171 | 172 | return (tables) 173 | } 174 | -------------------------------------------------------------------------------- /R/get-osmdata-sc.R: -------------------------------------------------------------------------------- 1 | #' Return an OSM Overpass query as an \link{osmdata} object in 2 | #' `silicate` (`SC`) format. 3 | #' 4 | #' @inheritParams osmdata_sp 5 | #' @return An object of class `osmdata_sc` representing the original OSM hierarchy 6 | #' of nodes, ways, and relations. 7 | #' 8 | #' @note The `silicate` format is currently highly experimental, and 9 | #' recommended for use only if you really know what you're doing. 10 | #' 11 | #' @family extract 12 | #' @export 13 | #' 14 | #' @examples 15 | #' \dontrun{ 16 | #' hampi_sf <- opq ("hampi india") %>% 17 | #' add_osm_feature (key = "historic", value = "ruins") %>% 18 | #' osmdata_sc () 19 | #' 20 | #' # Complex query as a string (not possible with regular osmdata functions) 21 | #' q <- '[out:xml][timeout:50]; 22 | #' area[name="Països Catalans"][boundary=political]->.boundaryarea; 23 | #' 24 | #' rel(area.boundaryarea)[admin_level=8][boundary=administrative]; 25 | #' map_to_area -> .all_level_8_areas; 26 | #' 27 | #' ( nwr(area.boundaryarea)[amenity=townhall]; >; ); 28 | #' is_in; 29 | #' area._[admin_level=8][boundary=administrative] -> .level_8_areas_with_townhall; 30 | #' 31 | #' (.all_level_8_areas; - .level_8_areas_with_townhall;); 32 | #' rel(pivot); 33 | #' (._; >;); 34 | #' out;' 35 | #' 36 | #' no_townhall <- osmdata_sc (q) 37 | #' no_townhall 38 | #' } 39 | osmdata_sc <- function (q, doc, quiet = TRUE) { 40 | 41 | obj <- osmdata () # class def used here to for fill_overpass_data fn 42 | 43 | if (missing (q)) { 44 | if (missing (doc)) { 45 | stop ( 46 | 'arguments "q" and "doc" are missing, with no default. ', 47 | "At least one must be provided." 48 | ) 49 | } 50 | if (!quiet) { 51 | message ("q missing: osmdata object will not include query") 52 | } 53 | } else if (is (q, "overpass_query")) { 54 | obj$bbox <- q$bbox 55 | obj$overpass_call <- opq_string_intern (q, quiet = quiet) 56 | } else if (is.character (q)) { 57 | obj$overpass_call <- q 58 | } else { 59 | stop ("q must be an overpass query or a character string") 60 | } 61 | 62 | check_not_implemented_queries (obj) 63 | 64 | temp <- fill_overpass_data (obj, doc, quiet = quiet) 65 | obj <- temp$obj 66 | doc <- temp$doc 67 | 68 | if (isTRUE (obj$meta$query_type == "adiff")) { 69 | stop ("adiff queries not yet implemented.") 70 | } 71 | 72 | if (!quiet) { 73 | message ("converting OSM data to sc format") 74 | } 75 | 76 | res <- rcpp_osmdata_sc (paste0 (doc)) 77 | 78 | if (nrow (res$object_link_edge) > 0L) { 79 | res$object_link_edge$native_ <- TRUE 80 | } 81 | 82 | obj <- list () # SC **does not** use osmdata class definition 83 | obj$nodes <- tibble::as_tibble (res$nodes) 84 | obj$relation_members <- tibble::as_tibble (res$relation_members) 85 | obj$relation_properties <- tibble::as_tibble (res$relation_properties) 86 | obj$object <- tibble::as_tibble (res$object) 87 | obj$object_link_edge <- tibble::as_tibble (res$object_link_edge) 88 | obj$edge <- tibble::as_tibble (res$edge) 89 | obj$vertex <- tibble::as_tibble (res$vertex) 90 | obj$meta <- tibble::tibble ( 91 | proj = NA_character_, 92 | ctime = temp$obj$meta$timestamp, 93 | OSM_version = temp$obj$meta$OSM_version, 94 | overpass_version = temp$obj$meta$overpass_version 95 | ) 96 | 97 | has_tags <- c ("nodes", "relation_properties", "object") 98 | obj [has_tags] <- lapply (obj [has_tags], function (x) { 99 | x [, c ("key", "value")] <- setenc_utf8 (x [, c ("key", "value")]) 100 | x 101 | }) 102 | 103 | if (!missing (q)) { 104 | if (!is.character (q)) { 105 | obj$meta$bbox <- q$bbox 106 | } 107 | } else { 108 | obj$meta$bbox <- getbb_sc (obj) 109 | } 110 | 111 | attr (obj, "join_ramp") <- c ( 112 | "nodes", 113 | "relation_members", 114 | "relation_properties", 115 | "object", 116 | "object_link_edge", 117 | "edge", 118 | "vertex" 119 | ) 120 | attr (obj, "class") <- c ("SC", "sc", "osmdata_sc") 121 | 122 | return (obj) 123 | } 124 | 125 | 126 | getbb_sc <- function (x) { 127 | 128 | apply (x$vertex [, 1:2], 2, range) %>% 129 | bbox_to_string () 130 | } 131 | -------------------------------------------------------------------------------- /R/get-osmdata-sp.R: -------------------------------------------------------------------------------- 1 | #' Return an OSM Overpass query as an \link{osmdata} object in \pkg{sp} 2 | #' format. 3 | #' 4 | #' @param q An object of class `overpass_query` constructed with 5 | #' \link{opq} and \link{add_osm_feature} or a string with a valid query, such 6 | #' as `"(node(39.4712701,-0.3841326,39.4713799,-0.3839475);); out;"`. 7 | #' 39.4712701,-0.3841326,39.4713799,-0.3839475 8 | #' May be be omitted, in which case the \link{osmdata} object will not 9 | #' include the query. See examples below. 10 | #' @param doc If missing, `doc` is obtained by issuing the overpass query, 11 | #' `q`, otherwise either the name of a file from which to read data, 12 | #' or an object of class \pkg{xml2} returned from \link{osmdata_xml}. 13 | #' @param quiet suppress status messages. 14 | #' 15 | #' @return An object of class `osmdata` with the OSM components (points, lines, 16 | #' and polygons) represented in \pkg{sp} format. 17 | #' 18 | #' @family extract 19 | #' @export 20 | #' 21 | #' @examples 22 | #' \dontrun{ 23 | #' hampi_sp <- opq ("hampi india") %>% 24 | #' add_osm_feature (key = "historic", value = "ruins") %>% 25 | #' osmdata_sp () 26 | #' 27 | #' # Complex query as a string (not possible with regular osmdata functions) 28 | #' q <- '[out:xml][timeout:50]; 29 | #' area[name="Països Catalans"][boundary=political]->.boundaryarea; 30 | #' 31 | #' rel(area.boundaryarea)[admin_level=8][boundary=administrative]; 32 | #' map_to_area -> .all_level_8_areas; 33 | #' 34 | #' ( nwr(area.boundaryarea)[amenity=townhall]; >; ); 35 | #' is_in; 36 | #' area._[admin_level=8][boundary=administrative] -> .level_8_areas_with_townhall; 37 | #' 38 | #' (.all_level_8_areas; - .level_8_areas_with_townhall;); 39 | #' rel(pivot); 40 | #' (._; >;); 41 | #' out;' 42 | #' 43 | #' no_townhall <- osmdata_sp (q) 44 | #' no_townhall 45 | #' } 46 | osmdata_sp <- function (q, doc, quiet = TRUE) { 47 | 48 | obj <- osmdata () # uses class def 49 | if (missing (q)) { 50 | if (missing (doc)) { 51 | stop ( 52 | 'arguments "q" and "doc" are missing, with no default. ', 53 | "At least one must be provided." 54 | ) 55 | } 56 | if (!quiet) { 57 | message ("q missing: osmdata object will not include query") 58 | } 59 | } else if (is (q, "overpass_query")) { 60 | obj$bbox <- q$bbox 61 | obj$overpass_call <- opq_string_intern (q, quiet = quiet) 62 | } else if (is.character (q)) { 63 | obj$overpass_call <- q 64 | } else { 65 | stop ("q must be an overpass query or a character string") 66 | } 67 | 68 | check_not_implemented_queries (obj) 69 | 70 | temp <- fill_overpass_data (obj, doc, quiet = quiet) 71 | obj <- temp$obj 72 | doc <- temp$doc 73 | 74 | if (isTRUE (obj$meta$query_type == "adiff")) { 75 | # return incorrect result 76 | stop ("adiff queries not yet implemented.") 77 | } 78 | 79 | if (!quiet) { 80 | message ("converting OSM data to sp format") 81 | } 82 | 83 | res <- rcpp_osmdata_sp (paste0 (doc)) 84 | if (is.null (obj$bbox)) { 85 | obj$bbox <- paste (res$bbox, collapse = " ") 86 | } 87 | obj$osm_points <- res$points 88 | obj$osm_lines <- res$lines 89 | obj$osm_polygons <- res$polygons 90 | obj$osm_multilines <- res$multilines 91 | obj$osm_multipolygons <- res$multipolygons 92 | 93 | osm_items <- grep ("^osm_", names (obj)) 94 | obj [osm_items] <- fix_columns_list (obj [osm_items]) 95 | obj [osm_items] <- lapply (obj [osm_items], function (x) { 96 | x@data <- setenc_utf8 (x@data) 97 | x 98 | }) 99 | class (obj) <- c (class (obj), "osmdata_sp") 100 | 101 | return (obj) 102 | } 103 | -------------------------------------------------------------------------------- /R/get-osmdata-xml.R: -------------------------------------------------------------------------------- 1 | #' Return an OSM Overpass query in XML format 2 | #' Read an (XML format) OSM Overpass response from a string, a connection, 3 | #' or a raw vector. 4 | #' 5 | #' @param q An object of class `overpass_query` constructed with 6 | #' \link{opq} and \link{add_osm_feature} or a string with a valid query, such 7 | #' as `"(node(39.4712701,-0.3841326,39.4713799,-0.3839475);); out;"`. See examples below. 8 | #' @param filename If given, OSM data are saved to the named file 9 | #' @param quiet suppress status messages. 10 | #' @param encoding Unless otherwise specified XML documents are assumed to be 11 | #' encoded as UTF-8 or UTF-16. If the document is not UTF-8/16, and lacks 12 | #' an explicit encoding directive, this allows you to supply a default. 13 | #' @return An object of class `xml2::xml_document` containing the result of the 14 | #' overpass API query. 15 | #' 16 | #' @note Objects of class `xml_document` can be saved as `.xml` or 17 | #' `.osm` files with `xml2::write_xml`. 18 | #' 19 | #' @family extract 20 | #' @export 21 | #' 22 | #' @examples 23 | #' \dontrun{ 24 | #' q <- opq ("hampi india") 25 | #' q <- add_osm_feature (q, key = "historic", value = "ruins") 26 | #' osmdata_xml (q, filename = "hampi.osm") 27 | #' 28 | #' # Complex query as a string (not possible with regular osmdata functions) 29 | #' q <- '[out:xml][timeout:50]; 30 | #' area[name="Països Catalans"][boundary=political]->.boundaryarea; 31 | #' 32 | #' rel(area.boundaryarea)[admin_level=8][boundary=administrative]; 33 | #' map_to_area -> .all_level_8_areas; 34 | #' 35 | #' ( nwr(area.boundaryarea)[amenity=townhall]; >; ); 36 | #' is_in; 37 | #' area._[admin_level=8][boundary=administrative] -> .level_8_areas_with_townhall; 38 | #' 39 | #' (.all_level_8_areas; - .level_8_areas_with_townhall;); 40 | #' rel(pivot); 41 | #' out tags;' 42 | #' 43 | #' no_townhall <- osmdata_xml (q) 44 | #' no_townhall 45 | #' } 46 | osmdata_xml <- function (q, filename, quiet = TRUE, encoding) { 47 | 48 | if (missing (encoding)) { 49 | encoding <- "UTF-8" 50 | } 51 | 52 | if (missing (q)) { 53 | stop ('argument "q" is missing, with no default.') 54 | } else if (is (q, "overpass_query")) { 55 | q <- opq_string_intern (q, quiet = quiet) 56 | } else if (!is.character (q)) { 57 | stop ("q must be an overpass query or a character string") 58 | } 59 | 60 | if (grepl ("\\[out:csv", q)) { 61 | stop ("out:csv queries only work with osmdata_data_frame().") 62 | } 63 | 64 | doc <- overpass_query (query = q, quiet = quiet, encoding = encoding) 65 | if (!missing (filename)) { 66 | xml2::write_xml (doc, file = filename) 67 | } 68 | 69 | invisible (doc) 70 | } 71 | -------------------------------------------------------------------------------- /R/osmdata-class.R: -------------------------------------------------------------------------------- 1 | #' osmdata class def 2 | #' 3 | #' @param bbox bounding box 4 | #' @param overpass_call overpass_call 5 | #' @param meta metadata of overpass query, including timestamps and version 6 | #' numbers 7 | #' @param osm_points OSM nodes as \pkg{sf} Simple Features Collection of points 8 | #' or \pkg{sp} SpatialPointsDataFrame 9 | #' @param osm_lines OSM ways \pkg{sf} Simple Features Collection of linestrings 10 | #' or \pkg{sp} SpatialLinesDataFrame 11 | #' @param osm_polygons OSM ways as \pkg{sf} Simple Features Collection of 12 | #' polygons or \pkg{sp} SpatialPolygonsDataFrame 13 | #' @param osm_multilines OSM relations as \pkg{sf} Simple Features Collection 14 | #' of multilinestrings or \pkg{sp} SpatialLinesDataFrame 15 | #' @param osm_multipolygons OSM relations as \pkg{sf} Simple Features 16 | #' Collection of multipolygons or \pkg{sp} 17 | #' SpatialPolygonsDataFrame 18 | #' 19 | #' @note Class constructor should never be used directly, and is only exported 20 | #' to provide access to the print method 21 | #' 22 | #' @family package 23 | #' @export 24 | osmdata <- function (bbox = NULL, overpass_call = NULL, meta = NULL, 25 | osm_points = NULL, osm_lines = NULL, osm_polygons = NULL, 26 | osm_multilines = NULL, osm_multipolygons = NULL) { 27 | 28 | obj <- list ( 29 | bbox = bbox, 30 | overpass_call = overpass_call, 31 | meta = meta, 32 | osm_points = osm_points, 33 | osm_lines = osm_lines, 34 | osm_polygons = osm_polygons, 35 | osm_multilines = osm_multilines, 36 | osm_multipolygons = osm_multipolygons 37 | ) 38 | class (obj) <- append (class (obj), "osmdata") 39 | 40 | return (obj) 41 | } 42 | -------------------------------------------------------------------------------- /R/osmdata-package.R: -------------------------------------------------------------------------------- 1 | #' Import OpenStreetMap data in 'sf', 'SC', 'sp', 'data.frame' and 'xml' formats 2 | #' 3 | #' Imports OpenStreetMap (OSM) data into R as 'sf', 'SC', 'sp', 'data.frame' or 4 | #' 'xml_document' objects. OSM data are extracted from the overpass API and 5 | #' processed with very fast C++ routines for return to R. The package enables 6 | #' simple overpass queries to be constructed without the user necessarily 7 | #' understanding the syntax of the overpass query language, while retaining the 8 | #' ability to handle arbitrarily complex queries. Functions are also provided to 9 | #' enable recursive searching between different kinds of OSM data (for example, 10 | #' to find all lines which intersect a given point). 11 | #' 12 | #' @section Functions to Prepare Queries: 13 | #' \itemize{ 14 | #' \item \link{getbb}: Get bounding box for a given place name 15 | #' \item \link{bbox_to_string}: Convert a named matrix or a named vector 16 | #' (or an unnamed vector) return a string 17 | #' \item \link{overpass_status}: Retrieve status of the overpass API 18 | #' \item \link{opq}: Build an overpass query 19 | #' \item \link{add_osm_feature}: Add a feature to an overpass query 20 | #' \item \link{opq_string}: Convert an osmdata query to overpass API 21 | #' string 22 | #' } 23 | #' 24 | #' @section Functions to Get Additional OSM Information: 25 | #' \itemize{ 26 | #' \item \link{available_features}: List recognised features in OSM 27 | #' \item \link{available_tags}: List tags associated with a feature 28 | #' } 29 | #' 30 | #' @section Functions to Extract OSM Data: 31 | #' \itemize{ 32 | #' \item \link{osmdata_data_frame}: Return OSM data in \code{\link{data.frame}} 33 | #' format 34 | #' \item \link{osmdata_sc}: Return OSM data in \pkg{silicate} format 35 | #' \item \link{osmdata_sf}: Return OSM data in \pkg{sf} format 36 | #' \item \link{osmdata_sp}: Return OSM data in \pkg{sp} format 37 | #' \item \link{osmdata_xml}: Return OSM data in \pkg{xml2} format 38 | #' } 39 | #' 40 | #' @section Functions to Search Data: 41 | #' \itemize{ 42 | #' \item `osm_points`: Extract all `osm_points` objects 43 | #' \item `osm_lines`: Extract all `osm_lines` objects 44 | #' \item `osm_polygons`: Extract all `osm_polygons` objects 45 | #' \item `osm_multilines`: Extract all `osm_multilines` objects 46 | #' \item `osm_multipolygons`: Extract all `osm_multipolygons` objects 47 | #' } 48 | #' 49 | #' @name osmdata 50 | #' @docType package 51 | #' @family package 52 | #' @author Mark Padgham, Bob Rudis, Robin Lovelace, Maëlle Salmon, Joan Maspons 53 | #' @importFrom magrittr %>% 54 | #' @importFrom methods is slot 55 | #' @importFrom Rcpp evalCpp 56 | #' @importFrom utils browseURL read.table 57 | #' @useDynLib osmdata, .registration = TRUE 58 | "_PACKAGE" 59 | 60 | #' Pipe operator 61 | #' 62 | #' @name %>% 63 | #' @rdname pipe 64 | #' @keywords internal 65 | #' @export 66 | #' @importFrom magrittr %>% 67 | #' @usage lhs \%>\% rhs 68 | NULL 69 | -------------------------------------------------------------------------------- /R/poly2line.R: -------------------------------------------------------------------------------- 1 | #' Convert osmdata polygons into lines 2 | #' 3 | #' Street networks downloaded with `add_osm_object(key = "highway")` will 4 | #' store any circular highways in `osm_polygons`. this function combines 5 | #' those with the `osm_lines` component to yield a single \pkg{sf} 6 | #' `data.frame` of all highways, whether polygonal or not. 7 | #' 8 | #' @param osmdat An \link{osmdata} object. 9 | #' @return Modified version of same object with all `osm_polygons` 10 | #' objects merged into `osm_lines`. 11 | #' 12 | #' @note The `osm_polygons` field is retained, with those features also 13 | #' repeated as `LINESTRING` objects in `osm_lines`. 14 | #' 15 | #' @family transform 16 | #' @export 17 | #' @examples 18 | #' \dontrun{ 19 | #' dat <- opq ("colchester uk") %>% 20 | #' add_osm_feature (key = "highway") %>% 21 | #' osmdata_sf () 22 | #' # colchester has lots of roundabouts, and these are stored in 'osm_polygons' 23 | #' # rather than 'osm_lines'. The former can be merged with the latter by: 24 | #' dat2 <- osm_poly2line (dat) 25 | #' # 'dat2' will have more lines than 'dat', but the same number of polygons 26 | #' # (they are left unchanged.) 27 | #' } 28 | osm_poly2line <- function (osmdat) { 29 | 30 | if (!is (osmdat, "osmdata_sf")) { 31 | stop ("osm_poly2line only works for objects of class osmdata_sf") 32 | } 33 | 34 | g <- lapply (osmdat$osm_polygons$geometry, function (i) { 35 | p1 <- i [[1]] 36 | class (p1) <- c ("XY", "LINESTRING", "sfg") 37 | return (p1) 38 | }) 39 | names (g) <- names (osmdat$osm_polygons$geometry) 40 | # then copy all attributes from the lines 41 | attrs <- attributes (osmdat$osm_lines$geometry) 42 | attrs <- attrs [names (attrs) != "names"] 43 | attributes (g) <- c (attributes (g), attrs) 44 | attr (g, "bbox") <- attr (osmdat$osm_polygons$geometry, "bbox") 45 | polys <- osmdat$osm_polygons 46 | polys$geometry <- g 47 | 48 | # use osmdata.c method to join the two sets of lines 49 | newdat <- osmdata () 50 | newdat$osm_lines <- polys 51 | # This has to be put into newdat to ensure fields with no features are 52 | # retained as empty data frames rather than NULL objects 53 | newdat <- c (osmdat, newdat) 54 | osmdat$osm_lines <- newdat$osm_lines 55 | return (osmdat) 56 | } 57 | -------------------------------------------------------------------------------- /R/reproj.R: -------------------------------------------------------------------------------- 1 | # sf::st_crs(4326)$proj4string 2 | # testepsg -e "EPSG:4326" 3 | # testepsg -e "EPSG:3857" 4 | 5 | .sph_merc <- function () { 6 | ## https://github.com/ropensci/mapscanner/issues/33 7 | paste0 ( 8 | "+proj=merc +a=6378137 +b=6378137 ", 9 | "+lat_ts=0 +lon_0=0 +x_0=0 +y_0=0 ", 10 | "+k=1 +units=m +nadgrids=@null +wktext +no_defs" 11 | ) 12 | } 13 | 14 | .lonlat <- function () { 15 | "+proj=longlat +datum=WGS84 +no_defs" 16 | 17 | } 18 | -------------------------------------------------------------------------------- /R/unique-osmdata.R: -------------------------------------------------------------------------------- 1 | #' unique_osmdata 2 | #' 3 | #' Reduce the components of an \link{osmdata} object to only unique items of 4 | #' each type. That is, reduce `$osm_points` to only those points not 5 | #' present in other objects (lines, polygons, etc.); reduce `$osm_lines` to 6 | #' only those lines not present in multiline objects; and reduce 7 | #' `$osm_polygons` to only those polygons not present in multipolygon 8 | #' objects. This renders an \link{osmdata} object more directly compatible with 9 | #' typical output of \pkg{sf}. 10 | #' 11 | #' @param dat An \link{osmdata} object 12 | #' @return Equivalent object reduced to only unique objects of each type 13 | #' @family transform 14 | #' @export 15 | unique_osmdata <- function (dat) { 16 | 17 | if (!is (dat, "osmdata")) { 18 | stop ("dat must be an osmdata object") 19 | } 20 | 21 | if (is (dat$osm_points, "sf")) { 22 | 23 | indx_points <- unique_points_sf (dat) 24 | indx_lines <- unique_lines_sf (dat) 25 | indx_polys <- unique_polygons_sf (dat) 26 | } else { 27 | 28 | indx_points <- unique_points_sp (dat) 29 | indx_lines <- unique_lines_sp (dat) 30 | indx_polys <- unique_polygons_sp (dat) 31 | } 32 | 33 | dat$osm_points <- dat$osm_points [indx_points, ] 34 | dat$osm_lines <- dat$osm_lines [indx_lines, ] 35 | dat$osm_polygons <- dat$osm_polygons [indx_polys, ] 36 | 37 | return (dat) 38 | } 39 | 40 | #' unique_points_sf 41 | #' get index of unique points in the `$osm_points` object 42 | #' @noRd 43 | unique_points_sf <- function (dat) { 44 | 45 | pts <- paste0 (dat$osm_points$osm_id) 46 | 47 | lns_pts <- unlist (lapply (dat$osm_lines$geometry, function (i) { 48 | rownames (i) 49 | })) 50 | names (lns_pts) <- NULL 51 | lns_pts <- unique (lns_pts) 52 | 53 | poly_pts <- unlist (lapply (dat$osm_polygons$geometry, function (i) { 54 | rownames (i [[1]]) 55 | })) 56 | names (poly_pts) <- NULL 57 | poly_pts <- unique (poly_pts) 58 | 59 | which (!pts %in% c (lns_pts, poly_pts)) 60 | } 61 | 62 | #' unique_points_sp 63 | #' get index of unique points in the `$osm_points` object 64 | #' @noRd 65 | unique_points_sp <- function (dat) { 66 | 67 | pts <- rownames (slot (dat$osm_points, "data")) 68 | 69 | lns <- slot (dat$osm_lines, "lines") 70 | lns_pts <- lapply (lns, function (i) { 71 | rownames (slot (slot (i, "Lines") [[1]], "coords")) 72 | }) 73 | lns_pts <- unlist (lns_pts) 74 | names (lns_pts) <- NULL 75 | lns_pts <- unique (lns_pts) 76 | 77 | polys <- slot (dat$osm_polygons, "polygons") 78 | poly_pts <- lapply (polys, function (i) { 79 | rownames (slot (slot (i, "Polygons") [[1]], "coords")) 80 | }) 81 | poly_pts <- unlist (poly_pts) 82 | names (poly_pts) <- NULL 83 | poly_pts <- unique (poly_pts) 84 | 85 | which (!pts %in% c (lns_pts, poly_pts)) 86 | } 87 | 88 | #' unique_lines_sf 89 | #' get index of unique lines in the `$osm_lines` object 90 | #' @noRd 91 | unique_lines_sf <- function (dat) { 92 | 93 | lns <- paste0 (dat$osm_lines$osm_id) 94 | 95 | mlns <- unlist (lapply (dat$osm_multilines$geometry, names)) 96 | names (mlns) <- NULL 97 | mlns <- unique (mlns) 98 | 99 | which (!lns %in% mlns) 100 | } 101 | 102 | #' unique_lines_sp 103 | #' get index of unique lines in the `$osm_lines` object 104 | #' @noRd 105 | unique_lines_sp <- function (dat) { 106 | 107 | lns <- rownames (slot (dat$osm_lines, "data")) 108 | 109 | mlns <- slot (dat$osm_multilines, "lines") [[1]] 110 | mlns <- names (slot (mlns, "Lines")) 111 | mlns <- unique (mlns) 112 | 113 | which (!lns %in% mlns) 114 | } 115 | 116 | #' unique_polygons_sf 117 | #' get index of unique polygons in the `$osm_polygons` object 118 | #' @noRd 119 | unique_polygons_sf <- function (dat) { 120 | 121 | polys <- paste0 (dat$osm_polygons$osm_id) 122 | 123 | mpolys <- unlist (lapply (dat$osm_multipolygons$geometry, function (i) { 124 | names (i [[1]]) 125 | })) 126 | names (mpolys) <- NULL 127 | mpolys <- unique (mpolys) 128 | 129 | which (!polys %in% mpolys) 130 | } 131 | 132 | #' unique_polygons_sp 133 | #' get index of unique polygons in the `$osm_polygons` object 134 | #' @noRd 135 | unique_polygons_sp <- function (dat) { 136 | 137 | polys <- rownames (slot (dat$osm_polygons, "data")) 138 | 139 | mpolys <- slot (dat$osm_multipolygons, "polygons") 140 | mpolys <- unlist (lapply (mpolys, function (i) { 141 | names (slot (i, "Polygons")) 142 | })) 143 | names (mpolys) <- NULL 144 | mpolys <- unique (mpolys) 145 | 146 | which (!polys %in% mpolys) 147 | } 148 | -------------------------------------------------------------------------------- /R/utils.R: -------------------------------------------------------------------------------- 1 | 2 | is_datetime <- function (x) { 3 | 4 | ptn <- "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}[A-Z]$" 5 | grepl (ptn, x) 6 | } 7 | 8 | #' unname_osmdata_sf 9 | #' 10 | #' Remove names from `osmdata` geometry objects, for cases in which these cause 11 | #' issues, particularly with plotting, such as 12 | #' \url{https://github.com/rstudio/leaflet/issues/631}, or 13 | #' \url{https://github.com/r-spatial/sf/issues/1177}. Note that removing these 14 | #' names also removes any ability to inter-relate the different components of an 15 | #' `osmdata` object, so use of this function is only recommended to resolve 16 | #' issues such as those linked to above. 17 | #' 18 | #' @param x An 'osmdata_sf' object returned from function of same name 19 | #' @return Same object, yet with no row names on geometry objects. 20 | #' @family transform 21 | #' @examples 22 | #' \dontrun{ 23 | #' hampi_sf <- opq ("hampi india") %>% 24 | #' add_osm_feature (key = "historic", value = "ruins") %>% 25 | #' osmdata_sf () 26 | #' hampi_clean <- unname_osmdata_sf (hampi_sf) 27 | #' 28 | #' # All coordinate matrices include rownames with OSM ID values: 29 | #' head (as.matrix (hampi_sf$osm_lines$geometry [[1]])) 30 | #' # But 'unname_osmdata_sf' removes both row and column names: 31 | #' head (as.matrix (hampi_clean$osm_lines$geometry [[1]])) 32 | #' } 33 | #' @export 34 | unname_osmdata_sf <- function (x) { 35 | 36 | requireNamespace ("sf") 37 | 38 | x <- unname_osm_points (x) 39 | x <- unname_osm (x, "osm_lines") 40 | x <- unname_osm (x, "osm_polygons") 41 | x <- unname_osm (x, "osm_multilines") 42 | x <- unname_osm (x, "osm_multipolygons") 43 | 44 | return (x) 45 | } 46 | 47 | unname_osm_points <- function (x) { 48 | 49 | if (nrow (x$osm_points) > 0) { 50 | names (x$osm_points$geometry) <- NULL 51 | } 52 | return (x) 53 | } 54 | 55 | unname_osm <- function (x, what = "osm_lines") { 56 | 57 | if (is.null (x [[what]])) { 58 | return (x) 59 | } 60 | 61 | g <- lapply (x [[what]]$geometry, function (i) unname (i)) 62 | names (g) <- NULL 63 | 64 | if (what == "osm_polygons") { 65 | 66 | g <- lapply (g, function (i) { 67 | rownames (i [[1]]) <- NULL 68 | return (i) }) 69 | 70 | } else if (what == "osm_multilines") { 71 | 72 | g <- lapply (g, function (i) { 73 | sf::st_multilinestring (lapply ( 74 | i, 75 | function (j) unname (j) 76 | )) 77 | }) 78 | 79 | } else if (what == "osm_multipolygons") { 80 | 81 | g <- lapply (g, function (i) { 82 | sf::st_multipolygon (lapply (i, function (j) unname (j))) 83 | }) 84 | } 85 | 86 | x [[what]]$geometry <- sf::st_sfc (g, crs = 4326) 87 | return (x) 88 | } 89 | -------------------------------------------------------------------------------- /R/wkt4326.R: -------------------------------------------------------------------------------- 1 | # sf::st_crs (4326)$wkt 2 | wkt4326 <- 3 | "GEOGCRS[\"WGS 84\", 4 | ENSEMBLE[\"World Geodetic System 1984 ensemble\", 5 | MEMBER[\"World Geodetic System 1984 (Transit)\"], 6 | MEMBER[\"World Geodetic System 1984 (G730)\"], 7 | MEMBER[\"World Geodetic System 1984 (G873)\"], 8 | MEMBER[\"World Geodetic System 1984 (G1150)\"], 9 | MEMBER[\"World Geodetic System 1984 (G1674)\"], 10 | MEMBER[\"World Geodetic System 1984 (G1762)\"], 11 | ELLIPSOID[\"WGS 84\",6378137,298.257223563, 12 | LENGTHUNIT[\"metre\",1]], 13 | ENSEMBLEACCURACY[2.0]], 14 | PRIMEM[\"Greenwich\",0, 15 | ANGLEUNIT[\"degree\",0.0174532925199433]], 16 | CS[ellipsoidal,2], 17 | AXIS[\"geodetic latitude (Lat)\",north, 18 | ORDER[1], 19 | ANGLEUNIT[\"degree\",0.0174532925199433]], 20 | AXIS[\"geodetic longitude (Lon)\",east, 21 | ORDER[2], 22 | ANGLEUNIT[\"degree\",0.0174532925199433]], 23 | USAGE[ 24 | SCOPE[\"Horizontal component of 3D system.\"], 25 | AREA[\"World.\"], 26 | BBOX[-90,-180,90,180]], 27 | ID[\"EPSG\",4326]]" 28 | -------------------------------------------------------------------------------- /R/zzz.R: -------------------------------------------------------------------------------- 1 | # nocov start 2 | .onLoad <- function (libname, pkgname) { # nolint 3 | 4 | op <- options () 5 | 6 | ## https://wiki.openstreetmap.org/wiki/Overpass_API#Public_Overpass_API_instances # nolint 7 | ## see https://github.com/ropensci/osmdata/pull/149 8 | ## Added and edited code here by JimShady to use random API each time. 9 | available_apis <- c ( 10 | "https://overpass-api.de/api/interpreter", 11 | "https://overpass.kumi.systems/api/interpreter" 12 | ) 13 | 14 | op.osmdata <- list ( # nolint 15 | osmdata.base_url = # nolint 16 | sample (available_apis, 1) 17 | ) 18 | 19 | ## End of code edited by JimShady 20 | 21 | toset <- !(names (op.osmdata) %in% names (op)) 22 | if (any (toset)) { 23 | options (op.osmdata [toset]) 24 | } 25 | invisible () 26 | } 27 | # nocov end 28 | 29 | .onAttach <- function (libname, pkgname) { # nolint 30 | msg <- paste0 ( 31 | "Data (c) OpenStreetMap contributors,", 32 | " ODbL 1.0. https://www.openstreetmap.org/copyright" 33 | ) 34 | packageStartupMessage (msg) 35 | } 36 | 37 | #' get_overpass_url 38 | #' 39 | #' Return the URL of the specified overpass API. Default is 40 | #' . 41 | #' 42 | #' @return The overpass API URL 43 | #' 44 | #' @seealso [set_overpass_url()] 45 | #' 46 | #' @family overpass 47 | #' @export 48 | get_overpass_url <- function () { 49 | 50 | op <- options () 51 | if (!"osmdata.base_url" %in% names (op)) { 52 | stop ("overpass can not be retrieved") 53 | } # nocov 54 | options ()$osmdata.base_url 55 | } 56 | 57 | # nocov start 58 | 59 | #' set_overpass_url 60 | #' 61 | #' Set the URL of the specified overpass API. Possible APIs with global coverage 62 | #' are: 63 | #' \itemize{ 64 | #' \item "https://overpass-api.de/api/interpreter" (default) 65 | #' \item "https://overpass.kumi.systems/api/interpreter" 66 | #' \item "https://overpass.osm.rambler.ru/cgi/interpreter" 67 | #' \item "https://api.openstreetmap.fr/oapi/interpreter" 68 | #' \item "https://overpass.osm.vi-di.fr/api/interpreter" 69 | #' } 70 | #' Additional APIs with limited local coverage include: 71 | #' \itemize{ 72 | #' \item "https://overpass.osm.ch/api/interpreter" (Switzerland) 73 | #' \item "https://overpass.openstreetmap.ie/api/interpreter" (Ireland) 74 | #' } 75 | #' 76 | #' For further details, see 77 | #' 78 | #' 79 | #' @param overpass_url The desired overpass API URL 80 | #' 81 | #' @return The overpass API URL 82 | #' 83 | #' @seealso [get_overpass_url()] 84 | #' 85 | #' @family overpass 86 | #' @export 87 | set_overpass_url <- function (overpass_url) { 88 | 89 | # check URL first 90 | if (!grepl ("interpreter", overpass_url)) { 91 | stop ("overpass_url not valid - must end with /interpreter") 92 | } 93 | 94 | old_url <- get_overpass_url () 95 | op <- options () # nolint 96 | op.osmdata <- list (osmdata.base_url = overpass_url) # nolint 97 | options (op.osmdata) 98 | 99 | st <- overpass_status (quiet = TRUE) 100 | if (!"available" %in% names (st)) { 101 | set_overpass_url (old_url) 102 | stop ("overpass_url not valid") 103 | } 104 | 105 | invisible () 106 | } 107 | # nocov end 108 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | title: osmdata 2 | 3 | templates: 4 | params: 5 | bootswatch: cerulean 6 | 7 | reference: 8 | - title: Package doc and class 9 | contents: 10 | - has_concept("package") 11 | - title: Overpass server 12 | contents: 13 | - has_concept("overpass") 14 | - title: Prepare queries 15 | contents: 16 | - has_concept("queries") 17 | - title: Get additional OSM info 18 | contents: 19 | - has_concept("osminfo") 20 | - title: Extract data 21 | contents: 22 | - has_concept("extract") 23 | - title: Search data 24 | contents: 25 | - has_concept("search") 26 | - title: Transform data 27 | contents: 28 | - has_concept("transform") 29 | 30 | articles: 31 | - title: The osmdata package 32 | contents: 33 | - osmdata 34 | - osmdata-sc 35 | - osm-sf-translation 36 | - query-split 37 | 38 | -------------------------------------------------------------------------------- /cleanup: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | rm -f src/Makevars src/*.gcno src/*.gcda src/*.o src/*.so 4 | -------------------------------------------------------------------------------- /cran-comments.md: -------------------------------------------------------------------------------- 1 | # CRAN notes for osmdata_0.2.5 submission 2 | 3 | The previous submission was removed from CRAN shortly after submission without any notice or consultation. The reason was because of a "pragma" warning-suppression statement in one C++ file which has been in that state throughout the entire package history. This submission removes that statement, resulting in the package now issuing around 20 compiler warnings. Absent any public reference from CRAN of which classes of warnings may or may not be acceptable, I trust these warnings will be ignored. 4 | 5 | ## Test environments 6 | 7 | This submission generates NO notes on: 8 | 9 | * Linux (via github actions): R-release, R-oldrelease, R-devel 10 | * Windows (via github actions): R-release 11 | * MacOS (via github actions): R-release 12 | * win-builder: R-oldrelease, R-release, R-devel 13 | 14 | Package also checked using `Clang++ -Weverything and local memory sanitzer with clean results. 15 | 16 | ## revdepcheck results 17 | 18 | We checked 9 reverse dependencies (0 from CRAN + 9 from Bioconductor), comparing R CMD check results across CRAN and dev versions of this package. 19 | 20 | * We saw 0 new problems 21 | * We failed to check 0 packages 22 | -------------------------------------------------------------------------------- /inst/CITATION: -------------------------------------------------------------------------------- 1 | citHeader("To cite osmdata in publications use:") 2 | 3 | bibentry(bibtype = "Article", 4 | title = "osmdata", 5 | author = c(person(given = "Mark Padgham"), 6 | person(given = "Bob Rudis"), 7 | person(given = "Robin Lovelace"), 8 | person(given = "Maëlle Salmon")), 9 | journal = "Journal of Open Source Software", 10 | year = "2017", 11 | volume = "2", 12 | number = "14", 13 | pages = "305", 14 | month = "jun", 15 | publisher = "The Open Journal", 16 | url = "https://joss.theoj.org/papers/10.21105/joss.00305", 17 | doi = "10.21105/joss.00305") 18 | -------------------------------------------------------------------------------- /inst/httptest2/redact.R: -------------------------------------------------------------------------------- 1 | function (resp) { 2 | 3 | resp <- httptest2::gsub_response ( 4 | resp, 5 | "https://nominatim.openstreetmap.org/", 6 | "nominatim/", 7 | fixed = TRUE 8 | ) 9 | 10 | resp <- httptest2::gsub_response ( 11 | resp, 12 | "https://wiki.openstreetmap.org/wiki/", 13 | "wiki/", 14 | fixed = TRUE 15 | ) 16 | 17 | resp <- httptest2::gsub_response ( 18 | resp, 19 | "overpass.kumi.systems/api/", 20 | "overpass/", 21 | fixed = TRUE 22 | ) 23 | 24 | # Timestamp pattern: 25 | ptn <- paste0 ("[A-Za-z]{3},\\s[0-9]{2}\\s[A-Za-z]{3}\\s[0-9]{4}\\s", # date 26 | "[0-9]{2}\\:[0-9]{2}\\:[0-9]{2}") # time 27 | resp <- httptest2::gsub_response ( 28 | resp, 29 | ptn, 30 | "Sat, 01 Jan 20222 00:00:00", 31 | fixed = FALSE 32 | ) 33 | 34 | # Datestamp pattern (for api status requests): 35 | ptn <- "[0-9]{4}\\-[0-9]{2}\\-[0-9]{2}T[0-9]{2}\\:[0-9]{2}\\:[0-9]{2}Z" 36 | resp <- httptest2::gsub_response ( 37 | resp, 38 | ptn, 39 | "2022-01-01T00:00:00Z", 40 | fixed = FALSE 41 | ) 42 | 43 | # overpass status with encoded ip address: 44 | resp <- httptest2::gsub_response ( 45 | resp, 46 | "Connected\\sas\\:\\s[0-9]*", 47 | "Connected as: 123456789", 48 | fixed = FALSE 49 | ) 50 | 51 | return (resp) 52 | } 53 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | LFILE = README 2 | VIGNETTE = osmdata 3 | 4 | all: help 5 | 6 | init: ## Initialize `pkgdown` site 7 | echo "pkgdown::init_site()" | R --no-save -q 8 | 9 | vignette: ## Render vignette defined at top of `makefile` 10 | echo "pkgdown::build_article('$(VIGNETTE)',quiet=FALSE)" | R --no-save -q 11 | 12 | site: ## Build entire `pkgdown` site 13 | echo "pkgdown::build_site()" | R --no-save -q 14 | 15 | knith: $(LFILE).Rmd ## Render readme to HTML 16 | echo "rmarkdown::render('$(LFILE).Rmd',output_file='$(LFILE).html')" | R --no-save -q 17 | 18 | knitr: $(LFILE).Rmd ## Render `REAMDE.Rds` to `README.md`. 19 | echo "rmarkdown::render('$(LFILE).Rmd',output_file='$(LFILE).md')" | R --no-save -q 20 | 21 | open: ## Open HTML-rendered vignette 22 | xdg-open docs/index.html & 23 | 24 | check: ## Run `rcmdcheck` 25 | Rscript -e 'rcmdcheck::rcmdcheck()' 26 | 27 | test: ## Run test suite 28 | Rscript -e 'devtools::load_all(); testthat::test_local()' 29 | 30 | pkgcheck: ## Run `pkgcheck` and print results to screen. 31 | Rscript -e 'library(pkgcheck); checks <- pkgcheck(); print(checks); summary (checks)' 32 | 33 | allcontribs: ## Update 'allcontributors' list on README 34 | Rscript -e 'allcontributors::add_contributors (check_urls = FALSE)' 35 | 36 | clean: ## Clean all temp and cached files 37 | rm -rf *.html *.png README_cache 38 | 39 | help: ## Show this help 40 | @printf "Usage:\033[36m make [target]\033[0m\n" 41 | @grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' 42 | 43 | # Phony targets: 44 | .PHONY: doc 45 | .PHONY: check 46 | .PHONY: help 47 | -------------------------------------------------------------------------------- /man/add_osm_feature.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/opq.R 3 | \name{add_osm_feature} 4 | \alias{add_osm_feature} 5 | \title{Add a feature to an Overpass query} 6 | \usage{ 7 | add_osm_feature( 8 | opq, 9 | key, 10 | value, 11 | key_exact = TRUE, 12 | value_exact = TRUE, 13 | match_case = TRUE, 14 | bbox = NULL 15 | ) 16 | } 17 | \arguments{ 18 | \item{opq}{An \code{overpass_query} object} 19 | 20 | \item{key}{feature key; can be negated with an initial exclamation mark, 21 | \code{key = "!this"}, and can also be a vector if \code{value} is missing.} 22 | 23 | \item{value}{value for feature key; can be negated with an initial 24 | exclamation mark, \code{value = "!this"}, and can also be a vector, 25 | \code{value = c ("this", "that")}.} 26 | 27 | \item{key_exact}{If FALSE, \code{key} is not interpreted exactly; see 28 | \url{https://wiki.openstreetmap.org/wiki/Overpass_API}} 29 | 30 | \item{value_exact}{If FALSE, \code{value} is not interpreted exactly} 31 | 32 | \item{match_case}{If FALSE, matching for both \code{key} and \code{value} is 33 | not sensitive to case} 34 | 35 | \item{bbox}{optional bounding box for the feature query; must be set if no 36 | opq query bbox has been set} 37 | } 38 | \value{ 39 | \link{opq} object 40 | } 41 | \description{ 42 | Add a feature to an Overpass query 43 | } 44 | \note{ 45 | \code{key_exact} should generally be \code{TRUE}, because OSM uses a 46 | reasonably well defined set of possible keys, as returned by 47 | \link{available_features}. Setting \code{key_exact = FALSE} allows matching 48 | of regular expressions on OSM keys, as described in Section 6.1.5 of 49 | \url{https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL}. The actual 50 | query submitted to the overpass API can be obtained from 51 | \link{opq_string}. 52 | } 53 | \section{\code{add_osm_feature} vs \code{add_osm_features}}{ 54 | 55 | Features defined within an \link{add_osm_features} call are combined with a 56 | logical OR. 57 | 58 | Chained calls to either \link{add_osm_feature} or \code{add_osm_features()} combines 59 | features from these calls in a logical AND; this is analagous to chaining 60 | \code{dplyr::filter()} on a data frame. 61 | 62 | \code{add_osm_features()} with only one feature is logically equivalent to 63 | \code{add_osm_feature()}. 64 | } 65 | 66 | \examples{ 67 | \dontrun{ 68 | q <- opq ("portsmouth usa") \%>\% 69 | add_osm_feature ( 70 | key = "amenity", 71 | value = "restaurant" 72 | ) \%>\% 73 | add_osm_feature (key = "amenity", value = "pub") 74 | osmdata_sf (q) # all objects that are restaurants AND pubs (there are none!) 75 | q1 <- opq ("portsmouth usa") \%>\% 76 | add_osm_feature ( 77 | key = "amenity", 78 | value = "restaurant" 79 | ) 80 | q2 <- opq ("portsmouth usa") \%>\% 81 | add_osm_feature (key = "amenity", value = "pub") 82 | c (osmdata_sf (q1), osmdata_sf (q2)) # all restaurants OR pubs 83 | # Use of negation to extract all non-primary highways 84 | q <- opq ("portsmouth uk") \%>\% 85 | add_osm_feature (key = "highway", value = "!primary") 86 | 87 | # key negation without warnings 88 | q3 <- opq ("Vinçà", osm_type="node") \%>\% 89 | add_osm_feature (key = c("name", "!name:ca")) 90 | q4 <- opq ("el Carxe", osm_type="node") \%>\% 91 | add_osm_feature (key = "natural", value = "peak") \%>\% 92 | add_osm_feature (key = "!ele") 93 | } 94 | } 95 | \references{ 96 | \url{https://wiki.openstreetmap.org/wiki/Map_Features} 97 | } 98 | \seealso{ 99 | \link{add_osm_features} 100 | 101 | Other queries: 102 | \code{\link{add_osm_features}()}, 103 | \code{\link{bbox_to_string}()}, 104 | \code{\link{getbb}()}, 105 | \code{\link{opq}()}, 106 | \code{\link{opq_around}()}, 107 | \code{\link{opq_csv}()}, 108 | \code{\link{opq_enclosing}()}, 109 | \code{\link{opq_osm_id}()}, 110 | \code{\link{opq_string}()}, 111 | \code{\link{overpass_status}()} 112 | } 113 | \concept{queries} 114 | -------------------------------------------------------------------------------- /man/add_osm_features.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/opq.R 3 | \name{add_osm_features} 4 | \alias{add_osm_features} 5 | \title{Add multiple features to an Overpass query} 6 | \usage{ 7 | add_osm_features( 8 | opq, 9 | features, 10 | bbox = NULL, 11 | key_exact = TRUE, 12 | value_exact = TRUE 13 | ) 14 | } 15 | \arguments{ 16 | \item{opq}{An \code{overpass_query} object} 17 | 18 | \item{features}{A named list or vector with the format \code{list("" = "")} or \code{c("" = "")} or a character vector of 19 | key-value pairs with keys and values enclosed in escape-formatted 20 | quotations. See examples for details.} 21 | 22 | \item{bbox}{optional bounding box for the feature query; must be set if no 23 | opq query bbox has been set.} 24 | 25 | \item{key_exact}{If FALSE, \code{key} is not interpreted exactly; see 26 | \url{https://wiki.openstreetmap.org/wiki/Overpass_API}} 27 | 28 | \item{value_exact}{If FALSE, \code{value} is not interpreted exactly} 29 | } 30 | \value{ 31 | \link{opq} object 32 | } 33 | \description{ 34 | Alternative version of \link{add_osm_feature} for creating single queries 35 | with multiple features. Key-value matching may be controlled by using the 36 | filter symbols described in 37 | \url{https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#By_tag_.28has-kv.29}. 38 | } 39 | \section{\code{add_osm_feature} vs \code{add_osm_features}}{ 40 | 41 | Features defined within an \link{add_osm_features} call are combined with a 42 | logical OR. 43 | 44 | Chained calls to either \link{add_osm_feature} or \code{add_osm_features()} combines 45 | features from these calls in a logical AND; this is analagous to chaining 46 | \code{dplyr::filter()} on a data frame. 47 | 48 | \code{add_osm_features()} with only one feature is logically equivalent to 49 | \code{add_osm_feature()}. 50 | } 51 | 52 | \examples{ 53 | \dontrun{ 54 | q <- opq ("portsmouth usa") \%>\% 55 | add_osm_features (features = list ( 56 | "amenity" = "restaurant", 57 | "amenity" = "pub" 58 | )) 59 | 60 | q <- opq ("portsmouth usa") \%>\% 61 | add_osm_features (features = c ( 62 | "\"amenity\"=\"restaurant\"", 63 | "\"amenity\"=\"pub\"" 64 | )) 65 | # This extracts in a single query the same result as the following: 66 | q1 <- opq ("portsmouth usa") \%>\% 67 | add_osm_feature ( 68 | key = "amenity", 69 | value = "restaurant" 70 | ) 71 | q2 <- opq ("portsmouth usa") \%>\% 72 | add_osm_feature (key = "amenity", value = "pub") 73 | c (osmdata_sf (q1), osmdata_sf (q2)) # all restaurants OR pubs 74 | } 75 | } 76 | \references{ 77 | \url{https://wiki.openstreetmap.org/wiki/Map_Features} 78 | } 79 | \seealso{ 80 | \link{add_osm_feature} 81 | 82 | Other queries: 83 | \code{\link{add_osm_feature}()}, 84 | \code{\link{bbox_to_string}()}, 85 | \code{\link{getbb}()}, 86 | \code{\link{opq}()}, 87 | \code{\link{opq_around}()}, 88 | \code{\link{opq_csv}()}, 89 | \code{\link{opq_enclosing}()}, 90 | \code{\link{opq_osm_id}()}, 91 | \code{\link{opq_string}()}, 92 | \code{\link{overpass_status}()} 93 | } 94 | \concept{queries} 95 | -------------------------------------------------------------------------------- /man/available_features.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/features.R 3 | \name{available_features} 4 | \alias{available_features} 5 | \title{List recognized features in OSM} 6 | \usage{ 7 | available_features() 8 | } 9 | \value{ 10 | character vector of all known features 11 | } 12 | \description{ 13 | List recognized features in OSM 14 | } 15 | \note{ 16 | requires internet access 17 | } 18 | \examples{ 19 | \dontrun{ 20 | available_features () 21 | } 22 | } 23 | \references{ 24 | \url{https://wiki.openstreetmap.org/wiki/Map_Features} 25 | } 26 | \seealso{ 27 | Other osminfo: 28 | \code{\link{available_tags}()} 29 | } 30 | \concept{osminfo} 31 | -------------------------------------------------------------------------------- /man/available_tags.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/features.R 3 | \name{available_tags} 4 | \alias{available_tags} 5 | \title{List tags associated with a feature} 6 | \usage{ 7 | available_tags(feature) 8 | } 9 | \arguments{ 10 | \item{feature}{feature to retrieve} 11 | } 12 | \value{ 13 | character vector of all known tags for a feature 14 | } 15 | \description{ 16 | List tags associated with a feature 17 | } 18 | \note{ 19 | requires internet access 20 | } 21 | \examples{ 22 | \dontrun{ 23 | available_tags ("aerialway") 24 | } 25 | } 26 | \references{ 27 | \url{https://wiki.openstreetmap.org/wiki/Map_Features} 28 | } 29 | \seealso{ 30 | Other osminfo: 31 | \code{\link{available_features}()} 32 | } 33 | \concept{osminfo} 34 | -------------------------------------------------------------------------------- /man/bbox_to_string.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/getbb.R 3 | \name{bbox_to_string} 4 | \alias{bbox_to_string} 5 | \title{Convert a named matrix or a named or unnamed vector or data.frame to a string} 6 | \usage{ 7 | bbox_to_string(bbox) 8 | } 9 | \arguments{ 10 | \item{bbox}{bounding box as character, matrix, vector or a data.frame with 11 | \code{osm_type} and \code{osm_id} columns. 12 | If character, the bbox will be found (geocoded) and extracted with 13 | \link{getbb}. Unnamed vectors will be sorted appropriately and must merely be 14 | in the order (x, y, x, y).} 15 | } 16 | \value{ 17 | A character string representing min x, min y, max x, and max y 18 | bounds. For example: \code{"15.3152361,76.4406446,15.3552361,76.4806446"} is 19 | the bounding box for Hampi, India. For data.frames with OSM objects, a 20 | character string representing a set of OSM objects in overpass query 21 | language. For example: \code{"relation(id:11747082)"} represents the area of 22 | the Catalan Countries. A set of objects can also be represented for multirow 23 | data.frames (e.g. \code{"relation(id:11747082,307833); way(id:22422490)"}). 24 | } 25 | \description{ 26 | This function converts a bounding box into a string for use in web apis 27 | } 28 | \examples{ 29 | \dontrun{ 30 | bbox_to_string (getbb ("València")) 31 | bbox_to_string (getbb ("València", format_out = "data.frame")) 32 | } 33 | } 34 | \seealso{ 35 | Other queries: 36 | \code{\link{add_osm_feature}()}, 37 | \code{\link{add_osm_features}()}, 38 | \code{\link{getbb}()}, 39 | \code{\link{opq}()}, 40 | \code{\link{opq_around}()}, 41 | \code{\link{opq_csv}()}, 42 | \code{\link{opq_enclosing}()}, 43 | \code{\link{opq_osm_id}()}, 44 | \code{\link{opq_string}()}, 45 | \code{\link{overpass_status}()} 46 | } 47 | \concept{queries} 48 | -------------------------------------------------------------------------------- /man/figures/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/osmdata/927b7f419313acde6494b4795b48d94cbd0ce57d/man/figures/logo.png -------------------------------------------------------------------------------- /man/figures/title.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ropensci/osmdata/927b7f419313acde6494b4795b48d94cbd0ce57d/man/figures/title.png -------------------------------------------------------------------------------- /man/get_overpass_url.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/zzz.R 3 | \name{get_overpass_url} 4 | \alias{get_overpass_url} 5 | \title{get_overpass_url} 6 | \usage{ 7 | get_overpass_url() 8 | } 9 | \value{ 10 | The overpass API URL 11 | } 12 | \description{ 13 | Return the URL of the specified overpass API. Default is 14 | \url{https://overpass-api.de/api/interpreter/}. 15 | } 16 | \seealso{ 17 | \code{\link[=set_overpass_url]{set_overpass_url()}} 18 | 19 | Other overpass: 20 | \code{\link{set_overpass_url}()} 21 | } 22 | \concept{overpass} 23 | -------------------------------------------------------------------------------- /man/getbb.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/getbb.R 3 | \name{getbb} 4 | \alias{getbb} 5 | \title{Get bounding box for a given place name} 6 | \usage{ 7 | getbb( 8 | place_name, 9 | display_name_contains = NULL, 10 | viewbox = NULL, 11 | format_out = "matrix", 12 | base_url = "https://nominatim.openstreetmap.org", 13 | featuretype = "settlement", 14 | limit = 10, 15 | key = NULL, 16 | silent = TRUE 17 | ) 18 | } 19 | \arguments{ 20 | \item{place_name}{The name of the place you're searching for} 21 | 22 | \item{display_name_contains}{Text string to match with display_name field 23 | returned by \url{https://wiki.openstreetmap.org/wiki/Nominatim}} 24 | 25 | \item{viewbox}{The bounds in which you're searching} 26 | 27 | \item{format_out}{Character string indicating output format: \code{matrix} 28 | (default), \code{string} (see \code{\link[=bbox_to_string]{bbox_to_string()}}), \code{data.frame} (all 'hits' returned 29 | by Nominatim), \code{sf_polygon} (for polygons that work with the sf package), 30 | \code{polygon} (full polygonal bounding boxes for each match) or \code{osm_type_id} ( 31 | string for quering inside deffined OSM areas \code{\link[=bbox_to_string]{bbox_to_string()}}).} 32 | 33 | \item{base_url}{Base website from where data is queried} 34 | 35 | \item{featuretype}{The type of OSM feature (settlement is default; see Note)} 36 | 37 | \item{limit}{How many results should the API return?} 38 | 39 | \item{key}{The API key to use for services that require it} 40 | 41 | \item{silent}{Should the API be printed to screen? TRUE by default} 42 | } 43 | \value{ 44 | Defaults to a matrix in the form: 45 | \code{ 46 | min max 47 | x ... ... 48 | y ... ... 49 | } 50 | 51 | If \code{format_out = "polygon"}, one or more two-columns matrices of polygonal 52 | longitude-latitude points. Where multiple \code{place_name} occurrences are found 53 | within \code{nominatim}, each item of the list of coordinates may itself contain 54 | multiple coordinate matrices where multiple exact matches exist. If one 55 | exact match exists with potentially multiple polygonal boundaries (for 56 | example, "london uk" is an exact match, but can mean either greater London or 57 | the City of London), only the first is returned. See examples below for 58 | illustration. 59 | 60 | For \code{format_out = "osm_type_id"}, a character string representing an OSM object in overpass query 61 | language. For example: \code{"relation(id:11747082)"} represents the area of 62 | the Catalan Countries. If one exact match exists with potentially multiple 63 | polygonal boundaries, only the first relation or way is returned. A set of 64 | objects can also be represented for multiple results (e.g. 65 | \verb{relation(id:11747082,307833); way(id:22422490)}). See examples below for 66 | illustration. The OSM objects that can be used as 67 | \href{https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#Map_way/relation_to_area_(map_to_area)}{areas in overpass queries} 68 | \emph{must be closed rings} (ways or relations). 69 | } 70 | \description{ 71 | This function uses the free Nominatim API provided by OpenStreetMap to find 72 | the bounding box (bb) associated with place names. 73 | } 74 | \details{ 75 | It was inspired by the functions 76 | \code{bbox} from the \pkg{sp} package, 77 | \code{bb} from the \pkg{tmaptools} package and 78 | \code{bb_lookup} from the github package \pkg{nominatim} package, 79 | which can be found at \url{https://github.com/hrbrmstr/nominatim}. 80 | 81 | See \url{https://wiki.openstreetmap.org/wiki/Nominatim} for details. 82 | } 83 | \note{ 84 | Specific values of \code{featuretype} include "street", "city", 85 | \url{https://wiki.openstreetmap.org/wiki/Nominatim} for details). The default 86 | \code{featuretype = "settlement"} combines results from all intermediate 87 | levels below "country" and above "streets". If the bounding box or polygon of 88 | a city is desired, better results will usually be obtained with 89 | \code{featuretype = "city"}. 90 | } 91 | \examples{ 92 | \dontrun{ 93 | getbb ("Salzburg") 94 | # select based on display_name, print query url 95 | getbb ("Hereford", display_name_contains = "United States", silent = FALSE) 96 | # top 3 matches as data frame 97 | getbb ("Hereford", format_out = "data.frame", limit = 3) 98 | 99 | # Examples of polygonal boundaries 100 | bb <- getbb ("london uk", format_out = "polygon") # single match 101 | dim (bb [[1]] [[1]]) # matrix of longitude/latitude pairs 102 | bb_sf <- getbb ("kathmandu", format_out = "sf_polygon") 103 | # sf:::plot.sf(bb_sf) # can be plotted if sf is installed 104 | getbb ("london", format_out = "sf_polygon") 105 | getbb ("accra", format_out = "sf_polygon") # rectangular bb 106 | 107 | area <- getbb ("València", format_out = "osm_type_id") 108 | # select multiple areas with format_out = "osm_type_id" 109 | areas <- getbb ("València", format_out = "data.frame") 110 | bbox_to_string (areas [areas$osm_type != "node", ]) 111 | 112 | # Using an alternative service (locationiq requires an API key) 113 | # add LOCATIONIQ=type_your_api_key_here to .Renviron: 114 | key <- Sys.getenv ("LOCATIONIQ") 115 | if (nchar (key) == 32) { 116 | getbb (place_name, 117 | base_url = "https://locationiq.org/v1/search.php", 118 | key = key 119 | ) 120 | } 121 | } 122 | } 123 | \seealso{ 124 | Other queries: 125 | \code{\link{add_osm_feature}()}, 126 | \code{\link{add_osm_features}()}, 127 | \code{\link{bbox_to_string}()}, 128 | \code{\link{opq}()}, 129 | \code{\link{opq_around}()}, 130 | \code{\link{opq_csv}()}, 131 | \code{\link{opq_enclosing}()}, 132 | \code{\link{opq_osm_id}()}, 133 | \code{\link{opq_string}()}, 134 | \code{\link{overpass_status}()} 135 | } 136 | \concept{queries} 137 | -------------------------------------------------------------------------------- /man/opq_around.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/opq.R 3 | \name{opq_around} 4 | \alias{opq_around} 5 | \title{opq_around} 6 | \usage{ 7 | opq_around(lon, lat, radius = 15, key = NULL, value = NULL, timeout = 25) 8 | } 9 | \arguments{ 10 | \item{lon}{Longitude of desired point} 11 | 12 | \item{lat}{Latitude of desired point} 13 | 14 | \item{radius}{Radius in metres around the point for which data should be 15 | extracted. Queries with large values for this parameter may fail.} 16 | 17 | \item{key}{(Optional) OSM key of enclosing data} 18 | 19 | \item{value}{(Optional) OSM value matching 'key' of enclosing data} 20 | 21 | \item{timeout}{It may be necessary to increase this value for large queries, 22 | because the server may time out before all data are delivered.} 23 | } 24 | \description{ 25 | Find all features around a given point, and optionally match specific 26 | 'key'-'value' pairs. This function is \emph{not} intended to be combined with 27 | \link{add_osm_feature}, rather is only to be used in the sequence 28 | \link{opq_around} -> \link{osmdata_xml} (or other extraction function). See 29 | examples for how to use. 30 | } 31 | \examples{ 32 | \dontrun{ 33 | # Get all benches ("amenity=bench") within 100m of a particular point 34 | lat <- 53.94542 35 | lon <- -2.52017 36 | key <- "amenity" 37 | value <- "bench" 38 | radius <- 100 39 | x <- opq_around (lon, lat, radius, key, value) \%>\% 40 | osmdata_sf () 41 | } 42 | } 43 | \seealso{ 44 | Other queries: 45 | \code{\link{add_osm_feature}()}, 46 | \code{\link{add_osm_features}()}, 47 | \code{\link{bbox_to_string}()}, 48 | \code{\link{getbb}()}, 49 | \code{\link{opq}()}, 50 | \code{\link{opq_csv}()}, 51 | \code{\link{opq_enclosing}()}, 52 | \code{\link{opq_osm_id}()}, 53 | \code{\link{opq_string}()}, 54 | \code{\link{overpass_status}()} 55 | } 56 | \concept{queries} 57 | -------------------------------------------------------------------------------- /man/opq_csv.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/opq.R 3 | \name{opq_csv} 4 | \alias{opq_csv} 5 | \title{Transform an Overpass query to return the result in a csv format} 6 | \usage{ 7 | opq_csv(q, fields, header = TRUE) 8 | } 9 | \arguments{ 10 | \item{q}{A opq string or an object of class \code{overpass_query} constructed with 11 | \link{opq} or alternative opq builders (+ \link{add_osm_feature}/s).} 12 | 13 | \item{fields}{a character vector with the field names.} 14 | 15 | \item{header}{if \code{FALSE}, do not ask for column names.} 16 | } 17 | \value{ 18 | The \code{overpass_query} or string with the prefix changed to 19 | return a csv. 20 | } 21 | \description{ 22 | Transform an Overpass query to return the result in a csv format 23 | } 24 | \details{ 25 | The output format \code{csv}, ask for results in csv. See 26 | \href{https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#CSV_output_mode}{CSV output mode} 27 | for details. To get the data, use \link{osmdata_data_frame}. 28 | } 29 | \note{ 30 | csv queries that reach the timeout will return a 0 row data.frame 31 | without any warning. Increase \code{timeout} in \code{q} if you don't see the 32 | expected result. 33 | } 34 | \examples{ 35 | \dontrun{ 36 | q <- getbb ("Catalan Countries", format_out = "osm_type_id") \%>\% 37 | opq (out = "tags center", osm_type = "relation", timeout = 100) \%>\% 38 | add_osm_feature ("admin_level", "7") \%>\% 39 | add_osm_feature ("boundary", "administrative") \%>\% 40 | opq_csv (fields = c("name", "::type", "::id", "::lat", "::lon")) 41 | comarques <- osmdata_data_frame (q) # without timeout parameter, 0 rows 42 | 43 | qid<- opq_osm_id ( 44 | type = "relation", 45 | id = c ("341530", "1809102", "1664395", "343124"), 46 | out = "tags" 47 | ) \%>\% 48 | opq_csv (fields = c ("name", "name:ca")) 49 | cities <- osmdata_data_frame (qid) 50 | } 51 | } 52 | \seealso{ 53 | Other queries: 54 | \code{\link{add_osm_feature}()}, 55 | \code{\link{add_osm_features}()}, 56 | \code{\link{bbox_to_string}()}, 57 | \code{\link{getbb}()}, 58 | \code{\link{opq}()}, 59 | \code{\link{opq_around}()}, 60 | \code{\link{opq_enclosing}()}, 61 | \code{\link{opq_osm_id}()}, 62 | \code{\link{opq_string}()}, 63 | \code{\link{overpass_status}()} 64 | } 65 | \concept{queries} 66 | -------------------------------------------------------------------------------- /man/opq_enclosing.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/opq.R 3 | \name{opq_enclosing} 4 | \alias{opq_enclosing} 5 | \title{opq_enclosing} 6 | \usage{ 7 | opq_enclosing( 8 | lon = NULL, 9 | lat = NULL, 10 | key = NULL, 11 | value = NULL, 12 | enclosing = "relation", 13 | timeout = 25 14 | ) 15 | } 16 | \arguments{ 17 | \item{lon}{Longitude of desired point} 18 | 19 | \item{lat}{Latitude of desired point} 20 | 21 | \item{key}{(Optional) OSM key of enclosing data} 22 | 23 | \item{value}{(Optional) OSM value matching 'key' of enclosing data} 24 | 25 | \item{enclosing}{Either 'relation' or 'way' for whether to return enclosing 26 | objects of those respective types (where generally 'relation' will correspond 27 | to multipolygon objects, and 'way' to polygon objects).} 28 | 29 | \item{timeout}{It may be necessary to increase this value for large queries, 30 | because the server may time out before all data are delivered.} 31 | } 32 | \description{ 33 | Find all features which enclose a given point, and optionally match specific 34 | 'key'-'value' pairs. This function is \emph{not} intended to be combined with 35 | \link{add_osm_feature}, rather is only to be used in the sequence 36 | \link{opq_enclosing} -> \link{opq_string} -> \link{osmdata_xml} (or other 37 | extraction function). See examples for how to use. 38 | } 39 | \examples{ 40 | \dontrun{ 41 | # Get water body surrounding a particular point: 42 | lat <- 54.33601 43 | lon <- -3.07677 44 | key <- "natural" 45 | value <- "water" 46 | x <- opq_enclosing (lon, lat, key, value) \%>\% 47 | opq_string () \%>\% 48 | osmdata_sf () 49 | } 50 | } 51 | \seealso{ 52 | Other queries: 53 | \code{\link{add_osm_feature}()}, 54 | \code{\link{add_osm_features}()}, 55 | \code{\link{bbox_to_string}()}, 56 | \code{\link{getbb}()}, 57 | \code{\link{opq}()}, 58 | \code{\link{opq_around}()}, 59 | \code{\link{opq_csv}()}, 60 | \code{\link{opq_osm_id}()}, 61 | \code{\link{opq_string}()}, 62 | \code{\link{overpass_status}()} 63 | } 64 | \concept{queries} 65 | -------------------------------------------------------------------------------- /man/opq_osm_id.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/opq.R 3 | \name{opq_osm_id} 4 | \alias{opq_osm_id} 5 | \title{Add a feature specified by OSM ID to an Overpass query} 6 | \usage{ 7 | opq_osm_id( 8 | id = NULL, 9 | type = NULL, 10 | open_url = FALSE, 11 | out = "body", 12 | datetime = NULL, 13 | datetime2 = NULL, 14 | adiff = FALSE, 15 | timeout = 25, 16 | memsize 17 | ) 18 | } 19 | \arguments{ 20 | \item{id}{One or more official OSM identifiers (long-form integers), which 21 | must be entered as either a character or \emph{numeric} value (because R does 22 | not support long-form integers). id can also be a character string 23 | prefixed with the id type, e.g. "relation/11158003"} 24 | 25 | \item{type}{Type of objects (recycled); must be either \code{node}, \code{way}, or 26 | \code{relation}. Optional if id is prefixed with the type.} 27 | 28 | \item{open_url}{If \code{TRUE}, open the OSM page of the specified object in web 29 | browser. Multiple objects (\code{id} values) will be opened in multiple 30 | pages.} 31 | 32 | \item{out}{The level of verbosity of the overpass result: \code{body} (geometries 33 | and tags, the default), \code{tags} (tags without geometry), \code{meta} (like 34 | body + Timestamp, Version, Changeset, User, User ID of the last 35 | edition), \code{skel} (geometries only), \verb{tags center} (tags without geometry 36 | + the coordinates of the center of the bounding box) and \code{ids} (type and 37 | id of the objects only).} 38 | 39 | \item{datetime}{If specified, a date and time to extract data from the OSM 40 | database as it was up to the specified date and time, as described at 41 | \url{https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#date}. 42 | This \emph{must} be in ISO8601 format ("YYYY-MM-DDThh:mm:ssZ"), where 43 | both the "T" and "Z" characters must be present.} 44 | 45 | \item{datetime2}{If specified, return the \emph{difference} in the OSM 46 | database between \code{datetime} and \code{datetime2}, where 47 | \code{datetime2 > datetime}. See 48 | \url{https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#Difference_between_two_dates_(diff)}.} 49 | 50 | \item{adiff}{If \code{TRUE}, query for \href{https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#Augmented-difference_between_two_dates_(adiff)}{augmented difference}. 51 | The result indicates what happened to the modified and deleted OSM 52 | objects. Requires \verb{datetime(2)*}.} 53 | 54 | \item{timeout}{It may be necessary to increase this value for large queries, 55 | because the server may time out before all data are delivered.} 56 | 57 | \item{memsize}{The default memory size for the 'overpass' server in \emph{bytes}; 58 | may need to be increased in order to handle large queries.} 59 | } 60 | \value{ 61 | \link{opq} object 62 | } 63 | \description{ 64 | Add a feature specified by OSM ID to an Overpass query 65 | } 66 | \note{ 67 | Extracting elements by ID requires explicitly specifying the type of 68 | element. Only elements of one of the three given types can be extracted in a 69 | single query, but the results of multiple types can nevertheless be combined 70 | with the \link{c} operation of \link{osmdata}. 71 | } 72 | \examples{ 73 | \dontrun{ 74 | id <- c (1489221200, 1489221321, 1489221491) 75 | dat1 <- opq_osm_id (type = "node", id = id) \%>\% 76 | opq_string () \%>\% 77 | osmdata_sf () 78 | dat1$osm_points # the desired nodes 79 | id <- c (136190595, 136190596) 80 | dat2 <- opq_osm_id (type = "way", id = id) \%>\% 81 | opq_string () \%>\% 82 | osmdata_sf () 83 | dat2$osm_lines # the desired ways 84 | dat <- c (dat1, dat2) # The node and way data combined 85 | # All in one (same result as dat) 86 | id <- c (1489221200, 1489221321, 1489221491, 136190595, 136190596) 87 | type <- c ("node", "node", "node", "way", "way") 88 | datAiO <- opq_osm_id (id = id, type = type) \%>\% 89 | opq_string () \%>\% 90 | osmdata_sf () 91 | } 92 | } 93 | \references{ 94 | \url{https://wiki.openstreetmap.org/wiki/Overpass_API/Overpass_QL#By_element_id} 95 | } 96 | \seealso{ 97 | Other queries: 98 | \code{\link{add_osm_feature}()}, 99 | \code{\link{add_osm_features}()}, 100 | \code{\link{bbox_to_string}()}, 101 | \code{\link{getbb}()}, 102 | \code{\link{opq}()}, 103 | \code{\link{opq_around}()}, 104 | \code{\link{opq_csv}()}, 105 | \code{\link{opq_enclosing}()}, 106 | \code{\link{opq_string}()}, 107 | \code{\link{overpass_status}()} 108 | } 109 | \concept{queries} 110 | -------------------------------------------------------------------------------- /man/opq_string.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/opq.R 3 | \name{opq_string} 4 | \alias{opq_string} 5 | \alias{opq_to_string} 6 | \title{Convert an overpass query into a text string} 7 | \usage{ 8 | opq_string(opq) 9 | } 10 | \arguments{ 11 | \item{opq}{An \code{overpass_query} object} 12 | } 13 | \value{ 14 | Character string to be submitted to the overpass API 15 | } 16 | \description{ 17 | Convert an osmdata query of class opq to a character string query to 18 | be submitted to the overpass API. 19 | } 20 | \examples{ 21 | \dontrun{ 22 | q <- opq ("hampi india") 23 | opq_string (q) 24 | } 25 | } 26 | \seealso{ 27 | Other queries: 28 | \code{\link{add_osm_feature}()}, 29 | \code{\link{add_osm_features}()}, 30 | \code{\link{bbox_to_string}()}, 31 | \code{\link{getbb}()}, 32 | \code{\link{opq}()}, 33 | \code{\link{opq_around}()}, 34 | \code{\link{opq_csv}()}, 35 | \code{\link{opq_enclosing}()}, 36 | \code{\link{opq_osm_id}()}, 37 | \code{\link{overpass_status}()} 38 | } 39 | \concept{queries} 40 | -------------------------------------------------------------------------------- /man/osm_elevation.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/elevation.R 3 | \name{osm_elevation} 4 | \alias{osm_elevation} 5 | \title{osm_elevation} 6 | \usage{ 7 | osm_elevation(dat, elev_file) 8 | } 9 | \arguments{ 10 | \item{dat}{An \code{SC} object produced by \link{osmdata_sc}.} 11 | 12 | \item{elev_file}{A vector of one or more character strings specifying paths 13 | to \code{.tif} files containing global elevation data.} 14 | } 15 | \value{ 16 | A modified version of the input \code{dat} with an additional \code{z_} column 17 | appended to the vertices. 18 | } 19 | \description{ 20 | Add elevation data to a previously-extracted OSM data set, using a 21 | pre-downloaded global elevation file from 22 | \url{https://srtm.csi.cgiar.org/srtmdata/}. Currently only works for 23 | \code{SC}-class objects returned from \link{osmdata_sc}. 24 | } 25 | \seealso{ 26 | Other transform: 27 | \code{\link{osm_poly2line}()}, 28 | \code{\link{trim_osmdata}()}, 29 | \code{\link{unique_osmdata}()}, 30 | \code{\link{unname_osmdata_sf}()} 31 | } 32 | \concept{transform} 33 | -------------------------------------------------------------------------------- /man/osm_lines.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/osm-extract.R 3 | \name{osm_lines} 4 | \alias{osm_lines} 5 | \title{Extract all \code{osm_lines} from an osmdata object} 6 | \usage{ 7 | osm_lines(dat, id) 8 | } 9 | \arguments{ 10 | \item{dat}{An object of class \link{osmdata}} 11 | 12 | \item{id}{OSM identification of one or more objects for which lines are to be 13 | extracted} 14 | } 15 | \value{ 16 | An \pkg{sf} Simple Features Collection of linestrings 17 | } 18 | \description{ 19 | If \code{id} is of a point object, \code{osm_lines} will return all lines 20 | containing that point. If \code{id} is of a line or polygon object, 21 | \code{osm_lines} will return all lines which intersect the given line or 22 | polygon. 23 | } 24 | \examples{ 25 | \dontrun{ 26 | dat <- opq ("hengelo nl") \%>\% 27 | add_osm_feature (key = "highway") \%>\% 28 | osmdata_sf () 29 | bus <- dat$osm_points [which (dat$osm_points$highway == "bus_stop"), ] \%>\% 30 | rownames () # all OSM IDs of bus stops 31 | osm_lines (dat, bus) # all highways containing bus stops 32 | 33 | # All lines which intersect with Piccadilly Circus in London, UK 34 | dat <- opq ("Fitzrovia London") \%>\% 35 | add_osm_feature (key = "highway") \%>\% 36 | osmdata_sf () 37 | i <- which (dat$osm_polygons$name == "Piccadilly Circus") 38 | id <- rownames (dat$osm_polygons [i, ]) 39 | osm_lines (dat, id) 40 | } 41 | } 42 | \seealso{ 43 | Other search: 44 | \code{\link{osm_multilines}()}, 45 | \code{\link{osm_multipolygons}()}, 46 | \code{\link{osm_points}()}, 47 | \code{\link{osm_polygons}()} 48 | } 49 | \concept{search} 50 | -------------------------------------------------------------------------------- /man/osm_multilines.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/osm-extract.R 3 | \name{osm_multilines} 4 | \alias{osm_multilines} 5 | \title{Extract all \code{osm_multilines} from an osmdata object} 6 | \usage{ 7 | osm_multilines(dat, id) 8 | } 9 | \arguments{ 10 | \item{dat}{An object of class \link{osmdata}} 11 | 12 | \item{id}{OSM identification of one of more objects for which multilines are 13 | to be extracted} 14 | } 15 | \value{ 16 | An \pkg{sf} Simple Features Collection of multilines 17 | } 18 | \description{ 19 | \code{id} must be of an \code{osm_points} or \code{osm_lines} object (and can 20 | not be the \code{id} of an \code{osm_polygons} object because multilines by 21 | definition contain no polygons. \code{osm_multilines} returns any multiline 22 | object(s) which contain the object specified by \code{id}. 23 | } 24 | \examples{ 25 | \dontrun{ 26 | dat <- opq ("London UK") \%>\% 27 | add_osm_feature (key = "name", value = "Thames", exact = FALSE) \%>\% 28 | osmdata_sf () 29 | # Get ids of lines called "The Thames": 30 | id <- rownames (dat$osm_lines [which (dat$osm_lines$name == "The Thames"), ]) 31 | # and find all multilinestring objects which include those lines: 32 | osm_multilines (dat, id) 33 | # Now note that 34 | nrow (dat$osm_multilines) # = 24 multiline objects 35 | nrow (osm_multilines (dat, id)) # = 1 - the recursive search selects the 36 | # single multiline containing "The Thames" 37 | } 38 | } 39 | \seealso{ 40 | Other search: 41 | \code{\link{osm_lines}()}, 42 | \code{\link{osm_multipolygons}()}, 43 | \code{\link{osm_points}()}, 44 | \code{\link{osm_polygons}()} 45 | } 46 | \concept{search} 47 | -------------------------------------------------------------------------------- /man/osm_multipolygons.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/osm-extract.R 3 | \name{osm_multipolygons} 4 | \alias{osm_multipolygons} 5 | \title{Extract all \code{osm_multipolygons} from an osmdata object} 6 | \usage{ 7 | osm_multipolygons(dat, id) 8 | } 9 | \arguments{ 10 | \item{dat}{An object of class \link{osmdata}} 11 | 12 | \item{id}{OSM identification of one or more objects for which multipolygons 13 | are to be extracted} 14 | } 15 | \value{ 16 | An \pkg{sf} Simple Features Collection of multipolygons 17 | } 18 | \description{ 19 | \code{id} must be of an \code{osm_points}, \code{osm_lines}, or 20 | \code{osm_polygons} object. \code{osm_multipolygons} returns any multipolygon 21 | object(s) which contain the object specified by \code{id}. 22 | } 23 | \examples{ 24 | \dontrun{ 25 | # find all multipolygons which contain the single polygon called 26 | # "Chiswick Eyot" (which is an island). 27 | dat <- opq ("London UK") \%>\% 28 | add_osm_feature (key = "name", value = "Thames", exact = FALSE) \%>\% 29 | osmdata_sf () 30 | index <- which (dat$osm_multipolygons$name == "Chiswick Eyot") 31 | id <- rownames (dat$osm_polygons [id, ]) 32 | osm_multipolygons (dat, id) 33 | # That multipolygon is the Thames itself, but note that 34 | nrow (dat$osm_multipolygons) # = 14 multipolygon objects 35 | nrow (osm_multipolygons (dat, id)) # = 1 - the main Thames multipolygon 36 | } 37 | } 38 | \seealso{ 39 | Other search: 40 | \code{\link{osm_lines}()}, 41 | \code{\link{osm_multilines}()}, 42 | \code{\link{osm_points}()}, 43 | \code{\link{osm_polygons}()} 44 | } 45 | \concept{search} 46 | -------------------------------------------------------------------------------- /man/osm_points.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/osm-extract.R 3 | \name{osm_points} 4 | \alias{osm_points} 5 | \title{Extract all \code{osm_points} from an osmdata object} 6 | \usage{ 7 | osm_points(dat, id) 8 | } 9 | \arguments{ 10 | \item{dat}{An object of class \link{osmdata}} 11 | 12 | \item{id}{OSM identification of one or more objects for which points are to 13 | be extracted} 14 | } 15 | \value{ 16 | An \pkg{sf} Simple Features Collection of points 17 | } 18 | \description{ 19 | Extract all \code{osm_points} from an osmdata object 20 | } 21 | \examples{ 22 | \dontrun{ 23 | tr <- opq ("trentham australia") \%>\% osmdata_sf () 24 | coliban <- tr$osm_lines [which (tr$osm_lines$name == "Coliban River"), ] 25 | pts <- osm_points (tr, rownames (coliban)) # all points of river 26 | # the waterfall point: 27 | waterfall <- pts [which (pts$waterway == "waterfall"), ] 28 | } 29 | } 30 | \seealso{ 31 | Other search: 32 | \code{\link{osm_lines}()}, 33 | \code{\link{osm_multilines}()}, 34 | \code{\link{osm_multipolygons}()}, 35 | \code{\link{osm_polygons}()} 36 | } 37 | \concept{search} 38 | -------------------------------------------------------------------------------- /man/osm_poly2line.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/poly2line.R 3 | \name{osm_poly2line} 4 | \alias{osm_poly2line} 5 | \title{Convert osmdata polygons into lines} 6 | \usage{ 7 | osm_poly2line(osmdat) 8 | } 9 | \arguments{ 10 | \item{osmdat}{An \link{osmdata} object.} 11 | } 12 | \value{ 13 | Modified version of same object with all \code{osm_polygons} 14 | objects merged into \code{osm_lines}. 15 | } 16 | \description{ 17 | Street networks downloaded with \code{add_osm_object(key = "highway")} will 18 | store any circular highways in \code{osm_polygons}. this function combines 19 | those with the \code{osm_lines} component to yield a single \pkg{sf} 20 | \code{data.frame} of all highways, whether polygonal or not. 21 | } 22 | \note{ 23 | The \code{osm_polygons} field is retained, with those features also 24 | repeated as \code{LINESTRING} objects in \code{osm_lines}. 25 | } 26 | \examples{ 27 | \dontrun{ 28 | dat <- opq ("colchester uk") \%>\% 29 | add_osm_feature (key = "highway") \%>\% 30 | osmdata_sf () 31 | # colchester has lots of roundabouts, and these are stored in 'osm_polygons' 32 | # rather than 'osm_lines'. The former can be merged with the latter by: 33 | dat2 <- osm_poly2line (dat) 34 | # 'dat2' will have more lines than 'dat', but the same number of polygons 35 | # (they are left unchanged.) 36 | } 37 | } 38 | \seealso{ 39 | Other transform: 40 | \code{\link{osm_elevation}()}, 41 | \code{\link{trim_osmdata}()}, 42 | \code{\link{unique_osmdata}()}, 43 | \code{\link{unname_osmdata_sf}()} 44 | } 45 | \concept{transform} 46 | -------------------------------------------------------------------------------- /man/osm_polygons.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/osm-extract.R 3 | \name{osm_polygons} 4 | \alias{osm_polygons} 5 | \title{Extract all \code{osm_polygons} from an osmdata object} 6 | \usage{ 7 | osm_polygons(dat, id) 8 | } 9 | \arguments{ 10 | \item{dat}{An object of class \link{osmdata}} 11 | 12 | \item{id}{OSM identification of one or more objects for which polygons are to 13 | be extracted} 14 | } 15 | \value{ 16 | An \pkg{sf} Simple Features Collection of polygons 17 | } 18 | \description{ 19 | If \code{id} is of a point object, \code{osm_polygons} will return all 20 | polygons containing that point. If \code{id} is of a line or polygon object, 21 | \code{osm_polygons} will return all polygons which intersect the given line 22 | or polygon. 23 | } 24 | \examples{ 25 | \dontrun{ 26 | # Extract polygons which intersect Conway Street in London 27 | dat <- opq ("Marylebone London") \%>\% 28 | add_osm_feature (key = "highway") \%>\% 29 | osmdata_sf () 30 | conway <- which (dat$osm_lines$name == "Conway Street") 31 | id <- rownames (dat$osm_lines [conway, ]) 32 | osm_polygons (dat, id) 33 | } 34 | } 35 | \seealso{ 36 | Other search: 37 | \code{\link{osm_lines}()}, 38 | \code{\link{osm_multilines}()}, 39 | \code{\link{osm_multipolygons}()}, 40 | \code{\link{osm_points}()} 41 | } 42 | \concept{search} 43 | -------------------------------------------------------------------------------- /man/osmdata.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/osmdata-class.R, R/osmdata-package.R 3 | \docType{package} 4 | \name{osmdata} 5 | \alias{osmdata-package} 6 | \alias{osmdata} 7 | \title{osmdata class def} 8 | \usage{ 9 | osmdata( 10 | bbox = NULL, 11 | overpass_call = NULL, 12 | meta = NULL, 13 | osm_points = NULL, 14 | osm_lines = NULL, 15 | osm_polygons = NULL, 16 | osm_multilines = NULL, 17 | osm_multipolygons = NULL 18 | ) 19 | } 20 | \arguments{ 21 | \item{bbox}{bounding box} 22 | 23 | \item{overpass_call}{overpass_call} 24 | 25 | \item{meta}{metadata of overpass query, including timestamps and version 26 | numbers} 27 | 28 | \item{osm_points}{OSM nodes as \pkg{sf} Simple Features Collection of points 29 | or \pkg{sp} SpatialPointsDataFrame} 30 | 31 | \item{osm_lines}{OSM ways \pkg{sf} Simple Features Collection of linestrings 32 | or \pkg{sp} SpatialLinesDataFrame} 33 | 34 | \item{osm_polygons}{OSM ways as \pkg{sf} Simple Features Collection of 35 | polygons or \pkg{sp} SpatialPolygonsDataFrame} 36 | 37 | \item{osm_multilines}{OSM relations as \pkg{sf} Simple Features Collection 38 | of multilinestrings or \pkg{sp} SpatialLinesDataFrame} 39 | 40 | \item{osm_multipolygons}{OSM relations as \pkg{sf} Simple Features 41 | Collection of multipolygons or \pkg{sp} 42 | SpatialPolygonsDataFrame} 43 | } 44 | \description{ 45 | Imports OpenStreetMap (OSM) data into R as 'sf', 'SC', 'sp', 'data.frame' or 46 | 'xml_document' objects. OSM data are extracted from the overpass API and 47 | processed with very fast C++ routines for return to R. The package enables 48 | simple overpass queries to be constructed without the user necessarily 49 | understanding the syntax of the overpass query language, while retaining the 50 | ability to handle arbitrarily complex queries. Functions are also provided to 51 | enable recursive searching between different kinds of OSM data (for example, 52 | to find all lines which intersect a given point). 53 | } 54 | \note{ 55 | Class constructor should never be used directly, and is only exported 56 | to provide access to the print method 57 | } 58 | \section{Functions to Prepare Queries}{ 59 | 60 | \itemize{ 61 | \item \link{getbb}: Get bounding box for a given place name 62 | \item \link{bbox_to_string}: Convert a named matrix or a named vector 63 | (or an unnamed vector) return a string 64 | \item \link{overpass_status}: Retrieve status of the overpass API 65 | \item \link{opq}: Build an overpass query 66 | \item \link{add_osm_feature}: Add a feature to an overpass query 67 | \item \link{opq_string}: Convert an osmdata query to overpass API 68 | string 69 | } 70 | } 71 | 72 | \section{Functions to Get Additional OSM Information}{ 73 | 74 | \itemize{ 75 | \item \link{available_features}: List recognised features in OSM 76 | \item \link{available_tags}: List tags associated with a feature 77 | } 78 | } 79 | 80 | \section{Functions to Extract OSM Data}{ 81 | 82 | \itemize{ 83 | \item \link{osmdata_data_frame}: Return OSM data in \code{\link{data.frame}} 84 | format 85 | \item \link{osmdata_sc}: Return OSM data in \pkg{silicate} format 86 | \item \link{osmdata_sf}: Return OSM data in \pkg{sf} format 87 | \item \link{osmdata_sp}: Return OSM data in \pkg{sp} format 88 | \item \link{osmdata_xml}: Return OSM data in \pkg{xml2} format 89 | } 90 | } 91 | 92 | \section{Functions to Search Data}{ 93 | 94 | \itemize{ 95 | \item \code{osm_points}: Extract all \code{osm_points} objects 96 | \item \code{osm_lines}: Extract all \code{osm_lines} objects 97 | \item \code{osm_polygons}: Extract all \code{osm_polygons} objects 98 | \item \code{osm_multilines}: Extract all \code{osm_multilines} objects 99 | \item \code{osm_multipolygons}: Extract all \code{osm_multipolygons} objects 100 | } 101 | } 102 | 103 | \seealso{ 104 | Useful links: 105 | \itemize{ 106 | \item \url{https://docs.ropensci.org/osmdata/ (website) https://github.com/ropensci/osmdata/ (devel)} 107 | \item Report bugs at \url{https://github.com/ropensci/osmdata/issues} 108 | } 109 | 110 | } 111 | \author{ 112 | Mark Padgham, Bob Rudis, Robin Lovelace, Maëlle Salmon, Joan Maspons 113 | } 114 | \concept{package} 115 | -------------------------------------------------------------------------------- /man/osmdata_data_frame.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get-osmdata-df.R 3 | \name{osmdata_data_frame} 4 | \alias{osmdata_data_frame} 5 | \title{Return an OSM Overpass query as a \link{data.frame} object.} 6 | \usage{ 7 | osmdata_data_frame(q, doc, quiet = TRUE, stringsAsFactors = FALSE) 8 | } 9 | \arguments{ 10 | \item{q}{An object of class \code{overpass_query} constructed with 11 | \link{opq} and \link{add_osm_feature} or a string with a valid query, such 12 | as \code{"(node(39.4712701,-0.3841326,39.4713799,-0.3839475);); out;"}. 13 | May be be omitted, in which case the attributes of the \link{data.frame} 14 | will not include the query. See examples below.} 15 | 16 | \item{doc}{If missing, \code{doc} is obtained by issuing the overpass query, 17 | \code{q}, otherwise either the name of a file from which to read data, 18 | or an object of class \pkg{xml2} returned from \link{osmdata_xml}.} 19 | 20 | \item{quiet}{suppress status messages.} 21 | 22 | \item{stringsAsFactors}{Should character strings in the 'data.frame' be 23 | coerced to factors?} 24 | } 25 | \value{ 26 | A \code{data.frame} with id, type and tags of the the objects from the 27 | query. 28 | } 29 | \description{ 30 | Return an OSM Overpass query as a \link{data.frame} object. 31 | } 32 | \details{ 33 | If you are not interested in the geometries of the results, it's a 34 | good option to query for objects that match the features only and forget 35 | about members of the ways and relations. You can achieve this by passing 36 | the parameter \code{body = "tags"} to \code{\link{opq}}. 37 | } 38 | \examples{ 39 | \dontrun{ 40 | hampi_df <- opq ("hampi india") \%>\% 41 | add_osm_feature (key = "historic", value = "ruins") \%>\% 42 | osmdata_data_frame () 43 | attr (hampi_df, "bbox") 44 | attr (hampi_df, "overpass_call") 45 | attr (hampi_df, "meta") 46 | 47 | # Complex query as a string (not possible with regular osmdata functions) 48 | q <- '[out:csv(::type, ::id, "name:ca", "wikidata")][timeout:50]; 49 | area[name="Països Catalans"][boundary=political]->.boundaryarea; 50 | 51 | rel(area.boundaryarea)[admin_level=8][boundary=administrative]; 52 | map_to_area -> .all_level_8_areas; 53 | 54 | ( nwr(area.boundaryarea)[amenity=townhall]; >; ); 55 | is_in; 56 | area._[admin_level=8][boundary=administrative] -> .level_8_areas_with_townhall; 57 | 58 | (.all_level_8_areas; - .level_8_areas_with_townhall;); 59 | rel(pivot); 60 | out tags;' 61 | 62 | no_townhall <- osmdata_data_frame (q) 63 | no_townhall 64 | } 65 | } 66 | \seealso{ 67 | Other extract: 68 | \code{\link{osmdata_sc}()}, 69 | \code{\link{osmdata_sf}()}, 70 | \code{\link{osmdata_sp}()}, 71 | \code{\link{osmdata_xml}()} 72 | } 73 | \concept{extract} 74 | -------------------------------------------------------------------------------- /man/osmdata_sc.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get-osmdata-sc.R 3 | \name{osmdata_sc} 4 | \alias{osmdata_sc} 5 | \title{Return an OSM Overpass query as an \link{osmdata} object in 6 | \code{silicate} (\code{SC}) format.} 7 | \usage{ 8 | osmdata_sc(q, doc, quiet = TRUE) 9 | } 10 | \arguments{ 11 | \item{q}{An object of class \code{overpass_query} constructed with 12 | \link{opq} and \link{add_osm_feature} or a string with a valid query, such 13 | as \code{"(node(39.4712701,-0.3841326,39.4713799,-0.3839475);); out;"}. 14 | 39.4712701,-0.3841326,39.4713799,-0.3839475 15 | May be be omitted, in which case the \link{osmdata} object will not 16 | include the query. See examples below.} 17 | 18 | \item{doc}{If missing, \code{doc} is obtained by issuing the overpass query, 19 | \code{q}, otherwise either the name of a file from which to read data, 20 | or an object of class \pkg{xml2} returned from \link{osmdata_xml}.} 21 | 22 | \item{quiet}{suppress status messages.} 23 | } 24 | \value{ 25 | An object of class \code{osmdata_sc} representing the original OSM hierarchy 26 | of nodes, ways, and relations. 27 | } 28 | \description{ 29 | Return an OSM Overpass query as an \link{osmdata} object in 30 | \code{silicate} (\code{SC}) format. 31 | } 32 | \note{ 33 | The \code{silicate} format is currently highly experimental, and 34 | recommended for use only if you really know what you're doing. 35 | } 36 | \examples{ 37 | \dontrun{ 38 | hampi_sf <- opq ("hampi india") \%>\% 39 | add_osm_feature (key = "historic", value = "ruins") \%>\% 40 | osmdata_sc () 41 | 42 | # Complex query as a string (not possible with regular osmdata functions) 43 | q <- '[out:xml][timeout:50]; 44 | area[name="Països Catalans"][boundary=political]->.boundaryarea; 45 | 46 | rel(area.boundaryarea)[admin_level=8][boundary=administrative]; 47 | map_to_area -> .all_level_8_areas; 48 | 49 | ( nwr(area.boundaryarea)[amenity=townhall]; >; ); 50 | is_in; 51 | area._[admin_level=8][boundary=administrative] -> .level_8_areas_with_townhall; 52 | 53 | (.all_level_8_areas; - .level_8_areas_with_townhall;); 54 | rel(pivot); 55 | (._; >;); 56 | out;' 57 | 58 | no_townhall <- osmdata_sc (q) 59 | no_townhall 60 | } 61 | } 62 | \seealso{ 63 | Other extract: 64 | \code{\link{osmdata_data_frame}()}, 65 | \code{\link{osmdata_sf}()}, 66 | \code{\link{osmdata_sp}()}, 67 | \code{\link{osmdata_xml}()} 68 | } 69 | \concept{extract} 70 | -------------------------------------------------------------------------------- /man/osmdata_sf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get-osmdata-sf.R 3 | \name{osmdata_sf} 4 | \alias{osmdata_sf} 5 | \title{Return an OSM Overpass query as an \link{osmdata} object in \pkg{sf} 6 | format.} 7 | \usage{ 8 | osmdata_sf(q, doc, quiet = TRUE, stringsAsFactors = FALSE) 9 | } 10 | \arguments{ 11 | \item{q}{An object of class \code{overpass_query} constructed with 12 | \link{opq} and \link{add_osm_feature} or a string with a valid query, such 13 | as \code{"(node(39.4712701,-0.3841326,39.4713799,-0.3839475);); out;"}. 14 | 39.4712701,-0.3841326,39.4713799,-0.3839475 15 | May be be omitted, in which case the \link{osmdata} object will not 16 | include the query. See examples below.} 17 | 18 | \item{doc}{If missing, \code{doc} is obtained by issuing the overpass query, 19 | \code{q}, otherwise either the name of a file from which to read data, 20 | or an object of class \pkg{xml2} returned from \link{osmdata_xml}.} 21 | 22 | \item{quiet}{suppress status messages.} 23 | 24 | \item{stringsAsFactors}{Should character strings in 'sf' 'data.frame' be 25 | coerced to factors?} 26 | } 27 | \value{ 28 | An object of class \code{osmdata} with the OSM components (points, lines, 29 | and polygons) represented in \pkg{sf} format. 30 | } 31 | \description{ 32 | Return an OSM Overpass query as an \link{osmdata} object in \pkg{sf} 33 | format. 34 | } 35 | \examples{ 36 | \dontrun{ 37 | hampi_sf <- opq ("hampi india") \%>\% 38 | add_osm_feature (key = "historic", value = "ruins") \%>\% 39 | osmdata_sf () 40 | 41 | # Complex query as a string (not possible with regular osmdata functions) 42 | q <- '[out:xml][timeout:50]; 43 | area[name="Països Catalans"][boundary=political]->.boundaryarea; 44 | 45 | rel(area.boundaryarea)[admin_level=8][boundary=administrative]; 46 | map_to_area -> .all_level_8_areas; 47 | 48 | ( nwr(area.boundaryarea)[amenity=townhall]; >; ); 49 | is_in; 50 | area._[admin_level=8][boundary=administrative] -> .level_8_areas_with_townhall; 51 | 52 | (.all_level_8_areas; - .level_8_areas_with_townhall;); 53 | rel(pivot); 54 | (._; >;); 55 | out;' 56 | 57 | no_townhall <- osmdata_sf (q) 58 | no_townhall 59 | } 60 | } 61 | \seealso{ 62 | Other extract: 63 | \code{\link{osmdata_data_frame}()}, 64 | \code{\link{osmdata_sc}()}, 65 | \code{\link{osmdata_sp}()}, 66 | \code{\link{osmdata_xml}()} 67 | } 68 | \concept{extract} 69 | -------------------------------------------------------------------------------- /man/osmdata_sp.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get-osmdata-sp.R 3 | \name{osmdata_sp} 4 | \alias{osmdata_sp} 5 | \title{Return an OSM Overpass query as an \link{osmdata} object in \pkg{sp} 6 | format.} 7 | \usage{ 8 | osmdata_sp(q, doc, quiet = TRUE) 9 | } 10 | \arguments{ 11 | \item{q}{An object of class \code{overpass_query} constructed with 12 | \link{opq} and \link{add_osm_feature} or a string with a valid query, such 13 | as \code{"(node(39.4712701,-0.3841326,39.4713799,-0.3839475);); out;"}. 14 | 39.4712701,-0.3841326,39.4713799,-0.3839475 15 | May be be omitted, in which case the \link{osmdata} object will not 16 | include the query. See examples below.} 17 | 18 | \item{doc}{If missing, \code{doc} is obtained by issuing the overpass query, 19 | \code{q}, otherwise either the name of a file from which to read data, 20 | or an object of class \pkg{xml2} returned from \link{osmdata_xml}.} 21 | 22 | \item{quiet}{suppress status messages.} 23 | } 24 | \value{ 25 | An object of class \code{osmdata} with the OSM components (points, lines, 26 | and polygons) represented in \pkg{sp} format. 27 | } 28 | \description{ 29 | Return an OSM Overpass query as an \link{osmdata} object in \pkg{sp} 30 | format. 31 | } 32 | \examples{ 33 | \dontrun{ 34 | hampi_sp <- opq ("hampi india") \%>\% 35 | add_osm_feature (key = "historic", value = "ruins") \%>\% 36 | osmdata_sp () 37 | 38 | # Complex query as a string (not possible with regular osmdata functions) 39 | q <- '[out:xml][timeout:50]; 40 | area[name="Països Catalans"][boundary=political]->.boundaryarea; 41 | 42 | rel(area.boundaryarea)[admin_level=8][boundary=administrative]; 43 | map_to_area -> .all_level_8_areas; 44 | 45 | ( nwr(area.boundaryarea)[amenity=townhall]; >; ); 46 | is_in; 47 | area._[admin_level=8][boundary=administrative] -> .level_8_areas_with_townhall; 48 | 49 | (.all_level_8_areas; - .level_8_areas_with_townhall;); 50 | rel(pivot); 51 | (._; >;); 52 | out;' 53 | 54 | no_townhall <- osmdata_sp (q) 55 | no_townhall 56 | } 57 | } 58 | \seealso{ 59 | Other extract: 60 | \code{\link{osmdata_data_frame}()}, 61 | \code{\link{osmdata_sc}()}, 62 | \code{\link{osmdata_sf}()}, 63 | \code{\link{osmdata_xml}()} 64 | } 65 | \concept{extract} 66 | -------------------------------------------------------------------------------- /man/osmdata_xml.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/get-osmdata-xml.R 3 | \name{osmdata_xml} 4 | \alias{osmdata_xml} 5 | \title{Return an OSM Overpass query in XML format 6 | Read an (XML format) OSM Overpass response from a string, a connection, 7 | or a raw vector.} 8 | \usage{ 9 | osmdata_xml(q, filename, quiet = TRUE, encoding) 10 | } 11 | \arguments{ 12 | \item{q}{An object of class \code{overpass_query} constructed with 13 | \link{opq} and \link{add_osm_feature} or a string with a valid query, such 14 | as \code{"(node(39.4712701,-0.3841326,39.4713799,-0.3839475);); out;"}. See examples below.} 15 | 16 | \item{filename}{If given, OSM data are saved to the named file} 17 | 18 | \item{quiet}{suppress status messages.} 19 | 20 | \item{encoding}{Unless otherwise specified XML documents are assumed to be 21 | encoded as UTF-8 or UTF-16. If the document is not UTF-8/16, and lacks 22 | an explicit encoding directive, this allows you to supply a default.} 23 | } 24 | \value{ 25 | An object of class \code{xml2::xml_document} containing the result of the 26 | overpass API query. 27 | } 28 | \description{ 29 | Return an OSM Overpass query in XML format 30 | Read an (XML format) OSM Overpass response from a string, a connection, 31 | or a raw vector. 32 | } 33 | \note{ 34 | Objects of class \code{xml_document} can be saved as \code{.xml} or 35 | \code{.osm} files with \code{xml2::write_xml}. 36 | } 37 | \examples{ 38 | \dontrun{ 39 | q <- opq ("hampi india") 40 | q <- add_osm_feature (q, key = "historic", value = "ruins") 41 | osmdata_xml (q, filename = "hampi.osm") 42 | 43 | # Complex query as a string (not possible with regular osmdata functions) 44 | q <- '[out:xml][timeout:50]; 45 | area[name="Països Catalans"][boundary=political]->.boundaryarea; 46 | 47 | rel(area.boundaryarea)[admin_level=8][boundary=administrative]; 48 | map_to_area -> .all_level_8_areas; 49 | 50 | ( nwr(area.boundaryarea)[amenity=townhall]; >; ); 51 | is_in; 52 | area._[admin_level=8][boundary=administrative] -> .level_8_areas_with_townhall; 53 | 54 | (.all_level_8_areas; - .level_8_areas_with_townhall;); 55 | rel(pivot); 56 | out tags;' 57 | 58 | no_townhall <- osmdata_xml (q) 59 | no_townhall 60 | } 61 | } 62 | \seealso{ 63 | Other extract: 64 | \code{\link{osmdata_data_frame}()}, 65 | \code{\link{osmdata_sc}()}, 66 | \code{\link{osmdata_sf}()}, 67 | \code{\link{osmdata_sp}()} 68 | } 69 | \concept{extract} 70 | -------------------------------------------------------------------------------- /man/overpass_status.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/overpass-query.R 3 | \name{overpass_status} 4 | \alias{overpass_status} 5 | \title{Retrieve status of the Overpass API} 6 | \usage{ 7 | overpass_status(quiet = FALSE) 8 | } 9 | \arguments{ 10 | \item{quiet}{if \code{FALSE} display a status message} 11 | } 12 | \value{ 13 | an invisible list of whether the API is available along with the 14 | text of the message from Overpass and the timestamp of the 15 | next available slot 16 | } 17 | \description{ 18 | Retrieve status of the Overpass API 19 | } 20 | \seealso{ 21 | Other queries: 22 | \code{\link{add_osm_feature}()}, 23 | \code{\link{add_osm_features}()}, 24 | \code{\link{bbox_to_string}()}, 25 | \code{\link{getbb}()}, 26 | \code{\link{opq}()}, 27 | \code{\link{opq_around}()}, 28 | \code{\link{opq_csv}()}, 29 | \code{\link{opq_enclosing}()}, 30 | \code{\link{opq_osm_id}()}, 31 | \code{\link{opq_string}()} 32 | } 33 | \concept{queries} 34 | -------------------------------------------------------------------------------- /man/pipe.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/osmdata-package.R 3 | \name{\%>\%} 4 | \alias{\%>\%} 5 | \title{Pipe operator} 6 | \usage{ 7 | lhs \%>\% rhs 8 | } 9 | \description{ 10 | Pipe operator 11 | } 12 | \keyword{internal} 13 | -------------------------------------------------------------------------------- /man/set_overpass_url.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/zzz.R 3 | \name{set_overpass_url} 4 | \alias{set_overpass_url} 5 | \title{set_overpass_url} 6 | \usage{ 7 | set_overpass_url(overpass_url) 8 | } 9 | \arguments{ 10 | \item{overpass_url}{The desired overpass API URL} 11 | } 12 | \value{ 13 | The overpass API URL 14 | } 15 | \description{ 16 | Set the URL of the specified overpass API. Possible APIs with global coverage 17 | are: 18 | \itemize{ 19 | \item "https://overpass-api.de/api/interpreter" (default) 20 | \item "https://overpass.kumi.systems/api/interpreter" 21 | \item "https://overpass.osm.rambler.ru/cgi/interpreter" 22 | \item "https://api.openstreetmap.fr/oapi/interpreter" 23 | \item "https://overpass.osm.vi-di.fr/api/interpreter" 24 | } 25 | Additional APIs with limited local coverage include: 26 | \itemize{ 27 | \item "https://overpass.osm.ch/api/interpreter" (Switzerland) 28 | \item "https://overpass.openstreetmap.ie/api/interpreter" (Ireland) 29 | } 30 | } 31 | \details{ 32 | For further details, see 33 | \url{https://wiki.openstreetmap.org/wiki/Overpass_API} 34 | } 35 | \seealso{ 36 | \code{\link[=get_overpass_url]{get_overpass_url()}} 37 | 38 | Other overpass: 39 | \code{\link{get_overpass_url}()} 40 | } 41 | \concept{overpass} 42 | -------------------------------------------------------------------------------- /man/trim_osmdata.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/trim-osmdata.R 3 | \name{trim_osmdata} 4 | \alias{trim_osmdata} 5 | \title{trim_osmdata} 6 | \usage{ 7 | trim_osmdata(dat, bb_poly, exclude = TRUE) 8 | } 9 | \arguments{ 10 | \item{dat}{An \link{osmdata} object returned from \link{osmdata_sf} or 11 | \link{osmdata_sp}.} 12 | 13 | \item{bb_poly}{A matrix representing a bounding polygon obtained with 14 | \code{getbb (..., format_out = "polygon")} (and possibly selected from 15 | resultant list where multiple polygons are returned).} 16 | 17 | \item{exclude}{If TRUE, objects are trimmed exclusively, only retaining those 18 | strictly within the bounding polygon; otherwise all objects which partly 19 | extend within the bounding polygon are retained.} 20 | } 21 | \value{ 22 | A trimmed version of \code{dat}, reduced only to those components 23 | lying within the bounding polygon. 24 | } 25 | \description{ 26 | Trim an \link{osmdata} object to within a bounding polygon 27 | } 28 | \note{ 29 | It will generally be necessary to pre-load the \pkg{sf} package for 30 | this function to work correctly. 31 | 32 | Caution is advised when using polygons obtained from Nominatim via 33 | \code{getbb(..., format_out = "polygon"|"sf_polygon")}. These shapes can be 34 | outdated and thus could cause the trimming operation to not give results 35 | expected based on the current state of the OSM data. 36 | } 37 | \examples{ 38 | \dontrun{ 39 | dat <- opq ("colchester uk") \%>\% 40 | add_osm_feature (key = "highway") \%>\% 41 | osmdata_sf (quiet = FALSE) 42 | bb <- getbb ("colchester uk", format_out = "polygon") 43 | library (sf) # required for this function to work 44 | dat_tr <- trim_osmdata (dat, bb) 45 | bb <- getbb ("colchester uk", format_out = "sf_polygon") 46 | class (bb) # sf data.frame 47 | dat_tr <- trim_osmdata (dat, bb) 48 | bb <- as (bb, "Spatial") 49 | class (bb) # SpatialPolygonsDataFrame 50 | dat_tr <- trim_osmdata (dat, bb) 51 | } 52 | } 53 | \seealso{ 54 | Other transform: 55 | \code{\link{osm_elevation}()}, 56 | \code{\link{osm_poly2line}()}, 57 | \code{\link{unique_osmdata}()}, 58 | \code{\link{unname_osmdata_sf}()} 59 | } 60 | \concept{transform} 61 | -------------------------------------------------------------------------------- /man/unique_osmdata.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/unique-osmdata.R 3 | \name{unique_osmdata} 4 | \alias{unique_osmdata} 5 | \title{unique_osmdata} 6 | \usage{ 7 | unique_osmdata(dat) 8 | } 9 | \arguments{ 10 | \item{dat}{An \link{osmdata} object} 11 | } 12 | \value{ 13 | Equivalent object reduced to only unique objects of each type 14 | } 15 | \description{ 16 | Reduce the components of an \link{osmdata} object to only unique items of 17 | each type. That is, reduce \verb{$osm_points} to only those points not 18 | present in other objects (lines, polygons, etc.); reduce \verb{$osm_lines} to 19 | only those lines not present in multiline objects; and reduce 20 | \verb{$osm_polygons} to only those polygons not present in multipolygon 21 | objects. This renders an \link{osmdata} object more directly compatible with 22 | typical output of \pkg{sf}. 23 | } 24 | \seealso{ 25 | Other transform: 26 | \code{\link{osm_elevation}()}, 27 | \code{\link{osm_poly2line}()}, 28 | \code{\link{trim_osmdata}()}, 29 | \code{\link{unname_osmdata_sf}()} 30 | } 31 | \concept{transform} 32 | -------------------------------------------------------------------------------- /man/unname_osmdata_sf.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/utils.R 3 | \name{unname_osmdata_sf} 4 | \alias{unname_osmdata_sf} 5 | \title{unname_osmdata_sf} 6 | \usage{ 7 | unname_osmdata_sf(x) 8 | } 9 | \arguments{ 10 | \item{x}{An 'osmdata_sf' object returned from function of same name} 11 | } 12 | \value{ 13 | Same object, yet with no row names on geometry objects. 14 | } 15 | \description{ 16 | Remove names from \code{osmdata} geometry objects, for cases in which these cause 17 | issues, particularly with plotting, such as 18 | \url{https://github.com/rstudio/leaflet/issues/631}, or 19 | \url{https://github.com/r-spatial/sf/issues/1177}. Note that removing these 20 | names also removes any ability to inter-relate the different components of an 21 | \code{osmdata} object, so use of this function is only recommended to resolve 22 | issues such as those linked to above. 23 | } 24 | \examples{ 25 | \dontrun{ 26 | hampi_sf <- opq ("hampi india") \%>\% 27 | add_osm_feature (key = "historic", value = "ruins") \%>\% 28 | osmdata_sf () 29 | hampi_clean <- unname_osmdata_sf (hampi_sf) 30 | 31 | # All coordinate matrices include rownames with OSM ID values: 32 | head (as.matrix (hampi_sf$osm_lines$geometry [[1]])) 33 | # But 'unname_osmdata_sf' removes both row and column names: 34 | head (as.matrix (hampi_clean$osm_lines$geometry [[1]])) 35 | } 36 | } 37 | \seealso{ 38 | Other transform: 39 | \code{\link{osm_elevation}()}, 40 | \code{\link{osm_poly2line}()}, 41 | \code{\link{trim_osmdata}()}, 42 | \code{\link{unique_osmdata}()} 43 | } 44 | \concept{transform} 45 | -------------------------------------------------------------------------------- /osmdata.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 | PackageRoxygenize: rd,collate,namespace 22 | -------------------------------------------------------------------------------- /paper.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: osmdata 3 | tags: 4 | - openstreetmap 5 | - spatial 6 | - R 7 | - Simple Features 8 | authors: 9 | - name: Mark Padgham 10 | affiliation: 1 11 | - name: Robin Lovelace 12 | affiliation: 3 13 | - name: Maëlle Salmon 14 | affiliation: 2 15 | - name: Bob Rudis 16 | affiliation: 4 17 | affiliations: 18 | - name: Department of Geoinformatics, University of Salzburg, Austria 19 | index: 1 20 | - name: ISGlobal, Centre for Research in Environmental Epidemiology,Universitat Pompeu Fabra, CIBER Epidemiología y Salud Pública, Barcelona, Spain. 21 | index: 2 22 | - name: Institute of Transport Studies, University of Leeds, U.K. 23 | index: 3 24 | - name: Rapid7 25 | index: 4 26 | date: 8 March 2017 27 | bibliography: vignettes/osmdata-refs.bib 28 | nocite: | 29 | @* 30 | --- 31 | 32 | # Summary 33 | 34 | `osmdata` imports OpenStreetMap (OSM) data into R as either Simple Features or 35 | `R` Spatial objects, respectively able to be processed with the R packages `sf` 36 | and `sp`. OSM data are extracted from the Overpass API and processed with very 37 | fast C++ routines for return to R. The package enables simple Overpass queries 38 | to be constructed without the user necessarily understanding the syntax of the 39 | Overpass query language, while retaining the ability to handle arbitrarily 40 | complex queries. Functions are also provided to enable recursive searching 41 | between different kinds of OSM data (for example, to find all lines which 42 | intersect a given point). The package is faster than current alternatives for importing 43 | OSM data into R and is the only one compatible with `sf`. 44 | 45 | # References 46 | -------------------------------------------------------------------------------- /src/RcppExports.cpp: -------------------------------------------------------------------------------- 1 | // Generated by using Rcpp::compileAttributes() -> do not edit by hand 2 | // Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | #include 5 | 6 | using namespace Rcpp; 7 | 8 | #ifdef RCPP_USE_GLOBAL_ROSTREAM 9 | Rcpp::Rostream& Rcpp::Rcout = Rcpp::Rcpp_cout_get(); 10 | Rcpp::Rostream& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get(); 11 | #endif 12 | 13 | // rcpp_osmdata_df 14 | Rcpp::List rcpp_osmdata_df(const std::string& st); 15 | RcppExport SEXP _osmdata_rcpp_osmdata_df(SEXP stSEXP) { 16 | BEGIN_RCPP 17 | Rcpp::RObject rcpp_result_gen; 18 | Rcpp::RNGScope rcpp_rngScope_gen; 19 | Rcpp::traits::input_parameter< const std::string& >::type st(stSEXP); 20 | rcpp_result_gen = Rcpp::wrap(rcpp_osmdata_df(st)); 21 | return rcpp_result_gen; 22 | END_RCPP 23 | } 24 | // rcpp_osmdata_sc 25 | Rcpp::List rcpp_osmdata_sc(const std::string& st); 26 | RcppExport SEXP _osmdata_rcpp_osmdata_sc(SEXP stSEXP) { 27 | BEGIN_RCPP 28 | Rcpp::RObject rcpp_result_gen; 29 | Rcpp::RNGScope rcpp_rngScope_gen; 30 | Rcpp::traits::input_parameter< const std::string& >::type st(stSEXP); 31 | rcpp_result_gen = Rcpp::wrap(rcpp_osmdata_sc(st)); 32 | return rcpp_result_gen; 33 | END_RCPP 34 | } 35 | // rcpp_osmdata_sf 36 | Rcpp::List rcpp_osmdata_sf(const std::string& st); 37 | RcppExport SEXP _osmdata_rcpp_osmdata_sf(SEXP stSEXP) { 38 | BEGIN_RCPP 39 | Rcpp::RObject rcpp_result_gen; 40 | Rcpp::RNGScope rcpp_rngScope_gen; 41 | Rcpp::traits::input_parameter< const std::string& >::type st(stSEXP); 42 | rcpp_result_gen = Rcpp::wrap(rcpp_osmdata_sf(st)); 43 | return rcpp_result_gen; 44 | END_RCPP 45 | } 46 | // rcpp_osmdata_sp 47 | Rcpp::List rcpp_osmdata_sp(const std::string& st); 48 | RcppExport SEXP _osmdata_rcpp_osmdata_sp(SEXP stSEXP) { 49 | BEGIN_RCPP 50 | Rcpp::RObject rcpp_result_gen; 51 | Rcpp::RNGScope rcpp_rngScope_gen; 52 | Rcpp::traits::input_parameter< const std::string& >::type st(stSEXP); 53 | rcpp_result_gen = Rcpp::wrap(rcpp_osmdata_sp(st)); 54 | return rcpp_result_gen; 55 | END_RCPP 56 | } 57 | -------------------------------------------------------------------------------- /src/common.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "common.h" 3 | 4 | // APS sadly xml_document has no copy constructor, so despite NRVO/copy elision, 5 | // cannot return by value. This forces us into using a unique_ptr 6 | XmlDocPtr parseXML (const std::string& xmlString) 7 | { 8 | XmlDocPtr doc (new rapidxml::xml_document<>()); 9 | doc->parse(0)> (const_cast (xmlString.c_str())); 10 | return doc; 11 | } 12 | -------------------------------------------------------------------------------- /src/convert-osm-rcpp.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Project: osmdata 3 | * File: convert_osm_rcpp.h 4 | * Language: C++ 5 | * 6 | * osmdata is free software: you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License as published by the Free 8 | * Software Foundation, either version 3 of the License, or (at your option) 9 | * any later version. 10 | * 11 | * osmdata is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 14 | * details. 15 | * 16 | * You should have received a copy of the GNU General Public License along with 17 | * osm-router. If not, see . 18 | * 19 | * Author: Mark Padgham 20 | * E-Mail: mark.padgham@email.com 21 | * 22 | * Description: Functions to convert OSM data stored in C++ arrays to Rcpp 23 | * structures. 24 | * 25 | * Limitations: 26 | * 27 | * Dependencies: none (rapidXML header included in osmdata) 28 | * 29 | * Compiler Options: -std=c++11 30 | ***************************************************************************/ 31 | 32 | #pragma once 33 | 34 | #include "common.h" 35 | 36 | #include 37 | 38 | namespace osm_convert { 39 | 40 | void trace_way_nmat (const Ways &ways, const Nodes &nodes, 41 | const osmid_t &wayi_id, Rcpp::NumericMatrix &nmat); 42 | 43 | void get_value_mat_way (Ways::const_iterator wayi, 44 | const UniqueVals &unique_vals, Rcpp::CharacterMatrix &value_arr, 45 | unsigned int rowi); 46 | 47 | void get_value_mat_rel (Relations::const_iterator &reli, 48 | const UniqueVals &unique_vals, Rcpp::CharacterMatrix &value_arr, 49 | unsigned int rowi); 50 | 51 | Rcpp::CharacterMatrix restructure_kv_mat (Rcpp::CharacterMatrix &kv, bool ls); 52 | 53 | template Rcpp::List convert_poly_linestring_to_sf ( 54 | const double_arr3 &lon_arr, const double_arr3 &lat_arr, 55 | const string_arr3 &rowname_arr, 56 | const std::vector > &id_vec, 57 | const std::vector &rel_id, const std::string type); 58 | 59 | void convert_multipoly_to_sp (Rcpp::S4 &multipolygons, const Relations &rels, 60 | const double_arr3 &lon_arr, const double_arr3 &lat_arr, 61 | const string_arr3 &rowname_arr, const string_arr2 &id_vec, 62 | const UniqueVals &unique_vals); 63 | 64 | void convert_multiline_to_sp (Rcpp::S4 &multilines, const Relations &rels, 65 | const double_arr3 &lon_arr, const double_arr3 &lat_arr, 66 | const string_arr3 &rowname_arr, const osmt_arr2 &id_vec, 67 | const UniqueVals &unique_vals); 68 | 69 | void convert_relation_to_sc (string_arr2 &members_out, 70 | string_arr2 &kv_out, const Relations &rels, 71 | const UniqueVals &unique_vals); 72 | 73 | } // end namespace osm_convert 74 | -------------------------------------------------------------------------------- /src/get-bbox.cpp: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Project: osmdata 3 | * File: get-bbox.cpp 4 | * Language: C++ 5 | * 6 | * osmdata is free software: you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License as published by the Free 8 | * Software Foundation, either version 3 of the License, or (at your option) 9 | * any later version. 10 | * 11 | * osmdata is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 14 | * details. 15 | * 16 | * You should have received a copy of the GNU General Public License along with 17 | * osm-router. If not, see . 18 | * 19 | * Author: Mark Padgham 20 | * E-Mail: mark.padgham@email.com 21 | * 22 | * Description: Header for rcpp_get_bbox 23 | * 24 | * Limitations: 25 | * 26 | * Dependencies: none (rapidXML header included in osmdata) 27 | * 28 | * Compiler Options: -std=c++11 29 | ***************************************************************************/ 30 | 31 | #include "get-bbox.h" 32 | 33 | Rcpp::NumericMatrix rcpp_get_bbox (double xmin, double xmax, double ymin, double ymax) 34 | { 35 | std::vector colnames, rownames; 36 | colnames.push_back ("min"); 37 | colnames.push_back ("max"); 38 | rownames.push_back ("x"); 39 | rownames.push_back ("y"); 40 | Rcpp::List dimnames (2); 41 | dimnames (0) = rownames; 42 | dimnames (1) = colnames; 43 | 44 | Rcpp::NumericMatrix bbox (Rcpp::Dimension (2, 2)); 45 | bbox (0, 0) = xmin; 46 | bbox (0, 1) = xmax; 47 | bbox (1, 0) = ymin; 48 | bbox (1, 1) = ymax; 49 | 50 | bbox.attr ("dimnames") = dimnames; 51 | 52 | return bbox; 53 | } 54 | 55 | Rcpp::NumericVector rcpp_get_bbox_sf (double xmin, double xmax, double ymin, double ymax) 56 | { 57 | std::vector names; 58 | names.push_back ("xmin"); 59 | names.push_back ("ymin"); 60 | names.push_back ("xmax"); 61 | names.push_back ("ymax"); 62 | 63 | Rcpp::NumericVector bbox (4, NA_REAL); 64 | bbox (0) = xmin; 65 | bbox (1) = xmax; 66 | bbox (2) = ymin; 67 | bbox (3) = ymax; 68 | 69 | bbox.attr ("names") = names; 70 | bbox.attr ("class") = "bbox"; 71 | 72 | return bbox; 73 | } 74 | -------------------------------------------------------------------------------- /src/get-bbox.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Project: osmdata 3 | * File: get-bbox.h 4 | * Language: C++ 5 | * 6 | * osmdata is free software: you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License as published by the Free 8 | * Software Foundation, either version 3 of the License, or (at your option) 9 | * any later version. 10 | * 11 | * osmdata is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 14 | * details. 15 | * 16 | * You should have received a copy of the GNU General Public License along with 17 | * osm-router. If not, see . 18 | * 19 | * Author: Mark Padgham 20 | * E-Mail: mark.padgham@email.com 21 | * 22 | * Description: Header for rcpp_get_bbox 23 | * 24 | * Limitations: 25 | * 26 | * Dependencies: none (rapidXML header included in osmdata) 27 | * 28 | * Compiler Options: -std=c++11 29 | ***************************************************************************/ 30 | 31 | #pragma once 32 | 33 | #include 34 | 35 | Rcpp::NumericMatrix rcpp_get_bbox (double xmin, double xmax, double ymin, double ymax); 36 | Rcpp::NumericVector rcpp_get_bbox_sf (double xmin, double xmax, double ymin, double ymax); 37 | -------------------------------------------------------------------------------- /src/osmdata_init.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include // for NULL 4 | #include 5 | 6 | /* FIXME: 7 | Check these declarations against the C/Fortran source code. 8 | */ 9 | 10 | /* .Call calls */ 11 | extern SEXP _osmdata_rcpp_osmdata_df(SEXP); 12 | extern SEXP _osmdata_rcpp_osmdata_sc(SEXP); 13 | extern SEXP _osmdata_rcpp_osmdata_sf(SEXP); 14 | extern SEXP _osmdata_rcpp_osmdata_sp(SEXP); 15 | 16 | static const R_CallMethodDef CallEntries[] = { 17 | {"_osmdata_rcpp_osmdata_df", (DL_FUNC) &_osmdata_rcpp_osmdata_df, 1}, 18 | {"_osmdata_rcpp_osmdata_sc", (DL_FUNC) &_osmdata_rcpp_osmdata_sc, 1}, 19 | {"_osmdata_rcpp_osmdata_sf", (DL_FUNC) &_osmdata_rcpp_osmdata_sf, 1}, 20 | {"_osmdata_rcpp_osmdata_sp", (DL_FUNC) &_osmdata_rcpp_osmdata_sp, 1}, 21 | {NULL, NULL, 0} 22 | }; 23 | 24 | void R_init_osmdata(DllInfo *dll) 25 | { 26 | R_registerRoutines(dll, NULL, CallEntries, NULL, NULL); 27 | R_useDynamicSymbols(dll, FALSE); 28 | } 29 | -------------------------------------------------------------------------------- /src/trace-osm.h: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | * Project: osmdata 3 | * File: trace-osm.h 4 | * Language: C++ 5 | * 6 | * osmdata is free software: you can redistribute it and/or modify it under 7 | * the terms of the GNU General Public License as published by the Free 8 | * Software Foundation, either version 3 of the License, or (at your option) 9 | * any later version. 10 | * 11 | * osmdata is distributed in the hope that it will be useful, but WITHOUT ANY 12 | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 13 | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more 14 | * details. 15 | * 16 | * You should have received a copy of the GNU General Public License along with 17 | * osm-router. If not, see . 18 | * 19 | * Author: Mark Padgham 20 | * E-Mail: mark.padgham@email.com 21 | * 22 | * Description: Functions to trace OSM ways and store in C++ dynamic arrays 23 | * (no RCpp here). 24 | * 25 | * Limitations: 26 | * 27 | * Dependencies: none (rapidXML header included in osmdata) 28 | * 29 | * Compiler Options: -std=c++11 30 | ***************************************************************************/ 31 | 32 | #pragma once 33 | 34 | #include "common.h" 35 | 36 | void trace_relation (Relations::const_iterator &itr_rel, 37 | osm_str_vec &relation_ways, 38 | std::vector > & relation_kv); 39 | 40 | void trace_multipolygon (Relations::const_iterator &itr_rel, const Ways &ways, 41 | const Nodes &nodes, double_arr2 &lon_vec, double_arr2 &lat_vec, 42 | string_arr2 &rowname_vec, std::vector &ids); 43 | 44 | void trace_multilinestring (Relations::const_iterator &itr_rel, 45 | const std::string role, const Ways &ways, const Nodes &nodes, 46 | double_arr2 &lon_vec, double_arr2 &lat_vec, string_arr2 &rowname_vec, 47 | std::vector &ids); 48 | 49 | osmid_t trace_way (const Ways &ways, const Nodes &nodes, osmid_t first_node, 50 | const osmid_t &wayi_id, std::vector &lons, 51 | std::vector &lats, std::vector &rownames, 52 | const bool append); 53 | 54 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | library(osmdata) 3 | 4 | test_check("osmdata") 5 | -------------------------------------------------------------------------------- /tests/testthat/fixtures/osm-adiff2.osm: -------------------------------------------------------------------------------- 1 | 2 | 3 | The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /tests/testthat/fixtures/osm-date.osm: -------------------------------------------------------------------------------- 1 | 2 | 3 | The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/testthat/fixtures/osm-empty.osm: -------------------------------------------------------------------------------- 1 | 2 | 3 | The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. 4 | 5 | 6 | -------------------------------------------------------------------------------- /tests/testthat/fixtures/osm-key_clashes.osm: -------------------------------------------------------------------------------- 1 | 2 | 3 | The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | -------------------------------------------------------------------------------- /tests/testthat/fixtures/osm-meta_adiff.osm: -------------------------------------------------------------------------------- 1 | 2 | 3 | The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /tests/testthat/fixtures/osm-meta_diff.osm: -------------------------------------------------------------------------------- 1 | 2 | 3 | The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /tests/testthat/fixtures/osm-multi.osm: -------------------------------------------------------------------------------- 1 | 2 | 3 | The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | -------------------------------------------------------------------------------- /tests/testthat/fixtures/osm-tags.osm: -------------------------------------------------------------------------------- 1 | 2 | 3 | The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | -------------------------------------------------------------------------------- /tests/testthat/fixtures/osm-tags_center-adiff.osm: -------------------------------------------------------------------------------- 1 | 2 | 3 | The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 |
68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 |
77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 |
86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 |
95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 |
105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 |
113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 |
123 | 124 | 125 | 126 | 127 | 128 |
129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 |
141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 |
151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 |
159 | 160 | 161 | 162 | 163 | 164 |
165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | -------------------------------------------------------------------------------- /tests/testthat/fixtures/osm-tags_center.osm: -------------------------------------------------------------------------------- 1 | 2 | 3 | The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 |
38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 |
48 | 49 | 50 | 51 | 52 | 53 |
54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 |
62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 |
72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | -------------------------------------------------------------------------------- /tests/testthat/fixtures/osm-ways.osm: -------------------------------------------------------------------------------- 1 | 2 | 3 | The data included in this document is from www.openstreetmap.org. The data is made available under ODbL. 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /tests/testthat/mock_bb/nominatim/search-619814.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "place_id": 307835155, 4 | "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright", 5 | "osm_type": "relation", 6 | "osm_id": 86538, 7 | "lat": "47.7981346", 8 | "lon": "13.0464806", 9 | "class": "boundary", 10 | "type": "administrative", 11 | "place_rank": 12, 12 | "importance": 0.5754709096560191, 13 | "addresstype": "city", 14 | "name": "Salzburg", 15 | "display_name": "Salzburg, 5020, Österreich", 16 | "boundingbox": [ 17 | "47.7512115", 18 | "47.8543925", 19 | "12.9856478", 20 | "13.1275256" 21 | ] 22 | }, 23 | { 24 | "place_id": 307852111, 25 | "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright", 26 | "osm_type": "relation", 27 | "osm_id": 86539, 28 | "lat": "47.4166667", 29 | "lon": "13.25", 30 | "class": "boundary", 31 | "type": "administrative", 32 | "place_rank": 8, 33 | "importance": 0.5614282515201715, 34 | "addresstype": "state", 35 | "name": "Salzburg", 36 | "display_name": "Salzburg, Österreich", 37 | "boundingbox": [ 38 | "46.9438580", 39 | "48.0414691", 40 | "12.0760956", 41 | "13.9961250" 42 | ] 43 | }, 44 | { 45 | "place_id": 307733752, 46 | "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright", 47 | "osm_type": "relation", 48 | "osm_id": 114907, 49 | "lat": "48.8230783", 50 | "lon": "6.5113122", 51 | "class": "boundary", 52 | "type": "administrative", 53 | "place_rank": 16, 54 | "importance": 0.551945755236079, 55 | "addresstype": "village", 56 | "name": "Château-Salins", 57 | "display_name": "Château-Salins, Sarrebourg-Château-Salins, Moselle, Grand Est, France métropolitaine, 57170, France", 58 | "boundingbox": [ 59 | "48.8037039", 60 | "48.8364496", 61 | "6.4566055", 62 | "6.5287811" 63 | ] 64 | } 65 | ] 66 | -------------------------------------------------------------------------------- /tests/testthat/mock_bb_df/nominatim/search-619814.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "place_id": 307835155, 4 | "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright", 5 | "osm_type": "relation", 6 | "osm_id": 86538, 7 | "lat": "47.7981346", 8 | "lon": "13.0464806", 9 | "class": "boundary", 10 | "type": "administrative", 11 | "place_rank": 12, 12 | "importance": 0.5754709096560191, 13 | "addresstype": "city", 14 | "name": "Salzburg", 15 | "display_name": "Salzburg, 5020, Österreich", 16 | "boundingbox": [ 17 | "47.7512115", 18 | "47.8543925", 19 | "12.9856478", 20 | "13.1275256" 21 | ] 22 | }, 23 | { 24 | "place_id": 307852111, 25 | "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright", 26 | "osm_type": "relation", 27 | "osm_id": 86539, 28 | "lat": "47.4166667", 29 | "lon": "13.25", 30 | "class": "boundary", 31 | "type": "administrative", 32 | "place_rank": 8, 33 | "importance": 0.5614282515201715, 34 | "addresstype": "state", 35 | "name": "Salzburg", 36 | "display_name": "Salzburg, Österreich", 37 | "boundingbox": [ 38 | "46.9438580", 39 | "48.0414691", 40 | "12.0760956", 41 | "13.9961250" 42 | ] 43 | }, 44 | { 45 | "place_id": 307733752, 46 | "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright", 47 | "osm_type": "relation", 48 | "osm_id": 114907, 49 | "lat": "48.8230783", 50 | "lon": "6.5113122", 51 | "class": "boundary", 52 | "type": "administrative", 53 | "place_rank": 16, 54 | "importance": 0.551945755236079, 55 | "addresstype": "village", 56 | "name": "Château-Salins", 57 | "display_name": "Château-Salins, Sarrebourg-Château-Salins, Moselle, Grand Est, France métropolitaine, 57170, France", 58 | "boundingbox": [ 59 | "48.8037039", 60 | "48.8364496", 61 | "6.4566055", 62 | "6.5287811" 63 | ] 64 | } 65 | ] 66 | -------------------------------------------------------------------------------- /tests/testthat/mock_bb_nope/nominatim/search-619814.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "place_id": 307835155, 4 | "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright", 5 | "osm_type": "relation", 6 | "osm_id": 86538, 7 | "lat": "47.7981346", 8 | "lon": "13.0464806", 9 | "class": "boundary", 10 | "type": "administrative", 11 | "place_rank": 12, 12 | "importance": 0.5754709096560191, 13 | "addresstype": "city", 14 | "name": "Salzburg", 15 | "display_name": "Salzburg, 5020, Österreich", 16 | "boundingbox": [ 17 | "47.7512115", 18 | "47.8543925", 19 | "12.9856478", 20 | "13.1275256" 21 | ] 22 | }, 23 | { 24 | "place_id": 307852111, 25 | "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright", 26 | "osm_type": "relation", 27 | "osm_id": 86539, 28 | "lat": "47.4166667", 29 | "lon": "13.25", 30 | "class": "boundary", 31 | "type": "administrative", 32 | "place_rank": 8, 33 | "importance": 0.5614282515201715, 34 | "addresstype": "state", 35 | "name": "Salzburg", 36 | "display_name": "Salzburg, Österreich", 37 | "boundingbox": [ 38 | "46.9438580", 39 | "48.0414691", 40 | "12.0760956", 41 | "13.9961250" 42 | ] 43 | }, 44 | { 45 | "place_id": 307733752, 46 | "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright", 47 | "osm_type": "relation", 48 | "osm_id": 114907, 49 | "lat": "48.8230783", 50 | "lon": "6.5113122", 51 | "class": "boundary", 52 | "type": "administrative", 53 | "place_rank": 16, 54 | "importance": 0.551945755236079, 55 | "addresstype": "village", 56 | "name": "Château-Salins", 57 | "display_name": "Château-Salins, Sarrebourg-Château-Salins, Moselle, Grand Est, France métropolitaine, 57170, France", 58 | "boundingbox": [ 59 | "48.8037039", 60 | "48.8364496", 61 | "6.4566055", 62 | "6.5287811" 63 | ] 64 | } 65 | ] 66 | -------------------------------------------------------------------------------- /tests/testthat/mock_bb_state/nominatim/search-226ae6.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "place_id": 307835155, 4 | "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright", 5 | "osm_type": "relation", 6 | "osm_id": 86538, 7 | "lat": "47.7981346", 8 | "lon": "13.0464806", 9 | "class": "boundary", 10 | "type": "administrative", 11 | "place_rank": 12, 12 | "importance": 0.5754709096560191, 13 | "addresstype": "city", 14 | "name": "Salzburg", 15 | "display_name": "Salzburg, 5020, Österreich", 16 | "boundingbox": [ 17 | "47.7512115", 18 | "47.8543925", 19 | "12.9856478", 20 | "13.1275256" 21 | ] 22 | }, 23 | { 24 | "place_id": 307852111, 25 | "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright", 26 | "osm_type": "relation", 27 | "osm_id": 86539, 28 | "lat": "47.4166667", 29 | "lon": "13.25", 30 | "class": "boundary", 31 | "type": "administrative", 32 | "place_rank": 8, 33 | "importance": 0.5614282515201715, 34 | "addresstype": "state", 35 | "name": "Salzburg", 36 | "display_name": "Salzburg, Österreich", 37 | "boundingbox": [ 38 | "46.9438580", 39 | "48.0414691", 40 | "12.0760956", 41 | "13.9961250" 42 | ] 43 | }, 44 | { 45 | "place_id": 307733752, 46 | "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright", 47 | "osm_type": "relation", 48 | "osm_id": 114907, 49 | "lat": "48.8230783", 50 | "lon": "6.5113122", 51 | "class": "boundary", 52 | "type": "administrative", 53 | "place_rank": 16, 54 | "importance": 0.551945755236079, 55 | "addresstype": "village", 56 | "name": "Château-Salins", 57 | "display_name": "Château-Salins, Sarrebourg-Château-Salins, Moselle, Grand Est, France métropolitaine, 57170, France", 58 | "boundingbox": [ 59 | "48.8037039", 60 | "48.8364496", 61 | "6.4566055", 62 | "6.5287811" 63 | ] 64 | } 65 | ] 66 | -------------------------------------------------------------------------------- /tests/testthat/mock_bb_str/nominatim/search-619814.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "place_id": 307835155, 4 | "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright", 5 | "osm_type": "relation", 6 | "osm_id": 86538, 7 | "lat": "47.7981346", 8 | "lon": "13.0464806", 9 | "class": "boundary", 10 | "type": "administrative", 11 | "place_rank": 12, 12 | "importance": 0.5754709096560191, 13 | "addresstype": "city", 14 | "name": "Salzburg", 15 | "display_name": "Salzburg, 5020, Österreich", 16 | "boundingbox": [ 17 | "47.7512115", 18 | "47.8543925", 19 | "12.9856478", 20 | "13.1275256" 21 | ] 22 | }, 23 | { 24 | "place_id": 307852111, 25 | "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright", 26 | "osm_type": "relation", 27 | "osm_id": 86539, 28 | "lat": "47.4166667", 29 | "lon": "13.25", 30 | "class": "boundary", 31 | "type": "administrative", 32 | "place_rank": 8, 33 | "importance": 0.5614282515201715, 34 | "addresstype": "state", 35 | "name": "Salzburg", 36 | "display_name": "Salzburg, Österreich", 37 | "boundingbox": [ 38 | "46.9438580", 39 | "48.0414691", 40 | "12.0760956", 41 | "13.9961250" 42 | ] 43 | }, 44 | { 45 | "place_id": 307733752, 46 | "licence": "Data © OpenStreetMap contributors, ODbL 1.0. http://osm.org/copyright", 47 | "osm_type": "relation", 48 | "osm_id": 114907, 49 | "lat": "48.8230783", 50 | "lon": "6.5113122", 51 | "class": "boundary", 52 | "type": "administrative", 53 | "place_rank": 16, 54 | "importance": 0.551945755236079, 55 | "addresstype": "village", 56 | "name": "Château-Salins", 57 | "display_name": "Château-Salins, Sarrebourg-Château-Salins, Moselle, Grand Est, France métropolitaine, 57170, France", 58 | "boundingbox": [ 59 | "48.8037039", 60 | "48.8364496", 61 | "6.4566055", 62 | "6.5287811" 63 | ] 64 | } 65 | ] 66 | -------------------------------------------------------------------------------- /tests/testthat/mock_bb_typo/nominatim/search-c218d5.json: -------------------------------------------------------------------------------- 1 | [ 2 | 3 | ] 4 | -------------------------------------------------------------------------------- /tests/testthat/mock_csv/overpass-api.de/api/interpreter-14ea8d-POST.csv: -------------------------------------------------------------------------------- 1 | name @type @id @lat @lon 2 | Berguedà relation 358838 42.1103717 1.8402952 3 | Selva relation 368462 41.8546888 2.6891871 4 | els Ports relation 1110951 40.5778284 -0.0978422 5 | l'Alcalatén relation 1111146 40.1398706 -0.2193438 6 | l'Alt Maestrat relation 1690971 40.3629586 -0.1424604 7 | el Baix Maestrat relation 1690974 40.4683788 0.2525967 8 | la Plana Alta relation 1690975 40.1342846 0.2622046 9 | la Plana Baixa relation 1690976 39.8852319 -0.2143932 10 | el Camp de Morvedre relation 1691745 39.7078123 -0.3166373 11 | el Camp de Túria relation 1691746 39.6323445 -0.7172835 12 | l'Horta Nord relation 1691749 39.5619896 -0.3883448 13 | l'Horta Sud relation 1691751 39.4129175 -0.4736044 14 | la Costera relation 1691752 38.9193098 -0.6547474 15 | la Ribera Alta relation 1691755 39.2128139 -0.5245022 16 | la Ribera Baixa relation 1691756 39.2144885 -0.3212461 17 | la Safor relation 1691758 38.9881946 -0.2047513 18 | la Vall d'Albaida relation 1691760 38.8539189 -0.5737529 19 | l'Alacantí relation 1692438 38.4056201 -0.5033693 20 | l'Alt Vinalopó / El Alto Vinalopó relation 1692439 38.6277348 -0.8526744 21 | el Baix Vinalopó relation 1692440 38.2363541 -0.7015191 22 | el Comtat relation 1692441 38.7613212 -0.3958977 23 | l'Alcoià relation 1692442 38.6167866 -0.5455140 24 | la Marina Alta relation 1692443 38.7562583 -0.0365367 25 | la Marina Baixa relation 1692445 38.6099302 -0.1989179 26 | el Vinalopó Mitjà / El Vinalopó Medio relation 1692446 38.4028238 -0.8652338 27 | el Baix Segura / La Vega Baja del Segura relation 1692447 38.0867248 -0.8370737 28 | Maresme relation 2140187 41.6024395 2.5124775 29 | Migjorn relation 2174950 39.4081245 2.9995631 30 | Palma relation 2174951 39.3894950 2.7718533 31 | Raiguer relation 2175689 39.7377554 2.9359534 32 | Serra de Tramuntana relation 2175756 39.7096097 2.7587523 33 | Pla de Mallorca relation 2175937 39.6379776 3.0288588 34 | Llevant relation 2176079 39.6141218 3.3006899 35 | Alt Empordà relation 2177382 42.2902431 2.9321336 36 | Eivissa relation 2181664 38.9660000 1.4038483 37 | Menorca relation 2182003 39.9468675 4.0594383 38 | Vallès Occidental relation 2350067 41.5661409 2.0428701 39 | Bages relation 2350331 41.7804742 1.7993868 40 | Barcelonès relation 2417889 41.4049760 2.1612620 41 | Vallès Oriental relation 2417929 41.6486686 2.3523480 42 | Osona relation 2422857 41.9513563 2.2460331 43 | Perpignan relation 2766170 42.7653771 2.8145209 44 | Céret relation 2767883 42.5009570 2.7483306 45 | Prades relation 2767884 42.5993224 2.2356377 46 | Andorra la Vella relation 2804753 42.4958104 1.5097246 47 | Canillo relation 2804754 42.5869390 1.6743395 48 | Encamp relation 2804755 42.5244998 1.6424672 49 | Escaldes-Engordany relation 2804756 42.4868412 1.5924268 50 | La Massana relation 2804757 42.5584571 1.4877966 51 | Ordino relation 2804758 42.6008913 1.5377353 52 | Sant Julià de Lòria relation 2804759 42.4666490 1.4892648 53 | Baix Empordà relation 2805694 41.9465701 3.0600131 54 | Cerdanya relation 2805972 42.3926994 1.7981772 55 | Ripollès relation 2806754 42.2729757 2.2571603 56 | Garrotxa relation 2806999 42.1730998 2.5556873 57 | Gironès relation 2807130 41.9370996 2.8088387 58 | Pla de l'Estany relation 2807146 42.1219920 2.7703125 59 | Anoia relation 2808804 41.6149868 1.6081218 60 | Solsonès relation 2809162 41.9815569 1.5149080 61 | Baix Llobregat relation 2809457 41.4333914 1.9810282 62 | Garraf relation 2809538 41.2609631 1.7927329 63 | Alt Penedès relation 2809672 41.3682496 1.6857944 64 | Alt Urgell relation 2810001 42.2414509 1.4088788 65 | Pallars Sobirà relation 2810705 42.5236699 1.1910900 66 | Alta Ribagorça relation 2810808 42.4653972 0.8315735 67 | Pallars Jussà relation 2810954 42.2806710 0.9330304 68 | Segarra relation 2815579 41.7419394 1.3350335 69 | Noguera relation 2816276 41.9043257 0.9378452 70 | Urgell relation 2818895 41.6632089 1.0861269 71 | Pla d'Urgell relation 2819346 41.6451962 0.9142457 72 | Segrià relation 2819857 41.5641758 0.5684077 73 | Garrigues relation 2819870 41.4401563 0.8279492 74 | Conca de Barberà relation 2822039 41.4440063 1.1906778 75 | Alt Camp relation 2822130 41.3396603 1.2904195 76 | Baix Penedès relation 2822410 41.2794928 1.5218204 77 | Tarragonès relation 2822691 41.1546279 1.2948932 78 | Baix Camp relation 2824935 41.1440772 0.9830428 79 | Priorat relation 2826145 41.2139646 0.8172476 80 | Baix Ebre relation 2826423 40.8544372 0.5499162 81 | Montsià relation 2827413 40.6527475 0.5179996 82 | Ribera d'Ebre relation 2829952 41.1328120 0.6196728 83 | Terra Alta relation 2829953 41.0272217 0.3858587 84 | Oriental relation 2902368 38.2298550 -1.0904053 85 | Altiplano relation 2902371 38.5214777 -1.2501508 86 | Moianès relation 4791885 41.8093396 2.0737237 87 | Comarca de València relation 5813174 39.4225292 -0.3525358 88 | La Ribagorza relation 6488309 42.3303706 0.4973777 89 | La Litera / La Llitera relation 6488338 41.8787046 0.4276618 90 | Bajo Cinca / Baix Cinca relation 6488361 41.5141079 0.1942071 91 | Matarraña / Matarranya relation 6630537 40.8856740 0.0731607 92 | Bajo Aragón relation 6630546 40.9550285 -0.2615028 93 | Formentera relation 6914328 38.7227575 1.4824392 94 | Bajo Aragón-Caspe / Baix Aragó-Casp relation 10601144 41.2217806 0.0845647 95 | -------------------------------------------------------------------------------- /tests/testthat/mock_csv/overpass-api.de/api/status.txt: -------------------------------------------------------------------------------- 1 | Connected as: 123456789 2 | Current time: 2022-01-01T00:00:00Z 3 | Announced endpoint: lambert.openstreetmap.de/ 4 | Rate limit: 6 5 | 6 slots available now. 6 | Currently running queries (pid, space limit, time limit, start time): 7 | -------------------------------------------------------------------------------- /tests/testthat/mock_csv_quotes/overpass-api.de/api/status.txt: -------------------------------------------------------------------------------- 1 | Connected as: 123456789 2 | Current time: 2022-01-01T00:00:00Z 3 | Announced endpoint: lambert.openstreetmap.de/ 4 | Rate limit: 6 5 | 6 slots available now. 6 | Currently running queries (pid, space limit, time limit, start time): 7 | -------------------------------------------------------------------------------- /tests/testthat/mock_elevation/overpass-api.de/api/status.txt: -------------------------------------------------------------------------------- 1 | Connected as: 123456789 2 | Current time: 2022-01-01T00:00:00Z 3 | Announced endpoint: z.overpass-api.de/api/ 4 | Rate limit: 3 5 | 3 slots available now. 6 | Currently running queries (pid, space limit, time limit, start time): 7 | -------------------------------------------------------------------------------- /tests/testthat/mock_osm_df/overpass-api.de/api/status.txt: -------------------------------------------------------------------------------- 1 | Connected as: 123456789 2 | Current time: 2022-01-01T00:00:00Z 3 | Announced endpoint: z.overpass-api.de/api/ 4 | Rate limit: 3 5 | Slot available after: 2022-01-01T00:00:00Z, in 0 seconds. 6 | Slot available after: 2022-01-01T00:00:00Z, in 2 seconds. 7 | Slot available after: 2022-01-01T00:00:00Z, in 8 seconds. 8 | Currently running queries (pid, space limit, time limit, start time): 9 | -------------------------------------------------------------------------------- /tests/testthat/mock_osm_sc/overpass-api.de/api/status.txt: -------------------------------------------------------------------------------- 1 | Connected as: 123456789 2 | Current time: 2022-01-01T00:00:00Z 3 | Announced endpoint: z.overpass-api.de/api/ 4 | Rate limit: 3 5 | 3 slots available now. 6 | Currently running queries (pid, space limit, time limit, start time): 7 | -------------------------------------------------------------------------------- /tests/testthat/mock_osm_sf/overpass-api.de/api/status.txt: -------------------------------------------------------------------------------- 1 | Connected as: 123456789 2 | Current time: 2022-01-01T00:00:00Z 3 | Announced endpoint: z.overpass-api.de/api/ 4 | Rate limit: 3 5 | Slot available after: 2022-01-01T00:00:00Z, in 4 seconds. 6 | Slot available after: 2022-01-01T00:00:00Z, in 5 seconds. 7 | Slot available after: 2022-01-01T00:00:00Z, in 13 seconds. 8 | Currently running queries (pid, space limit, time limit, start time): 9 | -------------------------------------------------------------------------------- /tests/testthat/mock_osm_sp/overpass-api.de/api/status.txt: -------------------------------------------------------------------------------- 1 | Connected as: 123456789 2 | Current time: 2022-01-01T00:00:00Z 3 | Announced endpoint: z.overpass-api.de/api/ 4 | Rate limit: 3 5 | Slot available after: 2022-01-01T00:00:00Z, in 5 seconds. 6 | Slot available after: 2022-01-01T00:00:00Z, in 12 seconds. 7 | Slot available after: 2022-01-01T00:00:00Z, in 20 seconds. 8 | Currently running queries (pid, space limit, time limit, start time): 9 | -------------------------------------------------------------------------------- /tests/testthat/mock_osm_xml/overpass-api.de/api/status.txt: -------------------------------------------------------------------------------- 1 | Connected as: 123456789 2 | Current time: 2022-01-01T00:00:00Z 3 | Announced endpoint: z.overpass-api.de/api/ 4 | Rate limit: 3 5 | 2 slots available now. 6 | Slot available after: 2022-01-01T00:00:00Z, in 22 seconds. 7 | Currently running queries (pid, space limit, time limit, start time): 8 | -------------------------------------------------------------------------------- /tests/testthat/mock_osm_xml2/overpass-api.de/api/status.txt: -------------------------------------------------------------------------------- 1 | Connected as: 123456789 2 | Current time: 2022-01-01T00:00:00Z 3 | Announced endpoint: z.overpass-api.de/api/ 4 | Rate limit: 3 5 | 1 slots available now. 6 | Slot available after: 2022-01-01T00:00:00Z, in 13 seconds. 7 | Slot available after: 2022-01-01T00:00:00Z, in 21 seconds. 8 | Currently running queries (pid, space limit, time limit, start time): 9 | -------------------------------------------------------------------------------- /tests/testthat/mock_unname/overpass-api.de/api/status.txt: -------------------------------------------------------------------------------- 1 | Connected as: 123456789 2 | Current time: 2022-01-01T00:00:00Z 3 | Announced endpoint: z.overpass-api.de/api/ 4 | Rate limit: 3 5 | 1 slots available now. 6 | Slot available after: 2022-01-01T00:00:00Z, in 2 seconds. 7 | Slot available after: 2022-01-01T00:00:00Z, in 3 seconds. 8 | Currently running queries (pid, space limit, time limit, start time): 9 | -------------------------------------------------------------------------------- /tests/testthat/setup.R: -------------------------------------------------------------------------------- 1 | library(httptest2) 2 | 3 | set_overpass_url ("https://overpass-api.de/api/interpreter") 4 | 5 | test_all <- Sys.getenv ("GITHUB_WORKFLOW") != "R-CMD-check" 6 | -------------------------------------------------------------------------------- /tests/testthat/test-c.R: -------------------------------------------------------------------------------- 1 | context ("c") 2 | 3 | test_that ("c-method", { 4 | 5 | # osmdata_sf: 6 | q <- opq (bbox = c (1, 1, 5, 5)) 7 | x1 <- osmdata_sf (q, test_path ("fixtures", "osm-multi.osm")) 8 | x2 <- osmdata_sf (q, test_path ("fixtures", "osm-ways.osm")) 9 | x <- c (x1, x2) 10 | osm_indx <- which (grepl ("osm_", names (x))) 11 | for (i in osm_indx) { 12 | expect_true (nrow (x [[i]]) >= nrow (x1 [[i]])) 13 | if (!is.null (x2 [[i]])) { 14 | expect_true (nrow (x [[i]]) >= nrow (x2 [[i]])) 15 | } 16 | } 17 | 18 | # osmdata_sc: 19 | q0 <- opq (bbox = c (1, 1, 5, 5)) 20 | x1 <- osmdata_sc (q0, test_path ("fixtures", "osm-multi.osm")) 21 | x2 <- osmdata_sc (q0, test_path ("fixtures", "osm-ways.osm")) 22 | x12 <- c (x1, x2) 23 | n1 <- vapply (x1, nrow, integer (1L)) 24 | n2 <- vapply (x2, nrow, integer (1L)) 25 | n12 <- vapply (x12, nrow, integer (1L)) 26 | # There is some redundancy in the data, so some n12 == n1 | n2: 27 | expect_true (all (n12 >= n1 & n12 >= n2)) 28 | expect_true (any (n12 > n1 & n12 > n2)) 29 | }) 30 | 31 | 32 | test_that ("poly2line", { 33 | q <- opq (bbox = c (1, 1, 5, 5)) 34 | x <- osmdata_sf (q, test_path ("fixtures", "osm-multi.osm")) 35 | nold <- nrow (x$osm_lines) 36 | x <- osm_poly2line (x) 37 | nnew <- nrow (x$osm_lines) 38 | expect_identical (nrow (x$osm_polygons), nnew - nold) 39 | }) 40 | -------------------------------------------------------------------------------- /tests/testthat/test-elevation.R: -------------------------------------------------------------------------------- 1 | test_that ("elevation", { 2 | 3 | # elevation can't actually be tested, because it only works with a full SRTM 4 | # elevation file, so this test doesn't actually do anything. 5 | qry <- opq (bbox = c (-0.116, 51.516, -0.115, 51.517)) %>% 6 | add_osm_feature (key = "highway") 7 | 8 | f <- file.path (tempdir (), "junk.osm") 9 | doc <- with_mock_dir ("mock_elevation", { 10 | osmdata_xml (qry, file = f) 11 | }) 12 | 13 | expect_silent (x <- osmdata_sc (qry, doc = f)) 14 | expect_true (file.exists (f)) 15 | 16 | xml <- xml2::read_xml (f) 17 | expect_s3_class (xml, "xml_document") 18 | 19 | # elev_file = "/data/data/elevation/srtm_36_02.zip" 20 | # x <- osm_elevation (x, elev_file = elev_file) 21 | }) 22 | 23 | # elevation.R has two helper fns: 24 | # 1. check_bbox() 25 | # 2. get_file_index() 26 | test_that ("misc elevation fns", { 27 | 28 | bbox <- c (-0.116, 51.516, -0.115, 51.517) 29 | # 2nd param of check_bbox() is a raster object to which sp::bbox can be 30 | # directly applied; faked here with a simple matrix: 31 | bbox_mat <- t (matrix (bbox, ncol = 2)) 32 | 33 | qry <- opq (bbox = bbox) 34 | dat <- list (meta = list (bbox = qry$bbox)) 35 | # 'sp' will soon issue a message here about depending on legacy packages. 36 | # Expectation may be restored once sp-dependency has been removed (#273). 37 | # expect_silent ( 38 | check_bbox (dat, bbox_mat) 39 | # ) 40 | 41 | ti <- get_tile_index (qry$bbox) 42 | expect_s3_class (ti, "data.frame") 43 | expect_length (ti, 2L) 44 | expect_identical (names (ti), c ("xi", "yi")) 45 | expect_type (ti$xi, "integer") 46 | expect_type (ti$yi, "integer") 47 | }) 48 | -------------------------------------------------------------------------------- /tests/testthat/test-features.R: -------------------------------------------------------------------------------- 1 | # Note: the html files produced by these calls, and stored by `httptest2`, are 2 | # huge (> 1MB each), so have to be "post-processeed" here to reduce them to a 3 | # small sample only. Post-process of features is done in the test call; tags are 4 | # done via separate fn defined below. 5 | 6 | test_that ("available_features", { 7 | 8 | expect_error (available_features (1), "unused argument") 9 | 10 | post_process <- !dir.exists ("mock_features") 11 | f <- with_mock_dir ("mock_features", { 12 | available_features () 13 | }) 14 | 15 | if (post_process) { 16 | fname <- list.files ("mock_features", 17 | full.names = TRUE, 18 | recursive = TRUE 19 | ) [1] 20 | x <- xml2::read_html (fname) 21 | nodes_all <- rvest::html_elements (x, "td") 22 | nodes_sample <- nodes_all [1:20] 23 | writeLines (as.character (nodes_sample), fname) 24 | } 25 | 26 | expect_is (f, "character") 27 | expect_true (length (f) > 1L) 28 | }) 29 | 30 | 31 | #' The raw HTML files are > 1MB. This function reduces their size by selecting 32 | #' just a few sample nodes, and only tables for a specific key. Note that keys 33 | #' like "highway" still correspond to overly large tables. The default key 34 | #' corresponds to the item in `tables_r` below which has the smallest number of 35 | #' rows. 36 | #' @noRd 37 | post_process_tags <- function (dir_name, keys = "building") { 38 | 39 | fname <- list.files (dir_name, 40 | full.names = TRUE, 41 | recursive = TRUE 42 | ) [1] 43 | 44 | x <- xml2::read_html (fname) 45 | 46 | nodes_sample <- rvest::html_elements (x, "div[class='taglist']") [1:10] 47 | 48 | tables <- rvest::html_elements (x, "table") 49 | tables_r <- rvest::html_table (tables) 50 | index <- which (vapply (tables_r, function (i) { 51 | ret <- FALSE 52 | if ("Key" %in% names (i)) { 53 | ret <- any (keys %in% i$Key) 54 | } 55 | return (ret) 56 | }, logical (1L))) 57 | 58 | tables_sample <- xml2::xml_child (tables, index) 59 | table_body <- xml2::xml_children (tables_sample) 60 | rm_rows <- table_body [10:length (table_body)] 61 | xml2::xml_remove (rm_rows) 62 | 63 | writeLines (c (as.character (nodes_sample), as.character (tables_sample)), fname) 64 | } 65 | 66 | test_that ("available_tags", { 67 | 68 | expect_error (available_tags ("building", 1), "unused argument") 69 | post_process <- !dir.exists ("mock_tags_fail") 70 | expect_error ( 71 | tags <- with_mock_dir ("mock_tags_fail", { 72 | available_tags ("junk") 73 | }), 74 | "feature \\[junk\\] not listed as Key" 75 | ) 76 | if (post_process) { 77 | post_process_tags ("mock_tags_fail") 78 | } 79 | 80 | post_process <- !dir.exists ("mock_tags") 81 | tags <- with_mock_dir ("mock_tags", { 82 | available_tags ("building") 83 | }) 84 | if (post_process) { 85 | post_process_tags ("mock_tags", keys = "building") 86 | } 87 | expect_s3_class (tags, "data.frame") 88 | expect_equal (names (tags), c ("Key", "Value")) 89 | expect_true (all (tags$Key == "building")) 90 | expect_true (nrow (tags) > 1L) 91 | }) 92 | -------------------------------------------------------------------------------- /tests/testthat/test-getbb.R: -------------------------------------------------------------------------------- 1 | test_that ("bbox", { 2 | 3 | expect_error (bbox_to_string (), "bbox must be provided") 4 | # expect_error (bbox_to_string ("a"), "bbox must be numeric") 5 | expect_error (bbox_to_string (1:3), "bbox must contain four elements") 6 | expect_error (bbox_to_string (TRUE), "bbox must be numeric") 7 | expect_message ( 8 | bbox_to_string (1:5), 9 | "only the first four elements of bbox used" 10 | ) 11 | expect_error ( 12 | bbox_to_string (data.frame (a = "type", b = "id")), 13 | "bbox must be a data.frame with osm_type and osm_id columns" 14 | ) 15 | }) 16 | 17 | test_that ("getbb-place_name", { 18 | 19 | res0 <- with_mock_dir ("mock_bb", { 20 | getbb (place_name = "Salzburg") 21 | }) 22 | expect_is (res0, "matrix") 23 | expect_length (res0, 4) 24 | 25 | res1 <- with_mock_dir ("mock_bb_str", { 26 | getbb (place_name = "Salzburg", format_out = "string") 27 | }) 28 | expect_is (res1, "character") 29 | 30 | expect_silent ( 31 | res2 <- with_mock_dir ("mock_bb_state", { 32 | getbb (place_name = "Salzburg", featuretype = "state") 33 | }) 34 | ) 35 | range0 <- apply (res0, 1, function (i) diff (range (i))) 36 | range2 <- apply (res2, 1, function (i) diff (range (i))) 37 | expect_true (all (range2 >= range0)) 38 | 39 | expect_message ( 40 | res0 <- with_mock_dir ("mock_bb", { 41 | getbb (place_name = "Salzburg", silent = FALSE) 42 | }) 43 | ) 44 | expect_silent ( 45 | res4 <- with_mock_dir ("mock_bb_df", { 46 | getbb (place_name = "Salzburg", format_out = "data.frame") 47 | }) 48 | ) 49 | expect_is (res4, "data.frame") 50 | expect_true (nrow (res4) > 1L) 51 | 52 | expect_error ( 53 | res5 <- with_mock_dir ("mock_bb_nope", { 54 | getbb (place_name = "Salzburg", format_out = "no format") 55 | }), 56 | "format_out not recognised" 57 | ) 58 | 59 | expect_silent ( 60 | res6 <- with_mock_dir ("mock_bb_df", { 61 | getbb (place_name = "Salzburg", format_out = "osm_type_id") 62 | }) 63 | ) 64 | expect_is (res6, "character") 65 | expect_length (res6, 1L) 66 | 67 | expect_error ( 68 | with_mock_dir ("mock_bb_typo", { 69 | getbb ("Salzzburg") 70 | }), 71 | "`place_name` 'Salzzburg' can't be found" 72 | ) 73 | }) 74 | 75 | # Note that the polygon calls produce large mock files which are reduced with 76 | # post-processing routines. See `test-features.R` for explanations. 77 | post_process_polygons <- function (dir_name, min_polys = 2) { 78 | 79 | fname <- list.files ( 80 | dir_name, 81 | full.names = TRUE, 82 | recursive = TRUE 83 | ) [1] 84 | j <- jsonlite::fromJSON (fname) 85 | sizes <- vapply ( 86 | j$geotext, 87 | object.size, 88 | numeric (1L), 89 | USE.NAMES = FALSE 90 | ) 91 | # include smallest objects, but ensure at least 2 polygons: 92 | ord <- order (sizes) 93 | n <- 5 94 | while (length (which (j$osm_type [ord [seq (n)]] != "node")) < min_polys) { 95 | n <- n + 1 96 | } 97 | j <- j [ord [seq (n)], ] 98 | jsonlite::write_json (j, path = fname, pretty = TRUE) 99 | } 100 | 101 | test_that ("getbb-polygon", { 102 | 103 | post_process <- !dir.exists ("mock_bb_poly") 104 | res <- with_mock_dir ("mock_bb_poly", { 105 | getbb (place_name = "Salzburg", format_out = "polygon") 106 | }) 107 | if (post_process) { 108 | post_process_polygons ("mock_bb_poly", min_polys = 2L) 109 | } 110 | 111 | expect_is (res, "list") 112 | expect_true (all (lapply (res, nrow) > 2)) 113 | expect_true (all (vapply ( 114 | res, function (i) { 115 | methods::is (i, "matrix") 116 | }, 117 | logical (1) 118 | ))) 119 | 120 | expect_silent (res_str <- bbox_to_string (res [[1]])) 121 | expect_is (res_str, "character") 122 | 123 | post_process <- !dir.exists ("mock_bb_sf") 124 | res <- with_mock_dir ("mock_bb_sf", { 125 | getbb (place_name = "Salzburg", format_out = "sf_polygon") 126 | }) 127 | if (post_process) { 128 | post_process_polygons ("mock_bb_sf", min_polys = 2L) 129 | } 130 | expect_is (res, "sf") 131 | expect_is (res$geometry, "sfc_POLYGON") 132 | expect_true (length (res$geometry) > 1) 133 | expect_true (ncol (res) > 1) 134 | }) 135 | 136 | test_that ("bbox-to-string", { 137 | 138 | bb <- cbind (1:2, 3:4) 139 | expect_is (bbox_to_string (bb), "character") 140 | rownames (bb) <- c ("x", "y") 141 | colnames (bb) <- c ("min", "max") 142 | expect_is (bbox_to_string (bb), "character") 143 | rownames (bb) <- c ("coords.x1", "coords.x2") 144 | colnames (bb) <- c ("min", "max") 145 | expect_is (bbox_to_string (bb), "character") 146 | bb <- 1:4 147 | names (bb) <- c ("left", "bottom", "right", "top") 148 | expect_is (bbox_to_string (bb), "character") 149 | 150 | area <- data.frame (osm_type = "relation", osm_id = "11747082") 151 | expect_is (bbox_to_string (area), "character") 152 | expect_length (bbox_to_string (area), 1) 153 | area <- data.frame ( 154 | osm_type = c ("relation", "relation", "way"), 155 | osm_id = c ("11747082", "307833", "22422490") 156 | ) 157 | expect_is (bbox_to_string (area), "character") 158 | expect_length (bbox_to_string (area), 1) 159 | }) 160 | -------------------------------------------------------------------------------- /tests/testthat/test-sc-osm.R: -------------------------------------------------------------------------------- 1 | # Current names of SC objects as returned by osmdata: 2 | sc_names <- c ( 3 | "nodes", "relation_members", "relation_properties", 4 | "object", "object_link_edge", "edge", "vertex", "meta" 5 | ) 6 | 7 | test_that ("multipolygon", { 8 | q0 <- opq (bbox = c (1, 1, 5, 5)) 9 | x <- osmdata_sc (q0, test_path ("fixtures", "osm-multi.osm")) 10 | # TODO: Write proper tests 11 | expect_is (x, "SC") 12 | expect_equal (names (x), sc_names) 13 | }) 14 | 15 | 16 | test_that ("ways", { 17 | q0 <- opq (bbox = c (1, 1, 5, 5)) 18 | x <- osmdata_sc (q0, test_path ("fixtures", "osm-ways.osm")) 19 | expect_is (x, "SC") 20 | expect_equal (names (x), sc_names) 21 | }) 22 | 23 | 24 | test_that ("non-valid key names", { 25 | osm_multi <- test_path ("fixtures", "osm-multi.osm") 26 | q0 <- opq (bbox = c (1, 1, 5, 5)) 27 | x <- osmdata_sc (q0, osm_multi) 28 | 29 | k<- lapply (x[c ("nodes", "relation_properties", "object")], function (f) { 30 | expect_true ("name:ca" %in% f$key) 31 | }) 32 | }) 33 | 34 | # test_that ("clashes in key names", { 35 | # osm_multi_key_clashes <- test_path ("fixtures", "osm-key_clashes.osm") 36 | # q0 <- opq (bbox = c (1, 1, 5, 5)) 37 | # x <- osmdata_sc (q0, osm_multi_key_clashes) 38 | # 39 | # k <- lapply (x[c ("nodes", "relation_properties", "object")], function (f) { 40 | # expect_false (any ( duplicated (f$key))) 41 | # }) 42 | # }) 43 | -------------------------------------------------------------------------------- /tests/testthat/test-set_bind_key_pre.R: -------------------------------------------------------------------------------- 1 | # NOTE: As of November 2022, these conditions are currently not possible, and 2 | # can only be triggered by direct calls to the internal functions. The bind 3 | # and key_pre parameters may be exposed in add_osm_features() in the future if 4 | # package developers decide the option could be useful. 5 | 6 | test_that ("set_bind_key_pre errors", { 7 | features <- list ("amenity" = "restaurant", "amenity" = "pub") 8 | 9 | expect_error ( 10 | set_bind_key_pre ( 11 | features = features, 12 | bind = rep ("=", 3) 13 | ), 14 | "bind must be length 1 or the same length as features" 15 | ) 16 | 17 | expect_error ( 18 | set_bind_key_pre ( 19 | features = features, 20 | key_pre = rep ("", 3) 21 | ), 22 | "key_pre must be length 1 or the same length as features" 23 | ) 24 | 25 | expect_error ( 26 | set_bind_key_pre (key_pre = "-"), 27 | 'key_pre must only include "" or "~"' 28 | ) 29 | 30 | expect_error ( 31 | set_bind_key_pre (bind = "-"), 32 | 'bind must only include "=", "!=", "~", or "!~"' 33 | ) 34 | }) 35 | -------------------------------------------------------------------------------- /tests/testthat/test-sp-osm.R: -------------------------------------------------------------------------------- 1 | test_that ("multipolygon", { 2 | osm_multi <- test_path ("fixtures", "osm-multi.osm") 3 | x_sf <- sf::st_read (osm_multi, layer = "multipolygons", quiet = TRUE) 4 | x_sp <- as (x_sf, "Spatial") 5 | q0 <- opq (bbox = c (1, 1, 5, 5)) 6 | x <- osmdata_sp (q0, osm_multi)$osm_multipolygons 7 | # GDAL spits out a whole lot of generic field names, so first the 8 | # two have to be reduced to common fields. 9 | x <- x [, which (names (x) %in% names (x_sp))] 10 | x_sp <- x_sp [, which (names (x_sp) %in% names (x))] 11 | # Then all of the object and dimnames inserted by `osmdata` have 12 | # to be removed 13 | rownames (slot (x, "data")) <- rownames (slot (x_sp, "data")) 14 | # crs arguments for x_sp include "+ellps=WGS84", while the 15 | # corresponding value for x (the osmdata version) is 16 | # "+datum=WGS84". 17 | slot (x, "proj4string") <- slot (x_sp, "proj4string") 18 | # Then, as for sf, all of the object and dimnames inserted by 19 | # `osmdata` have to be removed 20 | names (slot (x, "polygons")) <- NULL 21 | names (slot (slot (x, "polygons") [[1]], "Polygons")) <- NULL 22 | np <- length (slot (slot (x, "polygons") [[1]], "Polygons")) 23 | for (i in seq (np)) { 24 | rownames (slot (slot ( 25 | slot (x, "polygons") [[1]], 26 | "Polygons" 27 | ) [[i]], "coords")) <- NULL 28 | colnames (slot (slot ( 29 | slot (x, "polygons") [[1]], 30 | "Polygons" 31 | ) [[i]], "coords")) <- NULL 32 | dimnames (slot (slot ( 33 | slot (x, "polygons") [[1]], 34 | "Polygons" 35 | ) [[i]], "coords")) <- NULL 36 | } 37 | # sp arbitrarily re-sorts the coordinates, so the following 38 | # always fails: 39 | for (i in seq (np)) { 40 | pi <- slot (slot (x, "polygons") [[1]], "Polygons") [[i]] 41 | pi_sp <- slot ( 42 | slot (x_sp, "polygons") [[1]], 43 | "Polygons" 44 | ) [[i]] 45 | xyi <- slot (pi, "coords") 46 | xyi_sp <- slot (pi_sp, "coords") 47 | # expect_identical (xyi, xyi_sp) 48 | expect_identical (attributes (xyi), attributes (xyi_sp)) 49 | } 50 | 51 | # sp also inserts row.names in the "data" slot of type integer 52 | # instead of char, so those slots can't be compared either 53 | # ... sp tests are not continued any further, and these tests 54 | # really just exist to cover the relevant lines of code. 55 | }) 56 | 57 | 58 | test_that ("multilinestring", { 59 | osm_multi <- test_path ("fixtures", "osm-multi.osm") 60 | x_sf <- sf::st_read (osm_multi, layer = "multilinestrings", quiet = TRUE) 61 | x_sp <- as (x_sf, "Spatial") 62 | q0 <- opq (bbox = c (1, 1, 5, 5)) 63 | x <- osmdata_sp (q0, osm_multi)$osm_multilines 64 | x <- x [, which (names (x) %in% names (x_sp))] 65 | x_sp <- x_sp [, which (names (x_sp) %in% names (x))] 66 | rownames (slot (x, "data")) <- rownames (slot (x_sp, "data")) 67 | slot (x, "proj4string") <- slot (x_sp, "proj4string") 68 | names (slot (x, "lines")) <- NULL 69 | names (slot (slot (x, "lines") [[1]], "Lines")) <- NULL 70 | np <- length (slot (slot (x, "lines") [[1]], "Lines")) 71 | for (i in seq (np)) { 72 | rownames (slot (slot ( 73 | slot (x, "lines") [[1]], 74 | "Lines" 75 | ) [[i]], "coords")) <- NULL 76 | colnames (slot (slot ( 77 | slot (x, "lines") [[1]], 78 | "Lines" 79 | ) [[i]], "coords")) <- NULL 80 | dimnames (slot (slot ( 81 | slot (x, "lines") [[1]], 82 | "Lines" 83 | ) [[i]], "coords")) <- NULL 84 | } 85 | for (i in seq (np)) { 86 | pi <- slot (slot (x, "lines") [[1]], "Lines") [[i]] 87 | pi_sp <- slot (slot (x_sp, "lines") [[1]], "Lines") [[i]] 88 | xyi <- slot (pi, "coords") 89 | xyi_sp <- slot (pi_sp, "coords") 90 | expect_identical (attributes (xyi), attributes (xyi_sp)) 91 | } 92 | }) 93 | 94 | test_that ("ways", { 95 | osm_ways <- test_path ("fixtures", "osm-ways.osm") 96 | x_sf <- sf::st_read (osm_ways, layer = "lines", quiet = TRUE) 97 | x_sp <- as (x_sf, "Spatial") 98 | q0 <- opq (bbox = c (1, 1, 5, 5)) 99 | x <- osmdata_sp (q0, osm_ways)$osm_lines 100 | x <- x [, which (names (x) %in% names (x_sp))] 101 | x_sp <- x_sp [, which (names (x_sp) %in% names (x))] 102 | np <- length (slot (slot (x, "lines") [[1]], "Lines")) 103 | for (i in seq (np)) { 104 | rownames (slot (slot ( 105 | slot (x, "lines") [[1]], 106 | "Lines" 107 | ) [[i]], "coords")) <- NULL 108 | colnames (slot (slot ( 109 | slot (x, "lines") [[1]], 110 | "Lines" 111 | ) [[i]], "coords")) <- NULL 112 | dimnames (slot (slot ( 113 | slot (x, "lines") [[1]], 114 | "Lines" 115 | ) [[i]], "coords")) <- NULL 116 | } 117 | for (i in seq (np)) { 118 | pi <- slot (slot (x, "lines") [[1]], "Lines") [[i]] 119 | pi_sp <- slot (slot (x_sp, "lines") [[1]], "Lines") [[i]] 120 | xyi <- slot (pi, "coords") 121 | xyi_sp <- slot (pi_sp, "coords") 122 | expect_identical (attributes (xyi), attributes (xyi_sp)) 123 | } 124 | }) 125 | 126 | test_that ("non-valid key names", { 127 | osm_multi <- test_path ("fixtures", "osm-multi.osm") 128 | q0 <- opq (bbox = c (1, 1, 5, 5)) 129 | x <- osmdata_sp (q0, osm_multi) 130 | 131 | k <- lapply (x[grep ("osm_", names (x))], function (f) { 132 | expect_true("name:ca" %in% names(f)) 133 | }) 134 | }) 135 | 136 | test_that ("clashes in key names", { 137 | osm_multi_key_clashes <- test_path ("fixtures", "osm-key_clashes.osm") 138 | q0 <- opq (bbox = c (1, 1, 5, 5)) 139 | expect_warning( 140 | x <- osmdata_sp (q0, osm_multi_key_clashes), 141 | "Feature keys clash with id or metadata columns and will be renamed by " 142 | ) 143 | 144 | expect_false (any (duplicated (names (x$osm_points)))) 145 | # x$osm_points don't have osm_id column in tags TODO? 146 | k <- lapply (x[grep ("osm_", names (x))[-1]], function (f) { 147 | expect_false (any (duplicated (names (f)))) 148 | expect_true (all (c ("osm_id", "osm_id.1") %in% names (f))) 149 | }) 150 | }) 151 | -------------------------------------------------------------------------------- /tests/testthat/test-trim.R: -------------------------------------------------------------------------------- 1 | context ("trim-osm-data") 2 | 3 | skip_on_os ("mac") 4 | skip_on_os ("windows") 5 | 6 | test_that ("trim_osm_data", { 7 | osm_multi <- test_path ("fixtures", "osm-multi.osm") 8 | q0 <- opq (bbox = c (1, 1, 5, 5)) 9 | x0 <- osmdata_sf (q0, osm_multi) 10 | bb <- cbind (c (2, 3), c (2, 3)) 11 | require (sf) 12 | expect_error ( 13 | trim_osmdata (1, bb_poly = bb), 14 | "unrecognised format: numeric" 15 | ) 16 | expect_silent (x1 <- trim_osmdata (x0, bb_poly = bb)) 17 | expect_equal (nrow (x1$osm_points), 0) 18 | expect_equal (nrow (x1$osm_lines), 0) 19 | expect_equal (nrow (x1$osm_polygons), 0) 20 | expect_equal (nrow (x1$osm_multilines), 0) 21 | expect_equal (nrow (x1$osm_multipolygons), 0) 22 | 23 | expect_silent (x1 <- trim_osmdata (x0, 24 | bb_poly = bb, 25 | exclude = FALSE 26 | )) 27 | expect_equal (nrow (x1$osm_points), 2) 28 | expect_equal (nrow (x1$osm_lines), 1) 29 | expect_equal (nrow (x1$osm_polygons), 1) 30 | expect_equal (nrow (x1$osm_multilines), 0) 31 | expect_equal (nrow (x1$osm_multipolygons), 1) 32 | 33 | expect_true (nrow (x1$osm_points) < nrow (x0$osm_points)) 34 | expect_true (nrow (x1$osm_lines) < nrow (x0$osm_lines)) 35 | expect_true (nrow (x1$osm_polygons) == nrow (x0$osm_polygons)) 36 | expect_true (nrow (x1$osm_multilines) < nrow (x0$osm_multilines)) 37 | expect_true (nrow (x1$osm_multipolygons) == 38 | nrow (x0$osm_multipolygons)) 39 | 40 | expect_silent (x0_sc <- osmdata_sc (q0, osm_multi)) 41 | expect_silent (x1 <- trim_osmdata (x0_sc, bb_poly = bb)) 42 | expect_equal (nrow (x1$object), 0) 43 | expect_equal (nrow (x1$object_link_edge), 0) 44 | expect_equal (nrow (x1$edge), 0) 45 | expect_equal (nrow (x1$vertex), 0) 46 | 47 | bb <- list ( 48 | rbind ( 49 | c (0, 0), 50 | c (0, 1), 51 | c (1, 1), 52 | c (1, 0), 53 | c (0, 0) 54 | ), 55 | rbind ( 56 | c (2, 3), 57 | c (2, 4), 58 | c (3, 4), 59 | c (3, 3), 60 | c (2, 3) 61 | ) 62 | ) 63 | 64 | expect_message ( 65 | x1 <- trim_osmdata (x0, bb_poly = bb), 66 | "bb_poly has more than one polygon" 67 | ) 68 | }) 69 | 70 | test_that ("bb_poly as sf/sc", { 71 | q0 <- opq (bbox = c (1, 1, 5, 5)) 72 | x0 <- osmdata_sf (q0, test_path ("fixtures", "osm-multi.osm")) 73 | bb <- rbind ( 74 | c (2, 2), 75 | c (2, 3), 76 | c (3, 3), 77 | c (3, 2), 78 | c (2, 2) 79 | ) 80 | x1 <- trim_osmdata (x0, bb, exclude = FALSE) 81 | 82 | bb_sf <- sf::st_polygon (list (bb)) %>% 83 | st_sfc () %>% 84 | st_sf () 85 | expect_silent (x2 <- trim_osmdata (x0, 86 | bb_poly = bb_sf, 87 | exclude = FALSE 88 | )) 89 | expect_identical (x1, x2) 90 | 91 | bb_sp <- as (bb_sf, "Spatial") 92 | expect_silent (x3 <- trim_osmdata (x0, 93 | bb_poly = bb_sp, 94 | exclude = FALSE 95 | )) 96 | expect_identical (x1, x3) 97 | }) 98 | -------------------------------------------------------------------------------- /tests/testthat/test-unique.R: -------------------------------------------------------------------------------- 1 | context ("unique-osm-data") 2 | 3 | require (sf) 4 | 5 | test_that ("unique sf", { 6 | q0 <- opq (bbox = c (1, 1, 5, 5)) 7 | x0 <- osmdata_sf (q0, test_path ("fixtures", "osm-multi.osm")) 8 | x1 <- unique_osmdata (x0) 9 | expect_true (!identical (x0, x1)) 10 | expect_true (nrow (x0$osm_points) > nrow (x1$osm_points)) 11 | # trim converts the polygon to a linestring, but for the ways, 12 | # all objects extend through the trim bb_poly and out, so nothing 13 | # is trimmed. 14 | 15 | x0 <- osmdata_sf (q0, test_path ("fixtures", "osm-ways.osm")) 16 | x1 <- unique_osmdata (x0) 17 | expect_true (!identical (x0, x1)) 18 | expect_true (nrow (x0$osm_points) > nrow (x1$osm_points)) 19 | }) 20 | 21 | test_that ("unique sp", { 22 | q0 <- opq (bbox = c (1, 1, 5, 5)) 23 | x0 <- osmdata_sp (q0, test_path ("fixtures", "osm-multi.osm")) 24 | x1 <- unique_osmdata (x0) 25 | expect_true (!identical (x0, x1)) 26 | expect_true (nrow (x0$osm_points) > nrow (x1$osm_points)) 27 | # trim converts the polygon to a linestring, but for the ways, 28 | # all objects extend through the trim bb_poly and out, so nothing 29 | # is trimmed. 30 | 31 | x0 <- osmdata_sp (q0, test_path ("fixtures", "osm-ways.osm")) 32 | # x1 <- unique_osmdata (x0) 33 | # expect_true (!identical (x0, x1)) 34 | # expect_true (nrow (x0$osm_points) > nrow (x1$osm_points)) 35 | }) 36 | -------------------------------------------------------------------------------- /tests/testthat/test-unname.R: -------------------------------------------------------------------------------- 1 | context ("unname-osmdata-sf") 2 | 3 | test_all <- (identical (Sys.getenv ("MPADGE_LOCAL", "false"), "true") || 4 | identical (Sys.getenv ("GITHUB_WORKFLOW", "nope"), "test-coverage")) 5 | skip_if (!test_all) 6 | 7 | has_internet <- curl::has_internet () 8 | skip_if (!has_internet) 9 | 10 | require (sf) 11 | 12 | test_that ("unname", { 13 | 14 | qry <- opq (bbox = c (-0.116, 51.516, -0.115, 51.517)) 15 | qry <- add_osm_feature (qry, key = "highway") 16 | 17 | res <- with_mock_dir ("mock_unname", { 18 | osmdata_sf (qry) 19 | }) 20 | 21 | expect_true (all (nzchar (rownames (res$osm_points)))) 22 | m_l <- as.matrix (res$osm_lines$geometry [[1]]) 23 | expect_false (is.null (rownames (m_l))) 24 | expect_true (length (nchar (rownames (m_l))) > 0L) 25 | m_p <- as.matrix (res$osm_polygons$geometry [[1]]) 26 | expect_true (!is.null (rownames (m_p))) 27 | expect_true (length (nchar (rownames (m_p))) > 0L) 28 | 29 | res_u <- unname_osmdata_sf (res) 30 | expect_true (all (nzchar (rownames (res_u$osm_points)))) 31 | m_l <- as.matrix (res_u$osm_lines$geometry [[1]]) 32 | expect_true (is.null (rownames (m_l))) 33 | expect_false (length (nchar (rownames (m_l))) > 0L) 34 | m_p <- as.matrix (res_u$osm_polygons$geometry [[1]]) 35 | expect_true (is.null (rownames (m_p))) 36 | expect_false (length (nchar (rownames (m_p))) > 0L) 37 | }) 38 | -------------------------------------------------------------------------------- /tests/timing-benchmark.R: -------------------------------------------------------------------------------- 1 | #library (osmdata) 2 | 3 | benchmark <- function (times = 100) { 4 | 5 | devtools::load_all (".", export_all = FALSE) 6 | q0 <- opq (bbox = c(-0.27, 51.47, -0.20, 51.50)) 7 | q1 <- add_osm_feature (q0, key = "name", value = "Thames") 8 | # contains both multipolygons and multilinestrings 9 | doc <- osmdata_xml (q1, "export.osm") 10 | 11 | objs <- c ("points", "lines", "multilinestrings", "multipolygons", 12 | "other_relations") 13 | mt_sf <- size_sf <- NULL 14 | for (i in seq (objs)) { 15 | mb <- microbenchmark::microbenchmark ( 16 | dat <- sf::st_read ("export.osm", layer = objs [i], quiet = TRUE), 17 | times = times) 18 | size_sf <- c (size_sf, object.size (dat)) 19 | mt_sf <- c (mt_sf, median (mb$time)) 20 | cat ("\r", i, " / ", length (objs)) 21 | } 22 | mt_sf <- mt_sf / 1e6 # nano-seconds to milli-seconds 23 | cat ("\rSF: Median times (in ms) for (", paste (objs), "):\n") 24 | cat ("\t(", mt_sf, "); total = ", sum (mt_sf), "\n") 25 | 26 | mb <- microbenchmark::microbenchmark (x <- osmdata_sf (q1, doc), 27 | times = times) 28 | #mb <- microbenchmark::microbenchmark ( x <- osmdata_sf (q1, "export.osm"), 29 | # times = 10L) 30 | mt <- median (mb$time / 1e6) 31 | cat ("osmdata: Median time = ", mt, " ms\n") 32 | size_od <- object.size (x) 33 | 34 | cat ("\nosmdata took ", mt / sum (mt_sf), " times longer to extract ", 35 | size_od / sum (size_sf), " times as much data\n") 36 | } 37 | -------------------------------------------------------------------------------- /tests/valgrind-test.R: -------------------------------------------------------------------------------- 1 | vg_check <- function () { 2 | vg <- system2 (command = "R", 3 | args = c ('-d "valgrind --tool=memcheck --leak-check=full"', # nolint 4 | '-f valgrind-script.R'), # nolint 5 | stdout = TRUE, stderr = TRUE) 6 | 7 | lost <- NULL 8 | types <- c ("definitely lost", "indirectly lost", "possibly lost") 9 | for (ty in types) { 10 | lost_type <- which (grepl (ty, vg)) 11 | n <- regmatches (vg [lost_type], 12 | gregexpr ("[[:digit:]]+", vg [lost_type])) 13 | lost <- c (lost, as.numeric (n [[1]] [2:3])) 14 | } 15 | if (any (lost > 0)) 16 | stop ("valgrind memory leaks detected!") 17 | 18 | return (TRUE) 19 | } 20 | -------------------------------------------------------------------------------- /vignettes/makefile: -------------------------------------------------------------------------------- 1 | LFILE = query-split 2 | 3 | all: knith open 4 | 5 | knith: $(LFILE).Rmd 6 | echo "rmarkdown::render('$(LFILE).Rmd',output_file='$(LFILE).html')" | R --no-save -q 7 | 8 | knitr: $(LFILE).Rmd 9 | echo "rmarkdown::render('$(LFILE).Rmd',rmarkdown::md_document(variant='markdown_github'))" | R --no-save -q 10 | 11 | open: $(LFILE).html 12 | xdg-open $(LFILE).html & 13 | 14 | clean: 15 | rm -rf *.html *.png 16 | -------------------------------------------------------------------------------- /vignettes/osmdata-refs.bib: -------------------------------------------------------------------------------- 1 | @incollection{olbricht2015data, 2 | title={Data Retrieval for Small Spatial Regions in OpenStreetMap}, 3 | author={Olbricht, Roland M}, 4 | booktitle={OpenStreetMap in GIScience}, 5 | pages={101--122}, 6 | year={2015}, 7 | publisher={Springer} 8 | } 9 | @incollection{mashhadi2015impact, 10 | title={The Impact of Society on Volunteered Geographic Information: The Case of OpenStreetMap}, 11 | author={Mashhadi, Afra and Quattrone, Giovanni and Capra, Licia}, 12 | booktitle={OpenStreetMap in GIScience}, 13 | pages={125--141}, 14 | year={2015}, 15 | publisher={Springer} 16 | } 17 | @article{neis2012analyzing, 18 | title={Analyzing the contributor activity of a volunteered geographic information project—The case of OpenStreetMap}, 19 | author={Neis, Pascal and Zipf, Alexander}, 20 | journal={ISPRS International Journal of Geo-Information}, 21 | volume={1}, 22 | number={2}, 23 | pages={146--165}, 24 | year={2012}, 25 | publisher={Molecular Diversity Preservation International} 26 | } 27 | @misc{OpenStreetMap, 28 | author = {{OpenStreetMap contributors}}, 29 | title = {{Planet dump retrieved from https://planet.osm.org }}, 30 | howpublished = "\url{https://www.openstreetmap.org}", 31 | year = {2017}, 32 | } 33 | 34 | @article{eugster_osmar:_2012, 35 | title = {Osmar: {{OpenStreetMap}} and {{R}}}, 36 | volume = {5}, 37 | issn = {20734859}, 38 | abstract = {OpenStreetMap provides freely accessible and editable geographic data. The osmar package smoothly integrates the OpenStreetMap project into the R ecosystem. The osmar package provides infrastructure to access OpenStreetMap data from different sources, to enable working with the OSM data in the familiar R idiom, and to convert the data into objects based on classes provided by existing R packages. This paper explains the package’s concept and shows how to use it. As an application we present a simple navigation device.}, 39 | timestamp = {2016-10-20T14:39:46Z}, 40 | number = {1}, 41 | journaltitle = {The R Journal}, 42 | author = {a Eugster, Manuel J and Schlesinger, Thomas}, 43 | date = {2012}, 44 | pages = {53--64} 45 | } 46 | 47 | @article{lovelace_harnessing_2014, 48 | title = {Harnessing Open Street Map Data with {{R}} and {{QGIS}}}, 49 | timestamp = {2017-02-26T22:16:22Z}, 50 | journaltitle = {EloGeo}, 51 | shortjournal = {EloGeo}, 52 | author = {Lovelace, Robin}, 53 | date = {2014} 54 | } 55 | 56 | @Manual{osmplotr, 57 | title = {osmplotr: Customisable Images of OpenStreetMap Data}, 58 | author = {Mark Padgham}, 59 | year = {2016}, 60 | note = {R package version 0.2.3}, 61 | url = {https://cran.r-project.org/package=osmplotr}, 62 | } 63 | 64 | @article{johnson_models_2017, 65 | title = {Models of direct editing of government spatial data: challenges and constraints to the acceptance of contributed data}, 66 | volume = {44}, 67 | issn = {1523-0406}, 68 | url = {https://dx.doi.org/10.1080/15230406.2016.1176536}, 69 | doi = {10.1080/15230406.2016.1176536}, 70 | number = {2}, 71 | journal = {Cartography and Geographic Information Science}, 72 | author = {Johnson, Peter A.}, 73 | month = mar, 74 | year = {2017}, 75 | pages = {128--138} 76 | } 77 | --------------------------------------------------------------------------------