[
  {
    "path": ".Rbuildignore",
    "content": ".travis.yml\nPROPOSAL.md\nconfig.log\nconfig.status\nTODO\n^windows\n^appveyor\\.yml$\n^.*\\.Rproj$\n^\\.Rproj\\.user$\nblog\nREADME.md\nCONDUCT.md\nrdev\n^codecov\\.yml$\nhub\ntic.R\nNOTES\n^\\.ccache$\n^\\.github$\n^tic\\.R$\nvignettes.awk\n^\\.gitattributes$\n_pkgdown.yml\ndocs\npkgdown\nchanges0.txt\nchanges1.txt\nchanges2.txt\nchanges3.txt\nchanges.txt\naware.patch\n"
  },
  {
    "path": ".gitattributes",
    "content": "* text=auto\ndata/* binary\nsrc/* text=lf\nR/* text=lf\n\n# Force the following filetypes to have unix eols, so Windows does not break them\nconfigure.ac text eol=lf\n"
  },
  {
    "path": ".github/.gitignore",
    "content": "*.html\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Standard bug report template\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nIt is easier for developers to help if they can reproduce the problem.   \nCould you please provide a minimal reproducible example?\n\n**If reporting a change from previous versions**\n\nPlease read https://cran.r-project.org/web/packages/sf/news/news.html first.\n\n**Additional context**\nAdd any other context about the problem here.\n\n<details>\nPaste the output of your `sessionInfo()` and `sf::sf_extSoftVersion()`\n</details>\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/other_issue.md",
    "content": "---\nname: Other issue\nabout: Blank template for other issue types\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n\n"
  },
  {
    "path": ".github/workflows/R-CMD-check.yaml",
    "content": "# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples\n# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help\non:\n  push:\n    branches: [main, master]\n  pull_request:\n    branches: [main, master]\n  schedule:\n    - cron: \"0 4 * * *\"\n\nname: R-CMD-check\n\njobs:\n  R-CMD-check:\n    runs-on: ${{ matrix.config.os }}\n\n    name: ${{ matrix.config.os }} (${{ matrix.config.r }})\n\n    strategy:\n      fail-fast: false\n      matrix:\n        config:\n          - {os: macos-latest,   r: 'release'}\n          - {os: windows-latest, r: 'release'}\n          - {os: ubuntu-latest,   r: 'devel', http-user-agent: 'release'}\n          - {os: ubuntu-latest,   r: 'release'}\n          - {os: ubuntu-latest,   r: 'oldrel-1'}\n          - {os: ubuntu-latest,   r: 'oldrel-2'}\n\n    env:\n      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}\n      R_KEEP_PKG_SOURCE: yes\n\n    steps:\n      - uses: actions/checkout@v6\n\n      - uses: r-lib/actions/setup-pandoc@v2\n\n      - uses: r-lib/actions/setup-r@v2\n        with:\n          r-version: ${{ matrix.config.r }}\n          http-user-agent: ${{ matrix.config.http-user-agent }}\n          use-public-rspm: true\n\n      - name: Install macOS system dependencies\n        if: runner.os == 'macos'\n        run: brew install gdal proj\n\n      - uses: r-lib/actions/setup-r-dependencies@v2\n        with:\n          extra-packages: any::rcmdcheck\n          needs: check\n\n      - uses: r-lib/actions/check-r-package@v2\n        with:\n          upload-snapshots: true\n"
  },
  {
    "path": ".github/workflows/pkgdown.yaml",
    "content": "# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples\n# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help\non:\n  push:\n    branches: [main, master]\n  pull_request:\n    branches: [main, master]\n  release:\n    types: [published]\n  workflow_dispatch:\n\nname: pkgdown\n\npermissions: read-all\n\njobs:\n  pkgdown:\n    runs-on: ubuntu-latest\n    # Only restrict concurrency for non-PR jobs\n    concurrency:\n      group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }}\n    env:\n      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}\n    permissions:\n      contents: write\n    steps:\n      - uses: actions/checkout@v6\n\n      - uses: r-lib/actions/setup-pandoc@v2\n\n      - uses: r-lib/actions/setup-r@v2\n        with:\n          use-public-rspm: true\n\n      - uses: r-lib/actions/setup-r-dependencies@v2\n        with:\n          extra-packages: any::pkgdown, local::.\n          needs: website\n\n      - name: Build site\n        run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE)\n        shell: Rscript {0}\n\n      - name: Deploy to GitHub pages 🚀\n        if: github.event_name != 'pull_request'\n        uses: JamesIves/github-pages-deploy-action@v4.8.0\n        with:\n          clean: false\n          branch: gh-pages\n          folder: docs\n"
  },
  {
    "path": ".github/workflows/rhub.yaml",
    "content": "# R-hub's generic GitHub Actions workflow file. It's canonical location is at\n# https://github.com/r-hub/actions/blob/v1/workflows/rhub.yaml\n# You can update this file to a newer version using the rhub2 package:\n#\n# rhub::rhub_setup()\n#\n# It is unlikely that you need to modify this file manually.\n\nname: R-hub\nrun-name: \"${{ github.event.inputs.id }}: ${{ github.event.inputs.name || format('Manually run by {0}', github.triggering_actor) }}\"\n\non:\n  workflow_dispatch:\n    inputs:\n      config:\n        description: 'A comma separated list of R-hub platforms to use.'\n        type: string\n        default: 'linux,windows,macos'\n      name:\n        description: 'Run name. You can leave this empty now.'\n        type: string\n      id:\n        description: 'Unique ID. You can leave this empty now.'\n        type: string\n\njobs:\n\n  setup:\n    runs-on: ubuntu-latest\n    outputs:\n      containers: ${{ steps.rhub-setup.outputs.containers }}\n      platforms: ${{ steps.rhub-setup.outputs.platforms }}\n\n    steps:\n    # NO NEED TO CHECKOUT HERE\n    - uses: r-hub/actions/setup@v1\n      with:\n        config: ${{ github.event.inputs.config }}\n      id: rhub-setup\n\n  linux-containers:\n    needs: setup\n    if: ${{ needs.setup.outputs.containers != '[]' }}\n    runs-on: ubuntu-latest\n    name: ${{ matrix.config.label }}\n    strategy:\n      fail-fast: false\n      matrix:\n        config: ${{ fromJson(needs.setup.outputs.containers) }}\n    container:\n      image: ${{ matrix.config.container }}\n\n    steps:\n      - uses: r-hub/actions/checkout@v1\n      - uses: r-hub/actions/platform-info@v1\n        with:\n          token: ${{ secrets.RHUB_TOKEN }}\n          job-config: ${{ matrix.config.job-config }}\n      - uses: r-hub/actions/setup-deps@v1\n        with:\n          token: ${{ secrets.RHUB_TOKEN }}\n          job-config: ${{ matrix.config.job-config }}\n      - uses: r-hub/actions/run-check@v1\n        with:\n          token: ${{ secrets.RHUB_TOKEN }}\n          job-config: ${{ matrix.config.job-config }}\n\n  other-platforms:\n    needs: setup\n    if: ${{ needs.setup.outputs.platforms != '[]' }}\n    runs-on: ${{ matrix.config.os }}\n    name: ${{ matrix.config.label }}\n    strategy:\n      fail-fast: false\n      matrix:\n        config: ${{ fromJson(needs.setup.outputs.platforms) }}\n\n    steps:\n      - uses: r-hub/actions/checkout@v1\n      - uses: r-hub/actions/setup-r@v1\n        with:\n          job-config: ${{ matrix.config.job-config }}\n          token: ${{ secrets.RHUB_TOKEN }}\n      - uses: r-hub/actions/platform-info@v1\n        with:\n          token: ${{ secrets.RHUB_TOKEN }}\n          job-config: ${{ matrix.config.job-config }}\n      - uses: r-hub/actions/setup-deps@v1\n        with:\n          job-config: ${{ matrix.config.job-config }}\n          token: ${{ secrets.RHUB_TOKEN }}\n      - uses: r-hub/actions/run-check@v1\n        with:\n          job-config: ${{ matrix.config.job-config }}\n          token: ${{ secrets.RHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/test-coverage.yaml",
    "content": "# Workflow derived from https://github.com/r-lib/actions/tree/v2/examples\n# Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help\non:\n  push:\n    branches: [main, master]\n  pull_request:\n    branches: [main, master]\n\nname: test-coverage\n\njobs:\n  test-coverage:\n    runs-on: ubuntu-latest\n    env:\n      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: r-lib/actions/setup-r@v2\n        with:\n          use-public-rspm: true\n\n      - uses: r-lib/actions/setup-r-dependencies@v2\n        with:\n          extra-packages: any::covr\n          needs: coverage\n\n      - name: Test coverage\n        run: |\n          covr::codecov(\n            quiet = FALSE,\n            clean = FALSE,\n            install_path = file.path(normalizePath(Sys.getenv(\"RUNNER_TEMP\"), winslash = \"/\"), \"package\")\n          )\n        shell: Rscript {0}\n\n      - name: Show testthat output\n        if: always()\n        run: |\n          ## --------------------------------------------------------------------\n          find ${{ runner.temp }}/package -name 'testthat.Rout*' -exec cat '{}' \\; || true\n        shell: bash\n\n      - name: Upload test results\n        if: failure()\n        uses: actions/upload-artifact@v4\n        with:\n          name: coverage-test-failures\n          path: ${{ runner.temp }}/package\n"
  },
  {
    "path": ".github/workflows/tic-db.yml",
    "content": "## tic GitHub Actions template: linux\n## revision date: 2021-06-27\n# [Custom header]\non:\n  workflow_dispatch:\n  push:\n    branches:\n      - main\n  pull_request:\n  # for now, CRON jobs only run on the default branch of the repo (i.e. usually on master)\n  schedule:\n    # * is a special character in YAML so you have to quote this string\n    - cron: \"0 4 * * *\"\n\nname: tic-db\n\njobs:\n  all:\n    runs-on: ${{ matrix.config.os }}\n\n    name: ${{ matrix.config.os }} (${{ matrix.config.r }})\n\n    strategy:\n      fail-fast: false\n      matrix:\n        config:\n          # use a different tic template type if you do not want to build on all listed platforms\n          - { os: ubuntu-latest, r: \"release\" }\n\n    services:\n      postgres:\n        image: kartoza/postgis\n        ports:\n        - 5432:5432\n\n    env:\n      # otherwise remotes::fun() errors cause the build to fail. Example: Unavailability of binaries\n      R_REMOTES_NO_ERRORS_FROM_WARNINGS: true\n      CRAN: ${{ matrix.config.cran }}\n      # make sure to run `tic::use_ghactions_deploy()` to set up deployment\n      TIC_DEPLOY_KEY: ${{ secrets.TIC_DEPLOY_KEY }}\n      # prevent rgl issues because no X11 display is available\n      RGL_USE_NULL: true\n      # if you use bookdown or blogdown, replace \"PKGDOWN\" by the respective\n      # capitalized term. This also might need to be done in tic.R\n      BUILD_PKGDOWN: ${{ matrix.config.pkgdown }}\n      # macOS >= 10.15.4 linking\n      SDKROOT: /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk\n      # use GITHUB_TOKEN from GitHub to workaround rate limits in {remotes}\n      GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }}\n\n    steps:\n      - uses: actions/checkout@v4\n\n      - uses: r-lib/actions/setup-r@v2\n        with:\n          r-version: ${{ matrix.config.r }}\n          Ncpus: 4\n\n      # LaTeX. Installation time:\n      # Linux: ~ 1 min\n      # macOS: ~ 1 min 30s\n      # Windows: never finishes\n      - uses: r-lib/actions/setup-tinytex@v2\n        if: matrix.config.latex == 'true'\n\n      - uses: r-lib/actions/setup-pandoc@v2\n\n      # set date/week for use in cache creation\n      # https://github.community/t5/GitHub-Actions/How-to-set-and-access-a-Workflow-variable/m-p/42970\n      # - cache R packages daily\n#     - name: \"[Cache] Prepare daily timestamp for cache\"\n#       if: runner.os != 'Windows'\n#       id: date\n#       run: echo \"::set-output name=date::$(date '+%d-%m')\"\n\n#     - name: \"[Cache] Cache R packages\"\n#       if: runner.os != 'Windows'\n#       uses: pat-s/always-upload-cache@v2\n#       with:\n#         path: ${{ env.R_LIBS_USER }}\n#         key: ${{ runner.os }}-r-${{ matrix.config.r }}-${{steps.date.outputs.date}}\n#         restore-keys: ${{ runner.os }}-r-${{ matrix.config.r }}-${{steps.date.outputs.date}}\n\n      - name: \"[Stage] [Linux] Install required system libs\"\n        if: runner.os == 'Linux'\n        run: sudo apt install libcurl4-openssl-dev libgit2-dev\n\n      # for some strange Windows reason this step and the next one need to be decoupled\n      - name: \"[Stage] Prepare\"\n        run: |\n          Rscript -e \"if (!requireNamespace('remotes')) install.packages('remotes', type = 'source')\"\n          Rscript -e \"if (getRversion() < '3.2' && !requireNamespace('curl')) install.packages('curl', type = 'source')\"\n\n      - name: \"[Custom block] [Linux] Install spatial libraries\"\n        if: runner.os == 'Linux'\n        run: sudo apt-get install libgdal-dev libproj-dev libgeos-dev libudunits2-dev\n\n      - name: \"[Custom block] [macOS] Install spatial libraries\"\n        if: runner.os == 'macOS'\n        run: |\n          # conflicts with gfortran from r-lib/actions when linking gcc\n          rm '/usr/local/bin/gfortran'\n          brew install pkg-config gdal proj geos\n\n      - name: \"[Stage] [macOS] Install libgit2\"\n        if: runner.os == 'macOS'\n        run: brew install libgit2\n\n      - name: \"[Stage] [macOS] Install system libs for pkgdown\"\n        if: runner.os == 'macOS' && matrix.config.pkgdown != ''\n        run: brew install harfbuzz fribidi\n\n      - name: \"[Stage] [Linux] Install system libs for pkgdown\"\n        if: runner.os == 'Linux' && matrix.config.pkgdown != ''\n        run: sudo apt install libharfbuzz-dev libfribidi-dev\n\n      # Try to automatically check for system dependencies and install them\n      # Note: this might not catch all required system libs and manual action might be needed\n      - name: \"[Stage] [Linux] Install linux system dependencies\"\n        if: runner.os == 'Linux'\n        run: |\n          while read -r cmd\n          do\n            eval sudo $cmd\n          done < <(Rscript -e 'writeLines(remotes::system_requirements(\"ubuntu\", \"20.04\"))')\n\n      - name: \"[Stage] Install\"\n        if: matrix.config.os != 'macOS-latest' || matrix.config.r != 'devel'\n        run: Rscript -e \"remotes::install_github('ropensci/tic')\" -e \"print(tic::dsl_load())\" -e \"tic::prepare_all_stages()\" -e \"tic::before_install()\" -e \"tic::install()\"\n\n      # macOS devel needs its own stage because we need to work with an option to suppress the usage of binaries\n      - name: \"[Stage] Prepare & Install (macOS-devel)\"\n        if: matrix.config.os == 'macOS-latest' && matrix.config.r == 'devel'\n        run: |\n          echo -e 'options(Ncpus = 4, pkgType = \"source\", repos = structure(c(CRAN = \"https://cloud.r-project.org/\")))' > $HOME/.Rprofile\n          Rscript -e \"remotes::install_github('ropensci/tic')\" -e \"print(tic::dsl_load())\" -e \"tic::prepare_all_stages()\" -e \"tic::before_install()\" -e \"tic::install()\"\n\n      - name: \"[Stage] Script\"\n        run: Rscript -e 'tic::script()'\n\n      - name: \"[Stage] After Success\"\n        if: matrix.config.os == 'macOS-latest' && matrix.config.r == 'release'\n        run: Rscript -e \"tic::after_success()\"\n\n      - name: \"[Stage] Upload R CMD check artifacts\"\n        if: failure()\n        uses: actions/upload-artifact@v4\n        with:\n          name: ${{ runner.os }}-r${{ matrix.config.r }}-results\n          path: check\n"
  },
  {
    "path": ".gitignore",
    "content": ".Rproj.user\n.Rhistory\n.RData\n.Ruserdata\n\nsrc/*.o\nsrc/*.so\nsrc/*.dll\nsrc/Makevars\nconfig.log\nconfig.status\n\nwindows/\ninst/gdal/\ninst/proj/\n\nnc.shp\nnc.prj\nnc.dbf\nnc.shx\ndocs/\ntests/testthat/Rplots.pdf\n"
  },
  {
    "path": "CONDUCT.md",
    "content": "# Contributor Code of Conduct\n\nAs contributors and maintainers of this project, we pledge to respect all people who \ncontribute through reporting issues, posting feature requests, updating documentation,\nsubmitting pull requests or patches, and other activities.\n\nWe are committed to making participation in this project a harassment-free experience for\neveryone, regardless of level of experience, gender, gender identity and expression,\nsexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion.\n\nExamples of unacceptable behavior by participants include the use of sexual language or\nimagery, derogatory comments or personal attacks, trolling, public or private harassment,\ninsults, or other unprofessional conduct.\n\nProject maintainers have the right and responsibility to remove, edit, or reject comments,\ncommits, code, wiki edits, issues, and other contributions that are not aligned to this \nCode of Conduct. Project maintainers who do not follow the Code of Conduct may be removed \nfrom the project team.\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be reported by \nopening an issue or contacting one or more of the project maintainers.\n\nThis Code of Conduct is adapted from the Contributor Covenant \n(http:contributor-covenant.org), version 1.0.0, available at \nhttp://contributor-covenant.org/version/1/0/0/\n"
  },
  {
    "path": "DESCRIPTION",
    "content": "Package: sf\nVersion: 1.1-1\nTitle: Simple Features for R\nAuthors@R:\n    c(person(given = \"Edzer\",\n             family = \"Pebesma\",\n             role = c(\"aut\", \"cre\"),\n             email = \"edzer.pebesma@uni-muenster.de\",\n             comment = c(ORCID = \"0000-0001-8049-7069\")),\n      person(given = \"Roger\",\n             family = \"Bivand\",\n             role = \"ctb\",\n             comment = c(ORCID = \"0000-0003-2392-6140\")),\n      person(given = \"Etienne\",\n             family = \"Racine\",\n             role = \"ctb\"),\n      person(given = \"Michael\",\n             family = \"Sumner\",\n             role = \"ctb\"),\n      person(given = \"Ian\",\n             family = \"Cook\",\n             role = \"ctb\"),\n      person(given = \"Tim\",\n             family = \"Keitt\",\n             role = \"ctb\"),\n      person(given = \"Robin\",\n             family = \"Lovelace\",\n             role = \"ctb\"),\n      person(given = \"Hadley\",\n             family = \"Wickham\",\n             role = \"ctb\"),\n      person(given = \"Jeroen\",\n             family = \"Ooms\",\n             role = \"ctb\",\n             comment = c(ORCID = \"0000-0002-4035-0289\")),\n      person(given = \"Kirill\",\n             family = \"M\\u00fcller\",\n             role = \"ctb\"),\n      person(given = \"Thomas Lin\",\n             family = \"Pedersen\",\n             role = \"ctb\"),\n      person(given = \"Dan\",\n             family = \"Baston\",\n             role = \"ctb\"),\n      person(given = \"Dewey\",\n             family = \"Dunnington\",\n             role = \"ctb\",\n             comment = c(ORCID = \"0000-0002-9415-4582\")),\n      person(given = \"Alexandre\",\n             family = \"Courtiol\",\n             role = \"ctb\",\n             comment = c(ORCID = \"0000-0003-0637-2959\"))\n\t\t\t )\nDescription: Support for simple feature access, a standardized way to\n    encode and analyze spatial vector data. Binds to 'GDAL' \n\t<doi:10.5281/zenodo.5884351> for reading and writing data, to 'GEOS'\n    <doi:10.5281/zenodo.11396894> for geometrical operations,\n    and to 'PROJ' <doi:10.5281/zenodo.5884394> for projection\n    conversions and datum transformations. Uses by default the 's2'\n    package for geometry operations on geodetic (long/lat degree)\n\tcoordinates.\nLicense: GPL-2 | MIT + file LICENSE\nURL: https://r-spatial.github.io/sf/, https://github.com/r-spatial/sf\nBugReports: https://github.com/r-spatial/sf/issues\nDepends:\n    methods,\n    R (>= 4.1.0)\nImports:\n    classInt (>= 0.4-1),\n    DBI (>= 0.8),\n    graphics,\n    grDevices,\n    grid,\n    s2 (>= 1.1.0),\n    stats,\n    tools,\n    units (>= 0.7-0),\n    utils\nSuggests:\n    blob,\n    nanoarrow,\n    covr,\n    dplyr (>= 1.0.0),\n    ggplot2,\n    knitr,\n    lwgeom (>= 0.2-14),\n    maps,\n    mapview,\n    Matrix,\n    microbenchmark,\n    odbc,\n    pbapply,\n    pillar,\n    pool,\n    raster,\n    rlang,\n    rmarkdown,\n    RPostgres (>= 1.1.0),\n    RPostgreSQL,\n    RSQLite,\n    sp (>= 1.2-4),\n    spatstat (>= 2.0-1),\n    spatstat.geom, \n    spatstat.random, \n    spatstat.linnet, \n    spatstat.utils,\n    stars (>= 0.6-0),\n    terra,\n    testthat (>= 3.0.0),\n    tibble (>= 1.4.1),\n    tidyr (>= 1.2.0),\n    tidyselect (>= 1.0.0),\n    tmap (>= 2.0),\n    vctrs,\n    wk (>= 0.9.0)\nLinkingTo: \n    Rcpp\nVignetteBuilder: \n    knitr\nEncoding: UTF-8\nConfig/testthat/edition: 2\nConfig/needs/coverage: XML\nConfig/roxygen2/markdown: TRUE\nConfig/roxygen2/version: 8.0.0\nSystemRequirements: GDAL (>= 2.0.1), GEOS (>= 3.4.0),\n    PROJ (>= 4.8.0), sqlite3\nCollate: \n    'RcppExports.R'\n    'init.R'\n    'import-standalone-s3-register.R'\n    'crs.R'\n    'bbox.R'\n    'read.R'\n    'db.R'\n    'sfc.R'\n    'sfg.R'\n    'sf.R'\n    'bind.R'\n    'wkb.R'\n    'wkt.R'\n    'plot.R'\n    'geom-measures.R'\n    'geom-predicates.R'\n    'geom-transformers.R'\n    'transform.R'\n    'proj.R'\n    'sp.R'\n    'grid.R'\n    'arith.R'\n    'tidyverse.R'\n    'tidyverse-vctrs.R'\n    'cast_sfg.R'\n    'cast_sfc.R'\n    'graticule.R'\n    'datasets.R'\n    'aggregate.R'\n    'agr.R'\n    'maps.R'\n    'join.R'\n    'sample.R'\n    'valid.R'\n    'collection_extract.R'\n    'jitter.R'\n    'sgbp.R'\n    'spatstat.R'\n    'stars.R'\n    'crop.R'\n    'gdal_utils.R'\n    'nearest.R'\n    'normalize.R'\n    'sf-package.R'\n    'defunct.R'\n    'z_range.R'\n    'm_range.R'\n    'shift_longitude.R'\n    'make_grid.R'\n    's2.R'\n    'terra.R'\n    'geos-overlayng.R'\n    'break_antimeridian.R'\n"
  },
  {
    "path": "LICENSE",
    "content": "YEAR: 2016-2024\nCOPYRIGHT HOLDER: Edzer Pebesma\n"
  },
  {
    "path": "NAMESPACE",
    "content": "# Generated by roxygen2: do not edit by hand\n\nS3method(\"$\",bbox)\nS3method(\"$\",crs)\nS3method(\"$\",m_range)\nS3method(\"$\",z_range)\nS3method(\"$<-\",sf)\nS3method(\"[\",sf)\nS3method(\"[\",sfc)\nS3method(\"[<-\",sf)\nS3method(\"[<-\",sfc)\nS3method(\"[[<-\",sf)\nS3method(\"st_agr<-\",sf)\nS3method(\"st_crs<-\",bbox)\nS3method(\"st_crs<-\",sf)\nS3method(\"st_crs<-\",sfc)\nS3method(\"st_geometry<-\",data.frame)\nS3method(\"st_geometry<-\",sf)\nS3method(Ops,crs)\nS3method(Ops,sfc)\nS3method(Ops,sfg)\nS3method(Ops,sgbp)\nS3method(aggregate,sf)\nS3method(as.data.frame,sf)\nS3method(as.data.frame,sfc)\nS3method(as.data.frame,sgbp)\nS3method(as.matrix,sfg)\nS3method(as.matrix,sgbp)\nS3method(c,sfc)\nS3method(c,sfg)\nS3method(cbind,sf)\nS3method(dim,sgbp)\nS3method(duplicated,sf)\nS3method(format,bbox)\nS3method(format,crs)\nS3method(format,sfc)\nS3method(format,sfg)\nS3method(head,sfg)\nS3method(identify,sf)\nS3method(identify,sfc)\nS3method(is.na,bbox)\nS3method(is.na,crs)\nS3method(is.na,m_range)\nS3method(is.na,z_range)\nS3method(is_geometry_column,PqConnection)\nS3method(is_geometry_column,default)\nS3method(merge,sf)\nS3method(plot,sf)\nS3method(plot,sfc_CIRCULARSTRING)\nS3method(plot,sfc_GEOMETRY)\nS3method(plot,sfc_GEOMETRYCOLLECTION)\nS3method(plot,sfc_LINESTRING)\nS3method(plot,sfc_MULTILINESTRING)\nS3method(plot,sfc_MULTIPOINT)\nS3method(plot,sfc_MULTIPOLYGON)\nS3method(plot,sfc_POINT)\nS3method(plot,sfc_POLYGON)\nS3method(plot,sfg)\nS3method(points,sf)\nS3method(points,sfc)\nS3method(print,bbox)\nS3method(print,crs)\nS3method(print,m_range)\nS3method(print,proj_pipelines)\nS3method(print,sf)\nS3method(print,sf_layers)\nS3method(print,sfc)\nS3method(print,sfg)\nS3method(print,sgbp)\nS3method(print,z_range)\nS3method(rbind,sf)\nS3method(rep,sfc)\nS3method(st_agr,character)\nS3method(st_agr,default)\nS3method(st_agr,factor)\nS3method(st_agr,sf)\nS3method(st_area,sf)\nS3method(st_area,sfc)\nS3method(st_area,sfg)\nS3method(st_as_binary,sfc)\nS3method(st_as_binary,sfg)\nS3method(st_as_grob,CIRCULARSTRING)\nS3method(st_as_grob,COMPOUNDCURVE)\nS3method(st_as_grob,CURVEPOLYGON)\nS3method(st_as_grob,GEOMETRYCOLLECTION)\nS3method(st_as_grob,LINESTRING)\nS3method(st_as_grob,MULTILINESTRING)\nS3method(st_as_grob,MULTIPOINT)\nS3method(st_as_grob,MULTIPOLYGON)\nS3method(st_as_grob,MULTISURFACE)\nS3method(st_as_grob,POINT)\nS3method(st_as_grob,POLYGON)\nS3method(st_as_grob,sfc)\nS3method(st_as_grob,sfc_CIRCULARSTRING)\nS3method(st_as_grob,sfc_LINESTRING)\nS3method(st_as_grob,sfc_MULTILINESTRING)\nS3method(st_as_grob,sfc_MULTIPOINT)\nS3method(st_as_grob,sfc_MULTIPOLYGON)\nS3method(st_as_grob,sfc_POINT)\nS3method(st_as_grob,sfc_POLYGON)\nS3method(st_as_s2,sf)\nS3method(st_as_s2,sfc)\nS3method(st_as_sf,SpatVector)\nS3method(st_as_sf,Spatial)\nS3method(st_as_sf,data.frame)\nS3method(st_as_sf,lpp)\nS3method(st_as_sf,map)\nS3method(st_as_sf,owin)\nS3method(st_as_sf,ppp)\nS3method(st_as_sf,ppplist)\nS3method(st_as_sf,psp)\nS3method(st_as_sf,s2_geography)\nS3method(st_as_sf,sf)\nS3method(st_as_sf,sfc)\nS3method(st_as_sfc,SpatialLines)\nS3method(st_as_sfc,SpatialMultiPoints)\nS3method(st_as_sfc,SpatialPixels)\nS3method(st_as_sfc,SpatialPoints)\nS3method(st_as_sfc,SpatialPolygons)\nS3method(st_as_sfc,WKB)\nS3method(st_as_sfc,bbox)\nS3method(st_as_sfc,blob)\nS3method(st_as_sfc,character)\nS3method(st_as_sfc,dimensions)\nS3method(st_as_sfc,factor)\nS3method(st_as_sfc,list)\nS3method(st_as_sfc,map)\nS3method(st_as_sfc,owin)\nS3method(st_as_sfc,pq_geometry)\nS3method(st_as_sfc,psp)\nS3method(st_as_sfc,raw)\nS3method(st_as_sfc,s2_geography)\nS3method(st_as_sfc,sf)\nS3method(st_as_sfc,tess)\nS3method(st_as_text,crs)\nS3method(st_as_text,sfc)\nS3method(st_as_text,sfg)\nS3method(st_bbox,CIRCULARSTRING)\nS3method(st_bbox,COMPOUNDCURVE)\nS3method(st_bbox,CURVEPOLYGON)\nS3method(st_bbox,Extent)\nS3method(st_bbox,GEOMETRYCOLLECTION)\nS3method(st_bbox,LINESTRING)\nS3method(st_bbox,MULTICURVE)\nS3method(st_bbox,MULTILINESTRING)\nS3method(st_bbox,MULTIPOINT)\nS3method(st_bbox,MULTIPOLYGON)\nS3method(st_bbox,MULTISURFACE)\nS3method(st_bbox,POINT)\nS3method(st_bbox,POLYGON)\nS3method(st_bbox,POLYHEDRALSURFACE)\nS3method(st_bbox,Raster)\nS3method(st_bbox,SpatExtent)\nS3method(st_bbox,SpatRaster)\nS3method(st_bbox,SpatVector)\nS3method(st_bbox,Spatial)\nS3method(st_bbox,TIN)\nS3method(st_bbox,TRIANGLE)\nS3method(st_bbox,bbox)\nS3method(st_bbox,numeric)\nS3method(st_bbox,sf)\nS3method(st_bbox,sfc)\nS3method(st_boundary,sf)\nS3method(st_boundary,sfc)\nS3method(st_boundary,sfg)\nS3method(st_break_antimeridian,sf)\nS3method(st_break_antimeridian,sfc)\nS3method(st_buffer,sf)\nS3method(st_buffer,sfc)\nS3method(st_buffer,sfg)\nS3method(st_cast,CIRCULARSTRING)\nS3method(st_cast,COMPOUNDCURVE)\nS3method(st_cast,CURVE)\nS3method(st_cast,GEOMETRYCOLLECTION)\nS3method(st_cast,LINESTRING)\nS3method(st_cast,MULTICURVE)\nS3method(st_cast,MULTILINESTRING)\nS3method(st_cast,MULTIPOINT)\nS3method(st_cast,MULTIPOLYGON)\nS3method(st_cast,MULTISURFACE)\nS3method(st_cast,POINT)\nS3method(st_cast,POLYGON)\nS3method(st_cast,sf)\nS3method(st_cast,sfc)\nS3method(st_cast,sfc_CIRCULARSTRING)\nS3method(st_centroid,sf)\nS3method(st_centroid,sfc)\nS3method(st_centroid,sfg)\nS3method(st_collection_extract,sf)\nS3method(st_collection_extract,sfc)\nS3method(st_collection_extract,sfg)\nS3method(st_concave_hull,sf)\nS3method(st_concave_hull,sfc)\nS3method(st_concave_hull,sfg)\nS3method(st_convex_hull,sf)\nS3method(st_convex_hull,sfc)\nS3method(st_convex_hull,sfg)\nS3method(st_coordinates,sf)\nS3method(st_coordinates,sfc)\nS3method(st_coordinates,sfg)\nS3method(st_crop,sf)\nS3method(st_crop,sfc)\nS3method(st_crs,CRS)\nS3method(st_crs,Raster)\nS3method(st_crs,SpatRaster)\nS3method(st_crs,SpatVector)\nS3method(st_crs,Spatial)\nS3method(st_crs,bbox)\nS3method(st_crs,character)\nS3method(st_crs,crs)\nS3method(st_crs,default)\nS3method(st_crs,numeric)\nS3method(st_crs,sf)\nS3method(st_crs,sfc)\nS3method(st_difference,sf)\nS3method(st_difference,sfc)\nS3method(st_difference,sfg)\nS3method(st_drop_geometry,default)\nS3method(st_drop_geometry,sf)\nS3method(st_exterior_ring,sf)\nS3method(st_exterior_ring,sfc)\nS3method(st_exterior_ring,sfg)\nS3method(st_filter,sf)\nS3method(st_geometry,sf)\nS3method(st_geometry,sfc)\nS3method(st_geometry,sfg)\nS3method(st_inscribed_circle,sf)\nS3method(st_inscribed_circle,sfc)\nS3method(st_inscribed_circle,sfg)\nS3method(st_interpolate_aw,sf)\nS3method(st_intersection,sf)\nS3method(st_intersection,sfc)\nS3method(st_intersection,sfg)\nS3method(st_intersects,sf)\nS3method(st_intersects,sfc)\nS3method(st_intersects,sfg)\nS3method(st_is,sf)\nS3method(st_is,sfc)\nS3method(st_is,sfg)\nS3method(st_is_full,bbox)\nS3method(st_is_full,sf)\nS3method(st_is_full,sfc)\nS3method(st_is_full,sfg)\nS3method(st_is_valid,sf)\nS3method(st_is_valid,sfc)\nS3method(st_is_valid,sfg)\nS3method(st_join,sf)\nS3method(st_line_merge,sf)\nS3method(st_line_merge,sfc)\nS3method(st_line_merge,sfg)\nS3method(st_m_range,CIRCULARSTRING)\nS3method(st_m_range,COMPOUNDCURVE)\nS3method(st_m_range,CURVEPOLYGON)\nS3method(st_m_range,GEOMETRYCOLLECTION)\nS3method(st_m_range,LINESTRING)\nS3method(st_m_range,MULTICURVE)\nS3method(st_m_range,MULTILINESTRING)\nS3method(st_m_range,MULTIPOINT)\nS3method(st_m_range,MULTIPOLYGON)\nS3method(st_m_range,MULTISURFACE)\nS3method(st_m_range,POINT)\nS3method(st_m_range,POLYGON)\nS3method(st_m_range,POLYHEDRALSURFACE)\nS3method(st_m_range,TIN)\nS3method(st_m_range,TRIANGLE)\nS3method(st_m_range,m_range)\nS3method(st_m_range,numeric)\nS3method(st_m_range,sf)\nS3method(st_m_range,sfc)\nS3method(st_make_valid,sf)\nS3method(st_make_valid,sfc)\nS3method(st_make_valid,sfg)\nS3method(st_minimum_bounding_circle,sf)\nS3method(st_minimum_bounding_circle,sfc)\nS3method(st_minimum_bounding_circle,sfg)\nS3method(st_minimum_rotated_rectangle,sf)\nS3method(st_minimum_rotated_rectangle,sfc)\nS3method(st_minimum_rotated_rectangle,sfg)\nS3method(st_nearest_points,sf)\nS3method(st_nearest_points,sfc)\nS3method(st_nearest_points,sfg)\nS3method(st_node,sf)\nS3method(st_node,sfc)\nS3method(st_node,sfg)\nS3method(st_normalize,sf)\nS3method(st_normalize,sfc)\nS3method(st_normalize,sfg)\nS3method(st_point_on_surface,sf)\nS3method(st_point_on_surface,sfc)\nS3method(st_point_on_surface,sfg)\nS3method(st_polygonize,sf)\nS3method(st_polygonize,sfc)\nS3method(st_polygonize,sfg)\nS3method(st_precision,sf)\nS3method(st_precision,sfc)\nS3method(st_read,DBIObject)\nS3method(st_read,Pool)\nS3method(st_read,PostgreSQLConnection)\nS3method(st_read,character)\nS3method(st_read,default)\nS3method(st_reverse,sf)\nS3method(st_reverse,sfc)\nS3method(st_reverse,sfg)\nS3method(st_sample,bbox)\nS3method(st_sample,sf)\nS3method(st_sample,sfc)\nS3method(st_sample,sfg)\nS3method(st_segmentize,sf)\nS3method(st_segmentize,sfc)\nS3method(st_segmentize,sfg)\nS3method(st_set_precision,sf)\nS3method(st_set_precision,sfc)\nS3method(st_shift_longitude,sf)\nS3method(st_shift_longitude,sfc)\nS3method(st_simplify,sf)\nS3method(st_simplify,sfc)\nS3method(st_simplify,sfg)\nS3method(st_snap,sf)\nS3method(st_snap,sfc)\nS3method(st_snap,sfg)\nS3method(st_sym_difference,sf)\nS3method(st_sym_difference,sfc)\nS3method(st_sym_difference,sfg)\nS3method(st_transform,bbox)\nS3method(st_transform,sf)\nS3method(st_transform,sfc)\nS3method(st_transform,sfg)\nS3method(st_triangulate,sf)\nS3method(st_triangulate,sfc)\nS3method(st_triangulate,sfg)\nS3method(st_triangulate_constrained,sf)\nS3method(st_triangulate_constrained,sfc)\nS3method(st_triangulate_constrained,sfg)\nS3method(st_union,sf)\nS3method(st_union,sfc)\nS3method(st_union,sfg)\nS3method(st_voronoi,sf)\nS3method(st_voronoi,sfc)\nS3method(st_voronoi,sfg)\nS3method(st_wrap_dateline,sf)\nS3method(st_wrap_dateline,sfc)\nS3method(st_wrap_dateline,sfg)\nS3method(st_write,data.frame)\nS3method(st_write,sf)\nS3method(st_write,sfc)\nS3method(st_z_range,CIRCULARSTRING)\nS3method(st_z_range,COMPOUNDCURVE)\nS3method(st_z_range,CURVEPOLYGON)\nS3method(st_z_range,GEOMETRYCOLLECTION)\nS3method(st_z_range,LINESTRING)\nS3method(st_z_range,MULTICURVE)\nS3method(st_z_range,MULTILINESTRING)\nS3method(st_z_range,MULTIPOINT)\nS3method(st_z_range,MULTIPOLYGON)\nS3method(st_z_range,MULTISURFACE)\nS3method(st_z_range,POINT)\nS3method(st_z_range,POLYGON)\nS3method(st_z_range,POLYHEDRALSURFACE)\nS3method(st_z_range,TIN)\nS3method(st_z_range,TRIANGLE)\nS3method(st_z_range,numeric)\nS3method(st_z_range,sf)\nS3method(st_z_range,sfc)\nS3method(st_z_range,z_range)\nS3method(st_zm,list)\nS3method(st_zm,matrix)\nS3method(st_zm,sf)\nS3method(st_zm,sfc)\nS3method(st_zm,sfg)\nS3method(str,sfc)\nS3method(summary,sfc)\nS3method(t,sgbp)\nS3method(text,sf)\nS3method(text,sfc)\nS3method(transform,sf)\nS3method(unique,sfc)\nS3method(xtfrm,sfc)\nexport(\"st_agr<-\")\nexport(\"st_crs<-\")\nexport(\"st_geometry<-\")\nexport(\"st_precision<-\")\nexport(.degAxis)\nexport(.get_layout)\nexport(.image_scale)\nexport(.image_scale_factor)\nexport(.stop_geos)\nexport(FULL_bbox_)\nexport(NA_agr_)\nexport(NA_bbox_)\nexport(NA_crs_)\nexport(NA_m_range_)\nexport(NA_z_range_)\nexport(as_Spatial)\nexport(gdal_addo)\nexport(gdal_compressors)\nexport(gdal_create)\nexport(gdal_crs)\nexport(gdal_extract)\nexport(gdal_inv_geotransform)\nexport(gdal_metadata)\nexport(gdal_polygonize)\nexport(gdal_rasterize)\nexport(gdal_read)\nexport(gdal_read_mdim)\nexport(gdal_subdatasets)\nexport(gdal_utils)\nexport(gdal_write)\nexport(gdal_write_mdim)\nexport(get_key_pos)\nexport(plot_sf)\nexport(rawToHex)\nexport(read_sf)\nexport(sf.colors)\nexport(sf_add_proj_units)\nexport(sf_extSoftVersion)\nexport(sf_proj_info)\nexport(sf_proj_network)\nexport(sf_proj_pipelines)\nexport(sf_proj_search_paths)\nexport(sf_project)\nexport(sf_use_s2)\nexport(st_agr)\nexport(st_area)\nexport(st_as_binary)\nexport(st_as_grob)\nexport(st_as_s2)\nexport(st_as_sf)\nexport(st_as_sfc)\nexport(st_as_text)\nexport(st_axis_order)\nexport(st_bbox)\nexport(st_bind_cols)\nexport(st_boundary)\nexport(st_break_antimeridian)\nexport(st_buffer)\nexport(st_can_transform)\nexport(st_cast)\nexport(st_centroid)\nexport(st_collection_extract)\nexport(st_combine)\nexport(st_concave_hull)\nexport(st_contains)\nexport(st_contains_properly)\nexport(st_convex_hull)\nexport(st_coordinates)\nexport(st_covered_by)\nexport(st_covers)\nexport(st_crop)\nexport(st_crosses)\nexport(st_crs)\nexport(st_delete)\nexport(st_difference)\nexport(st_dimension)\nexport(st_disjoint)\nexport(st_distance)\nexport(st_drivers)\nexport(st_drop_geometry)\nexport(st_equals)\nexport(st_equals_exact)\nexport(st_exterior_ring)\nexport(st_filter)\nexport(st_geometry)\nexport(st_geometry_type)\nexport(st_geometrycollection)\nexport(st_graticule)\nexport(st_inscribed_circle)\nexport(st_interpolate_aw)\nexport(st_intersection)\nexport(st_intersects)\nexport(st_is)\nexport(st_is_empty)\nexport(st_is_full)\nexport(st_is_longlat)\nexport(st_is_simple)\nexport(st_is_valid)\nexport(st_is_within_distance)\nexport(st_jitter)\nexport(st_join)\nexport(st_layers)\nexport(st_length)\nexport(st_line_interpolate)\nexport(st_line_merge)\nexport(st_line_project)\nexport(st_line_sample)\nexport(st_linestring)\nexport(st_m_range)\nexport(st_make_grid)\nexport(st_make_valid)\nexport(st_minimum_bounding_circle)\nexport(st_minimum_rotated_rectangle)\nexport(st_multilinestring)\nexport(st_multipoint)\nexport(st_multipolygon)\nexport(st_nearest_feature)\nexport(st_nearest_points)\nexport(st_node)\nexport(st_normalize)\nexport(st_overlaps)\nexport(st_perimeter)\nexport(st_point)\nexport(st_point_on_surface)\nexport(st_polygon)\nexport(st_polygonize)\nexport(st_precision)\nexport(st_read)\nexport(st_read_db)\nexport(st_relate)\nexport(st_reverse)\nexport(st_sample)\nexport(st_segmentize)\nexport(st_set_agr)\nexport(st_set_crs)\nexport(st_set_geometry)\nexport(st_set_precision)\nexport(st_sf)\nexport(st_sfc)\nexport(st_shift_longitude)\nexport(st_simplify)\nexport(st_snap)\nexport(st_sym_difference)\nexport(st_touches)\nexport(st_transform)\nexport(st_triangulate)\nexport(st_triangulate_constrained)\nexport(st_union)\nexport(st_viewport)\nexport(st_voronoi)\nexport(st_within)\nexport(st_wrap_dateline)\nexport(st_write)\nexport(st_write_db)\nexport(st_z_range)\nexport(st_zm)\nexport(write_sf)\nexportMethods(dbDataType)\nexportMethods(dbWriteTable)\nimport(graphics)\nimportClassesFrom(DBI,DBIObject)\nimportFrom(DBI,dbConnect)\nimportFrom(DBI,dbDisconnect)\nimportFrom(DBI,dbExecute)\nimportFrom(DBI,dbGetQuery)\nimportFrom(DBI,dbReadTable)\nimportFrom(DBI,dbSendQuery)\nimportFrom(DBI,dbWriteTable)\nimportFrom(classInt,classIntervals)\nimportFrom(grDevices,cm)\nimportFrom(grDevices,dev.size)\nimportFrom(grDevices,rgb)\nimportFrom(grid,convertHeight)\nimportFrom(grid,convertUnit)\nimportFrom(grid,convertWidth)\nimportFrom(grid,current.viewport)\nimportFrom(grid,gList)\nimportFrom(grid,gpar)\nimportFrom(grid,linesGrob)\nimportFrom(grid,nullGrob)\nimportFrom(grid,pathGrob)\nimportFrom(grid,pointsGrob)\nimportFrom(grid,polylineGrob)\nimportFrom(grid,unit)\nimportFrom(grid,viewport)\nimportFrom(methods,\"slot<-\")\nimportFrom(methods,as)\nimportFrom(methods,new)\nimportFrom(methods,slot)\nimportFrom(methods,slotNames)\nimportFrom(stats,aggregate)\nimportFrom(stats,dist)\nimportFrom(stats,na.omit)\nimportFrom(stats,rbinom)\nimportFrom(stats,runif)\nimportFrom(stats,setNames)\nimportFrom(tools,file_ext)\nimportFrom(tools,file_path_sans_ext)\nimportFrom(units,as_units)\nimportFrom(units,drop_units)\nimportFrom(units,make_unit_label)\nimportFrom(units,set_units)\nimportFrom(utils,compareVersion)\nimportFrom(utils,globalVariables)\nimportFrom(utils,head)\nimportFrom(utils,object.size)\nimportFrom(utils,packageVersion)\nimportFrom(utils,str)\nimportFrom(utils,tail)\nimportMethodsFrom(DBI,dbDataType)\nimportMethodsFrom(DBI,dbExistsTable)\nimportMethodsFrom(DBI,dbWriteTable)\nuseDynLib(sf, .registration=TRUE)\n"
  },
  {
    "path": "NEWS.md",
    "content": "# version 1.1-1\n\n* use RAII in functions calling GEOS for handling context, based on how terra does this; #2604\n\n* `st_graticule()` simplifies output lines; #1364\n\n* `dplyr::count()` drops geometries if `.drop_geom = TRUE` is set; #2596\n\n* better handle graticules crossing the antemeridian; #2561\n\n* add the option `by_element = TRUE` to binary geometry predicates, measures and transformers; #2594 and #2595 by @rariariari w. help from Claude\n\n* add `MULTISURFACE` and `CURVEPOLYGON` to vctrs methods; #2589 #2601\n￼\n* add argument `include_non_intersected` to `st_interpolate_aw()`\n\n* add argument `weights`, for dasymetric mapping, to `st_interpolate_aw()` (experimental)\n\n* replace magrittr pipe `%>%` with base pipe `|>`, and hence require R >= 4.1.0\n\n# version 1.1-0\n\n* `gdal_compressors()` queries GDAL compressor and decompressor capabilities\n\n* `st_cast.sfc()` deals with zero-length objects; #2584\n\n* rewrite/migrate `vctrs` methods for `sf` and `sfc`; #2568, #2584, w. help from @DavisVaughan\n\n* `st_agr()` and `st_agr<-()` better handle multiple geometry columns\n\n* for an `sfc` object `x`, `x[0]` retains the class of `x`; #2568\n\n* When sampling a degenerate (zero length) line, a warning is raised rather than a message; #2575\n\n# version 1.0-24\n\n* `gdal_write()` handles drivers that only have a `CreateCopy()` option; https://github.com/r-spatial/stars/issues/762 \n\n* if `datum` is missing in a call to `st_graticule()`, a graticule by default will try to use the geographic coordinate reference system of arguments `x` or `crs`; when nothing is found there it falls back to `OGC:CRS84` (WGS84).\n\n* the figure margins parameter `mar` can be specified in a call to `plot.sf()`; #2558\n\n* fix class label setting in `[.sf()`; #2557\n\n# version 1.0-23\n\n* allow tests reading blosc compressed Zarr files to fail\n\n* `st_as_sf.data.frame()` sets `z_range` and `m_range` if needed; https://github.com/geoarrow/geoarrow-r/issues/75\n\n# version 1.0-22\n\n* `st_combine()` on `POINT` geometries ignores empty points; #2551\n\n* handle empty points better in `st_point()`, `st_as_sf.data.frame()` and `st_distance()`; https://github.com/r-spatial/s2/issues/289\n\n* for unprojected lines, `st_line_interpolate()` requires distance values with degree units; #2542\n\n* `unique.sfc()` added; #2546\n\n* for geodetic coordinates, `st_perimeter()` uses ellipsoidal computation if `sf_use_s2()` is `FALSE`; #2541\n\n* `st_as_sf.owin()` and `st_as_sfc.owin()` no longer ignore `crs` argument; #2532\n\n* clarify approximation errors in `st_buffer()` and how they differ for the GEOS or S2 backends, with examples by David Kaplan @dmkaplan2000; #2528\n\n# version 1.0-21\n\n* `st_crs(..., parameters = TRUE)` returns base geographic CRS as `gcs_crs`; #2524\n\n* loading `sf` no longer initializes the RNG state; see https://github.com/r-quantities/units/issues/409\n\n* fix `st_sample()` on geodetic coordinates; #2515\n\n* use `compareVersion()` consistently to compare GDAL versions; #2512\n\n# version 1.0-20\n\n* `st_buffer()` on geodetic coordinates with negative buffer distance now automatically switches to using GEOS, while giving a warning; #1987\n\n* `st_interpolate_aw()` fixes bug when a GEOMETRYCOLLECTION contains multiple POLYGON structures; found by @mtennekes\n\n* `st_buffer()` for geodetic coordinates allows `max_dist` and `min_level` \n   to be specified by feature; #2488 and https://github.com/r-spatial/s2/pull/264\n\n* `distinct.sf()` allows for comparing exact equality of geometries when `exact = TRUE`; #2484\n\n* `st_minimum_bounding_circle()` returns geometries representing the smallest circle that contains the input; #2473\n\n# version 1.0-19\n\n* fix type checks in C++ GDAL area and length computation functions, anticipating GDAL 3.10.0; #2466, #2468, #2469 by @rsbivand and @rouault\n\n* improve test on empty geometries, which changed in 1.0-18; #2463\n\n* `gdal_utils()` `ogrinfo` has an argument `read_only` which, when `TRUE` (or `options` includes `\"-ro\"`), opens a datasource in read-only mode (#2460; `sf` did this before 1.0-17); by default a datasource is opened in update (read-write) mode (since sf 1.0-17; #2420)\n\n* the `sf` -> `ppp` conversion `as.ppp.sf()` accepts a data.frame of marks instead of just 1 column #2450, by @agila5\n\n* add flag for preservation of point order in `st_voronoi` #1371 for GEOS >= 3.12\n\n# version 1.0-18\n\n* support  `POLYGON FULL` simple feature geometry, representing the entire Earth surface, as used by `s2geometry`; see also https://r-spatial.org/r/2024/10/11/polygonfull.html for a longer introduction; #2441\n\n* `st_sfc()` has an argument `oriented` which, when set to `TRUE`, adds an attribute `oriented=TRUE` to an `sfc` object, indicating that this object should not be reoriented in conversion to `s2_geography` (avoiding using the global option `s2_oriented`); `st_as_sfc.bbox()` sets this to `TRUE`; #2441\n\n* fix build failure with GDAL < 3.4.0 #2436\n\n* `st_simplify()` now accepts feature-wise tolerance values when `s2` is switched on #2442\n\n# version 1.0-17\n\n* add `st_transform()` method for `bbox` objects; this uses OGRCoordinateTransformation::TransformBounds(), densifying first and antemeridian proof; #2415\n\n* `st_filter.sf()` correctly scopes `x` and `y` arguments using !! operator; #2416\n\n* `[.sfc` and `[<-.sfc` use matrix/array type subsetting for `sfc` objects that have a `dim` attribute\n\n* add `st_exterior_ring()` to extract exterior rings (remove holes); #2406\n\n* add `text.sf()`, `text.sfc()`, `points.sf()`, `points.sfc()` to annotate base plots at geometry centroids; #2399\n\n* `st_sf()` no longer strips `tbl` or `tbl_df` class labels; #2378\n\n* `st_layers()` returns an object of class `c(\"sf_layers\", \"data.frame\")`, with a dedicated `print` method.\n\n* when `dim` is not `XYZM`, `sf_as_sf.data.frame()` interprets a length 4 `coords` argument to specify the corners of a rectangular polygon; #2357\n\n* `st_interpolate_aw()` gains an `na.rm` argument, for removing features with `NA` attributes before interpolating; #830\n\n* `merge.sf()` no longer renames geometry column; #2334\n\n# version 1.0-16\n\n* `st_join()` no longer renames the geometry column; #2327\n\n* `st_sample()` works when unprojected polygon geometry crosses the antemeridian; #2331\n\n* clean up and modernization of S3 registration of methods and tests; #2285, #2288, #2316, #2341, #2342, by @olivroy\n\n* `[.sfc` works when setting argument `op`; #2320\n\n* `st_sample()` for polygons is sensitive to setting `oriented = TRUE` to prevent wrongly correcting ring directions; #2308\n\n* add support for the GDAL `footprint` utility (requiring GDAL >= 3.8.0) to `gdal_utils`; #2305, by @goergen95\n\n* existing environment variables `PROJ_LIB` and `PROJ_DATA` are (again) ignored on `sf` binary CRAN installations (win + macos), effectively by overwriting them during the R session and restoring them on exit; this does not happen if environment variable `R_SF_USE_PROJ_DATA` is set to `true`. #2298\n\n* add `st_line_project()` to find how far a point is when projected on a line; #2291\n\n* add `st_line_interpolate()` to obtain a point at a certain distance along a line; #2291\n\n# version 1.0-15\n\n* add `st_perimeter()` generic to cover both geographic and projected coordinates; #268, #2279, by @JosiahParry\n\n* add `st_sample()` method for `bbox`, with special provisions for ellipsoidal coordinates; #2283\n\n* documentation clean-up by @olivroy; #2266, #2285\n\n* `st_convex_hull()` uses `s2::s2_convex_hull()` for geodetic coordinates; #2250\n\n* add `directed` argument to `st_line_merge()`; #2264\n\n* `st_union.sfc()` given `x` and `y` works consistently across geodetic and projected objects; #2262\n\n* `st_union.sf()` given `x` and `y` unions pairwise if `by_feature = TRUE`; #2259\n\n* `st_read()` work around issue with GPKG driver if `wkt_filter` is set; #2248\n\n* `st_read()` uses GDAL's stream reading when `use_stream = TRUE`; #2238 by @paleolimbot\n\n* `st_transform()` responds to in-session changes to `sf_proj_network()`; #2166\n\n* `plot.sf()`: `key.width` is sensitive to pointsize graphics parameter `par(\"ps\")`; keys with factor levels suggest a proper size if they won't fit.\n\n* `plot.sf()`: `key.pos` can hold a second value in [0, 1] determining the relative position of the key in the available space \n\n* `[<-.sf` fixes the `agr` attribute when it is broken; #2211\n\n* if the env. variable `ADD_SF_NAMESPACE` is set to `true`, `sf` objects get a new attribute, `.sf_namespace`, which forces loading the `sf` namespace when it has not been loaded so far, e.g. for proper printing or plotting of an `sf` object; #2212 by Mike Mahoney\n\n* `distinct.sf()` is type-safe for `sf` objects with zero rows; #2204\n\n* `summarise.sf()` raises an error if `.by` is given but no `across()` on the geometry; #2207\n\n* `st_write()` matches fields on name first, than on position; this matters for formats that have pre-defined names, such as GPX; #2202 \n\n# version 1.0-14\n\n* fix `plot.sf()` when using a key for multiple factor variables; #2196, #2195\n\n* fix use of `as.numeric_version` in a test, for upcoming change in r-devel\n\n* code tidy-ing: fix many lintr suggestions, thanks to Michael Chirico (#2181 - #2191)\n\n# version 1.0-13\n\n* `gdal_utils()` adds `\"ogrinfo\"` utility (requires GDAL >= 3.7.0); #2160\n\n* `st_as_sf()` catches errors when setting invalid crs values, raised by Jon Skøien\n\n* add `rename_with.sf()` method; #1472\n\n* use GEOS' overlayNG routines for (GEOS) Intersection, Difference, Union and SymDifference; #2143\n\n* added `duplicated.sf()`; #2138, #2140, thanks to @bart1\n\n* `select.sf()` allows selecting the same column twice under different names; #1886\n\n* `st_as_sf.ppplist()` is deprecated; #1926\n\n* `st_cast()` handles empty geometries; #1961\n\n* don't repeat longlat messages in `summarise.sf()`; #1519\n\n* fix random sampling on the sphere; #2133\n\n# version 1.0-12\n\n* update NAMESPACE to `useDynLib(sf, .registration=TRUE)`; #2127 thanks to @eddelbuettel\n\n* fix call in `gdal_addo()`; #2124\n\n* fix issues that came up with older GDAL version, use `GDAL_VERSION_NUM` consistently; #2123 #2121 #2119\n\n# version 1.0-11\n\n* `st_make_grid()` also accepts area units for `cellsize`, for square and hexagonal grids; #1505\n\n* add `st_concave_hull()`, for concave hulls, if GEOS >= 3.11.0; #1964\n\n* add `st_triangulate_constrained()`, for constrained Delaunay triangulation, if GEOS >= 3.10.0; #1964\n\n* clean up the retrieval of length or angle units from WKT representations; https://lists.osgeo.org/pipermail/gdal-dev/2023-March/056994.html\n\n* conversion to GEOS uses the `GEOS_PREC_VALID_OUTPUT` flag, which makes sure that the \"[o]utput is always valid. Collapsed geometry elements (including both polygons and lines) are removed.\"\n\n# version 1.0-10\n\n* `gdal_utils()` has a `config_options` argument to set further GDAL options, just like `st_write()`; #2003\n\n* fix slow writing of logical vectors in `st_write()`; #1409; #1689\n\n* `st_drivers()` has an argument `regex` to filter on driver (long) name; #2090\n\n* drop C++11 as a system requirement\n\n* `c.sfc()` (and, consequently, `dplyr::bind_rows()`) gives an error if components have different CRS; #1884\n\n* data imported from `maps` are associated with the Clark 1866 ellipsoid; #2080\n\n* fix importing legacy `SpatialPolygon` objects without comments; #2063, #2069, https://github.com/rstudio/leaflet/issues/833\n\n* `st_read()` no longer errors on mixes of `XY` and `XYZ` geometries; #2046 #1592\n\n* in `plot.sf()`, when numeric `breaks` are given a legend key is always plotted; #2065\n\n* `st_crs()$axes` returns a `data.frame` with axes properties (name, orientation, conversion factor) when GDAL >= 3.0.0\n\n* clean up unit handling for geometry measures (length, area, distance) and crs; \n\n* `st_crs(x)$ud_unit` returns `NULL` if units are unknown; #2049\n\n* `st_write()` substitutes an `NA` crs with `ENGCRS[\"Undefined Cartesian SRS with unknown unit\"]`; #2049, #2054\n\n* `st_can_transform()` checks whether a transformation between two crs exists; see https://github.com/dieghernan/tidyterra/issues/64; #2049\n\n* the matrix returned by `st_coordinates()` has no row names, to reduce output size\n\n# version 1.0-9\n\n* adjust for changes how R-devel handles `POSIXlt`; #2028\n\n* add `st_break_antimeridian()`; #1983, #1991 by Roger Bivand\n\n* add `Fibonacci` as a spatial sampling type in `st_sample()`\n\n* use the global `options(\"sf_use_s2\")` to determine whether to use s2, rather than a value in a local environment; #1977\n\n* fix utils `mdiminfo` and `mdimtranslate` in `gdal_utils()` \n\n* extend arguments of `gdal_read_mdim()` needed by `stars::read_mdim()` if `stars` >= 0.5-7; add `gdal_write_mdim()`\n\n* add `drop_na()` method for `sf` objects; #1975\n\n# version 1.0-8\n\n* `st_drop_geometry.default()` returns `x` unmodified;\n\n* `sf_project()` accepts 3- or 4-column matrices, containing z and t values;\n\n* optimization for `st_sfc()` by @paleolimbot; #1938, #1925\n\n* `[<-.sfc()` recomputes the bounding box; `st_sfc()` gets parameter `compute_bbox`; #1965\n\n* add new algorithm and drop option to `st_make_valid()` when using GEOS and GEOS >= 3.10.1; #1655\n\n* add `st_minimum_rotated_rectangle()`, available when GEOS >= 3.9.0; #1953\n\n* fix `st_sample()` with `type = \"hexagonal\"` for corner case (n=1), add a `progress` argument for a progress bar; #1945\n\n* add package `pbapply` to Suggests; #1945\n\n* add pdf driver to windows build; #1942\n\n* clarify `pipeline` argument in `st_transform()` when axis order is ambiguous; #1934\n\n* handle argument `xpd` in calls to `plot.sfc_POLYGON()` and `plot.sfc_MULTIPOLYGON()`\n\n* add `pivot_wider()` method, by Henning Teickner; #1915\n\n* add `gdal_addo()` to add or remove overviews from raster images; #1921\n\n* `st_layers()` returns `crs` of each layer in a `crs` list of `crs` objects\n\n* restore `st_graticule()` behaviour to pre-sf 1.0-0; https://github.com/tidyverse/ggplot2/issues/4571\n\n* `gdal_metadata()` sets metadata item names properly\n\n* `st_read()` gains an argument `optional` passed on to `as.data.frame` to avoid changing column names; #1916\n\n* GPX files are autodetected by `st_read()`; #1917\n\n* unnecessary coordinate names are not returned in `st_sample()`, making the output size smaller; #1879\n\n# version 1.0-7\n\n* `st_drop_geometry()` is a generic; #1914\n\n* `st_crs(x)$ud_unit` returns the unit of the coordinate reference system of `x`\n\n* geometric predicates return `sgbp` objects omitting self-intersections etc. by passing `remove_self = TRUE` and unique symmetric relationship by passing `retain_unique = TRUE` (to `...` if needed); this simplifies identifying (and removing) duplicated geometries; duplicates are identified by e.g. by `st_equals(x, retain_unique = TRUE) |> unlist() |> unique()`; #1893\n\n* fix compile issue against GDAL < 2.5.0 introduced in 1.0-6; #1899\n\n# version 1.0-6\n\n* adapt to new `spatstat.random` package; #1892\n\n* `st_geometry<-()` also allows to rename a geometry column in an `sf` object; #1890\n\n* for `sf` objects, the `st_as_sfc()` method is an alias for `st_geometry()`; #1882\n\n* `st_make_grid()` speeded up; #1579 thanks to Krzysztof Dyba\n\n* remove direct and indirect dependencies on `rgeos` and `rgdal`; #1869\n\n* use `stats::dist` rather than GEOS for symmetric point-point Euclidian distance computation; #1874\n\n# version 1.0-5\n\n* package startup message reports status of `sf_use_s2()`; #1782\n\n* `sf_use_s2()` uses `message()` to report a change; #1782\n\n* `st_sample()` using regular sampling for ellipsoidal coordinates \"works\" as if coordinates were Cartesian; #1837\n\n# version 1.0-4\n\n* new function `st_delete()` deletes a data source, or layer(s) within a data source; #1828\n\n* fix memory leak in `WKT1_ESRI` retrieval; #1690\n\n# version 1.0-3\n\n* cope with how GEOS >= 3.10.0 handles illegal geometries (e.g., non-closed rings); #1807\n\n* `crs` objects have a `$srid` method to extract the SRID (as authority \"name:code\"); #1804\n\n* `st_as_grob()` methods for `sfc_*` objects correctly handle empty geometries; #1789 with help from Hiroaki Yutani\n\n* when writing objects with `NA` as CRS to GeoPackage, assign \"Unknown Cartesian CRS\" first - this is in line with using Cartesian geometry operations for objects with `NA` as CRS; #1776\n\n* add coerce method from `sgbp` to `sparseMatrix`; #1750\n\n* fix `st_cast()` for `GEOMETRYCOLLECTIONS` containing empty geometries; #1767\n\n* fix `st_is_valid()` for bogus polygons and projected coordinates; #1666, #1760; #1761\n\n# version 1.0-2\n\n* `st_read()` and `st_write()` using GDAL handle binary attributes (OFTBinary fields) ; #1721\n\n* a `pivot_longer` method is added for `sf` objects (the `data.frame` method works, but raises a warning)\n\n* `rbind.sf` preserves primary geometry column; #1717\n\n* `configure` constrains using `--static` to `Darwin` platform; #1702, #1712, #1713\n\n* old-style `crs` objects created with sf < 0.9-0 generate a message, and will cause a warning in the future.\n\n* when `st_crs()` is called with a WKT2 as text input, its `input` field will be replaced with the CRS name (if it has one).\n\n* GEOS (>= 3.9.0) operations use `GEOSGeom_setPrecision_r` to set precision of geometries; #1535\n\n* `st_read()` with specified `query` ignores argument `layers`, and warns if it is given; #1444\n\n# version 1.0-1\n\n* fix regression in `st_intersection()`: when using s2 attributes were assigned wrongly; #1704\n\n* `crs` (sf) to `CRS` (sp) conversion no longer needs validation by `rgdal`; https://github.com/edzer/sp/issues/107\n\n* retrieve ESRI's WKT version of CRS by `st_crs(id)$WKT1_ESRI`; #1690 \n\n# version 1.0-0\n\n* add `s2` to Imports:\n\n* add Dewey Dunnington to contributors\n\n* `sf_use_s2()` prints a message when using s2 has been switched to on or off.\n\n* use `s2` spherical geometry as default when coordinates are ellipsoidal. This can\n  be switched off (defaulting to planar geometry, using GEOS, as in sf < 1.0-0) \n  by setting environment variable `_SF_USE_S2` to `false` before package `sf` \n  is loaded, or by `sf_use_s2(FALSE)`; #1649\n\n* `st_nearest_feature()` with missing `y` returns nearest features in the remaining set of `x`; https://github.com/r-spatial/s2/issues/111\n\n* `st_write()` gains an argument `config_options` to set GDAL config options; #1618\n\n* fix regression in `sf_project(..., keep = TRUE)`; #1635\n\n# version 0.9-8\n\n* add `st_as_sf()` method for terra's `SpatVector` class; #1567\n\n* `distinct.sf()` works by default on all variables, and keeps active geometry active; #1613\n\n* improve (fix?) polygonize/contour code; #1608\n\n* `sf_proj_network()` reports whether PROJ uses network (CDN) grids, can switch it on or off, and can set the CDN url.\n\n* `st_write()` returns obj, invisibly; #1597\n\n* fix regression in n-ary `st_intersection()`, #1595, introduced at #1549\n\n* `st_inscribed_circle()` computes the maximum inscribed circle for polygons (requires GEOS >= 3.9.0)\n\n* allow to `st_cast()` from COMPOUNDCURVE, MULTISURFACE or CURVEPOLYGON to GEOMETRYCOLLECTION, and back; #1573\n\n* Fixed a bug in `st_as_grob()` when plotting a mix of MULTI and non-MULTI geometries of the same base type\n\n# version 0.9-7\n\n* n-ary `st_intersection()` skips failing geometries, rather than returning an error; #1549\n\n* use `s2_centroid()` for geographical coordinates if `sf_use_s2()` is `TRUE`.\n\n* `st_as_text()` method for `crs` objects can return projjson (if GDAL >= 3.1.0 and PROJ > 6.2.0)\n\n* `st_transform()` no longer warns on conversions like `\"+proj=ob_tran +o_proj=longlat +o_lat_p=45 +o_lon_p=30\"`\n\n* `st_as_wkb()` takes `srid` from `wkt` field of `crs` when `input` field doesn't contain it; #1490\n\n* `plot.sf()` adds `key.pos=0` option to run the logic behind the key without plotting it; #1487\n\n* fix bug in `select.sf()` when selected variables were renamed; #1483\n\n* `st_as_sf.stars(..., merge = TRUE)` now works if CRS is `NA`; #1389\n\n* add (dynamically loaded) `as_wkb()` methods for `sf`, `sfc` and `sfg`, making `st_as_s2()` unnecessary\n\n* `st_as_s2()` transforms non-longlat objects to EPSG:4326 first\n\n# version 0.9-6\n\n* `gdal_utils()` print (GDAL-style) progress bar if `quiet = FALSE` (except for `info` and `mdiminfo`)\n\n* fix `CPL_gdal_warper` for multi bands; https://github.com/r-spatial/stars/issues/320\n\n* `sf_proj_search_paths()` retrieves and sets the proj search path (if GDAL > 3.0.3)\n\n* when loading sf, `sf_use_s2()` is set to `FALSE` unless environment variable `_SF_USE_S2` equals `true` (this changes to `TRUE` in sf 1.0-0)\n\n* resolve GDAL/PROJ version vulnerabilities in CRS-crs conversion; #1479\n\n* `st_sample()` gains an argument, `by_polygon`, to more clevery sample `MULTIPOLYGON` geometries; #1480\n\n* `st_sample()` accepts non-integer sample sizes, with a (suppressable) warning and handles values of sizes that would round to zero; #1480\n\n* `gdal_utils()` adds utils `mdiminfo` and `mdimtranslate` (requires GDAL >= 3.1)\n\n* `st_union()` gains an argument `is_coverage`, which, when set to `TRUE`, leads to much faster unioning in case features form a coverage (polygons don't overlap); #1462 by Don Baston\n\n* fix `gdal_utils(\"translate\")` locking input file; #1452\n\n* `st_make_grid()` no longer selects cells intersecting with `x`; #1447\n\n* use `s2::s2_dwithin_matrix()` in `st_is_within_distance()`; #1367\n\n# version 0.9-5\n\n* Only when package `s2` >= 1.0.1 is available: support for spherical geometry operators (predicates, transformers, measures, nearest point/feature) for geographic coordinates in package `s2` is now by default switched off, and can be switched on by `sf_use_s2(TRUE)`; see https://www.r-spatial.org/r/2020/06/17/s2.html and vignette sf7. It is planned to be switched on by default in sf 1.0-0.\n\n* drop Z and/or M coordinate in `st_as_s2()`, with message\n\n* geometry predicates and transformers gain an ... argument to pass `s2::s2_options()`\n\n* `dplyr::select()` now ensures the geometry column sticks to the back rather than the front of the data frame; #1425\n\n* `dplyr::rename()` now preserves the active geometry column even when it is renamed; #1431\n\n* proj units query adjusted to PROJ 7.1.0 release; #1434\n\n# version 0.9-4\n\n* empty geom generators take care of XYZ etc dim; #1400\n\n* `write_sf()` and `read_sf()` no longer warn when reading tables without geometries\n\n* `st_write()` writes non-spatial tables when given a plain `data.frame` or `tbl_df`; #1345\n\n* the default for `stringsAsFactors` in `st_read` and `st_sf` is `FALSE` for R version >= 4.1.0\n\n* the sf method for `dplyr::select()` supports renaming the geometry column; #1415\n\n# version 0.9-3\n\n* `st_is_valid()` is a generic\n\n* Windows CRAN binaries use GDAL 3.0.4, PROJ 6.3.1 and GEOS 3.8.0, thanks to Jeroen Ooms' rwinlib work; #1275\n\n* `plot.sf()` gains an `extent` argument to set the extent (xlim, ylim) of the plot; `extent` must be an object with an `st_bbox()` method, such as an `sf` or a `stars` object; #1193\n\n# version 0.9-2\n\n* `st_axis_order(TRUE)` gives and error if GDAL has version < 2.5.0\n\n* loading PROJ units `link`, `us_in`, `ind_yd`, `ind_ft`, and `ind_ch` into the udunits database is no longer done at package load time, but when function `sf_add_proj_units()` is called.\n\n* fix line sampling for small densities; #1365\n\n* `sf_project()` handles `crs` objects when PROJ version is below 6 using proj.4 string representations.\n\n* avoid using `isFALSE` in `st_write()`; #1342\n\n* fix regression in `gdal_utils(\"translate\", ...)`; #1339\n\n# version 0.9-1\n\n* fix an invalid read bug in `st_m_range()`; #1332\n\n* `st_crs(4326) == st_crs(\"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs\")` returns `TRUE` for GDAL >= 3.0, irrespective authority compliance of axis order; see #1331 and https://github.com/ropensci/scrubr/issues/34\n\n* `sf_project()` has a parameter `authority_compliant` to return coordinates in \"visualisation order\"; when `TRUE` it returns coordinates in authority compliant axis order (e.g. EPSG:4326 latitude longitude); default is `st_axis_order()`.\n\n* fix test for Solaris and certain GDAL/PROJ versions\n\n* fix error reading category table through GDAL; https://github.com/r-spatial/stars/issues/245\n\n# version 0.9-0\n\n* see r-spatial blog post: https://www.r-spatial.org/r/2020/03/17/wkt.html\n\n* modify `crs` objects to reflect our post-proj4string world (#1146; #1225): crs objects contain two fields, `input` with the user input (if any), and `wkt` with a well-known-text  (or WKT2) representation of the coordinate reference system. `crs` objects have a `$` method to dynamically retrieve the `epsg` (integer) or `proj4string` representation, using e.g. `x$epsg`.\n\n* support for PostGIS 3 using WKT and the new-style `crs` objects; #1234, #1303, #1308 by @etiennebr\n\n* `st_write_db()` and `st_read_db()` are defunct. Use `st_write` and `st_read` instead.\n\n* `st_write()` uses `append`, replacing (and deprecating) argument `update`; `st_write` fails when a layer already exists and `append` has not been set explicitly to `TRUE` (append) or `FALSE` (overwrite); #1266\n\n* `st_proj_info()` was renamed into `sf_proj_info`; `sf_proj_info` can get and set the PROJ data search path and use of CDN; #1277\n\n* adapt to new `dplyr` version; https://github.com/tidyverse/dplyr/issues/4917\n\n* `st_sample()` is a generic\n\n* write `stars` rasters with wkt info, rather than proj4strings\n\n* when GEOS >= 3.8.0, `st_make_valid` is provided by `sf` rather than by `lwgeom` #989\n\n* allow for single-sided buffers for linear geometries; #1001\n\n* add `st_reverse()` methods to reverse points in a linestring (requires GEOS >= 3.7.0); #1246\n\n* `st_make_grid()` returns grid cells or points that intersect with the target geometry, not its bounding box; #1260\n\n* allow for PROJ >= 7; #1254\n\n* `st_geometry_type()` accepts `by_geometry` argument; #1264\n\n# version 0.8-1\n\n* `st_as_sf.map()` no longer requires `maptools` and `sp`; dropped dependency on maptools.\n\n* work around a bug in 6.0.0 <= PROJ < 6.3.1: replace `+init=epsg:XXXX ...` strings with the `XXXX` EPSG integer, to work around a bug in PROJ; see https://github.com/OSGeo/PROJ/pull/1875 and links therein. If `...` arguments are present, raise a warning that these are ignored. \n\n* `st_as_sf.map()` no longer requires `maptools` and `sp`; drop dependency on maptools.\n\n* conversion between `spatstat` classes `owin`, `ppp` and `psp` and `sf` classes no longer use `maptools`; #1204\n\n* `gdal_utils()` processes open options `-oo` and `-doo` properly; https://github.com/ITSLeeds/geofabric/issues/12\n\n* `st_sample()` directly interfaces `spatstat` sampling methods, e.g. `type = \"Thomas\"` calls `spatstat::rThomas` after converting input arguments (window) and converts returned `ppp` object to `sf`'s `POINT` geometries; #1204 with help from Ege Rubak and Jakub Nowosad\n\n* `sf_project()` gains an option `keep = TRUE` to return `Inf` values for points not projectable; #1228\n\n* support `vctrs` methods for geometry list columns; this makes `unnest` work again (#1172); #1196 by Lionel Henry\n\n* `st_as_sf.pq_geometry()` converts binary geom columns from RPostgres::dbGetQuery; #1195\n\n* `st_cast()` can convert `MULTICURVE` to `MULTILINESTRING`; #1194\n\n* `st_read()` gains a parameter `wkt_filter` for spatially filtering the features to be read; #1192\n\n* `st_area()` and `st_length()` handle `+to_meter` argument in PROJ strings; #1170\n\n* add `st_filter()` generic for filtering on spatial features only; #1148\n\n* a new UBSAN error in `wkb_read()` was resolved; #1154, #1152\n\n* new method `st_shift_longitude()` to re-center data for a Pacific view. #1218\n\n* output of `st_as_text()` with `MULTIPOINT` has nested parentheses around points. E.g., `MULTIPOINT ((0 0), (1 1))` instead of `MULTIPOINT (0 0, 1 1)`; #1219, #1221\n\n# version 0.8-0\n\n* fix tests for PROJ 6.2.0 not accepting +units=\n\n* fixes for tidyr 1.0-0 release; attempt to port `nest.sf()` and `unnest.sf()`; #1068, #1145\n\n* `gdal_utils()` better closes connections after use; #1143\n\n* `st_write()` gains a `drivers` options, to limit the drivers attempted; #1142\n\n* rather than replacing, `st_write()` and `write_sf()` append to an existing layer if `update=TRUE`; #1126\n\n* improve plotting of `POSIXct` and `Date` attributes (`Date` requiring classInt >= 0.4-2)\n\n* `NULL` geometries read by GDAL are returned as empty geometries; #1119\n\n* `gdal_utils('rasterize', ...)` accepts non-existing destinations, defined by e.g. resolution and extent options (see #1116 for an example), and overwrites if needed (see #1136 for an example)\n\n* add Dan Baston as contributor; #1120 and many others\n\n* in addition to `NULL`, `st_sfc()` also converts `NA` values into empty geometries; #1114.\n\n* `st_join()` is a generic\n\n# version 0.7-7\n\n* `plot()` handles `POSIXct` values in legend\n\n* constructor functions like `st_linestring()` check and break on `NA` coordinates; #1101, #1102\n\n# version 0.7-6\n\n* have examples of `st_write` write only to the temporary R session directory\n\n# version 0.7-5\n\n* `as(x, \"Spatial\")` gives a proper error message on empty geometries; #1093\n\n* `st_cast()` takes care of empty polygons; #1094\n\n* `st_nearest_*` functions warn in case they are used with geographic coordinates; #1081\n\n* `st_union()` no longer segfaults on zero row `sf` objects; #1077\n\n* `st_transform()` no longer breaks on zero row `sf` objects; #1075\n\n* when PROJ >= 6.1.0 is available and sf comes with datum files (as is the case with statically linked Windows and OSX CRAN binaries), `PROJ_LIB` is no longer temporarily overwritten, but the PROJ C api is used to set the datum path; #1074, suggested by Jeroen Ooms\n\n* sf compiles against GDAL 3.x and PROJ 6.1.0, using the new `proj.h` interface; #1070\n\n* `st_distance()` returns `NA` for empty geometries, rather than 0; #1055\n\n# version 0.7-4\n\n* add example on how voronoi polygons can be tied back to the points they contain; #1030\n\n* `st_difference(x, y)`, with `x` an `sfc` with zero feature geometries, returns `x`; #1024\n\n* don't reset (base) plot device when `add = TRUE`\n\n* `==` and `!=` return `NA` when one of the operands is an empty geometry; #1013\n\n* `st_intersects()` is a generic\n\n* drop requiring `proj_api.h` in favor of `proj.h`, this enables compatibility to PROJ 6.0.0 and GDAL 2.5.0-dev; #988\n\n* fix regression in binary predicates introduced in #855; #999 reported by Barry Rowlingson\n\n* fix bug in `gdal_utils` util `warper` on certain GDAL/OS combinations; https://github.com/r-spatial/stars/issues/117\n\n* `c.sfc()` ignores the type (class) of empty `sfc` objects when choosing the result type; #985, #982\n\n* rename the default value for `distance` to `\"Euclidean\"`, rather than  `\"distance\"` in `st_distance()`\n\n# version 0.7-3\n\n* add argument `exact` to `st_sample()`, defaulting to `FALSE`; #896\n\n* fixed n-ary `st_difference()` for cases where geometries are entirely contained in others; #975, by Jonathan Marshall\n\n* faster `Ops.sfc()`, added `st_normalize()`; #973 by Thomas Lin Pedersen\n\n* new grob constructor for sfc objects; #971 by Thomas Lin Pedersen; add Thomas as contributor\n\n* add `group_split()` and `group_map()` methods for `sf` objects (experimental); #969\n\n* make `st_interpolate_aw()` a generic;\n\n* argument `col` for `plot` of `GEOMETRY` `sfc`'s is `NA` (open) for (multi) polygon geometries\n\n# version 0.7-2\n\n* feature IDs are no longer returned as names on the geometry list column, but optionally returned by `st_read` as attribute column; #812\n\n* when plotting multiple attributes, plot.sf adds a (single, common) key if `key.pos` is set\n\n* precision can be specified in distance units; #901\n\n* support log-scale in color legend by setting `logz` to `TRUE` in `plot.sf`\n\n* `st_intersects()` etc. will prepare `y` when `y` is polygons and `x` is points; #885 by Dan Baston\n\n* `st_write()` (and `write_sf()`) returns its first argument, invisibly; #889\n\n# version 0.7-1\n\n* fix bug that broke n-ary `st_intersection()` on platforms using clang; #867\n\n# version 0.7-0\n\n* adds several interfaces to GDAL functions, meant to be used by package `stars`\n\n* `st_read()` receives a `query` argument that can run queries against OGR datasets; #834, by Barry Rowlingson and Michael Sumner\n\n* `read_sf()` no longer first creates tibbles from `data.frame`s, but creates them directly; #853, db propagation by Etienne Racine\n\n* check difference between compile-time and run-time GEOS versions; #844\n\n* all GEOS routines are (more) robust against memory leaks, by using unique pointers; #822, #845, by Dan Baston\n\n* `st_buffer()` receives the buffer styles `endCapStyle`, `joinStyle` and `mitreLimit`; #833, #842 by Michael Sumner\n\n# version 0.6-4\n\n* `st_area()` is a generic; https://github.com/r-spatial/stars/issues/32\n\n* `st_write()` resolves `~` correctly; #456\n\n* read and write feature IDs as sfc list column names; #812\n\n* `st_centroid()` works for empty geometries, returning an empty point #769\n\n* add `st_nearest_points()`, to obtain the (`LINESTRING` connecting the) two nearest points for pairs of geometries; #788\n\n* add hexagonal tiling to `st_make_grid()`\n\n* add regular and hexagonal sampling to `st_sample()`\n\n* fixes for PROJ 5.0.1; #545\n\n* fixes for GDAL 2.3.0; #759\n\n* `st_sample()` supports regular sampling of `LINESTRING`; #725 by @statnmap \n\n* Support reading and writing of database `Pool` objects; #756\n\n* fix plotting of `sf` objects without attributes; #755\n\n* add reference to the [R Journal article](https://journal.r-project.org/articles/RJ-2018-009/index.html) in CITATION\n\n# version 0.6-3\n\n* move dependency `RPostgreSQL` from Imports: back to Suggests:\n\n* `st_centroid.sf()` and `st_point_on_surface.sf` also warn if attributes are not constant over geometries.\n\n* `summarise()` allows the user to define geometries for summaries; #714, by Kirill Mueller\n\n* `plot.sf()` emits a warning if `col` does not have length 1 or `nrow(x)`, and requires `pal` (rather than `col`) to set a palette for factors.\n\n* `plot.sf()` provides control over legend keys using `key.length` and `key.width`, decrease default key length; #731\n\n* `sgbp` objects receive an `as.data.frame` method; #715\n\n# version 0.6-2\n\n* GDAL read/write supports logical variables; #722\n\n* add `st_crop()` to simplify cropping objects with a rectangular area; #720\n\n* fix bug in `[<-` when columns are added to an `sf` object; #718\n\n* use dynamic registration of S3 methods, similar to how hms does this; #710 by Kirill Mueller\n\n* (partially) address writing GPKG to network drive, writing to temp file first; #628\n\n* add Kirill Mueller as contributor\n\n* `st_make_grid()` is faster; #708, by Dan Baston\n\n* `st_read()` and `st_write()` are generic, with methods for directly reading from and writing to database connections; `st_read_db` and `st_write_db` are deprecated; #558, thanks to Etienne Racine @etiennebr\n\n* Package `RPostgreSQL` moved from Suggests to Imports\n\n* restore compatibility with GDAL 2.0.x versions (which won't have `gdal_utils`); #686\n\n* `read_sf()` can also read tables without geometry; #684, by Andy Teucher\n\n# version 0.6-1\n\n* method `distinct()` works; #669, #672\n\n* `+`, `-`, `*` and `/` for pairs of geometries (`sfg`, `sfc`) return geometric union, difference, intersection and symmetric difference, respectively.\n\n* `st_cast()` from `MULTIPOLYGON` to `MULTILINESTRING` should work properly; #660\n\n* all Rcpp interfaces needed by package `stars` have been moved into `sf`; pkg `stars` is R-only, and only `sf` needs linking to GDAL.\n\n* `gdal_utils()` interfaces the 9 gdal utils using the C++ API\n\n* improve resetting (base) plots; add `reset = FALSE` in a call to `plot` to enable adding to plots that have a legend\n\n* `st_read()` returns a `data.frame` when a table contains no geometries, rather than giving an error; it does emit a warning in this case. See https://stat.ethz.ch/pipermail/r-sig-geo/2018-February/026344.html\n\n* move `pillar` from `Imports:` to `Suggests:`\n\n* update to the new rwinlib distribution of gdal (adds JPG2000); #639\n\n* speed up computation of centroids for largest polygon; #623\n\n* add `st_as_sfc.raw` method\n\n* Bugfix: binary operations (`st_intersection`, `st_difference`, etc) no longer fail when operating on data frames of class `\"tbl_df\"` with common column names; #644\n\n# version 0.6-0\n\n* add `pillar` to Imports: to provide method for printing WKT geometries in tibbles\n\n* `st_as_text`, and subsequently `format` and `print`, use argument `digits` (or `options(digits = n)`) to control the number of digits used for printing coordinates; default is `options(\"digits\")`, which is typically 7.\n\n* `st_is_within_distance` works with geographic coordinates\n\n* `st_cast` from `MULTIPOLYGON` to `MULTILINESTRING` no longer changes the number of features/feature geometries, but conversion from `MULTIPOLYGON` to `LINESTRING` (typically) does; #596\n\n* `st_distance` for long/lat geographic coordinates uses `lwgeom`, accepting all geometry types; argument `dist_fun` is deprecated as a consequence, and distance calculations are different from those in sf versions 0.5-5 or earlier; #593\n\n* add package `lwgeom` to Suggests; `st_area`, `st_length`, `st_distance`, `st_segmentize` for long/lat CRS use package `lwgeom` instead of `geosphere`; #593\n\n* `st_length` returns zero for polygon-type geometries; #593\n\n* if present, add units of attribute to default plot title; #591\n\n* add `unnest` method, which depends on `tidyr` > 0.7-2; #570 PR by @karldw\n\n* add `largest` option to `st_join` to get largest intersection match only; #547, by @tiernanmartin\n\n* change default maximum number of feature to print to 10, controllable by `options(sf_max_print)`; #556\n\n* add `Hausdorff` (and `Frechet` for those with GEOS 3.7.0) as options to `st_distance`; add `par` for densified versions\n\n* add `st_snap`, for snapping geometries to other geometries, within a tolerance\n\n* make `st_wrap_dateline` a generic, with methods for `sf`, `sfc` and `sfg`; #541\n\n* `plot.sf` and `st_as_grob` (used by ggplot2) are robust against misspecified ring directions (holes that have the same direction as the exterior rings), by using `rule = \"evenodd\"`; #540\n\n* functions depending on `liblwgeom` (`st_make_valid`, `st_geohash`, `st_plit`) have been moved to their own package, https://github.com/r-spatial/lwgeom; argument `use_gdal` of `st_transform` has been deprecated, instead one can use `lwgeom::st_transform_proj`; sf no longer tries to link to liblwgeom; #509, #537, #487\n\n* `st_read`, `st_sf` and `st_sfc` gain a parameter `check_ring_dir` (default: `FALSE`) that checks ring directions and corrects to: exterior counter clockwise, holes clockwise, when seen from above.\n\n* get rid of `classInt::classIntervals` warning if number of unique values is smaller than the number of breaks asked for\n\n# version 0.5-5\n\n* have `classInt` in Imports:, to not break other package checks\n\n* add vignettes 5: plotting sf objects and 6: miscellaneous; #324\n\n* add (default) color key to `plot.sf` if single map is plotted, contributed by @hughjonesd; #528 \n\n* `st_as_sfc` can read EWKT; #530\n\n* argument `max.plot` takes its default from `options(sf_max.plot=n)`, if present; #516\n\n* `plot.sf` gets an arguments `pal` to specify a color palette function; #526\n\n* `plot.sf` gets arguments `breaks` and `nbreaks`; add support for `classInt::classIntervals` styles for finding class intervals (using `breaks`)\n\n* add `st_as_sf` methods for `ppp`, `lpp` and `psp` objects from spatstat.\n\n* allow for direct route to proj.4 ignoring GDAL (requiring liblwgeom); #509, #511\n\n* add `print` method for `crs` objects; #517\n\n* `sf_extSoftVersion` reveals whether GDAL was linked to GEOS; #510\n\n* better check input of `st_polygon`; #514\n\n* add `st_node`, similar to `rgeos::gNode`\n\n* support for reading `OFTInteger64List` fields; #508\n\n* sparse geometric binary predicate lists have a class, `sgbp`, and attributes `region.id` and `predicate`; #234, #524\n\n* prevent `st_split` from stopping the R session; #492\n\n* `st_intersection`, `st_union` and so on also print a message when used directly on long/lat coordinates; #496\n\n* add `rep` method for `sfc` objects\n\n* comparing two `crs` objects uses the GDAL function `IsSame`; #180\n\n* add `st_collection_extract`, which, given an object with geometries of type `GEOMETRY` or `GEOMETRYCOLLECTION`, returns an object consisting only of elements of the specified type; by Andy Teucher, #482\n\n* `st_write` exports GeoJSON with UTF-8 encoding on Windows; #444\n\n* move package methods from Imports: to Depends: ; #478\n\n* deal better with precision setting and propagation; #476\n\n* fix bug in `st_layers` in case layers have no geometry; #334\n\n* clarify argument `envelope` in `st_voronoi`; #474\n\n* change aggregate to make it return the same geometry as 'by', padding attributes with NA where needed; #453 \n\n# version 0.5-4\n\n* fix compatibility problems introduced by `tidyr` 0.7-0 using rlang magic\n\n* convert path names to UTF-8 in `st_read`, `st_write` and `st_layers`; #471\n\n* `st_sfc` converts `NULL` values into empty geometries, and correctly identifies empty `POINT`s; #466, #463\n\n* `st_write` abbreviates column names if driver is `ESRI Shapefile`; #464\n\n* add `of_largest_polygon` argument to `st_centroid`, to get the centroid of the largest polygon; #450\n\n* fix use of `st_relate` as join predicate for `st_join`; #454\n\n* fix bug where `st_intersects` with empty second argument would crash; #458\n\n* produce better WKT; #463\n\n* fix bug in `st_cast.sf`; #461, #462\n\n* change `st_read` SRS assignment logic; corrects reading projected geojson with gdal 2.2.0; #449\n\n* `st_intersection` etc. on `tbl` also return `tbl`; #448\n\n* `[.sf` preserves class, e.g. of `tbl`; #448\n\n# version 0.5-3\n\n* support and propagate all Proj.4 +units=xx length units; #446\n\n* allow for arith ops on empty `sfc` objects\n\n* have `st_graticule` return an empty graticule object when argument `datum` is `NA`; \n\n* export `as_Spatial`, to make it easier for packages to convert `sfc` objects without importing `sf`\n\n* `st_distance` gains a parameter `by_element` to obtain pairwise distances; #437\n\n* add the ability to `aggregate` using a simple feature `by` argument; #429\n\n* make the `op` argument to `[.sf` work\n\n* speed up `st_coordinates` for `POINT` geometries; #433\n\n* fix performance regression for `st_bbox`; #418\n\n* correct bug in `st_union`, `st_difference` and `st_sym_difference` introduced in 0.5-2; #431\n\n* inform gdal about the CRS always through the proj4string, never through the epsg; see #424\n\n* properly deal with kilometre units; #424 (fixed by Karl Dunkle Werner)\n\n* add `st_is_within_distance`, only to return a sparse index matrix; #419\n\n* have `st_graticule` work with world2 (0,360); #421, #422, fixed by Ben Best\n\n* `st_graticule` to return graticules in native crs; https://github.com/tidyverse/ggplot2/issues/2200 (WIP)\n\n* `st_graticule` to support data in `NA_crs_`; https://github.com/tidyverse/ggplot2/issues/2199\n\n* fix bug when joining an sf-tibble with a `tibble`; #414\n\n* read gdal `StringList`, `RealList`, and `IntegerList` fields into a list-column; #416\n\n# version 0.5-2\n\n* made ready for rwinlib/gdal2; #408\n\n* make `[.sf` for selections including `NA` values like `x[c(1,NA,2)]`; #403\n\n* add a `[<-` method for `sfc` objects; automatically replaces `NULL` with an empty geometry; #411\n\n* add `st_point_on_surface()` to return a point that is guaranteed to be on the surface (standard compliance)\n\n* `read_sf` returns an sf-tibble, an object of class `c(\"sf\", \"tbl_df\", \"tbl\", \"data.frame\")`\n\n* work around for `dplyr::filter` not dispatching geometry column subsetting to `sf::[.sfc`\n\n* allow `units` object as `dist` argument to `st_buffer`; these must be convertable to `arc_degree` for geographic, and to a length unit for non-geographic data; #399\n\n* prevent gdal from crashing when trying to `st_transform` an empty geometry; #398\n\n* add `st_as_sfc` method for `bbox`, returning the bbox polygon; #377\n\n* strip file name extension from default layer name in `st_write`; #392\n\n* have `st_sf` replace `NULL` values in an `sfc` list-column with the appropriate empty geometry; #372\n\n* allow setting `ndiscr` through `ggplot2::coords_sf` to improve graticule plotting in `geom_sf`; #396\n\n# version 0.5-1\n\n* add spatial indexes to most binary geometry operations; #394 and http://r-spatial.org/r/2017/06/22/spatial-index.html\n\n* drastically reduce memory footprint of `st_intersection` and similar; #394\n\n* support RSQLite 2.0 by providing an `st_as_sfc` method for list columns of class `blob`\n\n* drop dependency on dbplyr\n\n# version 0.5-0\n\n* better handle empty/NULL geometries in shapefiles; #351\n\n* add `unite_.sf` method\n\n* deprecate `FUN` argument to `st_join`; #376\n\n* improve graticule tic label placement in `ggplot2`; #375 and https://github.com/tidyverse/ggplot2/issues/2119\n\n* improve `configure` logic to deal with libraries installed in custom locations; #335\n\n* fix bug where `geom_sf` wouldn't deal with Z and/or M geoms; #373\n\n* return more conveniently typed empty geoms; #372 \n\n* fix subsetting with `[` of `sf` using `drop = TRUE`, #370\n\n* in addition to `m`, allow `rad` units to `st_segmentize` \n\n* add example how to `st_read` GeoJSON from a string; #185\n\n* add `separate_.sf` method\n\n* add `st_split` to split geometries (only available if compiled against liblwgeom), #359\n\n* fix bug reading and writing dates (months 1 off): #358\n\n* [.sf and [.sfc also select on i when i is an `sfg` object, and accept a geometric predicate function with optional arguments; #352\n\n* on reading through GDAL, empty (NULL) geometries no longer result in an error; on creation, they no longer automatically give a `GEOMETRY` object; #351\n\n* on plotting with `ggplot2::geom_sf`, empty geometries no longer break; grid functions return `nullGrob()` for them; #351\n\n* arith operations on empty geometries no longer break or give warnings; #351\n\n* have `st_as_sf.data.frame` by default break on `NA` values in coordinates; #342\n\n* have `st_join` accept further arguments, to be passed on to the `join` function (e.g. a pattern for `st_relate`)\n\n* have WKB reader throw an error on (some) malformed inputs, and check for buffer bounds\n\n# version 0.4-3\n\n* back-port `do_union` argument to dplyr <= 0.5.0, using lazyeval\n\n* all strings returned from OGR/GDAL get encoding set to `UTF-8`, making them work on non-UTF-8 platforms; #5\n\n* `$.crs` retrieves proj4string components, such as `st_crs(4326)$datum` in addition to `epsg` and `proj4string`\n\n* let `st_geohash` return geohash for (average) points (only when sf was linked to liblwgeom)\n\n# version 0.4-2\n\n* `summarise.sf` always returns an `sf` object, also for global (non-grouped) summaries.\n\n* `summarise.sf` gains an argument `do_union` which determines whether to union the geometries for which a summary is given, or to `st_combine` them (not resolving boundaries); #331\n\n* rename argument `union` of `aggregate.sf` into `do_union`, for consistency with `summarise`; #331\n\n* add a `nest_` method for `sf` objects\n\n* `st_relate` gets a `pattern` parameter, same as `rgeos::gRelate`; add examples to get rook and queen neighbour lists using this; #234\n\n* support for direct reading of spatialite and sqlite geometry wkb blobs\n\n* build proper support for `cbind` and `rbind` methods for `sf`, which work (as documented) when _all_ arguments are of class `sf`; `dplyr::bind_cols` or `st_sf(data.frame(sf, df))` work for binding `data.frame`s to an `sf` object.\n\n* `st_segmentize()` and `st_line_sample()` accept units arguments\n\n* document problem reading shapefiles from USB drives on OSX; #252\n\n* improve docs of `st_is_valid` and `st_make_valid`; #296\n\n* coercing `sf` to `data.frame` works better; #298\n\n* `st_line_sample` gains argument `sample` to specify the points t.b. sampled; #299 #300 thanks to @joethorley\n\n* add compatibility to upcoming dplyr 0.6.0; #304 #42\n\n* write GDAL fields by name, not by number, fixing a KML problem #308\n\n* `st_write` gains arguments `delete_layer` and `delete_dsn` to allow overwrite capability #307 #274\n\n* `write_sf` defaults to `delete_layer=TRUE`, silently overwriting layers if they're already present\n\n* compatibility with GDAL 2.2beta0; #303; #309\n\n* replace `st_write_db` with a version that is fast for large datasets (#285), thanks to Josh London\n\n* take out more memory leaking examples in tests\n\n* the `aggregate` method for `sf` objects assumes the `by` argument to be identical to that of `stats::aggregate`\n\n* `st_wrap_dateline` wraps (cuts up) geometries crossing the antimeridian, such that they no longer cross it.\n\n# version 0.4-1\n\n* restore 3.3.0 and c++11 requirement\n\n* `st_read` respects time that is read as UTC\n\n* `st_write` writes time always as UTC, since GDAL does not have a mechanism to define local timezones other than \"unknown\" or \"local\"\n\n* `st_length` works for POINT and MULTIPOINT (returning 0); POLYGON and MULTIPOLYGON are converted to MULTILINESTRING before computing length, thus giving polygon perimeter (#268)\n\n* `st_write` has `update` depend on driver; for databases, the default is `TRUE`, otherwise `FALSE` (it refers to update of the database, and not to overwriting the table in the database, this will by default not succeed); #274\n\n* `st_read` supports reading objects with multiple geometry columns #257 #255\n\n* support writing (exporting) objects with non-standard columns, such as `units` or `POSIXlt` #264\n\n* catch dependencies on GEOS 3.3.5 (hence no 0.4-0 CRAN binary for MacOSX) #260\n\n# version 0.4-0\n\n* have `st_is_valid` catch corrupt geometries too, returning `NA` in that case (requiring GEOS 3.5.0)\n\n* add `st_make_valid`, only available when sf was linked to `liblwgeom`\n\n* add `st_coordinates` method, returning coordinates matrix with indexes\n\n* remove `unlist.sfg` \n\n* add `as.matrix.sfg`; have as.matrix.sfg add indexes to coordinates\n\n* add `st_bind_cols` method\n\n* improve handling features that can't be projected \n\n* support uniform sampling over polygons on the sphere\n\n* add `st_sample`, for sampling points on multipoints, linestrings, or polygons\n\n* add `c` method for `sfc` objects\n\n* import and export `magrittr::%>%`\n\n* support ggplot'ing geometrycollections\n\n* drop C++11 requirement, allowing build for older R versions\n\n* add `st_proj_info`, modelled after `rgdal::projInfo`\n\n* overwriting datasets with `st_write()` is no longer allowed; `update=TRUE` appends to them, permitted the driver supports appending.\n\n* `st_write` gains an argument, `update`, which when `TRUE` will try to append to existing datasets (#204)\n\n* added list of corresponding function for migration from sp, rgdal and rgeos to sf at https://github.com/edzer/sfr/wiki/migrating\n\n* remove deprecated `st_list`\n\n* rename `st_makegrid` to `st_make_grid`, and `st_linemerge` to `st_line_merge`\n* add NEWS.md file (#207)\n\n* faster conversion of `data.frame` into `POINT` `sf` object, using `st_as_sf` (Michael Sumner)\n\n* `rbind` method for `sf` objects keeps coordinate reference system\n\n# version 0.3-4, Feb 6, 2017\n\n* add `st_contains_properly` spatial predicate\n\n* GEOS functions (geometry operations) accept XYZ geometries (and ignore Z)\n\n* make `prepared = TRUE` the default for all geometry binary operations\n\n# version 0.3-2, Feb 4, 2017\n\n* add user interrupt checks in all GEOS geometry operations\n\n* make `st_graticule` do something useful for polar projections\n\n* make `st_graticule` return `NA` labels when labels are useless\n\n* add `merge.sf` methods to merge `sf` object and `data.frame` (#193)\n\n* add `st_join` for table joins based on (user-defined) spatial predicates\n\n* add `dplyr`-style non-spatial joins for `sf` objects (`left_join`, `full_join` etc.) (#193)\n\n* allow for multiple non-gathered variables (#196)\n\n* add missing meridian to `st_graticule` (#198)\n\n# version 0.3-1, Jan 31, 2017\n\n* add `merge` method (#193)\n\n* `st_graticule` for laea (#198)\n\n* allow `st_buffer` with feature-dependent buffer distance (#197)\n\n* have `spread` return an `sf` object (#196)\n\n* clarify `overwrite = TRUE` in write docs\n\n* fix `st_as_sf.map` (#194)\n\n* add `prepared` arg to spatial binary predicates, to speed up large intersections\n\n* add `st_voronoi` interface (requires that lib GEOS >= 3.5.0)\n\n* add `st_as_sf` methods for `map` objects (library maps)\n\n* add RStudio project file\n\n* have `st_bbox` return a `bbox` object which has an `st_crs` method\n\n* rename `st_drop_zm` into `st_zm`, for general more handling of Z and M\n\n* allow for 3D coordinates returned, when `+proj=geocent` (#172; #103)\n\n* fix `NA_integer_` handling in shapefiles I/O (#184)\n\n* add and fix `st_agr` API, to set and get attribute-to-geometry relationships\n\n# version 0.2-8, Jan 5, 2017\n\n"
  },
  {
    "path": "PROPOSAL.md",
    "content": "# Simple Features for R\n\nApplicant: [Edzer Pebesma](https://github.com/edzer/), [Institute for Geoinformatics](https://www.uni-muenster.de/Geoinformatics/en/), University of Muenster, Germany; [edzer.pebesma@uni-muenster.de](mailto:edzer.pebesma@uni-muenster.de)\n\nSupporting authors: Edzer Pebesma, Roger Bivand, Michael Sumner, Robert Hijmans, Virgilio Gómez-Rubio\n\n[Simple features](https://en.wikipedia.org/wiki/Simple_Features) is an open ([OGC](https://www.ogc.org/standard/sfa/) and [ISO](https://www.iso.org/standard/40114.html)) interface standard for access and manipulation of spatial vector data (points, lines, polygons). It includes a standard [SQL schema](http://www.opengeospatial.org/standards/sfs) that supports storage, retrieval, query and update of feature collections via a SQL interface. All commonly used databases provide this interface. [GeoJSON](https://geojson.org/) is a standard for encoding simple features in JSON, and is used in JavaScript and MongoDB. Well-known-text ([WKT](https://en.wikipedia.org/wiki/Well-known_text)) is a text representation of simple features used often in linked data; well-known-binary ([WKB] (https://en.wikipedia.org/wiki/Well-known_text)) a standard binary representation used in databases. _Simple Feature Access_ defines coordinate reference systems, and makes it easy to move data from longitude-latitude to projections back and forth in a standardized way. \n\n\n[GDAL](https://gdal.org/) is an open source C++ library for reading and writing both raster and vector data with more than 225 drivers (supported file formats, data base connectors, web service interfaces). GDAL is used by practically all open source geospatial projects and by many industry products (including ESRI's ArcGIS, ERDAS, and FME). It provides coordinate transformations (built on top of PROJ.4) and geometric operations (e.g. polygon intersections, unions, buffers and distance). Standards for coordinate transformations change over time; such changes are typically adopted directly in GDAL/PROJ.4 but do not easily find their way into R-only packages such as `mapproj`.\n\nSince [2005](https://stat.ethz.ch/pipermail/r-sig-geo/2005-April/000378.html), CRAN has package [sp](https://cran.r-project.org/package=sp) which provides classes and methods for spatial (point, line, polygon and raster) data. The approach `sp` takes is similar to how `xts` and `zoo` handle the time index of time series data: objects store spatial geometries separately from associated attribute data, matching by order. Package [spacetime](https://cran.r-project.org/package=spacetime), on CRAN since 2010, extends both `sp` and `xts` to handle data that varies over both space and time.\n\nToday, 221 CRAN packages depend on, import or link to `sp`, 259 when including _Suggests_; when including recursive dependencies these numbers are 376 and 5040. The implementation of `sp` does not follow simple features, but rather the practice used at the time of release, following how ESRI shapefiles are implemented. The cluster of packages around `sp` is shown in Andrie de Vries' [blog on CRAN's network structure](https://blog.revolutionanalytics.com/2015/07/the-network-structure-of-cran.html) in green.\n\nOff-CRAN package [rgdal2](https://github.com/thk686/rgdal2) is an interface to GDAL 2.0, which uses raw pointers to interface features, but does not import any data in R, using GDAL to handle everything. CRAN Package [wkb](https://cran.r-project.org/package=wkb), contributed by Tibco Software, converts between WKB representations of several simple feature classes and corresponding classes in `sp`, and seems to be needed for Tibco software purposes.\n\n<!---\n[second edition](http://www.springer.com/statistics/life+sciences%2C+medicine+%26+health/book/978-1-4614-7617-7))\n-->\n\n## The problem\n\nThe problems we will solve are:\n\n1. R can currently not represent simple features directly. It can read most simple feature classes in `sp` classes, but uses its own representation for this, and can only write data back without loss of information if it is furnished with ancilliary metadata encoded in a comment attribute to each Polygons object. It does for instance internally not distinguish between `POLYGON` and `MULTIPOLYGON`  nor deal with several simple feature classes, including `TIN` and `GEOMETRYCOLLECTION`, nor handle `CURVE` geometries.\n2. The current implementation of lines and vector data in package `sp` is partly ambiguous (both slot `ringDir` or slot `hole` indicate whether a Polygon is a hole but are superceded by the comment attribute), complicated (to which exterior polygon does a hole belong - handled by the comment attribute), and by some considered difficult to work with (S4). The current implementation is hard to maintain because it contains incremental changes from a baseline that predated the industry-standard OGC/ISO ([Simple Feature Interface Specification](https://www.ogc.org/standard/sfa/)).\n3. The lack of support for simple features makes current interfaces to open source libraries (GDAL/OGR and PROJ.4: rgdal, GEOS: rgeos) difficult to understand and maintain, even though they work to specification.\n4. The current implementation has no [scale model](https://libgeos.org/doxygen/classgeos_1_1geom_1_1PrecisionModel.html#details) for coordinates.\n5. It is desirable that other R packages are offered the opportunity to migrate to more up-to-date libraries for coordinate transformations (providing proper support for datum transformation), and to avoid having to make simplifying assumptions (e.g., all spatial data come as longitude/latitude using datum `WGS84`; all web maps use [_web Mercator_](https://en.wikipedia.org/wiki/Web_Mercator)).\n\nWhich users will benefit from solving these problems?  It will mainly affect those who use data bases or modern javascript-based web APIs which largely converged on adopting simple features (such as [CartoDB](https://cartodb.com/)), as well as those who need a simpler and more light-weight handling of spatial data in R. It will also reduce the effort for users and developers to understand the way spatial information is represented in R, making it easier to build upon and reuse the R code for this, and lead to a good, sustainable shared R code base.\n\nIn the longer run it will affect users of all packages currently reusing `sp` classes, when we manage to migrate `sp` to exclusively use the simple feature classes for representing vector data. Since the recent [2.0](https://gdal.org/index.html) release of GDAL integrates raster and vector data, having an R package that mirrors its classes makes it possible to implement operations in-database (similar to what `DBI`, `RPostgreSQL` and `dplyr` do), making it possible for R to manipulate spatial data that do not fit in memory.\n\nBig Data analysis with R often proceeds by connecting R to a database that holds the data. All commonly used commercial and open source databases store spatial point, line and polygon data in the form of simple features. Representing simple features in R will simplify big data analysis for spatial data.\n\n## The plan\n\nWe want to solve the problem by carrying out the following steps (M1 refers to month 1):\n\n1. develop an R package that implements simple features in R, that is simple yet gives users access to the complete data, and includes an S3 representation that extends `data.frame` (M1-3)\n2. add to this package a C++ interface to GDAL 2.0, to read and write simple feature data, and to interface other functionality (coordinate transformation, geometry operations) (M3-8)\n3. develop and prototypically implement a migration path for sp to become compliant with simple features (M7-12)\n4. write user-oriented tutorial vignettes showing how to use it with files, data base connections, web API's, leaflet, ggmap, dplyr and so on (M7-10)\n5. write a tutorial vignette for R package writers reusing the package (M10)\n6. Collect and process community feed back (M6-12).\n\nFailure modes and recovery plan:\n\n1. Failure mode: S3 classes are too simple to represent simple\nfeatures class hierarchy. Recovery plan: try (i) using a list column\nwith geometry, and nested lists to represent nested structures; (ii) \nuse a `WKT` character column; (iii) using a `WKB` blob column\n\n2. Migrating `sp` breaks downstream packages. Recovery plan: involve\nRoger Bivand, Barry Rowlingson, Robert Hijmans (`raster`)\nand Tim Keitt (`rgdal`/`rgdal2`) how to proceed; be patient and\nsmooth out problems together with package maintainers.\n\n## How can the ISC help\n\nThe following table contains the cost items.\n\n| Item | Cost |\n| ---- | ---- |\n| employ a student assistant for one year (10 hrs/week) | &euro; 6500  |\n| one week visit of Roger Bivand to the Inst. for Geoinformatics | &euro; 1000 |\n| present the results at UseR! 2016 | &euro; 1500 |\n| Total: | &euro; 9000 (9750 USD) |\n\nThe visit of Roger is anticipated halfway the project; further communications will use skype. The project has a planned duration of 12 months.\n\n## Dissemination\n\nDevelopment will take place on github, information will be shared and reactions and contributions invited through [r-sig-geo](https://stat.ethz.ch/mailman/listinfo/r-sig-geo), as well as [StackOverflow](https://stackoverflow.com/) and [GIS StackExchange](https://gis.stackexchange.com/). The project will use an Apache 2.0 license for maximum dissemination (similar to GDAL, which uses X/MIT). The work will be published in 4 blogs (quarterly), announced on r-sig-geo (3300 subscribers), and intermediary results will be presented at [UseR! 2016](https://www.r-project.org/conferences/useR-2016/). The final result will be published in a paper either submitted to [The R Journal](https://journal.r-project.org/) or to the [Journal of Statistical Software](https://www.jstatsoft.org/index); this paper will be available before publication as a package vignette.\n\n## UseR! slides\n\nUseR! 2016 slides are found [here](https://pebesma.staff.ifgi.de/pebesma_sfr.pdf).\n"
  },
  {
    "path": "R/RcppExports.R",
    "content": "# Generated by using Rcpp::compileAttributes() -> do not edit by hand\n# Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393\n\nCPL_get_bbox <- function(sf, depth = 0L) {\n    .Call(`_sf_CPL_get_bbox`, sf, depth)\n}\n\nCPL_gdal_init <- function() {\n    invisible(.Call(`_sf_CPL_gdal_init`))\n}\n\nCPL_gdal_cleanup_all <- function() {\n    invisible(.Call(`_sf_CPL_gdal_cleanup_all`))\n}\n\nCPL_gdal_version <- function(what = \"RELEASE_NAME\") {\n    .Call(`_sf_CPL_gdal_version`, what)\n}\n\nCPL_crs_parameters <- function(crs) {\n    .Call(`_sf_CPL_crs_parameters`, crs)\n}\n\nCPL_crs_equivalent <- function(crs1, crs2) {\n    .Call(`_sf_CPL_crs_equivalent`, crs1, crs2)\n}\n\nCPL_crs_from_input <- function(input) {\n    .Call(`_sf_CPL_crs_from_input`, input)\n}\n\nCPL_roundtrip <- function(sfc) {\n    .Call(`_sf_CPL_roundtrip`, sfc)\n}\n\nCPL_circularstring_to_linestring <- function(sfc) {\n    .Call(`_sf_CPL_circularstring_to_linestring`, sfc)\n}\n\nCPL_multisurface_to_multipolygon <- function(sfc) {\n    .Call(`_sf_CPL_multisurface_to_multipolygon`, sfc)\n}\n\nCPL_compoundcurve_to_linear <- function(sfc) {\n    .Call(`_sf_CPL_compoundcurve_to_linear`, sfc)\n}\n\nCPL_curve_to_linestring <- function(sfc) {\n    .Call(`_sf_CPL_curve_to_linestring`, sfc)\n}\n\nCPL_can_transform <- function(src, dst) {\n    .Call(`_sf_CPL_can_transform`, src, dst)\n}\n\nCPL_transform <- function(sfc, crs, AOI, pipeline, reverse = FALSE, desired_accuracy = -1.0, allow_ballpark = TRUE) {\n    .Call(`_sf_CPL_transform`, sfc, crs, AOI, pipeline, reverse, desired_accuracy, allow_ballpark)\n}\n\nCPL_transform_bounds <- function(bb, crs_dst, densify_pts = 21L) {\n    .Call(`_sf_CPL_transform_bounds`, bb, crs_dst, densify_pts)\n}\n\nCPL_wrap_dateline <- function(sfc, opt, quiet = TRUE) {\n    .Call(`_sf_CPL_wrap_dateline`, sfc, opt, quiet)\n}\n\nCPL_get_gdal_drivers <- function(dummy) {\n    .Call(`_sf_CPL_get_gdal_drivers`, dummy)\n}\n\nCPL_sfc_from_wkt <- function(wkt) {\n    .Call(`_sf_CPL_sfc_from_wkt`, wkt)\n}\n\nCPL_gdal_with_geos <- function() {\n    .Call(`_sf_CPL_gdal_with_geos`)\n}\n\nCPL_axis_order_authority_compliant <- function(authority_compliant) {\n    .Call(`_sf_CPL_axis_order_authority_compliant`, authority_compliant)\n}\n\nCPL_compressors <- function() {\n    .Call(`_sf_CPL_compressors`)\n}\n\nCPL_area <- function(sfc) {\n    .Call(`_sf_CPL_area`, sfc)\n}\n\nCPL_gdal_dimension <- function(sfc, NA_if_empty = TRUE) {\n    .Call(`_sf_CPL_gdal_dimension`, sfc, NA_if_empty)\n}\n\nCPL_length <- function(sfc) {\n    .Call(`_sf_CPL_length`, sfc)\n}\n\nCPL_gdal_segmentize <- function(sfc, dfMaxLength = 0.0) {\n    .Call(`_sf_CPL_gdal_segmentize`, sfc, dfMaxLength)\n}\n\nCPL_gdal_linestring_sample <- function(sfc, distLst) {\n    .Call(`_sf_CPL_gdal_linestring_sample`, sfc, distLst)\n}\n\nCPL_get_layers <- function(datasource, options, do_count = FALSE) {\n    .Call(`_sf_CPL_get_layers`, datasource, options, do_count)\n}\n\nCPL_read_ogr <- function(datasource, layer, query, options, quiet, toTypeUser, fid_column_name, drivers, wkt_filter, promote_to_multi = TRUE, int64_as_string = FALSE, dsn_exists = TRUE, dsn_isdb = FALSE, width = 80L) {\n    .Call(`_sf_CPL_read_ogr`, datasource, layer, query, options, quiet, toTypeUser, fid_column_name, drivers, wkt_filter, promote_to_multi, int64_as_string, dsn_exists, dsn_isdb, width)\n}\n\nCPL_read_gdal_stream <- function(stream_xptr, datasource, layer, query, options, quiet, drivers, wkt_filter, dsn_exists, dsn_isdb, fid_column, width) {\n    .Call(`_sf_CPL_read_gdal_stream`, stream_xptr, datasource, layer, query, options, quiet, drivers, wkt_filter, dsn_exists, dsn_isdb, fid_column, width)\n}\n\nCPL_gdalinfo <- function(obj, options, oo, co) {\n    .Call(`_sf_CPL_gdalinfo`, obj, options, oo, co)\n}\n\nCPL_ogrinfo <- function(obj, options, oo, co, read_only = FALSE) {\n    .Call(`_sf_CPL_ogrinfo`, obj, options, oo, co, read_only)\n}\n\nCPL_gdaladdo <- function(obj, method, overviews, bands, oo, co, clean = FALSE, read_only = FALSE) {\n    .Call(`_sf_CPL_gdaladdo`, obj, method, overviews, bands, oo, co, clean, read_only)\n}\n\nCPL_gdalwarp <- function(src, dst, options, oo, doo, co, quiet = TRUE, overwrite = FALSE) {\n    .Call(`_sf_CPL_gdalwarp`, src, dst, options, oo, doo, co, quiet, overwrite)\n}\n\nCPL_gdalrasterize <- function(src, dst, options, oo, doo, co, overwrite = FALSE, quiet = TRUE) {\n    .Call(`_sf_CPL_gdalrasterize`, src, dst, options, oo, doo, co, overwrite, quiet)\n}\n\nCPL_gdaltranslate <- function(src, dst, options, oo, co, quiet = TRUE) {\n    .Call(`_sf_CPL_gdaltranslate`, src, dst, options, oo, co, quiet)\n}\n\nCPL_gdalfootprint <- function(src, dst, options, oo, co, quiet = TRUE) {\n    .Call(`_sf_CPL_gdalfootprint`, src, dst, options, oo, co, quiet)\n}\n\nCPL_gdalvectortranslate <- function(src, dst, options, oo, doo, co, quiet = TRUE) {\n    .Call(`_sf_CPL_gdalvectortranslate`, src, dst, options, oo, doo, co, quiet)\n}\n\nCPL_gdalbuildvrt <- function(src, dst, options, oo, co, quiet = TRUE) {\n    .Call(`_sf_CPL_gdalbuildvrt`, src, dst, options, oo, co, quiet)\n}\n\nCPL_gdaldemprocessing <- function(src, dst, options, processing, colorfilename, oo, co, quiet = TRUE) {\n    .Call(`_sf_CPL_gdaldemprocessing`, src, dst, options, processing, colorfilename, oo, co, quiet)\n}\n\nCPL_gdalnearblack <- function(src, dst, options, oo, doo, co, quiet = TRUE) {\n    .Call(`_sf_CPL_gdalnearblack`, src, dst, options, oo, doo, co, quiet)\n}\n\nCPL_gdalgrid <- function(src, dst, options, oo, co, quiet = TRUE) {\n    .Call(`_sf_CPL_gdalgrid`, src, dst, options, oo, co, quiet)\n}\n\nCPL_gdalmdiminfo <- function(obj, options, oo, co) {\n    .Call(`_sf_CPL_gdalmdiminfo`, obj, options, oo, co)\n}\n\nCPL_gdalmdimtranslate <- function(src, dst, options, oo, co, quiet = TRUE) {\n    .Call(`_sf_CPL_gdalmdimtranslate`, src, dst, options, oo, co, quiet)\n}\n\nCPL_gdal_warper <- function(infile, outfile, options, oo, doo, co, quiet = TRUE) {\n    .Call(`_sf_CPL_gdal_warper`, infile, outfile, options, oo, doo, co, quiet)\n}\n\nCPL_write_ogr <- function(obj, dsn, layer, driver, dco, lco, geom, dim, fids, ConfigOptions, quiet, append, delete_dsn = FALSE, delete_layer = FALSE, write_geometries = TRUE, width = 80L) {\n    .Call(`_sf_CPL_write_ogr`, obj, dsn, layer, driver, dco, lco, geom, dim, fids, ConfigOptions, quiet, append, delete_dsn, delete_layer, write_geometries, width)\n}\n\nCPL_delete_ogr <- function(dsn, layer, driver, quiet = TRUE) {\n    .Call(`_sf_CPL_delete_ogr`, dsn, layer, driver, quiet)\n}\n\nCPL_geos_binop <- function(sfc0, sfc1, op, par = 0.0, pattern = \"\", prepared = FALSE) {\n    .Call(`_sf_CPL_geos_binop`, sfc0, sfc1, op, par, pattern, prepared)\n}\n\nCPL_geos_binop_by_element <- function(sfc0, sfc1, op, par, pattern, prepared) {\n    .Call(`_sf_CPL_geos_binop_by_element`, sfc0, sfc1, op, par, pattern, prepared)\n}\n\nCPL_geos_is_valid_reason <- function(sfc) {\n    .Call(`_sf_CPL_geos_is_valid_reason`, sfc)\n}\n\nCPL_geos_make_valid <- function(sfc, method, keep_collapsed) {\n    .Call(`_sf_CPL_geos_make_valid`, sfc, method, keep_collapsed)\n}\n\nCPL_geos_is_valid <- function(sfc, NA_on_exception = TRUE) {\n    .Call(`_sf_CPL_geos_is_valid`, sfc, NA_on_exception)\n}\n\nCPL_geos_is_simple <- function(sfc) {\n    .Call(`_sf_CPL_geos_is_simple`, sfc)\n}\n\nCPL_geos_is_empty <- function(sfc) {\n    .Call(`_sf_CPL_geos_is_empty`, sfc)\n}\n\nCPL_geos_normalize <- function(sfc) {\n    .Call(`_sf_CPL_geos_normalize`, sfc)\n}\n\nCPL_geos_union <- function(sfc, by_feature = FALSE, is_coverage = FALSE) {\n    .Call(`_sf_CPL_geos_union`, sfc, by_feature, is_coverage)\n}\n\nCPL_geos_snap <- function(sfc0, sfc1, tolerance) {\n    .Call(`_sf_CPL_geos_snap`, sfc0, sfc1, tolerance)\n}\n\nCPL_geos_op <- function(op, sfc, bufferDist, nQuadSegs, dTolerance, preserveTopology, bOnlyEdges = 1L, endCapStyle = 0L, joinStyle = 0L, mitreLimit = 1L, singleside = 0L) {\n    .Call(`_sf_CPL_geos_op`, op, sfc, bufferDist, nQuadSegs, dTolerance, preserveTopology, bOnlyEdges, endCapStyle, joinStyle, mitreLimit, singleside)\n}\n\nCPL_geos_voronoi <- function(sfc, env, dTolerance = 0.0, bOnlyEdges = 1L) {\n    .Call(`_sf_CPL_geos_voronoi`, sfc, env, dTolerance, bOnlyEdges)\n}\n\nCPL_geos_op2 <- function(op, sfcx, sfcy) {\n    .Call(`_sf_CPL_geos_op2`, op, sfcx, sfcy)\n}\n\nCPL_geos_dist_by_element <- function(sfc0, sfc1, which, par) {\n    .Call(`_sf_CPL_geos_dist_by_element`, sfc0, sfc1, which, par)\n}\n\nCPL_geos_version <- function(runtime = FALSE, capi = FALSE) {\n    .Call(`_sf_CPL_geos_version`, runtime, capi)\n}\n\nCPL_geos_op2_by_element <- function(op, sfcx, sfcy) {\n    .Call(`_sf_CPL_geos_op2_by_element`, op, sfcx, sfcy)\n}\n\nCPL_geos_dist <- function(sfc0, sfc1, which, par) {\n    .Call(`_sf_CPL_geos_dist`, sfc0, sfc1, which, par)\n}\n\nCPL_geos_nearest_feature <- function(sfc0, sfc1) {\n    .Call(`_sf_CPL_geos_nearest_feature`, sfc0, sfc1)\n}\n\nCPL_geos_nearest_points <- function(sfc0, sfc1, pairwise) {\n    .Call(`_sf_CPL_geos_nearest_points`, sfc0, sfc1, pairwise)\n}\n\nCPL_transpose_sparse_incidence <- function(m, n) {\n    .Call(`_sf_CPL_transpose_sparse_incidence`, m, n)\n}\n\nCPL_nary_difference <- function(sfc) {\n    .Call(`_sf_CPL_nary_difference`, sfc)\n}\n\nCPL_nary_intersection <- function(sfc) {\n    .Call(`_sf_CPL_nary_intersection`, sfc)\n}\n\nCPL_line_project <- function(lines, points, normalized) {\n    .Call(`_sf_CPL_line_project`, lines, points, normalized)\n}\n\nCPL_line_interpolate <- function(lines, dists, normalized) {\n    .Call(`_sf_CPL_line_interpolate`, lines, dists, normalized)\n}\n\nCPL_hex_to_raw <- function(cx) {\n    .Call(`_sf_CPL_hex_to_raw`, cx)\n}\n\nCPL_raw_to_hex <- function(raw) {\n    .Call(`_sf_CPL_raw_to_hex`, raw)\n}\n\nCPL_read_mdim <- function(file, array_names, oo, offset, count, step, proxy = FALSE, debug = FALSE) {\n    .Call(`_sf_CPL_read_mdim`, file, array_names, oo, offset, count, step, proxy, debug)\n}\n\nCPL_write_mdim <- function(name, driver, dimensions, variables, wkt, xy, RootGroupOptions, CreationOptions, as_float = TRUE) {\n    .Call(`_sf_CPL_write_mdim`, name, driver, dimensions, variables, wkt, xy, RootGroupOptions, CreationOptions, as_float)\n}\n\nopp_sfc <- function(geom, value, mult, crs) {\n    .Call(`_sf_opp_sfc`, geom, value, mult, crs)\n}\n\nnormalize_sfc <- function(geom, min, range, crs) {\n    .Call(`_sf_normalize_sfc`, geom, min, range, crs)\n}\n\nCPL_polygonize <- function(raster, mask_name, raster_driver, vector_driver, vector_dsn, options, iPixValField, contour_options, use_contours = FALSE, use_integer = TRUE) {\n    .Call(`_sf_CPL_polygonize`, raster, mask_name, raster_driver, vector_driver, vector_dsn, options, iPixValField, contour_options, use_contours, use_integer)\n}\n\nCPL_rasterize <- function(raster, raster_driver, sfc, values, options, NA_value) {\n    .Call(`_sf_CPL_rasterize`, raster, raster_driver, sfc, values, options, NA_value)\n}\n\nCPL_proj_h <- function(b = FALSE) {\n    .Call(`_sf_CPL_proj_h`, b)\n}\n\nCPL_get_pipelines <- function(crs, authority, AOI, Use, grid_availability, accuracy = -1.0, strict_containment = FALSE, axis_order_auth_compl = FALSE) {\n    .Call(`_sf_CPL_get_pipelines`, crs, authority, AOI, Use, grid_availability, accuracy, strict_containment, axis_order_auth_compl)\n}\n\nCPL_get_data_dir <- function(from_proj = FALSE) {\n    .Call(`_sf_CPL_get_data_dir`, from_proj)\n}\n\nCPL_is_network_enabled <- function(b = FALSE) {\n    .Call(`_sf_CPL_is_network_enabled`, b)\n}\n\nCPL_enable_network <- function(url, enable = TRUE) {\n    .Call(`_sf_CPL_enable_network`, url, enable)\n}\n\nCPL_set_data_dir <- function(data_dir, with_proj) {\n    .Call(`_sf_CPL_set_data_dir`, data_dir, with_proj)\n}\n\nCPL_use_proj4_init_rules <- function(v) {\n    .Call(`_sf_CPL_use_proj4_init_rules`, v)\n}\n\nCPL_proj_version <- function(b = FALSE) {\n    .Call(`_sf_CPL_proj_version`, b)\n}\n\nCPL_proj_is_valid <- function(proj4string) {\n    .Call(`_sf_CPL_proj_is_valid`, proj4string)\n}\n\nCPL_have_datum_files <- function(foo) {\n    .Call(`_sf_CPL_have_datum_files`, foo)\n}\n\nCPL_proj_direct <- function(from_to, pts, keep, warn = TRUE, authority_compliant = FALSE) {\n    .Call(`_sf_CPL_proj_direct`, from_to, pts, keep, warn, authority_compliant)\n}\n\nCPL_proj_info <- function(type) {\n    .Call(`_sf_CPL_proj_info`, type)\n}\n\nCPL_xy2sfc <- function(cc, dim, to_points, which, cc_has_NAs) {\n    .Call(`_sf_CPL_xy2sfc`, cc, dim, to_points, which, cc_has_NAs)\n}\n\nsfc_is_null <- function(sfc) {\n    .Call(`_sf_sfc_is_null`, sfc)\n}\n\nsfc_unique_sfg_dims_and_types <- function(sfc) {\n    .Call(`_sf_sfc_unique_sfg_dims_and_types`, sfc)\n}\n\nsfc_is_empty <- function(sfc) {\n    .Call(`_sf_sfc_is_empty`, sfc)\n}\n\nsfc_is_full <- function(sfc) {\n    .Call(`_sf_sfc_is_full`, sfc)\n}\n\npoints_cpp <- function(pts, gdim = \"XY\") {\n    .Call(`_sf_points_cpp`, pts, gdim)\n}\n\nCPL_signed_area <- function(pts) {\n    .Call(`_sf_CPL_signed_area`, pts)\n}\n\nCPL_get_metadata <- function(obj, domain_item, options) {\n    .Call(`_sf_CPL_get_metadata`, obj, domain_item, options)\n}\n\nCPL_get_crs <- function(obj, options) {\n    .Call(`_sf_CPL_get_crs`, obj, options)\n}\n\nCPL_inv_geotransform <- function(gt_r) {\n    .Call(`_sf_CPL_inv_geotransform`, gt_r)\n}\n\nCPL_read_gdal <- function(fname, options, driver, read_data, NA_value, RasterIO_parameters, max_cells) {\n    .Call(`_sf_CPL_read_gdal`, fname, options, driver, read_data, NA_value, RasterIO_parameters, max_cells)\n}\n\nCPL_write_gdal <- function(x, fname, driver, options, Type, dims, from, gt, p4s, na_val, scale_offset, create = TRUE, only_create = FALSE) {\n    invisible(.Call(`_sf_CPL_write_gdal`, x, fname, driver, options, Type, dims, from, gt, p4s, na_val, scale_offset, create, only_create))\n}\n\nCPL_extract <- function(input, xy, interpolate) {\n    .Call(`_sf_CPL_extract`, input, xy, interpolate)\n}\n\nCPL_create <- function(file, nxy, value, wkt, xlim, ylim) {\n    invisible(.Call(`_sf_CPL_create`, file, nxy, value, wkt, xlim, ylim))\n}\n\nCPL_read_wkb <- function(wkb_list, EWKB = FALSE, spatialite = FALSE) {\n    .Call(`_sf_CPL_read_wkb`, wkb_list, EWKB, spatialite)\n}\n\nCPL_write_wkb <- function(sfc, EWKB = FALSE) {\n    .Call(`_sf_CPL_write_wkb`, sfc, EWKB)\n}\n\nCPL_get_z_range <- function(sf, depth) {\n    .Call(`_sf_CPL_get_z_range`, sf, depth)\n}\n\nCPL_get_m_range <- function(sf, depth) {\n    .Call(`_sf_CPL_get_m_range`, sf, depth)\n}\n\n# Register entry points for exported C++ functions\nmethods::setLoadAction(function(ns) {\n    .Call(`_sf_RcppExport_registerCCallable`)\n})\n"
  },
  {
    "path": "R/aggregate.R",
    "content": "#' aggregate an \\code{sf} object\n#'\n#' aggregate an \\code{sf} object, possibly union-ing geometries\n#' \n#' @note Does not work using the formula notation involving \\code{~} defined in \\link[stats]{aggregate}.\n#' \n#' @param x object of class \\link{sf}\n#' @param by either a list of grouping vectors with length equal to \\code{nrow(x)} (see \\link[stats]{aggregate}), or an object of class \\code{sf} or \\code{sfc} with geometries that are used to generate groupings, using the binary predicate specified by the argument \\code{join}\n#' @param FUN function passed on to \\link[stats]{aggregate}, in case \\code{ids} was specified and attributes need to be grouped\n#' @param ... arguments passed on to \\code{FUN}\n#' @param do_union logical; should grouped geometries be unioned using \\link{st_union}? See details.\n#' @param simplify logical; see \\link[stats]{aggregate}\n#' @param join logical spatial predicate function to use if \\code{by} is a simple features object or geometry; see \\link{st_join}\n#' @return an \\code{sf} object with aggregated attributes and geometries; additional grouping variables having the names of \\code{names(ids)} or are named \\code{Group.i} for \\code{ids[[i]]}; see \\link[stats]{aggregate}.\n#' @details In case \\code{do_union} is \\code{FALSE}, \\code{aggregate} will simply combine geometries using \\link{c.sfg}. When polygons sharing a boundary are combined, this leads to geometries that are invalid; see \\url{https://github.com/r-spatial/sf/issues/681}.\n#' @aliases aggregate\n#' @examples\n#' m1 = cbind(c(0, 0, 1, 0), c(0, 1, 1, 0))\n#' m2 = cbind(c(0, 1, 1, 0), c(0, 0, 1, 0))\n#' pol = st_sfc(st_polygon(list(m1)), st_polygon(list(m2)))\n#' set.seed(1985)\n#' d = data.frame(matrix(runif(15), ncol = 3))\n#' p = st_as_sf(x = d, coords = 1:2)\n#' plot(pol)\n#' plot(p, add = TRUE)\n#' (p_ag1 = aggregate(p, pol, mean))\n#' plot(p_ag1) # geometry same as pol\n#' # works when x overlaps multiple objects in 'by':\n#' p_buff = st_buffer(p, 0.2)\n#' plot(p_buff, add = TRUE)\n#' (p_ag2 = aggregate(p_buff, pol, mean)) # increased mean of second\n#' # with non-matching features\n#' m3 = cbind(c(0, 0, -0.1, 0), c(0, 0.1, 0.1, 0))\n#' pol = st_sfc(st_polygon(list(m3)), st_polygon(list(m1)), st_polygon(list(m2)))\n#' (p_ag3 = aggregate(p, pol, mean))\n#' plot(p_ag3)\n#' # In case we need to pass an argument to the join function:\n#' (p_ag4 = aggregate(p, pol, mean, \n#'      join = function(x, y) st_is_within_distance(x, y, dist = 0.3)))\n#' @export\naggregate.sf = function(x, by, FUN, ..., do_union = TRUE, simplify = TRUE,\n\t\tjoin = st_intersects) {\n\n\tif (inherits(by, \"sf\") || inherits(by, \"sfc\")) {\n\t\tif (inherits(by, \"sfc\"))\n\t\t\tby = st_sf(by)\n\t\ti = join(st_geometry(by), st_geometry(x))\n\t\tst_geometry(x) = NULL\n\t\t# dispatch to stats::aggregate:\n\t\ta = aggregate(x[unlist(i), , drop = FALSE],\n\t\t\tlist(rep(seq_len(nrow(by)), lengths(i))), FUN, ...)\n\t\tnrow_diff = nrow(by) - nrow(a)\n\n\t\tif (is.matrix(a[[2]])) # https://github.com/r-spatial/sf/issues/2375\n\t\t\ta = data.frame(a[1], as.data.frame(a[[2]]))\n\n\t\tif(nrow_diff > 0) {\n\t\t\ta_na = a[rep(NA, nrow(by)),] # 'top-up' missing rows\n\t\t\ta_na[a$Group.1,] = a\n\t\t\ta = a_na\n\t\t}\n\t\ta$Group.1 = NULL # remove\n\t\trow.names(a) = row.names(by)\n\t\tst_set_geometry(a, st_geometry(by))\n\t} else {\n\t\tcrs = st_crs(x)\n\t\tlst = lapply(split(st_geometry(x), by), function(y) do.call(c, y))\n\t\tgeom = do.call(st_sfc, lst[!sapply(lst, is.null)])\n\n\t\tif (do_union)\n\t\t\tgeom = st_union(st_set_precision(geom, st_precision(x)), by_feature = TRUE)\n\n\t\tst_geometry(x) = NULL\n\t\tx = aggregate(x, by, FUN, ..., simplify = simplify)\n\t\tst_geometry(x) = geom # coerces to sf\n\t\tst_crs(x) = crs\n\n\t\t# now set agr:\n\t\tgeoms = which(vapply(x, function(vr) inherits(vr, \"sfc\"), TRUE))\n\t\tagr_names = names(x)[-geoms]\n\t\tagr = rep(\"aggregate\", length(agr_names))\n\t\tnames(agr) = agr_names\n\t\t# which ones are identity variables?\n\t\tn = if (!is.null(names(by)))\n\t\t\tnames(by)\n\t\telse\n\t\t\tpaste0(\"Group.\", seq_along(by))\n\t\tagr[n] = \"identity\"\n\t\tst_set_agr(x, agr)\n\t}\n}\n\n#' Area-weighted interpolation or dasymetric mapping of polygon data\n#'\n#' Area-weighted interpolation or dasymetric mapping of polygon data\n#' @name interpolate_aw\n#' @param x object of class \\code{sf}, for which we want to aggregate attributes\n#' @param to object of class \\code{sf} or \\code{sfc}, with the target geometries\n#' @param extensive logical; if TRUE, the attribute variables are assumed to be spatially extensive (like population) and the sum is preserved, otherwise, spatially intensive (like population density) and the mean is preserved.\n#' @param na.rm logical; if `TRUE` remove features with `NA` attributes from `x` before interpolating\n#' @param ... ignored\n#' @param keep_NA logical; if \\code{TRUE}, return all features in \\code{to}, if \\code{FALSE} return only those with non-NA values (but with \\code{row.names} the index corresponding to the feature in \\code{to})\n#' @param include_non_intersected logical; for the case when `extensive=FALSE`, when set to `TRUE` divide by the target areas (including non-intersected areas), \n#' when `FALSE` divide by the sum of the source areas.\n#' @param weights character; name of column in `to` that indicates (extensive) weights, to be used instead of areas, for redistributing attributes in `x`; currently only works for `extensive=TRUE`.\n#' @details if `extensive` is `TRUE` and `na.rm` is set to `TRUE`, geometries with `NA` are effectively treated as having zero attribute values. Dasymetric mapping is obtained when `weights` are specified.\n#' @examples\n#' # example Area-weighted interpolation:\n#' nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\n#' g = st_make_grid(nc, n = c(10, 5))\n#' a1 = st_interpolate_aw(nc[\"BIR74\"], g, extensive = FALSE)\n#' sum(a1$BIR74) / sum(nc$BIR74) # not close to one: property is assumed spatially intensive\n#' a2 = st_interpolate_aw(nc[\"BIR74\"], g, extensive = TRUE)\n#' # verify mass preservation (pycnophylactic) property:\n#' sum(a2$BIR74) / sum(nc$BIR74)\n#' a1$intensive = a1$BIR74\n#' a1$extensive = a2$BIR74\n#' \\donttest{plot(a1[c(\"intensive\", \"extensive\")], key.pos = 4)}\n#' \n#' # example Dasymetric mapping:\n#' # load nr of addresses per 10 km grid cell, to proxy population -> birth density:\n#' grd.addr = system.file(\"gpkg/grd_addr.gpkg\", package=\"sf\") |> read_sf()\n#' xgrd.addr = grd.addr # copy for plotting\n#' xgrd.addr$ones[grd.addr$ones==0] = 1 # so that logz shows finite values\n#' \\donttest{plot(xgrd.addr, logz=TRUE, main = \"nr of addresses per cell\") # log scale}\n#' nc = st_transform(nc, st_crs(grd.addr))\n#' # avoid \"assumes attributes are constant or uniform over areas\" warnings:\n#' st_agr(nc) = c(BIR74 = \"constant\", BIR79 = \"constant\")\n#' st_agr(grd.addr) = c(ones = \"constant\")\n#' # dasymetric mapping\n#' bir.grd = st_interpolate_aw(nc[c(\"BIR74\",\"BIR79\")], extensive = TRUE, grd.addr, weights = \"ones\")\n#' xbir.grd = bir.grd # copy for plotting\n#' xbir.grd$BIR74[xbir.grd$BIR74 == 0] = 1 # so that logz shows finite values\n#' \\donttest{plot(xbir.grd[\"BIR74\"], logz = TRUE, main = \"redistributed birth counts, 1974-\")}\n#' # verify sums:\n#' apply(as.data.frame(bir.grd)[1:2], 2, sum)\n#' apply(as.data.frame(nc)[c(\"BIR74\", \"BIR79\")], 2, sum)\n#' # compare county-wise:\n#' st_agr(bir.grd) = c(BIR74 = \"constant\")\n#' aw = st_interpolate_aw(bir.grd[\"BIR74\"], st_geometry(nc), extensive = TRUE)\n#' plot(nc$BIR74, aw$BIR74, log = 'xy', xlab = 'county-value', ylab = 'area-w interpolated')\n#' abline(0,1)\n#' @export\nst_interpolate_aw = function(x, to, extensive, ...) UseMethod(\"st_interpolate_aw\")\n\n#' @export\n#' @name interpolate_aw\nst_interpolate_aw.sf = function(x, to, extensive, ..., keep_NA = FALSE, na.rm = FALSE,\n\t\tinclude_non_intersected = FALSE, weights = character(0)) {\n\n\tif (!inherits(to, \"sf\") && !inherits(to, \"sfc\")) {\n\t\tto <- try(st_as_sf(to))\n\t\tif (inherits(to, \"try-error\"))\n\t\t\tstop(\"st_interpolate_aw requires geometries in argument to\")\n\t}\n\tif (isTRUE(na.rm))\n\t\tx = x[! apply(is.na(x), 1, any),]\n\n\tif (length(weights)) {\n\t\tstopifnot(length(weights) == 1, is.character(weights), inherits(to, \"sf\"), weights %in% names(to))\n\t\treturn(dasymetric(x, to[weights], extensive, keep_NA, include_non_intersected))\n\t}\n\n\tif (! all_constant(x))\n\t\twarning(\"st_interpolate_aw assumes attributes are constant or uniform over areas of x\")\n\ti = st_intersection(st_geometry(x), st_geometry(to), dimensions = \"polygon\")\n\tidx = attr(i, \"idx\")\n\n\t# https://stackoverflow.com/questions/57767022/how-do-you-use-st-interpolate-aw-with-polygon-layers-that-legitimately-include-p\n\tgc = which(st_is(i, \"GEOMETRYCOLLECTION\"))\n\t# i[gc] = st_collection_extract(i[gc], \"POLYGON\") ## breaks if there are several POLYGONs in a GC\n\ti[gc] = do.call(c, lapply(i[gc], function(x) st_sfc(st_union(st_collection_extract(x, \"POLYGON\")))))\n\ttwo_d = which(st_dimension(i) == 2)\n\ti[two_d] = st_cast(i[two_d], \"MULTIPOLYGON\")\n\n\tx_st = st_set_geometry(x, NULL)[idx[,1],, drop=FALSE]   # create st table, remove geom\n\tif (any(!sapply(x_st, is.numeric)))\n\t\tstop(\"x contains non-numeric column(s)\")\n\tarea_i = try(st_area(i), silent = TRUE)\n\tif (inherits(area_i, \"try-error\"))\n\t\tarea_i <- st_area(st_make_valid(i)) # work-around for https://github.com/r-spatial/sf/issues/1810\n\tx_st$...area_st = unclass(area_i)\n\n\tx_st = if (extensive) {\n\t\t\t# compute area_s:\n\t\t\tx_st$...area_s = unclass(st_area(x))[idx[,1]]\n\t\t\tlapply(x_st, function(v) v * x_st$...area_st / x_st$...area_s)\n\t\t} else {\n\t\t\t# compute target area:\n\t\t\ttarget = if (include_non_intersected)\n\t\t\t\t\t\tsetNames(as.numeric(st_area(to)), seq_len(NROW(to))) # use all of \"to\"\n\t\t\t\t\telse\n\t\t\t\t\t\tsapply(split(area_i, idx[, 2]), sum) # sum \"to\" parts intersecting \"x\"\n\t\t\tdf = data.frame(area = target, idx = as.integer(names(target)))\n\t\t\tx_st$...area_t = merge(data.frame(idx = idx[,2]), df)$area\n\t\t\tlapply(x_st, function(v) v * x_st$...area_st / x_st$...area_t)\n\t\t}\n\tx_st = aggregate(x_st, list(idx[,2]), sum)\n\tdf = if (keep_NA) {\n\t\t\tix = rep(NA_integer_, length(to))\n\t\t\tix[x_st$Group.1] = seq_along(x_st$Group.1)\n\t\t\tst_sf(x_st[ix,], geometry = st_geometry(to))\n\t\t} else\n\t\t\tst_sf(x_st, geometry = st_geometry(to)[x_st$Group.1], row.names = x_st$Group.1)\n\t# clean up:\n\tdf$...area_t = df$...area_st = df$...area_s = df$Group.1 = NULL\n\tst_set_agr(df, \"aggregate\")\n}\n\ndasymetric = function(x, to, extensive, keep_NA, include_non_intersected) {\n\tstopifnot(isTRUE(extensive), !keep_NA, !include_non_intersected) # later...\n\tstopifnot(length(to) == 2)\n\tif (!inherits(to[[2]], \"sfc\"))\n\t\tto = to[2:1] # swap: geom last\n\ti = st_intersection(st_geometry(x), st_geometry(to), dimensions = \"polygon\")\n\tidx = attr(i, \"idx\")\n\tst_geometry(x) = NULL\n\tstopifnot(!(\"...x_s\" %in% names(x))) # avoid overwrite\n\tx = x[idx[,1], , drop=FALSE] # x attributes corresponding to each area of i\n\ti = st_set_geometry(x[idx[,1], , drop = FALSE], i) # add geometry\n\n\t# https://stackoverflow.com/questions/57767022/how-do-you-use-st-interpolate-aw-with-polygon-layers-that-legitimately-include-p\n\t# i[gc] = st_collection_extract(i[gc], \"POLYGON\") ## breaks if there are several POLYGONs in a GC\n\tgc = which(st_is(i, \"GEOMETRYCOLLECTION\"))\n\tif (length(gc)) {\n\t\tg = st_geometry(i)\n\t\tg[gc] = do.call(c, lapply(g[gc,], function(x) st_sfc(st_union(st_collection_extract(x, \"POLYGON\")))))\n\t\tst_geometry(i) = g\n\t}\n\ttwo_d = which(st_dimension(i) == 2)\n\tif (any(two_d)) {\n\t\tg = st_geometry(i)\n\t\tg[two_d] = st_cast(g[two_d], \"MULTIPOLYGON\")\n\t\tst_geometry(i) = g\n\t}\n\n\tx$...x_st = st_interpolate_aw(to, i, extensive = extensive)[[1]] # distribute weights over the intersection geometries\n\t# split according to source regions:\n\t# first copy over idx[,2], as split() will rearrange records\n\tx$...idx2 = idx[,2]\n\tspl = split(x, idx[,1])\n\t# reconstruct idx2:\n\tidx2 = do.call(c, lapply(spl, function(x) x$...idx2))\n\t# for each of the source regions, compute weighted sum\n\tspl = lapply(spl, function(u) {\n\t\t\tw = if ((s <- sum(u$...x_st)) == 0)\n\t\t\t\t\tNA_real_\n\t\t\t\telse\n\t\t\t\t\tu$...x_st / s\n\t\t\tu$...x_st = u$...idx2 = NULL # remove\n\t\t\tas.data.frame(lapply(u, function(v) v * w))\n\t\t})\n\tx = do.call(rbind, spl)\n\t# sum over the target regions:\n\t# x = aggregate(x, list(idx[,2]), sum)\n\tx = aggregate(x, list(idx2), sum)\n\tdf = if (keep_NA) {\n\t\t\tix = rep(NA_integer_, length(to))\n\t\t\tix[x$Group.1] = seq_along(x$Group.1)\n\t\t\tst_sf(x[ix,], geometry = st_geometry(to))\n\t\t} else\n\t\t\tst_sf(x, geometry = st_geometry(to)[x$Group.1], row.names = x$Group.1)\n\t# clean up:\n\tdf$Group.1 = NULL\n\tst_set_agr(df, \"aggregate\")\n}\n"
  },
  {
    "path": "R/agr.R",
    "content": "agr_levels = c(\"constant\", \"aggregate\", \"identity\")\n\n#' @name st_agr\n#' @details\n#' \\code{NA_agr_} is the \\code{agr} object with a missing value.\n#' @export\nNA_agr_ = factor(NA, levels = agr_levels)\n\n#' get or set relation_to_geometry attribute of an \\code{sf} object\n#'\n#' get or set relation_to_geometry attribute of an \\code{sf} object\n#' @name st_agr\n#' @param x object of class \\code{sf}\n#' @param ... ignored\n#' @export\nst_agr = function(x, ...) UseMethod(\"st_agr\")\n\n#' @export\nst_agr.sf = function(x, ...) {\n\tsfc_s = sapply(x, inherits, \"sfc\")\n\tnm = names(x)[!sfc_s]\n\tret = attr(x, \"agr\")[nm]\n\tif (is.null(names(ret)) || all(is.na(names(ret))))\n\t\tstructure(rep(NA_agr_, length(nm)), names = nm)\n\telse\n\t\tret\n}\n\n#' @export\nst_agr.character = function(x, ...) {\n\tstructure(factor(x, levels = agr_levels), names = names(x))\n}\n\n#' @export\nst_agr.factor = function(x, ...) {\n\tstopifnot(all(levels(x) == agr_levels))\n\tx\n}\n\n#' @export\nst_agr.default = function(x = NA_character_, ...) {\n\tif (is.data.frame(x) && !is.null(attr(x, \"agr\")))\n\t\tx = attr(x, \"agr\")\n\tstructure(st_agr(as.character(x)), names = names(x))\n}\n\n#' @name st_agr\n#' @param value character, or factor with appropriate levels; if named, names should correspond to the non-geometry list-column columns of \\code{x}\n#' @export\n`st_agr<-` = function(x, value) UseMethod(\"st_agr<-\")\n\n#' @export\n`st_agr<-.sf` = function(x, value) {\n\tstopifnot(is.character(value) || is.factor(value))\n\tsfc_s = sapply(x, inherits, \"sfc\")\n\t# nv = setdiff(names(x), attr(x, \"sf_column\"))\n\tnv = names(x)[!sfc_s]\n\tif (length(value) == 0)\n\t\tattr(x, \"agr\") = setNames(NA_agr_[0], character())\n\telse if (! is.null(names(value)) && length(value) == 1) { \n\t\t# as in: st_agr(x) = c(Group.1 = \"identity\"): replace one particular named\n\t\tif (!is.null(attr(x, \"agr\")))\n\t\t\tattr(x, \"agr\")[names(value)] = st_agr(value)\n\t\telse\n\t\t\tattr(x, \"agr\") = st_agr(value)\n\t} else {\n\t\tvalue = rep(st_agr(value), length.out = length(nv))\n\t\tif (! is.null(names(value)))\n\t\t\tvalue = value[match(nv, names(value))]\n\t\telse\n\t\t\tnames(value) = nv\n\t\tattr(x, \"agr\") <- value\n\t}\n \t#print(paste(\"vars: \", paste(nv, collapse=\",\"), \"value(s):\", paste(value, collapse = \",\")))\n \t#print(rlang::trace_back())\n#\ta = st_agr(x)\n#\tabsent = setdiff(names(x), c(na.omit(names(a)), attr(x, \"sf_column\")))\n#\tif (length(absent)) { # repair:\n#\t\ta[absent] = NA_agr_\n#\t\tnames(a[absent]) = absent\n#\t\tattr(x, \"agr\") = a[nv]\n#\t}\n\tx\n}\n\n#' @name st_agr\n#' @export\nst_set_agr = function(x, value) { \n\tif (!missing(value))\n\t\tst_agr(x) = value\n\telse { # needs repair?\n\t\tvalue = st_agr(x)\n\t\tif (any(is.na(names(value))) && length(value) == length(x) - 1) {\n\t\t\tnames(value) = setdiff(names(x), attr(x, \"sf_column\"))\n\t\t\tst_agr(x) = value\n\t\t}\n\t}\n\tx\n}\n\nsummarize_agr = function(x) {\n\tsu = summary(st_agr(x))\n\tsu = su[su > 0]\n\tpaste0(names(su), \" (\", su, \")\", collapse = \", \")\n}\n\nall_constant = function(x) {\n\tx = attr(x, \"agr\")\n\t!anyNA(x) && all(x %in% c(\"identity\", \"constant\"))\n}\n"
  },
  {
    "path": "R/arith.R",
    "content": "#' Arithmetic operators for simple feature geometries\n#' @name Ops\n#'\n#' @param e1 object of class \\code{sfg} or \\code{sfc}\n#' @param e2 numeric, or object of class \\code{sfg}; in case \\code{e1} is of class \\code{sfc} also an object of class \\code{sfc} is allowed\n#'\n#' @details in case \\code{e2} is numeric, +, -, *, /, %% and %/% add, subtract, multiply, divide, modulo, or integer-divide by \\code{e2}. In case \\code{e2} is an n x n matrix, * matrix-multiplies and / multiplies by its inverse. If \\code{e2} is an \\code{sfg} object, |, /, & and %/% result in the geometric union, difference, intersection and symmetric difference respectively, and \\code{==} and \\code{!=} return geometric (in)equality, using \\link{st_equals}. If `e2` is an `sfg` or `sfc` object, for operations `+` and `-` it has to have `POINT` geometries.\n#'\n#' If \\code{e1} is of class \\code{sfc}, and \\code{e2} is a length 2 numeric, then it is considered a two-dimensional point (and if needed repeated as such) only for operations \\code{+} and \\code{-}, in other cases the individual numbers are repeated; see commented examples.\n#'\n#' @details\n#' It has been reported (https://github.com/r-spatial/sf/issues/2067) that\n#' certain ATLAS versions result in invalid polygons, where the final point\n#' in a ring is no longer equal to the first point. In that case, setting\n#' the precisions with \\link{st_set_precision} may help.\n#' @return object of class \\code{sfg}\n#' @export\n#'\n#' @examples\n#' st_point(c(1,2,3)) + 4\n#' st_point(c(1,2,3)) * 3 + 4\n#' m = matrix(0, 2, 2)\n#' diag(m) = c(1, 3)\n#' # affine:\n#' st_point(c(1,2)) * m + c(2,5)\n#' # world in 0-360 range:\n#' if (require(maps, quietly = TRUE)) {\n#'  w = st_as_sf(map('world', plot = FALSE, fill = TRUE))\n#'  w2 = (st_geometry(w) + c(360,90)) %% c(360) - c(0,90)\n#'  w3 = st_wrap_dateline(st_set_crs(w2 - c(180,0), 4326)) + c(180,0)\n#'  plot(st_set_crs(w3, 4326), axes = TRUE)\n#' }\n#' (mp <- st_point(c(1,2)) + st_point(c(3,4))) # MULTIPOINT (1 2, 3 4)\n#' mp - st_point(c(3,4)) # POINT (1 2)\n#' opar = par(mfrow = c(2,2), mar = c(0, 0, 1, 0))\n#' a = st_buffer(st_point(c(0,0)), 2)\n#' b = a + c(2, 0)\n#' p = function(m) { plot(c(a,b)); plot(eval(parse(text=m)), col=grey(.9), add = TRUE); title(m) }\n#' o = lapply(c('a | b', 'a / b', 'a & b', 'a %/% b'), p)\n#' par(opar)\n#' sfc = st_sfc(st_point(0:1), st_point(2:3))\n#' sfc + c(2,3) # added to EACH geometry\n#' sfc * c(2,3) # first geometry multiplied by 2, second by 3\nOps.sfg <- function(e1, e2) {\n\n\tif (nargs() == 1) {\n\t\tswitch (.Generic,\n\t\t\t\"-\" = return(e1 * -1.0),\n\t\t\t\"+\" = return(e1),\n\t\t\tstop(paste(\"unary\", .Generic, 'not defined for \"sfg\" objects'))\n\t\t)\n\t}\n\n\tprd <- switch(.Generic, \"*\" = TRUE, \"/\" = TRUE, FALSE)\n\tpm  <- switch(.Generic, \"+\" = , \"-\" = TRUE, FALSE)\n\tmod <- switch(.Generic, \"%%\" = TRUE, \"%/%\" = TRUE, FALSE)\n\tset <- switch(.Generic, \"&\" = TRUE, \"|\" = TRUE, FALSE)\n\tlgcl <- switch(.Generic, \"==\" = TRUE, \"!=\" = TRUE, FALSE)\n\n\tif (!(prd || pm || mod || set || lgcl))\n\t\tstop(paste(\"operation\", .Generic, \"not supported for sfg objects\"))\n\n\te1_empty = st_is_empty(e1)\n\te2_empty = inherits(e2, \"sfg\") && st_is_empty(e2)\n\tif (lgcl && (e1_empty || e2_empty))\n\t\treturn(NA)\n\n\tif (e1_empty && (.Generic %in% c(\"*\", \"+\", \"-\", \"%%\")))\n\t\treturn(e1)\n\n\tif (inherits(e2, \"sfg\")) {\n\t\te2 = switch(.Generic,\n\t\t\t\"|\" = st_union(e1, e2),\n\t\t\t\"/\" = st_difference(e1, e2),\n\t\t\t\"&\" = st_intersection(e1, e2),\n\t\t\t\"%/%\" = st_sym_difference(e1, e2),\n\t\t\t\"==\" = length(st_equals(e1, e2)[[1]]) != 0,\n\t\t\t\"!=\" = length(st_equals(e1, e2)[[1]]) == 0,\n\t\t\tunclass(e2))\n\t\tif (inherits(e2, \"sfg\") || is.logical(e2))\n\t\t\treturn(e2)\n\t}\n\n\tdims = nchar(class(e1)[1])\n\tVec = rep(0, dims)\n\tMat = matrix(0, dims, dims)\n\tdiag(Mat) = 1\n\tif (pm || mod) {\n\t\tif (length(e2) == 1)\n\t\t\tVec = rep(e2, length.out = dims)\n\t\telse\n\t\t\tVec = e2\n\t\tif (.Generic == \"-\")\n\t\t\tVec = -Vec\n\t} else if (prd) {\n\t\tif (length(e2) == 1 || length(e2) == dims)\n\t\t\tdiag(Mat) = e2\n\t\telse\n\t\t\tMat = e2\n\t\tif (.Generic == \"/\")\n\t\t\tMat = solve(Mat) # inverse\n\t}\n\n\tif_pt = function(x, y) { if(inherits(x, \"POINT\")) as.vector(y) else y }\n\tfn = if (prd)\n\t\t\tfunction(x, Mat, Vec) structure(if_pt(x, x %*% Mat), class = class(x))\n\t\telse if (pm)\n\t\t\tfunction(x, Mat, Vec) structure(if_pt(x, unclass(x) + conform(Vec, x)), class = class(x))\n\t\telse # mod:\n\t\t\tfunction(x, Mat, Vec) structure(if_pt(x, unclass(x) %% conform(Vec, x)), class = class(x))\n\n\tif (is.list(e1))\n\t\trapply(e1, fn, how = \"replace\", Mat = Mat, Vec = Vec)\n\telse\n\t\tfn(e1, Mat, Vec)\n}\n\nconform = function(vec, m) {\n\tif (is.matrix(m))\n\t\tt(matrix(vec, ncol(m), nrow(m)))\n\telse\n\t\tvec\n}\n\n#' @export\n#' @name Ops\n#' @examples\n#' nc = st_transform(st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\")), 32119) # nc state plane, m\n#' b = st_buffer(st_centroid(st_union(nc)), units::set_units(50, km)) # shoot a hole in nc:\n#' plot(st_geometry(nc) / b, col = grey(.9))\nOps.sfc <- function(e1, e2) {\n\n\tif (length(e1) == 0) # empty set\n\t\treturn(e1)\n\n\tif (is.numeric(e2) && !is.matrix(e2) && length(e2) <= 2 && .Generic %in% c(\"+\", \"-\")) {\n\t\tif (.Generic == \"-\")\n\t\t\te2 <- -e2\n\t\treturn(opp_sfc(e1, as.numeric(e2), 0L, NA_crs_))\n\t} else if (.Generic %in% c(\"*\", \"/\") && is.numeric(e2) && (length(e2) == 1 || (is_only_pos_diag(e2)))) {\n\t\tif (is.matrix(e2)) e2 <- diag(e2)\n\t\tif (.Generic == \"/\")\n\t\t\te2 <- 1 / e2\n\t\treturn(opp_sfc(e1, as.numeric(e2), 1L, NA_crs_))\n\t}\n\tif ((is.matrix(e2) && ncol(e2) == 2) || (is.numeric(e2) && length(e2) == 2))\n\t\te1 = st_zm(e1) # drop z and/or m\n\n\tif (!is.list(e2) && ((.Generic %in% c(\"+\", \"-\") && length(e2) == 2) || is.matrix(e2)))\n\t\te2 = list(e2)\n\n\tret = switch(\n\t\t.Generic,\n\t\t\"&\"   =  mapply(function(x, y) { x  & y }, e1, e2, SIMPLIFY = FALSE),\n\t\t\"|\"   =  mapply(function(x, y) { x  | y }, e1, e2, SIMPLIFY = FALSE),\n\t\t\"%/%\" =  mapply(function(x, y) { x %/% y}, e1, e2, SIMPLIFY = FALSE),\n\t\t\"/\"   =  mapply(function(x, y) { x  / y }, e1, e2, SIMPLIFY = FALSE),\n\t\t\"!=\"  =  mapply(function(x, y) { x != y }, e1, e2, SIMPLIFY = TRUE),\n\t\t\"==\"  =  mapply(function(x, y) { x == y }, e1, e2, SIMPLIFY = TRUE),\n\t\t\"*\"   =  mapply(function(x, y) { x  * y }, e1, e2, SIMPLIFY = FALSE),\n\t\t\"+\"   =  mapply(function(x, y) { x  + y }, e1, e2, SIMPLIFY = FALSE),\n\t\t\"-\"   =  mapply(function(x, y) { x  - y }, e1, e2, SIMPLIFY = FALSE),\n\t\t\"%%\"  =  mapply(function(x, y) { x %% y }, e1, e2, SIMPLIFY = FALSE),\n\t\tstop(paste(\"operation\", .Generic, \"not supported\")))\n\n\tif (!(.Generic %in% c(\"!=\", \"==\"))) {\n\t\tcrs = if (.Generic %in% c(\"&\", \"|\", \"%/%\", \"/\") && inherits(e2, c(\"sfc\", \"sfg\"))) # retain:\n\t\t\tst_crs(e1)\n\t\telse # geometry got displaced:\n\t\t\tNA_crs_\n\t\tst_sfc(ret, crs = crs, precision = attr(e1, \"precision\"), recompute_bbox = TRUE) # also check_ring_dir, if polygons? #2377\n\t} else\n\t\tret\n}\n\nis_only_pos_diag <- function(x) {\n\tis.matrix(x) && all(`diag<-`(x, 0) == 0) && all(diag(x) >= 0) # nocov\n}\n"
  },
  {
    "path": "R/bbox.R",
    "content": "\n#' @name st_bbox\n#' @param x object of class \\code{bbox}\n#' @export\nis.na.bbox = function(x) identical(x, NA_bbox_)\n\nbb_wrap = function(bb) {\n\tstopifnot(is.numeric(bb), length(bb) == 4)\n\tstructure(as.double(bb), names = c(\"xmin\", \"ymin\", \"xmax\", \"ymax\"), class = \"bbox\")\n}\n\nbbox.Set = function(obj, ...) {\n\tsel = !sfc_is_empty(obj)\n\tif (! any(sel))\n\t\tNA_bbox_\n\telse\n\t\tbb_wrap(CPL_get_bbox(unclass(obj)[sel], 0))\n}\nbbox.Mtrx = function(obj, ...) {\n\tif (length(obj) == 0)\n\t\tNA_bbox_\n\telse\n\t\tbb_wrap(CPL_get_bbox(list(obj), 1)) # note the list()\n}\nbbox.MtrxSet = function(obj, ...) {\n\tif (length(obj) == 0)\n\t\tNA_bbox_\n\telse\n\t\tbb_wrap(CPL_get_bbox(obj, 1))\n}\nbbox.MtrxSetSet = function(obj, ...) {\n\tif (length(obj) == 0)\n\t\tNA_bbox_\n\telse\n\t\tbb_wrap(CPL_get_bbox(obj, 2))\n}\nbbox.MtrxSetSetSet = function(obj, ...) {\n\tif (length(obj) == 0)\n\t\tNA_bbox_\n\telse\n\t\tbb_wrap(CPL_get_bbox(obj, 3))\n}\n\n#' Return bounding of a simple feature or simple feature set\n#'\n#' Return bounding of a simple feature or simple feature set\n#' @param obj object to compute the bounding box from\n#' @param ... for format.bbox, passed on to \\link[base]{format} to format individual numbers\n#' @export\n#' @return a numeric vector of length four, with \\code{xmin}, \\code{ymin}, \\code{xmax}\n#' and \\code{ymax} values; if \\code{obj} is of class \\code{sf}, \\code{sfc}, \\code{Spatial} or \\code{Raster}, the object\n#' returned has a class \\code{bbox}, an attribute \\code{crs} and a method to print the\n#' bbox and an \\code{st_crs} method to retrieve the coordinate reference system\n#' corresponding to \\code{obj} (and hence the bounding box). \\link{st_as_sfc} has a\n#' methods for \\code{bbox} objects to generate a polygon around the four bounding box points.\n#' @name st_bbox\n#' @examples\n#' a = st_sf(a = 1:2, geom = st_sfc(st_point(0:1), st_point(1:2)), crs = 4326)\n#' st_bbox(a)\n#' st_as_sfc(st_bbox(a))\nst_bbox = function(obj, ...) UseMethod(\"st_bbox\")\n\n#' @export\n#' @name st_bbox\nst_bbox.POINT = function(obj, ...) bb_wrap(c(obj[1L], obj[2L], obj[1L], obj[2L]))\n#' @export\n#' @name st_bbox\nst_bbox.MULTIPOINT = bbox.Mtrx\n#' @export\n#' @name st_bbox\nst_bbox.LINESTRING = bbox.Mtrx\n#' @export\n#' @name st_bbox\nst_bbox.POLYGON = function(obj, ...) if (st_is_full(obj)) FULL_bbox_ else bbox.MtrxSet(obj)\n#' @export\n#' @name st_bbox\nst_bbox.MULTILINESTRING = bbox.MtrxSet\n#' @export\n#' @name st_bbox\nst_bbox.MULTIPOLYGON = bbox.MtrxSetSet\n\nbbox_list = function(obj, ...) {\n\ts = vapply(obj, st_bbox, c(0.,0.,0.,0.)) # dispatch on class\n\tif (length(s) == 0 || all(is.na(s[1L,])))\n\t\tNA_bbox_\n\telse\n\t\tbb_wrap(c(min(s[1L,], na.rm = TRUE), min(s[2L,], na.rm = TRUE),\n\t\t  max(s[3L,], na.rm = TRUE), max(s[4L,], na.rm = TRUE)))\n}\n\n#' @name st_bbox\n#' @export\nst_bbox.GEOMETRYCOLLECTION = bbox_list\n\n#' @name st_bbox\n#' @export\nst_bbox.MULTISURFACE = bbox_list\n\n#' @name st_bbox\n#' @export\nst_bbox.MULTICURVE = bbox_list\n\n#' @name st_bbox\n#' @export\nst_bbox.CURVEPOLYGON = bbox_list\n\n#' @name st_bbox\n#' @export\nst_bbox.COMPOUNDCURVE = bbox_list\n\n#' @name st_bbox\n#' @export\nst_bbox.POLYHEDRALSURFACE = bbox.MtrxSetSet\n\n#' @name st_bbox\n#' @export\nst_bbox.TIN = bbox.MtrxSetSet\n\n#' @name st_bbox\n#' @export\nst_bbox.TRIANGLE = bbox.MtrxSet\n\n#' @name st_bbox\n#' @export\nst_bbox.CIRCULARSTRING = function(obj, ...) {\n\t# this is of course wrong:\n\tst_bbox(st_cast(obj, \"LINESTRING\"))\n}\n\n#' @export\nprint.bbox = function(x, ...) {\n\tx = structure(x, crs = NULL, class = NULL)\n\tprint(set_units(x, attr(x, \"units\"), mode = \"standard\"), ...)\n}\n\ncompute_bbox = function(obj) {\n\tswitch(class(obj)[1],\n\t\tsfc_POINT = bb_wrap(bbox.Set(obj)),\n\t\tsfc_MULTIPOINT = bb_wrap(bbox.MtrxSet(obj)),\n\t\tsfc_LINESTRING = bb_wrap(bbox.MtrxSet(obj)),\n\t\tsfc_POLYGON = if (any(st_is_full(obj))) FULL_bbox_ else bb_wrap(bbox.MtrxSetSet(obj)),\n\t\tsfc_MULTILINESTRING = bb_wrap(bbox.MtrxSetSet(obj)),\n\t\tsfc_MULTIPOLYGON = bb_wrap(bbox.MtrxSetSetSet(obj)),\n\t\tbbox_list(obj)\n\t)\n}\n\n#' @name st_bbox\n#' @export\nst_bbox.sfc = function(obj, ...) structure(attr(obj, \"bbox\"), crs = st_crs(obj))\n\n#' @name st_bbox\n#' @export\nst_bbox.sf = function(obj, ...) st_bbox(st_geometry(obj))\n\n#' @name st_bbox\n#' @export\nst_bbox.Spatial = function(obj, ...) {\n\tif (!requireNamespace(\"sp\", quietly = TRUE))\n\t\tstop(\"package sp required, please install it first\")\n\tbb = sp::bbox(obj)\n\tstructure(bb_wrap(c(bb[1,1],bb[2,1],bb[1,2],bb[2,2])),\n\t\tcrs = st_crs(slot(obj, \"proj4string\")))\n}\n\n#' @name st_bbox\n#' @export\nst_bbox.Raster = function(obj, ...) {\n\tif (!requireNamespace(\"sp\", quietly = TRUE))\n\t\tstop(\"package sp required, please install it first\")\n\tif (!requireNamespace(\"raster\", quietly = TRUE))\n\t\tstop(\"package raster required, please install it first\")\n\tbb = sp::bbox(obj)\n\tstructure(bb_wrap(c(bb[1,1],bb[2,1],bb[1,2],bb[2,2])),\n\t\tcrs = st_crs(sp::proj4string(obj)))\n}\n\n#' @name st_bbox\n#' @export\nst_bbox.Extent = function(obj, ..., crs = NA_crs_) {\n\tif (!requireNamespace(\"raster\", quietly = TRUE))\n\t\tstop(\"package raster required, please install it first\")\n\tstructure(bb_wrap(c(obj@xmin, obj@ymin, obj@xmax, obj@ymax)), crs = st_crs(crs))\n}\n\n#' @name st_bbox\n#' @param crs object of class \\code{crs}, or argument to \\link{st_crs}, specifying the CRS of this bounding box.\n#' @examples\n#' st_bbox(c(xmin = 16.1, xmax = 16.6, ymax = 48.6, ymin = 47.9), crs = st_crs(4326))\n#' @export\nst_bbox.numeric = function(obj, ..., crs = NA_crs_) {\n\tstructure(bb_wrap(obj[c(\"xmin\", \"ymin\", \"xmax\", \"ymax\")]), crs = st_crs(crs))\n}\n\n#' @export\nst_bbox.bbox = function(obj, ...) obj\n\n\n#' @export\n\"$.bbox\" = function(x, name) {\n\tswitch(name,\n\t\txrange =,\n\t\txlim = x[c(\"xmin\", \"xmax\")],\n\t\tyrange =,\n\t\tylim = x[c(\"ymin\", \"ymax\")],\n\t\txmin = x[\"xmin\"],\n\t\tymin = x[\"ymin\"],\n\t\txmax = x[\"xmax\"],\n\t\tymax = x[\"ymax\"],\n\t\tstop(\"unsupported name\")\n\t)\n}\n\n#' @name st_bbox\n#' @details \\code{NA_bbox_} represents the missing value for a \\code{bbox} object\n#' @export\nNA_bbox_ = structure(rep(NA_real_, 4),\n\tnames = c(\"xmin\", \"ymin\", \"xmax\", \"ymax\"),\n\tcrs = NA_crs_,\n\tclass = \"bbox\")\n\n#' @name st_bbox\n#' @details \\code{NA_bbox_} represents the missing value for a \\code{bbox} object\n#' @export\nFULL_bbox_ = structure(c(-180.,-90.,180.,90.),\n\tnames = c(\"xmin\", \"ymin\", \"xmax\", \"ymax\"),\n\tcrs = NA_crs_,\n\tclass = \"bbox\")\n\n#' @name st_bbox\n#' @export\nformat.bbox = function(x, ...) {\n\tp1 = paste0(\"(\",paste0(c(format(x[1], ...), format(x[2], ...)), collapse=\",\"),\")\")\n\tp2 = paste0(\"(\",paste0(c(format(x[3], ...), format(x[4], ...)), collapse=\",\"),\")\")\n\tpaste0(\"(\",p1,\",\",p2,\")\")\n}\n"
  },
  {
    "path": "R/bind.R",
    "content": "chk_equal_crs = function(dots) {\n\tif (length(dots) > 1L) {\n\t\tcrs0 = st_crs(dots[[1]])\n\t\tvapply(dots[-1L], function(x) {\n\t\t\t\tif (st_crs(x) != crs0) \n\t\t\t\t\tstop(\"arguments have different crs\", call. = FALSE)\n\t\t\t\tTRUE\n\t\t\t}, TRUE)\n\t}\n\tNULL\n}\n\n#' Bind rows (features) of sf objects\n#'\n#' Bind rows (features) of sf objects\n#' @param ... objects to bind; note that for the rbind and cbind methods, all objects have to be of class \\code{sf}; see \\link{dotsMethods}\n#' @param deparse.level integer; see \\link{rbind}\n#' @name bind\n#' @details both \\code{rbind} and \\code{cbind} have non-standard method dispatch (see \\link[base]{cbind}): the \\code{rbind} or \\code{cbind} method for \\code{sf} objects is only called when all arguments to be binded are of class \\code{sf}.\n#' @export\n#' @examples\n#' crs = st_crs(3857)\n#' a = st_sf(a=1, geom = st_sfc(st_point(0:1)), crs = crs)\n#' b = st_sf(a=1, geom = st_sfc(st_linestring(matrix(1:4,2))), crs = crs)\n#' c = st_sf(a=4, geom = st_sfc(st_multilinestring(list(matrix(1:4,2)))), crs = crs)\n#' rbind(a,b,c)\n#' rbind(a,b)\n#' rbind(a,b)\n#' rbind(b,c)\nrbind.sf = function(..., deparse.level = 1) {\n\tdots = list(...)\n\tdots = dots[!sapply(dots, is.null)]\n\tnr = sapply(dots, NROW)\n\tsf_column = if (any(nr > 0))\n\t\t\tattr(dots[[ which(nr > 0)[1] ]], \"sf_column\")\n\t\telse\n\t\t\tNULL\n\tchk_equal_crs(dots)\n\tret = st_sf(rbind.data.frame(...), crs = st_crs(dots[[1]]), sf_column_name = sf_column)\n\tst_geometry(ret) = st_sfc(st_geometry(ret)) # might need to reclass to GEOMETRY\n\tbb = do.call(rbind, lapply(dots, st_bbox))\n\tbb = bb_wrap(c(min(bb[,1L], na.rm = TRUE), min(bb[,2L], na.rm = TRUE),\n\t\t  max(bb[,3L], na.rm = TRUE), max(bb[,4L], na.rm = TRUE)))\n\tattr(ret[[ attr(ret, \"sf_column\") ]], \"bbox\") = bb\n\tret\n}\n\n#' Bind columns (variables) of sf objects\n#'\n#' Bind columns (variables) of sf objects\n#' @name bind\n#' @param sf_column_name character; specifies active geometry; passed on to \\link{st_sf}\n#' @return \\code{cbind} called with multiple \\code{sf} objects warns about multiple geometry columns present when the geometry column to use is not specified by using argument \\code{sf_column_name}; see also \\link{st_sf}.\n#' @export\n#' @details If you need to \\code{cbind} e.g. a \\code{data.frame} to an \\code{sf}, use \\link{data.frame} directly and use \\link{st_sf} on its result, or use \\link[dplyr:bind]{bind_cols}; see examples.\n#' @examples\n#' cbind(a,b,c) # warns\n#' if (require(dplyr, quietly = TRUE))\n#'   dplyr::bind_cols(a,b)\n#' c = st_sf(a=4, geomc = st_sfc(st_multilinestring(list(matrix(1:4,2)))), crs = crs)\n#' cbind(a,b,c, sf_column_name = \"geomc\")\n#' df = data.frame(x=3)\n#' st_sf(data.frame(c, df))\n#' if (require(dplyr, quietly = TRUE))\n#'   dplyr::bind_cols(c, df)\ncbind.sf = function(..., deparse.level = 1, sf_column_name = NULL) {\n\t# TODO: handle st_agr?\n\tst_sf(data.frame(...), sf_column_name = sf_column_name)\n}\n\n#' @name bind\n#' @export\n#' @details \\code{st_bind_cols} is deprecated; use \\code{cbind} instead.\nst_bind_cols = function(...) {\n\t# nocov start\n\t.Deprecated(\"cbind\",\n\t\t\t\tmsg = paste0(\"Use 'cbind' instead when all arguments\",\n\t\t\t\t             \" to be binded are of class sf.\\n\",\n\t\t\t\t             \"If you need to cbind a data.frame to an sf,\",\n\t\t\t\t             \" use 'st_sf' or 'dplyr::bind_cols' (see the examples).\"))\n\tcbind.sf(...)\n\t# nocov end\n}\n"
  },
  {
    "path": "R/break_antimeridian.R",
    "content": "\n#' Break antimeridian for plotting not centred on Greenwich\n#'\n#' Longitudes can be broken at the antimeridian of a target central longitude \n#' to permit plotting of (usually world) line or polygon objects centred \n#' on the chosen central longitude. The method may only be used with \n#' non-projected, geographical coordinates and linestring or polygon objects.\n#' s2 is turned off internally to permit the use of a rectangular bounding \n#' box. If the input geometries go outside `[-180, 180]` degrees longitude,\n#' the protruding geometries will also be split using the same \\code{tol=} \n#' values; in this case empty geometries will be dropped first.\n#'\n#' @param x object of class `sf` or `sfc`\n#' @param lon_0 target central longitude (degrees)\n#' @param tol half of break width (degrees, default 0.0001)\n#' @param ... ignored here\n#' @export\n#' @name st_break_antimeridian\n#' @examples\n#' \\donttest{\n#' if (require(\"maps\", quietly=TRUE)) {\n#'  opar = par(mfrow=c(3, 2))\n#'  wld = st_as_sf(map(fill=FALSE, interior=FALSE, plot=FALSE), fill=FALSE)\n#'  for (lon_0 in c(-170, -90, -10, 10, 90, 170)) {\n#'    br = st_break_antimeridian(wld, lon_0 = lon_0)\n#'    tr = st_transform(br, paste0(\"+proj=natearth +lon_0=\", lon_0))\n#'    plot(st_geometry(tr), main=lon_0)\n#'  }\n#'  par(opar)\n#' }\n#' }\nst_break_antimeridian = function(x, lon_0=0, tol=0.0001, ...) {\n\tll = st_is_longlat(x)\n\tif (!isTRUE(ll))\n\t\tstop(\"'st_break_antimeridian' requires non-projected geographic coordinates\",\n\t\t\t call. = FALSE)\n\n\tUseMethod(\"st_break_antimeridian\")\n}\n\n#' @export\n#' @name st_break_antimeridian\nst_break_antimeridian.sf = function(x, lon_0=0, tol=0.0001, ...) {\n\ttype = st_geometry_type(x)\n        if (length(grep(\"CURVE\", type[grep(\"LINESTRING|POLYGON\", type)],\n            invert=TRUE)) == 0L) stop(\"'st_break_antimeridian' requires linestring or polygon objects\", call. = FALSE)\n\tbb0 = st_bbox(x)\n        low = bb0[1] < -(180+tol)\n\thigh = bb0[3] > (180+tol)\n        if (low || high) {\n\t    warning(\"st_break_antimeridian: longitude coordinates outside [-180, 180]\")\n#\t     x_c = st_geometry(x)\n#            g = ((x_c + c(360, 90)) %% c(360) - c(0, 90))  - c(180, 0)\n#\t     st_crs(g) <- st_crs(x)\n#            st_geometry(x) = g\n            x <- st_within_pm180(x, tol=tol)\n            bb0 = st_bbox(x)\n        }\n        if (lon_0 < 0) {\n\t    am = lon_0 + 180\n            am_w = am - tol\n\t    am_e = am + tol\n            if (am_w > 180) am_w = am_w - 360\n        } else {\n\t    am = lon_0 - 180\n            am_w = am - tol\n\t    am_e = am + tol\n            if (am_w < -180) am_w = am_w + 360\n\t}\n        if (lon_0 == 0) {\n\t    bb1 = bb0\n            bb1[1] = am_e\n\t    bb1[3] = am_w\n            bb1 = st_as_sfc(bb1)\n        } else {\n            bb1w = bb1e = bb0\n\t    bb1w[3] = am_w # antimeridian of target minus fuzz\n\t    bb1e[1] = am_e # plus fuzz\n\t    bb1 = c(st_as_sfc(bb1w), st_as_sfc(bb1e))\n\t}\n        s2_status = sf_use_s2()\n\tsf_use_s2(FALSE) # avoid s2 because we need a planar bounding box\n\ton.exit(sf_use_s2(s2_status))\n\tres = st_intersection(x, bb1)\n\tst_crs(res) = st_crs(x)\n        res\n}\n#' @export\n#' @name st_break_antimeridian\nst_break_antimeridian.sfc = function(x, lon_0=0, tol=0.0001, ...) {\n# cannot reduce sf to sfc because the length of the returned object is\n# not restricted to the row count of the input object\n        st_geometry(st_break_antimeridian(st_as_sf(x), lon_0=lon_0, tol=tol))\n}\n\nst_within_pm180 <- function(x, tol=0.0001) {\n\tstopifnot(inherits(x, \"sf\"))\n        xempt = st_is_empty(x)\n\tif (any(xempt)) x = x[!xempt,]\n        xcrs = st_crs(x)\n        xnames = names(x)\n\txnames = xnames[grep(attr(x, \"sf_column\"), xnames, invert=TRUE)]\n\tx$st_within_pm180_ID = as.character(seq_len(nrow(x)))\n        s2_status = sf_use_s2()\n\tsf_use_s2(FALSE) # avoid s2 because we need a planar bounding box\n\tbb0 = st_bbox(x)\n        low = bb0[1] < -(180+tol)\n\thigh = bb0[3] > (180+tol)\n        bb1w = bb1e = bb0\n\tif (low) {\n\t    am = -180\n            am_w = am - tol\n\t    am_e = am + tol\n            if (am_w > 180) am_w = am_w - 360\n\t    bb1w[3] = am_w # 180 minus fuzz\n\t    bb1e[1] = am_e # 180 plus fuzz\n            xw = st_intersection(x, st_as_sfc(bb1w))\n\t    xe = st_intersection(x, st_as_sfc(bb1e))\n            gw = st_geometry(xw)\n            gw = gw + c(360, 0)\n\t    st_crs(gw) <- xcrs\n\t    st_geometry(xw) <- gw\n\t    o = rbind(xw, xe)\n\t    x = aggregate(o, list(o$st_within_pm180_ID), head, 1)\n\t    x = x[, xnames]\n\t    st_crs(x) = xcrs\n\t}\n\tbb0 = st_bbox(x)\n        bb1w = bb1e = bb0\n\tif (high) {\n\t    am = 180\n            am_w = am - tol\n\t    am_e = am + tol\n            if (am_w < -180) am_w = am_w + 360\n\t    bb1w[3] = am_w # 180 minus fuzz\n\t    bb1e[1] = am_e # 180 plus fuzz\n            xw = st_intersection(x, st_as_sfc(bb1w))\n\t    xe = st_intersection(x, st_as_sfc(bb1e))\n            ge = st_geometry(xe)\n            ge = ge - c(360, 0)\n\t    st_crs(ge) <- xcrs\n\t    st_geometry(xe) <- ge\n\t    o = rbind(xw, xe)\n\t    x = aggregate(o, list(o$st_within_pm180_ID), head, 1)\n\t    x = x[, xnames]\n\t    st_crs(x) = xcrs\n\t}\n\tsf_use_s2(s2_status)\n\tst_crs(x) = xcrs\n        x\n\n}\n"
  },
  {
    "path": "R/cast_sfc.R",
    "content": "#' Cast geometry to another type: either simplify, or cast explicitly\n#'\n#' Cast geometry to another type: either simplify, or cast explicitly\n#'\n#' @param x object of class \\code{sfg}, \\code{sfc} or \\code{sf}\n#' @param to character; target type, if missing, simplification is tried; when \\code{x} is of type \\code{sfg} (i.e., a single geometry) then \\code{to} needs to be specified.\n#' @return object of class \\code{to} if successful, or unmodified object if unsuccessful. If information gets lost while type casting, a warning is raised.\n#' @examples\n#' s = st_multipoint(rbind(c(1,0)))\n#' st_cast(s, \"POINT\")\n#' @export\nst_cast <- function(x, to, ...) UseMethod(\"st_cast\")\n\n# see this figure:\n# https://cloud.githubusercontent.com/assets/520851/21387553/5f1edcaa-c778-11e6-92d0-2d735e4c8e40.png\n# columns start counting at 0:\n\nwhich_sfc_col = function(cls) {\n\tstopifnot(!missing(cls))\n\tswitch(cls,\n\t\tPOINT = 0,\n\t\tLINESTRING = 1,\n\t\tMULTIPOINT = 1,\n\t\tMULTILINESTRING = 2,\n\t\tPOLYGON = 2,\n\t\tMULTIPOLYGON = 3,\n\t\tMULTICURVE = 3,\n\t\tGEOMETRYCOLLECTION = 4,\n\t\tCOMPOUNDCURVE = 4,\n\t\tMULTISURFACE = 4,\n\t\tCURVEPOLYGON = 4,\n\t\tGEOMETRY = 5,\n\t\tstop(paste(\"st_cast for\", cls, \"not supported\"))\n\t)\n}\n\n# does this geometry type need closed polygons?\nneed_close = function(cls) {\n\tswitch(cls,\n\t\tPOLYGON = TRUE,\n\t\tMULTIPOLYGON = TRUE,\n\t\tFALSE\n\t)\n}\n\n# add y's attributes to x, return x\nadd_attributes = function(x, y) {\n\tattributes(x) = attributes(y)\n\tx\n}\n\nclose_polygon_or_multipolygon = function(x, to) {\n\tto_col = which_sfc_col(to)\n\tclose_mat = function(m) {\n\t\tif (any(m[1,] != m[nrow(m),]))\n\t\t\tm = rbind(m, m[1,])\n\t\tif (nrow(m) < 4)\n\t\t\tstop(\"polygons require at least 4 points\")\n\t\tunclass(m)\n\t}\n\tadd_attributes(\n\t\tif (to_col == 2)\n\t\t\tlapply(x, function(y) add_attributes(lapply(y, close_mat), y))\n\t\telse if (to_col == 3)\n\t\t\tlapply(x, function(y) add_attributes(lapply(y, function(z) lapply(z, close_mat)), y))\n\t\telse\n\t\t\tstop(\"invalid to_col value\")\n\t, x)\n}\n\n# change the class of sfc x, and all its sfg list elements\n# (vertical cast)\nreclass = function(x, to, must_close) {\n\tl = if (length(x)) {\n\t\tfull_cls = c(class(x[[1]])[1], to, \"sfg\")\n\t\tif (must_close)\n\t\t\tx = close_polygon_or_multipolygon(x, to)\n\t\tlapply(x, function(g) structure(g, class = full_cls))\n\t} else\n\t\tlist()\n\tattributes(l) = attributes(x)\n\tstructure(l, class = c(paste0(\"sfc_\", to), \"sfc\"))\n}\n\n# how long is each geometry in the sfc?\nget_lengths = function(x) {\n\tswitch(class(x)[1],\n\t\tsfc_POINT = rep(1, length(x)),\n\t\tsfc_MULTIPOINT = vapply(x, nrow, 0L),\n\t\tsfc_LINESTRING = vapply(x, nrow, 0L),\n\t\tlengths(x) # list\n\t)\n}\n\n#' Coerce geometry to MULTI* geometry\n#'\n#' Mixes of POINTS and MULTIPOINTS, LINESTRING and MULTILINESTRING,\n#' POLYGON and MULTIPOLYGON are returned as MULTIPOINTS, MULTILINESTRING and MULTIPOLYGONS respectively\n#' @param x list of geometries or simple features\n#' @details Geometries that are already MULTI* are left unchanged.\n#' Features that can't be cast to a single  MULTI* geometry are return as a\n#' GEOMETRYCOLLECTION\nst_cast_sfc_default = function(x) {\n\n\tif (length(x) == 0)\n\t\treturn(x)\n\n\tif (!identical(unique(vapply(x, function(w) class(w)[3L], \"\")), \"sfg\"))\n\t\tstop(\"list item(s) not of class sfg\") # sanity check\n\n\ta <- attributes(x)\n\tids = NULL\n\tcls = unique(vapply(x, function(x) class(x)[2L], \"\"))\n\tif (length(cls) > 1) {\n\t\tif (all(cls %in% c(\"POINT\", \"MULTIPOINT\"))) {\n\t\t\tx <- lapply(x, function(x) if (inherits(x, \"POINT\")) POINT2MULTIPOINT(x) else x)\n\t\t\tclass(x) <- c(\"sfc_MULTIPOINT\", \"sfc\")\n\t\t} else if (all(cls %in% c(\"LINESTRING\", \"MULTILINESTRING\"))) {\n\t\t\tx <- lapply(x, function(x) if (inherits(x, \"LINESTRING\")) LINESTRING2MULTILINESTRING(x) else x)\n\t\t\tclass(x) <- c(\"sfc_MULTILINESTRING\", \"sfc\")\n\t\t} else if (all(cls %in% c(\"POLYGON\", \"MULTIPOLYGON\"))) {\n\t\t\tx <- lapply(x, function(x) if (inherits(x, \"POLYGON\")) POLYGON2MULTIPOLYGON(x) else x)\n\t\t\tclass(x) <- c(\"sfc_MULTIPOLYGON\", \"sfc\")\n\t\t}\n\t} else if (cls == \"GEOMETRYCOLLECTION\" && all(lengths(x))) { # https://github.com/r-spatial/sf/issues/1767\n\t\tids = get_lengths(x)\n\t\tx <- do.call(st_sfc, unlist(x, recursive = FALSE))\n\t}\n\tattributes(x) <- a\n\tstructure(st_sfc(x), ids = ids)\n}\n\ncopy_sfc_attributes_from = function(x, ret) {\n\tstructure(ret, precision = attr(x, \"precision\"),\n\t\tbbox = attr(x, \"bbox\"), crs = attr(x, \"crs\"), n_empty = attr(x, \"n_empty\"), \n\t\tz_range = attr(x, \"z_range\"), m_range = attr(x, \"m_range\"))\n}\n\nempty_sfg <- function(to) {\n\tswitch(to,\n\t\t   GEOMETRYCOLLECTION = st_geometrycollection(),\n\t\t   MULTIPOLYGON = st_multipolygon(),\n\t\t   POLYGON = st_polygon(),\n\t\t   MULTILINESTRING = st_multilinestring(),\n\t\t   LINESTRING = st_linestring(),\n\t\t   MULTIPOINT = st_multipoint(),\n\t\t   POINT = st_point()\n\t   )\n}\n\nis_exotic = function(x) {\n\tstopifnot(length(x) > 0)\n\tif (inherits(x, c(\"sfc_MULTICURVE\", \"sfc_COMPOUNDCURVE\", \"sfc_CURVEPOLYGON\", \"sfc_MULTISURFACE\"))) # for which GEOS has no st_is_empty()\n\t\tTRUE\n\telse if (inherits(x, \"sfc_GEOMETRY\")) {\n\t\tcls = sapply(x, class)\n\t\tany(cls[2,] %in% c(\"MULTICURVE\", \"COMPOUNDCURVE\", \"CURVEPOLYGON\", \"MULTISURFACE\"))\n\t} else\n\t\tFALSE\n}\n\n#' @name st_cast\n#' @param ids integer vector, denoting how geometries should be grouped (default: no grouping)\n#' @param group_or_split logical; if TRUE, group or split geometries; if FALSE, carry out a 1-1 per-geometry conversion.\n#' @param ... ignored\n#' @export\n#' @return In case \\code{to} is missing, \\code{st_cast.sfc} will coerce combinations of \"POINT\" and \"MULTIPOINT\", \"LINESTRING\" and \"MULTILINESTRING\", \"POLYGON\" and \"MULTIPOLYGON\" into their \"MULTI...\" form, or in case all geometries are \"GEOMETRYCOLLECTION\" will return a list of all the contents of the \"GEOMETRYCOLLECTION\" objects, or else do nothing. In case \\code{to} is specified, if \\code{to} is \"GEOMETRY\", geometries are not converted, else, \\code{st_cast} will try to coerce all elements into \\code{to}; \\code{ids} may be specified to group e.g. \"POINT\" objects into a \"MULTIPOINT\", if not specified no grouping takes place. If e.g. a \"sfc_MULTIPOINT\" is cast to a \"sfc_POINT\", the objects are split, so no information gets lost, unless \\code{group_or_split} is \\code{FALSE}.\n#' @details When converting a GEOMETRYCOLLECTION to COMPOUNDCURVE, MULTISURFACE or CURVEPOLYGON, the user is responsible for the validity of the resulting object: no checks are being carried out by the software.\n#' \n#' When converting mixed, GEOMETRY sets, it may help to first convert to the MULTI-type, see examples\n#' @examples\n#' # https://github.com/r-spatial/sf/issues/1930:\n#' pt1 <- st_point(c(0,1))\n#' pt23 <- st_multipoint(matrix(c(1,2,3,4), ncol = 2, byrow = TRUE))\n#' d <- st_sf(geom = st_sfc(pt1, pt23))\n#' st_cast(d, \"POINT\") # will not convert the entire MULTIPOINT, and warns\n#' st_cast(d, \"MULTIPOINT\") |> st_cast(\"POINT\")\nst_cast.sfc = function(x, to, ..., ids = seq_along(x), group_or_split = TRUE) {\n\n\tif (missing(to))\n\t\treturn(st_cast_sfc_default(x))\n\n\tif (length(x) == 0) # empty set\n\t\treturn(structure(x, class = c(paste0(\"sfc_\", to), \"sfc\")))\n\n\te = rep(FALSE, length(x))\n\tif (!is_exotic(x)) { # for which GEOS has no st_is_empty()\n\t\te = st_is_empty(x)\n\t\tif (all(e)) {\n\t\t\tx[e] = empty_sfg(to)\n\t\t\treturn(x) # RETURNS\n\t\t}\n\t}\n\tif (any(e))\n\t\tx = x[!e]\n\tfrom_cls = substr(class(x)[1], 5, 100)\n\tfrom_col = which_sfc_col(from_cls)\n\tto_col = which_sfc_col(to)\n\tret = if (from_cls == to)\n\t\tx # returns x: do nothing\n\telse if (to == \"GEOMETRY\") # we can always do that:\n\t\tstructure(x, class = c(\"sfc_GEOMETRY\", \"sfc\"))\n\telse if (from_cls == \"GEOMETRY\" || !group_or_split)\n\t\tst_sfc(lapply(x, st_cast, to = to), crs = st_crs(x), precision = st_precision(x))\n\telse if (from_col == to_col) # \"vertical\" conversion: only reclass, possibly close polygons\n\t\treclass(x, to, need_close(to))\n\telse if (abs(from_col - to_col) > 1) {\n\t\tif (to == \"POINT\")\n\t\t\tst_cast(st_cast(x, \"MULTIPOINT\"), \"POINT\")\n\t\telse if (to == \"MULTIPOINT\") {\n\t\t\tret = lapply(x, function(y) structure(as.matrix(y), class = c(class(y)[1], to, \"sfg\")))\n\t\t\tret = copy_sfc_attributes_from(x, ret)\n\t\t\treclass(ret, to, FALSE)\n\t\t} else\n\t\t\t#st_cast(st_cast(x, \"MULTILINESTRING\"), to)\n\t\t\tstop(\"use smaller steps for st_cast; first cast to MULTILINESTRING or POLYGON?\")\n\t} else if (from_col < to_col) { # \"horizontal\", to the right: group\n\t\tret = if (from_col == 0)\n\t\t\t\tlapply(unname(split(x, ids)), function(y) structure(do.call(rbind, y), \n\t\t\t\t\tclass = class(x[[1]])))\n\t\t\telse\n\t\t\t\tlapply(unname(split(x, ids)), function(y) structure(y, class = class(x[[1]])))\n\t\tret = copy_sfc_attributes_from(x, ret)\n\t\treclass(ret, to, need_close(to))\n\t} else if (from_col == 3 && to == \"MULTILINESTRING\") {\n\t\tif (from_cls == \"MULTICURVE\") {\n\t\t\tret = lapply(x, st_cast, to = \"MULTILINESTRING\")\n\t\t} else {\n\t\t\tret = lapply(x, unlist, recursive = FALSE) # unlist one level deeper; one MULTIPOLYGON -> one MULTILINESTRING\n\t\t\tif (length(ret))\n\t\t\t\tclass(ret[[1]]) = class(x[[1]]) # got dropped\n\t\t}\n\t\tret = copy_sfc_attributes_from(x, ret)\n\t\tstructure(reclass(ret, to, FALSE))\n\t} else { # \"horizontal\", to the left: split\n\t\tret = if (from_col == 1) # LINESTRING or MULTIPOINT to POINT\n\t\t\t\tunlist(lapply(x, function(m) lapply(seq_len(nrow(m)), function(i) m[i,])), recursive = FALSE)\n\t\t\telse {\n\t\t\t\tif (to_col == 0 && from_cls == \"POLYGON\") # POLYGON -> POINT\n\t\t\t\t\tlapply(x, function(y) do.call(rbind, y))\n\t\t\t\telse\n\t\t\t\t\tunlist(x, recursive = FALSE)\n\t\t\t}\n\t\tret = lapply(ret, function(y) structure(y, class = class(x[[1]]))) # will be reset by reclass()\n\t\tret = copy_sfc_attributes_from(x, ret)\n\t\t# EJP: FIXME:\n\t\tstructure(reclass(ret, to, need_close(to)), ids = get_lengths(x))\n\t}\n\tif (any(e)) {\n\t\tcrs = st_crs(x)\n\t\tx = vector(\"list\", length = length(e))\n\t\tx[e] = list(empty_sfg(to))\n\t\tx[!e] = ret\n\t\tst_set_crs(do.call(st_sfc, x), crs)\n\t} else\n\t\tret\n}\n\n#' @name st_cast\n#' @param warn logical; if \\code{TRUE}, warn if attributes are assigned to sub-geometries\n#' @param do_split logical; if \\code{TRUE}, allow splitting of geometries in sub-geometries\n#' @export\n#' @details the \\code{st_cast} method for \\code{sf} objects can only split geometries, e.g. cast \\code{MULTIPOINT} into multiple \\code{POINT} features.  In case of splitting, attributes are repeated and a warning is issued when non-constant attributes are assigned to sub-geometries. To merge feature geometries and attribute values, use \\link[sf:aggregate.sf]{aggregate} or \\link[sf:tidyverse]{summarise}.\nst_cast.sf = function(x, to, ..., warn = TRUE, do_split = TRUE) {\n\tgeom = st_cast(st_geometry(x), to, group_or_split = do_split)\n\tagr = st_agr(x)\n\tall_const = all_constant(x)\n\tsf_column = attr(x, \"sf_column\") # keep name\n\tst_geometry(x) = NULL\n\t# class(x) = setdiff(class(x), \"sf\")\n\tids = attr(geom, \"ids\")          # e.g. 3 2 4\n\tif (!is.null(ids)) { # split:\n\t\tif (warn && ! all_const)\n\t\t\twarning(\"repeating attributes for all sub-geometries for which they may not be constant\")\n\t\treps = rep(seq_len(length(ids)), ids) # 1 1 1 2 2 3 3 3 3 etc\n\t\tagr[agr == \"identity\"] = \"constant\" # since we splitted\n\t\tx = x[reps,, drop = FALSE]\n\t\tstopifnot(nrow(x) == length(geom))\n\t}\n\tattr(geom, \"ids\") = NULL # remove\n\tx[[sf_column]] = geom\n\tst_geometry(x) = sf_column\n\tst_agr(x) = agr\n\tx\n}\n\n#' @name st_cast\n#' @export\nst_cast.sfc_CIRCULARSTRING <- function(x, to, ...) {\n\tif (isTRUE(st_is_longlat(x)))\n\t\tmessage_longlat(\"st_cast\")\n\tstopifnot(to == \"LINESTRING\")\n\tst_sfc(CPL_circularstring_to_linestring(st_sfc(x)), crs = st_crs(x)) # should add attributes?\n}\n\n#' test equality between the geometry type and a class or set of classes\n#'\n#' test equality between the geometry type and a class or set of classes\n#' @param x object of class \\code{sf}, \\code{sfc} or \\code{sfg}\n#' @param type character; class, or set of classes, to test against\n#' @examples\n#' st_is(st_point(0:1), \"POINT\")\n#' sfc = st_sfc(st_point(0:1), st_linestring(matrix(1:6,,2)))\n#' st_is(sfc, \"POINT\")\n#' st_is(sfc, \"POLYGON\")\n#' st_is(sfc, \"LINESTRING\")\n#' st_is(st_sf(a = 1:2, sfc), \"LINESTRING\")\n#' st_is(sfc, c(\"POINT\", \"LINESTRING\"))\n#' @export\nst_is = function(x, type) UseMethod(\"st_is\")\n\n#' @export\nst_is.sf = function(x, type)\n\tst_is(st_geometry(x), type)\n\n#' @export\nst_is.sfc = function(x, type)\n\tvapply(x, inherits, type, FUN.VALUE = logical(1))\n\n#' @export\nst_is.sfg = function(x, type)\n\tinherits(x, type)\n"
  },
  {
    "path": "R/cast_sfg.R",
    "content": "## utility functions, patterns that are either used elsewhere or can be \n##  replaced by other changes \n## \n## worker functions from the internals of c.sfg\n##  to unclass the underlying coordinates\nPaste0 <- function(lst) lapply(lst, unclass)\n##\n## drop the tail coordinate of a polygon ring\nTail1 <- function(lst) lapply(lst, head, -1)\n\nClosePol <- function(mtrx) { \n\tstopifnot(is.matrix(mtrx))\n\tif (!all(mtrx[1,] == mtrx[nrow(mtrx),])) \n\t\tmtrx = rbind(mtrx, mtrx[1,]) \n\tif (nrow(mtrx) < 4)\n\t\tstop(\"polygons require at least 4 points\")\n\tmtrx\n}\n\n## multi-polygon and polygon constructor, allow unclosed (but don't apply auto-closing)\n## note use of local constructor below, not the sf-API one\n#st_multipolygon_close <- function(x = list(), dim = \"XYZ\") {\n#\tMtrxSetSet(x, dim, type = \"MULTIPOLYGON\", needClosed = FALSE)\n#}\n\n#st_polygon_close <- function(x = list(), dim = \"XYZ\") {\n#\tMtrxSet(x, dim, type = \"POLYGON\", needClosed = FALSE)\n#}\n\n# TODO\n# FIXME: warn on multi-part loss only if there are multiple parts\n# disallow auto-polygon-closure for two-point inputs:  st_cast(st_linestring(cbind(0, 1:2)), \"POLYGON\")\n# -> that should give an error\n# check discussions, holes become lines, those lines become overlapping islands, or does polygonize auto-detect nesting\n##  and assign holes to islands as sp-comments did?\n# test on holes\n# warnings on these individual tests as here, or on detection of loss higher up?\n# geometrycollection conversions?\n# check comments and warnings are consistent in each case below\n\n#' @name st_cast\n#' @export\n#' @examples \n#' # example(st_read)\n#' nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\n#' mpl <- st_geometry(nc)[[4]]\n#' #st_cast(x) ## error 'argument \"to\" is missing, with no default'\n#' cast_all <- function(xg) {\n#'   lapply(c(\"MULTIPOLYGON\", \"MULTILINESTRING\", \"MULTIPOINT\", \"POLYGON\", \"LINESTRING\", \"POINT\"), \n#'       function(x) st_cast(xg, x))\n#' }\n#' st_sfc(cast_all(mpl))\n#' ## no closing coordinates should remain for multipoint\n#' any(duplicated(unclass(st_cast(mpl, \"MULTIPOINT\"))))  ## should be FALSE\n#' ## number of duplicated coordinates in the linestrings should equal the number of polygon rings \n#' ## (... in this case, won't always be true)\n#' sum(duplicated(do.call(rbind, unclass(st_cast(mpl, \"MULTILINESTRING\"))))\n#'      ) == sum(unlist(lapply(mpl, length)))  ## should be TRUE\n#' \n#' p1 <- structure(c(0, 1, 3, 2, 1, 0, 0, 0, 2, 4, 4, 0), .Dim = c(6L, 2L))\n#' p2 <- structure(c(1, 1, 2, 1, 1, 2, 2, 1), .Dim = c(4L, 2L))\n#' st_polygon(list(p1, p2))\nst_cast.MULTIPOLYGON <- function(x, to, ...) {\n\tswitch(to, \n\t\tMULTIPOLYGON = x, \n\t\tMULTILINESTRING = st_multilinestring(     unlist(Paste0(x), recursive = FALSE, use.names = FALSE)), \n\t\tMULTIPOINT = st_multipoint(do.call(rbind, Tail1(unlist(Paste0(x), recursive = FALSE, use.names = FALSE)))), \n         ## loss, drop to first part\n\t\tPOLYGON = {\n\t\t \tif (length(x) > 1)\n\t\t\t\twarning(\"polygon from first part only\")\n\t\t\tst_polygon(x[[1L]])\n\t\t}, \n\t\tLINESTRING = {warning(\"line from first ring only\"); st_linestring(x[[1L]][[1L]])}, \n\t\t## loss, drop to first coordinate of first ring of first part\n\t\tPOINT = {warning(\"point from first coordinate only\"); st_point(x[[1L]][[1L]][1L, , drop = TRUE])},\n\t\tGEOMETRYCOLLECTION = st_geometrycollection(list(x))\n\t)\n}\n\n#' @name st_cast\n#' @export\n#' @examples \n#' mls <- st_cast(st_geometry(nc)[[4]], \"MULTILINESTRING\")\n#' st_sfc(cast_all(mls))\nst_cast.MULTILINESTRING <- function(x, to, ...) {\n\tswitch(to, \n\t\tMULTIPOLYGON = st_multipolygon(list(lapply(x, ClosePol))), \n\t\tMULTILINESTRING = x, \n\t\tMULTIPOINT = st_multipoint(do.call(rbind, Paste0(x))), \n\t\t## loss, drop to first line\n\t\t#POLYGON = {warning(\"keeping first linestring only\"); st_polygon(x[1L])}, \n\t\tPOLYGON = st_polygon(lapply(x, ClosePol)),\n\t\tLINESTRING = {\n\t\t\tif (length(x) > 1)\n\t\t\t\twarning(\"keeping first linestring only\")\n\t\t\tst_linestring(x[[1L]])\n\t\t},\n\t\t## loss, drop to first coordinate of first line \n\t\tPOINT = {\n\t\t\twarning(\"keeping first coordinate only\")\n\t\t\tst_point(x[[1L]][1L, , drop = TRUE])\n\t\t},\n\t\tGEOMETRYCOLLECTION = st_geometrycollection(list(x))\n\t)\n}\n\n#' @name st_cast\n#' @export\n#' @examples\n#' mpt <- st_cast(st_geometry(nc)[[4]], \"MULTIPOINT\")\n#' st_sfc(cast_all(mpt))\nst_cast.MULTIPOINT <- function(x, to, ...) {\n  switch(to, \n         ## DANGER: polygon, linestring forms unlikely to be valid\n         MULTIPOLYGON = st_multipolygon(list(list(ClosePol(unclass(x))))), \n         MULTILINESTRING = st_multilinestring(list(unclass(x))), \n         MULTIPOINT = x, \n         POLYGON = st_polygon(list(unclass(ClosePol(x)))), \n         LINESTRING = st_linestring(unclass(x)),\n         ## loss, drop to first coordinate\n         POINT = {\n             if (st_is_empty(x)) {\n                 row <- NA_integer_\n             } else {\n\t             warning(\"point from first coordinate only\")\n                 row <- 1L\n             }\n             st_point(unclass(x)[row, , drop = TRUE])\n         },\n\t\t GEOMETRYCOLLECTION = st_geometrycollection(list(x))\n  )\n}\n\n#' @name st_cast\n#' @export\n#' @examples\n#' pl <- st_cast(st_geometry(nc)[[4]], \"POLYGON\")\n#' st_sfc(cast_all(pl))\nst_cast.POLYGON <- function(x, to, ...) {\n  switch(to, \n         MULTIPOLYGON = {\n\t\t\t if (length(x))\n\t\t\t\tx = list(lapply(Paste0(x), ClosePol))\n\t\t\t st_multipolygon(x)\n\t\t },\n         MULTILINESTRING = st_multilinestring(unclass(x)), \n         MULTIPOINT = st_multipoint(Tail1(unclass(x))[[1L]]), \n         POLYGON = x, \n         LINESTRING = st_linestring(unclass(x)[[1L]]),\n         POINT = {warning(\"point from first coordinate only\"); st_point(unclass(x)[[1L]][1L, , drop = TRUE])},\n\t\t GEOMETRYCOLLECTION = st_geometrycollection(list(x))\n  )\n}\n\n#' @name st_cast\n#' @export\n#' @examples\n#' ls <- st_cast(st_geometry(nc)[[4]], \"LINESTRING\")\n#' st_sfc(cast_all(ls))\nst_cast.LINESTRING <- function(x, to, ...) {\n  switch(to, \n         MULTIPOLYGON = st_multipolygon(list(list(ClosePol(unclass(x))))), \n         MULTILINESTRING = st_multilinestring(list(unclass(x))), \n         MULTIPOINT = st_multipoint(unclass(x)), \n         POLYGON = st_polygon(list(unclass(ClosePol(x)))), \n         LINESTRING = x,\n         POINT = {warning(\"point from first coordinate only\"); st_point(unclass(x)[1L, , drop = TRUE])},\n\t\t GEOMETRYCOLLECTION = st_geometrycollection(list(x))\n  )\n}\n\n#' @name st_cast\n#' @export\n#' @examples\n#' pt <- st_cast(st_geometry(nc)[[4]], \"POINT\")\n#' ## st_sfc(cast_all(pt))  ## Error: cannot create MULTIPOLYGON from POINT \n#' st_sfc(lapply(c(\"POINT\", \"MULTIPOINT\"), function(x) st_cast(pt, x)))\nst_cast.POINT <- function(x, to, ...) {\n  switch(to, \n         MULTIPOLYGON = stop(\"cannot create MULTIPOLYGON from POINT\"), \n         MULTILINESTRING = stop(\"cannot create MULTILINESTRING from POINT\"), \n         MULTIPOINT = st_multipoint(matrix(unclass(x), nrow = 1L)), \n         POLYGON = stop(\"cannot create POLYGON from POINT\"), \n         LINESTRING = stop(\"cannot create LINESTRING from POINT\"),\n         POINT = x,\n\t\t GEOMETRYCOLLECTION = st_geometrycollection(list(x))\n  )\n}\n\n#' @name st_cast\n#' @export\nst_cast.GEOMETRYCOLLECTION <- function(x, to, ...) {\n  switch(to, \n  \tGEOMETRYCOLLECTION = x,\n  \t{\n\t\tif (length(x) > 1)\n\t\t\twarning(\"only first part of geometrycollection is retained\")\n\t\tst_cast(x[[1]], to, ...)\n\t}\n  )\n}\n\n#' @name st_cast\n#' @export\nst_cast.CIRCULARSTRING <- function(x, to, ...) {\n\tif (to != \"LINESTRING\")\n\t\tstop(\"CIRCULARSTRING can only be converted into LINESTRING\")\n\tCPL_circularstring_to_linestring(structure(list(x), crs = NA_crs_, precision = 0.0, \n\t\tclass = c(\"sfc_CIRCULARSTRING\", \"sfc\")))[[1]]\n}\n\n#' @name st_cast\n#' @export\nst_cast.MULTISURFACE <- function(x, to, ...) {\n\tif (! missing(to) && to != \"MULTIPOLYGON\")\n\t\tstop(\"MULTISURFACE can only be converted into MULTIPOLYGON\")\n\tCPL_multisurface_to_multipolygon(structure(list(x), crs = NA_crs_, precision = 0.0, \n\t\tclass = c(\"sfc_MULTISURFACE\", \"sfc\")))[[1]]\n}\n\n#' @name st_cast\n#' @export\nst_cast.COMPOUNDCURVE <- function(x, to, ...) {\n\tif (! missing(to) && to != \"LINESTRING\")\n\t\tstop(\"to should be missing or LINESTRING\")\n\tCPL_compoundcurve_to_linear(structure(list(x), crs = NA_crs_, precision = 0.0, \n\t\tclass = c(\"sfc_COMPOUNDCURVE\", \"sfc\")))[[1]]\n}\n\n#' @name st_cast\n#' @export\nst_cast.MULTICURVE <- function(x, to, ...) {\n\tif (! missing(to) && to != \"MULTILINESTRING\")\n\t\tstop(\"to should be missing or MULTILINESTRING\")\n\tst_multilinestring(lapply(x, st_cast, to = \"LINESTRING\"))\n}\n\n\n#' @name st_cast\n#' @export\nst_cast.CURVE <- function(x, to, ...) { # nocov start\n\tif (! missing(to) && to != \"LINESTRING\")\n\t\tstop(\"CURVE can only be converted into LINESTRING\")\n\tCPL_curve_to_linestring(structure(list(x), crs = NA_crs_, precision = 0.0, \n\t\tclass = c(\"sfc_CURVE\", \"sfc\")))[[1]]\n} # nocov end\n\n# st_cast.class <- function(x, to) {\n#   switch(to, \n#          MULTIPOLYGON = x, \n#          MULTILINESTRING = x, \n#          MULTIPOINT = x, \n#          POLYGON = x, \n#          LINESTRING = x,\n#          POINT = x\n#   )\n# }\n\n"
  },
  {
    "path": "R/collection_extract.R",
    "content": "#' Given an object with geometries of type \\code{GEOMETRY} or \\code{GEOMETRYCOLLECTION},\n#' return an object consisting only of elements of the specified type.\n#'\n#' Similar to ST_CollectionExtract in PostGIS. If there are no sub-geometries\n#' of the specified type, an empty geometry is returned.\n#'\n#' @param x an object of class \\code{sf}, \\code{sfc} or \\code{sfg} that has\n#' mixed geometry (\\code{GEOMETRY} or \\code{GEOMETRYCOLLECTION}).\n#' @param type character; one of \"POLYGON\", \"POINT\", \"LINESTRING\"\n#' @param warn logical; if \\code{TRUE}, warn if attributes are assigned to\n#' sub-geometries when casting (see \\code{\\link{st_cast}})\n#'\n#' @return An object having the same class as \\code{x}, with geometries\n#' consisting only of elements of the specified type.\n#' For \\code{sfg} objects, an \\code{sfg} object is returned if there is only\n#' one geometry of the specified type, otherwise the geometries are combined\n#' into an \\code{sfc} object of the relevant type. If any subgeometries in the\n#' input are MULTI, then all of the subgeometries in the output will be MULTI.\n#'\n#' @export\n#'\n#' @examples\n#' pt <- st_point(c(1, 0))\n#' ls <- st_linestring(matrix(c(4, 3, 0, 0), ncol = 2))\n#' poly1 <- st_polygon(list(matrix(c(5.5, 7, 7, 6, 5.5, 0, 0, -0.5, -0.5, 0), ncol = 2)))\n#' poly2 <- st_polygon(list(matrix(c(6.6, 8, 8, 7, 6.6, 1, 1, 1.5, 1.5, 1), ncol = 2)))\n#' multipoly <- st_multipolygon(list(poly1, poly2))\n#'\n#' i <- st_geometrycollection(list(pt, ls, poly1, poly2))\n#' j <- st_geometrycollection(list(pt, ls, poly1, poly2, multipoly))\n#'\n#' st_collection_extract(i, \"POLYGON\")\n#' st_collection_extract(i, \"POINT\")\n#' st_collection_extract(i, \"LINESTRING\")\n#'\n#' ## A GEOMETRYCOLLECTION\n#' aa <- rbind(st_sf(a=1, geom = st_sfc(i)),\n#' \t\t\tst_sf(a=2, geom = st_sfc(j)))\n#'\n#' ## With sf objects\n#' st_collection_extract(aa, \"POLYGON\")\n#' st_collection_extract(aa, \"LINESTRING\")\n#' st_collection_extract(aa, \"POINT\")\n#'\n#' ## With sfc objects\n#' st_collection_extract(st_geometry(aa), \"POLYGON\")\n#' st_collection_extract(st_geometry(aa), \"LINESTRING\")\n#' st_collection_extract(st_geometry(aa), \"POINT\")\n#'\n#' ## A GEOMETRY of single types\n#' bb <- rbind(\n#' \tst_sf(a = 1, geom = st_sfc(pt)),\n#' \tst_sf(a = 2, geom = st_sfc(ls)),\n#' \tst_sf(a = 3, geom = st_sfc(poly1)),\n#' \tst_sf(a = 4, geom = st_sfc(multipoly))\n#' )\n#'\n#' st_collection_extract(bb, \"POLYGON\")\n#'\n#' ## A GEOMETRY of mixed single types and GEOMETRYCOLLECTIONS\n#' cc <- rbind(aa, bb)\n#'\n#' st_collection_extract(cc, \"POLYGON\")\n#'\nst_collection_extract = function(x, type = c(\"POLYGON\", \"POINT\", \"LINESTRING\"), warn = FALSE) {\n\tUseMethod(\"st_collection_extract\")\n}\n\n#' @name st_collection_extract\n#'\n#' @export\nst_collection_extract.sfg = function(x, type = c(\"POLYGON\", \"POINT\", \"LINESTRING\"), warn = FALSE) {\n\ttype = match.arg(type)\n\ttypes = c(type, paste0(\"MULTI\", type))\n\n\tif (inherits(x, types)) {\n\t\twarning(\"x is already of type \", type, \".\")\n\t\treturn(x)\n\t}\n\n\tif (!inherits(x, \"GEOMETRYCOLLECTION\")) {\n\t\tstop(\"x is of singular geometry type that is different to supplied type: \", type) # nocov\n\t}\n\n\t# Find the geometries of the specified type and extract into a list\n\tmatches = vapply(x, st_is, types, FUN.VALUE = logical(1))\n\tx_types = x[which(matches)]\n\tif (length(x_types) == 0L) {\n\t\t## return an empty sfg of the specified type\n\t\twarning(\"x contains no geometries of specified type\")\n\t\treturn(typed_empty(paste0(\"sfc_\", type)))\n\t} else if (length(x_types) == 1L) {\n\t\t# Get the contents of the first (only) list element which is an sfg\n\t\treturn(x_types[[1]])\n\t} else {\n\t\t# turn list into an sfc, and cast it to single type. Will be multi\n\t\t# if any are multi\n\t\treturn(st_cast(st_sfc(x_types), warn = warn))\n\t}\n}\n\n#' @name st_collection_extract\n#'\n#' @export\nst_collection_extract.sfc = function(x, type = c(\"POLYGON\", \"POINT\", \"LINESTRING\"), warn = FALSE) {\n\ttype = match.arg(type)\n\ttypes = c(type, paste0(\"MULTI\", type))\n\n\tif (length(x) == 0)\n\t\treturn(x)\n\n\t# Check it's not already what user is asking for\n\tif (inherits(st_geometry(x), paste0(\"sfc_\", types))) {\n\t\twarning(\"x is already of type \", type, \".\") # nocov\n\t\treturn(x)                                   # nocov\n\t}\n\n\tif (!inherits(st_geometry(x), c(\"sfc_GEOMETRY\", \"sfc_GEOMETRYCOLLECTION\"))) {\n\t\tstop(\"x is of singular geometry type that is different to supplied type: \", type)\n\t}\n\n\t# Cast to GEOMETRYCOLLECTION if is GEOMETRY)\n\tif (inherits(st_geometry(x), \"sfc_GEOMETRY\")) {\n\t\tx = st_cast(x, \"GEOMETRYCOLLECTION\")\n\t}\n\n\t## Cast GEOMETRYCOLLECTION into all components\n\tgc_casted = st_cast(x, warn = warn)\n\n\t## Keep only components that match input type\n\tif (inherits(gc_casted, \"sf\")) {\n\t\tgc_types = gc_casted[st_is(gc_casted, types), ]\n\t} else {\n\t\tgc_types = gc_casted[st_is(gc_casted, types)]\n\t}\n\n\t## Cast to specified (MULTI) type\n\n\tif (length(st_geometry(gc_types)) == 0L) {\n\t\twarning(\"x contains no geometries of specified type\")\n\t\treturn(gc_types)\n\t}\n\n\tst_cast(gc_types, warn = warn)\n}\n\n#' @name st_collection_extract\n#'\n#' @export\nst_collection_extract.sf = st_collection_extract.sfc\n"
  },
  {
    "path": "R/crop.R",
    "content": "\n#' crop an sf object to a specific rectangle\n#' @param x object of class \\code{sf} or \\code{sfc}\n#' @param y numeric vector with named elements \\code{xmin}, \\code{ymin}, \\code{xmax} and \\code{ymax}, or object of class \\code{bbox}, or object for which there is an \\link{st_bbox} method to convert it to a \\code{bbox} object\n#' @param ... ignored\n#' @details\n#' setting arguments \\code{xmin}, \\code{ymin}, \\code{xmax} and \\code{ymax} implies that argument \\code{y} gets ignored.\n#' @export\n#' @examples\n#' box = c(xmin = 0, ymin = 0, xmax = 1, ymax = 1)\n#' pol = st_sfc(st_buffer(st_point(c(.5, .5)), .6))\n#' pol_sf = st_sf(a=1, geom=pol)\n#' plot(st_crop(pol, box))\n#' plot(st_crop(pol_sf, st_bbox(box)))\n#' # alternative:\n#' plot(st_crop(pol, xmin = 0, ymin = 0, xmax = 1, ymax = 1))\n#' @export\nst_crop = function(x, y, ...) UseMethod(\"st_crop\")\n\n#' @export\n#' @name st_crop\n#' @param xmin minimum x extent of cropping area\n#' @param ymin minimum y extent of cropping area\n#' @param xmax maximum x extent of cropping area\n#' @param ymax maximum y extent of cropping area\nst_crop.sfc = function(x, y, ..., xmin, ymin, xmax, ymax) {\n\tif (!missing(xmin) && !missing(ymin) && !missing(xmax) && !missing(ymax))\n\t\ty = c(xmin = xmin, ymin = ymin, xmax = xmax, ymax = ymax)\n\tif (! inherits(y, \"bbox\"))\n\t\ty = st_bbox(y)\n\tif (is.na(st_crs(y)))\n\t\ty = structure(y, crs = st_crs(x))\n\tst_intersection(x, st_as_sfc(y))\n}\n\n#' @export\n#' @name st_crop\nst_crop.sf = function(x, y, ...) {\n\tst_crop.sfc(x, y, ...)\n}\n"
  },
  {
    "path": "R/crs.R",
    "content": "#  alternative, but more limiting from sp/R/CRS-methods.R, https://github.com/edzer/sp/pull/31 @hughjonesd\n#  (no longer used)\n#identicalCRS1 = function(x, y) {\n#  args_x <- strsplit(x, \" +\")[[1]]\n#  args_y <- strsplit(y, \" +\")[[1]]\n#  setequal(args_x, args_y)\n#}\n\n# this function establishes whether two crs objects are semantically identical. This is\n# the case when: (1) they are completely identical (including NA), or (2) GDAL considers\n# them equivalent\n#' @export\nOps.crs <- function(e1, e2) {\n\tif (nargs() == 1)\n\t\tstop(paste(\"unary\", .Generic, \"not defined for \\\"crs\\\" objects\"), call. = FALSE)\n\n\tcmp <- switch(.Generic, \"==\" =, \"!=\" = TRUE, FALSE)\n\tif (!cmp)\n\t\tstop(paste(\"operation\", .Generic, \"not supported for crs objects\"), call. = FALSE)\n\tif (.Generic == \"!=\")\n\t\t!(e1 == e2)\n\telse { # \"==\": check semantic equality\n\t\tif (isTRUE(all.equal(e1, e2))) # includes both are NA_crs_\n\t\t\tTRUE\n\t\telse if (is.na(e1) || is.na(e2)) # only one of them is NA_crs_\n\t\t\tFALSE\n\t\telse\n\t\t\tisTRUE(try(CPL_crs_equivalent(e1, e2), silent = TRUE)) # use GDAL's srs1->IsSame(srs2)\n\t}\n}\n\n#' Retrieve coordinate reference system from object\n#'\n#' Retrieve coordinate reference system from sf or sfc object\n#' @name st_crs\n#' @param x numeric, character, or object of class \\link{sf} or \\link{sfc}\n#' @param ... ignored\n#' @export\n#' @return If \\code{x} is numeric, return \\code{crs} object for EPSG:\\code{x};\n#' if \\code{x} is character, return \\code{crs} object for \\code{x};\n#' if \\code{x} is of class \\code{sf} or \\code{sfc}, return its \\code{crs} object.\n#' @details The *crs functions create, get, set or replace the \\code{crs} attribute\n#' of a simple feature geometry list-column. This attribute is of class \\code{crs},\n#' and is a list consisting of \\code{input} (user input, e.g. \"EPSG:4326\" or \"WGS84\"\n#' or a proj4string), and \\code{wkt}, an automatically generated wkt2 representation of the crs.\n#' If \\code{x} is identical to the wkt2 representation, and the CRS has a name, this name\n#' is used for the \\code{input} field.\n#'\n#' Comparison of two objects of class \\code{crs} uses the GDAL function\n#' \\code{OGRSpatialReference::IsSame}.\n#' @return Object of class \\code{crs}, which is a list with elements \\code{input} (length-1 character)\n#' and \\code{wkt} (length-1 character).\n#' Elements may be \\code{NA} valued; if all elements are \\code{NA} the CRS is missing valued, and coordinates are\n#' assumed to relate to an arbitrary Cartesian coordinate system.\nst_crs = function(x, ...) UseMethod(\"st_crs\")\n\n#' @name st_crs\n#' @export\nst_crs.sf = function(x, ...) st_crs(st_geometry(x), ...)\n\n#' @name st_crs\n#' @export\nst_crs.numeric = function(x, ...) {\n\tif (!is.finite(x))\n\t\tNA_crs_\n\telse\n    \tmake_crs(paste0(\"EPSG:\", x))\n}\n\n\n#' @name st_crs\n#' @export\nst_crs.character = function(x, ...) {\n\tif (is.na(x))\n\t\tNA_crs_\n\telse {\n\t\tcrs = make_crs(x)\n\t\tif (is.na(crs))\n\t\t\tstop(paste(\"invalid crs:\", x))\n\t\t# if we input wkt2, and CRS has a name, use it:\n\t\tif (identical(x, crs$wkt) && !identical(crs$Name, \"unknown\"))\n\t\t\tcrs$input = crs$Name\n\t\tcrs\n\t}\n}\n\nfix_crs = function(x) {\n\tif (all(c(\"epsg\", \"proj4string\") %in% names(x))) {\n\t\tmessage(\"old-style crs object detected; please recreate object with a recent sf::st_crs()\")\n\t\tx = unclass(x)\n\t\tif (!is.na(x$epsg))\n\t\t\tst_crs(x$epsg)\n\t\telse\n\t\t\tst_crs(x$proj4string)\n\t} else\n\t\tx\n}\n\n\n#' @name st_crs\n#' @param parameters logical; \\code{FALSE} by default; only for the `st_crs.sfc()` method: if \\code{TRUE} return a classed list of coordinate reference system parameters, with named elements \\code{SemiMajor}, \\code{InvFlattening}, \\code{units_gdal}, \\code{IsVertical}, \\code{WktPretty}, \\code{Wkt}, \\code{Name}, \\code{proj4string}, \\code{epsg}, \\code{yx}, \\code{ProjJson}, \\code{WKT1_ESRI}, \\code{srid} (in authority:code form), \\code{axes} (a data.frame with columns \\code{name} and \\code{orientation}), \\code{gcs_crs} with the WKT of the base geographic coordinate system, \\code{ud_unit}. The list has class \\code{crs_parameters}.\n#' @export\nst_crs.sfc = function(x, ..., parameters = FALSE) {\n\tcrs = fix_crs(attr(x, \"crs\"))\n\tif (isTRUE(parameters)) {\n\t\tp = crs_parameters(crs)\n\t\tp$ud_unit = crs_ud_unit(crs)\n\t\tp\n\t} else\n\t\tcrs\n}\n\n#' @name st_crs\n#' @export\nst_crs.bbox = function(x, ...) {\n\tcrs = attr(x, \"crs\")\n\tif (is.null(crs))\n\t\tNA_crs_\n\telse\n\t\tcrs\n}\n\n#' @name st_crs\n#' @export\nst_crs.CRS = function(x, ...) {\n\tif (is.null(comment(x)) || CPL_proj_version() < \"6.0.0\" || \n\t\t\tCPL_gdal_version() < \"3.0.0\")\n\t\tst_crs(x@projargs)\n\telse {\n\t\tret = st_crs(comment(x))\n\t\tname = ret$Name\n\t\tret$input = if (name == \"unknown\")\n\t\t\t\tx@projargs\n\t\t\telse\n\t\t\t\tname\n\t\tret\n\t}\n}\n\n#' @name st_crs\n#' @export\nst_crs.crs = function(x, ...) x\n\n#' @export\nst_crs.default = function(x, ...) NA_crs_\n\n#' Set or replace coordinate reference system from object\n#'\n#' Set or replace retrieve coordinate reference system from object\n#' @name st_crs\n#' @param value one of (i) character: a string accepted by GDAL, (ii) integer, a valid EPSG value (numeric), or (iii) an object of class \\code{crs}.\n#' @details In case a coordinate reference system is replaced, no transformation takes\n#' place and a warning is raised to stress this.\n#'\n#' @export\n`st_crs<-` = function(x, value) UseMethod(\"st_crs<-\")\n\n#' @name st_crs\n#' @examples\n#' sfc = st_sfc(st_point(c(0,0)), st_point(c(1,1)))\n#' sf = st_sf(a = 1:2, geom = sfc)\n#' st_crs(sf) = 4326\n#' st_geometry(sf)\n#' @export\n`st_crs<-.sf` = function(x, value) {\n\tst_crs(x[[ attr(x, \"sf_column\") ]]) = value\n\tx\n}\n\n# return crs object from crs, integer, or character string\nmake_crs = function(x) {\n\n\tif (inherits(x, \"CRS\")) {\n\t\tx = if (is.null(comment(x)) || (CPL_proj_version() < \"6.0.0\" || \n                    CPL_gdal_version() < \"3.0.0\"))\n\n\t\t\t\tx@projargs\n\t\t\telse\n\t\t\t\tcomment(x) # WKT2\n\t}\n\tif (is.numeric(x) && !is.na(x))\n\t\tx = paste0(\"EPSG:\", x)\n\t# return:\n\tif (is.na(x))\n\t\tNA_crs_\n\telse if (inherits(x, \"crs\"))\n\t\tx\n\telse if (is.character(x)) {\n\t\tif (grepl(\"+init=epsg:\", x) &&\n\t\t\t\tcompareVersion(sf_extSoftVersion()[[\"proj.4\"]], \"6.0.0\") >= 0 &&\n\t\t\t\tcompareVersion(sf_extSoftVersion()[[\"proj.4\"]], \"6.3.1\") < 0) { # nocov start FIXME:\n\t\t\tx = strsplit(x, \" \")[[1]]\n\t\t\tif (length(x) > 1)\n\t\t\t\twarning(paste(\"the following proj4string elements are ignored:\",\n\t\t\t\t\tpaste(x[-1], collapse = \" \"), \"; remove the +init=epsg:XXXX to undo this\"))\n\t\t\tx = paste0(\"EPSG:\", as.integer(substr(x[1], 12, 20))) # nocov end\n\t\t}\n\t\tCPL_crs_from_input(x)\n\t} else\n\t\tstop(paste(\"cannot create a crs from an object of class\", class(x)), call. = FALSE)\n}\n\n#' @name st_crs\n#' @examples\n#' sfc = st_sfc(st_point(c(0,0)), st_point(c(1,1)))\n#' st_crs(sfc) = 4326\n#' sfc\n#' @export\n`st_crs<-.sfc` = function(x, value) {\n\n\tif (is.null(attr(x, \"crs\")))\n\t\tstart_crs = NA_crs_\n\telse\n\t\tstart_crs = st_crs(x)\n\n\tend_crs = make_crs(value)\n\n\tif (!is.na(start_crs) && !is.na(end_crs) && start_crs != end_crs)\n\t\twarning(\"st_crs<- : replacing crs does not reproject data; use st_transform for that\", call. = FALSE)\n\n\tif (is.na(end_crs) && !is.na(start_crs) && isTRUE(st_is_longlat(start_crs)) && any(st_is_full(x)))\n\t\tstop(\"To set the crs to NA, first remove the full polygons; see: st_is_full()\")\n\n\tstructure(x, crs = end_crs)\n}\n\n#' @export\n`st_crs<-.bbox` = function(x, value) {\n\tstructure(x, crs = make_crs(value))\n}\n\n\n#' @name st_crs\n#' @examples\n#' sfc = st_sfc(st_point(c(0,0)), st_point(c(1,1)))\n#' sfc |> st_set_crs(4326) |> st_transform(3857)\n#' @export\nst_set_crs = function(x, value) {\n\tst_crs(x) = value\n\tx\n}\n\n#' Assert whether simple feature coordinates are longlat degrees\n#'\n#' Assert whether simple feature coordinates are longlat degrees\n#' @param x object of class \\link{sf} or \\link{sfc}, or otherwise an object of a class that has an \\link{st_crs} method returning a \\code{crs} object\n#' @return `TRUE` if `x` has geographic coordinates, `FALSE` if it has projected coordinates, or `NA` if \\code{is.na(st_crs(x))}.\n#' @export\nst_is_longlat = function(x) {\n\tcrs = st_crs(x)\n\tif (is.na(crs))\n\t\tNA\n\telse {\n\t\tret = crs_parameters(crs)$IsGeographic\n\t\tif (ret && inherits(x, c(\"sf\", \"sfc\", \"stars\")) && !is.null(attr(x, \"bbox\"))) {\n\t\t\tbb = st_bbox(x)\n\t\t\t# check for potentially meaningless value range:\n\t\t\teps = sqrt(.Machine$double.eps)\n\t\t\tif (all(!is.na(unclass(bb))) &&\n\t\t\t\t\t(bb[\"xmin\"] < (-180-eps) || bb[\"xmax\"] > (360+eps) || bb[\"ymin\"] < (-90-eps) || bb[\"ymax\"] > (90+eps)))\n\t\t\t\twarning(\"bounding box has potentially an invalid value range for longlat data\")\n\t\t}\n\t\tret\n\t}\n}\n\n# a = \"b\" => a is the proj.4 unit (try: cs2cs -lu); \"b\" is the udunits2 unit\nudunits_from_proj = list(\n#   PROJ.4     UDUNITS\n\t`km` =     as_units(\"km\"),\n\t`m` =      as_units(\"m\"),\n\t`dm` =     as_units(\"dm\"),\n\t`cm` =     as_units(\"cm\"),\n\t`mm` =     as_units(\"mm\"),\n\t`kmi` =    as_units(\"nautical_mile\"),\n\t`in` =     as_units(\"in\"),\n\t`ft` =     as_units(\"ft\"),\n\t`yd` =     as_units(\"yd\"),\n\t`mi` =     as_units(\"mi\"),\n\t`fath` =   as_units(\"fathom\"),\n\t`ch` =     as_units(\"chain\"),\n\t`link` =   as_units(\"link\", check_is_valid = FALSE), # not (yet) existing; set in .onLoad()\n \t`us-in` =  as_units(\"us_in\", check_is_valid = FALSE),\n\t`us-ft` =  as_units(\"US_survey_foot\"),\n\t`us-yd` =  as_units(\"US_survey_yard\"),\n\t`us-ch` =  as_units(\"chain\"),\n\t`us-mi` =  as_units(\"US_survey_mile\"),\n\t`ind-yd` = as_units(\"ind_yd\", check_is_valid = FALSE),\n\t`ind-ft` = as_units(\"ind_ft\", check_is_valid = FALSE),\n\t`ind-ch` = as_units(\"ind_ch\", check_is_valid = FALSE),\n\t`kilometre` =  as_units(\"km\"),\n\t`metre` =  as_units(\"m\"),\n\t`decimetre` =     as_units(\"dm\"),\n\t`centimetre` =     as_units(\"cm\"),\n\t`millimetre` =     as_units(\"mm\"),\n\t`nautical mile` = as_units(\"nautical_mile\"),\n\t`Statute mile` = as_units(\"mi\"),\n \t`US survey inch` =  as_units(\"us_in\", check_is_valid = FALSE),\n\t`US survey foot` =  as_units(\"US_survey_foot\"),\n\t`US survey yard` =  as_units(\"US_survey_yard\"),\n\t`US survey chain` =  as_units(\"chain\"),\n\t`US survey mile` =  as_units(\"US_survey_mile\"),\n\t`Indian yard (1937)` = as_units(\"ind_yd\", check_is_valid = FALSE),\n\t`Indian foot (1937)` = as_units(\"ind_ft\", check_is_valid = FALSE),\n\t`Indian chain` = as_units(\"ind_ch\", check_is_valid = FALSE)\n)\n\ncrs_ud_unit = function(x) {\n\tstopifnot(inherits(x, \"crs\"))\n\tif (is.na(x))\n\t\treturn(NULL)\n\n\tx = crs_parameters(x)\n\tif (!is.null(x$units_gdal)) {\n\t\tu = udunits_from_proj[[x$units_gdal]]\n\t\tif (is.null(u)) {\n\t\t\tu = try(as_units(x$units_gdal), silent = TRUE)\n\t\t\tif (inherits(u, \"try-error\"))\n\t\t\t\tu = NULL\n\t\t}\n\t\tu\n\t} else\n\t\tNULL #2049\n}\n\ncrs_parameters = function(x) {\n\tstopifnot(inherits(x, \"crs\"))\n\tif (is.na(x))\n\t\tlist()\n\telse {\n\t\tret = CPL_crs_parameters(x)\n\t\tunits(ret$SemiMajor) = as_units(\"m\")\n\t\tunits(ret$SemiMinor) = as_units(\"m\")\n\t\tret\n\t}\n}\n\nepsg = function(x) {\n\tif (is.na(x))\n\t\tNA_integer_\n\telse if (grepl(\"^EPSG:\", x[[\"input\"]]))\n\t# else if (startsWith(x[[\"input\"]], \"EPSG:\"))\n\t\tas.integer(gsub(\"^EPSG:(\\\\d+)\\\\b.*$\", \"\\\\1\", x[[\"input\"]]))\n\telse\n\t\tcrs_parameters(x)[[\"epsg\"]]\n}\n\nproj4string = function(x) {\n\tif (is.na(x))\n\t\tNA_character_\n\telse\n\t\tcrs_parameters(x)[[\"proj4string\"]]\n}\n\n\n#' @name st_as_text\n#' @param projjson logical; if TRUE, return projjson form (requires GDAL 3.1 and PROJ 6.2), else return well-known-text form\n#' @param pretty logical; if TRUE, print human-readable well-known-text representation of a coordinate reference system\n#' @export\nst_as_text.crs = function(x, ..., projjson = FALSE, pretty = FALSE) {\n\tif (is.na(x))\n\t\tNA_character_\n\telse if (projjson) {\n\t\tif (compareVersion(sf_extSoftVersion()[\"GDAL\"], \"3.1.0\") == -1 || compareVersion(sf_extSoftVersion()[\"proj.4\"], \"6.2.0\") == -1)\n\t\t\tstop(\"ProjJson requires GDAL >= 3.1.0 and PROJ >= 6.2.0\")\n\t\tcrs_parameters(x)$ProjJson\n\t} else { # wkt:\n\t\tif (pretty)\n\t\t\tcrs_parameters(x)$WktPretty\n\t\telse\n\t\t\tcrs_parameters(x)$Wkt\n\t}\n}\n\n\n#' @name st_crs\n#' @details\n#' \\code{NA_crs_} is the \\code{crs} object with missing values for \\code{input} and \\code{wkt}.\n#' @export\nNA_crs_ = structure(\n\tlist(input = NA_character_,\n\t\twkt = NA_character_),\n\tclass = \"crs\")\n\n#' @name st_crs\n#' @export\n#' @method is.na crs\nis.na.crs = function(x) {\n\tidentical(x, NA_crs_)\n}\n\n#' @name st_crs\n#' @param name element name\n#' @export\n#' @examples\n#' st_crs(\"EPSG:3857\")$input\n#' st_crs(3857)$proj4string\n#' @details the `$` method for `crs` objects retrieves named elements\n#' using the GDAL interface; named elements include\n#' `SemiMajor`, `SemiMinor`, `InvFlattening`, `IsGeographic`,\n#' `units_gdal`, `IsVertical`, `WktPretty`, `Wkt`,\n#' `Name`, `proj4string`, `epsg`, `yx`, \n#' `ud_unit`, and `axes` (this may be subject to changes in future GDAL versions).\n#'\n#' Note that not all valid CRS have a corresponding `proj4string`. \n#'\n#' `ud_unit` returns a valid \\link[units]{units} object or `NULL` if units are missing.\n#' @export\n`$.crs` = function(x, name) {\n\n\tif (!is.null(x[[\"proj4string\"]])) { # old-style object:\n\t\twarning(\"CRS uses proj4string, which is deprecated.\")\n\t\tx = st_crs(x[[\"proj4string\"]]) # FIXME: should this be only for some transition period? Add test?\n\t}\n\tif (name == \"ud_unit\")\n\t\tcrs_ud_unit(x)\n\telse if (is.na(x))\n\t\tNA_character_\n\telse if (is.numeric(name) || name %in% names(x))\n\t\tx[[name]]\n\telse {\n\t\tp = crs_parameters(x)\n\t\tif (name %in% names(p))\n\t\t\tp[[name]]\n\t\telse {\n\t\t\ttryNum = function(x) { n = suppressWarnings(as.numeric(x)); if (is.na(n)) x else n }\n\t\t\tp4s = strsplit(p$proj4string, \" \")[[1]]\n\t\t\tp4s2 = strsplit(p4s, \"=\")\n\t\t\tvals = lapply(p4s2, function(x) if (length(x) == 1) TRUE else tryNum(x[2]))\n\t\t\tnames(vals) = substring(sapply(p4s2, function(x) x[1]), 2)\n\t\t\tvals[[name]]\n\t\t}\n\t}\n}\n\n#' @export\nprint.crs = function(x, ...) {\n  cat(\"Coordinate Reference System:\")\n  if (is.na(x)) {\n    cat(\" NA\\n\")\n  } else {\n    cat(\"\\n\")\n    if (is.na(x$input))\n       cat(\"  No user input\\n\")\n    else\n       cat(\"  User input:\", x$input, \"\\n\")\n\n\t# print wkt:\n    if (!is.na(x$wkt))\n      cat(\"  wkt:\\n\", x$wkt, \"\\n\", sep = \"\")\n  }\n}\n\n#' @name st_crs\n#' @export\n#' @details format.crs returns NA if the crs is missing valued, or else\n#' the name of a crs if it is different from \"unknown\", or\n#' else the user input if it was set, or else its \"proj4string\" representation;\nformat.crs = function(x, ...) {\n\tif (is.na(x))\n\t\tNA_character_\n\telse {\n\t\tp = crs_parameters(x)\n\t\tif (p$Name == \"unknown\") {\n\t\t\tif (x$input == \"unknown\")\n\t\t\t\tx$proj4string\n\t\t\telse\n\t\t\t\tx$input\n\t\t} else\n\t\t\tx$Name\n\t}\n}\n\n\n#' @export\nst_crs.Raster = function(x, ...) {\n\tcrsobj <- raster::crs(x)\n\tst_crs(crsobj) # nocov\n}\n\n#' @export\nst_crs.Spatial = function(x, ...) {\n\tif (! requireNamespace(\"sp\", quietly = TRUE))\n\t\tstop(\"package sp required, please install it first\")\n\tst_crs(x@proj4string) # nocov\n}\n\n#' @name st_crs\n#' @param authority_compliant logical; specify whether axis order should be\n#' handled compliant to the authority; if omitted, the current value is printed.\n#' @details\n#' \\code{st_axis_order} can be used to get and set the axis order: \\code{TRUE}\n#' indicates axes order according to the authority\n#' (e.g. EPSG:4326 defining coordinates to be latitude,longitude pairs), \\code{FALSE}\n#' indicates the usual GIS (display) order (longitude,latitude). This can be useful\n#' when data are read, or have to be written, with coordinates in authority compliant order.\n#' The return value is the current state of this (\\code{FALSE}, by default).\n#' @return \\code{st_axis_order} returns the (logical) current value if called without\n#' argument, or (invisibly) the previous value if it is being set.\n#' @export\n#' @examples\n#' pt = st_sfc(st_point(c(0, 60)), crs = 4326)\n#' # st_axis_order() only has effect in GDAL >= 2.5.0:\n#' st_axis_order() # query default: FALSE means interpret pt as (longitude latitude)\n#' st_transform(pt, 3857)[[1]]\n#' old_value = FALSE\n#' if (compareVersion(sf_extSoftVersion()[\"GDAL\"], \"2.5.0\") >= 0)\n#'    (old_value = st_axis_order(TRUE))\n#' # now interpret pt as (latitude longitude), as EPSG:4326 prescribes:\n#' st_axis_order() # query current value\n#' st_transform(pt, 3857)[[1]]\n#' st_axis_order(old_value) # set back to old value\nst_axis_order = function(authority_compliant = logical(0)) {\n\tret = CPL_axis_order_authority_compliant(authority_compliant)\n\tif (length(authority_compliant))\n\t\tinvisible(ret)\n\telse\n\t\tret\n}\n"
  },
  {
    "path": "R/datasets.R",
    "content": "#' North Carolina SIDS data\n#'\n#' Sudden Infant Death Syndrome (SIDS) sample data for North Carolina counties,\n#' two time periods (1974-78 and 1979-84). The details of the columns can be\n#' found in a [spdep package vignette](https://r-spatial.github.io/spdep/articles/sids.html). \n#' Please note that, though this is basically the same as \\code{nc.sids} dataset in spData\n#' package, \\code{nc} only contains a subset of variables. The differences are\n#' also discussed on the vignette.\n#' @format A `sf` object \n#' @name nc\n#' @docType data\n#' @seealso \\url{https://r-spatial.github.io/spdep/articles/sids.html}\n#' @examples\n#' \\donttest{\n#' nc <- st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\n#' }\nNULL\n"
  },
  {
    "path": "R/db.R",
    "content": "#' Read PostGIS table directly, using DBI and binary conversion\n#'\n#' Read PostGIS table directly through DBI and RPostgreSQL interface, converting\n#' Well-Know Binary geometries to sfc\n#' @param query SQL query to select records; see details\n#' @param EWKB logical; is the WKB of type EWKB? if missing, defaults to\n#'   \\code{TRUE}\n#' @param as_tibble logical; should the returned table be of class tibble or data.frame?\n#' @details if \\code{table} is not given but \\code{query} is, the spatial\n#'   reference system (crs) of the table queried is only available in case it\n#'   has been stored into each geometry record (e.g., by PostGIS, when using\n#'   EWKB)\n#' @examples\n#' \\dontrun{\n#' library(RPostgreSQL)\n#' try(conn <- dbConnect(PostgreSQL(), dbname = \"postgis\"))\n#' if (exists(\"conn\") && !inherits(conn, \"try-error\")) {\n#'   x = st_read(conn, \"meuse\", query = \"select * from meuse limit 3;\")\n#'   x = st_read(conn, table = \"public.meuse\")\n#'   print(st_crs(x)) # SRID resolved by the database, not by GDAL!\n#'   dbDisconnect(conn)\n#'  }\n#' }\n#' @name st_read\n#' @details The function will automatically find the `geometry` type columns for\n#'   drivers that support it. For the other drivers, it will try to cast all the\n#'   character columns, which can be slow for very wide tables.\n#' @export\nst_read.DBIObject = function(dsn = NULL,\n                             layer = NULL,\n                             query = NULL,\n                             EWKB = TRUE,\n                             quiet = TRUE,\n                             as_tibble = FALSE,\n                             geometry_column = NULL,\n                             ...) {\n    if (is.null(dsn))\n        stop(\"no connection provided\") # nocov\n\n    if (as_tibble && !requireNamespace(\"tibble\", quietly = TRUE)) {\n        stop(\"package tibble not available: install first?\") # nocov\n    }\n\n    # check that ellipsis contains only what is needed\n    expe <- setdiff(names(list(...)), names(formals(st_sf)))\n    if(length(expe) > 0) {\n        # error,  these arguments would be passed to st_sf\n        suggest <- NULL\n        if(\"table\" %in% expe){\n            suggest <- c(suggest, \"\\nMaybe you should use `layer` rather than `table` ?\")\n        }\n        pref <- if(length(expe) > 1) \"\\t *\" else  \"\"\n        stop(\n            \"Unused arguments: \",\n            if(length(expe) > 1) \"\\n\" else \"\",\n            paste(pref, expe, \"=\", list(...)[expe], collapse = \"\\n\", sep = \" \"),\n            suggest,\n            \"\\nCheck arguments for `st_sf()` for details.\",\n            call. = FALSE\n        )\n    }\n\n    # filter expected warnings (for RPostgreSQL driver)\n    filter_warning <- function(expr, regexp) {\n        wlist <- NULL\n        warning_handler <- function(w) {\n            wlist <<- c(wlist, list(w))\n            invokeRestart(\"muffleWarning\")\n        }\n        msg <- function(x) x$message\n        out <- withCallingHandlers(expr, warning = warning_handler)\n        if(!all(grepl(regexp, wlist))) {\n            lapply(vapply(wlist, msg, character(1)), warning, call. = FALSE)  # nocov\n        }\n        return(out)\n    }\n\n    # Check layer and query conflict\n    if (!is.null(layer)) {\n        if (!is.null(query)) {\n            warning(\"You provided both `layer` and `query` arguments,\",\n                    \" will only use `layer`.\", call. = FALSE)\n        }\n        # capture warnings from RPostgreSQL package\n        if (inherits(dsn, \"PostgreSQLConnection\")) {\n            tbl <- filter_warning(dbReadTable(dsn, layer), \"unrecognized PostgreSQL field type geometry\")\n        } else {\n            tbl <- dbReadTable(dsn, layer)\n        }\n    } else if(is.null(query)) {\n        stop(\"Provide either a `layer` or a `query`\", call. = FALSE)\n    } else {\n        # capture warnings from RPostgreSQL package\n        if (inherits(dsn, \"PostgreSQLConnection\")) {\n            filter_warning(tbl <- dbGetQuery(dsn, query), \"unrecognized PostgreSQL field type geometry\")\n        } else {\n            tbl <- dbGetQuery(dsn, query)\n        }\n    }\n\n    if (is.null(tbl)) {\n        stop(\"Query `\", query, \"` returned no results.\", call. = FALSE)  #nocov\n    }\n\n    if (is.null(geometry_column)) {\n        # scan table for simple features column\n        geometry_column = is_geometry_column(dsn, tbl)\n        tbl[geometry_column] <- lapply(tbl[geometry_column], try_postgis_as_sfc, EWKB = EWKB, conn = dsn)\n    } else {\n        if (!all(geometry_column %in% names(tbl))) {\n            # prepare error message\n            nm <- names(tbl)\n            prefix <- \"\"\n            new_line <- \"\"\n            if(length(nm) > 1) {\n                prefix <- \"  *\"\n                new_line <- \"\\n\"\n            }\n            stop(\"Could not find `geometry_column` (\\\"\", paste(geometry_column, collapse = \"\\\", \\\"\"), \"\\\") \",\n                \"in column names. Available names are:\",\n                new_line,\n                paste(prefix, nm, collapse = \"\\n\", sep = \" \"),\n                call. = FALSE)\n        }\n        tbl[geometry_column] <- lapply(tbl[geometry_column], postgis_as_sfc, EWKB = EWKB, conn = dsn)\n    }\n\n    # if there are no simple features geometries, return a data frame\n    if (! any(vapply(tbl, inherits, logical(1), \"sfc\"))) {\n\t\t# try reading blob columns:\n    \tblob_columns = vapply(tbl, inherits, logical(1), \"blob\")\n\t\tsuccess = FALSE\n\t\tfor (i in which(blob_columns)) {\n\t\t\ttry(sfc <- st_as_sfc(tbl[[i]]), silent = TRUE)\n\t\t\tif (!inherits(sfc, \"try-error\")) {\n\t\t\t\ttbl[[i]] = sfc\n\t\t\t\tsuccess = TRUE\n\t\t\t}\n\t\t}\n    \tif (! success) {\n        \twarning(\"Could not find a simple features geometry column. Will return a `data.frame`.\")\n        \treturn(tbl)\n\t\t}\n    }\n\n    x <- st_sf(tbl, ...)\n\n    if (!quiet) print(x, n = 0) # nocov\n\n    if (as_tibble) {\n        x <- tibble::new_tibble(x, nrow = nrow(x), class = \"sf\")\n    }\n    return(x)\n}\n\n#' @export\nst_read.Pool = function(dsn = NULL, layer = NULL, ...) {\n\tif (! requireNamespace(\"pool\", quietly = TRUE)) # nocov start\n\t\tstop(\"package pool required, please install it first\")\n\tdsn = pool::poolCheckout(dsn)\n\ton.exit(pool::poolReturn(dsn))\n\tst_read(dsn, layer = layer, ...)                # nocov end\n}\n\n\n#' @export\nst_read.PostgreSQLConnection <- function(...) {\n    st_read.DBIObject(...)\n}\n\npostgis_as_sfc <- function(x, EWKB, conn) {\n\tgeom <- st_as_sfc(as_wkb_(x), EWKB = EWKB)\n\tsrid <- attr(geom, \"srid\")\n\tif (!is.null(srid)) {\n\t\tst_crs(geom) = db_find_srid(conn, srid = srid, validate = FALSE)\n\t\tattr(geom, \"srid\") = NULL\n\t\twarning(\"Could not find database srid (\", srid, \") locally; using the remote database definition.\")\n\t}\n\treturn(geom)\n}\n\ntry_postgis_as_sfc <- function(x, EWKB, conn) {\n    tryCatch(postgis_as_sfc(x, EWKB, conn), error = function(...) return(x))\n}\n\nschema_table <- function(conn, table, public = \"public\") {\n\tif (!is.character(table))\n\t\tstop(\"table must be a character vector\", call. = FALSE)\n\n\tif (length(table) == 1L)\n\t\ttable = c(public, table)\n\telse if (length(table) > 2)\n\t\tstop(\"table cannot be longer than 2 (schema, table)\", call. = FALSE)\n\n\tif (anyNA(table))\n\t\tstop(\"table and schema cannot be NA\", call. = FALSE)\n\n\treturn(table)\n}\n\nas_wkb_ <- function(x) {\n\tstructure(x, class = \"WKB\")\n}\n\nget_possibly_new_srid <- function(conn, crs) {\n\n\tdb_crs <- db_find_srid(conn, crs)\n\tif(!is.na(db_crs)) {\n\t\treturn(db_crs)\n\t}\n\n\tdb_crs <- db_find_srtext(conn, crs)\n\tif (!is.na(db_crs)) {\n\t\treturn(db_crs)\n\t}\n\n\tdb_insert_crs(conn, crs)\n}\n\n# Find srid in a database by using the srid\n# @param conn Dababase connection (e.g. `DBI`)\n# @param srid An integer descriing the srid to fetch\n# @param validate if TRUE, then the crs_local is used to validate the remote crs.\n#   Use validate = FALSE when searching for an srid unavailable locally, or when\n#   the wkt is unknown locally.\n# @returns a `crs`\ndb_find_srid = function(conn, crs_local = st_crs(srid), srid = epsg(crs_local), validate = TRUE) {\n    if (validate && is.na(crs_local)) return(st_crs(NA))\n\tif (is.na(srid)) {\n\t\treturn(st_crs(NA))\n\t}\n\n    query <- paste0(\"select srtext from spatial_ref_sys where srid = \", srid)\n    db_crs <- dbGetQuery(conn, query)\n    if (nrow(db_crs) < 1) {\n    \treturn(st_crs(NA))\n    }\n    if (nrow(db_crs) > 1) {\n    \t# TODO: pretty print db_spatial_ref\n    \tstop(\"SRID should be unique, but the database returned \", nrow(db_crs), \" matching crs. \\n\",\n    \t\t db_crs, call. = FALSE)  # nocov\n    }\n    crs_found <- st_crs(db_crs[[\"srtext\"]])\n    crs_found[[\"input\"]] <- build_epsg(srid)\n    if(validate && crs_found != crs_local && !is.na(crs_local)) {\n    \t# TODO: pretty print db_spatial_ref\n        warning(\"Local crs different from database crs. You can inspect the \",\n                \"database crs using `dbReadtable(conn, \\\"spatial_ref_sys\\\")` \",\n                \"and compare it to `st_crs(\", srid,\")`.\")  # nocov\n    }\n    crs_found\n}\n\n# Find database projection using srtext (wkt)\ndb_find_srtext = function(conn, crs_local = st_crs(wkt), wkt = st_as_text(crs_local)) {\n\tif (is.na(crs_local)) return(st_crs(NA))\n\tif (is.na(wkt)) {\n\t\treturn(st_crs(NA))\n\t}\n\n\tquery <- paste0(\"select * from spatial_ref_sys where srtext = '\", wkt, \"'\")\n\tdb_spatial_ref <- DBI::dbGetQuery(conn, query)\n\tif (nrow(db_spatial_ref) < 1) {\n\t\t# need to relax comparison\n\n\t\t# read table, and find equivalent projections using ==\n\t\tquery <- \"select * from spatial_ref_sys where srtext is not null and srtext != ''\"\n\t\tdb_spatial_ref <- DBI::dbGetQuery(conn, query)\n\t\tdb_crs <- lapply(db_spatial_ref[[\"srtext\"]], function(string) try(st_crs(string)))\n\t\treject <- vapply(db_crs, function(x) inherits(x, \"try-error\"), logical(1))\n\t\teq <- vapply(db_crs[!reject], function(x) crs_local == x, logical(1))\n\t\tdb_spatial_ref <- db_spatial_ref[eq, ]\n\t}\n\n\tif (nrow(db_spatial_ref) > 1) {  # nocov start\n\t\t# Use the first match, but warn the user.\n\t\t# Only show first 10 matches\n\t\tdb_spatial_ref <- db_spatial_ref[seq_len(min(nrow(db_spatial_ref), 10)), ]\n\t\t# TODO: make it a warning -- check classes so they can be grabbed in dbWriteTable.DBI\n\t\tmessage(\"Found multiple matching projections, will use srid = \",\n\t\t\t\tdb_spatial_ref[[\"srid\"]][[1]],\n\t\t\t\t\".\\nOther database srid matching the projection WKT description: \",\n\t\t\t\tpaste(db_spatial_ref[[\"srid\"]][-1], collapse = \", \"), \"\\n\",\n\t\t\t\t\"You can suppress this warning by setting the projection to `st_crs(\",\n\t\t\t\tdb_spatial_ref[[\"srid\"]][[1]], \")`.\")\n\t\tdb_spatial_ref <- db_spatial_ref[1, ]\n\t} # nocov end\n\n\tif (nrow(db_spatial_ref) < 1) {\n\t\treturn(st_crs(NA))\n\t} else {\n\t\tcrs_found <- make_empty_crs(db_spatial_ref[[\"srid\"]], db_spatial_ref[[\"srtext\"]])\n\t}\n\n\tif(crs_found != crs_local) {  # nocov start\n\t\twarning(\"Local crs different from database crs. You can inspect the \",\n\t\t\t\t\"database crs using `dbReadtable(conn, \\\"spatial_ref_sys\\\")` \",\n\t\t\t\t\"and compare it to `st_crs(\\\"\", wkt,\"\\\")`.\")\n\t}  # nocov end\n\tcrs_found\n}\n\nmake_empty_crs <- function(epsg = NA, text = NA, wkt = NA) {\n\tif(!is.na(epsg)) {\n\t\tepsg <- build_epsg(epsg)[1]\n\t}\n\tif(is.na(wkt)) {\n\t\twkt = st_as_text(st_crs(text))\n\t}\n\tstructure(\n\t\tlist(\n\t\t\tinput = epsg,\n\t\t\twkt = wkt),\n\t\tclass = \"crs\")\n}\n\nbuild_epsg <- function(auth_srid, auth_name = \"EPSG\") {\n\tpaste0(auth_name, \":\", auth_srid)\n}\n\ndb_insert_crs <- function(conn,\n\t\t\t\t\t\t  crs,\n\t\t\t\t\t\t  srid = epsg(crs),\n\t\t\t\t\t\t  auth_name = \"sf\",\n\t\t\t\t\t\t  auth_srid = srid,\n\t\t\t\t\t\t  wkt = st_as_text(crs),\n\t\t\t\t\t\t  proj4text = proj4string(crs),\n\t\t\t\t\t\t  update = FALSE,\n\t\t\t\t\t\t  verbose = TRUE) {\n\t# fail fast ----------------------------------------------\n\t# We also try to provide all error messages at once\n\terror_msg <- NULL\n\tif (update) {\n\t\tif (is.na(srid)) {\n\t\t\terror_msg <- c(error_msg, paste0(\n\t\t\t   \t\"You need to provide an `srid` to update a projection,  but the `srid` is NA.\",\n\t\t\t   \t\"\\n  Either: \\n  * provide an `srid` or \\n  * use `update = FALSE` to receive an srid\",\n\t\t\t   \tcollapse = \"\"\n\t\t\t   ))\n\t\t}\n\t}\n\tif (is.na(wkt)) {\n\t\terror_msg <- c(error_msg,\n\t\t\t\t\t   \"You need to provide a `wkt` to update the database `spatial_ref_sys`.\")\n\t}\n\tif (!is.null(error_msg)) {\n\t\tn_errors <- length(error_msg)\n\t\tif (n_errors > 1) {\n\t\t\terror_msg <- c(paste0(\"We found \", n_errors, \" errors:\\n\"), error_msg)\n\t\t}\n\t\tstop(paste(error_msg, collapse = \"\\n\"), call. = FALSE)\n\t}\n\t# end tests ---------------------------------------\n\n\tif (is.na(srid)) {\n        srid <- get_new_postgis_srid(conn)\n\t}\n\tif (is.na(auth_srid)) {\n        auth_srid <- auth_srid\n\t}\n\tcrs <- make_empty_crs(epsg = srid, text = wkt)\n\n\tq <- function(x) paste0(\"'\", x, \"'\")\n\tif (update) {\n\t\tquery <- paste(\"UPDATE spatial_ref_sys SET\",\n\t\t\t\t\t   \"auth_name =\", q(auth_name), \", \",\n\t\t\t\t\t   \"auth_srid =\", auth_srid, \", \",\n\t\t\t\t\t   \"srtext =\", q(wkt), \", \",\n\t\t\t\t\t   \"proj4text =\", q(proj4string(crs)),\n\t\t\t\t\t   \"WHERE srid =\", srid, \";\")\n\t} else {\n\t\tquery <- paste(\"INSERT INTO spatial_ref_sys (srid, auth_name, auth_srid, srtext, proj4text)\",\n                      \"VALUES (\",\n                      paste(\n                      \tsrid,\n                      \tq(auth_name),\n                      \tauth_srid,\n                      \tq(wkt),\n                      \tq(proj4string(crs)), sep = \", \"),\n                      \");\")\n    }\n    tryCatch(dbExecute(conn, query),\n            error = function(err) {\n                if(grepl(\"permission denied\", err)) {  # nocov start\n                    stop(\"Write permission denied on table `spatial_ref_sys` because:\",\n                         \"\\n * Local crs is not in the database; \",\n                         \"\\n * Write permission on table `spatial_ref_sys` is denied.\",\n                         \"\\nEither: \",\n                         \"\\n * Change the crs locally using `st_transform()` on your `sf` object;\",\n                         \"\\n * Set the crs to NA using `st_set_crs({your_sf}, NA)`.\",\n                         \"\\n * Grant write access on `spatial_sys_ref`.\",\n                         \"\\n * Ask the database administrator to add your projection with :\",\n                    \t \"\\n ``` sql\\n\", query, \"\\n ```\",\n                    \t call. = FALSE)\n                }\n                stop(err) # nocov end\n            })\n    if (verbose) {\n    \tmessage(\"Inserted local crs: `\", wkt, \"` in database as srid:\", srid, \".\")\n    }\n    return(crs)\n}\n\ndb_check_user_permission <- function(conn, table, permission, strict = FALSE) {\n\tq <- paste0(\"select has_table_privilege('\", table, \"', '\", permission, \"') as has\")\n\tcan <- try(dbReadTable(conn, q)[[\"has\"]])\n\tif (inherits(can, \"try-error\")){\n\t\tif (strict) {\n\t\t\treturn(FALSE)\n\t\t}\n\t\t# we don't know if the user has the permission, but we'll let it pass since\n\t\t# the check isn't strict that way we can see what happens when the permission\n\t\t# is actually needed\n\t\treturn(TRUE)\n\t}\n\treturn(can)\n}\n\ndelete_postgis_crs <- function(conn, crs) {\n    if (is.na(epsg(crs))) stop(\"Missing SRID\")\n    wkt <- st_as_text(crs)\n    query <- paste0(\"DELETE FROM spatial_ref_sys \",\n                   \"WHERE srid = '\", epsg(crs), \"' \",\n                   \"AND srtext = '\", wkt, \"' \",\n                   \"AND proj4text = '\", proj4string(crs), \"';\")\n    dbExecute(conn, query)\n}\n\nget_new_postgis_srid <- function(conn) {\n    query = paste0(\"select srid + 1 as srid from spatial_ref_sys order by srid desc limit 1;\")\n    dbGetQuery(conn, query)[[\"srid\"]]\n}\n\n# for RPostgreSQL\n\n#' Write `sf` object to Database\n#' @inheritParams RPostgreSQL::postgresqlWriteTable\n#' @md\n#' @rdname dbWriteTable\n#' @importMethodsFrom DBI dbWriteTable\n#' @export\nsetMethod(\"dbWriteTable\", c(\"PostgreSQLConnection\", \"character\", \"sf\"),\n          function(conn, name, value, ..., row.names = FALSE, overwrite = FALSE,\n                   append = FALSE, field.types = NULL, binary = TRUE) {\n              if (is.null(field.types)) field.types <- dbDataType(conn, value)\n              tryCatch({\n                  dbWriteTable(conn, name, to_postgis(conn, value, binary),..., row.names = row.names,\n                               overwrite = overwrite, append = append,\n                               field.types = field.types)\n              }, warning=function(w) {\n                  stop(conditionMessage(w), call. = FALSE)\n              })\n          }\n)\n\n#' Write `sf` object to Database\n#' @inheritParams DBI::dbWriteTable\n#' @param conn DBIObject\n#' @param binary Send geometries serialized as Well-Known Binary (WKB);\n#' if `FALSE`, uses Well-Known Text (WKT). Defaults to `TRUE` (WKB).\n#' @param row.names Add a `row.name` column, or a vector of length `nrow(obj)`\n#' containing row.names; default `FALSE`.\n#' @param overwrite Will try to `drop` table before writing; default `FALSE`.\n#' @param append Append rows to existing table; default `FALSE`.\n#' @param field.types default `NULL`. Allows to override type conversion from R\n#' to PostgreSQL. See `dbDataType()` for details.\n#' @md\n#' @rdname dbWriteTable\n#' @importMethodsFrom DBI dbWriteTable dbExistsTable\n#' @export\nsetMethod(\"dbWriteTable\", c(\"DBIObject\", \"character\", \"sf\"),\n\t\t  function(conn, name, value, ..., row.names = FALSE, overwrite = FALSE,\n\t\t  \t\t append = FALSE, field.types = NULL, binary = TRUE) {\n\t\t  \tif (is.null(field.types)) field.types <- dbDataType(conn, value)\n\n\t\t   \t# DBI cannot set field types with append, but if the table does not exist,\n\t\t  \t# we need to set the field type.\n\t\t  \tif (append) {\n\t\t  \t\tif (!dbExistsTable(conn, name)) {\n\t\t  \t\t\tappend <- FALSE\n\t\t  \t\t} else {\n\t\t  \t\t\tfield.types <- NULL\n\t\t  \t\t}\n\t\t  \t}\n\t\t  \t\n\t\t  \tdbWriteTable(conn, name, to_postgis(conn, value, binary),..., row.names = row.names,\n\t\t  \t\t\t\t overwrite = overwrite, append = append,\n\t\t  \t\t\t\t field.types = field.types)\n\t\t  }\n)\n\nto_postgis <- function(conn, x, binary) {\n\tgeom_col <- vapply(x, inherits, TRUE, what = \"sfc\")\n\tx[geom_col] <- lapply(x[geom_col], sync_crs, conn = conn)\n\tif (binary) {\n\t\tx[geom_col] <- lapply(x[geom_col], db_binary)\n\t} else {\n\t\tx[geom_col] <- lapply(x[geom_col], st_as_text, EWKT = TRUE)\n\t}\n\tx <- as.data.frame(x)\n\tclean_columns(x, factorsAsCharacter = TRUE)\n}\n\n# Version of st_as_binary that allows locally invalid srids\ndb_binary <- function(x) {\n\tst_as_binary(x, EWKB = TRUE, hex = TRUE, pureR = FALSE, srid = epsg(st_crs(x)))\n}\n\nsync_crs <- function(conn, geom) {\n    crs <- st_crs(geom)\n    srid <- epsg(crs)\n    if (is.na(crs) || is.na(srid)) {\n        if (is.na(st_as_text(crs)))\n            crs <- st_crs(NA)\n        else {\n            crs <- get_possibly_new_srid(conn, crs)\n        }\n    }\n    st_set_crs(geom, crs)\n}\n\n#' Determine database type for R vector\n#'\n#' @export\n#' @rdname dbDataType\n#' @importMethodsFrom DBI dbDataType\nsetMethod(\"dbDataType\", c(\"PostgreSQLConnection\", \"sf\"), function(dbObj, obj) {\n\tdtyp <- vapply(obj, RPostgreSQL::dbDataType, character(1), dbObj =  dbObj)\n\tgtyp <- vapply(obj, inherits, TRUE, what = \"sfc\")\n\tdtyp[gtyp] <- \"geometry\"\n\t# explicit cast for units\n\tgtyp <- vapply(obj, inherits, TRUE, what = \"units\")\n\tdtyp[gtyp] <- \"numeric\"\n\treturn(dtyp)\n})\n\n#' Determine database type for R vector\n#'\n#' @export\n#' @rdname dbDataType\n#' @importClassesFrom DBI DBIObject\n#' @importMethodsFrom DBI dbDataType\n#' @param dbObj DBIObject driver or connection.\n#' @param obj Object to convert\nsetMethod(\"dbDataType\", c(\"DBIObject\", \"sf\"), function(dbObj, obj) {\n    dtyp <- vapply(obj, DBI::dbDataType, character(1), dbObj =  dbObj)\n    gtyp <- vapply(obj, inherits, TRUE, what = \"sfc\")\n    dtyp[gtyp] <- \"geometry\"\n    # explicit cast for units\n    gtyp <- vapply(obj, inherits, TRUE, what = \"units\")\n    dtyp[gtyp] <- \"numeric\"\n    return(dtyp)\n})\n\n#' Check if the columns could be of a coercable type for sf\n#'\n#' @param con database connection\n#' @param x inherits data.frame\n#' @param classes classes inherited\nis_geometry_column <- function(con, x, classes = \"\") UseMethod(\"is_geometry_column\")\n\n#' @export\nis_geometry_column.PqConnection <- function(con, x, classes = c(\"pq_geometry\")) {\n    vapply(x, inherits, logical(1), classes)\n}\n\n#' @export\nis_geometry_column.default <- function(con, x, classes = c(\"character\")) {\n    # try all character columns (in conjunction with try_postgis_as_sfc)\n    vapply(x, function(x) inherits(x, classes) && !all(is.na(x)),\n    \t   FUN.VALUE = logical(1))\n}\n\n# https://github.com/r-spatial/sf/issues/1195 :\n# RPostgres::dbGetQuery returns geometry columns of class pq_geometry:\n#' @name st_as_sfc\n#' @export\nst_as_sfc.pq_geometry <- function(x, ..., EWKB = TRUE, spatialite = FALSE,\n\t\tpureR = FALSE, crs = NA_crs_) { # nocov start\n  st_as_sfc.WKB(x, ..., EWKB = EWKB, spatiallite = spatialite, pureR = pureR, crs = crs)\n} # nocov end\n"
  },
  {
    "path": "R/defunct.R",
    "content": "#' @title Deprecated functions in `sf`\n#' @name sf-defunct\n#' @description\n#' These functions are provided for compatibility with older version of `sf`.\n#' They will eventually be completely removed.\n#' \n#' * Use [st_read()] instead of `st_read_db()`.\n#' * Use [st_write()] instead_of `st_write_db()`\n#' @param conn open database connection\n#' @param table table name\n#' @param geom_column deprecated. Geometry column name\n#' @details The `geom_column` argument is deprecated. The function will\n#' automatically find the `geometry` type columns. For the `RPostgreSQL` drivers\n#' it will try to cast all the character columns, which can be long for very wide\n#' tables.\n#' @inheritParams st_read\n#' @export\n#' @keywords internal\nst_read_db <- function(conn = NULL, table = NULL, query = NULL,\n\t\t\t\t\t   geom_column = NULL, EWKB = TRUE, ...) {\n\t.Defunct(\"st_read\")\n}\n\n#' @rdname sf-defunct\n#' @inheritParams DBI::dbWriteTable\n#' @export\nst_write_db <- function(conn = NULL, obj, table = deparse(substitute(obj)), ...,\n\t\t\t\t\t\tdrop = FALSE, append = FALSE) {\n\t.Defunct(\"st_write\")\n}\n"
  },
  {
    "path": "R/gdal_utils.R",
    "content": "# nocov start\nresampling_method = function(option = \"near\") {\n\tif (length(option) != 1)\n\t\tstop(\"warper options should have length 1\")\n\tswitch(option,\n\t\tnear = 0,\n\t\tbilinear = 1,\n\t\tcubic = 2,\n\t\tcubicspline = 3,\n\t\tlanczos = 4,\n\t\taverage = 5,\n\t\tmode = 6,\n\t\tmax = 8,\n\t\tmin = 9,\n\t\tmed = 10,\n\t\tq1 = 11,\n\t\tq3 = 12,\n\t\tsum = 13,\n\t\tstop(paste(\"unknown option:\", options))\n\t)\n}\n# nocov end\n\n#' Native interface to gdal utils\n#' @name gdal_utils\n#' @param util character; one of \\code{info}, \\code{warp}, \\code{rasterize}, \\code{translate}, \\code{vectortranslate} (for ogr2ogr), \\code{buildvrt}, \\code{demprocessing}, \\code{nearblack}, \\code{grid}, \\code{mdiminfo} and \\code{mdimtranslate} (the last two requiring GDAL 3.1), \\code{ogrinfo} (requiring GDAL 3.7), \\code{footprint} (requiring GDAL 3.8)\n#' @param source character; name of input layer(s); for \\code{warp}, \\code{buidvrt} or \\code{mdimtranslate} this can be more than one\n#' @param destination character; name of output layer\n#' @param options character; options for the utility\n#' @param config_options named character vector with GDAL config options, like \\code{c(option1=value1, option2=value2)}\n#' @param quiet logical; if \\code{TRUE}, suppress printing the output for \\code{info} and \\code{mdiminfo}, and suppress printing progress\n#' @param processing character; processing options for \\code{demprocessing}\n#' @param colorfilename character; name of color file for \\code{demprocessing} (mandatory if \\code{processing=\"color-relief\"})\n#' @param read_only logical; only for `ogrinfo`: if `TRUE`, source is opened in read-only mode\n#' @return \\code{info} returns a character vector with the raster metadata; all other utils return (invisibly) a logical indicating success (i.e., \\code{TRUE}); in case of failure, an error is raised.\n#' @export\n#' @seealso \\link{gdal_addo} for adding overlays to a raster file; \\link{st_layers} to query geometry type(s) and crs from layers in a (vector) data source\n#' @examples\n#'\n#' if (compareVersion(sf_extSoftVersion()[\"GDAL\"], \"2.1.0\") == 1) {\n#' # info utils can be used to list information about a raster\n#' # dataset. More info: https://gdal.org/programs/gdalinfo.html\n#' in_file <- system.file(\"tif/geomatrix.tif\", package = \"sf\")\n#' gdal_utils(\"info\", in_file, options = c(\"-mm\", \"-proj4\"))\n#'\n#' # vectortranslate utils can be used to convert simple features data between\n#' # file formats. More info: https://gdal.org/programs/ogr2ogr.html\n#' in_file <- system.file(\"shape/storms_xyz.shp\", package=\"sf\")\n#' out_file <- paste0(tempfile(), \".gpkg\")\n#' gdal_utils(\n#'   util = \"vectortranslate\",\n#'   source = in_file,\n#'   destination = out_file, # output format must be specified for GDAL < 2.3\n#'   options = c(\"-f\", \"GPKG\")\n#' )\n#' # The parameters can be specified as c(\"name\") or c(\"name\", \"value\"). The\n#' # vectortranslate utils can perform also various operations during the\n#' # conversion process. For example, we can reproject the features during the\n#' # translation.\n#' gdal_utils(\n#'   util = \"vectortranslate\",\n#'   source = in_file,\n#'   destination = out_file,\n#'   options = c(\n#'   \"-f\", \"GPKG\", # output file format for GDAL < 2.3\n#'   \"-s_srs\", \"EPSG:4326\", # input file SRS\n#'   \"-t_srs\", \"EPSG:2264\", # output file SRS\n#'   \"-overwrite\"\n#'   )\n#' )\n#' st_read(out_file)\n#' # The parameter s_srs had to be specified because, in this case, the in_file\n#' # has no associated SRS.\n#' st_read(in_file)\n#' }\ngdal_utils = function(util = \"info\", source, destination, options = character(0),\n\t\tquiet = !(util %in% c(\"info\", \"gdalinfo\", \"ogrinfo\", \"vectorinfo\", \n\t\t\t\t\t\t\t  \"mdiminfo\")) || (\"-multi\" %in% options),\n\t\tprocessing = character(0), colorfilename = character(0),\n\t\tconfig_options = character(0), read_only = FALSE) {\n\n\tstopifnot(is.character(options), is.character(config_options))\n\tif (!quiet && \"-multi\" %in% options)\n\t\tstop(\"with -multi quiet should be set to FALSE\")\n#\tif (\"-co\" %in% options)\n#\t\toptions[\"-co\" == options] = \"-oo\"\n\tif (\"-oo\" %in% options) { # -oo indicating opening options\n\t\tooi = which(\"-oo\" == options)\n\t\too = options[ooi + 1]\n\t\toptions = options[-c(ooi, ooi+1)]\n\t} else\n\t\too = character(0)\n\tif (\"-doo\" %in% options) { # -oo indicating destination opening options\n\t\tooi = which(\"-doo\" == options)\n\t\tdoo = options[ooi + 1]\n\t\toptions = options[-c(ooi, ooi+1)]\n\t} else\n\t\tdoo = character(0)\n\n\tif (\"-doo\" %in% options) # -oo indicating opening options\n\t\tstop(\"-doo options not (yet) supported; consider raising an issue\") # nocov\n\n\tquiet = as.logical(quiet)\n\n\tret = switch(util,\n\t\t\tgdalinfo =, info = CPL_gdalinfo(if (missing(source)) character(0) else source, options, oo, config_options),\n\t\t\tvectorinfo =, ogrinfo = CPL_ogrinfo(if (missing(source)) character(0) else source, options, oo, config_options, \n\t\t\t\t\t\t\t\t\t\t\t\tisTRUE(read_only) || \"-ro\" %in% options),\n\t\t\twarp = CPL_gdalwarp(source, destination, options, oo, doo, config_options, quiet, \"-overwrite\" %in% options),\n\t\t\twarper = CPL_gdal_warper(source, destination, as.integer(resampling_method(options)),\n\t\t\t\too, doo, config_options, quiet), # nocov\n\t\t\trasterize = {  # nocov start\n\t\t\t\toverwrite = any(options %in% c(\"-of\", \"-a_nodata\", \"-init\", \"-a_srs\", \"-co\",\n\t\t\t\t\t\t\"-te\", \"-tr\", \"-tap\", \"-ts\", \"-ot\")) # https://gdal.org/programs/gdal_rasterize.html\n\t\t\t\tCPL_gdalrasterize(source, destination, options, oo, doo, config_options, overwrite, quiet)\n\t\t\t}, # nocov end\n\t\t\tfootprint = CPL_gdalfootprint(source, destination, options, oo, config_options, quiet),\n\t\t\ttranslate = CPL_gdaltranslate(source, destination, options, oo, config_options, quiet),\n\t\t\tvectortranslate = CPL_gdalvectortranslate(source, destination, options, oo, doo, config_options, quiet),\n\t\t\tbuildvrt = CPL_gdalbuildvrt(if (missing(source)) character(0) else source, destination, options, oo, config_options, quiet),\n\t\t\tdemprocessing = CPL_gdaldemprocessing(source, destination, options, processing, colorfilename, oo, config_options, quiet),\n\t\t\tnearblack = CPL_gdalnearblack(source, destination, options, oo, config_options, doo, quiet),\n\t\t\tgrid = CPL_gdalgrid(source, destination, options, oo, config_options, quiet),\n\t\t\tmdiminfo = CPL_gdalmdiminfo(source, options, oo, config_options),\n\t\t\tmdimtranslate = CPL_gdalmdimtranslate(source, destination, options, oo, config_options, quiet),\n\t\t\tstop(paste(\"unknown util value for gdal_utils:\", util))\n\t\t)\n\n\tif (util %in% c(\"info\", \"gdalinfo\", \"ogrinfo\", \"vectorinfo\", \"mdiminfo\")) {\n\t\tif (! quiet)\n\t\t\tcat(ret)\n\t\tinvisible(ret)\n\t} else { # ret indicates error:\n\t\tif (ret)\n\t\t\tstop(paste0(\"gdal_utils \", util, \": an error occured\"))\n\t\tinvisible(! ret) # success\n\t}\n}\n"
  },
  {
    "path": "R/geom-measures.R",
    "content": "# unary, interfaced through GEOS:\n\n#' Dimension, simplicity, validity or is_empty queries on simple feature geometries\n#' @name geos_query\n#' @param x object of class \\code{sf}, \\code{sfc} or \\code{sfg}\n#' @param NA_if_empty logical; if TRUE, return NA for empty geometries\n#' @return st_dimension returns a numeric vector with 0 for points, 1 for lines, 2 for surfaces, and, if \\code{NA_if_empty} is \\code{TRUE}, \\code{NA} for empty geometries.\n#' @export\n#' @examples\n#' x = st_sfc(\n#' \tst_point(0:1),\n#' \tst_linestring(rbind(c(0,0),c(1,1))),\n#' \tst_polygon(list(rbind(c(0,0),c(1,0),c(0,1),c(0,0)))),\n#' \tst_multipoint(),\n#' \tst_linestring(),\n#' \tst_geometrycollection())\n#' st_dimension(x)\n#' st_dimension(x, FALSE)\nst_dimension = function(x, NA_if_empty = TRUE)\n\tCPL_gdal_dimension(st_geometry(x), NA_if_empty)\n\n#' @name geos_measures\n#' @export\n#' @return If the coordinate reference system of \\code{x} was set, these functions return values with unit of measurement; see \\link[units]{set_units}.\n#'\n#' st_area returns the area of each feature geometry, computed in the coordinate reference system used. In case \\code{x} has geodetic coordinates (unprojected), then if `sf_use_s2()` is `FALSE` \\link[lwgeom:geod]{st_geod_area} is used for area calculation, if it is `TRUE` then \\link[s2:s2_is_collection]{s2_area} is used: the former assumes an ellipsoidal shape, the latter a spherical shape of the Earth. In case of projected data, areas are computed in flat space. The argument `...` can be used to specify `radius` to \\link[s2:s2_is_collection]{s2_area}, to modify the Earth radius.\n#' @examples\n#' b0 = st_polygon(list(rbind(c(-1,-1), c(1,-1), c(1,1), c(-1,1), c(-1,-1))))\n#' b1 = b0 + 2\n#' b2 = b0 + c(-0.2, 2)\n#' x = st_sfc(b0, b1, b2)\n#' st_area(x)\nst_area = function(x, ...) UseMethod(\"st_area\")\n\n#' @name geos_measures\n#' @export\nst_area.sfc = function(x, ...) {\n\tif (isTRUE(st_is_longlat(x))) {\n\t\tif (sf_use_s2())\n\t\t\tunits::set_units(s2::s2_area(x, ...), \"m^2\", mode = \"standard\")\n\t\telse {\n\t\t\tif (! requireNamespace(\"lwgeom\", quietly = TRUE))\n\t\t\t\tstop(\"package lwgeom required, please install it first\")\n\t\t\tlwgeom::st_geod_area(x)\n\t\t}\n\t} else {\n\t\ta = CPL_area(x) # ignores units: units of coordinates\n\t\tif (!is.null(u <- st_crs(x)$ud_unit))\n\t\t\tunits(a) = u^2 # coord units\n\t\tif (!is.null(to_m <- st_crs(x)$to_meter) && !is.na(to_m) && !inherits(a, \"units\"))\n\t\t\ta = set_units(a * to_m^2, \"m^2\", mode = \"standard\")\n\t\ta\n\t}\n}\n\n#' @export\nst_area.sf = function(x, ...) st_area(st_geometry(x), ...)\n\n#' @export\nst_area.sfg = function(x, ...) st_area(st_geometry(x), ...)\n\n#' @name geos_measures\n#' @export\n#' @return st_length returns the length of a \\code{LINESTRING} or \\code{MULTILINESTRING} geometry, using the coordinate reference system.  \\code{POINT}, \\code{MULTIPOINT}, \\code{POLYGON} or \\code{MULTIPOLYGON} geometries return zero.\n#' If coordinates are geodetic (i.e., long/lat), great circle calculations are carried out on a sphere (if `sf_use_s2()` is `TRUE`), or a geodesic line is computed on an ellipsoid (if `sf_use_s2()` is `FALSE`). For all other non-geodetic, projected coordinate systems, length calculations are planar, Euclidean distance calculations in the units of the coordinate system.\n#' @seealso \\link{st_dimension}, \\link{st_cast} to convert geometry types\n#'\n#' @examples\n#' line = st_sfc(st_linestring(rbind(c(30,30), c(40,40))), crs = 4326)\n#' st_length(line)\n#'\n#' outer = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\n#' hole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\n#' hole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\n#'\n#' poly = st_polygon(list(outer, hole1, hole2))\n#' mpoly = st_multipolygon(list(\n#' \tlist(outer, hole1, hole2),\n#' \tlist(outer + 12, hole1 + 12)\n#' ))\n#'\n#' st_length(st_sfc(poly, mpoly))\nst_length = function(x, ...) {\n\tx = st_geometry(x)\n\n\tif (isTRUE(st_is_longlat(x))) {\n\t\tif (sf_use_s2())\n\t\t\tset_units(s2::s2_length(x, ...), \"m\", mode = \"standard\")\n\t\telse {\n\t\t\tif (! requireNamespace(\"lwgeom\", quietly = TRUE))\n\t\t\t\tstop(\"package lwgeom required, please install it first\")\n\t\t\tlwgeom::st_geod_length(x)\n\t\t}\n\t} else {\n\t\tret = CPL_length(x)\n\t\tret[is.nan(ret)] = NA\n\t\tif (!is.null(u <- st_crs(x)$ud_unit))\n\t\t\tunits(ret) = u\n\t\tif (!is.null(to_m <- st_crs(x)$to_meter) && !is.na(to_m) && !inherits(ret, \"units\"))\n\t\t\tret = set_units(ret * to_m, \"m\", mode = \"standard\")\n\t\tret\n\t}\n}\n\nmessage_longlat = function(caller) {\n\tm = paste(\"although coordinates are longitude/latitude,\", caller, \"assumes that they are planar\")\n\tm = strwrap(m, width = getOption(\"width\"))\n\tmessage(paste0(m, collapse = \"\\n\"))\n}\n\n\n#' @name geos_measures\n#' @export\n#' @examples\n#' if (requireNamespace(\"lwgeom\", quietly = TRUE)) {\n#'   st_perimeter(poly)\n#'   st_perimeter(mpoly)\n#' }\nst_perimeter = function(x, ...) {\n\tx = st_geometry(x)\n\tif (sf_use_s2() && isTRUE(st_is_longlat(x))) { # for spherical geometries we use s2 \n\t\tif (!requireNamespace(\"s2\", quietly = TRUE))\n\t\t\tstop(\"package s2 required to calculate the perimeter of spherical geometries\")\n\t\t# ensure units are set to meters \n\t\tunits::set_units(\n\t\t\ts2::s2_perimeter(x, ...), \n\t\t\t\"m\", \n\t\t\tmode = \"standard\"\n\t\t)\n\t} else { # non-spherical geometries use lwgeom:\n\t\tif (isTRUE(st_is_longlat(x)))\n\t\t\tunits::set_units(st_length(st_boundary(x)), \"m\", mode = \"standard\")\n\t\telse { \n\t\t\tif (!requireNamespace(\"lwgeom\", quietly = TRUE))\n\t\t\t\tstop(\"package lwgeom required, please install it first\")\n\t\t\t# note that units are handled appropriately by lwgeom\n\t\t\tlwgeom::st_perimeter_lwgeom(x)\n\t\t}\n\t}\n}\n\n#' Compute geometric measurements\n#'\n#' Compute Euclidean or great circle distance between pairs of geometries; compute, the area or the length of a set of geometries.\n#' @name geos_measures\n#' @param x object of class \\code{sf}, \\code{sfc} or \\code{sfg}\n#' @param y object of class \\code{sf}, \\code{sfc} or \\code{sfg}, defaults to \\code{x}\n#' @param ... passed on to \\link[s2]{s2_distance}, \\link[s2]{s2_distance_matrix}, or \\link[s2]{s2_perimeter}\n#' @param dist_fun deprecated\n#' @param by_element logical; if \\code{TRUE}, return a vector with distance between the first elements of \\code{x} and \\code{y}, the second, etc; an error is raised if \\code{x} and \\code{y} are not the same length. If \\code{FALSE}, return the dense matrix with all pairwise distances.\n#' @param which character; for Cartesian coordinates only: one of \\code{Euclidean}, \\code{Hausdorff} or \\code{Frechet}; for geodetic coordinates, great circle distances are computed; see details\n#' @param par for \\code{which} equal to \\code{Hausdorff} or \\code{Frechet}, optionally use a value between 0 and 1 to densify the geometry\n#' @param tolerance ignored if \\code{st_is_longlat(x)} is \\code{FALSE}; otherwise, if set to a positive value, the first distance smaller than \\code{tolerance} will be returned, and true distance may be smaller; this may speed up computation. In meters, or a \\code{units} object convertible to meters.\n#' @return If \\code{by_element} is \\code{FALSE} \\code{st_distance} returns a dense numeric matrix of dimension length(x) by length(y); otherwise it returns a numeric vector the same length as \\code{x} and \\code{y} with an error raised if the lengths of \\code{x} and \\code{y} are unequal. Distances involving empty geometries are \\code{NA}.\n#' @details great circle distance calculations use by default spherical distances (\\link[s2]{s2_distance} or \\link[s2]{s2_distance_matrix}); if \\code{sf_use_s2()} is \\code{FALSE}, ellipsoidal distances are computed using \\link[lwgeom]{st_geod_distance} which uses function \\code{geod_inverse} from GeographicLib (part of PROJ); see Karney, Charles FF, 2013, Algorithms for geodesics, Journal of Geodesy 87(1), 43--55\n#' @examples\n#' p = st_sfc(st_point(c(0,0)), st_point(c(0,1)), st_point(c(0,2)))\n#' st_distance(p, p)\n#' st_distance(p, p, by_element = TRUE)\n#' @export\nst_distance = function(x, y, ..., dist_fun, by_element = FALSE, \n\t\twhich = ifelse(isTRUE(st_is_longlat(x)), \"Great Circle\", \"Euclidean\"), \n\t\tpar = 0.0, tolerance = 0.0) {\n\n\tmissing_y = FALSE\n\tif (missing(y)) {\n\t\ty = x\n\t\tmissing_y = TRUE\n\t} else\n\t\tstopifnot(st_crs(x) == st_crs(y))\n\n\tif (! missing(dist_fun))\n\t\tstop(\"dist_fun is deprecated: lwgeom is used for distance calculation\")\n\n\tx = st_geometry(x)\n\ty = st_geometry(y)\n\tif (by_element)\n\t\tstopifnot(!missing_y, length(x) == length(y))\n\n\tif (isTRUE(st_is_longlat(x)) && which == \"Great Circle\") {\n\t\tif (sf_use_s2()) {\n\t\t\tret = if (by_element)\n\t\t\t\t\ts2::s2_distance(x, y, ...)\n\t\t\t\telse\n\t\t\t\t\ts2::s2_distance_matrix(x, y, ...)\n\t\t\tset_units(ret, \"m\", mode = \"standard\")\n\t\t} else { # lwgeom:\n\t\t\tif (which != \"Great Circle\")\n\t\t\t\tstop(\"for non-great circle distances, data should be projected; see st_transform()\")\n\t\t\tunits(tolerance) = as_units(\"m\")\n\t\t\tif (by_element) {\n\t\t\t\tcrs = st_crs(x)\n\t\t\t\tdist_ll = function(x, y, tolerance)\n\t\t\t\t\tlwgeom::st_geod_distance(st_sfc(x, crs = crs), st_sfc(y, crs = crs),\n\t\t\t\t\t\ttolerance = tolerance)\n\t\t\t\td = mapply(dist_ll, x, y, tolerance = tolerance)\n\t\t\t\tunits(d) = units(st_crs(x)$SemiMajor)\n\t\t\t\td\n\t\t\t} else\n\t\t\t\tlwgeom::st_geod_distance(x, y, tolerance)\n\t\t}\n\t} else {\n\t\td = if (by_element) {\n\t\t\t\tif (inherits(x, \"sfc_POINT\") && inherits(y, \"sfc_POINT\") && which == \"Euclidean\") {\n\t\t\t\t\txc = st_coordinates(x)\n\t\t\t\t\tyc = st_coordinates(y)\n\t\t\t\t\tsqrt((xc[,1] - yc[,1])^2 + (xc[,2] - yc[,2])^2)\n\t\t\t\t} else\n\t\t\t\t  CPL_geos_dist_by_element(x, y, which, par)\n\t\t\t} else {\n\t\t\t\tif (missing_y && inherits(x, \"sfc_POINT\") && which == \"Euclidean\") {\n\t\t\t\t\tm = as.matrix(stats::dist(cc <- st_coordinates(x)))\n\t\t\t\t\te = is.na(cc[,1])\n\t\t\t\t\tdiag(m)[e] = NA_real_\n\t\t\t\t\tm\n\t\t\t\t} else\n\t\t\t\t\tCPL_geos_dist(x, y, which, par)\n\t\t\t}\n\t\tif (!is.null(u <- st_crs(x)$ud_unit))\n\t\t\tunits(d) = u\n\t\td\n\t}\n}\n\ncheck_lengths = function (dots) {\n\tlengths <- vapply(dots, length, integer(1))\n\tnon_constant_lengths <- unique(lengths[lengths != 1])\n\tif (length(non_constant_lengths) == 0) {\n\t\t1\n\t}\n\telse if (length(non_constant_lengths) == 1) {\n\t\tnon_constant_lengths\n\t}\n\telse {\n\t\tlengths_label <- paste0(non_constant_lengths, collapse = \", \")\n\t\tstop(sprintf(\"Incompatible lengths: %s\", lengths_label), \n\t\t\tcall. = FALSE)\n\t}\n}\n\nrecycle_common = function (dots) {\n\tfinal_length <- check_lengths(dots)\n\tlapply(dots, rep_len, final_length)\n}\n\n\n#' Project point on linestring, interpolate along a linestring\n#'\n#' Project point on linestring, interpolate along a linestring\n#' @param line object of class `sfc` with `LINESTRING` geometry\n#' @param point object of class `sfc` with `POINT` geometry\n#' @param normalized logical; if `TRUE`, use or return distance normalised to 0-1\n#' @name st_line_project_point\n#' @returns `st_line_project` returns the distance(s) of point(s) along line(s), when projected on the line(s)\n#' @export\n#' @details\n#' arguments `line`, `point` and `dist` are recycled to common length when needed\n#' @examples\n#' st_line_project(st_as_sfc(\"LINESTRING (0 0, 10 10)\"), st_as_sfc(c(\"POINT (0 0)\", \"POINT (5 5)\")))\n#' st_line_project(st_as_sfc(\"LINESTRING (0 0, 10 10)\"), st_as_sfc(\"POINT (5 5)\"), TRUE)\nst_line_project = function(line, point, normalized = FALSE) {\n\tstopifnot(inherits(line, \"sfc\"), inherits(point, \"sfc\"),\n\t\tall(st_dimension(line) == 1), all(st_dimension(point) == 0),\n\t\tis.logical(normalized), length(normalized) == 1,\n\t\tst_crs(line) == st_crs(point))\n\tline = st_cast(line, \"LINESTRING\")\n\tpoint = st_cast(point, \"POINT\")\n\tif (isTRUE(st_is_longlat(line)))\n\t\tmessage_longlat(\"st_project_point\")\n\trecycled = recycle_common(list(line, point))\n\tCPL_line_project(recycled[[1]], recycled[[2]], normalized)\n}\n"
  },
  {
    "path": "R/geom-predicates.R",
    "content": "#' @name geos_query\n#' @export\n#' @return st_is_simple returns a logical vector, indicating for each geometry whether it is simple (e.g., not self-intersecting)\n#' @examples\n#' ls = st_linestring(rbind(c(0,0), c(1,1), c(1,0), c(0,1)))\n#' st_is_simple(st_sfc(ls, st_point(c(0,0))))\nst_is_simple = function(x) {\n\tx = st_geometry(x)\n\tnot_full = !sfc_is_full(x)\n\tret = rep(TRUE, length(x))\n\tret[not_full] = CPL_geos_is_simple(x[not_full])\n\tret\n}\n\n#' @name geos_query\n#' @export\n#' @return st_is_empty returns for each geometry whether it is empty\n#' @examples\n#' ls = st_linestring(rbind(c(0,0), c(1,1), c(1,0), c(0,1)))\n#' st_is_empty(st_sfc(ls, st_point(), st_linestring()))\nst_is_empty = function(x) sfc_is_empty(st_geometry(x)) \n  # used to call\n  # CPL_geos_is_empty(st_geometry(x))\n  # but this avoids a R -> WKB -> GEOS conversion\n\nis_symmetric = function(operation, pattern) {\n\tif (!is.na(pattern)) {\n\t\tm = matrix(sapply(1:9, function(i) substr(pattern, i, i)), 3, 3)\n\t\tisTRUE(all(m == t(m)))\n\t} else\n\t\tisTRUE(operation %in% c(\"intersects\", \"touches\", \"overlaps\", \"disjoint\", \"equals\"))\n}\n\n# binary, interfaced through GEOS or S2:\n\n# [1] X \"s2_contains_matrix\"    X \"s2_covered_by_matrix\"\n# [3] X \"s2_covers_matrix\"      X \"s2_disjoint_matrix\"\n# [5] X \"s2_distance_matrix\"    X \"s2_dwithin_matrix\"\n# [7] X \"s2_equals_matrix\"      X \"s2_intersects_matrix\"\n# [9] \"s2_max_distance_matrix\"    \"s2_may_intersect_matrix\"\n#[11] X \"s2_touches_matrix\"     X \"s2_within_matrix\"\n\n# returning matrix, distance or relation string -- the work horse is:\nst_geos_binop = function(op, x, y, par = 0.0, pattern = NA_character_,\n\t\tsparse = TRUE, prepared = FALSE, model = \"closed\", ...,\n\t\tremove_self = FALSE, retain_unique = FALSE,\n\t\tby_element = FALSE) {\n\n\tlonglat = inherits(x, \"s2geography\") || isTRUE(st_is_longlat(x))\n\tif (by_element) {\n\t\tif (missing(y))\n\t\t\tstop(\"y is required when by_element = TRUE\")\n\t\tif (inherits(x, c(\"sf\", \"sfc\")) && inherits(y, c(\"sf\", \"sfc\")))\n\t\t\tstopifnot(st_crs(x) == st_crs(y))\n\t\tx = st_geometry(x)\n\t\ty = st_geometry(y)\n\t\tstopifnot(length(x) == length(y))\n\t\tif (longlat && sf_use_s2() && op %in% c(\"intersects\", \"contains\", \"within\",\n\t\t\t\t\"covers\", \"covered_by\", \"disjoint\", \"equals\", \"touches\")) {\n\t\t\tfn = get(paste0(\"s2_\", op), envir = getNamespace(\"s2\"))\n\t\t\tfn(x, y, s2::s2_options(model = model, ...))\n\t\t} else {\n\t\t\tif (longlat && !(op %in% c(\"equals\", \"equals_exact\")))\n\t\t\t\tmessage_longlat(paste0(\"st_\", op))\n\t\t\tCPL_geos_binop_by_element(x, y, op, par, pattern, prepared)[[1]]\n\t\t}\n\t} else {\n\t\tif (missing(y))\n\t\t\ty = x\n\t\telse if (inherits(x, c(\"sf\", \"sfc\")) && inherits(y, c(\"sf\", \"sfc\")))\n\t\t\tstopifnot(st_crs(x) == st_crs(y))\n\t\tif (longlat && sf_use_s2() && op %in% c(\"intersects\", \"contains\", \"within\",\n\t\t\t\t\"covers\", \"covered_by\", \"disjoint\", \"equals\", \"touches\")) {\n\t\t\tfn = get(paste0(\"s2_\", op, \"_matrix\"), envir = getNamespace(\"s2\")) # get op function\n\t\t\tlst = fn(x, y, s2::s2_options(model = model, ...)) # call function\n\t\t\tid = if (is.null(row.names(x)))\n\t\t\t\t\tas.character(seq_along(lst))\n\t\t\t\telse\n\t\t\t\t\trow.names(x)\n\t\t\tsgbp(lst, predicate = op, region.id = id, ncol = length(st_geometry(y)), sparse,\n\t\t\t\tremove_self = remove_self, retain_unique = retain_unique)\n\t\t} else {\n\t\t\tif (longlat && !(op %in% c(\"equals\", \"equals_exact\")))\n\t\t\t\tmessage_longlat(paste0(\"st_\", op))\n\t\t\tif (prepared && is_symmetric(op, pattern) &&\n\t\t\t\t\tlength(dx <- st_dimension(x)) && length(dy <- st_dimension(y)) &&\n\t\t\t\t\tisTRUE(all(dx == 0)) && isTRUE(all(dy == 2))) {\n\t\t\t\tt(st_geos_binop(op, y, x, par = par, pattern = pattern, sparse = sparse, \n\t\t\t\t\tprepared = prepared, remove_self = remove_self, retain_unique = retain_unique,\n\t\t\t\t\t...))\n\t\t\t} else {\n\t\t\t\tret = CPL_geos_binop(st_geometry(x), st_geometry(y), op, par, pattern, prepared)\n\t\t\t\tif (length(ret) == 0 || is.null(dim(ret[[1]]))) {\n\t\t\t\t\tid = if (is.null(row.names(x)))\n\t\t\t\t\t\t\tas.character(seq_along(ret))\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\trow.names(x)\n\t\t\t\t\tsgbp(ret, predicate = op, region.id = id, ncol = length(st_geometry(y)), sparse,\n\t\t\t\t\t\tremove_self = remove_self, retain_unique = retain_unique)\n\t\t\t\t} else # CPL_geos_binop returned a matrix, e.g. from op = \"relate\"\n\t\t\t\t\tret[[1]]\n\t\t\t}\n\t\t}\n\t}\n}\n#' Compute DE9-IM relation between pairs of geometries, or match it to a given pattern\n#' @param x object of class \\code{sf}, \\code{sfc} or \\code{sfg}\n#' @param y object of class \\code{sf}, \\code{sfc} or \\code{sfg}\n#' @param pattern character; define the pattern to match to, see details.\n#' @param sparse logical; should a sparse matrix be returned (`TRUE`) or a dense matrix?\n#' @param ... may be used to specify `by_element=TRUE` to return a vector with element-wise relations or matches\n#' @return In case \\code{pattern} is not given, \\code{st_relate} returns a dense \\code{character} matrix; element `[i,j]` has nine characters, referring to the DE9-IM relationship between `x[i]` and `y[j]`, encoded as IxIy,IxBy,IxEy,BxIy,BxBy,BxEy,ExIy,ExBy,ExEy where I refers to interior, B to boundary, and E to exterior, and e.g. BxIy the dimensionality of the intersection of the the boundary of `x[i]` and the interior of `y[j]`, which is one of: 0, 1, 2, or F; digits denoting dimensionality of intersection, F denoting no intersection. When \\code{pattern} is given, a dense logical matrix or sparse index list returned with matches to the given pattern; see \\link{st_intersects} for a description of the returned matrix or list. See also \\url{https://en.wikipedia.org/wiki/DE-9IM} for further explanation.\n#' @export\n#' @examples\n#' p1 = st_point(c(0,0))\n#' p2 = st_point(c(2,2))\n#' pol1 = st_polygon(list(rbind(c(0,0),c(1,0),c(1,1),c(0,1),c(0,0)))) - 0.5\n#' pol2 = pol1 + 1\n#' pol3 = pol1 + 2\n#' st_relate(st_sfc(p1, p2), st_sfc(pol1, pol2, pol3))\n#' sfc = st_sfc(st_point(c(0,0)), st_point(c(3,3)))\n#' grd = st_make_grid(sfc, n = c(3,3))\n#' st_intersects(grd)\n#' st_relate(grd, pattern = \"****1****\") # sides, not corners, internals\n#' st_relate(grd, pattern = \"****0****\") # only corners touch\n#' st_rook = function(a, b = a) st_relate(a, b, pattern = \"F***1****\")\n#' st_rook(grd)\n#' # queen neighbours, see \\url{https://github.com/r-spatial/sf/issues/234#issuecomment-300511129}\n#' st_queen <- function(a, b = a) st_relate(a, b, pattern = \"F***T****\")\nst_relate = function(x, y, pattern = NA_character_, sparse = !is.na(pattern), ...) {\n\tif (!is.na(pattern)) {\n\t\tstopifnot(is.character(pattern), length(pattern) == 1, nchar(pattern) == 9)\n\t\tst_geos_binop(\"relate_pattern\", x, y, pattern = pattern, sparse = sparse, ...)\n\t} else\n\t\tst_geos_binop(\"relate\", x, y, sparse = FALSE, ...)\n}\n\n#' Geometric binary predicates on pairs of simple feature geometry sets\n#'\n#' Geometric binary predicates on pairs of simple feature geometry sets\n#' @name geos_binary_pred\n#' @param x object of class \\code{sf}, \\code{sfc} or \\code{sfg}\n#' @param y object of class \\code{sf}, \\code{sfc} or \\code{sfg}; if missing, \\code{x} is used\n#' @param sparse logical; should a sparse index list be returned (`TRUE`) or a dense logical matrix? See below.\n#' @inheritDotParams s2::s2_options\n#' @param prepared logical; prepare geometry for `x`, before looping over `y`? See Details.\n#' @param by_element logical; if `TRUE`, return logical vector with x-y pair-wise predicate values\n#' @details If \\code{prepared} is \\code{TRUE}, and \\code{x} contains POINT geometries and \\code{y} contains polygons, then the polygon geometries are prepared, rather than the points.\n#' @return If \\code{sparse=FALSE}, \\code{st_predicate} (with \\code{predicate} e.g. \"intersects\") returns a dense logical matrix with element \\code{i,j} equal to \\code{TRUE} when \\code{predicate(x[i], y[j])} (e.g., when geometry of feature i and j intersect); if \\code{sparse=TRUE}, an object of class \\code{\\link{sgbp}} is returned, which is a sparse list representation of the same matrix, with list element \\code{i} an integer vector with all indices \\code{j} for which \\code{predicate(x[i],y[j])} is \\code{TRUE} (and hence a zero-length integer vector if none of them is \\code{TRUE}). From the dense matrix, one can find out if one or more elements intersect by \\code{apply(mat, 1, any)}, and from the sparse list by \\code{lengths(lst) > 0}, see examples below. If `by_element=TRUE`, return a vector of pair-wise predicate values.\n#' @details For most predicates, a spatial index is built on argument \\code{x}; see \\url{https://r-spatial.org/r/2017/06/22/spatial-index.html}.\n#' Specifically, \\code{st_intersects}, \\code{st_disjoint}, \\code{st_touches} \\code{st_crosses}, \\code{st_within}, \\code{st_contains}, \\code{st_contains_properly}, \\code{st_overlaps}, \\code{st_equals}, \\code{st_covers} and \\code{st_covered_by} all build spatial indexes for more efficient geometry calculations. \\code{st_relate}, \\code{st_equals_exact}, and do not; \\code{st_is_within_distance} uses a spatial index for geographic coordinates when \\code{sf_use_s2()} is true.\n#'\n#' If \\code{y} is missing, `st_predicate(x, x)` is effectively called, and a square matrix is returned with diagonal elements `st_predicate(x[i], x[i])`.\n#'\n#' Sparse geometry binary predicate (\\code{\\link{sgbp}}) lists have the following attributes: \\code{region.id} with the \\code{row.names} of \\code{x} (if any, else \\code{1:n}), \\code{ncol} with the number of features in \\code{y}, and \\code{predicate} with the name of the predicate used.\n#'\n#' @note For intersection on pairs of simple feature geometries, use\n#' the function \\code{\\link{st_intersection}} instead of \\code{st_intersects}.\n#'\n#' @examples\n#' pts = st_sfc(st_point(c(.5,.5)), st_point(c(1.5, 1.5)), st_point(c(2.5, 2.5)))\n#' pol = st_polygon(list(rbind(c(0,0), c(2,0), c(2,2), c(0,2), c(0,0))))\n#' (lst = st_intersects(pts, pol))\n#' (mat = st_intersects(pts, pol, sparse = FALSE))\n#' # which points fall inside a polygon?\n#' apply(mat, 1, any)\n#' lengths(lst) > 0\n#' # which points fall inside the first polygon?\n#' st_intersects(pol, pts)[[1]]\n#' # remove duplicate geometries:\n#' p1 = st_point(0:1)\n#' p2 = st_point(2:1)\n#' p = st_sf(a = letters[1:8], geom = st_sfc(p1, p1, p2, p1, p1, p2, p2, p1))\n#' st_equals(p)\n#' st_equals(p, remove_self = TRUE)\n#' (u = st_equals(p, retain_unique = TRUE))\n#' # retain the records with unique geometries:\n#' p[-unlist(u),]\n#' @export\nst_intersects\t= function(x, y, sparse = TRUE, ..., by_element = FALSE) UseMethod(\"st_intersects\")\n\n#' @export\nst_intersects.sfc = function(x, y, sparse = TRUE, prepared = TRUE, ...)\n\tst_geos_binop(\"intersects\", x, y, sparse = sparse, prepared = prepared, ...)\n\n#' @export\nst_intersects.sf = function(x, y, sparse = TRUE, prepared = TRUE, ...)\n\tst_geos_binop(\"intersects\", x, y, sparse = sparse, prepared = prepared, ...)\n\n#' @export\nst_intersects.sfg = function(x, y, sparse = TRUE, prepared = TRUE, ...)\n\tst_geos_binop(\"intersects\", x, y, sparse = sparse, prepared = prepared, ...)\n\n\n#' @name geos_binary_pred\n#' @export\nst_disjoint\t\t= function(x, y = x, sparse = TRUE, prepared = TRUE, ...) {\n\t# st_geos_binop(\"disjoint\", x, y, sparse = sparse, prepared = prepared) -> didn't use STRtree\n\tint = st_geos_binop(\"intersects\", x, y, sparse = sparse, prepared = prepared, ...)\n\t# disjoint = !intersects :\n\tif (sparse)\n\t\tsgbp(lapply(int, function(g) setdiff(seq_along(st_geometry(y)), g)),\n\t\t\tpredicate = \"disjoint\",\n\t\t\tncol = attr(int, \"ncol\"),\n\t\t\tregion.id = attr(int, \"region.id\"))\n\telse\n\t\t!int\n}\n\n#' @name geos_binary_pred\n#' @export\nst_touches\t\t= function(x, y, sparse = TRUE, prepared = TRUE, ...)\n\tst_geos_binop(\"touches\", x, y, sparse = sparse, prepared = prepared, ...)\n\n#' @name geos_binary_pred\n#' @export\nst_crosses\t\t= function(x, y, sparse = TRUE, prepared = TRUE, ...)\n\tst_geos_binop(\"crosses\", x, y, sparse = sparse, prepared = prepared, ...)\n\n#' @name geos_binary_pred\n#' @export\nst_within\t= function(x, y, sparse = TRUE, prepared = TRUE, ...)\n\tst_geos_binop(\"within\", x, y, sparse = sparse, prepared = prepared, ...)\n\n#' @name geos_binary_pred\n#' @param model character; polygon/polyline model; one of\n#' \"open\", \"semi-open\" or \"closed\"; see Details.\n#' @details for \\code{model}, see https://github.com/r-spatial/s2/issues/32\n#' @export\nst_contains\t= function(x, y, sparse = TRUE, prepared = TRUE, ..., model = \"open\")\n\tst_geos_binop(\"contains\", x, y, sparse = sparse, prepared = prepared, ..., model = model)\n\n#' @name geos_binary_pred\n#' @export\n#' @details `st_contains_properly(A,B)` is true if A intersects B's interior, but not its edges or exterior; A contains A, but A does not properly contain A.\n#'\n#' See also \\link{st_relate} and \\url{https://en.wikipedia.org/wiki/DE-9IM} for a more detailed description of the underlying algorithms.\nst_contains_properly = function(x, y, sparse = TRUE, prepared = TRUE, ...) {\n\tif (! prepared)\n\t\tstop(\"non-prepared geometries not supported for st_contains_properly\")\n\tst_geos_binop(\"contains_properly\", x, y, sparse = sparse, prepared = TRUE, ...)\n}\n\n#' @name geos_binary_pred\n#' @export\nst_overlaps\t\t= function(x, y, sparse = TRUE, prepared = TRUE, ...)\n\tst_geos_binop(\"overlaps\", x, y, sparse = sparse, prepared = prepared, ...)\n\n#' @name geos_binary_pred\n#' @param retain_unique logical; if `TRUE` (and `y` is missing) return only indexes of points larger than the current index; this can be used to select unique geometries, see examples. This argument can be used for all geometry predicates; see also \\link{distinct.sf} to find records where geometries AND attributes are distinct.\n#' @param remove_self logical; if `TRUE` (and `y` is missing) return only indexes of geometries different from the current index; this can be used to omit self-intersections; see examples. This argument can be used for all geometry predicates\n#' @export\nst_equals\t\t= function(x, y, sparse = TRUE, prepared = FALSE, ..., \n\t\t\t\t\t\t\tretain_unique = FALSE, remove_self = FALSE) {\n\tif (prepared)\n\t\tstop(\"prepared geometries not supported for st_equals\")\n\tst_geos_binop(\"equals\", x, y, sparse = sparse, ..., \n\t\t\t\t  retain_unique = retain_unique, remove_self = remove_self)\n}\n\n#' @name geos_binary_pred\n#' @export\nst_covers = function(x, y, sparse = TRUE, prepared = TRUE, ..., model = \"closed\")\n\tst_geos_binop(\"covers\", x, y, sparse = sparse, prepared = prepared, ..., model = model)\n\n\n#' @name geos_binary_pred\n#' @export\nst_covered_by = function(x, y = x, sparse = TRUE, prepared = TRUE, ..., model = \"closed\")\n\tst_geos_binop(\"covered_by\", x, y, sparse = sparse, prepared = prepared, ...)\n\n\n#' @name geos_binary_pred\n#' @export\n#' @param par numeric; parameter used for \"equals_exact\" (margin);\n#' @details \\code{st_equals_exact} returns true for two geometries of the same type and their vertices corresponding by index are equal up to a specified tolerance.\nst_equals_exact = function(x, y, par, sparse = TRUE, prepared = FALSE, ...) {\n\tif (prepared)\n\t\tstop(\"prepared geometries not supported for st_equals_exact\")\n\tst_geos_binop(\"equals_exact\", x, y, par = par, sparse = sparse, ...)\n}\n\n#' @name geos_binary_pred\n#' @export\n#' @param dist distance threshold; geometry indexes with distances smaller or equal to this value are returned; numeric value or units value having distance units.\nst_is_within_distance = function(x, y = x, dist, sparse = TRUE, ..., remove_self = FALSE) {\n\n\tret = if (isTRUE(st_is_longlat(x))) {\n\t\t\tunits(dist) = as_units(\"m\") # might convert\n\t\t\tr = if (sf_use_s2()) {\n\t\t\t\t\tif (inherits(dist, \"units\"))\n\t\t\t\t\t\tdist = drop_units(dist)\n\t\t\t\t\ts2::s2_dwithin_matrix(x, y, dist, ...)\n\t\t\t\t} else {\n\t\t\t\t\tif (!requireNamespace(\"lwgeom\", quietly = TRUE) || \n\t\t\t\t\t\t\tutils::packageVersion(\"lwgeom\") <= \"0.1-2\")\n\t\t\t\t\t\tstop(\"lwgeom > 0.1-2 required: install first?\")\n\t\t\t\t\tlwgeom::st_geod_distance(x, y, tolerance = dist, sparse = TRUE)\n\t\t\t\t}\n\t\t\tsgbp(r, predicate = \"is_within_distance\", region.id = seq_along(x), \n\t\t\t\tremove_self = remove_self, ncol = length(st_geometry(y)))\n\t\t} else {\n\t\t\tif (!is.null(st_crs(x)$ud_unit))\n\t\t\t\tunits(dist) = st_crs(x)$ud_unit # might convert\n\t\t\tst_geos_binop(\"is_within_distance\", x, y, par = dist, sparse = sparse, remove_self = remove_self, ...)\n\t\t}\n\tif (!sparse)\n\t\tas.matrix(ret)\n\telse\n\t\tret\n}\n"
  },
  {
    "path": "R/geom-transformers.R",
    "content": "\n# unary, returning geometries\n\n#' Geometric unary operations on simple feature geometry sets\n#'\n#' Geometric unary operations on simple feature geometries. These are all generics, with methods for \\code{sfg}, \\code{sfc} and \\code{sf} objects, returning an object of the same class. All operations work on a per-feature basis, ignoring all other features.\n#' @name geos_unary\n#' @param x object of class \\code{sfg}, \\code{sfc} or \\code{sf}\n#' @param dist numeric or object of class `units`; buffer distance(s) for all, or for each of the elements in \\code{x}. \n#' In case \\code{x} has geodetic coordinates (lon/lat) and `sf_use_s2()` is `TRUE`, a numeric \n#' `dist` is taken as distance in meters and a `units` object in `dist` is converted to meters.\n#' In case \\code{x} has geodetic coordinates (lon/lat) and `sf_use_s2()` is `FALSE`, a numeric \n#' `dist` is taken as degrees, and a `units` object in `dist` is converted to `arc_degree` (and warnings are issued).\n#' In case \\code{x} does not have geodetic coordinates (projected) then\n#' numeric `dist` is assumed to have the units of the coordinates, and a `units` `dist` is converted to those if `st_crs(x)` is not `NA`.\n#' @param nQuadSegs integer; number of segments per quadrant (fourth of a circle), for all or per-feature; see details\n#' @param endCapStyle character; style of line ends, one of 'ROUND', 'FLAT', 'SQUARE'; see details\n#' @param joinStyle character; style of line joins, one of 'ROUND', 'MITRE', 'BEVEL'; see details\n#' @param mitreLimit numeric; limit of extension for a join if \\code{joinStyle} 'MITRE' is used (default 1.0, minimum 0.0); see details\n#' @param singleSide logical; if \\code{TRUE}, single-sided buffers are returned for linear geometries,\n#' in which case negative \\code{dist} values give buffers on the right-hand side, positive on the left; see details\n#' @param ... in `st_buffer` passed on to  [s2::s2_buffer_cells()], otherwise ignored\n#' @return an object of the same class of \\code{x}, with manipulated geometry.\n#' @export\n#' @details \\code{st_buffer} computes a buffer around this geometry/each geometry. Depending on the spatial\n#' coordinate system, a different engine (GEOS or S2) can be used, which have different function\n#' arguments. The \\code{nQuadSegs}, \\code{endCapsStyle}, \\code{joinStyle}, \\code{mitreLimit} and\n#' \\code{singleSide} parameters only work if the GEOS engine is used (i.e. projected coordinates or\n#' when \\code{sf_use_s2()} is set to \\code{FALSE}). See \\href{https://postgis.net/docs/ST_Buffer.html}{postgis.net/docs/ST_Buffer.html}\n#' for details. The \\code{max_cells} and \\code{min_level} parameters ([s2::s2_buffer_cells()]) work with the S2\n#' engine (i.e. geographic coordinates) and can be used to change the buffer shape (e.g. smoothing). \n#' The S2 engine returns a polygon _around_ a number of S2 cells that\n#' contain the buffer, and hence will always have an area larger than the\n#' true buffer, depending on `max_cells`, and will be non-smooth when sufficiently zoomed in. \n#' The GEOS engine will return line segments between points\n#' on the circle, and so will always be _smaller_ than the true\n#' buffer, and be smooth, depending on the number of segments `nQuadSegs`.\n#' A negative `dist` value for geodetic coordinates using S2 does not give a proper (geodetic) buffer.\n#' \n#' @examples\n#'\n#' ## st_buffer, style options (taken from rgeos gBuffer)\n#' l1 = st_as_sfc(\"LINESTRING(0 0,1 5,4 5,5 2,8 2,9 4,4 6.5)\")\n#' op = par(mfrow=c(2,3))\n#' plot(st_buffer(l1, dist = 1, endCapStyle=\"ROUND\"), reset = FALSE, main = \"endCapStyle: ROUND\")\n#' plot(l1,col='blue',add=TRUE)\n#' plot(st_buffer(l1, dist = 1, endCapStyle=\"FLAT\"), reset = FALSE, main = \"endCapStyle: FLAT\")\n#' plot(l1,col='blue',add=TRUE)\n#' plot(st_buffer(l1, dist = 1, endCapStyle=\"SQUARE\"), reset = FALSE, main = \"endCapStyle: SQUARE\")\n#' plot(l1,col='blue',add=TRUE)\n#' plot(st_buffer(l1, dist = 1, nQuadSegs=1), reset = FALSE, main = \"nQuadSegs: 1\")\n#' plot(l1,col='blue',add=TRUE)\n#' plot(st_buffer(l1, dist = 1, nQuadSegs=2), reset = FALSE, main = \"nQuadSegs: 2\")\n#' plot(l1,col='blue',add=TRUE)\n#' plot(st_buffer(l1, dist = 1, nQuadSegs= 5), reset = FALSE, main = \"nQuadSegs: 5\")\n#' plot(l1,col='blue',add=TRUE)\n#' par(op)\n#'\n#'\n#' l2 = st_as_sfc(\"LINESTRING(0 0,1 5,3 2)\")\n#' op = par(mfrow = c(2, 3))\n#' plot(st_buffer(l2, dist = 1, joinStyle=\"ROUND\"), reset = FALSE, main = \"joinStyle: ROUND\")\n#' plot(l2, col = 'blue', add = TRUE)\n#' plot(st_buffer(l2, dist = 1, joinStyle=\"MITRE\"), reset = FALSE, main = \"joinStyle: MITRE\")\n#' plot(l2, col= 'blue', add = TRUE)\n#' plot(st_buffer(l2, dist = 1, joinStyle=\"BEVEL\"), reset = FALSE, main = \"joinStyle: BEVEL\")\n#' plot(l2, col= 'blue', add=TRUE)\n#' plot(st_buffer(l2, dist = 1, joinStyle=\"MITRE\" , mitreLimit=0.5), reset = FALSE,\n#'    main = \"mitreLimit: 0.5\")\n#' plot(l2, col = 'blue', add = TRUE)\n#' plot(st_buffer(l2, dist = 1, joinStyle=\"MITRE\",mitreLimit=1), reset = FALSE,\n#'    main = \"mitreLimit: 1\")\n#' plot(l2, col = 'blue', add = TRUE)\n#' plot(st_buffer(l2, dist = 1, joinStyle=\"MITRE\",mitreLimit=3), reset = FALSE,\n#'    main = \"mitreLimit: 3\")\n#' plot(l2, col = 'blue', add = TRUE)\n#' par(op)\n#'\n#' # compare approximation errors depending on S2 or GEOS backend:\n#' # geographic coordinates, uses S2:\n#' x = st_buffer(st_as_sf(data.frame(lon=0,lat=0), coords=c(\"lon\",\"lat\"),crs='OGC:CRS84'), \n#'       units::as_units(1,\"km\"))\n#' y = units::set_units(st_area(x), \"km^2\")\n#' # error: postive, default maxcells = 1000\n#' (units::drop_units(y)-pi)/pi\n#' x = st_buffer(st_as_sf(data.frame(lon=0,lat=0), coords=c(\"lon\",\"lat\"),crs='OGC:CRS84'), \n#'       units::as_units(1,\"km\"), max_cells=1e5)\n#' y = units::set_units(st_area(x), \"km^2\")\n#' # error: positive but smaller:\n#' (units::drop_units(y)-pi)/pi\n#' \n#' # no CRS set: assumes Cartesian (projected) coordinates\n#' x = st_buffer(st_as_sf(data.frame(lon=0,lat=0), coords=c(\"lon\",\"lat\")), 1)\n#' y = st_area(x)\n#' # error: negative, nQuadSegs default at 30\n#' ((y)-pi)/pi\n#' x = st_buffer(st_as_sf(data.frame(lon=0,lat=0), coords=c(\"lon\",\"lat\")), 1, nQuadSegs = 100)\n#' y = st_area(x)\n#' # error: negative but smaller:\n#' ((y)-pi)/pi\nst_buffer = function(x, dist, nQuadSegs = 30,\n\t\t\t\t\t endCapStyle = \"ROUND\", joinStyle = \"ROUND\", mitreLimit = 1.0, singleSide = FALSE, ...)\n\tUseMethod(\"st_buffer\")\n\n#' @export\nst_buffer.sfg = function(x, dist, nQuadSegs = 30,\n\t\t\t\t\t\t endCapStyle = \"ROUND\", joinStyle = \"ROUND\", mitreLimit = 1.0, singleSide = FALSE, ...)\n\tget_first_sfg(st_buffer(st_sfc(x), dist, nQuadSegs = nQuadSegs, endCapStyle = endCapStyle,\n\t\tjoinStyle = joinStyle, mitreLimit = mitreLimit, singleSide = singleSide, ...))\n\n.process_style_opts = function(endCapStyle, joinStyle, mitreLimit, singleSide) {\n\tstyls = list(with_styles = FALSE, endCapStyle = NA, joinStyle = NA, mitreLimit = NA)\n\tif (endCapStyle == \"ROUND\" && joinStyle == \"ROUND\" && mitreLimit == 1\n\t\t\t&& all(singleSide == FALSE))\n\t\treturn(styls)\n\tecs = match(endCapStyle, c(\"ROUND\", \"FLAT\", \"SQUARE\"))\n\tjs = match(joinStyle, c(\"ROUND\", \"MITRE\", \"BEVEL\"))\n\tif (is.na(mitreLimit) || !mitreLimit > 0) stop(\"mitreLimit must be > 0\")\n\tif (is.na(ecs)) stop(\"endCapStyle must be 'ROUND', 'FLAT', or 'SQUARE'\")\n\tif (is.na(js))  stop(\"joinStyle must be 'ROUND', 'MITRE', or 'BEVEL'\")\n\tif (anyNA(singleSide)) stop(\"singleSide should be TRUE or FALSE\")\n\tstyls$with_styles = TRUE\n\tstyls$endCapStyle = ecs\n\tstyls$joinStyle = js\n\tstyls$mitreLimit = mitreLimit\n\tstyls\n}\n#' @export\nst_buffer.sfc = function(x, dist, nQuadSegs = 30,\n\t\t\t\t\t\t endCapStyle = \"ROUND\", joinStyle = \"ROUND\", mitreLimit = 1.0,\n\t\t\t\t\t\t singleSide = FALSE, ...) {\n\tlonglat = isTRUE(st_is_longlat(x))\n\tdist_n = dist\n\tif (inherits(dist_n, \"units\"))\n\t\tdist_n = drop_units(dist_n)\n\tif (longlat && sf_use_s2() && all(dist_n >= 0.0)) {\n#\t\tif (!missing(nQuadSegs) || !missing(endCapStyle) || !missing(joinStyle) ||\n#\t\t\t\t!missing(mitreLimit) || !missing(singleSide))\n#\t\t\twarning(\"all buffer style parameters are ignored; set st_use_s2(FALSE) first to use them\")\n\t\tif (inherits(dist, \"units\")) {\n\t\t\tif (!inherits(try(units(dist) <- as_units(\"rad\"), silent = TRUE), \"try-error\"))\n\t\t\t\treturn(st_as_sfc(s2::s2_buffer_cells(x, dist, radius = 1, ...),\n\t\t\t\t\tcrs = st_crs(x)))\n\t\t\tunits(dist) = as_units(\"m\") # make sure has dimension length, possibly convert\n\t\t\tdist = drop_units(dist)\n\t\t}\n\t\tst_as_sfc(s2::s2_buffer_cells(x, dist, ...), crs = st_crs(x))\n\t} else {\n\t\tif (longlat) {\n\t\t\twarning(\"st_buffer does not correctly buffer longitude/latitude data\")\n\t\t\tif (inherits(dist, \"units\"))\n\t\t\t\tunits(dist) = as_units(\"arc_degrees\")\n\t\t\telse\n\t\t\t\tmessage(\"dist is assumed to be in decimal degrees (arc_degrees).\")\n\t\t} else if (inherits(dist, \"units\")) {\n\t\t\tif (is.na(st_crs(x)))\n\t\t\t\tstop(\"x does not have a crs set: can't convert units\")\n\t\t\tif (is.null(st_crs(x)$units))\n\t\t\t\tstop(\"x has a crs without units: can't convert units\")\n\t\t\tif (!is.null(st_crs(x)$ud_unit))\n\t\t\t\tunits(dist) = st_crs(x)$ud_unit\n\t\t}\n\t\tdist = rep(dist, length.out = length(x))\n\t\tnQ = rep(nQuadSegs, length.out = length(x))\n\t\tstyles = .process_style_opts(endCapStyle, joinStyle, mitreLimit, singleSide)\n\t\tif (styles$with_styles) {\n\t\t\tendCapStyle = rep(styles$endCapStyle, length.out = length(x))\n\t\t\tjoinStyle = rep(styles$joinStyle, length.out = length(x))\n\t\t\tmitreLimit = rep(styles$mitreLimit, length.out = length(x))\n\t\t\tsingleSide = rep(as.logical(singleSide), length.out = length(x))\n\t\t\tif (any(endCapStyle == 2) && any(st_geometry_type(x) == \"POINT\" | st_geometry_type(x) == \"MULTIPOINT\"))\n\t\t\t\tstop(\"Flat capstyle is incompatible with POINT/MULTIPOINT geometries\") # nocov\n\t\t\tif (inherits(dist, \"units\"))\n\t\t\t\tdist = drop_units(dist)\n\t\t\tif (any(dist < 0) && any(st_dimension(x) < 1))\n\t\t\t\tstop(\"Negative dist values may only be used with 1-D or 2-D geometries\") # nocov\n\n\t\t\tst_sfc(CPL_geos_op(\"buffer_with_style\", x, dist, nQ, numeric(0), logical(0),\n\t\t\t\tendCapStyle = endCapStyle, joinStyle = joinStyle, mitreLimit = mitreLimit,\n\t\t\t\tsingleside = singleSide))\n\t\t} else\n\t\t\tst_sfc(CPL_geos_op(\"buffer\", x, dist, nQ, numeric(0), logical(0)))\n\t}\n}\n\n#' @export\nst_buffer.sf = function(x, dist, nQuadSegs = 30,\n\t\t\t\t\t\tendCapStyle = \"ROUND\", joinStyle = \"ROUND\", mitreLimit = 1.0,\n\t\t\t\t\t\tsingleSide = FALSE, ...) {\n\tst_set_geometry(x, st_buffer(st_geometry(x), dist, nQuadSegs,\n\t\t\t\t\t\t\t   endCapStyle = endCapStyle, joinStyle = joinStyle, mitreLimit = mitreLimit,\n\t\t\t\t\t\t\t   singleSide = singleSide, ...))\n}\n\n#' @name geos_unary\n#' @export\n#' @details \\code{st_boundary} returns the boundary of a geometry\nst_boundary = function(x)\n\tUseMethod(\"st_boundary\")\n\n#' @export\nst_boundary.sfg = function(x)\n\tget_first_sfg(st_boundary(st_sfc(x)))\n\n#' @export\nst_boundary.sfc = function(x)\n\tst_sfc(CPL_geos_op(\"boundary\", x, numeric(0), integer(0), numeric(0), logical(0)))\n\n#' @export\nst_boundary.sf = function(x) {\n\tst_set_geometry(x, st_boundary(st_geometry(x)))\n}\n\n#' @name geos_unary\n#' @export\n#' @details \\code{st_convex_hull} creates the convex hull of a set of points\n#' @seealso \\link[grDevices]{chull} for a more efficient algorithm for calculating the convex hull\n#' @examples\n#' nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\n#' nc_g = st_geometry(nc)\n#' plot(st_convex_hull(nc_g))\n#' plot(nc_g, border = grey(.5), add = TRUE)\n#' pt = st_combine(st_sfc(st_point(c(0,80)), st_point(c(120,80)), st_point(c(240,80))))\n#' st_convex_hull(pt) # R2\n#' st_convex_hull(st_set_crs(pt, 'OGC:CRS84')) # S2\nst_convex_hull = function(x)\n\tUseMethod(\"st_convex_hull\")\n\n#' @export\nst_convex_hull.sfg = function(x)\n\tget_first_sfg(st_convex_hull(st_sfc(x)))\n\n#' @export\nst_convex_hull.sfc = function(x) {\n\tif (isTRUE(st_is_longlat(x)) && sf_use_s2())\n\t\tst_as_sfc(s2::s2_convex_hull(x), crs = st_crs(x))\n\telse\n\t\tst_sfc(CPL_geos_op(\"convex_hull\", x, numeric(0), integer(0), numeric(0), logical(0)))\n}\n\n#' @export\nst_convex_hull.sf = function(x) {\n\tst_set_geometry(x, st_convex_hull(st_geometry(x)))\n}\n\n#' @name geos_unary\n#' @export\n#' @details \\code{st_concave_hull} creates the concave hull of a geometry\n#' @param ratio numeric; fraction convex: 1 returns the convex hulls, 0 maximally concave hulls\n#' @param allow_holes logical; if \\code{TRUE}, the resulting concave hull may have holes\n#' @examples\n#' set.seed(131)\n#' if (compareVersion(sf_extSoftVersion()[[\"GEOS\"]], \"3.11.0\") > -1) {\n#'  pts = cbind(runif(100), runif(100))\n#'  m = st_multipoint(pts)\n#'  co = sf:::st_concave_hull(m, 0.3)\n#'  coh = sf:::st_concave_hull(m, 0.3, allow_holes = TRUE)\n#'  plot(co, col = 'grey')\n#'  plot(coh, add = TRUE, border = 'red')\n#'  plot(m, add = TRUE)\n#' }\nst_concave_hull = function(x, ratio, ..., allow_holes)\n\tUseMethod(\"st_concave_hull\")\n\n#' @export\nst_concave_hull.sfg = function(x, ratio, ..., allow_holes = FALSE)\n\tget_first_sfg(st_concave_hull(st_sfc(x), ratio, allow_holes))\n\n#' @export\nst_concave_hull.sfc = function(x, ratio, ..., allow_holes = FALSE) {\n\tstopifnot(!missing(ratio), ratio >= 0, ratio <= 1.0, is.logical(allow_holes), !is.na(allow_holes))\n\tst_sfc(CPL_geos_op(\"concave_hull\", x, ratio, integer(0), numeric(0), allow_holes))\n}\n\n#' @export\nst_concave_hull.sf = function(x, ratio, ..., allow_holes = FALSE) {\n\tst_set_geometry(x, st_concave_hull(st_geometry(x), ratio, allow_holes))\n}\n\n#' @name geos_unary\n#' @export\n#' @details \\code{st_simplify} simplifies lines by removing vertices. \n#' @param preserveTopology logical; carry out topology preserving\n#'   simplification? May be specified for each, or for all feature geometries.\n#'   Note that topology is preserved only for single feature geometries, not for\n#'   sets of them. If not specified (i.e. the default), then it is internally\n#'   set equal to \\code{FALSE} when the input data is specified with projected\n#'   coordinates or \\code{sf_use_s2()} returns \\code{FALSE}. Ignored in all the\n#'   other cases (with a warning when set equal to \\code{FALSE}) since the\n#'   function implicitly calls \\code{s2::s2_simplify} which always preserve\n#'   topological relationships (per single feature).\n#' @param dTolerance numeric; tolerance parameter, specified for all or for each\n#'   feature geometry. If you run \\code{st_simplify}, the input data is\n#'   specified with long-lat coordinates and \\code{sf_use_s2()} returns\n#'   \\code{TRUE}, then the value of \\code{dTolerance} must be specified in\n#'   meters.\n#' @examples\n#'\n#' # st_simplify examples:\n#' op = par(mfrow = c(2, 3), mar = rep(0, 4))\n#' plot(nc_g[1])\n#' plot(st_simplify(nc_g[1], dTolerance = 1e3)) # 1000m\n#' plot(st_simplify(nc_g[1], dTolerance = 5e3)) # 5000m\n#' nc_g_planar = st_transform(nc_g, 2264) # planar coordinates, US foot\n#' plot(nc_g_planar[1])\n#' plot(st_simplify(nc_g_planar[1], dTolerance = 1e3)) # 1000 foot\n#' plot(st_simplify(nc_g_planar[1], dTolerance = 5e3)) # 5000 foot\n#' par(op)\n#'\nst_simplify = function(x, preserveTopology, dTolerance = 0.0)\n\tUseMethod(\"st_simplify\")\n\n#' @export\nst_simplify.sfg = function(x, preserveTopology, dTolerance = 0.0)\n\tget_first_sfg(st_simplify(st_sfc(x), preserveTopology, dTolerance = dTolerance))\n\n#' @export\nst_simplify.sfc = function(x, preserveTopology, dTolerance = 0.0) {\n\tll = isTRUE(st_is_longlat(x))\n\tif (ll && sf_use_s2()) {\n\t\tif (!missing(preserveTopology) && isFALSE(preserveTopology))\n\t\t\twarning(\"argument preserveTopology cannot be set to FALSE when working with ellipsoidal coordinates since the algorithm behind st_simplify always preserves topological relationships\")\n\t\tif (length(dTolerance) == 1) {\n\t\t\tst_as_sfc(s2::s2_simplify(x, dTolerance), crs = st_crs(x))\n\t\t} else {\n\t\t\tsimplify <- function(x, dTolerance) st_as_sfc(s2::s2_simplify(x, dTolerance))\n\t\t\tst_as_sfc(mapply(simplify, x, dTolerance), crs = st_crs(x))\n\t\t}\n\t} else {\n\t\tif (missing(preserveTopology)) {\n\t\t\tpreserveTopology = FALSE\n\t\t}\n\t\tstopifnot(mode(preserveTopology) == 'logical')\n\t\tif (ll)\n\t\t\twarning(\"st_simplify does not correctly simplify longitude/latitude data, dTolerance needs to be in decimal degrees\")\n\n\t\tst_sfc(CPL_geos_op(\"simplify\", x, numeric(0), integer(0),\n\t\t\tpreserveTopology = rep(preserveTopology, length.out = length(x)),\n\t\t\tdTolerance = rep(dTolerance, length.out = length(x))))\n\t}\n}\n\n#' @export\nst_simplify.sf = function(x, preserveTopology, dTolerance = 0.0) {\n\tst_set_geometry(x, st_simplify(st_geometry(x), preserveTopology, dTolerance))\n}\n\n#' @name geos_unary\n#' @export\n#' @param bOnlyEdges logical; if \\code{TRUE}, return lines, else return polygons\n#' @details \\code{st_triangulate} triangulates set of points (not constrained). \\code{st_triangulate} requires GEOS version 3.4 or above\nst_triangulate = function(x, dTolerance = 0.0, bOnlyEdges = FALSE)\n\tUseMethod(\"st_triangulate\")\n\n#' @export\nst_triangulate.sfg = function(x, dTolerance = 0.0, bOnlyEdges = FALSE)\n\tget_first_sfg(st_triangulate(st_sfc(x), dTolerance, bOnlyEdges = bOnlyEdges))\n\n#' @export\nst_triangulate.sfc = function(x, dTolerance = 0.0, bOnlyEdges = FALSE) {\n\tif (compareVersion(CPL_geos_version(), \"3.4.0\") > -1) { # >= ; see https://github.com/r-spatial/sf/issues/1653\n\t\tif (isTRUE(st_is_longlat(x)))\n\t\t\twarning(\"st_triangulate does not correctly triangulate longitude/latitude data\")\n\t\tst_sfc(CPL_geos_op(\"triangulate\", x, numeric(0), integer(0),\n\t\t\tdTolerance = rep(as.double(dTolerance), length.out = length(x)), logical(0),\n\t\t\tbOnlyEdges = as.integer(bOnlyEdges)))\n\t} else\n\t\tstop(\"for triangulate, GEOS version 3.4.0 or higher is required\")\n}\n\n#' @export\nst_triangulate.sf = function(x, dTolerance = 0.0, bOnlyEdges = FALSE) {\n\tst_set_geometry(x, st_triangulate(st_geometry(x), dTolerance, bOnlyEdges))\n}\n\n#' @name geos_unary\n#' @export\n#' @details \\code{st_triangulate_constrained} returns the constrained delaunay triangulation of polygons; requires GEOS version 3.10 or above\n#' @examples\n#' if (compareVersion(sf_extSoftVersion()[[\"GEOS\"]], \"3.10.0\") > -1) {\n#'  pts = rbind(c(0,0), c(1,0), c(1,1), c(.5,.5), c(0,1), c(0,0))\n#'  po = st_polygon(list(pts))\n#'  co = st_triangulate_constrained(po)\n#'  tr = st_triangulate(po)\n#'  plot(po, col = NA, border = 'grey', lwd = 15)\n#'  plot(tr, border = 'green', col = NA, lwd = 5, add = TRUE)\n#'  plot(co, border = 'red', col = 'NA', add = TRUE)\n#' }\nst_triangulate_constrained = function(x)\n\tUseMethod(\"st_triangulate_constrained\")\n\n#' @export\nst_triangulate_constrained.sfg = function(x)\n\tget_first_sfg(st_triangulate_constrained(st_sfc(x)))\n\n#' @export\nst_triangulate_constrained.sfc = function(x) {\n\tif (compareVersion(CPL_geos_version(), \"3.10.0\") > -1) { # >= ; see https://github.com/r-spatial/sf/issues/1653\n\t\tif (isTRUE(st_is_longlat(x)))\n\t\t\twarning(\"st_triangulate does not correctly triangulate longitude/latitude data\")\n\t\tst_sfc(CPL_geos_op(\"triangulate_constrained\", x, numeric(0), integer(0), numeric(0), logical(0)))\n\t} else\n\t\tstop(\"for triangulate_constrained, GEOS version 3.10.0 or higher is required\")\n}\n\n#' @export\nst_triangulate_constrained.sf = function(x) {\n\tst_set_geometry(x, st_triangulate_constrained(st_geometry(x)))\n}\n\n#' @name geos_unary\n#' @export\n#' @details \\code{st_inscribed_circle} returns the maximum inscribed circle for polygon geometries. \n#' For \\code{st_inscribed_circle}, if \\code{nQuadSegs} is 0 a 2-point LINESTRING is returned with the\n#' center point and a boundary point of every circle, otherwise a circle (buffer) is returned where\n#' \\code{nQuadSegs} controls the number of points per quadrant to approximate the circle.\n#' \\code{st_inscribed_circle} requires GEOS version 3.9 or above\n#' @examples\n#' if (compareVersion(sf_extSoftVersion()[[\"GEOS\"]], \"3.9.0\") > -1) {\n#'   nc_t = st_transform(nc, 'EPSG:2264')\n#'   x = st_inscribed_circle(st_geometry(nc_t))\n#'   plot(st_geometry(nc_t), asp = 1, col = grey(.9))\n#'   plot(x, add = TRUE, col = '#ff9999')\n#' }\nst_inscribed_circle = function(x, dTolerance, ...)\n\tUseMethod(\"st_inscribed_circle\")\n\n#' @export\nst_inscribed_circle.sfg = function(x, dTolerance, ...) {\n\tget_first_sfg(st_inscribed_circle(st_sfc(x), dTolerance, ...))\n}\n\n#' @export\nst_inscribed_circle.sfc = function(x, dTolerance = sqrt(st_area(st_set_crs(x, NA_crs_)))/1000, ..., nQuadSegs = 30) {\n\tif (compareVersion(CPL_geos_version(), \"3.9.0\") > -1) { # >=\n\t\tif (isTRUE(st_is_longlat(x)))\n\t\t\twarning(\"st_inscribed_circle does not work correctly for longitude/latitude data\")\n\t\tnQ = rep(nQuadSegs, length.out = length(x))\n\t\tret = st_sfc(CPL_geos_op(\"inscribed_circle\", x, nQ, integer(0),\n\t\t\tdTolerance = rep(as.double(dTolerance), length.out = length(x)), logical(0),\n\t\t\tbOnlyEdges = as.integer(FALSE)))\n\t\tif (any(nQuadSegs > 0)) {\n\t\t\tpts = st_cast(ret, \"POINT\")\n\t\t\tidx = seq(1, length(pts) * 2, by = 2)\n\t\t\tret = st_buffer(pts[idx], st_length(st_set_crs(ret, NA_crs_)), nQuadSegs = nQuadSegs)\n\t\t} \n\t\tret\n\t} else\n\t\tstop(\"for st_inscribed_circle, GEOS version 3.9.0 or higher is required\")\n}\n\n#' @export\nst_inscribed_circle.sf = function(x, dTolerance, ...) {\n\tst_set_geometry(x, st_inscribed_circle(st_geometry(x), dTolerance), ...)\n}\n\n#' @name geos_unary\n#' @details \\code{st_minimum_rotated_rectangle} returns the minimum\n#' rotated rectangular POLYGON which encloses the input geometry. The\n#' rectangle has width equal to the minimum diameter, and a longer\n#' length. If the convex hill of the input is degenerate (a line or\n#' point) a linestring or point is returned.\n#' @export\nst_minimum_rotated_rectangle = function(x, ...)\n\tUseMethod(\"st_minimum_rotated_rectangle\")\n\n#' @export\nst_minimum_rotated_rectangle.sfg = function(x, ...) {\n\tget_first_sfg(st_minimum_rotated_rectangle(st_sfc(x), ...))\n}\n\n#' @export\nst_minimum_rotated_rectangle.sfc = function(x, ...) {\n\tif (compareVersion(CPL_geos_version(), \"3.9.0\") > -1) { # >=\n\t\tif (isTRUE(st_is_longlat(x)))\n\t\t\twarning(\"st_minimum_rotated_rectangle does not work correctly for longitude/latitude data\")\n\t\tst_sfc(CPL_geos_op(\"minimum_rotated_rectangle\", x, 0L, integer(0),\n\t\t\tdTolerance = 0., logical(0), bOnlyEdges = as.integer(FALSE)))\n\t} else\n\t\tstop(\"for st_minimum_rotated_rectangle, GEOS version 3.9.0 or higher is required\")\n}\n\n#' @export\nst_minimum_rotated_rectangle.sf = function(x, dTolerance, ...) {\n\tst_set_geometry(x, st_minimum_rotated_rectangle(st_geometry(x)), ...)\n}\n\n#' @name geos_unary\n#' @details \\code{st_minimum_bounding_circle} \n#' returns a geometry which represents the \"minimum bounding circle\",\n#' the smallest circle that contains the input.\n#' @export\nst_minimum_bounding_circle = function(x, ...)\n\tUseMethod(\"st_minimum_bounding_circle\")\n\n#' @export\nst_minimum_bounding_circle.sfg = function(x, ...) {\n\tget_first_sfg(st_minimum_bounding_circle(st_sfc(x), ...))\n}\n\n#' @export\nst_minimum_bounding_circle.sfc = function(x, ...) {\n\tif (compareVersion(CPL_geos_version(), \"3.8.0\") > -1) { # >=\n\t\tif (isTRUE(st_is_longlat(x)))\n\t\t\twarning(\"st_minimum_rotated_rectangle does not work correctly for longitude/latitude data\")\n\t\tst_sfc(CPL_geos_op(\"bounding_circle\", x, 0L, integer(0),\n\t\t\tdTolerance = 0., logical(0), bOnlyEdges = as.integer(FALSE)))\n\t} else\n\t\tstop(\"for st_minimum_bounding_circle, GEOS version 3.8.0 or higher is required\")\n}\n\n#' @export\nst_minimum_bounding_circle.sf = function(x, ...) {\n\tst_set_geometry(x, st_minimum_bounding_circle(st_geometry(x)), ...)\n}\n\n#' @name geos_unary\n#' @export\n#' @param envelope object of class \\code{sfc} or \\code{sfg} containing a \\code{POLYGON} with the envelope for a voronoi diagram; this only takes effect when it is larger than the default envelope, chosen when \\code{envelope} is an empty polygon\n#' @param point_order logical; preserve point order if TRUE and GEOS version >= 3.12; overrides bOnlyEdges\n#' @details \\code{st_voronoi} creates voronoi tessellation. \\code{st_voronoi} requires GEOS version 3.5 or above\n#' @examples\n#' set.seed(1)\n#' x = st_multipoint(matrix(runif(10),,2))\n#' box = st_polygon(list(rbind(c(0,0),c(1,0),c(1,1),c(0,1),c(0,0))))\n#' if (compareVersion(sf_extSoftVersion()[[\"GEOS\"]], \"3.5.0\") > -1) {\n#'  v = st_sfc(st_voronoi(x, st_sfc(box)))\n#'  plot(v, col = 0, border = 1, axes = TRUE)\n#'  plot(box, add = TRUE, col = 0, border = 1) # a larger box is returned, as documented\n#'  plot(x, add = TRUE, col = 'red', cex=2, pch=16)\n#'  plot(st_intersection(st_cast(v), box)) # clip to smaller box\n#'  plot(x, add = TRUE, col = 'red', cex=2, pch=16)\n#'  # matching Voronoi polygons to data points:\n#'  # https://github.com/r-spatial/sf/issues/1030\n#'  # generate 50 random unif points:\n#'  n = 100\n#'  pts = st_as_sf(data.frame(matrix(runif(n), , 2), id = 1:(n/2)), coords = c(\"X1\", \"X2\"))\n#'  # compute Voronoi polygons:\n#'  pols = st_collection_extract(st_voronoi(do.call(c, st_geometry(pts))))\n#'  # match them to points:\n#'  pts_pol = st_intersects(pts, pols)\n#'  pts$pols = pols[unlist(pts_pol)] # re-order\n#'  if (isTRUE(try(compareVersion(sf_extSoftVersion()[\"GEOS\"], \"3.12.0\") > -1,\n#'    silent = TRUE))) {\n#'    pols_po = st_collection_extract(st_voronoi(do.call(c, st_geometry(pts)),\n#'      point_order = TRUE)) # GEOS >= 3.12 can preserve order of inputs\n#'    pts_pol_po = st_intersects(pts, pols_po)\n#'    print(all(unlist(pts_pol_po) == 1:(n/2)))\n#'  }\n#'  plot(pts[\"id\"], pch = 16) # ID is color\n#'  plot(st_set_geometry(pts, \"pols\")[\"id\"], xlim = c(0,1), ylim = c(0,1), reset = FALSE)\n#'  plot(st_geometry(pts), add = TRUE)\n#'  layout(matrix(1)) # reset plot layout\n#' }\nst_voronoi = function(x, envelope, dTolerance = 0.0, bOnlyEdges = FALSE, point_order = FALSE)\n\tUseMethod(\"st_voronoi\")\n\n#' @export\nst_voronoi.sfg = function(x, envelope = st_polygon(), dTolerance = 0.0, bOnlyEdges = FALSE, point_order = FALSE)\n\tget_first_sfg(st_voronoi(st_sfc(x), st_sfc(envelope), dTolerance, bOnlyEdges = bOnlyEdges, point_order = point_order))\n\n#' @export\nst_voronoi.sfc = function(x, envelope = st_polygon(), dTolerance = 0.0, bOnlyEdges = FALSE, point_order = FALSE) {\n\tif (compareVersion(CPL_geos_version(), \"3.5.0\") > -1) {\n\t\tif (isTRUE(st_is_longlat(x)))\n\t\t\twarning(\"st_voronoi does not correctly triangulate longitude/latitude data\")\n\t\tif (point_order) {\n\t\t\tif (compareVersion(CPL_geos_version(), \"3.12.0\") > -1)\n\t\t\t\tbOnlyEdges = 2L # GEOS enum GEOS_VORONOI_PRESERVE_ORDER\n\t\t\telse\n\t\t\t\twarning(\"Point order retention not supported for GEOS \", CPL_geos_version())\n\t\t}\n\t\tst_sfc(CPL_geos_voronoi(x, st_sfc(envelope), dTolerance = dTolerance,\n\t\t\tbOnlyEdges = as.integer(bOnlyEdges)))\n\t} else\n\t\tstop(\"for voronoi, GEOS version 3.5.0 or higher is required\")\n}\n\n#' @export\nst_voronoi.sf = function(x, envelope = st_polygon(), dTolerance = 0.0, bOnlyEdges = FALSE, point_order = FALSE) {\n\tst_set_geometry(x, st_voronoi(st_geometry(x), st_sfc(envelope), dTolerance, bOnlyEdges = bOnlyEdges, point_order = point_order))\n}\n\n#' @name geos_unary\n#' @details \\code{st_polygonize} creates a polygon from lines that form a closed ring. In case of \\code{st_polygonize}, \\code{x} must be an object of class \\code{LINESTRING} or \\code{MULTILINESTRING}, or an \\code{sfc} geometry list-column object containing these\n#' @export\n#' @examples\n#' mls = st_multilinestring(list(matrix(c(0,0,0,1,1,1,0,0),,2,byrow=TRUE)))\n#' st_polygonize(st_sfc(mls))\nst_polygonize = function(x)\n\tUseMethod(\"st_polygonize\")\n\n#' @export\nst_polygonize.sfg = function(x)\n\tget_first_sfg(st_polygonize(st_sfc(x)))\n\n#' @export\nst_polygonize.sfc = function(x) {\n\tstopifnot(inherits(x, \"sfc_LINESTRING\") || inherits(x, \"sfc_MULTILINESTRING\"))\n\tst_sfc(CPL_geos_op(\"polygonize\", x, numeric(0), integer(0), numeric(0), logical(0)))\n}\n\n#' @export\nst_polygonize.sf = function(x) {\n\tst_set_geometry(x, st_polygonize(st_geometry(x)))\n}\n\n#' @name geos_unary\n#' @export\n#' @param directed logical; if \\code{TRUE}, lines with opposite directions will not be merged\n#' @details \\code{st_line_merge} merges lines. In case of \\code{st_line_merge}, \\code{x} must be an object of class \\code{MULTILINESTRING}, or an \\code{sfc} geometry list-column object containing these\n#' @examples\n#' mls = st_multilinestring(list(rbind(c(0,0), c(1,1)), rbind(c(2,0), c(1,1))))\n#' st_line_merge(st_sfc(mls))\nst_line_merge = function(x, ..., directed = FALSE)\n\tUseMethod(\"st_line_merge\")\n\n#' @export\nst_line_merge.sfg = function(x, ..., directed = FALSE)\n\tget_first_sfg(st_line_merge(st_sfc(x), directed = directed, ...))\n\n#' @export\nst_line_merge.sfc = function(x, ..., directed = FALSE) {\n\tstopifnot(inherits(x, \"sfc_MULTILINESTRING\"))\n\tif (directed)\n\t\tst_sfc(CPL_geos_op(\"linemergedirected\", x, numeric(0), integer(0), numeric(0), logical(0)))\n\telse\n\t\tst_sfc(CPL_geos_op(\"linemerge\", x, numeric(0), integer(0), numeric(0), logical(0)))\n}\n\n#' @export\nst_line_merge.sf = function(x, ..., directed = FALSE) {\n\tst_set_geometry(x, st_line_merge(st_geometry(x), directed = directed, ...))\n}\n\n#' @name geos_unary\n#' @param of_largest_polygon logical; for \\code{st_centroid}: if \\code{TRUE}, return centroid of the largest (sub)polygon of a \\code{MULTIPOLYGON} rather than of the whole \\code{MULTIPOLYGON}\n#' @export\n#' @details \\code{st_centroid} gives the centroid of a geometry\n#' @examples\n#' plot(nc_g, axes = TRUE)\n#' plot(st_centroid(nc_g), add = TRUE, pch = 3, col = 'red')\n#' mp = st_combine(st_buffer(st_sfc(lapply(1:3, function(x) st_point(c(x,x)))), 0.2 * 1:3))\n#' plot(mp)\n#' plot(st_centroid(mp), add = TRUE, col = 'red') # centroid of combined geometry\n#' plot(st_centroid(mp, of_largest_polygon = TRUE), add = TRUE, col = 'blue', pch = 3)\nst_centroid = function(x, ..., of_largest_polygon = FALSE)\n\tUseMethod(\"st_centroid\")\n\n#' @export\nst_centroid.sfg = function(x, ..., of_largest_polygon = FALSE)\n\tget_first_sfg(st_centroid(st_sfc(x), of_largest_polygon = of_largest_polygon))\n\nlargest_ring = function(x) {\n\tpols = st_cast(x, \"POLYGON\", warn = FALSE)\n\tstopifnot(! is.null(attr(pols, \"ids\")))\n\tareas = st_area(pols)\n\tspl = split(areas, rep(seq_along(x), attr(pols, \"ids\"))) # group by x\n\tl = c(0, head(cumsum(lengths(spl)), -1)) # 0-based indexes of first rings of a MULTIPOLYGON\n\ti = l + sapply(spl, which.max)           # add relative index of largest ring\n\tst_sfc(pols[i], crs = st_crs(x))\n}\n\n#' @export\nst_centroid.sfc = function(x, ..., of_largest_polygon = FALSE) {\n\tif (of_largest_polygon) {\n\t\tmulti = which(sapply(x, inherits, what = \"MULTIPOLYGON\") & lengths(x) > 1)\n\t\tif (length(multi))\n\t\t\tx[multi] = largest_ring(x[multi])\n\t}\n\tlonglat = isTRUE(st_is_longlat(x))\n\tif (longlat && sf_use_s2())\n\t\tst_as_sfc(s2::s2_centroid(x), crs = st_crs(x))\n\telse { \n\t\tif (longlat)\n\t\t\twarning(\"st_centroid does not give correct centroids for longitude/latitude data\")\n\t\tst_sfc(CPL_geos_op(\"centroid\", x, numeric(0), integer(0), numeric(0), logical(0)))\n\t}\n}\n\n#' @export\nst_centroid.sf = function(x, ..., of_largest_polygon = FALSE) {\n\tif (any(st_dimension(x) > 0) && !all_constant(x))\n\t\twarning(\"st_centroid assumes attributes are constant over geometries\", call. = FALSE)\n\tret = st_set_geometry(x,\n\t\tst_centroid(st_geometry(x), of_largest_polygon = of_largest_polygon))\n\tagr = st_agr(ret)\n\tagr[ agr == \"identity\" ] = \"constant\"\n\tst_set_agr(ret, agr)\n}\n\n\n#' @name geos_unary\n#' @export\n#' @details \\code{st_point_on_surface} returns a point guaranteed to be on the (multi)surface.\n#' @examples\n#' plot(nc_g, axes = TRUE)\n#' plot(st_point_on_surface(nc_g), add = TRUE, pch = 3, col = 'red')\nst_point_on_surface = function(x)\n\tUseMethod(\"st_point_on_surface\")\n\n#' @export\nst_point_on_surface.sfg = function(x)\n\tget_first_sfg(st_point_on_surface(st_sfc(x)))\n\n#' @export\nst_point_on_surface.sfc = function(x) {\n\tif (isTRUE(st_is_longlat(x)))\n\t\twarning(\"st_point_on_surface may not give correct results for longitude/latitude data\")\n\tst_sfc(CPL_geos_op(\"point_on_surface\", x, numeric(0), integer(0), numeric(0), logical(0)))\n}\n\n#' @export\nst_point_on_surface.sf = function(x) {\n\tif (any(st_dimension(x) > 0) && !all_constant(x))\n\t\twarning(\"st_point_on_surface assumes attributes are constant over geometries\", call. = FALSE)\n\tst_set_geometry(x, st_point_on_surface(st_geometry(x)))\n}\n\n#' @name geos_unary\n#' @export\n#' @details \\code{st_reverse} reverses the nodes in a line\n#' @examples\n#' if (compareVersion(sf_extSoftVersion()[[\"GEOS\"]], \"3.7.0\") > -1) {\n#'   st_reverse(st_linestring(rbind(c(1,1), c(2,2), c(3,3))))\n#' }\n#nocov start\nst_reverse = function(x)\n\tUseMethod(\"st_reverse\")\n\n#' @export\nst_reverse.sfg = function(x)\n\tget_first_sfg(st_reverse(st_sfc(x)))\n\n#' @export\nst_reverse.sfc = function(x) {\n\tst_sfc(CPL_geos_op(\"reverse\", x, numeric(0), integer(0), numeric(0), logical(0)))\n}\n\n#' @export\nst_reverse.sf = function(x) {\n\tst_set_geometry(x, st_reverse(st_geometry(x)))\n}\n#nocov end\n\n#' @name geos_unary\n#' @export\n#' @details \\code{st_node} adds nodes to linear geometries at intersections without a node, and only works on individual linear geometries\n#' @examples\n#' (l = st_linestring(rbind(c(0,0), c(1,1), c(0,1), c(1,0), c(0,0))))\n#' st_polygonize(st_node(l))\n#' st_node(st_multilinestring(list(rbind(c(0,0), c(1,1), c(0,1), c(1,0), c(0,0)))))\nst_node = function(x) UseMethod(\"st_node\")\n\n#' @export\nst_node.sfg = function(x)\n\tget_first_sfg(st_node(st_sfc(x)))\n\n#' @export\nst_node.sfc = function(x) {\n\tdims = st_dimension(x)\n\tif (!all(is.na(dims) || dims == 1))\n\t\tstop(\"st_node: all geometries should be linear\")\n\tif (isTRUE(st_is_longlat(x)))\n\t\twarning(\"st_node may not give correct results for longitude/latitude data\")\n\tst_sfc(CPL_geos_op(\"node\", x, numeric(0), integer(0), numeric(0), logical(0)))\n}\n\n#' @export\nst_node.sf = function(x) {\n\tst_set_geometry(x, st_node(st_geometry(x)))\n}\n\n#' @name geos_unary\n#' @details \\code{st_segmentize} adds points to straight lines\n#' @export\n#' @param dfMaxLength maximum length of a line segment. If \\code{x} has geographical coordinates (long/lat), \\code{dfMaxLength} is either a numeric expressed in meter, or an object of class \\code{units} with length units \\code{rad} or \\code{degree}; segmentation in the long/lat case takes place along the great circle, using \\link[lwgeom:geod]{st_geod_segmentize}.\n#' @examples\n#' sf = st_sf(a=1, geom=st_sfc(st_linestring(rbind(c(0,0),c(1,1)))), crs = 4326)\n#' if (require(lwgeom, quietly = TRUE)) {\n#'  seg = st_segmentize(sf, units::set_units(100, km))\n#'  seg = st_segmentize(sf, units::set_units(0.01, rad))\n#'  nrow(seg$geom[[1]])\n#' }\nst_segmentize\t= function(x, dfMaxLength, ...)\n\tUseMethod(\"st_segmentize\")\n\n#' @export\nst_segmentize.sfg = function(x, dfMaxLength, ...)\n\tget_first_sfg(st_segmentize(st_sfc(x), dfMaxLength, ...))\n\n#' @export\nst_segmentize.sfc\t= function(x, dfMaxLength, ...) {\n\tif (isTRUE(st_is_longlat(x))) {\n\t\tif (! requireNamespace(\"lwgeom\", quietly = TRUE))\n\t\t\tstop(\"package lwgeom required, please install it first\")\n\t\tif (! inherits(dfMaxLength, \"units\"))\n\t\t\tunits(dfMaxLength) = as_units(\"m\")\n\t\tlwgeom::st_geod_segmentize(x, dfMaxLength) # takes care of rad or degree units\n\t} else {\n\t\tif (! is.na(st_crs(x)) && inherits(dfMaxLength, \"units\"))\n\t\t\tunits(dfMaxLength) = units(st_crs(x)$SemiMajor) # might convert\n\t\tst_sfc(CPL_gdal_segmentize(x, dfMaxLength), crs = st_crs(x))\n\t}\n}\n\n#' @export\nst_segmentize.sf = function(x, dfMaxLength, ...) {\n\tst_set_geometry(x, st_segmentize(st_geometry(x), dfMaxLength, ...))\n}\n\n#' Combine or union feature geometries\n#'\n#' Combine several feature geometries into one, without unioning or resolving internal boundaries\n#' @name geos_combine\n#' @param x object of class \\code{sf}, \\code{sfc} or \\code{sfg}\n#' @return \\code{st_combine} returns a single, combined geometry, with no resolved boundaries; returned geometries may well be invalid.\n#' @export\n#' @details \\code{st_combine} combines geometries without resolving borders, using \\link{c.sfg} (analogous to \\link[base]{c} for ordinary vectors).\n#' @examples\n#' nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\n#' st_combine(nc)\nst_combine = function(x)\n\tst_sfc(do.call(c, st_geometry(x)), crs = st_crs(x)) # flatten/merge\n\n# x: object of class sf\n# y: object of class sf or sfc\n# geoms: result from geos_op2: list of non-empty geometries with the intersection/union/difference/sym_difference\n# which has an idx attribute pointing to what is x, what is y\ngeos_op2_df = function(x, y, geoms) {\n\tidx = attr(geoms, \"idx\")\n\tattr(geoms, \"idx\") = NULL\n\tall_constant_x = all_constant_y = TRUE\n\tall_constant_x = all_constant(x)\n\tdf = x[idx[,1],,drop = FALSE]\n\tst_geometry(df) = NULL\n\tif (inherits(y, \"sf\")) {\n\t\tall_constant_y = all_constant(y)\n\t\tst_geometry(y) = NULL\n\t\tdf = data.frame(df, y[idx[,2], , drop = FALSE])\n\t}\n\tif (! (all_constant_x && all_constant_y))\n\t\twarning(\"attribute variables are assumed to be spatially constant throughout all geometries\",\n\t\t\tcall. = FALSE)\n\tif (inherits(x, \"tbl_df\")) {\n\t\tif (!requireNamespace(\"tibble\", quietly = TRUE))\n\t\t\tstop(\"package tibble required: install first?\")\n\t\tdf = tibble::new_tibble(df, nrow = nrow(df), class = \"sf\")\n\t}\n\tdf[[ attr(x, \"sf_column\") ]] = geoms\n\tst_sf(df, sf_column_name = attr(x, \"sf_column\"))\n}\n\n# after checking identical crs,\n# call geos_op2 function op on x and y:\n# DE-9IM compliant should use model = \"closed\", more robust seems:\ngeos_op2_geom = function(op, x, y, ..., by_element = FALSE, model = \"semi-open\") {\n\tstopifnot(st_crs(x) == st_crs(y))\n\tx = st_geometry(x)\n\ty = st_geometry(y)\n\tlonglat = isTRUE(st_is_longlat(x))\n\tif (by_element) {\n\t\tstopifnot(length(x) == length(y))\n\t\tif (longlat && sf_use_s2()) {\n\t\t\tfn = switch(op, intersection = s2::s2_intersection,\n\t\t\t\tdifference = s2::s2_difference,\n\t\t\t\tsym_difference = s2::s2_sym_difference,\n\t\t\t\tunion = s2::s2_union, stop(\"invalid operator\"))\n\t\t\tst_as_sfc(fn(x, y, s2::s2_options(model = model, ...)), crs = st_crs(x))\n\t\t} else {\n\t\t\tif (longlat)\n\t\t\t\tmessage_longlat(paste0(\"st_\", op))\n\t\t\tst_sfc(CPL_geos_op2_by_element(op, x, y), crs = st_crs(x))\n\t\t}\n\t} else {\n\t\tif (longlat && sf_use_s2()) {\n\t\t\tfn = switch(op, intersection = s2::s2_intersection,\n\t\t\t\tdifference = s2::s2_difference,\n\t\t\t\tsym_difference = s2::s2_sym_difference,\n\t\t\t\tunion = s2::s2_union, stop(\"invalid operator\"))\n\t\t\t# to be optimized -- this doesn't index on y:\n\t\t\tlst = structure(unlist(lapply(y, function(yy) fn(x, yy, s2::s2_options(model = model, ...))),\n\t\t\t\trecursive = FALSE), class = \"s2_geography\")\n\t\t\te = s2::s2_is_empty(lst)\n\t\t\tidx = cbind(rep(seq_along(x), length(y)), rep(seq_along(y), each = length(x)))\n\t\t\tlst = st_as_sfc(lst, crs = st_crs(x))\n\t\t\tstructure(lst[!e], idx = idx[!e,,drop = FALSE])\n\t\t} else {\n\t\t\tif (longlat)\n\t\t\t\tmessage_longlat(paste0(\"st_\", op))\n\t\t\tst_sfc(CPL_geos_op2(op, x, y), crs = st_crs(x))\n\t\t}\n\t}\n}\n\n# return first sfg, or empty geometry in case of zero features\nget_first_sfg = function(x) {\n\tif (length(x) == 0)\n\t\tst_geometrycollection()\n\telse\n\t\tx[[1]]\n}\n\n#' Geometric operations on pairs of simple feature geometry sets\n#'\n#' Perform geometric set operations with simple feature geometry collections\n#' @name geos_binary_ops\n#' @param x object of class \\code{sf}, \\code{sfc} or \\code{sfg}\n#' @param y object of class \\code{sf}, \\code{sfc} or \\code{sfg}\n#' @param ... arguments passed on to \\link[s2]{s2_options}\n#' @param by_element logical; if `TRUE`, return pair-wise computed geometries, rather than set-wise; can be used for all binary operations\n#' @export\n#' @return The intersection, difference or symmetric difference between two sets of geometries.\n#' The returned object has the same class as that of the first argument (\\code{x}) with the non-empty geometries resulting from applying the operation to all geometry pairs in \\code{x} and \\code{y}. In case \\code{x} is of class \\code{sf}, the matching attributes of the original object(s) are added. The \\code{sfc} geometry list-column returned carries an attribute \\code{idx}, which is an \\code{n}-by-2 matrix with every row the index of the corresponding entries of \\code{x} and \\code{y}, respectively.\n#' @details When using GEOS and not using s2, a spatial index is built on argument \\code{x}; see \\url{https://r-spatial.org/r/2017/06/22/spatial-index.html}. The reference for the STR tree algorithm is: Leutenegger, Scott T., Mario A. Lopez, and Jeffrey Edgington. \"STR: A simple and efficient algorithm for R-tree packing.\" Data Engineering, 1997. Proceedings. 13th international conference on. IEEE, 1997. For the pdf, search Google Scholar.\n#' @seealso \\link{st_union} for the union of simple features collections; \\link{intersect} and \\link{setdiff} for the base R set operations.\n#' @export\n#' @note To find whether pairs of simple feature geometries intersect, use\n#' the function \\code{\\link{st_intersects}} instead of \\code{st_intersection}.\n#'\n#' When using GEOS and not using s2 polygons contain their boundary. When using s2 this is determined by the \\code{model} defaults of \\link[s2]{s2_options}, which can be overridden via the ... argument, e.g. \\code{model = \"closed\"} to force DE-9IM compliant behaviour of polygons (and reproduce GEOS results).\n#' @examples\n#' set.seed(131)\n#' library(sf)\n#' m = rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0))\n#' p = st_polygon(list(m))\n#' n = 100\n#' l = vector(\"list\", n)\n#' for (i in 1:n)\n#'   l[[i]] = p + 10 * runif(2)\n#' s = st_sfc(l)\n#' plot(s, col = sf.colors(categorical = TRUE, alpha = .5))\n#' title(\"overlapping squares\")\n#' d = st_difference(s) # sequential differences: s1, s2-s1, s3-s2-s1, ...\n#' plot(d, col = sf.colors(categorical = TRUE, alpha = .5))\n#' title(\"non-overlapping differences\")\n#' i = st_intersection(s) # all intersections\n#' plot(i, col = sf.colors(categorical = TRUE, alpha = .5))\n#' title(\"non-overlapping intersections\")\n#' summary(lengths(st_overlaps(s, s))) # includes self-counts!\n#' summary(lengths(st_overlaps(d, d)))\n#' summary(lengths(st_overlaps(i, i)))\n#' sf = st_sf(s)\n#' i = st_intersection(sf) # all intersections\n#' plot(i[\"n.overlaps\"])\n#' summary(i$n.overlaps - lengths(i$origins))\nst_intersection = function(x, y, ..., by_element = FALSE) UseMethod(\"st_intersection\")\n\n#' @export\nst_intersection.sfg = function(x, y, ...)\n\tget_first_sfg(geos_op2_geom(\"intersection\", x, y, ...))\n\n#' @name geos_binary_ops\n#' @export\n#' @details When called with missing \\code{y}, the \\code{sfc} method for \\code{st_intersection} returns all non-empty intersections of the geometries of \\code{x}; an attribute \\code{idx} contains a list-column with the indexes of contributing geometries.\nst_intersection.sfc = function(x, y, ...) {\n\tif (missing(y)) {\n\t\tif (isTRUE(st_is_longlat(x)))\n\t\t\tmessage_longlat(\"st_intersection\")\n\t\tret = CPL_nary_intersection(x)\n\t\tstructure(st_sfc(ret), idx = attr(ret, \"idx\"))\n\t} else\n\t\tgeos_op2_geom(\"intersection\", x, y, ...)\n}\n\n#' @name geos_binary_ops\n#' @export\n#' @details when called with a missing \\code{y}, the \\code{sf} method for \\code{st_intersection} returns an \\code{sf} object with attributes taken from the contributing feature with lowest index; two fields are added: \\code{n.overlaps} with the number of overlapping features in \\code{x}, and a list-column \\code{origins} with indexes of all overlapping features.\nst_intersection.sf = function(x, y, ...) {\n\tif (missing(y)) {\n\t\tgeom = st_intersection(st_geometry(x), ...)\n\t\tidx = attr(geom, \"idx\")\n\t\ti = sapply(idx, function(i) i[1])\n\t\tsf_column = attr(x, \"sf_column\")\n\t\tst_geometry(x) = NULL\n\t\tx = x[i, , drop = FALSE]\n\t\tx$n.overlaps = lengths(idx)\n\t\tx$origins = idx\n\t\tx[[ sf_column ]] = structure(geom, idx = NULL)\n\t\tst_sf(x)\n\t} else\n\t\tgeos_op2_df(x, y, geos_op2_geom(\"intersection\", x, y, ...))\n}\n\n#' @name geos_binary_ops\n#' @export\n#' @examples\n#' # A helper function that erases all of y from x:\n#' st_erase = function(x, y) st_difference(x, st_union(st_combine(y)))\nst_difference = function(x, y, ...) UseMethod(\"st_difference\")\n\n#' @export\nst_difference.sfg = function(x, y, ...)\n\tget_first_sfg(geos_op2_geom(\"difference\", x, y, ...))\n\n#' @name geos_binary_ops\n#' @export\n#' @details When \\code{st_difference} is called with a single argument,\n#' overlapping areas are erased from geometries that are indexed at greater\n#' numbers in the argument to \\code{x}; geometries that are empty\n#' or contained fully inside geometries with higher priority are removed entirely.\n#' The \\code{st_difference.sfc} method with a single argument returns an object with\n#' an \\code{\"idx\"} attribute with the original index for returned geometries.\nst_difference.sfc = function(x, y, ...) {\n\tif (missing(y)) {\n\t\tif (isTRUE(st_is_longlat(x)))\n\t\t\tmessage_longlat(\"st_difference\")\n\t\tret = CPL_nary_difference(x)\n\t\tstructure(st_sfc(ret), ret = attr(ret, \"idx\"))\n\t} else\n\t\tgeos_op2_geom(\"difference\", x, y, ...)\n}\n\n#' @export\nst_difference.sf = function(x, y, ...) {\n\tif (missing(y)) {\n\t\tgeom = st_difference(st_geometry(x))\n\t\tsf_column = attr(x, \"sf_column\")\n\t\tst_geometry(x) = NULL\n\t\tx = x[attr(geom, \"idx\"), , drop=FALSE]\n\t\tx[[ sf_column ]] = structure(geom, idx = NULL)\n\t\tst_sf(x)\n\t} else\n\t\tgeos_op2_df(x, y, geos_op2_geom(\"difference\", x, y, ...))\n}\n\n#' @name geos_binary_ops\n#' @export\nst_sym_difference = function(x, y, ...) UseMethod(\"st_sym_difference\")\n\n#' @export\nst_sym_difference.sfg = function(x, y, ...)\n\tget_first_sfg(geos_op2_geom(\"sym_difference\", x, y, ...))\n\n#' @export\nst_sym_difference.sfc = function(x, y, ...)\n\tgeos_op2_geom(\"sym_difference\", x, y, ...)\n\n#' @export\nst_sym_difference.sf = function(x, y, ...)\n\tgeos_op2_df(x, y, geos_op2_geom(\"sym_difference\", x, y, ...))\n\n#' @name geos_binary_ops\n#' @param tolerance tolerance values used for \\code{st_snap}; numeric value or object of class \\code{units}; may have tolerance values for each feature in \\code{x}\n#' @details \\code{st_snap} snaps the vertices and segments of a geometry to another geometry's vertices. If \\code{y} contains more than one geometry, its geometries are merged into a collection before snapping to that collection.\n#'\n#' (from the GEOS docs:) \"A snap distance tolerance is used to control where snapping is performed. Snapping one geometry to another can improve robustness for overlay operations by eliminating nearly-coincident edges (which cause problems during noding and intersection calculation). Too much snapping can result in invalid topology being created, so the number and location of snapped vertices is decided using heuristics to determine when it is safe to snap. This can result in some potential snaps being omitted, however.\"\n#' @examples\n#' poly = st_polygon(list(cbind(c(0, 0, 1, 1, 0), c(0, 1, 1, 0, 0))))\n#' lines = st_multilinestring(list(\n#'  cbind(c(0, 1), c(1, 1.05)),\n#'  cbind(c(0, 1), c(0, -.05)),\n#'  cbind(c(1, .95, 1), c(1.05, .5, -.05))\n#' ))\n#' snapped = st_snap(poly, lines, tolerance=.1)\n#' plot(snapped, col='red')\n#' plot(poly, border='green', add=TRUE)\n#' plot(lines, lwd=2, col='blue', add=TRUE)\n#' @export\nst_snap = function(x, y, tolerance) UseMethod(\"st_snap\")\n\n#' @export\nst_snap.sfg = function(x, y, tolerance)\n\tget_first_sfg(st_snap(st_sfc(x), y, tolerance))\n\n#' @export\nst_snap.sfc = function(x, y, tolerance) {\n\tif (isTRUE(st_is_longlat(x)))\n\t\tstop(\"st_snap for longitude/latitude data not supported; use st_transform first?\")\n\telse if (inherits(tolerance, \"units\") && !is.null(st_crs(x)$ud_unit))\n\t\tunits(tolerance) = st_crs(x)$ud_unit # coordinate units\n\ttolerance = rep(tolerance, length.out = length(x))\n\tst_sfc(CPL_geos_snap(st_geometry(x), st_geometry(y), as.double(tolerance)))\n}\n\n#' @export\nst_snap.sf = function(x, y, tolerance)\n\tst_set_geometry(x, st_snap(st_geometry(x), st_geometry(y), tolerance))\n\n#' @name geos_combine\n#' @export\n#' @param by_feature logical; if `TRUE`, union each feature if \\code{y} is missing or else each pair of features; if `FALSE` return a single feature that is the geometric union of the set of features in \\code{x} if \\code{y} is missing, or else the unions of each of the elements of the Cartesian product of both sets\n#' @param is_coverage logical; if `TRUE`, use an optimized algorithm for features that form a polygonal coverage (have no overlaps)\n#' @param y object of class \\code{sf}, \\code{sfc} or \\code{sfg} (optional)\n#' @param ... ignored\n#' @seealso \\link{st_intersection}, \\link{st_difference}, \\link{st_sym_difference}\n#' @return If \\code{y} is missing, \\code{st_union(x)} returns a single geometry with resolved boundaries, else the geometries for all unioned pairs of `x[i]` and `y[j]`.\n#' @details\n#' If \\code{st_union} is called with a single argument, \\code{x}, (with \\code{y} missing) and \\code{by_feature} is \\code{FALSE} all geometries are unioned together and an \\code{sfg} or single-geometry \\code{sfc} object is returned.\n#' If \\code{by_feature} is \\code{TRUE} each feature geometry is unioned individually.\n#' This can for instance be used to resolve internal boundaries after polygons were combined using \\code{st_combine}. \n#' If \\code{y} is provided, all elements of \\code{x} and \\code{y} are unioned, pairwise if \\code{by_feature} is TRUE, or else as the Cartesian product of both sets. \n#'\n#' Unioning a set of overlapping polygons has the effect of merging the areas (i.e. the same effect as iteratively unioning all individual polygons together).\n#' Unioning a set of LineStrings has the effect of fully noding and dissolving the input linework. In this context \"fully noded\" means that there will be a node or endpoint in the output for every endpoint or line segment crossing in the input.\n#' \"Dissolved\" means that any duplicate (e.g. coincident) line segments or portions of line segments will be reduced to a single line segment in the output.\tUnioning a set of Points has the effect of merging all identical points (producing a set with no duplicates).\n#' @examples\n#' plot(st_union(nc))\nst_union = function(x, y, ..., by_feature = FALSE, is_coverage = FALSE) UseMethod(\"st_union\")\n\n#' @export\nst_union.sfg = function(x, y, ..., by_feature = FALSE, is_coverage = FALSE) {\n\tout = if (missing(y)) # unary union, possibly by_feature:\n\t\tst_sfc(CPL_geos_union(st_geometry(x), by_feature, is_coverage))\n\telse\n\t\tst_union(st_geometry(x), st_geometry(y))\n\tget_first_sfg(out)\n}\n\n#' @export\nst_union.sfc = function(x, y, ..., by_feature = isTRUE(list(...)$by_element), is_coverage = FALSE) {\n\tll = isTRUE(st_is_longlat(x))\n\tif (missing(y)) { # unary union, possibly by_feature:\n\t\tif (ll && sf_use_s2()) { \n\t\t\tif (! by_feature) { # see https://github.com/r-spatial/s2/issues/97 :\n\t\t\t\tif (is_coverage)\n\t\t\t\t\tst_as_sfc(s2::s2_coverage_union_agg(x, ...), crs = st_crs(x))\n\t\t\t\telse\n\t\t\t\t\tst_as_sfc(s2::s2_union_agg(x, ...), crs = st_crs(x)) \n\t\t\t} else\n\t\t\t\tst_as_sfc(s2::s2_union(x, ...), crs = st_crs(x)) \n\t\t} else {\n\t\t\tif (ll)\n\t\t\t\tmessage_longlat(\"st_union\")\n\t\t\tst_sfc(CPL_geos_union(x, by_feature, is_coverage))\n\t\t}\n\t} else {\n\t\ty = st_geometry(y)\n\t\tstopifnot(st_crs(x) == st_crs(y))\n\t\tif (is_coverage)\n\t\t\tmessage(\"in st_union(), is_coverage is ignored when y is given\")\n\t\tif (by_feature)\n\t\t\tstopifnot(length(x) == length(y))\n\t\tif (ll && sf_use_s2()) {\n\t\t\tif (by_feature)\n\t\t\t\tst_as_sfc(s2::s2_union(x, y, ...), crs = st_crs(x)) \n\t\t\telse {\n\t\t\t\ti = rep(seq_along(x), each = length(y))\n\t\t\t\tj = rep(seq_along(y), length(x))\n\t\t\t\tst_as_sfc(s2::s2_union(x[i], y[j], ...), crs = st_crs(x), precision = st_precision(x)) \n\t\t\t}\n\t\t} else {\n\t\t\tif (ll)\n\t\t\t\tmessage_longlat(\"st_union\")\n\t\t\tif (by_feature) # old-style: in case by_element is not specified\n\t\t\t\tgeos_op2_geom(\"union\", x, y, by_element = TRUE, ...)\n\t\t\telse\n\t\t\t\tgeos_op2_geom(\"union\", x, y, ...) # handles by_element\n\t\t}\n\t}\n}\n\n#' @export\nst_union.sf = function(x, y, ..., by_feature = FALSE, is_coverage = FALSE) {\n\tif (missing(y)) { # unary union, possibly by_feature:\n\t\tgeom = st_union(st_geometry(x), ..., by_feature = by_feature, is_coverage = is_coverage)\n\t\tif (by_feature)\n\t\t\tst_set_geometry(x, geom)\n\t\telse\n\t\t\tgeom\n\t} else {\n\t\tif (by_feature) {\n\t\t\tdf = cbind(st_drop_geometry(x), st_drop_geometry(y))\n\t\t\tst_set_geometry(df, st_union(st_geometry(x), st_geometry(y), is_coverage = is_coverage))\n\t\t} else\n\t\t\tgeos_op2_df(x, y, geos_op2_geom(\"union\", x, y, ...))\n\t}\n}\n\n#' Sample points on a linear geometry\n#' @param x object of class \\code{sf}, \\code{sfc} or \\code{sfg}\n#' @param n integer; number of points to choose per geometry; if missing, n will be computed as \\code{round(density * st_length(geom))}.\n#' @param density numeric; density (points per distance unit) of the sampling, possibly a vector of length equal to the number of features (otherwise recycled); \\code{density} may be of class \\code{units}.\n#' @param type character; indicate the sampling type, either \"regular\" or \"random\"\n#' @param sample numeric; a vector of numbers between 0 and 1 indicating the points to sample - if defined sample overrules n, density and type.\n#' @export\n#' @examples\n#' ls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))),\n#' \tst_linestring(rbind(c(0,0),c(10,0))))\n#' st_line_sample(ls, density = 1)\n#' ls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))),\n#'\t st_linestring(rbind(c(0,0),c(.1,0))), crs = 4326)\n#' try(st_line_sample(ls, density = 1/1000)) # error\n#' st_line_sample(st_transform(ls, 3857), n = 5) # five points for each line\n#' st_line_sample(st_transform(ls, 3857), n = c(1, 3)) # one and three points\n#' st_line_sample(st_transform(ls, 3857), density = 1/1000) # one per km\n#' st_line_sample(st_transform(ls, 3857), density = c(1/1000, 1/10000)) # one per km, one per 10 km\n#' st_line_sample(st_transform(ls, 3857), density = units::set_units(1, 1/km)) # one per km\n#' # five equidistant points including start and end:\n#' st_line_sample(st_transform(ls, 3857), sample = c(0, 0.25, 0.5, 0.75, 1))\nst_line_sample = function(x, n, density, type = \"regular\", sample = NULL) {\n\tif (isTRUE(st_is_longlat(x)))\n\t\tstop(\"st_line_sample for longitude/latitude not supported; use st_segmentize?\")\n\tl = st_length(x)\n\tdistList = if (is.null(sample)) {\n\t\tn = if (missing(n)) {\n\t\t\tif (!is.null(st_crs(x)$ud_unit) && inherits(density, \"units\"))\n\t\t\t\tunits(density) = 1/st_crs(x)$ud_unit # coordinate units\n\t\t\tround(rep(density, length.out = length(l)) * l)\n\t\t} else\n\t\t\trep(n, length.out = length(l))\n\t\tregular = function(n) { (seq_len(n) - 0.5)/n }\n\t\trandom = function(n) { sort(runif(n)) }\n\t\tfn = switch(type,\n\t\t\t\t\tregular = regular,\n\t\t\t\t\trandom = random,\n\t\t\t\t\tstop(\"unknown type\"))\n\t\tlapply(seq_along(n), function(i) fn(n[i]) * l[i])\n\t} else\n\t\tlapply(seq_along(l), function(i) sample * l[i])\n\n\tx = st_geometry(x)\n\tstopifnot(inherits(x, \"sfc_LINESTRING\"))\n\tst_sfc(CPL_gdal_linestring_sample(x, distList), crs = st_crs(x))\n}\n\n#' Internal functions\n#' @keywords internal\n#' @param msg error message\n#' @export\n.stop_geos = function(msg) { #nocov start\n\ton.exit(stop(msg))\n\tlst = strsplit(msg, \" at \")[[1]]\n\tpts = scan(text = lst[[length(lst)]], quiet = TRUE)\n\tif (length(pts) == 2 && is.numeric(pts))\n  \t\tassign(\".geos_error\", st_point(pts), envir=.sf_cache)\n} #nocov end\n\n#' @param dist numeric or units, vector with distance value(s), in units of the coordinates\n#' @name st_line_project_point\n#' @returns `st_line_interpolate` returns the point(s) at dist(s), when measured along (interpolated on) the line(s)\n#' @export\n#' @examples \n#' st_line_interpolate(st_as_sfc(\"LINESTRING (0 0, 1 1)\"), 1)\n#' st_line_interpolate(st_as_sfc(\"LINESTRING (0 0, 1 1)\"), 1, TRUE)\n#' # https://github.com/r-spatial/sf/issues/2542; use for geographic coordinates:\n#' l1 <- st_as_sfc(\"LINESTRING (10.1 50.1, 10.2 50.2)\", crs = 'OGC:CRS84')\n#' dists = units::set_units(seq(0, sqrt(2)/10, length.out = 5), degrees)\n#' st_line_interpolate(l1, dists)\nst_line_interpolate = function(line, dist, normalized = FALSE) {\n\tstopifnot(inherits(line, \"sfc\"), all(st_dimension(line) == 1), \n\t\tis.logical(normalized), length(normalized) == 1,\n\t\tis.numeric(dist))\n\tif (isTRUE(st_is_longlat(line))) {\n\t\tmessage_longlat(\"st_project_point\")\n\t\tif (inherits(dist, \"units\"))\n\t\t\tdist = units::set_units(dist, \"degree\", mode = \"standard\")\n\t\telse\n\t\t\tstop(\"for interpolating geographic coordinates, dist should have units degree; see examples\")\n\t}\n\tline = st_cast(line, \"LINESTRING\")\n\trecycled = recycle_common(list(line, dist))\n\tst_sfc(CPL_line_interpolate(recycled[[1]], recycled[[2]], normalized), \n\t\t   crs = st_crs(line))\n}\n\n#' @export\n#' @name geos_unary\n#' @details \\code{st_exterior_ring} returns the exterior rings of polygons, removing all holes.\nst_exterior_ring = function(x, ...) UseMethod(\"st_exterior_ring\")\n\n#' @export\nst_exterior_ring.sf = function(x, ...)\n\tst_set_geometry(x, st_exterior_ring(st_geometry(x)))\n\n#' @export\nst_exterior_ring.sfg = function(x, ...)\n\tst_exterior_ring(st_sfc(x))[[1]]\n\n#' @export\nst_exterior_ring.sfc = function(x, ...) {\n\tstopifnot(all(st_dimension(x, NA_if_empty = FALSE) == 2))\n\texterior_sfg = function(x) {\n\t\tif (inherits(x, \"MULTIPOLYGON\"))\n\t\t\tst_multipolygon(lapply(st_cast(st_sfc(x), \"POLYGON\"), exterior_sfg))\n\t\telse if (inherits(x, \"POLYGON\"))\n\t\t\tst_polygon(x[1])\n\t\telse\n\t\t\tstop(paste(\"no exterior_ring method for objects of class\", class(x)[1]))\n\t}\n\tst_as_sfc(lapply(x, exterior_sfg), crs = st_crs(x))\n}\n"
  },
  {
    "path": "R/geos-overlayng.R",
    "content": "# nocov start\nis_overlayng <- function() {\n\tpl1 = st_polygon(list(matrix(c(0, 0, 2, 0, 1, 1, 0 ,0), byrow = TRUE, ncol=2)))\n\tpl2 = st_polygon(list(matrix(c(0, 0.5, 2, 0.5, 1, 1.5, 0, 0.5), byrow = TRUE, ncol = 2)))\n\tpl3 = st_polygon(list(matrix(c(0, 1.25, 2, 1.25, 1, 2.5, 0, 1.25), byrow = TRUE, ncol = 2)))\n\tin1 = st_sfc(list(pl1, pl2, pl3))\n\tcorrect_geom = st_sfc(list(\n\t\tst_polygon(list(matrix(c(0, 2, 1, 0, 0, 0, 1, 0), ncol = 2))),\n\t\tst_polygon(list(matrix(c(0, 1, 2, 1.5, 1, 0.5, 0, 0.5, 1.5, 0.5, 0.5, 1, 0.5, 0.5), ncol = 2))),\n\t\tst_polygon(list(matrix(c(0, 1, 2, 1.25, 1, 0.75, 0, 1.25, 2.5, 1.25, 1.25, 1.5, 1.25, 1.25), ncol = 2)))))\n\tout1 = st_difference(in1)\n\tisTRUE(all.equal(out1[[2]][[1]], correct_geom[[2]][[1]]))\n}\n# nocov end\n"
  },
  {
    "path": "R/graticule.R",
    "content": "st_datum = function(x) {\n\tstopifnot(inherits(x, c(\"crs\", \"sf\", \"sfc\")))\n\tif (inherits(x, \"crs\"))\n\t\tx = st_sfc(st_point(), crs = x)\n\tx = st_geometry(x) # in case inherits(x, \"sf\")\n\tdatum = st_crs(st_crs(x, parameters = TRUE)$gcs_crs)\n\tif (is.na(datum))\n\t\tst_crs('OGC:CRS84') # + message or warning?\n\telse\n\t\tdatum\n}\n\n#' Compute graticules and their parameters\n#'\n#' Compute graticules and their parameters\n#'\n#' @section Use of graticules:\n#'  In cartographic visualization, the use of graticules is not advised, unless\n#'  the graphical output will be used for measurement or navigation, or the\n#'  direction of North is important for the interpretation of the content, or\n#'  the content is intended to display distortions and artifacts created by\n#'  projection. Unnecessary use of graticules only adds visual clutter but\n#'  little relevant information. Use of coastlines, administrative boundaries\n#'  or place names permits most viewers of the output to orient themselves\n#'  better than a graticule.\n#'\n#' @export\n#' @param x object of class \\code{sf}, \\code{sfc} or \\code{sfg} or numeric vector with bounding box given as (minx, miny, maxx, maxy).\n#' @param crs object of class \\code{crs}, with the display coordinate reference system\n#' @param datum either an object of class \\code{crs} with the coordinate reference system for the graticules, or \\code{NULL} in which case a grid in the coordinate system of \\code{x} is drawn, or \\code{NA}, in which case an empty \\code{sf} object is returned. If missing and \\code{x} has a crs with a datum, the geographic coordinate system (datum) of \\code{x} is taken.\n#' @param lon numeric; values in degrees East for the meridians, associated with \\code{datum}\n#' @param lat numeric; values in degrees North for the parallels, associated with \\code{datum}\n#' @param ndiscr integer; number of points to discretize a parallel or meridian\n#' @param margin numeric; small number to trim a longlat bounding box that touches or\n#'  crosses +/-180 long or +/-90 latitude.\n#' @param ... ignored\n#' @return an object of class \\code{sf} with additional attributes describing the type\n#' (E: meridian, N: parallel) degree value, label, start and end coordinates and angle;\n#' see example.\n#' @examples\n#' library(sf)\n#' if (require(maps, quietly = TRUE)) {\n#'\n#' usa = st_as_sf(map('usa', plot = FALSE, fill = TRUE))\n#' laea = st_crs(\"+proj=laea +lat_0=30 +lon_0=-95\") # Lambert equal area\n#' usa <- st_transform(usa, laea)\n#'\n#' bb = st_bbox(usa)\n#' bbox = st_linestring(rbind(c( bb[1],bb[2]),c( bb[3],bb[2]),\n#'    c( bb[3],bb[4]),c( bb[1],bb[4]),c( bb[1],bb[2])))\n#'\n#' g = st_graticule(usa)\n#' plot(usa, xlim = 1.2 * c(-2450853.4, 2186391.9), reset = FALSE)\n#' plot(g[1], add = TRUE, col = 'grey')\n#' plot(bbox, add = TRUE)\n#' points(g$x_start, g$y_start, col = 'red')\n#' points(g$x_end, g$y_end, col = 'blue')\n#'\n#' invisible(lapply(seq_len(nrow(g)), function(i) {\n#'\tif (g$type[i] == \"N\" && g$x_start[i] - min(g$x_start) < 1000)\n#'\t\ttext(g$x_start[i], g$y_start[i], labels = parse(text = g$degree_label[i]), \n#'\t\t\tsrt = g$angle_start[i], pos = 2, cex = .7)\n#'\tif (g$type[i] == \"E\" && g$y_start[i] - min(g$y_start) < 1000)\n#'\t\ttext(g$x_start[i], g$y_start[i], labels = parse(text = g$degree_label[i]), \n#'\t\t\tsrt = g$angle_start[i] - 90, pos = 1, cex = .7)\n#'\tif (g$type[i] == \"N\" && g$x_end[i] - max(g$x_end) > -1000)\n#'\t\ttext(g$x_end[i], g$y_end[i], labels = parse(text = g$degree_label[i]), \n#'\t\t\tsrt = g$angle_end[i], pos = 4, cex = .7)\n#'\tif (g$type[i] == \"E\" && g$y_end[i] - max(g$y_end) > -1000)\n#'\t\ttext(g$x_end[i], g$y_end[i], labels = parse(text = g$degree_label[i]), \n#'\t\t\tsrt = g$angle_end[i] - 90, pos = 3, cex = .7)\n#' }))\n#' plot(usa, graticule = st_crs(4326), axes = TRUE, lon = seq(-60,-130,by=-10))\n#' }\nst_graticule = function(x = c(-180, -90, 180, 90), crs = st_crs(x),\n\tdatum = st_crs('OGC:CRS84'), ..., lon = NULL, lat = NULL, ndiscr = 100,\n\tmargin = 0.001)\n{\n\ts2 = sf_use_s2()\n\ton.exit(suppressMessages(sf_use_s2(s2)))\n\tsuppressMessages(sf_use_s2(FALSE))\n\n\tif (missing(x)) {\n\t\tcrs = datum\n\t\tif (is.null(lon))\n\t\t\tlon = seq(-180, 180, by = 20)\n\t\tif (is.null(lat))\n\t\t\tlat = seq(-80, 80, by = 20)\n\t} else if (missing(datum)) {\n\t\tdatum = if (inherits(x, c(\"sf\", \"sfc\")))\n\t\t\t\tst_datum(x)\n\t\t\telse\n\t\t\t\tst_datum(crs)\n\t}\n\n\tif (is.null(crs))\n\t\tcrs = NA_crs_\n\n\tif (is.null(datum))\n\t\tdatum = crs\n\n\tif (is.na(datum))\n\t\treturn(st_graticule()[0,]) # empty set, but with all variables\n\n\t# Get the bounding box of the plotting space, in crs\n\tbb = if (inherits(x, \"sf\") || inherits(x, \"sfc\") || inherits(x, \"sfg\"))\n\t\tst_bbox(x)\n\telse\n\t\tx\n\tstopifnot(is.numeric(bb), length(bb) == 4)\n\n\tif (isTRUE(st_is_longlat(crs)))\n\t\tbb = trim_bb(bb, margin)\n\n\tls1 = st_linestring(rbind(c(bb[1],bb[2]), c(bb[3],bb[2]), c(bb[3],bb[4]),\n\t\tc(bb[1],bb[4]), c(bb[1],bb[2])))\n\tls2 = st_linestring(rbind(c(bb[1],bb[2]), c(bb[3],bb[4]), c(bb[1],bb[4]),\n\t\tc(bb[3],bb[2]), c(bb[1],bb[2])))\n\tbox = st_sfc(ls1, ls2)\n\n\t# without crs, we segmentize in planar coordinates --\n\t# segmentizing along great circles doesn't give parallels:\n\tbox = st_segmentize(box, st_length(box)[1] / ndiscr)\n\n\t# and only now set the crs:\n\tst_crs(box) = crs\n\n\t# Now, in case we're not already in longlat, we convert to longlat:\n\tbox_ll = if (! is.na(crs))\n\t\tst_transform(box, datum, partial = TRUE)\n\telse {\n\t\tdatum = NA_crs_ # nocov - remove when geom_sf is on CRAN\n\t\tbox             # nocov\n\t}\n\n\t# as in https://github.com/r-spatial/sf/issues/198 :\n\t# recreate, and ignore bbox_ll:\n\tif (any(!is.finite(st_bbox(box_ll)))) { # nocov start -- checked manually\n\t\tx = st_transform(st_graticule(datum = datum, ndiscr = ndiscr), crs)\n\t\tx$degree_label = NA_character_\n\t\treturn(x)\n\t} # nocov end\n\n\tbb = st_bbox(box_ll)\n\tif (is.null(lon)) {\n\t\tlon = if (bb[3] <= 180 && bb[1] < -170 && bb[3] > 170) # global, -180,180:\n\t\t\tseq(-180, 180, by = 60)\n\t\telse\n\t\t\tpretty(bb[c(1,3)], n = 6)\n\t}\n\tif (is.null(lat))\n\t\tlat = pretty(bb[c(2,4)], n = 6)\n\n\t# sanity:\n\tif (isTRUE(st_is_longlat(datum))) {\n\t\tlon = if (min(lon) >= -15 && max(lon) > 195) # +- 4%\n\t\t\tlon[lon >= 0 & lon <= 360] # assume 0,360\n\t\telse\n\t\t\tlon[lon >= -180 & lon <= 180]\n\t\tlat = lat[lat > -90 & lat < 90]\n\t}\n\n\t# widen bb if pretty() created values outside the box_ll:\n\tbb = c(min(bb[1], min(lon)), min(bb[2],min(lat)), max(bb[3], max(lon)), max(bb[4], max(lat)))\n\n\tlong_list <- vector(mode=\"list\", length=length(lon))\n\tfor (i in seq_along(long_list))\n\t\tlong_list[[i]] <- st_linestring(cbind(rep(lon[i], ndiscr), seq(bb[2], bb[4], length.out=ndiscr)))\n\n\tlat_list <- vector(mode=\"list\", length=length(lat))\n\tfor (i in seq_along(lat_list))\n\t\tlat_list[[i]] <- st_linestring(cbind(seq(bb[1], bb[3], length.out=ndiscr), rep(lat[i], ndiscr)))\n\n\tdf = data.frame(degree = c(lon, lat))\n\tdf$type = c(rep(\"E\", length(lon)), rep(\"N\", length(lat)))\n\tdf$degree_label = if (is.na(crs) || !isTRUE(st_is_longlat(datum)))\n\t\t\tc(format(lon), format(lat))\n\t\telse\n\t\t\tc(degreeLabelsEW(lon), degreeLabelsNS(lat))\n\n\tgeom = st_sfc(c(long_list, lat_list), crs = datum)\n\n\t# Now we're moving the straight lines back to curves in crs:\n\tif (!is.na(crs))\n\t\tgeom = st_transform(geom, crs)\n\n\tst_geometry(df) = geom\n\tst_agr(df) = \"constant\"\n\n\tif (! missing(x)) # cut out box:\n\t\tdf = suppressMessages(st_intersection(df, st_polygonize(box[1])))\n\n\tdf = st_line_merge(st_cast(df, \"MULTILINESTRING\"))\n\tdf = st_cast(st_cast(df, \"MULTILINESTRING\"), \"LINESTRING\", warn = FALSE)\n\tgraticule_attributes(df)\n}\n\ngraticule_attributes = function(df) {\n\tobject = st_geometry(df)\n\n\tif (nrow(df) == 0)\n\t\treturn(df)\n\n\txy = matrix(NA, nrow = length(object), ncol = 4)\n\tfor (i in seq_along(object)) {\n\t\tpts = unclass(object[[i]])\n\t\txy[i, 1:2] = pts[1,] # start\n\t\txy[i, 3:4] = pts[nrow(pts),] # end\n\t}\n\tdf$x_start = xy[,1]\n\tdf$y_start = xy[,2]\n\tdf$x_end   = xy[,3]\n\tdf$y_end   = xy[,4]\n\tdxdy = do.call(rbind, lapply(object, function(x) { apply(x[1:2,], 2, diff) } ))\n\tdf$angle_start = apply(dxdy, 1, function(x) atan2(x[2], x[1])*180/pi)\n\tdxdy = do.call(rbind, lapply(object,\n\t\tfunction(x) { n = nrow(x); apply(x[(n-1):n,], 2, diff) } ))\n\tdf$angle_end = apply(dxdy, 1, function(x) atan2(x[2], x[1])*180/pi)\n\tbb = st_bbox(df)\n\tselE = df$type == \"E\" & df$y_start < min(df$y_start) + 0.001 * (bb[3] - bb[1])\n\tselN = df$type == \"N\" & df$x_start < min(df$x_start) + 0.001 * (bb[4] - bb[2])\n\tdf$plot12 = selE | selN\n\tdf\n}\n\n# make sure lat stays slightly inside [-90,90], and lon inside [-180,180] or [0,360]\ntrim_bb = function(bb = c(-180, -90, 180, 90), margin) {\n\tstopifnot(margin > 0, margin <= 1.0)\n\tfr = 1.0 - margin\n\tif (min(bb[c(1,3)]) >= -1. && max(bb[c(1,3)]) > 181.) { # 0-360 span:\n\t\tbb[1] = max(bb[1], 0.)\n\t\tbb[3] = min(bb[3], 360. * fr)\n\t} else {\n\t\tbb[1] = max(bb[1], -180. * fr)\n\t\tbb[3] = min(bb[3],  180. * fr)\n\t}\n\tbb[2] = max(bb[2], -90. * fr)\n\tbb[4] = min(bb[4],  90. * fr)\n\tbb\n}\n\n# copied from sp:\ndegreeLabelsNS = function(x) {\n\tpos = sign(x) + 2\n\tdir = c(\"*S\", \"\", \"*N\")\n\tpaste0('\"', format(abs(x), digits = 10), '\"', \"*degree\", dir[pos])\n}\n\ndegreeLabelsEW = function(x) {\n\tx <- ifelse(x > 180, x - 360, x)\n\tpos = sign(x) + 2\n\tif (any(x == -180))\n\t\tpos[x == -180] = 2\n\tif (any(x == 180))\n\t\tpos[x == 180] = 2\n\tdir = c(\"*W\", \"\", \"*E\")\n\tpaste0('\"', format(abs(x), digits = 10), '\"', \"*degree\", dir[pos])\n}\n"
  },
  {
    "path": "R/grid.R",
    "content": "#' Convert sf* object to a grob\n#'\n#' Convert sf* object to an grid graphics object (grob)\n#' @param x object to be converted into an object class \\code{grob}\n#' @param ... passed on to the xxxGrob function, e.g. \\code{gp = gpar(col = 'red')}\n#' @export\nst_as_grob = function(x, ...) UseMethod(\"st_as_grob\")\n\n#' @export\nst_as_grob.POINT = function(x, pch = 1, size = unit(1, \"char\"), default.units = \"native\", name = NULL, gp = gpar(), vp = NULL, ...) {\n\tif (anyNA(x))\n\t\tnullGrob()\n\telse\n\t\tpointsGrob(x[1], x[2], pch = pch, size = size, default.units = default.units, name = name, gp = gp, vp = vp)\n}\n\n#' @export\nst_as_grob.MULTIPOINT = function(x, pch = 1, size = unit(1, \"char\"), default.units = \"native\", name = NULL, gp = gpar(), vp = NULL, ...) {\n\tif (nrow(x) == 0)\n\t\tnullGrob()\n\telse\n\t\tpointsGrob(x[,1], x[,2], pch = pch, size = size, default.units = default.units, name = name, gp = gp, vp = vp)\n}\n\n#' @export\nst_as_grob.LINESTRING = function(x, arrow = NULL, default.units = \"native\", name = NULL, gp = gpar(), vp = NULL, ...) {\n\tif (nrow(x) == 0)\n\t\tnullGrob()\n\telse\n\t\tlinesGrob(x[,1], x[,2], arrow = NULL, default.units = default.units, name = name, gp = gp, vp = vp)\n}\n\n#' @export\nst_as_grob.CIRCULARSTRING = function(x, y, ...) {\n\tst_as_grob(st_cast(x, \"LINESTRING\"),  ...)\n}\n\n#' @export\nst_as_grob.MULTILINESTRING = function(x, arrow = NULL, default.units = \"native\", name = NULL, gp = gpar(), vp = NULL, ...) {\n\tif (length(x) == 0)\n\t\tnullGrob()\n\telse {\n\t\tget_x = function(x) unlist(sapply(x, function(y) y[,1]))\n\t\tget_y = function(x) unlist(sapply(x, function(y) y[,2]))\n\t\tpolylineGrob(get_x(x), get_y(x), id.lengths = vapply(x, nrow, 0L), arrow = NULL,\n\t\t\tdefault.units = default.units, name = name, gp = gp, vp = vp)\n\t}\n}\n\n#' @export\nst_as_grob.POLYGON = function(x, default.units = \"native\", rule = \"evenodd\", name = NULL, gp = gpar(), vp = NULL, ...) {\n\tif (length(x) == 0)\n\t\tnullGrob()\n\telse {\n\t\tget_x = function(x) unlist(sapply(x, function(y) y[,1]))\n\t\tget_y = function(x) unlist(sapply(x, function(y) y[,2]))\n\t\tpathGrob(get_x(x), get_y(x), id.lengths = vapply(x, nrow, 0L), default.units = default.units, rule = rule, name = name, gp = gp, vp = vp)\n\t}\n}\n\n#' @export\nst_as_grob.MULTIPOLYGON = function(x, default.units = \"native\", rule = \"evenodd\", name = NULL, gp = gpar(), vp = NULL, ...) {\n\tif (length(x) == 0)\n\t\tnullGrob()\n\telse {\n\t\tget_x = function(x) unlist(sapply(x, function(y) sapply(y, function(z) z[,1])))\n\t\tget_y = function(x) unlist(sapply(x, function(y) sapply(y, function(z) z[,2])))\n\t\tget_l = function(x) unlist(sapply(x, function(y) vapply(y, nrow, 0L)))\n\t\tpathGrob(get_x(x), get_y(x), id.lengths = get_l(x), default.units = default.units, rule = rule, name = name, gp = gp, vp = vp)\n\t}\n}\n\n#' @export\nst_as_grob.GEOMETRYCOLLECTION = function(x, ...) {\n\tif (length(x) == 0)\n\t\tnullGrob()\n\telse\n\t\tdo.call(grid::grobTree, lapply(x, st_as_grob, ...))\n}\n\n#' @export\nst_as_grob.MULTISURFACE = st_as_grob.GEOMETRYCOLLECTION\n\n#' @export\nst_as_grob.CURVEPOLYGON = st_as_grob.GEOMETRYCOLLECTION\n\n#' @export\nst_as_grob.COMPOUNDCURVE = st_as_grob.GEOMETRYCOLLECTION\n\n\n#' Create viewport from sf, sfc or sfg object\n#'\n#' Create viewport from sf, sfc or sfg object\n#' @param x object of class sf, sfc or sfg object\n#' @param bbox the bounding box used for aspect ratio\n#' @param asp numeric; target aspect ratio (y/x), see Details\n#' @param ... parameters passed on to \\link[grid]{viewport}\n#' @details parameters \\code{width}, \\code{height}, \\code{xscale} and \\code{yscale} are set such that aspect ratio is honoured and plot size is maximized in the current viewport; others can be passed as \\code{...}\n#' @return The output of the call to \\link[grid]{viewport}\n#' @details If \\code{asp} is missing, it is taken as 1, except when \\code{isTRUE(st_is_longlat(x))}, in which case it is set to \\code{1.0 /cos(y)}, with \\code{y} the middle of the latitude bounding box.\n#' @examples\n#' library(grid)\n#' nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\n#' grid.newpage()\n#' pushViewport(viewport(width = 0.8, height = 0.8))\n#' pushViewport(st_viewport(nc))\n#' invisible(lapply(st_geometry(nc), function(x) grid.draw(st_as_grob(x, gp = gpar(fill = 'red')))))\n#' @export\nst_viewport = function(x, ..., bbox = st_bbox(x), asp) {\n\txscale = bbox[c(1,3)]\n\tyscale = bbox[c(2,4)]\n\n\t# from rgdal2/R/graphics.R:\n\tcurrent.viewport.size = function(units = \"inches\") {\n    \tvp = current.viewport()\n\t\tvi = convertHeight(vp$height, units, valueOnly = TRUE)\n\t\twi = convertWidth(vp$width, units, valueOnly = TRUE)\n    \tc(width = wi, height = vi)\n\t}\n\tcurrent.viewport.aspect = function() {\n    \tsz = current.viewport.size()\n    \tsz[2] / sz[1]\n\t}\n\tvp.asp = current.viewport.aspect()\n\tif (missing(asp))\n\t\tasp = if (isTRUE(st_is_longlat(x)))\n\t\t\t1.0 / cos((mean(yscale) * pi)/180)\n\t\telse\n\t\t\t1.0\n\n   \tobj.asp = asp * diff(yscale) / diff(xscale)\n\theight = obj.asp / vp.asp\n   \twidth = 1\n   \twidth = width / max(width, height)\n   \theight = height / max(width, height)\n\tviewport(width = unit(width, \"npc\"), height = unit(height, \"npc\"),\n    \t\txscale = unit(xscale, \"native\"), yscale = unit(yscale, \"native\"), ...)\n}\n\n#' @export\nst_as_grob.sfc_POINT <- function(x, pch = 1, size = unit(1, \"char\"), default.units = \"native\", name = NULL, gp = gpar(), vp = NULL, ...) {\n\tif (any(is_e <- st_is_empty(x))) {\n\t\tgp = gp[!is_e]\n\t\tx = x[!is_e]\n\t}\n\tif (length(x)) {\n\t\tx <- matrix(unlist(x, use.names = FALSE), ncol = length(x))\n\t\tpointsGrob(x[1, ], x[2, ], pch = pch, size = size,\n\t\t\t\t   default.units = default.units, name = name, gp = gp, vp = vp)\n\t} else\n\t\tnullGrob()\n}\n#' @export\n#' @importFrom grid gpar\nst_as_grob.sfc_MULTIPOINT <- function(x, pch = 1, size = unit(1, \"char\"), default.units = \"native\", name = NULL, gp = gpar(), vp = NULL, ...) {\n\tif (any(is_e <- st_is_empty(x))) {\n\t\tgp = gp[!is_e]\n\t\tx = x[!is_e]\n\t}\n\tif (length(x)) {\n\t\tx <- unclass(x)\n\t\tn_points <- vapply(x, nrow, integer(1))\n\t\tgp <- expand_gp(gp, n_points)\n\t\tif (length(pch) != 1) pch <- rep(rep(pch, length.out = length(x)), n_points)\n\t\tif (length(size) != 1) size <- rep(rep(size, length.out = length(x)), n_points)\n\t\tx <- do.call(rbind, x)\n\t\tpointsGrob(x[, 1], x[, 2], pch = pch, size = size, \n\t\t\t\t   default.units = default.units, name = name, gp = gp, vp = vp)\n\t} else\n\t\tnullGrob()\n}\n#' @export\nst_as_grob.sfc_LINESTRING <- function(x, arrow = NULL, default.units = \"native\", name = NULL, gp = gpar(), vp = NULL, ...) {\n\tif (any(is_e <- st_is_empty(x))) {\n\t\tgp = gp[!is_e]\n\t\tx = x[!is_e]\n\t}\n\tif (length(x)) {\n\t\tx <- unclass(x)\n\t\tn_points <- vapply(x, nrow, integer(1))\n\t\tx <- do.call(rbind, x)\n\t\tpolylineGrob(x[, 1], x[, 2], id.lengths = n_points, arrow = arrow, \n\t\t\t\t\t default.units = default.units, name = name, gp = gp, vp = vp)\n\t} else\n\t\tnullGrob()\n}\n#' @export\nst_as_grob.sfc_MULTILINESTRING <- function(x, arrow = NULL, default.units = \"native\", name = NULL, gp = gpar(), vp = NULL, ...) {\n\tif (any(is_e <- st_is_empty(x))) {\n\t\tgp = gp[!is_e]\n\t\tx = x[!is_e]\n\t}\n\tif (length(x)) {\n\t\tx <- unclass(x)\n\t\tn_lines <- vapply(x, length, integer(1))\n\t\tgp <- expand_gp(gp, n_lines)\n\t\tif (!is.null(arrow) && length(arrow) != 1) arrow <- rep(rep(arrow, length.out = length(x)), n_lines)\n\t\tx <- unlist(x, recursive = FALSE)\n\t\tn_points <- vapply(x, nrow, integer(1))\n\t\tx <- do.call(rbind, x)\n\t\tpolylineGrob(x[, 1], x[, 2], id.lengths = n_points, arrow = arrow, \n\t\t\t\t\t default.units = default.units, name = name, gp = gp, vp = vp)\n\t} else\n\t\tnullGrob()\n}\n#' @export\nst_as_grob.sfc_POLYGON <- function(x, rule = \"evenodd\", default.units = \"native\", name = NULL, gp = gpar(), vp = NULL, ...) {\n\tif (utils::packageVersion(\"grid\") < \"3.6\") {\n\t\treturn(scalar_grobs(x, rule = rule, default.units = default.units, name = name, gp = gp, vp = vp, ...)) # nocov\n\t}\n\tif (any(is_e <- st_is_empty(x))) {\n\t\tgp = gp[!is_e]\n\t\tx = x[!is_e]\n\t}\n\tif (length(x)) {\n\t\tx <- unclass(x) # nocov start\n\t\tn_poly <- vapply(x, length, integer(1))\n\t\tx <- unlist(x, recursive = FALSE)\n\t\tn_points <- vapply(x, nrow, integer(1))\n\t\tn_paths <- tapply(n_points, rep(seq_along(n_poly), n_poly), sum)\n\t\tx <- do.call(rbind, x)\n\t\tpathGrob(x[, 1], x[, 2], id.lengths = n_points, pathId.lengths = n_paths, \n\t\t\t\t rule = rule, default.units = default.units, name = name, gp = gp, vp = vp) # nocov end\n\t} else\n\t\tnullGrob()\n}\n#' @export\nst_as_grob.sfc_MULTIPOLYGON <- function(x, rule = \"evenodd\", default.units = \"native\", name = NULL, gp = gpar(), vp = NULL, ...) {\n\tif (utils::packageVersion(\"grid\") < \"3.6\") {\n\t\treturn(scalar_grobs(x, rule = rule, default.units = default.units, name = name, gp = gp, vp = vp, ...)) # nocov\n\t}\n\tif (any(is_e <- st_is_empty(x))) {\n\t\tgp = gp[!is_e]\n\t\tx = x[!is_e]\n\t}\n\tif (length(x)) {\n\t\tx <- unclass(x) # nocov start\n\t\tn_poly <- vapply(x, length, integer(1))\n\t\tgp <- expand_gp(gp, n_poly)\n\t\tx <- unlist(x, recursive = FALSE)\n\t\tn_poly <- vapply(x, length, integer(1))\n\t\tx <- unlist(x, recursive = FALSE)\n\t\tn_points <- vapply(x, nrow, integer(1))\n\t\tn_paths <- tapply(n_points, rep(seq_along(n_poly), n_poly), sum)\n\t\tx <- do.call(rbind, x)\n\t\tpathGrob(x[, 1], x[, 2], id.lengths = n_points, pathId.lengths = n_paths, \n\t\t\t\t rule = rule, default.units = default.units, name = name, gp = gp, vp = vp) # nocov end\n\t} else\n\t\tnullGrob()\n}\n#' @export\nst_as_grob.sfc_CIRCULARSTRING <- function(x, ...) {\n\tst_as_grob(st_cast(x, 'LINESTRING'), ...) # nocov\n}\n#' @export\n#' @importFrom grid gList\nst_as_grob.sfc <- function(x, pch = 1, size = unit(1, \"char\"), arrow = NULL, gp = gpar(), ...) {\n\told_length <- length(x)\n\tx <- st_cast_sfc_default(x)\n\tids <- attr(x, 'ids')\n\tif (!is.null(ids)) {\n\t\t# x was a geometrycollection that has been unlisted. Need to match gpar\n\t\tif (length(pch) > 1) {\n\t\t\tpch <- rep(rep_len(pch, old_length), ids)\n\t\t}\n\t\tif (length(size) > 1) {\n\t\t\tsize <- rep(rep_len(size, old_length), ids)\n\t\t}\n\t\tif (length(arrow) > 1) {\n\t\t\tarrow <- rep(rep_len(arrow, old_length), ids)\n\t\t}\n\t\tfor (par in names(gp)) {\n\t\t\tif (length(gp[[par]]) > 1) {\n\t\t\t\tgp[[par]] <- rep(rep_len(gp[[par]], old_length), ids)\n\t\t\t}\n\t\t}\n\t}\n\tif (class(x)[1] %in% c('sfc_MULTIPOINT', 'sfc_MULTILINESTRING', 'sfc_MULTIPOLYGON'))\n\t\tst_as_grob(x, pch = pch, size = size, arrow = arrow, gp = gp, ...)\n\telse\n\t\tscalar_grobs(x, pch, size, arrow, gp, ...)\n}\n\nscalar_grobs <- function(x, pch = 1, size = unit(1, \"char\"), arrow = NULL, gp = gpar(), ...) {\n\tgp <- split_gp(gp, length(x))\n\tpch <- rep(pch, length.out = length(x))\n\tsize <- rep(size,  length.out = length(x))\n\tif (!is.null(arrow)) arrow <- rep(arrow, length.out = length(x))\n\tdo.call(gList, lapply(seq_along(x), function(i) {\n\t\tst_as_grob(x[[i]], pch = pch[i], size = size[i], arrow = arrow[i], gp = gp[[i]], ...)\n\t}))\n}\n\nexpand_gp <- function(gp, n) {\n\tif (length(gp) == 0) return(gp)\n\tgp <- unclass(gp)\n\tn_gp <- vapply(gp, length, integer(1))\n\tgp[n_gp > 1] <- lapply(gp[n_gp > 1], rep, n)\n\t`class<-`(gp, 'gpar')\n}\nsplit_gp <- function(gp, n) {\n\tgp <- unclass(gp)\n\tgp <- lapply(gp, rep_len, n)\n\tlapply(seq_len(n), function(i) {\n\t\t`class<-`(lapply(gp, `[`, i), 'gpar')\n\t})\n}\n"
  },
  {
    "path": "R/import-standalone-s3-register.R",
    "content": "# Standalone file: do not edit by hand\n# Source: <https://github.com/r-lib/rlang/blob/main/R/standalone-s3-register.R>\n# ----------------------------------------------------------------------\n#\n# ---\n# repo: r-lib/rlang\n# file: standalone-s3-register.R\n# last-updated: 2022-08-29\n# license: https://unlicense.org\n# ---\n#\n# nocov start\n\n#' Register a method for a suggested dependency\n#'\n#' Generally, the recommended way to register an S3 method is to use the\n#' `S3Method()` namespace directive (often generated automatically by the\n#' `@export` roxygen2 tag). However, this technique requires that the generic\n#' be in an imported package, and sometimes you want to suggest a package,\n#' and only provide a method when that package is loaded. `s3_register()`\n#' can be called from your package's `.onLoad()` to dynamically register\n#' a method only if the generic's package is loaded.\n#'\n#' For R 3.5.0 and later, `s3_register()` is also useful when demonstrating\n#' class creation in a vignette, since method lookup no longer always involves\n#' the lexical scope. For R 3.6.0 and later, you can achieve a similar effect\n#' by using \"delayed method registration\", i.e. placing the following in your\n#' `NAMESPACE` file:\n#'\n#' ```\n#' if (getRversion() >= \"3.6.0\") {\n#'   S3method(package::generic, class)\n#' }\n#' ```\n#'\n#' @section Usage in other packages:\n#' To avoid taking a dependency on vctrs, you copy the source of\n#' [`s3_register()`](https://github.com/r-lib/rlang/blob/main/R/standalone-s3-register.R)\n#' into your own package. It is licensed under the permissive\n#' [unlicense](https://choosealicense.com/licenses/unlicense/) to make it\n#' crystal clear that we're happy for you to do this. There's no need to include\n#' the license or even credit us when using this function.\n#'\n#' @param generic Name of the generic in the form `\"pkg::generic\"`.\n#' @param class Name of the class\n#' @param method Optionally, the implementation of the method. By default,\n#'   this will be found by looking for a function called `generic.class`\n#'   in the package environment.\n#' @examples\n#' # A typical use case is to dynamically register tibble/pillar methods\n#' # for your class. That way you avoid creating a hard dependency on packages\n#' # that are not essential, while still providing finer control over\n#' # printing when they are used.\n#'\n#' .onLoad <- function(...) {\n#'   s3_register(\"pillar::pillar_shaft\", \"vctrs_vctr\")\n#'   s3_register(\"tibble::type_sum\", \"vctrs_vctr\")\n#' }\n#' @keywords internal\n#' @noRd\ns3_register <- function(generic, class, method = NULL) {\n  stopifnot(is.character(generic), length(generic) == 1)\n  stopifnot(is.character(class), length(class) == 1)\n\n  pieces <- strsplit(generic, \"::\")[[1]]\n  stopifnot(length(pieces) == 2)\n  package <- pieces[[1]]\n  generic <- pieces[[2]]\n\n  caller <- parent.frame()\n\n  get_method_env <- function() {\n    top <- topenv(caller)\n    if (isNamespace(top)) {\n      asNamespace(environmentName(top))\n    } else {\n      caller\n    }\n  }\n  get_method <- function(method) {\n    if (is.null(method)) {\n      get(paste0(generic, \".\", class), envir = get_method_env())\n    } else {\n      method\n    }\n  }\n\n  register <- function(...) {\n    envir <- asNamespace(package)\n\n    # Refresh the method each time, it might have been updated by\n    # `devtools::load_all()`\n    method_fn <- get_method(method)\n    stopifnot(is.function(method_fn))\n\n\n    # Only register if generic can be accessed\n    if (exists(generic, envir)) {\n      registerS3method(generic, class, method_fn, envir = envir)\n    } else if (identical(Sys.getenv(\"NOT_CRAN\"), \"true\")) {\n      warn <- .rlang_s3_register_compat(\"warn\")\n\n      warn(c(\n        sprintf(\n          \"Can't find generic `%s` in package %s to register S3 method.\",\n          generic,\n          package\n        ),\n        \"i\" = \"This message is only shown to developers using devtools.\",\n        \"i\" = sprintf(\"Do you need to update %s to the latest version?\", package)\n      ))\n    }\n  }\n\n  # Always register hook in case package is later unloaded & reloaded\n  setHook(packageEvent(package, \"onLoad\"), function(...) {\n    register()\n  })\n\n  # For compatibility with R < 4.1.0 where base isn't locked\n  is_sealed <- function(pkg) {\n    identical(pkg, \"base\") || environmentIsLocked(asNamespace(pkg))\n  }\n\n  # Avoid registration failures during loading (pkgload or regular).\n  # Check that environment is locked because the registering package\n  # might be a dependency of the package that exports the generic. In\n  # that case, the exports (and the generic) might not be populated\n  # yet (#1225).\n  if (isNamespaceLoaded(package) && is_sealed(package)) {\n    register()\n  }\n\n  invisible()\n}\n\n.rlang_s3_register_compat <- function(fn, try_rlang = TRUE) {\n  # Compats that behave the same independently of rlang's presence\n  out <- switch(\n    fn,\n    is_installed = return(function(pkg) requireNamespace(pkg, quietly = TRUE))\n  )\n\n  # Only use rlang if it is fully loaded (#1482)\n  if (try_rlang &&\n        requireNamespace(\"rlang\", quietly = TRUE) &&\n        environmentIsLocked(asNamespace(\"rlang\"))) {\n    switch(\n      fn,\n      is_interactive = return(rlang::is_interactive)\n    )\n\n    # Make sure rlang knows about \"x\" and \"i\" bullets\n    if (utils::packageVersion(\"rlang\") >= \"0.4.2\") {\n      switch(\n        fn,\n        abort = return(rlang::abort),\n        warn = return((rlang::warn)),\n        inform = return(rlang::inform)\n      )\n    }\n  }\n\n  # Fall back to base compats\n\n  is_interactive_compat <- function() {\n    opt <- getOption(\"rlang_interactive\")\n    if (!is.null(opt)) {\n      opt\n    } else {\n      interactive()\n    }\n  }\n\n  format_msg <- function(x) paste(x, collapse = \"\\n\")\n  switch(\n    fn,\n    is_interactive = return(is_interactive_compat),\n    abort = return(function(msg) stop(format_msg(msg), call. = FALSE)),\n    warn = return(function(msg) warning(format_msg(msg), call. = FALSE)),\n    inform = return(function(msg) message(format_msg(msg)))\n  )\n\n  stop(sprintf(\"Internal error in rlang shims: Unknown function `%s()`.\", fn))\n}\n\n# nocov end\n"
  },
  {
    "path": "R/init.R",
    "content": "#' @importFrom utils head object.size str tail packageVersion compareVersion globalVariables\n#' @importFrom stats aggregate dist na.omit rbinom runif setNames\n#' @importFrom tools file_ext file_path_sans_ext\n#' @importFrom methods as new slot slotNames slot<-\n#' @importFrom grid convertHeight convertUnit convertWidth current.viewport linesGrob nullGrob pathGrob pointsGrob polylineGrob unit viewport\n#' @import graphics\n#' @importFrom grDevices dev.size rgb cm\n#' @importFrom DBI dbConnect dbDisconnect dbExecute dbGetQuery dbReadTable dbSendQuery dbWriteTable\n#' @importFrom units as_units drop_units make_unit_label set_units\n#' @importFrom classInt classIntervals\n#' @useDynLib sf, .registration=TRUE\nNULL\n\nsetOldClass(\"sf\")\nsetOldClass(c(\"sfc_POINT\", \"sfc\"))\nsetOldClass(c(\"sfc_MULTIPOINT\", \"sfc\"))\nsetOldClass(c(\"sfc_LINESTRING\", \"sfc\"))\nsetOldClass(c(\"sfc_MULTILINESTRING\", \"sfc\"))\nsetOldClass(c(\"sfc_POLYGON\", \"sfc\"))\nsetOldClass(c(\"sfc_MULTIPOLYGON\", \"sfc\"))\nsetOldClass(c(\"sfc_GEOMETRY\", \"sfc\"))\nsetOldClass(c(\"sfc_GEOMETRYCOLLECTION\", \"sfc\"))\nsetOldClass(\"sfg\")\nsetOldClass(\"crs\")\nsetOldClass(\"bbox\")\n\n.sf_cache <- new.env(FALSE, parent=globalenv())\n\npathGrob <- NULL\n.onLoad = function(libname, pkgname) {\n\tif (getRversion() < as.numeric_version(\"3.6\")) { # nocov start\n\t\tpathGrob <<- function(..., pathId.lengths) {\n\t\t\tgrid::pathGrob(...)\n\t\t}\n\t} # nocov end\n\tload_gdal() \n\tif ((s2 <- Sys.getenv(\"_SF_USE_S2\")) != \"\")\n\t\toptions(sf_use_s2 = s2 != \"false\")\n\tFULL_bbox_ <<- st_set_crs(FULL_bbox_, \"OGC:CRS84\")\n}\n\n.onUnload = function(libname, pkgname) {\n\tunload_gdal() # nocov\n}\n\n.onAttach = function(libname, pkgname) {\n\tm = paste0(\"Linking to GEOS \", strsplit(CPL_geos_version(TRUE), \"-\")[[1]][1],\n\t\t\", GDAL \", CPL_gdal_version(), \", PROJ \", CPL_proj_version(),\n\t\t\"; sf_use_s2() is \", sf_use_s2())\n\tm = strwrap(m, width = getOption(\"width\"))\n\tpackageStartupMessage(paste0(m, collapse = \"\\n\"))\n\tif (length(grep(CPL_geos_version(FALSE, TRUE), CPL_geos_version(TRUE))) != 1) { # nocov start\n\t\tpackageStartupMessage(\"WARNING: different compile-time and runtime versions for GEOS found:\")\n\t\tpackageStartupMessage(paste(\n\t\t\t\"Linked against:\", CPL_geos_version(TRUE, TRUE),\n\t\t\t\"compiled against:\", CPL_geos_version(FALSE, TRUE)))\n\t\tpackageStartupMessage(\"It is probably a good idea to reinstall sf (and maybe lwgeom too)\")\n\t} # nocov end\n}\n\n#' Provide the external dependencies versions of the libraries linked to sf\n#'\n#' Provide the external dependencies versions of the libraries linked to sf\n#' @export\nsf_extSoftVersion = function() {\n\tstructure(c(CPL_geos_version(), CPL_gdal_version(), CPL_proj_version(), \n\t\tifelse(CPL_gdal_with_geos(), \"true\", \"false\"),\n\t\tifelse(CPL_proj_h(), \"true\", \"false\"), CPL_proj_version()),\n\t\tnames = c(\"GEOS\", \"GDAL\", \"proj.4\", \"GDAL_with_GEOS\", \"USE_PROJ_H\", \"PROJ\"))\n}\n\nsave_and_replace = function(var, value, where) {\n\tif (Sys.getenv(var) != \"\")\n\t\tassign(paste0(\".sf.\", var), Sys.getenv(var), envir = where)\n\t# Sys.setenv(var = value) uses NSE and will set var, not the variable var points to:\n\tdo.call(Sys.setenv, setNames(list(value), var))\n}\n\nif_exists_restore = function(vars, where) {\n\tfn = function(var, where) {\n\t\tlname = paste0(\".sf.\", var)\n\t\tif (!is.null(get0(lname, envir = where)))\n\t\t\tdo.call(Sys.setenv, setNames(list(get(lname, envir = where)), var)) # see above\n\t}\n\tlapply(vars, fn, where = where)\n}\n\nload_gdal <- function() {\n\tif (!identical(Sys.getenv(\"R_SF_USE_PROJ_DATA\"), \"true\")) {\n\t\tif (file.exists(prj <- system.file(\"proj\", package = \"sf\")[1])) {\n\t\t\t# nocov start\n\t\t\tif (! sf_proj_search_paths(prj)) { # if TRUE, uses C API to set path, leaving PROJ_LIB / PROJ_DATA alone\n\t\t\t\tsave_and_replace(\"PROJ_LIB\", prj, .sf_cache)\n\t\t\t\tsave_and_replace(\"PROJ_DATA\", prj, .sf_cache)\n\t\t\t}\n\t\t\t# CPL_use_proj4_init_rules(1L)\n\t\t\t# nocov end\n\t\t}\n\t\tif (file.exists(gdl <- system.file(\"gdal\", package = \"sf\")[1]))\n\t\t\tsave_and_replace(\"GDAL_DATA\", gdl, .sf_cache)\n\t}\n\tCPL_gdal_init()\n\tregister_all_s3_methods() # dynamically registers non-imported pkgs (tidyverse)\n}\n\nunload_gdal <- function() {\n\tCPL_gdal_cleanup_all()\n\tif_exists_restore(c(\"PROJ_LIB\", \"PROJ_DATA\", \"GDAL_DATA\"), .sf_cache)\n}\n \n\n#' @export\n#' @name sf_project\n#' @details \\code{sf_add_proj_units} loads the PROJ units `link`, `us_in`, `ind_yd`, `ind_ft`, and `ind_ch` into the udunits database, and returns \\code{TRUE} invisibly on success.\n#' @examples\n#' sf_add_proj_units()\nsf_add_proj_units = function() {\n\t#nocov start\n\tunits::install_unit(\"link\", \"0.201168 m\")\n\tunits::install_unit(\"us_in\", \"1./39.37 m\")\n\tunits::install_unit(\"ind_yd\", \"0.91439523 m\")\n\tunits::install_unit(\"ind_ft\", \"0.30479841 m\")\n\tunits::install_unit(\"ind_ch\", \"20.11669506 m\")\n\tinvisible(TRUE)\n\t#nocov end\n}\n"
  },
  {
    "path": "R/jitter.R",
    "content": "\n#' jitter geometries\n#' @param x object of class \\code{sf} or \\code{sfc}\n#' @param amount numeric; amount of jittering applied; if missing, the amount is set to factor * the bounding box diagonal; units of coordinates.\n#' @param factor numeric; fractional amount of jittering to be applied\n#' @details jitters coordinates with an amount such that \\code{runif(1, -amount, amount)} is added to the coordinates. x- and y-coordinates are jittered independently but all coordinates of a single geometry are jittered with the same amount, meaning that the geometry shape does not change. For longlat data, a latitude correction is made such that jittering in East and North directions are identical in distance in the center of the bounding box of \\code{x}.\n#' @examples\n#' nc = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"))\n#' pts = st_centroid(st_geometry(nc))\n#' plot(pts)\n#' plot(st_jitter(pts, .05), add = TRUE, col = 'red')\n#' plot(st_geometry(nc))\n#' plot(st_jitter(st_geometry(nc), factor = .01), add = TRUE, col = '#ff8888')\n#' @export\nst_jitter = function(x, amount, factor = 0.002) {      \n\tstopifnot(inherits(x, \"sf\") || inherits(x, \"sfc\"))\n\tbb = st_bbox(x)\n\tif (missing(amount))\n\t\tamount = factor * sqrt(diff(bb[c(3,1)])^2 + diff(bb[c(4,2)])^2)\n\tay = amount\n\tax = if (isTRUE(st_is_longlat(x)))\n\t\tamount * cos(pi * mean(bb[c(2,4)]) / 180)\n\telse\n\t\tamount\n    f = function(z, amount_x, amount_y) {\n\t\tst_point(c(runif(1L, -amount_x, amount_x),\n\t\t  runif(1L, -amount_y, amount_y)))\n\t}\n\tgeom = st_geometry(x)\n\tgeom = st_set_crs(geom + lapply(geom, f, amount_x = ax, amount_y = ay), st_crs(x))\n\tif (inherits(x, \"sf\"))\n\t\tst_set_geometry(x, geom)\n\telse\n\t\tgeom\n}\n"
  },
  {
    "path": "R/join.R",
    "content": "check_join = function(x, y) {\n\tif (inherits(y, \"sf\"))\n\t\tstop(\"y should not have class sf; for spatial joins, use st_join\", call. = FALSE)\n}\n\nsf_join = function(g, sf_column, suffix_x = \".x\") {\n\tif (!(sf_column %in% names(g))) {\n\t\tsf_column = paste0(sf_column, suffix_x)\n\t\tstopifnot(sf_column %in% names(g))\n\t}\n\tattr(g[[ sf_column ]], \"bbox\") = NULL # remove, so that st_sfc() recomputes:\n\tg[[ sf_column ]] = st_sfc(g[[ sf_column ]])\n\tst_sf(g, sf_column_name = sf_column)\n}\n\n#' @name tidyverse\n#' @inheritParams dplyr::inner_join\ninner_join.sf = function(x, y, by = NULL, copy = FALSE, suffix = c(\".x\", \".y\"), ...) {\n\tcheck_join(x, y)\n\tclass(x) = setdiff(class(x), \"sf\")\n\tsf_join(NextMethod(), attr(x, \"sf_column\"), suffix[1])\n}\n\n#' @name tidyverse\nleft_join.sf = function(x, y, by = NULL, copy = FALSE, suffix = c(\".x\", \".y\"), ...) {\n\tcheck_join(x, y)\n\tclass(x) = setdiff(class(x), \"sf\")\n\tsf_join(NextMethod(), attr(x, \"sf_column\"), suffix[1])\n}\n\n#' @name tidyverse\nright_join.sf = function(x, y, by = NULL, copy = FALSE, suffix = c(\".x\", \".y\"), ...) {\n\tcheck_join(x, y)\n\tclass(x) = setdiff(class(x), \"sf\")\n\tsf_join(NextMethod(), attr(x, \"sf_column\"), suffix[1])\n}\n\n#' @name tidyverse\nfull_join.sf = function(x, y, by = NULL, copy = FALSE, suffix = c(\".x\", \".y\"), ...) {\n\tcheck_join(x, y)\n\tclass(x) = setdiff(class(x), \"sf\")\n\tsf_join(NextMethod(), attr(x, \"sf_column\"), suffix[1])\n}\n\n#' @name tidyverse\nsemi_join.sf = function(x, y, by = NULL, copy = FALSE, suffix = c(\".x\", \".y\"), ...) {\n\tcheck_join(x, y)\n\tclass(x) = setdiff(class(x), \"sf\")\n\tsf_join(NextMethod(), attr(x, \"sf_column\"), suffix[1])\n}\n\n#' @name tidyverse\nanti_join.sf = function(x, y, by = NULL, copy = FALSE, suffix = c(\".x\", \".y\"), ...) {\n\tcheck_join(x, y)\n\tclass(x) = setdiff(class(x), \"sf\")\n\tsf_join(NextMethod(), attr(x, \"sf_column\"), suffix[1])\n}\n\n\n#' spatial join, spatial filter\n#'\n#' spatial join, spatial filter\n#' @name st_join\n#' @export\nst_join = function(x, y, join, ...) UseMethod(\"st_join\")\n\n#' @name st_join\n#' @param x object of class \\code{sf}\n#' @param y object of class \\code{sf}\n#' @param join geometry predicate function with the same profile as \\link{st_intersects}; see details\n#' @param suffix length 2 character vector; see \\link[base]{merge}\n#' @param ... for \\code{st_join}: arguments passed on to the \\code{join} function or to \\code{st_intersection} when \\code{largest} is \\code{TRUE}; for \\code{st_filter} arguments passed on to the \\code{.predicate} function, e.g. \\code{prepared}, or a pattern for \\link{st_relate}\n#' @param left logical; if \\code{TRUE} return the left join, otherwise an inner join; see details.\n#' see also \\link[dplyr:mutate-joins]{left_join}\n#' @param largest logical; if \\code{TRUE}, return \\code{x} features augmented with the fields of \\code{y} that have the largest overlap with each of the features of \\code{x}; see https://github.com/r-spatial/sf/issues/578\n#' \n#' @details alternative values for argument \\code{join} are:\n#' \\itemize{\n#'   \\item \\link{st_contains_properly},\n#'   \\item \\link{st_contains},\n#'   \\item \\link{st_covered_by},\n#'   \\item \\link{st_covers},\n#'   \\item \\link{st_crosses},\n#'   \\item \\link{st_disjoint},\n#'   \\item \\link{st_equals_exact},\n#'   \\item \\link{st_equals},\n#'   \\item \\link{st_is_within_distance},\n#'   \\item \\link{st_nearest_feature},\n#'   \\item \\link{st_overlaps},\n#'   \\item \\link{st_touches},\n#'   \\item \\link{st_within},\n#'   \\item \\link{st_relate} (which will require `pattern` to be set),\n#'   \\item or any user-defined function of the same profile as the above\n#' }\n#' A left join returns all records of the \\code{x} object with \\code{y} fields for non-matched records filled with \\code{NA} values; an inner join returns only records that spatially match.\n#' \n#' To replicate the results of \\code{st_within(x, y)} you will need to use \\code{st_join(x, y, join = \"st_within\", left = FALSE)}.\n#'\n#' @return an object of class \\code{sf}, joined based on geometry\n#' @examples\n#' a = st_sf(a = 1:3,\n#'  geom = st_sfc(st_point(c(1,1)), st_point(c(2,2)), st_point(c(3,3))))\n#' b = st_sf(a = 11:14,\n#'  geom = st_sfc(st_point(c(10,10)), st_point(c(2,2)), st_point(c(2,2)), st_point(c(3,3))))\n#' st_join(a, b)\n#' st_join(a, b, left = FALSE)\n#' # two ways to aggregate y's attribute values outcome over x's geometries:\n#' j = st_join(a, b)\n#' aggregate(j, list(j$a.x), mean)\n#' if (require(dplyr, quietly = TRUE)) {\n#'  st_join(a, b) |> group_by(a.x) |> summarise(mean(a.y))\n#' }\n#' # example of largest = TRUE:\n#' nc <- st_transform(st_read(system.file(\"shape/nc.shp\", package=\"sf\")), 2264)                \n#' gr = st_sf(\n#'     label = apply(expand.grid(1:10, LETTERS[10:1])[,2:1], 1, paste0, collapse = \" \"),\n#'     geom = st_make_grid(st_as_sfc(st_bbox(nc))))\n#' gr$col = sf.colors(10, categorical = TRUE, alpha = .3)\n#' # cut, to check, NA's work out:\n#' gr = gr[-(1:30),]\n#' nc_j <- st_join(nc, gr, largest = TRUE)\n#' # the two datasets:\n#' opar = par(mfrow = c(2,1), mar = rep(0,4))\n#' plot(st_geometry(nc_j))\n#' plot(st_geometry(gr), add = TRUE, col = gr$col)\n#' text(st_coordinates(st_centroid(gr)), labels = gr$label)\n#' # the joined dataset:\n#' plot(st_geometry(nc_j), border = 'black', col = nc_j$col)\n#' text(st_coordinates(st_centroid(nc_j)), labels = nc_j$label, cex = .8)\n#' plot(st_geometry(gr), border = 'green', add = TRUE)\n#' par(opar)\n#' # st_filter keeps the geometries in x where .predicate(x,y) returns any match in y for x\n#' st_filter(a, b)\n#' # for an anti-join, use the union of y\n#' st_filter(a, st_union(b), .predicate = st_disjoint)\n#' @export\nst_join.sf = function(x, y, join = st_intersects, ..., suffix = c(\".x\", \".y\"), \n\t\tleft = TRUE, largest = FALSE) {\n\n\tif (!inherits(y, \"sf\"))\n\t\tstop(\"second argument should be of class sf: maybe revert the first two arguments?\") # nocov\n\n\ti = if (largest) {\n\t\tx$.grp_a = seq_len(nrow(x))\n\t\ty$.grp_b = seq_len(nrow(y))\n\t\tst_intersection(x, y, ...)\n\t} else \n\t\tjoin(x, y, ...)\n\n\tst_geometry(y) = NULL\n\twhich.x = which(names(x) %in% names(y))\n\twhich.y = which(names(y) %in% names(x))\n\tif (length(which.x))\n\t\tnames(x)[which.x] = paste0(names(x)[which.x], suffix[1])\n\tif (length(which.y))\n\t\tnames(y)[which.y] = paste0(names(y)[which.y], suffix[2])\n\n\t# create match index ix & i:\n\tif (largest) {\n\t\tx$.grp_a = y$.grp_b = NULL # clean up\n\t\ti$.size = if (all(st_dimension(i) < 2)) st_length(i) else st_area(i)\n\t\tl = lapply(split(i, i$.grp_a), function(x) x[which.max(x$.size), ]$.grp_b)\n\t\tix = as.integer(names(l)) # non-empty x features\n\t\ti = unlist(l) # matching largest y feature\n\t\tif (left) { # fill NA's\n\t\t\tidx = rep(NA_integer_, nrow(x)) # all x features\n\t\t\tidx[ix] = i\n\t\t\tix = seq_len(nrow(x))\n\t\t\ti = idx\n\t\t}\n\t} else {\n\t\tif (left) # fill NA y values when no match:\n\t\t\ti = lapply(i, function(x) { if (length(x) == 0) NA_integer_ else x })\n\t\tix = rep(seq_len(nrow(x)), lengths(i))\n\t}\n\tif (inherits(x, \"tbl_df\") && requireNamespace(\"dplyr\", quietly = TRUE))\n\t\tst_sf(dplyr::bind_cols(x[ix,], y[unlist(i), , drop = FALSE]))\n  \telse\n\t\tst_sf(cbind(as.data.frame(x)[ix, ,drop=FALSE], y[unlist(i), , drop = FALSE]))\n}\n\n#' @export\n#' @name st_join\nst_filter = function(x, y, ...) UseMethod(\"st_filter\")\n\n#' @export\n#' @name st_join\n#' @param .predicate geometry predicate function with the same profile as \\link{st_intersects}; see details\nst_filter.sf = function(x, y, ..., .predicate = st_intersects) {\n\tif (!requireNamespace(\"dplyr\", quietly = TRUE))\n\t\tstop(\"dplyr is not installed: install first?\")\n\n    dplyr::filter(x, lengths(.predicate(!!x, !!y, ...)) > 0) # will call filter.sf\n}\n"
  },
  {
    "path": "R/m_range.R",
    "content": "\n#' @name st_m_range\n#' @param x object of class \\code{m_range}\n#' @export\nis.na.m_range = function(x) identical(x, NA_m_range_)\n\nmb_wrap = function(mb) {\n\tstopifnot(is.numeric(mb), length(mb) == 2)\n\tstructure(mb, names = c(\"mmin\", \"mmax\"), class = \"m_range\")\n}\n\nm_range.Set = function(obj, ...) {\n\tsel = vapply(obj, function(x) { length(x) && !all(is.na(x)) }, TRUE)\n\tif (! any(sel))\n\t\tNA_m_range_\n\telse\n\t\tmb_wrap(CPL_get_m_range(unclass(obj)[sel], 0))\n}\nm_range.Mtrx = function(obj, ...) {\n\tif (length(obj) == 0)\n\t\tNA_m_range_\n\telse\n\t\tmb_wrap(CPL_get_m_range(list(obj), 1)) # note the list()\n}\nm_range.MtrxSet = function(obj, ...) {\n\tif (length(obj) == 0)\n\t\tNA_m_range_\n\telse\n\t\tmb_wrap(CPL_get_m_range(obj, 1))\n}\nm_range.MtrxSetSet = function(obj, ...) {\n\tif (length(obj) == 0)\n\t\tNA_m_range_\n\telse\n\t\tmb_wrap(CPL_get_m_range(obj, 2))\n}\nm_range.MtrxSetSetSet = function(obj, ...) {\n\tif (length(obj) == 0)\n\t\tNA_m_range_\n\telse\n\t\tmb_wrap(CPL_get_m_range(obj, 3))\n}\n\n#' Return 'm' range of a simple feature or simple feature set\n#'\n#' Return 'm' range of a simple feature or simple feature set\n#' @param obj object to compute the m range from\n#' @param ... ignored\n#' @export\n#' @return a numeric vector of length two, with \\code{mmin} and \\code{mmax} values;\n#' if \\code{obj} is of class \\code{sf} or \\code{sfc} the object\n#' if \\code{obj} is of class \\code{sf} or \\code{sfc} the object\n#' returned has a class \\code{m_range}\n#' @name st_m_range\n#' @examples\n#' a = st_sf(a = 1:2, geom = st_sfc(st_point(0:3), st_point(1:4)), crs = 4326)\n#' st_m_range(a)\nst_m_range = function(obj, ...) UseMethod(\"st_m_range\")\n\n#' @export\n#' @name st_m_range\nst_m_range.POINT = function(obj, ...) mb_wrap(if (inherits(obj, \"XYM\")) c(obj[3L], obj[3L]) else c(obj[4L],obj[4L]))\n#' @export\n#' @name st_m_range\nst_m_range.MULTIPOINT = m_range.Mtrx\n#' @export\n#' @name st_m_range\nst_m_range.LINESTRING = m_range.Mtrx\n#' @export\n#' @name st_m_range\nst_m_range.POLYGON = m_range.MtrxSet\n#' @export\n#' @name st_m_range\nst_m_range.MULTILINESTRING = m_range.MtrxSet\n#' @export\n#' @name st_m_range\nst_m_range.MULTIPOLYGON = m_range.MtrxSetSet\n\nm_range_list = function(obj, ...) {\n\ts = vapply(obj, st_m_range, c(0.,0.)) # dispatch on class\n\tif (length(s) == 0 || all(is.na(s[1L,])))\n\t\tNA_m_range_\n\telse\n\t\tmb_wrap(c(min(s[1L,], na.rm = TRUE), max(s[2L,], na.rm = TRUE)))\n}\n\n#' @name st_m_range\n#' @export\nst_m_range.GEOMETRYCOLLECTION = m_range_list\n\n#' @name st_m_range\n#' @export\nst_m_range.MULTISURFACE = m_range_list\n\n#' @name st_m_range\n#' @export\nst_m_range.MULTICURVE = m_range_list\n\n#' @name st_m_range\n#' @export\nst_m_range.CURVEPOLYGON = m_range_list\n\n#' @name st_m_range\n#' @export\nst_m_range.COMPOUNDCURVE = m_range_list\n\n#' @name st_m_range\n#' @export\nst_m_range.POLYHEDRALSURFACE = m_range.MtrxSetSet\n\n#' @name st_m_range\n#' @export\nst_m_range.TIN = m_range.MtrxSetSet\n\n#' @name st_m_range\n#' @export\nst_m_range.TRIANGLE = m_range.MtrxSet\n\n#' @name st_m_range\n#' @export\nst_m_range.CIRCULARSTRING = function(obj, ...) {\n\t# this is of course wrong:\n\tst_m_range(st_cast(obj, \"LINESTRING\")) # nocov\n}\n\n#' @export\nprint.m_range = function(x, ...) {\n\tx = structure(x, crs = NULL, class = NULL) # nocov\n\tprint(set_units(x, attr(x, \"units\"), mode = \"standard\")) # nocov\n}\n\ncompute_m_range = function(obj) {\n\tswitch(class(obj)[1],\n\t\t   sfc_POINT = mb_wrap(m_range.Set(obj)),\n\t\t   sfc_MULTIPOINT = mb_wrap(m_range.MtrxSet(obj)),\n\t\t   sfc_LINESTRING = mb_wrap(m_range.MtrxSet(obj)),\n\t\t   sfc_POLYGON = mb_wrap(m_range.MtrxSetSet(obj)),\n\t\t   sfc_MULTILINESTRING = mb_wrap(m_range.MtrxSetSet(obj)),\n\t\t   sfc_MULTIPOLYGON = mb_wrap(m_range.MtrxSetSetSet(obj)),\n\t\t   m_range_list(obj)\n\t)\n}\n\n#' @name st_m_range\n#' @export\nst_m_range.sfc = function(obj, ...) {\n\ta = attr(obj, \"m_range\")\n\tif(is.null(a)) return( NULL ) ## TODO return null?\n\tstructure(a, crs = st_crs(obj))\n}\n#' @name st_m_range\n#' @export\nst_m_range.sf = function(obj, ...) st_m_range(st_geometry(obj))\n\n#' @name st_m_range\n#' @param crs object of class \\code{crs}, or argument to \\link{st_crs}, specifying the CRS of this bounding box.\n#' @examples\n#' st_m_range(c(mmin = 16.1, mmax = 16.6), crs = st_crs(4326))\n#' @export\nst_m_range.numeric = function(obj, ..., crs = NA_crs_) {\n\tstructure(mb_wrap(obj[c(\"mmin\", \"mmax\")]), crs = st_crs(crs)) # nocov\n}\n\n#' @export\nst_m_range.m_range = function(obj, ...) obj # nocov\n\n\n#' @export\n\"$.m_range\" = function(x, name) { # nocov start\n\tswitch(name,\n\t\t   mmin = x[\"mmin\"],\n\t\t   mmax = x[\"mmax\"],\n\t\t   stop(\"unsupported name\")\n\t)\n} # nocov end\n\n#' @name st_m_range\n#' @details \\code{NA_m_range_} represents the missing value for a \\code{m_range} object\n#' @export\nNA_m_range_ = structure(rep(NA_real_, 2),\n\t\t\t\t\t names = c(\"mmin\", \"mmax\"),\n\t\t\t\t\t crs = NA_crs_,\n\t\t\t\t\t class = \"m_range\")\n"
  },
  {
    "path": "R/make_grid.R",
    "content": "#' Create a regular tesselation over the bounding box of an sf or sfc object\n#'\n#' Create a square or hexagonal grid covering the bounding box of the geometry of an sf or sfc object\n#' @param x object of class \\link{sf} or \\link{sfc}\n#' @param cellsize numeric of length 1 or 2 with target cellsize: for square or rectangular cells the width and height, for hexagonal cells the distance between opposite edges (edge length is cellsize/sqrt(3)). A length units object can be passed, or an area unit object with area size of the square or hexagonal cell.\n#' @param offset numeric of length 2; lower left corner coordinates (x, y) of the grid\n#' @param n integer of length 1 or 2, number of grid cells in x and y direction (columns, rows)\n#' @param crs object of class \\code{crs}; coordinate reference system of the target grid in case argument \\code{x} is missing, if \\code{x} is not missing, its crs is inherited.\n#' @param what character; one of: \\code{\"polygons\"}, \\code{\"corners\"}, or \\code{\"centers\"}\n#' @param square logical; if \\code{FALSE}, create hexagonal grid\n#' @param flat_topped logical; if \\code{TRUE} generate flat topped hexagons, else generate pointy topped\n#' @return Object of class \\code{sfc} (simple feature geometry list column) with, depending on \\code{what} and \\code{square},\n#' square or hexagonal polygons, corner points of these polygons, or center points of these polygons.\n#' @examples\n#' plot(st_make_grid(what = \"centers\"), axes = TRUE)\n#' plot(st_make_grid(what = \"corners\"), add = TRUE, col = 'green', pch=3)\n#' sfc = st_sfc(st_polygon(list(rbind(c(0,0), c(1,0), c(1,1), c(0,0)))))\n#' plot(st_make_grid(sfc, cellsize = .1, square = FALSE))\n#' plot(sfc, add = TRUE)\n#' # non-default offset:\n#' plot(st_make_grid(sfc, cellsize = .1, square = FALSE, offset = c(0, .05 / (sqrt(3)/2))))\n#' plot(sfc, add = TRUE)\n#' nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\n#' g = st_make_grid(nc)\n#' plot(g)\n#' plot(st_geometry(nc), add = TRUE)\n#' # g[nc] selects cells that intersect with nc:\n#' plot(g[nc], col = '#ff000088', add = TRUE)\n#' @export\nst_make_grid = function(x,\n\t\tcellsize = c(diff(st_bbox(x)[c(1,3)]), diff(st_bbox(x)[c(2,4)]))/n,\n\t\toffset = st_bbox(x)[c(\"xmin\", \"ymin\")], n = c(10, 10),\n\t\tcrs = if (missing(x)) NA_crs_ else st_crs(x),\n\t\twhat = \"polygons\", square = TRUE, flat_topped = FALSE) {\n\n\tif (!inherits(crs, \"crs\"))\n\t\tcrs = st_crs(crs) # #2057\n\tif (missing(x) && missing(cellsize) && missing(offset)\n\t\t\t&& missing(n) && missing(crs)) # create global 10 x 10 degree grid\n\t\treturn(st_make_grid(cellsize = c(10,10), offset = c(-180,-90), n = c(36,18),\n\t\t\tcrs = st_crs(4326), what = what))\n\n\tif (! square) { # hexagons:\n\t\tif (!is.null(crs$ud_unit)) {\n\t\t\tif (inherits(cellsize, \"units\")) {\n\t\t\t\tif (units::ud_are_convertible(units(cellsize), \"m^2\")) { # size in area\n\t\t\t\t\t# convert: https://github.com/r-spatial/sf/issues/1505\n\t\t\t\t\ta = sqrt(cellsize * 2 / (3 * sqrt(3)))\n\t\t\t\t\tcellsize = a * sqrt(3)\n\t\t\t\t}\n\t\t\t\tunits(cellsize) = units(crs$ud_unit)\n\t\t\t\tcellsize = units::drop_units(cellsize)\n\t\t\t}\n\t\t\tif (inherits(offset, \"units\")) {\n\t\t\t\tunits(offset) = units(crs$ud_unit)\n\t\t\t\toffset = units::drop_units(offset)\n\t\t\t}\n\t\t}\n\t\thex = make_hex_grid(x, dx = cellsize[1]/sqrt(3), pt = offset, what = what, \n\t\t\tflat_topped = flat_topped)\n\t\tif (what == \"corners\")\n\t\t\thex = st_cast(hex, \"POINT\")[x]\n\t\treturn(hex)\n\t}\n\n\tbb = if (!missing(n) && !missing(offset) && !missing(cellsize)) {\n\t\tcellsize = rep(cellsize, length.out = 2)\n\t\tn = rep(n, length.out = 2)\n\t\tbb_wrap(c(offset, offset + n * cellsize))\n\t} else\n\t\tst_bbox(x)\n\n\tcellsize_missing = if (! missing(cellsize)) {\n\t\tcellsize = rep(cellsize, length.out = 2)\n\t\tFALSE\n\t} else\n\t\tTRUE\n\n\tif (!is.null(crs$ud_unit)) {\n\t\tif (inherits(cellsize, \"units\")) {\n\t\t\tif (units::ud_are_convertible(units(cellsize), \"m^2\")) # size in area\n\t\t\t\tcellsize = sqrt(cellsize)\n\t\t\tunits(cellsize) = units(crs$ud_unit)\n\t\t\tcellsize = units::drop_units(cellsize)\n\t\t}\n\t\tif (inherits(offset, \"units\")) {\n\t\t\tunits(offset) = units(crs$ud_unit)\n\t\t\toffset = units::drop_units(offset)\n\t\t}\n\t}\n\n\tif (missing(n)) {\n\t\tnx = ceiling((bb[3] - offset[1])/cellsize[1])\n\t\tny = ceiling((bb[4] - offset[2])/cellsize[2])\n\t} else {\n\t\tn = rep(n, length.out = 2)\n\t\tnx = n[1]\n\t\tny = n[2]\n\t}\n\n\t# corner points:\n\tif (cellsize_missing) {\n\t\txc = seq(offset[1], bb[3], length.out = nx + 1)\n\t\tyc = seq(offset[2], bb[4], length.out = ny + 1)\n\t} else {\n\t\txc = offset[1] + (0:nx) * cellsize[1]\n\t\tyc = offset[2] + (0:ny) * cellsize[2]\n\t}\n\n\tif (what == \"polygons\") {\n\t\tret = vector(\"list\", nx * ny)\n\t\tsquare = function(x1, y1, x2, y2)\n\t\t\tst_polygon(list(matrix(c(x1, x2, x2, x1, x1, y1, y1, y2, y2, y1), 5)))\n\t\tfor (i in 1:nx)\n\t\t\tfor (j in 1:ny)\n\t\t\t\tret[[(j - 1) * nx + i]] = square(xc[i], yc[j], xc[i+1], yc[j+1])\n\t\tst_sfc(ret, crs = crs)\n\t} else if (what == \"centers\") {\n\t\te = expand.grid(x = xc[-1] - 0.5 * diff(xc[1:2]), \n\t\t\t\t\t\ty = yc[-1] - 0.5 * diff(yc[1:2]), \n\t\t\t\t\t\tKEEP.OUT.ATTRS = FALSE)\n\t\tst_geometry(st_as_sf(e, coords = c(\"x\", \"y\"), crs = crs))\n\t} else if (what == \"corners\") {\n\t\te = expand.grid(x = xc, y = yc, KEEP.OUT.ATTRS = FALSE)\n\t\tst_geometry(st_as_sf(e, coords = c(\"x\", \"y\"), crs = crs))\n\t} else\n\t\tstop(\"unknown value of `what'\")\n}\n\n### hex grid tesselation that\n## - covers a bounding box st_bbox(obj)\n## - contains pt\n## - has x spacing dx: the shortest distance between x coordinates with identical y coordinate\nmake_hex_grid = function(obj, pt, dx, what, flat_topped = TRUE) {\n\n\tdy = sqrt(3) * dx / 2\n\tbb = st_bbox(obj)\n\tif (!flat_topped) { # pointy topped -- swap x and y:\n\t\tylim = bb[c(\"xmin\", \"xmax\")]\n\t\txlim = bb[c(\"ymin\", \"ymax\")]\n\t\tpt = pt[2:1]\n\t} else {\n\t\txlim = bb[c(\"xmin\", \"xmax\")]\n\t\tylim = bb[c(\"ymin\", \"ymax\")]\n\t}\n\toffset = c(x = (pt[1] - xlim[1]) %% dx, y = (pt[2] - ylim[1]) %% (2 * dy))\n\tx0 = seq(xlim[1] - dx, xlim[2] + 2 * dx, dx) + offset[1]\n\ty0 = seq(ylim[1] - 2 * dy, ylim[2] + 2 * dy, dy) + offset[2]\n\n\ty  <- rep(y0, each = length(x0))\n\tx  <- rep(c(x0, x0 + dx / 2), length.out = length(y))\n\txy = cbind(x, y) # the coordinates\n\n\t# compute the indexes, using double coordinates:\n\todd  <- seq(1, by = 2, length.out = length(x0))\n\teven <- seq(2, by = 2, length.out = length(x0))\n\txi <- rep(c(odd, even), length.out = length(y))\n\tyi <- rep(seq_along(y0), each = length(x0))\n\t# hexagon centers are columns with x index 3, 6, 9, ... :\n\tcenters = cbind(xi,yi)[xi %in% seq(3, max(xi) - 2, by = 3) & yi > 1 & yi < max(yi),]\n\n\t# relative offset in double coordinates, https://www.redblobgames.com/grids/hexagons/\n\tnx = length(x0)\n\txy_pattern = rbind(c(-2,0), c(-1,-1), c(1,-1), c(2,0), c(1,1), c(-1,1), c(-2,0))\n\ti_from_x = function(x) ((x[,1] - 1) %/% 2 + 1) + (x[,2] - 1) * nx\n\n\tmk_point = if (flat_topped)\n\t\t\tfunction(center) st_point(xy[i_from_x(matrix(center, ncol = 2)),])\n\t\telse\n\t\t\tfunction(center) st_point(xy[i_from_x(matrix(center, ncol = 2)),2:1])\n\n\tmk_pol = if (flat_topped)\n\t\t\tfunction(center) {\n\t\t\t\tm = matrix(center, ncol=2, nrow = 7, byrow=TRUE) + xy_pattern\n\t\t\t\tst_polygon(list(xy[i_from_x(m),]))\n\t\t\t}\n\t\telse\n\t\t\tfunction(center) {\n\t\t\t\tm = matrix(center, ncol=2, nrow = 7, byrow=TRUE) + xy_pattern\n\t\t\t\tst_polygon(list(xy[i_from_x(m),2:1]))\n\t\t\t}\n\n\tif (what == \"centers\")\n\t\tst_sfc(lapply(seq_len(nrow(centers)), function(i) mk_point(centers[i,])), crs = st_crs(bb))\n\telse # points:\n\t\tst_sfc(lapply(seq_len(nrow(centers)), function(i) mk_pol(centers[i,])), crs = st_crs(bb))\n}\n"
  },
  {
    "path": "R/maps.R",
    "content": "NAmat2xyList <- function(xy) {\n\tNAs <- unclass(attr(na.omit(xy), \"na.action\"))\n\tif ((length(NAs) == 1L) && (NAs == nrow(xy))) {\n\t\txy <- xy[-nrow(xy)] # nocov\n\t\tNAs <- NULL # nocov\n\t}\n# NA problem found by Edzer Pebesma, 24/8-06\n\tdiffNAs <- diff(NAs)\n\tif (any(diffNAs == 1)) {\n\t\txy <- xy[-(NAs[which(diffNAs == 1)] + 1), ] # nocov\n\t\tNAs <- unclass(attr(na.omit(xy), \"na.action\")) # nocov\n\t}\n\tnParts <- length(NAs) + 1L\n# two NAs at end of file 070905 RSB\n# no NAs at all RSB 080814\n\tif (!is.null(NAs) && nrow(xy) == NAs[length(NAs)])\n            nParts <- nParts - 1\n\tres <- vector(mode=\"list\", length=nParts)\n\tfrom <- integer(nParts)\n\tto <- integer(nParts)\n\tfrom[1] <- 1\n\tto[nParts] <- nrow(xy)\n# two NAs at end of file 070905 RSB\n# no NAs at all RSB 080814\n\tif (!is.null(NAs) && nrow(xy) == NAs[length(NAs)])\n\t\tto[nParts] <- to[nParts] - 1\n\tif (nParts > 1) {\n\t\tfor (i in 2:nParts) {\n\t\t\tto[(i-1)] <- NAs[(i-1)]-1\n\t\t\tfrom[i] <- NAs[(i-1)]+1\n\t\t}\n\t}\n\tfor (i in seq_len(nParts))\n\t\tres[[i]] <- xy[from[i]:to[i],, drop = FALSE]\n\tres\n}\n\nmap2pol = function(xyList, ID) {\n\t# close rings:\n\txyList = lapply(xyList, ClosePol)\n\t# group into MULTIPOLYGON:\n\tuID = unique(ID)\n\tret = vector(\"list\", length(uID))\n\tfor (g in seq_along(uID))\n\t\tret[[g]] = st_multipolygon(lapply(xyList[ uID[g] == ID ], function(x) list(x)))\n\tst_sfc(ret)\n}\n\nmap2lin = function(xyList, ID) {\n\t# group into MULTILINESTRING:\n\tuID = unique(ID)\n\tret = vector(\"list\", length(uID))\n\tfor (g in seq_along(uID)) {\n               x = xyList[uID[g] == ID]\n               x = x[!sapply(x, is.null)]\n               ret[[g]] = st_multilinestring(x)\n        }\n#\t\tret[[g]] = st_multilinestring(xyList[ uID[g] == ID ])\n\tst_sfc(ret)\n}\n\n\n#' @export\n#' @name st_as_sf\n#' @param fill logical; the value for \\code{fill} that was used in the call to \\link[maps]{map}.\n#' @param group logical; if \\code{TRUE}, group id labels from \\link[maps]{map} by their prefix before \\code{:}\nst_as_sf.map = function(x, ..., fill = TRUE, group = TRUE) {\n\tID = if (group)\n\t\t\tvapply(strsplit(x$names, \":\"), function(y) y[1], \"\")\n\t\telse \n\t\t\tx$names\n\txyList <- NAmat2xyList(cbind(x$x, x$y))\n\tgeom = if (fill)\n\t\t\tmap2pol(xyList, ID)\n\t\telse\n\t\t\tmap2lin(xyList, ID)\n\tID = unique(ID)\n\tstopifnot(length(ID) == length(geom))\n\tst_sf(ID = ID, geom = geom, crs = \"+proj=longlat +ellps=clrk66 +no_defs +type=crs\", row.names = ID)\n}\n\n\n#' @export\n#' @name st_as_sfc\nst_as_sfc.map = function(x, ...) {\n\tst_geometry(st_as_sf(x, ...))\n}\n"
  },
  {
    "path": "R/nearest.R",
    "content": "#' get nearest points between pairs of geometries\n#' \n#' get nearest points between pairs of geometries\n#' @param x object of class \\code{sfg}, \\code{sfc} or \\code{sf}\n#' @param y object of class \\code{sfg}, \\code{sfc} or \\code{sf}; needs to have the same number of geometries of `x` when `by_element=TRUE`\n#' @param by_element logical; if \\code{FALSE} (default) return nearest points between all possible pairs, if \\code{TRUE}, return nearest points between row-wise x-y pairs.\n#' @param pairwise logical; deprecated in favour of `by_element`\n#' @param ... ignored\n#' @seealso \\link{st_nearest_feature} for finding the nearest feature\n#' @return an \\link{sfc} object with all two-point \\code{LINESTRING} geometries of point pairs from the first to the second geometry, of length x * y if `by_element=FALSE` (with y cycling fastest), or lf length `length(x)` when `by_element=TRUE`. See examples for ideas how to convert these to \\code{POINT} geometries.\n#' @details in case \\code{x} lies inside \\code{y}, when using S2, the end points \n#' are on polygon boundaries, when using GEOS the end point are identical to \\code{x}.\n#' @examples\n#' r = sqrt(2)/10\n#' pt1 = st_point(c(.1,.1))\n#' pt2 = st_point(c(.9,.9))\n#' pt3 = st_point(c(.9,.1))\n#' b1 = st_buffer(pt1, r)\n#' b2 = st_buffer(pt2, r)\n#' b3 = st_buffer(pt3, r)\n#' (ls0 = st_nearest_points(b1, b2)) # sfg\n#' (ls = st_nearest_points(st_sfc(b1), st_sfc(b2, b3))) # sfc\n#' plot(b1, xlim = c(-.2,1.2), ylim = c(-.2,1.2), col = NA, border = 'green')\n#' plot(st_sfc(b2, b3), add = TRUE, col = NA, border = 'blue')\n#' plot(ls, add = TRUE, col = 'red')\n#' \n#' nc = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"))\n#' plot(st_geometry(nc))\n#' ls = st_nearest_points(nc[1,], nc)\n#' plot(ls, col = 'red', add = TRUE)\n#' pts = st_cast(ls, \"POINT\") # gives all start & end points\n#' # starting, \"from\" points, corresponding to x:\n#' plot(pts[seq(1, 200, 2)], add = TRUE, col = 'blue')\n#' # ending, \"to\" points, corresponding to y:\n#' plot(pts[seq(2, 200, 2)], add = TRUE, col = 'green')\n#' \n#' @export\nst_nearest_points = function(x, y, ..., by_element = FALSE) UseMethod(\"st_nearest_points\")\n\n#' @export\n#' @name st_nearest_points\nst_nearest_points.sfc = function(x, y, ..., pairwise = by_element, by_element = FALSE) {\n\tstopifnot(st_crs(x) == st_crs(y))\n\tlonglat = isTRUE(st_is_longlat(x))\n\tif (longlat && sf_use_s2()) {\n\t\tret = if (pairwise)\n\t\t\t\ts2::s2_minimum_clearance_line_between(x, y)\n\t\t\telse\n\t\t\t\tdo.call(c, lapply(x, s2::s2_minimum_clearance_line_between, y))\n\t\tst_as_sfc(ret, crs = st_crs(x))\n\t} else {\n\t\tif (longlat)\n\t\t\tmessage_longlat(\"st_nearest_points\")\n\t\tst_sfc(CPL_geos_nearest_points(x, st_geometry(y), pairwise), crs = st_crs(x))\n\t}\n}\n \n#' @export\n#' @name st_nearest_points\nst_nearest_points.sfg = function(x, y, ...) {\n\tst_nearest_points(st_geometry(x), st_geometry(y), ...)\n}\n\n#' @export\n#' @name st_nearest_points\nst_nearest_points.sf = function(x, y, ...) {\n\tst_nearest_points(st_geometry(x), st_geometry(y), ...)\n}\n\n#' get index of nearest feature\n#' \n#' get index of nearest feature\n#' @param x object of class \\code{sfg}, \\code{sfc} or \\code{sf}\n#' @param y object of class \\code{sfg}, \\code{sfc} or \\code{sf}; if missing, features in \\code{x} will be compared to all remaining features in \\code{x}.\n#' @param ... ignored\n#' @param check_crs logical; should \\code{x} and \\code{y} be checked for CRS equality?\n#' @param longlat logical; does \\code{x} have ellipsoidal coordinates?\n#' @return for each feature (geometry) in \\code{x} the index of the nearest feature (geometry) in \n#' set \\code{y}, or in the remaining set of \\code{x} if \\code{y} is missing;\n#' empty geometries result in \\code{NA} indexes\n#' @seealso \\link{st_nearest_points} for finding the nearest points for pairs of feature geometries\n#' @export\n#' @examples\n#' ls1 = st_linestring(rbind(c(0,0), c(1,0)))\n#' ls2 = st_linestring(rbind(c(0,0.1), c(1,0.1)))\n#' ls3 = st_linestring(rbind(c(0,1), c(1,1)))\n#' (l = st_sfc(ls1, ls2, ls3))\n#' \n#' p1 = st_point(c(0.1, -0.1))\n#' p2 = st_point(c(0.1, 0.11))\n#' p3 = st_point(c(0.1, 0.09))\n#' p4 = st_point(c(0.1, 0.9))\n#' \n#' (p = st_sfc(p1, p2, p3, p4))\n#' try(st_nearest_feature(p, l))\n#' try(st_nearest_points(p, l[st_nearest_feature(p,l)], pairwise = TRUE))\n#' \n#' r = sqrt(2)/10\n#' b1 = st_buffer(st_point(c(.1,.1)), r)\n#' b2 = st_buffer(st_point(c(.9,.9)), r)\n#' b3 = st_buffer(st_point(c(.9,.1)), r)\n#' circles = st_sfc(b1, b2, b3)\n#' plot(circles, col = NA, border = 2:4)\n#' pts = st_sfc(st_point(c(.3,.1)), st_point(c(.6,.2)), st_point(c(.6,.6)), st_point(c(.4,.8)))\n#' plot(pts, add = TRUE, col = 1)\n#' # draw points to nearest circle:\n#' nearest = try(st_nearest_feature(pts, circles))\n#' if (inherits(nearest, \"try-error\")) # GEOS 3.6.1 not available\n#'   nearest = c(1, 3, 2, 2)\n#' ls = st_nearest_points(pts, circles[nearest], pairwise = TRUE)\n#' plot(ls, col = 5:8, add = TRUE)\n#' # compute distance between pairs of nearest features:\n#' st_distance(pts, circles[nearest], by_element = TRUE)\nst_nearest_feature = function(x, y, ..., check_crs = TRUE, longlat = isTRUE(st_is_longlat(x))) {\n\n\tif (missing(y)) { # https://github.com/r-spatial/s2/issues/111#issuecomment-835306261\n\t\tlonglat = force(longlat) # evaluate only once\n\t\tx = st_geometry(x)\n\t\tind <- vapply(\n\t\t\tseq_along(x),\n\t\t\tfunction(i) st_nearest_feature(x[i], x[-i], check_crs = FALSE, longlat = longlat),\n\t\t\tinteger(1)\n\t\t)\n\t\tifelse(ind >= seq_along(x), ind + 1, ind)\n\t} else {\n\t\tif (check_crs)\n\t\t\tstopifnot(st_crs(x) == st_crs(y))\n\t\tif (longlat && sf_use_s2())\n\t\t\ts2::s2_closest_feature(x, y)\n\t\telse {\n\t\t\tif (longlat)\n\t\t\t\tmessage_longlat(\"st_nearest_feature\")\n\t\t\tCPL_geos_nearest_feature(st_geometry(x), st_geometry(y))\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "R/normalize.R",
    "content": "#' Normalize simple features\n#'\n#' \\code{st_normalize} transforms the coordinates in the input feature to fall\n#' between 0 and 1. By default the current domain is set to the bounding box of\n#' the input, but other domains can be used as well\n#'\n#' @param x object of class sf, sfc or sfg\n#' @param domain The domain \\code{x} should be normalized from as a length 4\n#' vector of the form \\code{c(xmin, ymin, xmax, ymax)}. Defaults to the\n#' bounding box of \\code{x}\n#' @param ... ignored\n#'\n#' @export\n#'\n#' @examples\n#' p1 = st_point(c(7,52))\n#' st_normalize(p1, domain = c(0, 0, 10, 100))\n#'\n#' p2 = st_point(c(-30,20))\n#' sfc = st_sfc(p1, p2, crs = 4326)\n#' sfc\n#' sfc_norm <- st_normalize(sfc)\n#' st_bbox(sfc_norm)\n#'\nst_normalize <- function(x, domain = st_bbox(x), ...) {\n\tUseMethod(\"st_normalize\")\n}\n\n#' @export\nst_normalize.sfg <- function(x, domain = st_bbox(x), ...) {\n\t(x - domain[c(1, 2)]) / diag(c(domain[3] - domain[1], domain[4] - domain[2]))\n}\n\n#' @export\nst_normalize.sfc <- function(x, domain = st_bbox(x), ...) {\n\tdomain <- as.numeric(domain)\n\tif (length(x) == 0) return(x)\n\tmin <- -domain[c(1, 2)]\n\trange <- 1 / c(domain[3] - domain[1], domain[4] - domain[2])\n\tif (any(is.infinite(range)) || any(range < 0)) {\n\t\tstop(\"domain must have a positive range\") # nocov\n\t}\n\tnormalize_sfc(x, min, range, NA_crs_)\n}\n\n#' @export\nst_normalize.sf <- function(x, domain = st_bbox(x), ...) {\n\tx[[ attr(x, \"sf_column\") ]] = st_normalize(st_geometry(x), domain, ...)\n\tx\n}\n"
  },
  {
    "path": "R/plot.R",
    "content": "kw_dflt = function(x, key.pos) {\n\tif (is.null(key.pos) || key.pos[1] == 0) # no key:\n\t\treturn(lcm(0))\n\n\tfont_scale = par(\"ps\") / 12\n\tif (key.pos[1] == -1)\n\t\tlcm(1.8 * font_scale)\n\telse if (key.pos[1] %in% c(2, 4) && (is.character(x[[1]]) || is.factor(x[[1]]))) {\n\t\tstrings = if (is.factor(x[[1]]))\n\t\t\t\tlevels(x[[1]])\n\t\t\telse\n\t\t\t\tx[[1]]\n\t\tlcm(cm(max(strwidth(strings, \"inches\"))) * 1.3 + font_scale) # cm\n\t\t#lcm(cm(max(strwidth(strings, \"inches\"))) * 1.3) # cm\n\t} else\n\t\tlcm(1.8 * font_scale)\n}\n\n# like cut.default, but only return integers, and allow for duplicate breaks:\nsf_cut = function(values, breaks, include.lowest = TRUE) {\n\ti = findInterval(values, breaks, left.open = TRUE)\n\tif (include.lowest)\n\t\ti[values == breaks[1]] = 1\n\ti[i == 0 | i == length(breaks)] = NA\n\ti\n}\n\n#' plot sf object\n#'\n#' plot one or more attributes of an sf object on a map\n#' Plot sf object\n#'\n#' @param x object of class sf\n#' @param y ignored\n#' @param ... further specifications, see \\link{plot_sf} and \\link{plot} and details.\n#' @param main title for plot (\\code{NULL} to remove)\n#' @param pal palette function, similar to \\link{rainbow}, or palette values; if omitted, \\code{sf.colors} is used\n#' @param nbreaks number of colors breaks (ignored for \\code{factor} or \\code{character} variables)\n#' @param breaks either a numeric vector with the actual breaks, or a name of a method accepted by the \\code{style} argument of \\link[classInt]{classIntervals}\n#' @param max.plot integer; lower boundary to maximum number of attributes to plot; the default value (9) can be overridden by setting the global option \\code{sf_max.plot}, e.g. \\code{options(sf_max.plot=2)}\n#' @param key.pos numeric; side to plot a color key: 1 bottom, 2 left, 3 top, 4 right; set to \\code{NULL} to omit key completely, 0 to only not plot the key, or -1 to select automatically. If multiple columns are plotted in a single function call by default no key is plotted and every submap is stretched individually; if a key is requested (and \\code{col} is missing) all maps are colored according to a single key. Auto select depends on plot size, map aspect, and, if set, parameter \\code{asp}. If it has lenght 2, the second value, ranging from 0 to 1, determines where the key is placed in the available space (default: 0.5, center).\n#' @param key.width amount of space reserved for the key (incl. labels), thickness/width of the scale bar\n#' @param key.length amount of space reserved for the key along its axis, length of the scale bar\n#' @param pch plotting symbol\n#' @param cex symbol size\n#' @param bg symbol background color\n#' @param lty line type\n#' @param lwd line width\n#' @param col color for plotting features; if \\code{length(col)} does not equal 1 or \\code{nrow(x)}, a warning is emitted that colors will be recycled. Specifying \\code{col} suppresses plotting the legend key.\n#' @param border color of polygon border(s); using \\code{NA} hides them\n#' @param add logical; add to current plot? Note that when using \\code{add=TRUE}, you may have to set \\code{reset=FALSE} in the first plot command.\n#' @param type plot type: 'p' for points, 'l' for lines, 'b' for both\n#' @param reset logical; if \\code{FALSE}, keep the plot in a mode that allows adding further map elements; if \\code{TRUE} restore original mode after plotting \\code{sf} objects with attributes; see details.\n#' @param logz logical; if \\code{TRUE}, use log10-scale for the attribute variable. In that case, \\code{breaks} and \\code{at} need to be given as log10-values; see examples.\n#' @param extent object with an \\code{st_bbox} method to define plot extent; defaults to \\code{x}\n#' @param xlim numeric; x-axis limits; overrides \\code{extent}\n#' @param ylim numeric; y-axis limits; overrides \\code{extent}\n#' @param compact logical; compact sub-plots over plotting space?\n#' @method plot sf\n#' @name plot\n#' @details \\code{plot.sf} maximally plots \\code{max.plot} maps with colors following from attribute columns,\n#' one map per attribute. It uses \\code{sf.colors} for default colors. For more control over placement of individual maps,\n#' set parameter \\code{mfrow} with \\link{par} prior to plotting, and plot single maps one by one; note that this only works\n#' in combination with setting parameters \\code{key.pos=NULL} (no legend) and \\code{reset=FALSE}.\n#'\n#' \\code{plot.sfc} plots the geometry, additional parameters can be passed on\n#' to control color, lines or symbols.\n#'\n#' When setting \\code{reset} to \\code{FALSE}, the original device parameters are lost, and the device must be reset using \\code{dev.off()} in order to reset it.\n#'\n#' parameter \\code{at} can be set to specify where labels are placed along the key; see examples.\n#'\n#' parameter \\code{mar} can be set in \\code{...} to override default margins.\n#' \n#' The features are plotted in the order as they apppear in the sf object. See examples for when a different plotting order is wanted.\n#'\n#' @examples\n#' nc = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), quiet = TRUE)\n#' # plot single attribute, auto-legend:\n#' plot(nc[\"SID74\"])\n#' # plot multiple:\n#' plot(nc[c(\"SID74\", \"SID79\")]) # better use ggplot2::geom_sf to facet and get a single legend!\n#' # adding to a plot of an sf object only works when using reset=FALSE in the first plot:\n#' plot(nc[\"SID74\"], reset = FALSE)\n#' plot(st_centroid(st_geometry(nc)), add = TRUE)\n#' # log10 z-scale:\n#' plot(nc[\"SID74\"], logz = TRUE, breaks = c(0,.5,1,1.5,2), at = c(0,.5,1,1.5,2))\n#' # and we need to reset the plotting device after that, e.g. by\n#' layout(1)\n#' # when plotting only geometries, the reset=FALSE is not needed:\n#' plot(st_geometry(nc))\n#' plot(st_geometry(nc)[1], col = 'red', add = TRUE)\n#' # add a custom legend to an arbitray plot:\n#' layout(matrix(1:2, ncol = 2), widths = c(1, lcm(2)))\n#' plot(1)\n#' .image_scale(1:10, col = sf.colors(9), key.length = lcm(8), key.pos = 4, at = 1:10)\n#' # manipulate plotting order, plot largest polygons first:\n#' p = st_polygon(list(rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0))))\n#' x = st_sf(a=1:4, st_sfc(p, p * 2, p * 3, p * 4)) # plot(x, col=2:5) only shows the largest polygon!\n#' plot(x[order(st_area(x), decreasing = TRUE),], col = 2:5) # plot largest polygons first\n#' \n#' @export\nplot.sf <- function(x, y, ..., main, pal = NULL, nbreaks = 10, breaks = \"pretty\",\n\t\tmax.plot = getOption(\"sf_max.plot\", default = 9),\n\t\tkey.pos = get_key_pos(x, ...), key.length = .618, key.width = kw_dflt(x, key.pos),\n\t\treset = TRUE, logz = FALSE, extent = x, xlim = st_bbox(extent)[c(1,3)],\n\t\tylim = st_bbox(extent)[c(2,4)], compact = FALSE) {\n\n\tstopifnot(missing(y))\n\tnbreaks.missing = missing(nbreaks)\n\tkey.pos.missing = missing(key.pos)\n\tmax_plot_missing = missing(max.plot)\n\tdots = list(...)\n\tcol_missing = is.null(dots$col)\n\tbreaks_numeric = is.numeric(breaks)\n\treset_layout_needed = reset\n\n\tx = swap_axes_if_needed(x)\n\t\n\t# The following code defines an expression which resets the plotting layout.\n\t# The on.exit approach is needed since the plotting routing may fail for\n\t# various reasons leaving the plot layout in a broken state. The on.exit\n\t# ensures that we \"clean\" such broken state regardless of the failure/success\n\t# of the plotting routing. See also #2519 for more details.\n\ton.exit(\n\t\texpr = {\n\t\t\tif (!isTRUE(dots$add) && reset) { # reset device: \n\t\t\t\tif (reset_layout_needed) \n\t\t\t\t\tlayout(matrix(1))\n\t\t\t\tpar(opar)\n\t\t\t}\n\t\t}, \n\t\tadd = TRUE\n\t)\n\t\n\topar = par(no.readonly = TRUE)\n\tif (ncol(x) > 2 && !isTRUE(dots$add)) { # multiple maps to plot...\n\t\tcols = setdiff(names(x), attr(x, \"sf_column\"))\n\t\tlt = .get_layout(st_bbox(x), min(max.plot, length(cols)), par(\"din\"), key.pos[1], key.width)\n\t\tif (key.pos.missing || key.pos[1] == -1)\n\t\t\tkey.pos = lt$key.pos\n\t\tlayout(lt$m, widths = lt$widths, heights = lt$heights, respect = compact)\n\n\t\tmar = if (is.null(dots$mar)) {\n\t\t\t\tif (isTRUE(dots$axes))\n\t\t\t\t\tc(2.1, 2.1, 1.2, 0)\n\t\t\t\telse\n\t\t\t\t\tc(0, 0, 1.2, 0)\n\t\t\t} else\n\t\t\t\tdots$mar\n\t\tpar(mar = mar)\n\n\t\tif (max_plot_missing)\n\t\t\tmax.plot = prod(lt$mfrow)\n\n\t\tif (isTRUE(is.finite(max.plot)) && ncol(x) - 1 > max.plot &&\n\t\t\t\tmax_plot_missing && is.null(options(\"sf_max.plot\")[[1]]))\n\t\t\twarning(paste(\"plotting the first\", max.plot, \"out of\", ncol(x)-1,\n\t\t\t\t\"attributes; use max.plot =\", ncol(x) - 1, \"to plot all\"), call. = FALSE)\n\n\t\t# col selection may have changed; set cols again:\n\t\tcols = setdiff(names(x), attr(x, \"sf_column\"))\n\t\tif (length(cols) > max.plot)\n\t\t\tcols = cols[1:max.plot]\n\n\t\tif (!is.null(key.pos)) {\n\t\t\tvalues = do.call(c, as.data.frame(x)[cols])\n\t\t\tif (is.character(values))\n\t\t\t\tvalues = as.factor(values)\n\t\t\tif (logz)\n\t\t\t\tvalues = log10(values)\n\t\t\tif (is.character(breaks) && is.numeric(values)) { # compute breaks from values:\n\t\t\t\tv0 = values[!is.na(values)]\n\t\t\t\tn.unq = length(unique(v0))\n\t\t\t\tbreaks = if (! all(is.na(values)) && n.unq > 1)\n\t\t\t\t\t\tclassInt::classIntervals(v0, min(nbreaks, n.unq),\n\t\t\t\t\t\t\tbreaks, warnSmallN = FALSE)$brks\n\t\t\t\t\telse\n\t\t\t\t\t\trange(values, na.rm = TRUE) # lowest and highest!\n\t\t\t\tnbreaks = length(breaks) - 1\n\t\t\t}\n\t\t}\n\t\tif (nbreaks.missing && is.numeric(breaks))\n\t\t\tnbreaks = length(breaks) - 1\n\n\t\t# loop over each map to plot:\n\t\tlapply(cols, function(cname) plot(x[, cname], main = cname,\n\t\t\tpal = pal, nbreaks = nbreaks, breaks = breaks, key.pos = NULL, reset = FALSE,\n\t\t\tlogz = logz, xlim = xlim, ylim = ylim,...))\n\n\t\tfor (i in seq_len(prod(lt$mfrow) - length(cols))) # empty panels:\n\t\t\tplot.new()\n\n\t\t# plot key?\n\t\tif (!is.null(key.pos) && key.pos[1] != 0 && col_missing) {\n\t\t\tif (is.null(pal))\n\t\t\t\tpal = function(n) sf.colors(n, categorical = is.factor(values))\n\t\t\tcolors = if (is.function(pal))\n\t\t\t\t\tpal(nbreaks)\n\t\t\t\telse\n\t\t\t\t\tpal\n\t\t\tif (is.factor(values))\n\t\t\t\t.image_scale_factor(levels(values), colors, key.pos = key.pos,\n\t\t\t\t\tkey.width = key.width, key.length = key.length, ...)\n\t\t\telse\n\t\t\t\t.image_scale(values, colors, breaks = breaks, key.pos = key.pos,\n\t\t\t\t\tkey.length = key.length, logz = logz, ...)\n\t\t}\n\n\t} else { # single map, or dots$add == TRUE:\n\t\tif (ncol(x) == 1) { # no attributes to choose colors from: plot geometry\n\t\t\tplot(st_geometry(x), xlim = xlim, ylim = ylim, ...)\n\t\t\treset_layout_needed = FALSE\n\t\t} else { # generate plot with colors and possibly key\n\t\t\tif (ncol(x) > 2) { # add = TRUE\n\t\t\t\twarning(\"ignoring all but the first attribute\")\n\t\t\t\tx = x[,1]\n\t\t\t}\n\t\t\t# store attribute in \"values\":\n\t\t\tvalues = x[[setdiff(names(x), attr(x, \"sf_column\"))]]\n\n\t\t\tif (is.list(values)) {\n\t\t\t\treset_layout_needed = TRUE # nocov\n\t\t\t\tstop(\"plotting list-columns not supported\") # nocov\n\t\t\t}\n\n\t\t\tif (is.character(values))\n\t\t\t\tvalues = as.factor(values)\n\t\t\telse if (logz)\n\t\t\t\tvalues = log10(as.numeric(values))\n\n\t\t\tif (is.null(pal))\n\t\t\t\tpal = function(n) sf.colors(n, categorical = is.factor(values))\n\t\t\telse if (! col_missing) {\n\t\t\t\treset_layout_needed = TRUE\n\t\t\t\tstop(\"specify only one of `col' and `pal'\")\n\t\t\t}\n\t\t\t\t\n\n\t\t\tif (col_missing) { # compute colors from values:\n\t\t\t\tcol = if (is.factor(values)) {\n\t\t\t\t\t\tif (key.pos.missing && nlevels(values) > 30) # doesn't make sense:\n\t\t\t\t\t\t\tkey.pos = NULL\n\t\t\t\t\t\tcolors = if (is.function(pal))\n\t\t\t\t\t\t\t\tpal(nlevels(values))\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tpal\n\t\t\t\t\t\tcolors[as.numeric(values)]\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif (! inherits(values, c(\"POSIXt\", \"Date\")))\n\t\t\t\t\t\t\tvalues = as.numeric(values) # drop units, if any\n\t\t\t\t\t\tif (is.character(breaks)) { # compute breaks from values:\n\t\t\t\t\t\t\tv0 = values[!is.na(values)]\n\t\t\t\t\t\t\tn.unq = length(unique(v0))\n\t\t\t\t\t\t\tbreaks = if (! all(is.na(values)) && n.unq > 1)\n\t\t\t\t\t\t\t\t\tclassInt::classIntervals(v0, min(nbreaks, n.unq),\n\t\t\t\t\t\t\t\t\t\tbreaks, warnSmallN = FALSE)$brks\n\t\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\t\trange(values, na.rm = TRUE) # lowest and highest!\n\t\t\t\t\t\t}\n\t\t\t\t\t\t# this is necessary if breaks were specified either as character or as numeric\n\t\t\t\t\t\t# \"pretty\" takes nbreaks as advice only:\n\t\t\t\t\t\tnbreaks = length(breaks) - 1\n\n\t\t\t\t\t\tcuts = if (all(is.na(values)))\n\t\t\t\t\t\t\t\trep(NA_integer_, length(values))\n\t\t\t\t\t\t\telse if (!breaks_numeric && diff(range(values, na.rm = TRUE)) == 0)\n\t\t\t\t\t\t\t\tifelse(is.na(values), NA_integer_, 1L)\n\t\t\t\t\t\t\telse if (inherits(values, c(\"POSIXt\", \"Date\")))\n\t\t\t\t\t\t\t\tcut(values, breaks, include.lowest = TRUE)\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tsf_cut(values, breaks, include.lowest = TRUE)\n\t\t\t\t\t\tcolors = if (is.function(pal))\n\t\t\t\t\t\t\t\tpal(nbreaks)\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tpal\n\t\t\t\t\t\tcolors[cuts]\n\t\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tcol = dots$col\n\t\t\t\tif (length(col) != 1 && length(col) != nrow(x))\n\t\t\t\t\twarning(\"col is not of length 1 or nrow(x): colors will be recycled; use pal to specify a color palette\")\n\t\t\t\tkey.pos = NULL # no key!\n\t\t\t}\n\n\t\t\tif (!isTRUE(dots$add) && !is.null(key.pos) && !all(is.na(values)) &&\n\t\t\t\t\t(is.factor(values) || length(unique(na.omit(values))) > 1 || breaks_numeric) && # 2065\n\t\t\t\t\tlength(col) > 1) { # plot key?\n\n\t\t\t\tswitch(key.pos[1],\n\t\t\t\t\tlayout(matrix(c(2,1), nrow = 2, ncol = 1),\n\t\t\t\t\t\twidths = 1, heights = c(1, key.width)), # 1 bottom\n\t\t\t\t\tlayout(matrix(c(1,2), nrow = 1, ncol = 2),\n\t\t\t\t\t\twidths = c(key.width, 1), heights = 1), # 2 left\n\t\t\t\t\tlayout(matrix(c(1,2), nrow = 2, ncol = 1),\n\t\t\t\t\t\twidths = 1, heights = c(key.width, 1)), # 3 top\n\t\t\t\t\tlayout(matrix(c(2,1), nrow = 1, ncol = 2),\n\t\t\t\t\t\twidths = c(1, key.width), heights = 1)  # 4 right\n\t\t\t\t)\n\n\t\t\t\tif (is.factor(values)) {\n\t\t\t\t\t.image_scale_factor(levels(values), colors, key.pos = key.pos,\n\t\t\t\t\t\tkey.width = key.width, key.length = key.length, ...)\n\t\t\t\t} else\n\t\t\t\t\t.image_scale(values, colors, breaks = breaks, key.pos = key.pos,\n\t\t\t\t\t\tkey.length = key.length, logz = logz, ...)\n\t\t\t} else\n\t\t\t\treset_layout_needed = FALSE # as we didn't call layout()\n\t\t\t# plot the map:\n\t\t\tif (!isTRUE(dots$add)) {\n\t\t\t\tif (is.null(dots$mar)) {\n\t\t\t\t\tmar = c(1, 1, 1.2, 1)\n\t\t\t\t\tif (isTRUE(dots$axes))\n\t\t\t\t\t\tmar[1:2] = 2.1\n\t\t\t\t} else\n\t\t\t\t\tmar = dots$mar\n\t\t\t\tpar(mar = mar)\n\t\t\t}\n\t\t\tif (col_missing)\n\t\t\t\tplot(st_geometry(x), col = col, xlim = xlim, ylim = ylim, ...)\n\t\t\telse\n\t\t\t\tplot(st_geometry(x), xlim = xlim, ylim = ylim, ...)\n\t\t}\n\t\tif (! isTRUE(dots$add)) { # title?\n\t\t\tif (missing(main)) {\n\t\t\t\tmain = setdiff(names(x), attr(x, \"sf_column\"))\n\t\t\t\tif (length(main) && inherits(x[[main]], \"units\"))\n\t\t\t\t\tmain = make_unit_label(main, x[[main]])\n\t\t\t}\n\t\t\tlocalTitle <- function(..., extent, col, bg, pch, cex, lty, lwd, axes, type, bgMap,\n\t\t\t\t\tborder, graticule, xlim, ylim, asp, bgc, xaxs, yaxs, lab, setParUsrBB,\n\t\t\t\t\texpandBB, col_graticule, at, lon, lat, crs, datum, ndiscr, margin) # absorb\n\t\t\t\ttitle(...)\n\t\t\tlocalTitle(main, ...)\n\t\t}\n\t}\n\tinvisible()\n}\n\nswap_axes_if_needed = function(x) {\n\tcrs = st_crs(x)\n\tif (st_axis_order() && !is.na(crs) && crs$yx)\n\t\tst_transform(x, pipeline = \"+proj=pipeline +step +proj=axisswap +order=2,1\")\n\telse\n\t\tx\n}\n\n\n#' @name plot\n#' @export\nget_key_pos = function(x, ...) {\n\tbb = st_bbox(x)\n\tif (anyNA(bb) || (inherits(x, \"sf\") && ncol(x) > 2))\n\t\tNULL\n\telse {\n\t\tpin = par(\"pin\") # (width, height)\n\t\tasp_plt = pin[2]/pin[1] # y/x: < 1 means wide\n\t\tasp_box = diff(bb[c(4,2)]) / diff(bb[c(3,1)])\n\t\tasp = list(...)$asp\n\t\tif (is.null(asp))\n\t\t\tasp <- ifelse(isTRUE(st_is_longlat(x)), 1/cos((mean(bb[c(2,4)]) * pi)/180), 1.0)\n\t\tasp_box = asp_box * asp\n\t\tif (!is.finite(asp_box) || asp_box < asp_plt) # plot is wider than device: below\n\t\t\t1\n\t\telse # plot is taller than device: to the right\n\t\t\t4\n\t}\n}\n\n#' @name plot\n#' @method plot sfc_POINT\n#' @export\nplot.sfc_POINT = function(x, y, ..., pch = 1, cex = 1, col = 1, bg = 0, lwd = 1, lty = 1,\n\t\ttype = 'p', add = FALSE) {\n\tstopifnot(missing(y))\n\tif (! add)\n\t\tplot_sf(x, ...)\n\tnpts = length(x)\n\tif (npts == 0)\n\t\treturn()\n\tpch = rep(pch, length.out = npts)\n\tcol = rep(col, length.out = npts)\n\tbg = rep(bg, length.out = npts)\n\tcex = rep(cex, length.out = npts)\n\tmat = t(matrix(unlist(x, use.names = FALSE), ncol = length(x))) #933\n\tif (!is.null(mat)) {\n\t\tne = !is.na(rowMeans(mat))  ## faster than apply; #933\n\t\tpoints(mat[ne,, drop = FALSE], pch = pch[ne], col = col[ne], bg = bg[ne],\n\t\t\tcex = cex[ne], lwd = lwd, lty = lty, type = type)\n\t}\n}\n\n#' @name plot\n#' @method plot sfc_MULTIPOINT\n#' @export\nplot.sfc_MULTIPOINT = function(x, y, ..., pch = 1, cex = 1, col = 1, bg = 0, lwd = 1, lty = 1,\n\t\ttype = 'p', add = FALSE) {\n\tstopifnot(missing(y))\n\tif (! add)\n\t\tplot_sf(x, ...)\n\tn = length(x)\n\tif (n == 0)\n\t\treturn()\n\tpch = rep(pch, length.out = n)\n\tcol = rep(col, length.out = n)\n\tbg = rep(bg, length.out = n)\n\tcex = rep(cex, length.out = n)\n\tlwd = rep(lwd, length.out = n)\n\tlty = rep(lty, length.out = n)\n\tnon_empty = ! st_is_empty(x)\n\tlapply(seq_along(x), function(i)\n\t  if (non_empty[i])\n\t\tpoints(x[[i]], pch = pch[i], col = col[i], bg = bg[i],\n\t\t\tcex = cex[i], lwd = lwd[i], lty = lty[i], type = type))\n\tinvisible(NULL)\n}\n\n#' @name plot\n#' @method plot sfc_LINESTRING\n#' @export\nplot.sfc_LINESTRING = function(x, y, ..., lty = 1, lwd = 1, col = 1, pch = 1, type = 'l',\n\t\tadd = FALSE) {\n# FIXME: take care of lend, ljoin, and lmitre\n\tstopifnot(missing(y))\n\tif (! add)\n\t\tplot_sf(x, ...)\n\tlty = rep(lty, length.out = length(x))\n\tlwd = rep(lwd, length.out = length(x))\n\tcol = rep(col, length.out = length(x))\n\tpch  = rep(pch, length.out = length(x))\n\tnon_empty = ! st_is_empty(x)\n\tlapply(seq_along(x), function(i)\n\t  if (non_empty[i])\n\t\tlines(x[[i]], lty = lty[i], lwd = lwd[i], col = col[i], pch = pch[i], type = type))\n\tinvisible(NULL)\n}\n\n#' @name plot\n#' @method plot sfc_CIRCULARSTRING\n#' @export\nplot.sfc_CIRCULARSTRING = function(x, y, ...) {\n\tplot(st_cast(x, \"LINESTRING\"),  ...)\n}\n\n#' @name plot\n#' @method plot sfc_MULTILINESTRING\n#' @export\nplot.sfc_MULTILINESTRING = function(x, y, ..., lty = 1, lwd = 1, col = 1, pch = 1, type = 'l',\n\t\tadd = FALSE) {\n# FIXME: take care of lend, ljoin, and lmitre\n\tstopifnot(missing(y))\n\tif (! add)\n\t\tplot_sf(x, ...)\n\tlty = rep(lty, length.out = length(x))\n\tlwd = rep(lwd, length.out = length(x))\n\tcol = rep(col, length.out = length(x))\n\tpch  = rep(pch, length.out = length(x))\n\tnon_empty = ! st_is_empty(x)\n\tlapply(seq_along(x), function(i)\n\t  if (non_empty[i])\n\t\tlapply(x[[i]], function(L)\n\t\t\tlines(L, lty = lty[i], lwd = lwd[i], col = col[i], pch = pch[i], type = type)))\n\tinvisible(NULL)\n}\n\n# sf (list) -> polypath (mtrx) : rbind polygon rings with NA rows inbetween\np_bind = function(lst) {\n\tif (length(lst) == 1)\n\t\tlst[[1]]\n\telse {\n\t\tret = vector(\"list\", length(lst) * 2 - 1)\n\t\tret[seq(1, length(lst) * 2 - 1, by = 2)] = lst # odd elements\n\t\tret[seq(2, length(lst) * 2 - 1, by = 2)] = NA  # even elements\n\t\tdo.call(rbind, ret) # replicates the NA to form an NA row\n\t}\n}\n\n#' @name plot\n#' @param rule see \\link[graphics]{polypath}; for \\code{winding}, exterior ring direction should be opposite that of the holes; with \\code{evenodd}, plotting is robust against misspecified ring directions\n#' @param xpd see \\link[graphics]{par}; sets polygon clipping strategy; only implemented for POLYGON and MULTIPOLYGON\n#' @export\nplot.sfc_POLYGON = function(x, y, ..., lty = 1, lwd = 1, col = NA, cex = 1, pch = NA, border = 1,\n\t\tadd = FALSE, rule = \"evenodd\", xpd = par(\"xpd\")) {\n# FIXME: take care of lend, ljoin, and lmitre\n\tstopifnot(missing(y))\n\tif (! add)\n\t\tplot_sf(x, ...)\n\tlty = rep(lty, length.out = length(x))\n\tlwd = rep(lwd, length.out = length(x))\n\tcol = rep(col, length.out = length(x))\n\tborder = rep(border, length.out = length(x))\n\tnon_empty = ! st_is_empty(x)\n\tlapply(seq_along(x), function(i)\n\t  if (non_empty[i])\n\t\tpolypath(p_bind(x[[i]]), border = border[i], lty = lty[i], lwd = lwd[i], col = col[i], rule = rule, xpd = xpd))\n#\tif (any(!is.na(pch))) {\n#\t\tpch = rep(pch, length.out = length(x))\n#\t\tcex = rep(cex, length.out = length(x))\n#\t\tlapply(seq_along(x), function(i)\n#\t\t  if (non_empty[i])\n#\t\t\tpoints(p_bind(x[[i]]), pch = pch[i], cex = cex[i], type = 'p'))\n#\t}\n\tinvisible(NULL)\n}\n\n#' @name plot\n#' @method plot sfc_MULTIPOLYGON\n#' @export\nplot.sfc_MULTIPOLYGON = function(x, y, ..., lty = 1, lwd = 1, col = NA, border = 1, add = FALSE, \n\t\trule = \"evenodd\", xpd = par(\"xpd\")) {\n# FIXME: take care of lend, ljoin, and lmitre\n\tstopifnot(missing(y))\n\tif (! add)\n\t\tplot_sf(x, ...)\n\tlty = rep(lty, length.out = length(x))\n\tlwd = rep(lwd, length.out = length(x))\n\tcol = rep(col, length.out = length(x))\n\tborder = rep(border, length.out = length(x))\n\tnon_empty = ! st_is_empty(x)\n\tlapply(seq_along(x), function(i)\n\t  if (non_empty[i])\n\t\tlapply(x[[i]], function(L)\n\t\t\tpolypath(p_bind(L), border = border[i], lty = lty[i], lwd = lwd[i], col = col[i], rule = rule, xpd = xpd)))\n\tinvisible(NULL)\n}\n\n# plot single geometrycollection:\nplot_gc = function(x, pch, cex, bg, border = 1, lty, lwd, col, add) {\n\tlapply(x, function(subx) {\n\t\targs = list(st_sfc(subx), pch = pch, cex = cex, bg = bg, border = border,\n\t\t\tlty = lty, lwd = lwd, col = col, add = TRUE)\n\t\tfn = switch(class(subx)[2],\n\t\t\tPOINT = plot.sfc_POINT,\n\t\t\tMULTIPOINT = plot.sfc_MULTIPOINT,\n\t\t\tLINESTRING = plot.sfc_LINESTRING,\n\t\t\tMULTILINESTRING = plot.sfc_MULTILINESTRING,\n\t\t\tPOLYGON = plot.sfc_POLYGON,\n\t\t\tCIRCULARSTRING = plot.sfc_CIRCULARSTRING,\n\t\t\tMULTIPOLYGON = plot.sfc_MULTIPOLYGON,\n\t\t\tMULTISURFACE = plot.sfc_GEOMETRYCOLLECTION,\n\t\t\tCURVEPOLYGON = plot.sfc_GEOMETRYCOLLECTION,\n\t\t\tCOMPOUNDCURVE = plot.sfc_GEOMETRYCOLLECTION,\n\t\t\tGEOMETRYCOLLECTION = plot.sfc_GEOMETRYCOLLECTION,\n\t\t\tstop(paste(\"plotting of\", class(x)[2], \"not yet supported: use st_cast?\"))\n\t\t)\n\t\tdo.call(fn, args)\n\t})\n\tinvisible(NULL)\n}\n\n#' @name plot\n#' @method plot sfc_GEOMETRYCOLLECTION\n#' @export\nplot.sfc_GEOMETRYCOLLECTION = function(x, y, ..., pch = 1, cex = 1, bg = 0, lty = 1, lwd = 1,\n\tcol = 1, border = 1, add = FALSE) {\n# FIXME: take care of lend, ljoin, xpd, and lmitre\n\tstopifnot(missing(y))\n\tif (! add)\n\t\tplot_sf(x, ...)\n\tcex = rep(cex, length.out = length(x))\n\tpch = rep(pch, length.out = length(x))\n\tlty = rep(lty, length.out = length(x))\n\tlwd = rep(lwd, length.out = length(x))\n\tcol = rep(col, length.out = length(x))\n\tborder = rep(border, length.out = length(x))\n\tlapply(seq_along(x), function(i) plot_gc(x[[i]],\n\t\t\tpch = pch[i], cex = cex[i], bg = bg[i], border = border[i], lty = lty[i],\n\t\t\tlwd = lwd[i], col = col[i]))\n\tinvisible(NULL)\n}\n\n#' @name plot\n#' @method plot sfc_GEOMETRY\n#' @export\nplot.sfc_GEOMETRY = function(x, y, ..., pch = 1, cex = 1, bg = 0, lty = 1, lwd = 1,\n\tcol = ifelse(st_dimension(x) == 2, NA, 1), border = 1, add = FALSE) {\n\tstopifnot(missing(y))\n\tif (! add)\n\t\tplot_sf(x, ...)\n\tcex = rep(cex, length.out = length(x))\n\tpch = rep(pch, length.out = length(x))\n\tlty = rep(lty, length.out = length(x))\n\tlwd = rep(lwd, length.out = length(x))\n\tcol = rep(col, length.out = length(x))\n\tborder = rep(border, length.out = length(x))\n\tlapply(seq_along(x), function(i) plot_gc(st_sfc(x[[i]]),\n\t\t\tpch = pch[i], cex = cex[i], bg = bg[i], border = border[i], lty = lty[i],\n\t\t\tlwd = lwd[i], col = col[i]))\n\tinvisible(NULL)\n}\n\n#' @name plot\n#' @method plot sfg\n#' @export\nplot.sfg = function(x, ...) {\n\tplot(st_sfc(x), ...)\n}\n\n# set up plotting area & axes; reuses sp:::plot.Spatial\n#' @name plot\n#' @param xlim see \\link{plot.window}\n#' @param ylim see \\link{plot.window}\n#' @param asp see below, and see \\link{par}\n#' @param axes logical; should axes be plotted? (default FALSE)\n#' @param bgc background color\n#' @param xaxs see \\link{par}\n#' @param yaxs see \\link{par}\n#' @param lab see \\link{par}\n#' @param setParUsrBB default FALSE; set the \\code{par} \\dQuote{usr} bounding box; see below\n#' @param bgMap object of class \\code{ggmap}, or returned by function \\code{RgoogleMaps::GetMap}\n#' @param expandBB numeric; fractional values to expand the bounding box with,\n#' in each direction (bottom, left, top, right)\n#' @param graticule logical, or object of class \\code{crs} (e.g., \\code{st_crs('OGC:CRS84')} for a WGS84 graticule), or object created by \\link{st_graticule}\n#' @param col_graticule color to used for the graticule (if present)\n#' @export\n#' @details \\code{plot_sf} sets up the plotting area, axes, graticule, or webmap background; it\n#' is called by all \\code{plot} methods before anything is drawn.\n#'\n#' The argument \\code{setParUsrBB} may be used to pass the logical value \\code{TRUE} to functions within \\code{plot.Spatial}. When set to \\code{TRUE}, par(\\dQuote{usr}) will be overwritten with \\code{c(xlim, ylim)}, which defaults to the bounding box of the spatial object. This is only needed in the particular context of graphic output to a specified device with given width and height, to be matched to the spatial object, when using par(\\dQuote{xaxs}) and par(\\dQuote{yaxs}) in addition to \\code{par(mar=c(0,0,0,0))}.\n#'\n#' The default aspect for map plots is 1; if however data are not\n#' projected (coordinates are long/lat), the aspect is by default set to\n#' 1/cos(My * pi/180) with My the y coordinate of the middle of the map\n#' (the mean of \\code{ylim}, which defaults to the y range of bounding box). This\n#' implies an \\href{https://en.wikipedia.org/wiki/Equirectangular_projection}{Equirectangular projection}.\n#'\nplot_sf = function(x, xlim = NULL, ylim = NULL, asp = NA, axes = FALSE, bgc = par(\"bg\"), ...,\n    xaxs, yaxs, lab, setParUsrBB = FALSE, bgMap = NULL, expandBB = c(0,0,0,0), graticule = NA_crs_,\n\tcol_graticule = 'grey', border, extent = x) {\n\n# sp's bbox: matrix\n#   min max\n# x\n# y\n\n\tbbox = matrix(st_bbox(extent), 2, dimnames = list(c(\"x\", \"y\"), c(\"min\", \"max\")))\n\t# expandBB: 1=below, 2=left, 3=above and 4=right.\n\texpBB = function(lim, expand) c(lim[1] - expand[1] * diff(lim), lim[2] + expand[2] * diff(lim))\n\tif (is.null(xlim))\n\t\txlim <- expBB(bbox[1,], expandBB[c(2,4)])\n\tif (is.null(ylim))\n\t\tylim <- expBB(bbox[2,], expandBB[c(1,3)])\n\tif (is.na(asp))\n\t\tasp <- ifelse(isTRUE(st_is_longlat(x)), 1/cos((mean(ylim) * pi)/180), 1.0)\n\n\tif (anyNA(bbox))\n\t\tstop(\"NA value(s) in bounding box. Trying to plot empty geometries?\")\n\n\tplot.new()\n\n\targs = list(xlim = xlim, ylim = ylim, asp = asp)\n\tif (!missing(xaxs)) args$xaxs = xaxs\n\tif (!missing(yaxs)) args$yaxs = yaxs\n\tif (!missing(lab)) args$lab = lab\n\tdo.call(plot.window, args)\n\n\tif (setParUsrBB)\n\t\tpar(usr=c(xlim, ylim))\n\tpl_reg <- par(\"usr\")\n\trect(xleft = pl_reg[1], ybottom = pl_reg[3], xright = pl_reg[2],\n\t\tytop = pl_reg[4], col = bgc, border = FALSE)\n\tlinAxis = function(side, ..., lon, lat, ndiscr, reset, at) axis(side = side, ...)\n\tif (!missing(graticule) && !identical(graticule, FALSE)) {\n\t\tg = if (isTRUE(graticule))\n\t\t\t\tst_graticule(pl_reg[c(1,3,2,4)], st_crs(x), st_datum(x), ...)\n\t\t\telse if (inherits(graticule, \"crs\") && !is.na(graticule))\n\t\t\t\tst_graticule(pl_reg[c(1,3,2,4)], st_crs(x), graticule, ...)\n\t\t\telse\n\t\t\t\tgraticule\n\t\tplot(st_geometry(g), col = col_graticule, add = TRUE)\n\t\tbox()\n\t\tif (axes) {\n\t\t\tsel = g$type == \"E\" & g$plot12\n\t\t\tlinAxis(1L, g$x_start[sel], parse(text = g$degree_label[sel]), ...)\n\t\t\tsel = g$type == \"N\" & g$plot12\n\t\t\tlinAxis(2L, g$y_start[sel], parse(text = g$degree_label[sel]), ...)\n\t\t}\n\t} else if (axes) {\n\t\tbox()\n\t\tif (isTRUE(st_is_longlat(x))) {\n\t\t\tlocal_degAxis = function(side, ..., at) .degAxis(side, ...) # absorb at\n\t\t\tlocal_degAxis(1, ...)\n\t\t\tlocal_degAxis(2, ...)\n\t\t} else {\n\t\t\tlinAxis(1, ...)\n\t\t\tlinAxis(2, ...)\n\t\t}\n\t}\n\tlocalTitle <- function(..., col, bgc, pch, cex, lty, lwd, lon, lat, ndiscr, at, labels, reset) title(...)\n\tlocalTitle(...)\n\tif (!is.null(bgMap)) {\n\t\tmercator = FALSE\n\t\tif (inherits(bgMap, \"ggmap\")) {\n\t\t\tbb = bb2merc(bgMap, \"ggmap\")\n\t\t\tmercator = TRUE\n\t\t} else if (all(c(\"lat.center\",\"lon.center\",\"zoom\",\"myTile\",\"BBOX\") %in% names(bgMap))) {\n\t\t\t# an object returned by RgoogleMaps::GetMap\n\t\t\tbb = bb2merc(bgMap, \"RgoogleMaps\")\n\t\t\tbgMap = bgMap$myTile\n\t\t\tmercator = TRUE\n\t\t} else\n\t\t\tbb = c(xlim[1], ylim[1], xlim[2], ylim[2]) # can be any crs!\n\t\tif (mercator &&  st_crs(x) != st_crs(3857))\n\t\t\twarning(\"crs of plotting object differs from that of bgMap, which is assumed to be st_crs(3857)\") # nocov\n\t\trasterImage(bgMap, bb[1], bb[2], bb[3], bb[4], interpolate = FALSE)\n\t}\n}\n\n\n#' @param n integer; number of colors\n#' @param cutoff.tails numeric, in `[0,0.5]` start and end values\n#' @param alpha numeric, in `[0,1]`, transparency\n#' @param categorical logical; do we want colors for a categorical variable? (see details)\n#' @name plot\n#' @export\n#' @details non-categorical colors from \\code{sf.colors} were taken from \\link[sp]{bpy.colors}, with modified \\code{cutoff.tails} defaults\n#' If categorical is \\code{TRUE}, default colors are from \\url{https://colorbrewer2.org/} (if n < 9, Set2, else Set3).\n#' @examples\n#' sf.colors(10)\nsf.colors = function (n = 10, cutoff.tails = c(0.35, 0.2), alpha = 1, categorical = FALSE) {\n\tif (categorical) {\n\t\tcb = if (n <= 8)\n\t\t# 8-class Set2:\n\t\tc('#66c2a5','#fc8d62','#8da0cb','#e78ac3','#a6d854','#ffd92f','#e5c494','#b3b3b3')\n\t\t# 12-class Set3:\n\t\telse c('#8dd3c7','#ffffb3','#bebada','#fb8072','#80b1d3','#fdb462','#b3de69','#fccde5','#d9d9d9','#bc80bd','#ccebc5','#ffed6f')\n\t\t# TODO: deal with alpha\n\t\tif (alpha != 1.0)\n\t\t\tcb = paste0(cb, as.hexmode(ceiling(alpha * 255)))\n\t\trep(cb, length.out = n)\n\t} else {\n\t\ti = seq(0.5 * cutoff.tails[1], 1 - 0.5 * cutoff.tails[2], length.out = n)\n   \t\tr = ifelse(i < .25, 0, ifelse(i < .57, i / .32 - .78125, 1))\n   \t\tg = ifelse(i < .42, 0, ifelse(i < .92, 2 * i - .84, 1))\n   \t\tb = ifelse(i < .25, 4 * i, ifelse(i < .42, 1,\n\t\t\tifelse(i < .92, -2 * i + 1.84, i / .08 - 11.5)))\n\t\trgb(r, g, b, alpha)\n\t}\n}\n\n# Add text to an existing (base) plot\n#\n#' @param labels character, text to draw (one per row of input)\n#' @name plot\n#' @export\n#' @details `text.sf` adds text to an existing base graphic. Text is placed at the centroid of \n#' each feature in \\code{x}. Provide POINT features for further control of placement.\n#' `points.sf` adds point symbols to an existing base graphic. If points of text are not shown\n#' correctly, try setting argument `reset` to `FALSE` in the `plot()` call.\n#' @examples\n#' text(nc, labels = substring(nc$NAME,1,1))\ntext.sf = function(x, labels = row.names(x), ...) {\n\ttext(st_geometry(x), labels = labels, ...)\n}\n\n#' @export\n#' @name plot\n#' @param of_largest_polygon logical, passed on to \\link{st_centroid}\ntext.sfc = function(x, labels = seq_along(x), ..., of_largest_polygon = FALSE){\n\tx = st_centroid(x, of_largest_polygon = of_largest_polygon)\n\txy = st_coordinates(x)\n\ttext(xy[,1], xy[,2], labels = labels, ...)\n}\n\n#' @name plot\n#' @export\npoints.sf = function(x, ...) {\n\tpoints(st_geometry(x), ...)\n}\n\n#' @name plot\n#' @export\npoints.sfc = function(x, ..., of_largest_polygon = FALSE) {\n\tx = st_centroid(x, of_largest_polygon = of_largest_polygon)\n\txy = st_coordinates(x)\n\tpoints(xy[,1], xy[,2], ...)\n}\n\n# get the aspect ratio of a bounding box, for geodetic coords true scale at mid latitude:\nget_asp = function(bb) {\n\tasp = diff(bb[c(2,4)])/diff(bb[c(1,3)])\n\tif (!is.finite(asp)) # 0/0\n\t\tasp = 1\n\tif (isTRUE(st_is_longlat(bb)))\n\t\tasp = asp / cos(mean(bb[c(2,4)]) * pi /180)\n\tasp\n}\n\n#' functions only exported to be used internally by stars\n#' @keywords internal\n#' @name stars\n#' @param bb ignore\n#' @param n ignore\n#' @param total_size ignore\n#' @param key.width ignore\n#' @param key.length ignore\n#' @param mfrow length-2 integer vector with number of rows, columns\n#' @param main main or sub title\n#' @export\n.get_layout = function(bb, n, total_size, key.pos, key.width, mfrow = NULL, main = NULL) {\n# return list with \"m\" matrix, \"key.pos\", \"widths\" and \"heights\" fields\n# if key.pos = -1 on input, it will be a return value, \"optimally\" placed\n\tasp = get_asp(bb)\n\tstrip = if (is.character(main))\n\t\t\t# strheight(main, \"inches\") \n\t\t\tpar(\"cin\")[2]\n\t\telse \n\t\t\t0.0\n\tsize = function(nrow, n, asp, strip = 0) { # given nrow n asp, what size does a single tile occupy?\n\t\tncol = ceiling(n / nrow)\n\t\txsize = total_size[1] / ncol\n\t\tysize = xsize  * asp + strip\n\t\tif (xsize * ysize * n > prod(total_size)) {\n\t\t\tysize = total_size[2] / nrow - strip\n\t\t\txsize = ysize / asp\n\t\t}\n\t\tc(xsize, ysize)\n\t}\n\tsz = vapply(1:n, function(nrow) size(nrow, n, asp, strip), c(0.0, 0.0))\n\tif (is.null(mfrow)) {\n\t\tnrow = which.max(apply(sz, 2, prod))\n\t\tncol = ceiling(n / nrow)\n\t} else {\n\t\tstopifnot(is.numeric(mfrow), length(mfrow) == 2)\n\t\tnrow = mfrow[1]\n\t\tncol = mfrow[2]\n\t}\n\txsize = sz[1, nrow]\n\tysize = sz[2, nrow]\n\tasp = ysize / xsize\n\n\tret = list()\n\tret$mfrow = c(nrow, ncol)\n\n\t# the following is right now only used by stars; FIXME:\n\t# nocov start\n\tret$key.pos = if (!is.null(key.pos) && key.pos == -1L) { # figure out here: right or bottom?\n\t\t\tnewasp = asp * nrow / ncol # of the composition\n\t\t\tdispasp = total_size[2] / total_size[1]\n\t\t\tifelse(newasp > dispasp, 4, 1)\n\t\t} else\n\t\t\tkey.pos\n\n\tm = matrix(seq_len(nrow * ncol), nrow, ncol, byrow = TRUE)\n\tif (!is.null(ret$key.pos) && ret$key.pos != 0) { # add key row or column:\n\t\tk = key.width\n\t\tn = nrow * ncol + 1\n\t\tswitch(ret$key.pos,\n\t\t\t{ ret$m = rbind(m, n); ret$widths = c(rep(1, ncol)); ret$heights = c(rep(asp, nrow), k) },\n\t\t\t{ ret$m = cbind(n, m); ret$widths = c(k, rep(1, ncol)); ret$heights = c(rep(asp, nrow)) },\n\t\t\t{ ret$m = rbind(n, m); ret$widths = c(rep(1, ncol)); ret$heights = c(k, rep(asp, nrow)) },\n\t\t\t{ ret$m = cbind(m, n); ret$widths = c(rep(1, ncol), k); ret$heights = c(rep(asp, nrow)) }\n\t\t)\n\t} else {\n\t\tret$m = m\n\t\tret$widths = rep(1, ncol)\n\t\tret$heights = rep(asp, nrow)\n\t}\n\t# nocov end\n\tret\n}\n\nbb2merc = function(x, cls = \"ggmap\") { # return bbox in the appropriate \"web mercator\" CRS\n\twgs84 = st_crs(4326)\n\tmerc =  st_crs(3857) # http://wiki.openstreetmap.org/wiki/EPSG:3857\n\tpts = if (cls == \"ggmap\") {\n\t\tb = vapply(attr(x, \"bb\"), c, 0.0)\n\t\tst_sfc(st_point(c(b[2:1])), st_point(c(b[4:3])), crs = wgs84)\n\t} else if (cls == \"RgoogleMaps\")\n\t\tst_sfc(st_point(rev(x$BBOX$ll)), st_point(rev(x$BBOX$ur)), crs = wgs84)\n\telse\n\t\tstop(\"unknown cls\")\n\tst_bbox(st_transform(pts, merc))\n}\n\n#' @rdname stars\n#' @param side ignore\n#' @param at ignore\n#' @param labels ignore\n#' @param lon ignore\n#' @param lat ignore\n#' @param ndiscr ignore\n#' @param reset ignore\n#' @export\n.degAxis = function (side, at, labels, ..., lon, lat, ndiscr, reset) {\n\tif (missing(at))\n       \tat = axTicks(side)\n\tif (missing(labels)) {\n\t\tlabels = FALSE\n\t\tif (side == 1 || side == 3)\n\t\t\tlabels = parse(text = degreeLabelsEW(at))\n\t\telse if (side == 2 || side == 4)\n\t\t\tlabels = parse(text = degreeLabelsNS(at))\n\t}\n\taxis(side, at = at, labels = labels, ...)\n}\n\n# find out where to place the legend key:\n# given range r = (a, b), key.length l, key offset o, return a value range that:\n#  (i)  scales such that (b - a) / (y - x) = l, and\n#  (ii) shifts linearly within [x, y] from a = x when o = 0 to b = y when o = 1\nxy_from_r = function(r, l, o) {\n\tstopifnot(length(r) == 2, l <= 1, l > 0, o >= 0, o <= 1)\n\tr = as.numeric(r)\n\ta = r[1]; b = r[2]\n\tif (o == 1) {\n\t\ty = b\n\t\tx = b - (b - a)/l\n\t} else {\n\t\ti = o / (o - 1)\n\t\ty = (a + (b - a)/l - i * b)/(1 - i)\n\t\tx = i * (y - b) + a\n\t}\n\tc(x, y)\n}\n\n#' @rdname stars\n#' @param z ignore\n#' @param col ignore\n#' @param breaks ignore\n#' @param key.pos ignore\n#' @param add.axis ignore\n#' @param axes ignore\n#' @param logz ignore\n#' @param ... ignore\n#' @param lab ignore\n#' @param cex.axis see \\link{par}\n#' @export\n.image_scale = function(z, col, breaks = NULL, key.pos, add.axis = TRUE,\n\t\tat = NULL, ..., axes = FALSE, key.length, logz = FALSE, lab = \"\", \n\t\tcex.axis = par(\"cex.axis\")) {\n\tif (!is.null(breaks) && length(breaks) != (length(col) + 1))\n\t\tstop(\"must have one more break than colour\")\n\tstopifnot(is.null(lab) || is.character(lab) || is.expression(lab))\n\tlab_set = (is.character(lab) && lab != \"\") || is.expression(lab)\n\tzlim = range(z, na.rm = TRUE)\n\tif (is.null(breaks))\n\t\tbreaks = seq(zlim[1], zlim[2], length.out = length(col) + 1)\n\toffset = 0.5\n\tif (length(key.pos) == 2) {\n\t\toffset = key.pos[2]\n\t\tkey.pos = key.pos[1]\n\t}\n\tif (is.character(key.length)) {\n\t\tkl = as.numeric(gsub(\" cm\", \"\", key.length))\n\t\tsz = if (key.pos %in% c(1,3))\n\t\t\t\tdev.size(\"cm\")[1]\n\t\t\telse\n\t\t\t\tdev.size(\"cm\")[2]\n\t\tkey.length = kl/sz\n\t}\n\tif (is.null(at)) {\n\t\tbr = range(breaks)\n\t\tat = pretty(br)\n\t\tat = at[at > br[1] & at < br[2]]\n\t}\n\tif (key.pos %in% c(1,3)) {\n\t\tylim = c(0, 1)\n\t\txlim = xy_from_r(range(breaks), key.length, offset)\n\t\tmar = c(0, ifelse(axes, 2.1, 1), 0, 1)\n\t}\n\tif (key.pos %in% c(2,4)) {\n\t\tylim = xy_from_r(range(breaks), key.length, offset)\n\t\txlim = c(0, 1)\n\t\tmar = c(ifelse(axes, 2.1, 1), 0, 1.2, 0)\n\t}\n\tmar[key.pos] = 2.1 + 1.5 * lab_set\n\tpar(mar = mar)\n\n\tplot(1, 1, type = \"n\", ylim = ylim, xlim = xlim, axes = FALSE,\n\t\txlab = \"\", ylab = \"\", xaxs = \"i\", yaxs = \"i\")\n\tif (!is.null(lab) && lab != \"\")\n\t\tmtext(lab, side = key.pos, line = 2.5, cex = .8)\n\tpoly = vector(mode=\"list\", length(col))\n\tfor (i in seq(poly))\n\t\tpoly[[i]] = c(breaks[i], breaks[i+1], breaks[i+1], breaks[i])\n\toffset = 0.2\n\toffs = switch(key.pos,\n\t\tc(0, 0, -offset, -offset),\n\t\tc(0, 0, -offset, -offset),\n\t\tc(offset, offset, 0, 0),\n\t\tc(offset, offset, 0, 0))\n\tfor(i in seq_along(poly)) {\n\t\tif (key.pos %in% c(1,3))\n\t\t\tpolygon(poly[[i]], c(0, 0, 1, 1) + offs, col = col[i], border = NA)\n\t\tif (key.pos %in% c(2,4))\n\t\t\tpolygon(c(0, 0, 1, 1) + offs, poly[[i]], col = col[i], border = NA)\n\t}\n\n\t# box() now would draw around [0,1]:\n\tbx = c(breaks[1], rep(tail(breaks, 1), 2), breaks[1])\n\tif (key.pos %in% c(1, 3))\n\t\tpolygon(bx, c(0, 0, 1, 1) + offs, col = NA, border = 'black')\n\tif (key.pos %in% c(2, 4))\n\t\tpolygon(c(0, 0, 1, 1) + offs, bx, col = NA, border = 'black')\n\n\tlabels = if (logz)\n\t\t\tparse(text = paste0(\"10^\", at))\n\t\telse if (inherits(breaks, c(\"POSIXt\", \"Date\")))\n\t\t\tformat(at)\n\t\telse\n\t\t\tTRUE\n\n\tif (add.axis)\n\t\taxis(key.pos, at = at, labels = labels, cex.axis = cex.axis)\n}\n\n#' @rdname stars\n#' @param key.width ignore\n#' @export\n.image_scale_factor = function(z, col, key.pos, add.axis = TRUE,\n\t..., axes = FALSE, key.width, key.length, cex.axis = par(\"cex.axis\")) {\n\n\tto_num = function(x) as.numeric(gsub(\" cm\", \"\", x))\n\tn = length(z)\n\tif ((kw <- to_num(key.width)) < to_num(kw_dflt(list(z), key.pos))) { # cut z until it fits:\n\t\tm = max(nchar(z))\n\t\twhile(kw < to_num(kw_dflt(list(z), key.pos))) { # cut z:\n\t\t\tm = m - 1\n\t\t\tz = substr(z, 1, m)\n\t\t}\n\t}\n\tksz = max(1.5 + max(nchar(z))/2, max(strwidth(z, \"inches\")) / par(\"cin\")[1]) # in \"mar\" lines\n\tbreaks = (0:n) + 0.5\n\toffset = 0.5\n\tif (length(key.pos) == 2) {\n\t\toffset = key.pos[2]\n\t\tkey.pos = key.pos[1]\n\t}\n\tif (is.character(key.length)) {\n\t\tkl = to_num(key.length)\n\t\tsz = if (key.pos %in% c(1, 3))\n\t\t\t\tdev.size(\"cm\")[1]\n\t\t\telse\n\t\t\t\tdev.size(\"cm\")[2]\n\t\tkey.length = kl/sz\n\t}\n\tif (key.pos %in% c(1, 3)) {\n\t\tylim = c(0, 1)\n\t\txlim = xy_from_r(range(breaks), key.length, offset)\n\t\tmar = c(0, ifelse(axes, 2.1, 1), 0, 1)\n\t\tmar[key.pos] = 2.1\n\t} else {\n\t\tylim = xy_from_r(range(breaks), key.length, offset)\n\t\txlim = c(0, 1)\n\t\tmar = c(ifelse(axes, 2.1, 1), 0, 1.2, 0)\n\t\tmar[key.pos] = ksz\n\t}\n\tpar(mar = mar)\n\n\tpoly = vector(mode=\"list\", length(col))\n\tfor (i in seq(poly))\n\t\tpoly[[i]] = c(breaks[i], breaks[i+1], breaks[i+1], breaks[i])\n\n\ttryCatch({\n\t\tplot(1, 1, type = \"n\", ylim = ylim, xlim = xlim, axes = FALSE,\n\t\t\txlab = \"\", ylab = \"\", xaxs = \"i\", yaxs = \"i\")\n\t\t},\n\t\terror = function(x) {\n\t\t\tsz = cm(max(strwidth(z, \"inches\"))) * 1.3 + par(\"ps\")/12 # cm\n\t\t\tstop(paste0(\"key.width too small, try key.width = lcm(\", signif(sz, 3), \")\"), call. = FALSE)\n\t\t}\n\t)\n\n\tfor(i in seq_along(poly)) {\n\t\tif (key.pos %in% c(1, 3))\n\t\t\tpolygon(poly[[i]], c(0, 0, 1, 1), col = col[i], border = NA)\n\t\tif (key.pos %in% c(2, 4))\n\t\t\tpolygon(c(0, 0, 1, 1), poly[[i]], col = col[i], border = NA)\n\t}\n\n\t# box() now would draw around [0,1]:\n\tbx = c(breaks[1], rep(tail(breaks, 1), 2), breaks[1])\n\tif (key.pos %in% c(1,3))\n\t\tpolygon(bx, c(0, 0, 1, 1), col = NA, border = 'black')\n\tif (key.pos %in% c(2,4))\n\t\tpolygon(c(0, 0, 1, 1), bx, col = NA, border = 'black')\n\n\tif (add.axis) {\n\t\topar = par(las = 1)\n\t\taxis(key.pos, at = 1:n, labels = z, cex.axis = cex.axis)\n\t\tpar(opar)\n\t}\n}\n\n# nocov start\n#' @export\nidentify.sfc = function(x, ..., n = min(10, length(x)), type = \"n\") {\n\tl = locator(n, type = type)\n\tpts = st_as_sf(as.data.frame(do.call(cbind, l)), coords = c(\"x\", \"y\"), crs = st_crs(x))\n\tsapply(st_intersects(pts, x), function(x) if (length(x)) x[1] else NA_integer_)\n}\n\n#' @export\nidentify.sf = function(x, ...) {\n\tidentify(st_geometry(x), ...)\n}\n# nocov end\n"
  },
  {
    "path": "R/proj.R",
    "content": "\n#' @name st_transform\n#' @param type character; one of `have_datum_files`, `proj`, `ellps`, `datum`, `units`, `path`, or `prime_meridians`; see Details.\n#' @param path character; PROJ search path to be set\n#' @export\n#' @details \\code{sf_proj_info} lists the available projections, ellipses, datums, units, or data search path of the PROJ library when \\code{type} is equal to proj, ellps, datum, units or path; when \\code{type} equals \\code{have_datum_files} a boolean is returned indicating whether datum files are installed and accessible (checking for \\code{conus}). `path` returns the `PROJ_INFO.searchpath` field directly, as a single string with path separaters (`:`  or `;`).\n#'\n#' for PROJ >= 6, \\code{sf_proj_info} does not provide option \\code{type = \"datums\"}. \n#' PROJ < 6 does not provide the option \\code{type = \"prime_meridians\"}.\n#'\n#' for PROJ >= 7.1.0, the \"units\" query of \\code{sf_proj_info} returns the \\code{to_meter} \n#' variable as numeric, previous versions return a character vector containing a numeric expression.\n#' @examples\n#' sf_proj_info(\"datum\")\nsf_proj_info = function(type = \"proj\", path) {\n\n\tif (type == \"have_datum_files\")\n\t\treturn(CPL_have_datum_files(0))\n\n\tif (type == \"path\")\n\t\treturn(CPL_get_data_dir(TRUE))\n\t\n\tif (!missing(path) && is.character(path))\n\t\treturn(invisible(unique(CPL_set_data_dir(path, TRUE))))\n\n\tif (type == \"network\")\n\t\treturn(CPL_is_network_enabled(TRUE))\n\n\topts <- c(\"proj\", \"ellps\", \"datum\", \"units\", \"prime_meridians\")\n\tif (!(type %in% opts))\n\t\tstop(\"unknown type\") # nocov\n\tt <- as.integer(match(type[1], opts) - 1)\n\tres = CPL_proj_info(as.integer(t))\n\tif (type == \"proj\")\n\t\tres$description <- sapply(strsplit(as.character(res$description), \"\\n\"),\n\t\t\tfunction(x) x[1])\n\tdata.frame(res)\n}\n\n#' directly transform a set of coordinates\n#'\n#' directly transform a set of coordinates\n#' @param from character description of source CRS, or object of class \\code{crs}, \n#' or pipeline describing a transformation\n#' @param to character description of target CRS, or object of class \\code{crs} \n#' @param pts two-, three- or four-column numeric matrix, or object that can be coerced into a matrix; columns 3 and 4 contain z and t values.\n#' @param keep logical value controlling the handling of unprojectable points. If\n#' `keep` is `TRUE`, then such points will yield `Inf` or `-Inf` in the\n#' return value; otherwise an error is reported and nothing is returned.\n#' @param warn logical; if \\code{TRUE}, warn when non-finite values are generated\n#' @param authority_compliant logical; \\code{TRUE} means handle axis order authority compliant (e.g. EPSG:4326 implying x=lat, y=lon), \\code{FALSE} means use visualisation order (i.e. always x=lon, y=lat)\n#' @return two-column numeric matrix with transformed/converted coordinates, returning invalid values as \\code{Inf}\n#' @export\nsf_project = function(from = character(0), to = character(0), pts, keep = FALSE, warn = TRUE, \n\t\tauthority_compliant = st_axis_order()) {\n\n\tif (!is.logical(keep) || length(keep) != 1 || is.na(keep))\n\t\tstop(\"'keep' must be single-length non-NA logical value\")\n\tproj_from_crs = function(x) {\n\t\tif (inherits(x, \"crs\")) {\n\t\t\tx = if (compareVersion(sf_extSoftVersion()[\"proj.4\"], \"6.0.0\") >= 0)\n\t\t\t\tx$wkt\n\t\t\telse\n\t\t\t\tx$proj4string\n\t\t}\n\t\tif (length(x)) {\n\t\t\tv = CPL_proj_is_valid(x)\n\t\t\tif (!v[[1]])\n\t\t\t\tstop(paste0(v[[2]], \": \", x))\n\t\t\tx[1]\n\t\t} else\n\t\t\tx # empty: character(0)\n\t}\n\n\tfrom_to = c(proj_from_crs(from), proj_from_crs(to))\n\tif ((length(from_to) == 1) && !missing(authority_compliant))\n\t\tstop(\"when specifying a projection pipeline, setting authority_compliant has no effect\")\n\n\tCPL_proj_direct(from_to, as.matrix(pts), keep, warn, authority_compliant)\n}\n\n#' Manage PROJ settings\n#' \n#' Query or manage PROJ search path and network settings\n#' @param paths the search path to be set; omit if paths need to be queried\n#' @param with_proj logical; if `NA` set for both GDAL and PROJ, otherwise set either for PROJ (`TRUE`) or GDAL (`FALSE`)\n#' @return `sf_proj_search_paths()` returns the search path (possibly after setting it)\n#' @name proj_tools\n#' @export\nsf_proj_search_paths = function(paths = character(0), with_proj = NA) {\n\tif (length(paths) == 0)\n\t\tCPL_get_data_dir(FALSE)\n\telse {\n\t\tif (is.na(with_proj) || !isTRUE(with_proj))\n\t\t\tCPL_set_data_dir(as.character(paths), FALSE) # set GDAL\n\t\tif (is.na(with_proj) || isTRUE(with_proj)) { # set for PROJ\n\t\t\tif (length(paths) > 1) {\n\t\t\t\tpaths = paste0(paths, collapse = .Platform$path.sep)\n\t\t\t\tmessage(paste(\"setting proj path(s) to\", paths))\n\t\t\t}\n\t\t\tCPL_set_data_dir(as.character(paths), TRUE)\n\t\t}\n\t}\n}\n\n#' @param enable logical; set this to enable (`TRUE`) or disable (`FALSE`) the proj network search facility\n#' @param url character; use this to specify and override the default proj network CDN \n#' @return `sf_proj_network` when called without arguments returns a logical indicating whether\n#' network search of datum grids is enabled, when called with arguments it returns a character\n#' vector with the URL of the CDN used (or specified with `url`).\n#' @name proj_tools\n#' @export\nsf_proj_network = function(enable = FALSE, url = character(0)) {\n\tif (missing(enable) && missing(url))\n\t\tCPL_is_network_enabled()\n\telse \n\t\tCPL_enable_network(url, enable)\n}\n\n#' @param source_crs,target_crs object of class `crs` or character\n#' @param authority character; constrain output pipelines to those of authority\n#' @param AOI length four numeric; desired area of interest for the resulting \n#' coordinate transformations (west, south, east, north, in degrees).\n#' For an area of interest crossing the anti-meridian, west will be greater than east.\n#' @param Use one of \"NONE\", \"BOTH\", \"INTERSECTION\", \"SMALLEST\", indicating how AOI's\n#' of source_crs and target_crs are being used\n#' @param grid_availability character; one of \"USED\" (Grid availability is only used for sorting \n#' results. Operations where some grids are missing will be sorted last), \"DISCARD\"\n#' (Completely discard an operation if a required grid is missing)\n#' , \"IGNORED\" (Ignore grid availability at all. Results will be presented as if all grids were \n#' available.), or \"AVAILABLE\" (Results will be presented as if grids known to PROJ (that is \n#' registered in the grid_alternatives table of its database) were available. Used typically when \n#' networking is enabled.)\n#' @param desired_accuracy numeric; only return pipelines with at least this accuracy\n#' @param strict_containment logical; default `FALSE`; permit partial matching of the area\n#' of interest; if `TRUE` strictly contain the area of interest.\n#' The area of interest is either as given in AOI, or as implied by the\n#' source/target coordinate reference systems \n#' @param axis_order_authority_compliant logical; if `FALSE` always \n#' choose ‘x’ or longitude for the first \n#' axis; if TRUE, follow the axis orders given by the coordinate reference systems when \n#' constructing the for the first axis; if `FALSE`, follow the axis orders given by\n#' @return `sf_proj_pipelines()` returns a table with candidate coordinate transformation\n#' pipelines along with their accuracy; `NA` accuracy indicates ballpark accuracy.\n#' @name proj_tools\n#' @export\nsf_proj_pipelines = function(source_crs, target_crs, authority = character(0), AOI = numeric(0),\n\t\tUse = \"NONE\", grid_availability = \"USED\", desired_accuracy = -1.0, \n\t\tstrict_containment = FALSE, axis_order_authority_compliant = st_axis_order()) {\n\tstopifnot(!missing(source_crs), !missing(target_crs))\n\tif (inherits(source_crs, \"crs\"))\n\t\tsource_crs = source_crs$wkt\n\tif (inherits(target_crs, \"crs\"))\n\t\ttarget_crs = target_crs$wkt\n\tstopifnot(is.character(source_crs), is.character(target_crs))\n\n\tret = CPL_get_pipelines(c(source_crs, target_crs), as.character(authority), \n\t\tas.numeric(AOI), as.character(Use), as.character(grid_availability),\n\t\tas.numeric(desired_accuracy), as.logical(strict_containment), \n\t\tas.logical(axis_order_authority_compliant))\n\tif (nrow(ret)) {\n\t\tif (!startsWith(ret$definition[1], \"+\")) # paste + to every word\n\t\t\tret$definition = \n\t\t\t\tsapply(strsplit(ret$definition, \" \"), \n\t\t\t\t\tfunction(x) paste0(paste0(\"+\", x), collapse=\" \"))\n\t\tret$containment = strict_containment\n\t\tstructure(ret, class = c(\"proj_pipelines\", \"data.frame\"),\n\t\t\tsource_crs = source_crs, target_crs = target_crs)\n\t} else\n\t\tinvisible(NULL)\n}\n\n#' @export\nprint.proj_pipelines = function(x, ...) {\n\tcat(\"Candidate coordinate operations found: \", nrow(x), \"\\n\")\n\tnos <- which(!x$instantiable)\n\tif (length(nos) > 0L)\n\t\txx <- x[-nos,]\n\telse\n\t\txx <- x\n\txx <- xx[order(xx$accuracy),]\n\ty = xx[1,]\n\tcat(\"Strict containment:    \", y$containment, \"\\n\")\n\tcat(\"Axis order auth compl: \", y$axis_order, \"\\n\")\n\tcat(\"Source: \", attr(x, \"source_crs\"), \"\\n\")\n\tcat(\"Target: \", attr(x, \"target_crs\"), \"\\n\")\n\tif (is.na(y$accuracy))\n\t\tcat(\"Best instantiable operation has only ballpark accuracy\", \"\\n\")\n\telse\n\t\tcat(\"Best instantiable operation has accuracy:\", y$accuracy, \"m\\n\")\n\tcat(\"Description: \")\n\tdesc <- strwrap(y$description, exdent=13, width=0.8*getOption(\"width\"))\n\tif (length(desc) == 1L)\n\t\tcat(desc, \"\\n\")\n\telse\n\t\tcat(desc, sep=\"\\n\")\n\tcat(\"Definition:  \")\n\tdef <- strwrap(y$definition, exdent=13, width=0.8*getOption(\"width\"))\n\tif (length(def) == 1L)\n\t\tcat(def, \"\\n\")\n\telse\n\t\tcat(def, sep=\"\\n\")\n\t# nos:\n\tif (length(nos) > 0L) {\n\t\tgrds <- attr(x, \"grids\")\n\t\tfor (i in seq(along.with = nos)) {\n\t\t\tgrd <- grds[[nos[i]]]\n\t\t\tii <- length(grd)\n\t\t\tif (ii > 0L) {\n\t\t\t\tcat(\"Operation\", nos[i], \"is lacking\", ii,\n\t\t\t\tifelse(ii == 1L, \"grid\", \"grids\"),\n\t\t\t\t\t\"with accuracy\", x$accuracy[nos[i]], \"m\\n\")\n\t\t\t\tfor (j in 1:ii) {\n\t\t\t\t\tcat(\"Missing grid:\", grd[[j]][[1]], \"\\n\")\n\t\t\t\t\tif (nzchar(grd[[j]][[2]])) cat(\"Name:\", grd[[j]][[2]], \"\\n\")\n\t\t\t\t\tif (nzchar(grd[[j]][[4]])) cat(\"URL:\", grd[[j]][[4]], \"\\n\")\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\tinvisible(x)\n}\n"
  },
  {
    "path": "R/read.R",
    "content": "sf_stringsAsFactors = function() {\n\tif (getRversion() < \"4.1.0\")\n\t\tdefault.stringsAsFactors()\n\telse\n\t\tFALSE\n}\n\nset_utf8 = function(x) {\n\tn = names(x)\n\tEncoding(n) = \"UTF-8\"\n\tto_utf8 = function(x) {\n\t\tif (is.character(x))\n\t\t\tEncoding(x) = \"UTF-8\"\n\t\tx\n\t}\n\tstructure(lapply(x, to_utf8), names = n)\n}\n\n#' Read simple features or layers from file or database\n#'\n#' Read simple features from file or database, or retrieve layer names and their\n#' geometry type(s)\n#' @param dsn data source name (interpretation varies by driver - for some\n#'   drivers, \\code{dsn} is a file name, but may also be a folder, or contain\n#'   the name and access credentials of a database); in case of GeoJSON,\n#'   \\code{dsn} may be the character string holding the geojson data. It can\n#'   also be an open database connection.\n#' @param layer layer name (varies by driver, may be a file name without\n#'   extension); in case \\code{layer} is missing, \\code{st_read} will read the\n#'   first layer of \\code{dsn}, give a warning and (unless \\code{quiet = TRUE})\n#'   print a message when there are multiple layers, or give an error if there\n#'   are no layers in \\code{dsn}. If \\code{dsn} is a database connection, then\n#'   \\code{layer} can be a table name or a database identifier (see\n#'   \\code{\\link[DBI]{Id}}). It is also possible to omit \\code{layer} and rather\n#'   use the \\code{query} argument.\n#' @param ... parameter(s) passed on to \\link{st_as_sf}\n#' @param options character; driver dependent dataset open options, multiple\n#'   options supported. For possible values, see the \"Open options\" section\n#'   of the GDAL documentation of the corresponding driver, and\n#'   <https://github.com/r-spatial/sf/issues/1157> for an example.\n#' @param quiet logical; suppress info on name, driver, size and spatial\n#'   reference, or signaling no or multiple layers\n#' @param geometry_column integer or character; in case of multiple geometry\n#'   fields, which one to take?\n#' @param type integer; ISO number of desired simple feature type; see details.\n#'   If left zero, and \\code{promote_to_multi} is \\code{TRUE}, in case of mixed\n#'   feature geometry types, conversion to the highest numeric type value found\n#'   will be attempted. A vector with different values for each geometry column\n#'   can be given.\n#' @param promote_to_multi logical; in case of a mix of Point and MultiPoint, or\n#'   of LineString and MultiLineString, or of Polygon and MultiPolygon, convert\n#'   all to the Multi variety; defaults to \\code{TRUE}\n#' @param stringsAsFactors logical; should character vectors be\n#'   converted to factors?  Default for \\code{read_sf} or R version >= 4.1.0 is\n#' \\code{FALSE}, for \\code{st_read} and R version < 4.1.0 equal to\n#' \\code{default.stringsAsFactors()}\n#' @param int64_as_string logical; if `TRUE`, Int64 attributes are returned as\n#'   string; if `FALSE`, they are returned as double and a warning is given when\n#'   precision is lost (i.e., values are larger than 2^53).\n#' @param check_ring_dir logical; if `TRUE`, polygon ring directions are checked\n#'   and if necessary corrected (when seen from above: exterior ring counter\n#'   clockwise, holes clockwise)\n#' @details for \\code{geometry_column}, see also\n#' \\url{https://gdal.org/en/latest/development/rfc/rfc41_multiple_geometry_fields.html}\n#'\n#' for values for \\code{type} see\n#' \\url{https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry#Well-known_binary}, \n#' but note that not every target value may lead to successful conversion. The\n#' typical conversion from POLYGON (3) to MULTIPOLYGON (6) should work; the\n#' other way around (type=3), secondary rings from MULTIPOLYGONS may be dropped\n#' without warnings. \\code{promote_to_multi} is handled on a per-geometry column\n#' basis; \\code{type} may be specified for each geometry column.\n#'\n#' Note that stray files in data source directories (such as \\code{*.dbf}) may\n#' lead to spurious errors that accompanying \\code{*.shp} are missing.\n#'\n#' In case of problems reading shapefiles from USB drives on OSX, please see\n#' \\url{https://github.com/r-spatial/sf/issues/252}. Reading shapefiles (or other\n#' data sources) directly from zip files can be done by prepending the path \n#' with \\code{/vsizip/}. This is part of the GDAL Virtual File Systems interface\n#' that also supports .gz, curl, and other operations, including chaining; see\n#' \\url{https://gdal.org/en/latest/user/virtual_file_systems.html} for a complete\n#' description and examples.\n#'\n#' For \\code{query} with a character \\code{dsn} the query text is handed to\n#' 'ExecuteSQL' on the GDAL/OGR data set and will result in the creation of a\n#' new layer (and \\code{layer} is ignored). See 'OGRSQL'\n#' \\url{https://gdal.org/en/latest/user/ogr_sql_dialect.html} for details. Please note that the\n#' 'FID' special field is driver-dependent, and may be either 0-based (e.g. ESRI\n#' Shapefile), 1-based (e.g. MapInfo) or arbitrary (e.g. OSM). Other features of\n#' OGRSQL are also likely to be driver dependent. The available layer names may\n#' be obtained with\n#' \\link{st_layers}. Care will be required to properly escape the use of some layer names.\n#'\n#' @return object of class \\link{sf} when a layer was successfully read; in case\n#'   argument \\code{layer} is missing and data source \\code{dsn} does not\n#'   contain a single layer, an object of class \\code{sf_layers} is returned\n#'   with the layer names, each with their geometry type(s). Note that the\n#'   number of layers may also be zero.\n#' @seealso \\link{st_layers}, \\link{st_drivers}\n#' @examples\n#' nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\n#' summary(nc) # note that AREA was computed using Euclidian area on lon/lat degrees\n#'\n#' ## only three fields by select clause\n#' ## only two features by where clause\n#' nc_sql = st_read(system.file(\"shape/nc.shp\", package=\"sf\"),\n#'                      query = \"SELECT NAME, SID74, FIPS FROM \\\"nc\\\" WHERE BIR74 > 20000\")\n#' \\dontrun{\n#'   library(sp)\n#'   example(meuse, ask = FALSE, echo = FALSE)\n#'   try(st_write(st_as_sf(meuse), \"PG:dbname=postgis\", \"meuse\",\n#'        layer_options = \"OVERWRITE=true\"))\n#'   try(st_meuse <- st_read(\"PG:dbname=postgis\", \"meuse\"))\n#'   if (exists(\"st_meuse\"))\n#'     summary(st_meuse)\n#' }\n#'\n#' \\dontrun{\n#' ## note that we need special escaping of layer  within single quotes (nc.gpkg)\n#' ## and that geom needs to be included in the select, otherwise we don't detect it\n#' layer <- st_layers(system.file(\"gpkg/nc.gpkg\", package = \"sf\"))$name[1]\n#' nc_gpkg_sql = st_read(system.file(\"gpkg/nc.gpkg\", package = \"sf\"),\n#'    query = sprintf(\"SELECT NAME, SID74, FIPS, geom  FROM \\\"%s\\\" WHERE BIR74 > 20000\", layer))\n#' }\n#' # spatial filter, as wkt:\n#' wkt = st_as_text(st_geometry(nc[1,]))\n#' # filter by (bbox overlaps of) first feature geometry:\n#' st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), wkt_filter = wkt)\n#' @export\nst_read = function(dsn, layer, ...) UseMethod(\"st_read\")\n\n#' @export\nst_read.default = function(dsn, layer, ...) {\n\tif (missing(dsn))\n\t\tstop(\"dsn should specify a data source or filename\")\n\telse {\n\t\tdsn_is_null = is.null(dsn)\n\t\tclass_dsn = class(dsn)\n\t\ttr <- try(dsn <- as.character(dsn))\n\t\tif (dsn_is_null || inherits(tr, \"try-error\"))\n\t\t\tstop(paste(\"no st_read method available for objects of class\", paste(class_dsn, collapse = \", \")))\n\t\telse\n\t\t\tst_read.character(dsn, layer, ...)\n\t}\n}\n\nprocess_cpl_read_ogr = function(x, quiet = FALSE, ..., check_ring_dir = FALSE,\n\t\tstringsAsFactors = ifelse(as_tibble, FALSE, sf_stringsAsFactors()),\n\t\tgeometry_column = 1, as_tibble = FALSE, optional = FALSE) {\n\n\twhich.geom = which(vapply(x, function(f) inherits(f, \"sfc\"), TRUE))\n\n\tif (as_tibble && !requireNamespace(\"tibble\", quietly = TRUE))\n\t\tstop(\"package tibble not available: install first?\")\n\n\t# in case no geometry is present:\n\tif (length(which.geom) == 0) {\n\t\tif (! quiet)\n\t\t\twarning(\"no simple feature geometries present: returning a data.frame or tbl_df\", call. = FALSE)\n\t\tx = if (!as_tibble) {\n\t\t\t\tif (any(sapply(x, is.list)))\n\t\t\t\t\twarning(\"list-column(s) present: in case of failure, try read_sf() or as_tibble=TRUE\") # nocov\n\t\t\t\tas.data.frame(x , stringsAsFactors = stringsAsFactors, optional = optional)\n\t\t\t} else\n\t\t\t\ttibble::as_tibble(x)\n\t\treturn(x)\n\t}\n\n\tnm = names(x)[which.geom]\n\tEncoding(nm) = \"UTF-8\"\n\tgeom = x[which.geom]\n\n\tlc.other = setdiff(which(vapply(x, is.list, TRUE)), which.geom) # non-sfc list-columns\n\tlist.cols = x[lc.other]\n\tnm.lc = names(x)[lc.other]\n\n\tif (length(x) == length(geom)) { # ONLY geometry column(s)\n\t\tif (as_tibble)\n\t\t\tx <- tibble::tibble(row.names = seq_along(geom[[1]]))[-1]\n\t\telse\n\t\t\tx <- data.frame(row.names = seq_along(geom[[1]]))\n\t} else {\n\t\tx <- as.data.frame(set_utf8(x[-c(lc.other, which.geom)]), stringsAsFactors = stringsAsFactors,\n\t\t\toptional = optional || as_tibble)\n\t\tif (as_tibble) {\n\t\t\t# \"sf\" class is added later by `st_as_sf` (and sets all the attributes)\n\t\t\tx <- tibble::new_tibble(x, nrow = nrow(x))\n\t\t}\n\t}\n\n\tfor (i in seq_along(lc.other))\n\t\tx[[ nm.lc[i] ]] = list.cols[[i]]\n\n\tfor (i in seq_along(geom)) {\n\t\tif (is.null(attr(geom[[i]], \"bbox\"))) {\n\t\t\tx[[ nm[i] ]] = st_sfc(geom[[i]], crs = attr(geom[[i]], \"crs\")) # computes bbox\n\t\t} else {\n\t\t\tx[[ nm[i] ]] = geom[[i]]\n\t\t}\n\t}\n\n\tx = st_as_sf(x, ...,\n\t\tsf_column_name = if (is.character(geometry_column)) geometry_column else nm[geometry_column],\n\t\tcheck_ring_dir = check_ring_dir)\n\tif (! quiet)\n\t\tprint(x, n = 0)\n\telse\n\t\tx\n}\n\n# Allow setting the default to TRUE to make it easier to run existing tests\n# of st_read() through the stream interface\ndefault_st_read_use_stream = function() {\n\tgetOption(\n\t\t\"sf.st_read_use_stream\",\n\t\tidentical(Sys.getenv(\"R_SF_ST_READ_USE_STREAM\"), \"true\")\n\t)\n}\n\nprocess_cpl_read_ogr_stream = function(x, geom_column_info, num_features, fid_column_name,\n                                       crs = NULL, promote_to_multi = TRUE, ...) {\n\tis_geometry_column = vapply(\n\t\tx$get_schema()$children,\n\t\tfunction(s) identical(s$metadata[[\"ARROW:extension:name\"]], \"ogc.wkb\"),\n\t\tlogical(1)\n\t)\n    \n    geom_column_info$index = which(is_geometry_column)\n    \n    if (num_features == -1) {\n\t\tnum_features = NULL\n\t}\n    \n    # Suppress warnings about extension type conversion (since we want the\n    # default behaviour of converting the storage type)\n\tdf = suppressWarnings(nanoarrow::convert_array_stream(x, size = num_features))\n\t\n\tfor (i in seq_len(nrow(geom_column_info))) {\n\t\tcrs = if (is.null(crs)) st_crs(geom_column_info$crs[[i]]) else st_crs(crs)\n\t\tname = geom_column_info$name[[i]]\n\t\tindex = geom_column_info$index[[i]]\n\t\t\n\t\tcolumn_wkb = df[[index]]\n\t\tattributes(column_wkb) = NULL\n\t\tcolumn_sfc = wk::wk_handle(\n\t\t\twk::new_wk_wkb(column_wkb),\n\t\t\twk::sfc_writer(promote_multi = promote_to_multi)\n\t\t)\n\t\t\n\t\tdf[[index]] = st_set_crs(column_sfc, crs)\n\t\tnames(df)[index] = name\n\t}\n\t\n\t# Rename OGC_FID to fid_column_name and move to end\n\tif (length(fid_column_name) == 1 && \"OGC_FID\" %in% names(df)) {\n\t\tdf = df[c(setdiff(names(df), \"OGC_FID\"), \"OGC_FID\")]\n\t\tnames(df)[names(df) == \"OGC_FID\"] = fid_column_name\n\t}\n\t\n\t# All geometry columns to the end\n\tdf = df[c(setdiff(seq_along(df), geom_column_info$index), geom_column_info$index)]\n\t\n\tprocess_cpl_read_ogr(df, ...)\n}\n\n#' @name st_read\n#' @param fid_column_name character; name of column to write feature IDs to; defaults to not doing this\n#' @param drivers character; limited set of driver short names to be tried (default: try all)\n#' @param wkt_filter character; WKT representation of a spatial filter (may be used as bounding box, selecting overlapping geometries); see examples\n#' @param optional logical; passed to \\link[base]{as.data.frame}; always \\code{TRUE} when \\code{as_tibble} is \\code{TRUE}\n#' @param use_stream Use `TRUE` to use the experimental columnar interface introduced in GDAL 3.6.\n#' @note The use of \\code{system.file} in examples make sure that examples run regardless where R is installed:\n#' typical users will not use \\code{system.file} but give the file name directly, either with full path or relative\n#' to the current working directory (see \\link{getwd}). \"Shapefiles\" consist of several files with the same basename\n#' that reside in the same directory, only one of them having extension \\code{.shp}.\n#' @export\nst_read.character = function(dsn, layer, ..., query = NA, options = NULL, quiet = FALSE, geometry_column = 1L,\n\t\ttype = 0, promote_to_multi = TRUE, stringsAsFactors = sf_stringsAsFactors(),\n\t\tint64_as_string = FALSE, check_ring_dir = FALSE, fid_column_name = character(0),\n\t\tdrivers = character(0), wkt_filter = character(0), optional = FALSE,\n\t\tuse_stream = default_st_read_use_stream()) {\n\n\tlayer = if (missing(layer))\n\t\tcharacter(0)\n\telse\n\t\tenc2utf8(layer)\n\tif (nchar(dsn) < 1)\n\t\tstop(\"`dsn` must point to a source, not an empty string.\", call. = FALSE)\n\tdsn_exists = file.exists(dsn)\n\tdsn_isdb = is_db_driver(dsn)\n\tif (length(dsn) == 1 && dsn_exists && !dsn_isdb)\n\t\tdsn = enc2utf8(normalizePath(dsn))\n\n\tif (length(promote_to_multi) > 1)\n\t\tstop(\"`promote_to_multi' should have length one, and applies to all geometry columns\")\n\n\tif (use_stream) {\n\t\tstream = nanoarrow::nanoarrow_allocate_array_stream()\n\t\tinfo = CPL_read_gdal_stream(stream, dsn, layer, query, as.character(options), quiet,\n\t\t    drivers, wkt_filter, dsn_exists, dsn_isdb, fid_column_name, getOption(\"width\"))\n\t\tgeom_column_info = data.frame(name = info[[1]], crs = info[[2]], stringsAsFactors = FALSE)\n\t\tprocess_cpl_read_ogr_stream(stream, geom_column_info, num_features = info[[3]],\n\t\t\tfid_column_name = fid_column_name, stringsAsFactors = stringsAsFactors, quiet = quiet,\n\t\t\tpromote_to_multi = promote_to_multi, ...)\n\t} else {\n\t\tx = CPL_read_ogr(dsn, layer, query, as.character(options), quiet, type, fid_column_name,\n\t\t    drivers, wkt_filter, promote_to_multi, int64_as_string, dsn_exists, dsn_isdb, getOption(\"width\"))\n\n        process_cpl_read_ogr(x, quiet, check_ring_dir = check_ring_dir,\n\t\t\tstringsAsFactors = stringsAsFactors, geometry_column = geometry_column,\n\t\t\toptional = optional, ...)\n\t}\n}\n\n#' @name st_read\n#' @export\n#' @details \\code{read_sf} and \\code{write_sf} are aliases for \\code{st_read} and \\code{st_write}, respectively, with some\n#' modified default arguments.\n#' \\code{read_sf} and \\code{write_sf} are quiet by default: they do not print information\n#' about the data source. \\code{read_sf} returns an sf-tibble rather than an sf-data.frame.\n#' \\code{write_sf} delete layers by default: it overwrites existing files without asking or warning.\n#' @examples\n#' # read geojson from string:\n#' geojson_txt <- paste(\"{\\\"type\\\":\\\"MultiPoint\\\",\\\"coordinates\\\":\",\n#'    \"[[3.2,4],[3,4.6],[3.8,4.4],[3.5,3.8],[3.4,3.6],[3.9,4.5]]}\")\n#' x = st_read(geojson_txt)\n#' x\nread_sf <- function(..., quiet = TRUE, stringsAsFactors = FALSE, as_tibble = TRUE) {\n\tst_read(..., quiet = quiet, stringsAsFactors = stringsAsFactors, as_tibble = as_tibble)\n}\n\nclean_columns = function(obj, factorsAsCharacter) {\n\tpermitted = c(\"character\", \"integer\", \"numeric\", \"Date\", \"POSIXct\", \"logical\", \"list\")\n\tfor (i in seq_along(obj)) {\n\t\tif (is.factor(obj[[i]])) {\n\t\t\tobj[[i]] = if (factorsAsCharacter)\n\t\t\t\t\tas.character(obj[[i]])\n\t\t\t\telse\n\t\t\t\t\tas.numeric(obj[[i]])\n\t\t}\n\t\tif (! inherits(obj[[i]], permitted)) {\n\t\t\tif (inherits(obj[[i]], \"POSIXlt\"))\n\t\t\t\tobj[[i]] = as.POSIXct(obj[[i]])\n\t\t\telse if (is.numeric(obj[[i]]))\n\t\t\t\tobj[[i]] = as.numeric(obj[[i]]) # strips class\n\t\t}\n\t\tif (is.character(obj[[i]]))\n\t\t\tobj[[i]] = enc2utf8(obj[[i]])\n\t}\n\tccls.ok = vapply(obj, function(x) inherits(x, permitted), TRUE)\n\tif (any(!ccls.ok)) {\n\t\t# nocov start\n                nms <- names(obj)[!ccls.ok]\n                cls <- sapply(obj, function(x) paste(class(x), collapse=\";\"))[!ccls.ok]\n                warning(\"Dropping column(s) \", paste(nms, collapse=\",\"),\n                    \" of class(es) \", paste(cls, collapse=\",\"))\n\t\tobj = obj[ccls.ok]\n\t\t# nocov end\n\t}\n\tcolclasses = vapply(obj, function(x) permitted[ which(inherits(x, permitted, which = TRUE) > 0)[1] ] , \"\")\n\t# check that list columns contain raw vectors:\n\tfor (lc in which(colclasses == \"list\")) {\n\t\tif (!all(sapply(obj[[lc]], inherits, \"raw\")))\n\t\t\tstop(\"list columns are only allowed with raw vector contents\")\n\t}\n\tstructure(obj, colclasses = colclasses)\n}\n\nabbreviate_shapefile_names = function(x) {\n# from: rgdal/pkg/R/ogr_write.R:\n    fld_names <- names(x)\n#   if (!is.null(encoding)) {\n#       fld_names <- iconv(fld_names, from=encoding, to=\"UTF-8\")\n#   }\n\tif (any(nchar(fld_names) > 10)) {\n\t\tfld_names <- abbreviate(fld_names, minlength = 7)\n\t\twarning(\"Field names abbreviated for ESRI Shapefile driver\")\n\t\tif (any(nchar(fld_names) > 10))\n\t\t\tfld_names <- abbreviate(fld_names, minlength = 5) # nocov\n\t}\n# fix for dots in DBF field names 121124\n\tif (length(wh. <- grep(\"\\\\.\", fld_names) > 0))\n\t\tfld_names[wh.] <- gsub(\"\\\\.\", \"_\", fld_names[wh.])\n\n\tif (anyDuplicated(fld_names))\n\t\tstop(\"Non-unique field names\") # nocov\n\n\tnames(x) = fld_names\n\tx\n}\n\n#' Write simple features object to file or database\n#'\n#' Write simple features object to file or database\n#' @param obj object of class \\code{sf} or \\code{sfc}\n#' @param dsn data source name. Interpretation varies by driver: can be\n#'   a filename, a folder, a database name, or a Database Connection\n#'   (we officially test support for\n#'   \\code{\\link[RPostgres:Postgres]{RPostgres::Postgres()}} connections).\n#' @param layer layer name. Varies by driver, may be a file name without\n#'   extension; for database connection, it is the name of the table. If layer\n#'   is missing, the \\code{basename} of \\code{dsn} is taken.\n#' @param driver character; name of driver to be used; if missing and \\code{dsn} is not a Database Connection, a driver name is guessed from \\code{dsn};\n#' \\code{st_drivers()} returns the drivers that are available with their properties; links to full driver documentation\n#' are found at \\url{https://gdal.org/en/latest/drivers/vector/index.html}\n#' @param ... other arguments passed to \\link[DBI]{dbWriteTable} when \\code{dsn} is a\n#' Database Connection\n#' @param dataset_options character; driver dependent dataset creation options;\n#' multiple options supported.\n#' @param layer_options character; driver dependent layer creation options;\n#' multiple options supported.\n#' @param quiet logical; suppress info on name, driver, size and spatial\n#'   reference\n#' @param factorsAsCharacter logical; convert \\code{factor} levels to character\n#'   strings (\\code{TRUE}, default), otherwise into numbers when\n#'   factorsAsCharacter is \\code{FALSE}. For database connections,\n#'   \\code{factorsAsCharacter} is always \\code{TRUE}.\n#' @param append logical; should we append to an existing layer, or replace it?\n#' if \\code{TRUE} append, if \\code{FALSE} replace.\n#' The default for \\code{st_write} is \\code{NA} which raises an error if the layer exists.\n#' The default for \\code{write_sf} is \\code{FALSE}, which overwrites any existing data.\n#' See also next two arguments for more control on overwrite behavior.\n#' @param delete_dsn logical; delete data source \\code{dsn} before attempting\n#' to write?\n#' @param delete_layer logical; delete layer \\code{layer} before attempting to\n#' write?\n#' The default for \\code{st_write} is \\code{FALSE} which raises an error if the layer exists.\n#' The default for \\code{write_sf} is \\code{TRUE}.\n#' @param fid_column_name character, name of column with feature IDs; if\n#' specified, this column is no longer written as feature attribute.\n#' @param config_options character, named vector with GDAL config options\n#' @details\n#' Columns (variables) of a class not supported are dropped with a warning.\n#'\n#' When updating an existing layer, records are appended to it if the updating\n#' object has the right variable names and types. If names don't match an\n#' error is raised. If types don't match, behaviour is undefined: GDAL may\n#' raise warnings or errors or fail silently.\n#'\n#' When deleting layers or data sources is not successful, no error is emitted.\n#' \\code{delete_dsn} and \\code{delete_layer} should be\n#' handled with care; the former may erase complete directories or databases.\n#' @seealso \\link{st_drivers}, \\link[DBI]{dbWriteTable}\n#' @return \\code{obj}, invisibly\n#' @examples\n#' nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\n#' st_write(nc, paste0(tempdir(), \"/\", \"nc.shp\"))\n#' st_write(nc, paste0(tempdir(), \"/\", \"nc.shp\"), delete_layer = TRUE) # overwrites\n#' if (require(sp, quietly = TRUE)) {\n#'  data(meuse, package = \"sp\") # loads data.frame from sp\n#'  meuse_sf = st_as_sf(meuse, coords = c(\"x\", \"y\"), crs = 28992)\n#'  # writes X and Y as columns:\n#'  st_write(meuse_sf, paste0(tempdir(), \"/\", \"meuse.csv\"), layer_options = \"GEOMETRY=AS_XY\")\n#'  st_write(meuse_sf, paste0(tempdir(), \"/\", \"meuse.csv\"), layer_options = \"GEOMETRY=AS_WKT\",\n#'    delete_dsn=TRUE) # overwrites\n#' \\dontrun{\n#'  library(sp)\n#'  example(meuse, ask = FALSE, echo = FALSE)\n#'  try(st_write(st_as_sf(meuse), \"PG:dbname=postgis\", \"meuse_sf\",\n#'      layer_options = c(\"OVERWRITE=yes\", \"LAUNDER=true\")))\n#'  demo(nc, ask = FALSE)\n#'  try(st_write(nc, \"PG:dbname=postgis\", \"sids\", layer_options = \"OVERWRITE=true\"))\n#' }\n#' }\n#' @export\nst_write = function(obj, dsn, layer, ...) UseMethod(\"st_write\")\n\n#' @name st_write\n#' @export\nst_write.sfc = function(obj, dsn, layer, ...) {\n\tif (missing(layer))\n\t\tst_write.sf(st_sf(geom = obj), dsn, ...)\n\telse\n\t\tst_write.sf(st_sf(geom = obj), dsn, layer, ...)\n\tinvisible(obj)\n}\n\n#' @name st_write\n#' @export\nst_write.sf = function(obj, dsn, layer = NULL, ...,\n\t\tdriver = guess_driver_can_write(dsn),\n\t\tdataset_options = NULL, layer_options = NULL, quiet = FALSE, factorsAsCharacter = TRUE,\n\t\tappend = NA, delete_dsn = FALSE, delete_layer = !is.na(append) && !append,\n\t\tfid_column_name = NULL, config_options = character(0)) {\n\n\treturn_obj = ret = obj\n\tif (!is.null(list(...)$update)) {\n\t\t.Deprecated(\"append\", old = \"update\") # deprecated at 0.9-0\n\t\tif (is.na(append))\n\t\t\tappend = list(...)$update\n\t}\n#\telse if (length(list(...)))\n#\t\tstop(paste(\"unrecognized argument(s)\", names(list(...)), \"\\n\"))\n\tif (missing(dsn))\n\t\tstop(\"dsn should specify a data source or filename\")\n\tif (inherits(dsn, c(\"DBIObject\", \"PostgreSQLConnection\", \"Pool\"))) {\n\t\tif (inherits(dsn, \"Pool\")) {\n\t\t\tif (! requireNamespace(\"pool\", quietly = TRUE)) # nocov start\n\t\t\t\tstop(\"package pool required, please install it first\")\n\t\t\tdsn = pool::poolCheckout(dsn)\n\t\t\ton.exit(pool::poolReturn(dsn)) # nocov end\n\t\t}\n\n\t\tif (is.null(layer)) {\n\t\t\tlayer = deparse(substitute(obj))\n\t\t}\n\n\t\tif (is.na(append)) {\n\t\t\tappend = FALSE\n\t\t}\n\n\t\t# check arguments\n\t\tcl <- as.list(match.call())[-1L]\n\t\tif (\"overwrite\" %in% names(cl)) {\n\t\t\tstop(\"Argument `overwrite` in `st_write()` is deprecated, use `delete_layer` instead.\", call. = FALSE)\n\t\t}\n\n\t\tcheck_append_delete(append, delete_layer)\n\t\tdbWriteTable(dsn, name = layer, value = obj,\n\t\t\t\t\t append = append, overwrite = delete_layer,\n\t\t\t\t\t factorsAsCharacter = factorsAsCharacter, ...)\n\t\treturn(invisible(return_obj))\n\t} else if (!inherits(dsn, \"character\")) { # add methods for other dsn classes here...\n\t\tstop(paste(\"no st_write method available for dsn of class\", class(dsn)[1]))\n\t}\n\n\tif (!is.na(append) && append == FALSE && delete_layer == FALSE)\n\t\tstop(\"cannot replace a layer if delete_layer is FALSE\")\n\n\tif (is.null(layer))\n\t\tlayer <- file_path_sans_ext(basename(dsn))\n\n\tif (length(dsn) == 1 && length(grep(\"~\", dsn)) == 1) # resolve ~\n\t\tdsn = normalizePath(dsn, mustWork = FALSE) # nocov\n\n\t# this seems to be always a good idea:\n\tdsn = enc2utf8(dsn)\n\n\t# handle the case where obj does not have a geometry column:\n\tif (write_geometries <- inherits(obj, \"sf\")) {\n\t\tgeom = st_geometry(obj)\n\t\tobj[[attr(obj, \"sf_column\")]] = NULL\n\t\tif (is.na(st_crs(geom))) {\n\t\t\tmessage('writing: substituting ENGCRS[\"Undefined Cartesian SRS with unknown unit\"] for missing CRS')\n\t\t\tst_crs(geom) = st_crs(\"ENGCRS[\\\"Undefined Cartesian SRS with unknown unit\\\",EDATUM[\\\"Unknown engineering datum\\\"],CS[Cartesian,2],AXIS[\\\"X\\\",unspecified,ORDER[1],LENGTHUNIT[\\\"unknown\\\",0]],AXIS[\\\"Y\\\",unspecified,ORDER[2],LENGTHUNIT[\\\"unknown\\\",0]]]\")\n\t\t}\n\t} else { # create fake geometries:\n\t\tv = vector(\"list\", nrow(obj))\n\t\tv[seq_len(nrow(obj))] = list(st_point())\n\t\tgeom = st_sfc(v)\n\t}\n\n\tif (driver == \"ESRI Shapefile\") { # remove trailing .shp from layer name\n\t\tlayer = sub(\".shp$\", \"\", layer)\n\t\tobj = abbreviate_shapefile_names(obj)\n\t}\n\n\tobj = clean_columns(as.data.frame(obj), factorsAsCharacter)\n\t# this attaches attr colclasses\n\n\tnames(obj) = enc2utf8(names(obj))\n\n\tdim = if (length(geom) == 0)\n\t\t\t\"XY\"\n\t\telse\n\t\t\tclass(geom[[1]])[1]\n\n\tfids = if (!is.null(fid_column_name)) {\n\t\t\tfids = as.character(obj[[fid_column_name]])\n\t\t\tobj[[fid_column_name]] = NULL\n\t\t\tfids\n\t\t} else\n\t\t\tcharacter(0)\n\n\tret = CPL_write_ogr(obj, dsn, layer, driver,\n\t\tas.character(dataset_options), as.character(layer_options),\n\t\tgeom, dim, fids, config_options, quiet, append, delete_dsn, delete_layer,\n\t\twrite_geometries, getOption(\"width\"))\n\tif (ret == 1) { # try through temp file:\n\t\ttmp = tempfile(fileext = paste0(\".\", tools::file_ext(dsn))) # nocov start\n\t\tif (!quiet)\n\t\t\tmessage(paste(\"writing first to temporary file\", tmp))\n\t\tif (CPL_write_ogr(obj, tmp, layer, driver,\n\t\t\t\tas.character(dataset_options), as.character(layer_options),\n\t\t\t\tgeom, dim, fids, config_options, quiet, append, delete_dsn, delete_layer,\n\t\t\t\twrite_geometries, getOption(\"width\")) == 1)\n\t\t\tstop(paste(\"failed writing to temporary file\", tmp))\n\t\tif (!file.copy(tmp, dsn, overwrite = append || delete_dsn || delete_layer))\n\t\t\tstop(paste(\"copying\", tmp, \"to\", dsn, \"failed\"))\n\t\tif (!file.remove(tmp))\n\t\t\twarning(paste(\"removing\", tmp, \"failed\"))\n\t} # nocov end\n\tinvisible(return_obj)\n}\n\n#' @name st_write\n#' @export\nst_write.data.frame <- function(obj, dsn, layer = NULL, ...) {\n\tsf = try(st_as_sf(obj), silent = TRUE)\n\tif (!inherits(sf, \"try-error\"))\n\t\tst_write.sf(sf, dsn = dsn, layer = layer, ...)\n\telse\n\t\tst_write.sf(obj, dsn = dsn, layer = layer, ...)\n\tinvisible(obj)\n}\n\n#' @name st_write\n#' @export\nwrite_sf <- function(..., quiet = TRUE, append = FALSE, delete_layer = !append) {\n\tst_write(..., quiet = quiet, append = append, delete_layer = delete_layer)\n}\n\n#' Get GDAL drivers\n#'\n#' Get a list of the available GDAL drivers\n#' @param what character: `\"vector\"` or `\"raster\"`, anything else will return all\n#'   drivers.\n#' @param regex character; regular expression to filter the `name` and `long_name`\n#'  fields on\n#' @details The drivers available will depend on the installation of GDAL/OGR,\n#'   and can vary; the `st_drivers()` function shows all the drivers that are\n#'   readable, and which may be written. The field `vsi` refers to the driver's\n#'   capability to read/create datasets through the VSI*L API. [See GDAL website\n#'   for additional details on driver\n#'   support](https://gdal.org/en/latest/drivers/vector/index.html)\n#' @return A `data.frame` with driver metadata.\n#' @export\n#' @md\n#' @examples\n#' # The following driver lists depend on the GDAL setup and platform used:\n#' st_drivers()\n#' st_drivers(\"raster\", \"GeoT\")\nst_drivers = function(what = \"vector\", regex) {\n\tret = CPL_get_gdal_drivers(0)\n\trow.names(ret) = ret$name\n\tret = switch(what,\n\t\tvector = ret[ret$is_vector,],\n\t\traster = ret[ret$is_raster,],\n\t\tret)\n\tif (missing(regex))\n\t\tret\n\telse {\n\t\tfn = function(x, pattern) any(grepl(x, pattern = pattern))\n\t\tret[apply(ret[c(\"name\", \"long_name\")], 1, fn, pattern = regex), ]\n\t}\n}\n\n#' @export\nprint.sf_layers = function(x, ...) {\n\tn_gt = max(sapply(x$geomtype, length))\n\tx$geomtype = vapply(x$geomtype, function(x) paste(x, collapse = \", \"), \"\")\n\tcat(paste(\"Driver:\", x$driver, \"\\n\"))\n\tx$driver = NULL\n\tx$features[x$features < 0] = NA\n\tcat(\"Available layers:\\n\")\n\tif (length(x$name) == 0) {\n\t\tcat(\"<none>\\n\") # nocov\n\t\tinvisible(x)    # nocov\n\t} else {\n\t\tcrs = sapply(x$crs, function(crs) crs$input)\n\t\tx$crs = crs\n\t\tdf = data.frame(unclass(x))\n\t\tgt = if (n_gt > 1)\n\t\t\t\t\"geometry_types\"\n\t\t\telse\n\t\t\t\t\"geometry_type\"\n\t\tnames(df) = c(\"layer_name\", gt, \"features\", \"fields\", \"crs_name\")\n\t\tprint(df)\n\t\tinvisible(df)\n\t}\n}\n\n#' Return properties of layers in a datasource\n#'\n#' Return properties of layers in a datasource\n#' @param dsn data source name (interpretation varies by driver - for some drivers, \\code{dsn} is a file name, but may also be a\n#' folder, or contain the name and access credentials of a database)\n#' @param options character; driver dependent dataset open options, multiple options supported.\n#' @param do_count logical; if TRUE, count the features by reading them, even if their count is not reported by the driver\n#' @name st_layers\n#' @return list object of class \\code{sf_layers} with elements\n#' \\describe{\n#'   \\item{name}{name of the layer}\n#'   \\item{geomtype}{list with for each layer the geometry types}\n#'   \\item{features}{number of features (if reported; see \\code{do_count})}\n#'   \\item{fields}{number of fields}\n#'   \\item{crs}{list with for each layer the \\code{crs} object}\n#' }\n#' @export\nst_layers = function(dsn, options = character(0), do_count = FALSE) {\n\tif (missing(dsn))\n\t\tstop(\"dsn should specify a data source or filename\")\n\tif (length(dsn) == 1 && file.exists(dsn))\n\t\tdsn = enc2utf8(normalizePath(dsn))\n\tret = CPL_get_layers(dsn, options, do_count)\n\tif (length(ret[[1]]) > 0) {\n\t\tEncoding(ret[[1]]) <- \"UTF-8\"\n\t\tret[[1]] <- enc2native(ret[[1]])\n\t}\n\tstructure(ret, row.names = seq_along(ret[[1]]), class = c(\"sf_layers\", \"data.frame\"))\n}\n\nguess_driver = function(dsn) {\n  stopifnot(is.character(dsn))\n  stopifnot(length(dsn) == 1)\n\n\t# find match: try extension first\n\tdrv = extension_map[tolower(tools::file_ext(dsn))]\n\tif (is_db_driver(dsn))\n\t\tdrv = prefix_map[tolower(strsplit(dsn, \":\")[[1]][1])]\n\n\tdrv <- unlist(drv)\n\n\tif (is.null(drv)) {\n\t  # no match\n\t  return(NA)\n\t}\n\tdrv\n}\n\nis_db_driver = function(dsn) {\n\tany(grep(\":\", gsub(\":[/\\\\]\", \"/\", dsn)))\n}\n\nguess_driver_can_write = function(dns, drv = guess_driver(dns)) {\n  if(is.na(drv)) {\n    stop(\"Could not guess driver for \", dns, call. = FALSE)\n  }\n  if(!is_driver_available(drv)) {\n    stop(unlist(drv), \" driver not available in supported drivers, see `st_drivers()'\", call. = FALSE)\n  }\n  if(!is_driver_can(drv, operation = \"write\")) {\n    stop(\"Driver \", drv, \" cannot write. see `st_drivers()'\", call. = FALSE)\n  }\n  return(drv)\n}\n\n#' Check if driver is available\n#'\n#' Search through the driver table if driver is listed\n#' @param drv character. Name of driver\n#' @param drivers data.frame. Table containing driver names and support. Default\n#' is from \\code{\\link{st_drivers}}\nis_driver_available = function(drv, drivers = st_drivers()) {\n  i = match(drv, drivers$name)\n  if (is.na(i))\n    return(FALSE)\n\n  return(TRUE)\n}\n\n#' Check if a driver can perform an action\n#'\n#' Search through the driver table to match a driver name with\n#' an action (e.g. \\code{\"write\"}) and check if the action is supported.\n#' @param drv character. Name of driver\n#' @param drivers data.frame. Table containing driver names and support. Default\n#' is from \\code{\\link{st_drivers}}\n#' @param operation character. What action to check\nis_driver_can = function(drv, drivers = st_drivers(), operation = \"write\") {\n  stopifnot(operation %in% names(drivers))\n  i = match(drv, drivers$name)\n  if (!drivers[i, operation])\n    return(FALSE)\n\n  return(TRUE)\n}\n\n#' Map extension to driver\n#' @docType data\nextension_map <- list(\n        \"bna\" = \"BNA\",\n        \"csv\" = \"CSV\",\n        \"e00\" = \"AVCE00\",\n        \"fgb\" = \"FlatGeobuf\",\n        \"gdb\" = \"OpenFileGDB\",\n        \"geojson\" = \"GeoJSON\",\n        \"gml\" = \"GML\",\n        \"gmt\" = \"GMT\",\n        \"gpkg\" = \"GPKG\",\n        \"gps\" = \"GPSBabel\",\n        \"gpx\" = \"GPX\",\n        \"gtm\" = \"GPSTrackMaker\",\n        \"gxt\" = \"Geoconcept\",\n        \"jml\" = \"JML\",\n        \"kml\" = \"KML\",\n        \"map\" = \"WAsP\",\n        \"mdb\" = \"Geomedia\",\n        \"nc\" = \"netCDF\",\n        \"ods\" = \"ODS\",\n        \"osm\" = \"OSM\",\n        \"pbf\" = \"OSM\",\n        \"shp\" = \"ESRI Shapefile\",\n        \"sqlite\" = \"SQLite\",\n        \"vdv\" = \"VDV\",\n        \"xls\" = \"xls\",\n        \"xlsx\" = \"XLSX\")\n\n#' Map prefix to driver\n#' @docType data\nprefix_map <- list(\n        \"couchdb\" = \"CouchDB\",\n        \"db2odbc\" = \"DB2ODBC\",\n        \"dods\" = \"DODS\",\n        \"gft\" = \"GFT\",\n        \"mssql\" = \"MSSQLSpatial\",\n        \"mysql\" = \"MySQL\",\n        \"oci\" = \"OCI\",\n        \"odbc\" = \"ODBC\",\n        \"pg\" = \"PostgreSQL\",\n        \"sde\" = \"SDE\")\n\n#' Drivers for which update should be \\code{TRUE} by default\n#' @docType data\ndb_drivers <- c(unlist(prefix_map), \"GPKG\", \"SQLite\")\n\n# Utils ----------------------------------------------------------------------\ncheck_append_delete <- function(append, delete) {\n\tif (append && delete) {\n\t\tstop(\"`delete_layer` and `append` cannot both be `TRUE`\", call. = FALSE)\n\t}\n}\n\n#' @name st_write\n#' @export\n#' @details `st_delete()` deletes layer(s) in a data source, or a data source if layers are\n#' omitted; it returns `TRUE` on success, `FALSE` on failure, invisibly.\nst_delete = function(dsn, layer = character(0), driver = guess_driver_can_write(dsn), quiet = FALSE) {\n\tinvisible(CPL_delete_ogr(dsn, layer, driver, quiet) == 0)\n}\n"
  },
  {
    "path": "R/s2.R",
    "content": "# see https://docs.google.com/presentation/d/1Hl4KapfAENAOf4gv-pSngKwvS_jwNVHRPZTTDzXXn6Q/view?pli=1#slide=id.i0\n# and the r-spatial/s2 package:\n# https://github.com/r-spatial/s2\n\n#' @export\n#' @param ... passed on\n#' @param use_s2 logical; if \\code{TRUE}, use the s2 spherical geometry package\n#' for geographical coordinate operations\n#' @name s2\n#' @return \\code{sf_use_s2} returns the value of this variable before (re)setting it,\n#' invisibly if \\code{use_s2} is not missing.\nsf_use_s2 = function(use_s2) {\n\tret_val = getOption(\"sf_use_s2\", default = TRUE)\n\tif (! missing(use_s2)) {\n\t\tstopifnot(is.logical(use_s2), length(use_s2)==1, !is.na(use_s2))\n\t\tif (ret_val != use_s2)\n\t\t\tmessage(paste0(\"Spherical geometry (s2) switched \", ifelse(use_s2, \"on\", \"off\")))\n\t\toptions(sf_use_s2 = use_s2)\n\t\tinvisible(ret_val)\n\t} else\n\t\tret_val\n}\n\n#' @name st_as_sfc\n#' @export\n#' @param crs coordinate reference system to be assigned; object of class \\code{crs}\n#' @param endian integer; 0 or 1: defaults to the endian of the native machine\nst_as_sfc.s2_geography = function(x, ..., crs = st_crs(4326),\n\t\tendian = match(.Platform$endian, c(\"big\", \"little\")) - 1L) {\n\tst_cast(st_as_sfc(s2::s2_as_binary(x, endian = endian), ..., crs = crs))\n}\n\n#' @name st_as_sf\n#' @param crs coordinate reference system to be assigned; object of class \\code{crs}\n#' @export\nst_as_sf.s2_geography = function(x, ..., crs = st_crs(4326)) {\n\tst_sf(geometry = st_as_sfc(x, ..., crs = crs))\n}\n\n# dynamically exported in tidyverse.R\nas_s2_geography.sfg <- function(x, ..., oriented = getOption(\"s2_oriented\", FALSE)) {\n\tb = structure(list(st_as_binary(x)), class = \"WKB\")\n\ts2::as_s2_geography(b, ..., oriented = oriented)\n}\n\n# dynamically exported in tidyverse.R\nas_s2_geography.sfc <- function(x, ..., oriented = getOption(\"s2_oriented\", FALSE) || isTRUE(attr(x, \"oriented\"))) {\n\tst_as_s2.sfc(x, ..., oriented = oriented)\n}\n\n# dynamically exported in tidyverse.R\nas_s2_geography.sf <- function(x, ...) {\n\tst_as_s2.sf(x, ...)\n}\n\n#' functions for spherical geometry, using s2 package\n#'\n#' functions for spherical geometry, using the s2 package based on the google s2geometry.io library\n#' @name s2\n#' @param x object of class \\code{sf}, \\code{sfc} or \\code{sfg}\n#' @export\n#' @details \\code{st_as_s2} converts an \\code{sf} POLYGON object into a form readable by \\code{s2}.\n#' @examples\n#' m = rbind(c(-1,-1), c(1,-1), c(1,1), c(-1,1), c(-1,-1))\n#' m1 = rbind(c(-1,-1), c(1,-1), c(1,1), c(-1,1), c(-1,0), c(-1,-1))\n#' m0 = m[5:1,]\n#' mp = st_multipolygon(list(\n#'\tlist(m, 0.8 * m0, 0.01 * m1 + 0.9),\n#'\tlist(0.7* m, 0.6*m0),\n#'\tlist(0.5 * m0),\n#'\tlist(m+2),\n#'\tlist(m+4,(.9*m0)+4)\n#'\t))\n#' sf = st_sfc(mp, mp, crs = 'EPSG:4326')\n#' s2 = st_as_s2(sf)\nst_as_s2 = function(x, ...) UseMethod(\"st_as_s2\")\n\n#' @name s2\n#' @export\nst_as_s2.sf = function(x, ...) st_as_s2(st_geometry(x), ...)\n\n#' @name s2\n#' @param oriented logical; if \\code{FALSE}, polygons that\n#' cover more than half of the globe are inverted; if \\code{TRUE}, no reversal\n#' takes place and it is assumed that the inside of the polygon is to the\n#' left of the polygon's path.\n#' @param rebuild logical; call \\link[s2]{s2_rebuild} on the geometry (think of this as a \\code{st_make_valid} on the sphere)\n#' @export\nst_as_s2.sfc = function(x, ..., oriented = getOption(\"s2_oriented\", FALSE) || isTRUE(attr(x, \"oriented\")), \n\t\t\t\t\t\trebuild = FALSE) {\n\tif (!is.na(st_crs(x)) && !st_is_longlat(x))\n\t\tx = st_transform(x, ifelse(st_axis_order(), \"OGC:CRS84\", \"EPSG:4326\"))\n\tif (length(x) && nchar(class(x[[1]])[1]) > 2) { # Z, M, ZM:\n\t\tmessage(\"st_as_s2(): dropping Z and/or M coordinate\")\n\t\tx = st_zm(x)\n\t}\n\tif (rebuild)\n\t\ts2::s2_rebuild(s2::as_s2_geography(st_as_binary(x), ..., oriented = oriented, check = FALSE))\n\telse\n\t\ts2::as_s2_geography(st_as_binary(x), ..., oriented = oriented)\n}\n"
  },
  {
    "path": "R/sample.R",
    "content": "#' @export\n#' @name st_sample\nst_sample = function(x, size, ...) UseMethod(\"st_sample\")\n\n#' sample points on or in (sets of) spatial features\n#'\n#' Sample points on or in (sets of) spatial features.\n#' By default, returns a pre-specified number of points that is equal to\n#' \\code{size} (if \\code{type = \"random\"} and \\code{exact = TRUE}) or an approximation of\n#' \\code{size} otherwise. \\code{spatstat} methods are\n#' interfaced and do not use the \\code{size} argument, see examples.\n#'\n#' The function is vectorised: it samples \\code{size} points across all geometries in\n#' the object if \\code{size} is a single number, or the specified number of points\n#' in each feature if \\code{size} is a vector of integers equal in length to the geometry\n#' of \\code{x}.\n#'\n#' @param x object of class \\code{sf} or \\code{sfc}\n#' @param size sample size(s) requested; either total size, or a numeric vector with sample sizes for each feature geometry. When sampling polygons, the returned sampling size may differ from the requested size, as the bounding box is sampled, and sampled points intersecting the polygon are returned.\n#' @param warn_if_not_integer logical; if \\code{FALSE} then no warning is emitted if \\code{size} is not an integer\n#' @param ... passed on to \\link[base]{sample} for \\code{multipoint} sampling, or to \\code{spatstat} functions for spatstat sampling types (see details)\n#' @param type character; indicates the spatial sampling type; one of \\code{random}, \\code{hexagonal} (triangular really), \\code{regular}, \\code{Fibonacci},\n#' or one of the \\code{spatstat} methods such as \\code{Thomas} for calling \\code{spatstat.random::rThomas} (see Details).\n#' @param exact logical; should the length of output be exactly\n#' @param by_polygon logical; for \\code{MULTIPOLYGON} geometries, should the effort be split by \\code{POLYGON}? See https://github.com/r-spatial/sf/issues/1480\n#' the same as specified by \\code{size}? \\code{TRUE} by default. Only applies to polygons, and\n#' when \\code{type = \"random\"}.\n#' @param progress logical; if \\code{TRUE} show progress bar (only if \\code{size} is a vector).\n#' @param force logical; if `TRUE` continue when the sampled bounding box area is more than 1e4 times the area of interest, else (default) stop with an error. If this error is not justified, try setting `oriented=TRUE`, see details.\n#' @return an \\code{sfc} object containing the sampled \\code{POINT} geometries\n#' @details if \\code{x} has dimension 2 (polygons) and geographical coordinates (long/lat), uniform random sampling on the sphere is applied, see e.g. \\url{https://mathworld.wolfram.com/SpherePointPicking.html}. \n#'\n#' For \\code{regular} or \\code{hexagonal} sampling of polygons, the resulting size is only an approximation.\n#'\n#' As parameter called \\code{offset} can be passed to control (\"fix\") regular or hexagonal sampling: for polygons a length 2 numeric vector (by default: a random point from \\code{st_bbox(x)}); for lines use a number like \\code{runif(1)}.\n#' \n#' Fibonacci sampling see: Alvaro Gonzalez, 2010. Measurement of Areas on a Sphere Using Fibonacci and Latitude-Longitude Lattices. \n#' Mathematical Geosciences 42(1), p. 49-64\n#' \n#' For regular sampling on the sphere, see also \\code{geosphere::regularCoordinates}.\n#'\n#' Sampling methods from package \\code{spatstat} are interfaced (see examples), and need their own parameters to be set. \n#' For instance, to use \\code{spatstat.random::rThomas()}, set \\code{type = \"Thomas\"}.\n#' \n#' For sampling polygons one can specify `oriented=TRUE` to make sure that polygons larger than half the globe are not reverted, e.g. when specifying a polygon from a bounding box of a global dataset. The `st_sample` method for `bbox` does this by default.\n#' @examples\n#' nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\n#' p1 = st_sample(nc[1:3, ], 6)\n#' p2 = st_sample(nc[1:3, ], 1:3)\n#' plot(st_geometry(nc)[1:3])\n#' plot(p1, add = TRUE)\n#' plot(p2, add = TRUE, pch = 2)\n#' x = st_sfc(st_polygon(list(rbind(c(0,0),c(90,0),c(90,90),c(0,90),c(0,0)))), crs = st_crs(4326))\n#' plot(x, axes = TRUE, graticule = TRUE)\n#' if (compareVersion(sf_extSoftVersion()[\"proj.4\"], \"4.9.0\") >= 0)\n#'   plot(p <- st_sample(x, 1000), add = TRUE)\n#' if (require(lwgeom, quietly = TRUE)) { # for st_segmentize()\n#'   x2 = st_transform(st_segmentize(x, 1e4), st_crs(\"+proj=ortho +lat_0=30 +lon_0=45\"))\n#'   g = st_transform(st_graticule(), st_crs(\"+proj=ortho +lat_0=30 +lon_0=45\"))\n#'   plot(x2, graticule = g)\n#'   if (compareVersion(sf_extSoftVersion()[\"proj.4\"], \"4.9.0\") >= 0) {\n#'     p2 = st_transform(p, st_crs(\"+proj=ortho +lat_0=30 +lon_0=45\"))\n#'     plot(p2, add = TRUE)\n#'   }\n#' }\n#' x = st_sfc(st_polygon(list(rbind(c(0,0),c(90,0),c(90,10),c(0,90),c(0,0))))) # NOT long/lat:\n#' plot(x)\n#' p_exact = st_sample(x, 1000, exact = TRUE)\n#' p_not_exact = st_sample(x, 1000, exact = FALSE)\n#' length(p_exact); length(p_not_exact)\n#' plot(st_sample(x, 1000), add = TRUE)\n#' x = st_sfc(st_polygon(list(rbind(c(-180,-90),c(180,-90),c(180,90),c(-180,90),c(-180,-90)))),\n#'\t crs=st_crs(4326))\n#' # FIXME:\n#' #if (compareVersion(sf_extSoftVersion()[\"proj.4\"], \"4.9.0\") >= 0) {\n#' #  p = st_sample(x, 1000)\n#' #  st_sample(p, 3)\n#' #}\n#' # hexagonal:\n#' sfc = st_sfc(st_polygon(list(rbind(c(0,0), c(1,0), c(1,1), c(0,0)))))\n#' plot(sfc)\n#' h = st_sample(sfc, 100, type = \"hexagonal\")\n#' h1 = st_sample(sfc, 100, type = \"hexagonal\")\n#' plot(h, add = TRUE)\n#' plot(h1, col = 'red', add = TRUE)\n#' c(length(h), length(h1)) # approximate!\n#' pt = st_multipoint(matrix(1:20,,2))\n#' ls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))),\n#'  st_linestring(rbind(c(0,0),c(.1,0))),\n#'  st_linestring(rbind(c(0,1),c(.1,1))),\n#'  st_linestring(rbind(c(2,2),c(2,2.00001))))\n#' st_sample(ls, 80)\n#' plot(st_sample(ls, 80))\n#' # spatstat example:\n#' if (require(spatstat.random)) {\n#'   x <- sf::st_sfc(sf::st_polygon(list(rbind(c(0, 0), c(10, 0), c(10, 10), c(0, 0)))))\n#'   # for spatstat.random::rThomas(), set type = \"Thomas\":\n#'   pts <- st_sample(x, kappa = 1, mu = 10, scale = 0.1, type = \"Thomas\") \n#' }\n#' @export\n#' @name st_sample\nst_sample.sf = function(x, size, ...) st_sample(st_geometry(x), size, ...)\n\n#' @export\n#' @name st_sample\nst_sample.sfc = function(x, size, ..., type = \"random\", exact = TRUE, warn_if_not_integer = TRUE,\n\t\tby_polygon = FALSE, progress = FALSE, force = FALSE) {\n\n\tif (!missing(size) && warn_if_not_integer && any(size %% 1 != 0))\n\t\twarning(\"size is not an integer\")\n\tif (!missing(size) && length(size) > 1) { # recurse:\n\t\tsize = rep(size, length.out = length(x))\n\t\tret = if (progress) {\n\t\t\t\tif (!requireNamespace(\"pbapply\", quietly = TRUE))\n\t\t\t\t\tstop(\"package pbapply required, please install it first\")\n\t\t\t\tpbapply::pblapply(seq_along(x), function(i) st_sample(x[i], size[i], type = type, exact = exact, ...))\n\t\t\t} else\n\t\t\t\tlapply(seq_along(x), function(i) st_sample(x[i], size[i], type = type, exact = exact, ...))\n\t\tst_set_crs(do.call(c, ret), st_crs(x))\n\t} else {\n\t\tres = switch(max(st_dimension(x)) + 1,\n\t\t\t\t\t st_multipoints_sample(do.call(c, x), size = size, ..., type = type),\n\t\t\t\t\t st_ll_sample(st_cast(x, \"LINESTRING\"), size = size, ..., type = type),\n\t\t\t\t\t st_poly_sample(x, size = size, ..., type = type, by_polygon = by_polygon, force = force))\n\t\tif (exact && type == \"random\" && all(st_geometry_type(res) == \"POINT\")) {\n\t\t\tdiff = size - length(res)\n\t\t\tif (diff > 0) { # too few points\n\t\t\t\tres_additional = st_sample_exact(x = x, size = diff, ..., \n\t\t\t\t\ttype = type, by_polygon = by_polygon)\n\t\t\t\tres = c(res, res_additional)\n\t\t\t} else if (diff < 0) { # too many points\n\t\t\t\tres = res[1:size]\n\t\t\t}\n\t\t}\n\t\tres\n\t}\n}\n\n#' @export\n#' @name st_sample\nst_sample.sfg = function(x, size, ...) {\n\tst_sample(st_geometry(x), size, ...)\n}\n\n#' @export\n#' @name st_sample\n#' @param great_circles logical; if `TRUE`, great circle arcs are used to connect the bounding box vertices, if `FALSE` parallels (graticules)\n#' @param segments units, or numeric (degrees); segment sizes for segmenting a bounding box polygon if `great_circles` is `FALSE`\n#' @examples\n#' bbox = st_bbox(\n#'\tc(xmin = 0, xmax = 40, ymax = 70, ymin = 60),\n#' \tcrs = st_crs('OGC:CRS84')\n#' )\n#' set.seed(13531)\n#' s1 = st_sample(bbox, 400)\n#' st_bbox(s1) # within bbox\n#' s2 = st_sample(bbox, 400, great_circles = TRUE)\n#' st_bbox(s2) # outside bbox\nst_sample.bbox = function(x, size, ..., great_circles = FALSE, segments = units::set_units(2, \"degree\", mode = \"standard\")) {\n\tpolygon = st_as_sfc(x)\n\tcrs = st_crs(x)\n\tif (isTRUE(st_is_longlat(x)) && !great_circles) {\n\t\tst_crs(polygon) = NA_crs_ # to fool segmentize that we're on R2:\n\t\tsegments = units::drop_units(units::set_units(segments, \"degree\", mode = \"standard\"))\n\t\tpolygon = st_set_crs(st_segmentize(polygon, segments), crs)\n\t}\n\tst_sample(polygon, size, ..., oriented = TRUE)\n}\n\nst_poly_sample = function(x, size, ..., type = \"random\",\n\t\t\t\t\t\toffset = st_sample(st_as_sfc(st_bbox(x)), 1)[[1]],\n\t\t\t\t\t\tby_polygon = FALSE, oriented = FALSE, force = FALSE) {\n\n\tif (by_polygon && inherits(x, \"sfc_MULTIPOLYGON\")) { # recurse into polygons:\n\t\tsum_a = units::drop_units(sum(st_area(x)))\n\t\tx = lapply(suppressWarnings(st_cast(st_geometry(x), \"POLYGON\")), st_sfc, crs = st_crs(x))\n\t\ta = sapply(x, st_area)\n\t\tret = mapply(st_poly_sample, x, size = size * a / sum_a, type = type, ...)\n\t\tdo.call(c, ret)\n\t} else if (type %in% c(\"hexagonal\", \"regular\", \"random\", \"Fibonacci\")) {\n\n\t\tif (isTRUE(st_is_longlat(x))) {\n\t\t\tif (type == \"regular\") {\n\t\t\t\tmessage_longlat(\"st_sample\")\n\t\t\t\tx = st_set_crs(x, NA)\n\t\t\t}\n\t\t\tif (type == \"hexagonal\")\n\t\t\t\tstop(\"hexagonal sampling on geographic coordinates not supported; consider projecting first\")\n\t\t} else if (type == \"Fibonacci\")\n\t\t\tstop(\"Fibonacci sampling requires geographic (longlat) coordinates\")\n\t\t\n\t\tglobal = FALSE\n\t\tbb = st_bbox(x)\n\t\tif (isTRUE(st_is_longlat(x))) {\n\t\t\tif (sf_use_s2()) { # if FALSE, the user wants the coord ranges to be the bbox\n\t\t\t\tif (!requireNamespace(\"lwgeom\", quietly = TRUE))\n\t\t\t\t\twarning(\"coordinate ranges not computed along great circles; install package lwgeom to get rid of this warning\")\n\t\t\t\telse {\n\t\t\t\t\t# see https://github.com/r-spatial/sf/issues/2331\n\t\t\t\t\t# bb = st_bbox(st_segmentize(st_as_sfc(bb),\n\t\t\t\t\t#\t\tunits::set_units(1, \"degree\", mode = \"standard\"))) # get coordinate range on S2\n\t\t\t\t\tdfMaxLength = units::set_units(100000, \"m\", mode = \"standard\")\n\t\t\t\t\tif (! is.na(st_crs(x)))\n\t\t\t\t\t\tunits(dfMaxLength) = units(st_crs(x)$SemiMajor) # might convert\n\t\t\t\t\tseg = st_sfc(CPL_gdal_segmentize(x, dfMaxLength), crs = st_crs(x)) # avoid lwgeom path\n\t\t\t\t\tbb = st_bbox(seg)\n\t\t\t\t}\n\t\t\t}\n\t\t\tR = s2::s2_earth_radius_meters()\n\t\t\tearth_surface = 4 * pi * R^2.\n\t\t\ttoRad = pi / 180.\n\t\t\th1 = sin(bb[\"ymax\"] * toRad)\n\t\t\th2 = sin(bb[\"ymin\"] * toRad)\n\t\t\ta0 = 2 * pi * R^2. * (h1 - h2) * (bb[\"xmax\"] - bb[\"xmin\"]) / 360. # total\n\t\t\ta1 = sum(s2::s2_area(st_as_s2(x, oriented = oriented))) # actual\n\t\t\tif (!is.finite(a1))\n\t\t\t\tstop(\"One or more geometries have a non-finite area\")\n\t\t\tglobal = (a0 / earth_surface) > .9999\n\t\t\tif (a0 / a1 > 1e4 && !force)\n\t\t\t\tstop(paste0(\"sampling box is \", format(a0/a1), \" times larger than sampling region;\\nuse force=TRUE if you really want this, or try setting oriented=TRUE\\n(after reading the documentation)\"), call. = FALSE)\n\t\t\tsize = round(size * a0 / a1)\n\t\t} else {\n\t\t\ta0 = as.numeric(st_area(st_as_sfc(bb))) # total\n\t\t\ta1 = as.numeric(sum(st_area(x))) # actual\n\t\t\t# we're sampling from a box, so n should be size_desired * a0 / a1\n\t\t\tif (is.finite(a0) && is.finite(a1) && a0 > a0 * 0.0 && a1 > a1 * 0.0) { # FIXME: reqs can be removed, now we handle long/lat separately?\n\t\t\t\tr = size * a0 / a1\n\t\t\t\tsize = if (round(r) == 0)\n\t\t\t\t\t\trbinom(1, 1, r)\n\t\t\t\t\telse\n\t\t\t\t\t\tround(r)\n\t\t\t}\n\t\t}\n\t\tsize = max(1, size)\n\n\t\tpts = if (type == \"hexagonal\") {\n\t\t\t\tdx = sqrt(a0 / size / (sqrt(3)/2))\n\t\t\t\thex_grid_points(x, pt = offset, dx = dx)\n\t\t\t} else if (type == \"regular\") {\n\t\t\t\tdx = as.numeric(sqrt(a0 / size))\n\t\t\t\toffset = c((offset[1] - bb[\"xmin\"]) %% dx,\n\t\t\t\t\t(offset[2] - bb[\"ymin\"]) %% dx) + bb[c(\"xmin\", \"ymin\")]\n\t\t\t\tn = c(round((bb[\"xmax\"] - offset[1])/dx), round((bb[\"ymax\"] - offset[2])/dx))\n\t\t\t\tst_make_grid(x, cellsize = c(dx, dx), offset = offset, n = n, what = \"corners\")\n\t\t\t} else { \n\t\t\t\tm = if (type == \"random\") {\n\t\t\t\t\t\tlon = runif(size, bb[1], bb[3])\n\t\t\t\t\t\tlat = if (isTRUE(st_is_longlat(x))) { # sampling on the sphere:\n\t\t\t\t\t\t\ttoRad = pi/180\n\t\t\t\t\t\t\tlat0 = (sin(bb[2] * toRad) + 1)/2\n\t\t\t\t\t\t\tlat1 = (sin(bb[4] * toRad) + 1)/2\n\t\t\t\t\t\t\ty = runif(size, lat0, lat1)\n\t\t\t\t\t\t\tasin(2 * y - 1) / toRad # http://mathworld.wolfram.com/SpherePointPicking.html\n\t\t\t\t\t\t} else\n\t\t\t\t\t\t\trunif(size, bb[2], bb[4])\n\t\t\t\t\t\tstructure(cbind(lon, lat), dimnames = NULL)\n\t\t\t\t\t} else if (type == \"Fibonacci\")\n\t\t\t\t\t\tfiboGrid(size %/% 2, bb[c(\"xmin\", \"xmax\")], bb[c(\"ymin\", \"ymax\")])\n\t\t\t\t\telse\n\t\t\t\t\t\tstop(\"unknown value for type\")\n\t\t\t\t# st_sfc(lapply(seq_len(nrow(m)), function(i) st_point(m[i,])), crs = st_crs(x))\n\t\t\t\tst_as_sf(as.data.frame(m), coords = 1:2, crs = st_crs(x))[[\"geometry\"]]\n\t\t\t}\n\t\tif (global)\n\t\t\tpts\n\t\telse\n\t\t\tpts[x] # cut out x from bbox\n\t} else { # try to go into spatstat\n\t\tif (!requireNamespace(\"spatstat.random\", quietly = TRUE))\n\t\t\tstop(\"package spatstat.random required, please install it (or the full spatstat package) first\")\n\t\tspatstat_fun = try(get(paste0(\"r\", type), asNamespace(\"spatstat.random\")), silent = TRUE)\n\t\tif (inherits(spatstat_fun, \"try-error\"))\n\t\t\tstop(paste0(\"r\", type), \" is not an exported function from spatstat.random.\")\n\t\tpts = if (\"win\" %in% names(as.list(args(spatstat_fun))))\n\t\t\t\ttry(spatstat_fun(..., win = spatstat.geom::as.owin(x)), silent = TRUE)\n\t\t\telse\n\t\t\t\ttry(spatstat_fun(..., W = spatstat.geom::as.owin(x)), silent = TRUE)\n\t\tif (inherits(pts, \"try-error\"))\n\t\t\tstop(\"The spatstat function \", paste0(\"r\", type),\n\t\t\t\t\" did not return a valid result. Consult the help file.\\n\",\n\t\t\t\t\"Error message from spatstat:\\n\", pts)\n\t\tst_as_sf(pts)[-1,]\n\t}\n}\n\nst_multipoints_sample = function(x, size, ..., type = \"random\") {\n\tif (!inherits(x, \"MULTIPOINT\"))\n\t\tstop(\"points sampling only implemented for MULTIPOINT; use sample to sample individual features\", call.=FALSE)\n\tm = unclass(x)\n\tst_sfc(st_multipoint(m[sample(nrow(m), size, ...),]), crs = st_crs(x))\n}\n\nst_ll_sample = function(x, size, ..., type = \"random\", offset = runif(1)) {\n\tcrs = st_crs(x)\n\tif (isTRUE(st_is_longlat(x))) {\n\t\tmessage_longlat(\"st_sample\")\n\t\tst_crs(x) = NA_crs_\n\t}\n\tl = st_length(x)\n\tif (inherits(l, \"units\"))\n\t\tl = drop_units(l)\n\tif (type == \"random\") {\n\t\td = runif(size, 0, sum(l))\n\t} else if (type == \"regular\") {\n\t\td = ((1:size) - (1. - (offset %% 1)))/size * sum(l)\n\t} else {\n\t\tstop(paste(\"sampling type\", type, \"not available for LINESTRING\")) # nocov\n\t}\n\tlcs = c(0, cumsum(l))\n\tif (sum(l) == 0) {\n\t\tgrp = list(0) # nocov\n\t\twarning(\"line is of length zero, only one point is sampled\") # nocov\n\t} else {\n\t\tgrp = split(d, cut(d, lcs, include.lowest = TRUE))\n\t\tgrp = lapply(seq_along(x), function(i) grp[[i]] - lcs[i])\n\t}\n\tst_sfc(CPL_gdal_linestring_sample(x, grp), crs = crs)\n}\n\n### return points on a triangular grid that\n## - covers a bounding box st_bbox(obj)\n## - contains pt\n## - has x spacing dx: the shortest distance between x coordinates with identical y coordinate\nhex_grid_points = function(obj, pt, dx) {\n\n\tbb = st_bbox(obj)\n\tdy = sqrt(3) * dx / 2\n\txlim = bb[c(\"xmin\", \"xmax\")]\n\tylim = bb[c(\"ymin\", \"ymax\")]\n\toffset = c(x = (pt[1] - xlim[1]) %% dx, y = (pt[2] - ylim[1]) %% (2 * dy))\n\tx = seq(xlim[1] - dx, xlim[2] + dx, dx) + offset[1]\n\ty = seq(ylim[1] - 2 * dy, ylim[2] + 2 * dy, dy) + offset[2]\n\n\ty = rep(y, each = length(x))\n\tx = rep(c(x, x + dx / 2), length.out = length(y))\n\txy = cbind(x, y)[x >= xlim[1] & x <= xlim[2] & y >= ylim[1] & y <= ylim[2], , drop = FALSE]\n\tcolnames(xy) = NULL\n\tst_sfc(lapply(seq_len(nrow(xy)), function(i) st_point(xy[i,])), crs = st_crs(bb))\n}\n\nfiboGrid <- function(N, xlim = c(-180,180), ylim = c(-90,90)) {\n\tif (max(xlim) <= 180)\n\t\tsubtr = 180\n\telse\n\t\tsubtr = 0\n    phi = (1 + sqrt(5))/2\n    i = seq(-N, N)\n    P = 2 * N + 1\n    lat = asin(2*i / P) * 180 / pi\n    lon = ((2 * pi * i / phi) %% pi) * 360 / pi - subtr\n    sel = lon <= xlim[2] & lon >= xlim[1] & lat <= ylim[2] & lat >= ylim[1]\n    cbind(lon, lat)[sel, ]\n}\n\nst_sample_exact = function(x, size, ..., type, by_polygon) {\n\trandom_pt = st_sample(x = x, size = size, ..., type = type, exact = FALSE)\n\twhile (length(random_pt) < size) {\n\t\tdiff = size - length(random_pt)\n\t\trandom_pt_new = st_sample(x, size = diff, ..., type, exact = FALSE, by_polygon = by_polygon)\n\t\trandom_pt = c(random_pt, random_pt_new)\n\t}\n\tif (length(random_pt) > size) {\n\t\trandom_pt = random_pt[1:size]\n\t}\n\trandom_pt\n}\n"
  },
  {
    "path": "R/sf-package.R",
    "content": "#' @keywords internal\n#' @aliases sf-package\n#' @references \n#' Pebesma, E. and Bivand, R. (2023). Spatial Data\n#'   Science: With Applications in R. Chapman and Hall/CRC.\n#'   \\doi{10.1201/9780429459016} which is also found freely\n#'   online at <https://r-spatial.org/book/>\n#'   \n#' Pebesma, E., 2018. Simple Features for R: Standardized Support\n#'   for Spatial Vector Data. The R Journal 10 (1), 439-446,\n#'   \\doi{10.32614/RJ-2018-009} (open access)\n\"_PACKAGE\"\n"
  },
  {
    "path": "R/sf.R",
    "content": "#' Convert foreign object to an sf object\n#'\n#' Convert foreign object to an sf object\n#' @param x object to be converted into an object class \\code{sf}\n#' @export\nst_as_sf = function(x, ...) UseMethod(\"st_as_sf\")\n\n#' @name st_as_sf\n#'\n#' @param agr character vector; see details section of \\link{st_sf}\n#' @param coords in case of point data: names or numbers of the numeric columns holding coordinates\n#' @param wkt name or number of the character column that holds WKT encoded geometries\n#' @param dim specify what 3- or 4-dimensional points reflect: passed on to \\link{st_point} (only when argument coords is given)\n#' @param remove logical; when coords or wkt is given, remove these columns from data.frame?\n#' @param na.fail logical; if \\code{TRUE}, raise an error if coordinates contain missing values\n#' @param sf_column_name character; name of the active list-column with simple feature geometries; in case\n#' there is more than one and \\code{sf_column_name} is \\code{NULL}, the first one is taken.\n#' @param ... passed on to \\link{st_sf}, might included named arguments \\code{crs} or \\code{precision}\n#' @details setting argument \\code{wkt} annihilates the use of argument \\code{coords}. If \\code{x} contains a column called \"geometry\", \\code{coords} will result in overwriting of this column by the \\link{sfc} geometry list-column.  Setting \\code{wkt} will replace this column with the geometry list-column, unless \\code{remove} is \\code{FALSE}.\n#'\n#' If `coords` has length 4, and `dim` is not `XYZM`, the four columns are taken as the xmin, ymin, xmax, ymax corner coordinates of a rectangle, and polygons are returned.\n#'\n#' @examples\n#' pt1 = st_point(c(0,1))\n#' pt2 = st_point(c(1,1))\n#' st_sfc(pt1, pt2)\n#' d = data.frame(a = 1:2)\n#' d$geom = st_sfc(pt1, pt2)\n#' df = st_as_sf(d)\n#' d$geom = c(\"POINT(0 0)\", \"POINT(0 1)\")\n#' df = st_as_sf(d, wkt = \"geom\")\n#' d$geom2 = st_sfc(pt1, pt2)\n#' st_as_sf(d) # should warn\n#' if (require(sp, quietly = TRUE)) {\n#'  data(meuse, package = \"sp\")\n#'  meuse_sf = st_as_sf(meuse, coords = c(\"x\", \"y\"), crs = 28992, agr = \"constant\")\n#'  meuse_sf[1:3,]\n#'  summary(meuse_sf)\n#' }\n#' @export\nst_as_sf.data.frame = function(x, ..., agr = NA_agr_, coords, wkt,\n\t\tdim = \"XYZ\", remove = TRUE, na.fail = TRUE, sf_column_name = NULL) {\n\tif (! missing(wkt)) {\n\t\tif (remove)\n\t\t\tx[[wkt]] = st_as_sfc(as.character(x[[wkt]]))\n\t\telse\n\t\t\tx$geometry = st_as_sfc(as.character(x[[wkt]]))\n\t} else if (! missing(coords)) {\n\t\tcc = as.matrix(as.data.frame(lapply(x[coords], as.numeric)))\n\t\tanyna = anyNA(cc)\n\t\tif (na.fail && anyna)\n\t\t\tstop(\"missing values in coordinates not allowed\")\n\t\tif (anyna)\n\t\t\tcc[apply(cc, 1, anyNA),] = NA_real_\n\t\t# classdim = getClassDim(rep(0, length(coords)), length(coords), dim, \"POINT\")\n\t\tif (is.null(sf_column_name))\n\t\t\tsf_column_name = \"geometry\"\n\t\tx[[sf_column_name]] = if (nchar(dim) < 4 && ncol(cc) == 4) { # create POLYGONs:\n\t\t\t\tfn = function(x) st_as_sfc(st_bbox(c(xmin = x[[1]], ymin = x[[2]], xmax = x[[3]], ymax = x[[4]])))\n\t\t\t\tdo.call(c, apply(cc, 1, fn))\n\t\t\t} else { # points:\n\t\t\t\tstructure(points_rcpp(cc, dim),\n\t\t\t\t\tn_empty = 0L, precision = 0, crs = NA_crs_,\n\t\t\t\t\tbbox = structure(\n\t\t\t\t\t\tc(xmin = min(cc[,1], na.rm = TRUE),\n\t\t\t\t\t\tymin =   min(cc[,2], na.rm = TRUE),\n\t\t\t\t\t\txmax =   max(cc[,1], na.rm = TRUE),\n\t\t\t\t\t\tymax =   max(cc[,2], na.rm = TRUE)), class = \"bbox\"),\n\t\t\t\t\tclass =  c(\"sfc_POINT\", \"sfc\" ), names = NULL)\n\t\t\t}\n\n\t\tif (remove) {\n\t\t\tif (is.character(coords))\n\t\t\t\tcoords = match(coords, names(x))\n\t\t\tx = x[-coords]\n\t\t}\n\t\tif (length(coords) > 2 && grepl(\"Z\", dim))\n\t\t\tattr(x[[sf_column_name]], \"z_range\") = compute_z_range(x[[sf_column_name]])\n\t\tif (length(coords) > 2 && grepl(\"M\", dim))\n\t\t\tattr(x[[sf_column_name]], \"m_range\") = compute_m_range(x[[sf_column_name]])\n\n\t}\n\tst_sf(x, ..., agr = agr, sf_column_name = sf_column_name)\n}\n\n#' @name st_as_sf\n#' @export\nst_as_sf.sf = function(x, ...) x\n\n#' @name st_as_sf\n#' @export\nst_as_sf.sfc = function(x, ...) st_sf(x, ...)\n\n#' Get, set, replace or rename geometry from an sf object\n#'\n#' Get, set, replace or rename geometry from an sf object\n#' @param obj object of class \\code{sf} or \\code{sfc}\n#' @param ... ignored\n#' @return st_geometry returns an object of class \\link{sfc}, a list-column with geometries\n#' @export\nst_geometry = function(obj, ...) UseMethod(\"st_geometry\")\n\n#' @name st_geometry\n#' @export\nst_geometry.sf = function(obj, ...) {\n\tret =  obj[[attr(obj, \"sf_column\")]]\n\tif (!inherits(ret, \"sfc\")) # corrupt!\n\t\tstop('attr(obj, \"sf_column\") does not point to a geometry column.\\nDid you rename it, without setting st_geometry(obj) <- \"newname\"?')\n\tret\n}\n\n#' @name st_geometry\n#' @export\nst_geometry.sfc = function(obj, ...) obj\n\n#' @name st_geometry\n#' @export\nst_geometry.sfg = function(obj, ...) st_sfc(obj)\n\n#' @name st_geometry\n#' @param x object of class \\code{data.frame} or \\code{sf}\n#' @param value object of class \\code{sfc}, or \\code{character} to set, replace, or rename the geometry of \\code{x}\n#' @export\n#' @return \\code{st_geometry} returns an object of class \\link{sfc}. Assigning geometry to a \\code{data.frame} creates an \\link{sf} object, assigning it to an \\link{sf} object replaces the geometry list-column.\n#' @details when applied to a \\code{data.frame} and when \\code{value} is an object of class \\code{sfc}, \\code{st_set_geometry} and \\code{st_geometry<-} will first check for the existence of an attribute \\code{sf_column} and overwrite that, or else look for list-columns of class \\code{sfc} and overwrite the first of that, or else write the geometry list-column to a column named \\code{geometry}.  In case \\code{value} is character and \\code{x} is of class \\code{sf}, the \"active\" geometry column is set to \\code{x[[value]]}.\n#'\n#' the replacement function applied to \\code{sf} objects will overwrite the geometry list-column, if \\code{value} is \\code{NULL}, it will remove it and coerce \\code{x} to a \\code{data.frame}.\n#' @examples\n#' df = data.frame(a = 1:2)\n#' sfc = st_sfc(st_point(c(3,4)), st_point(c(10,11)))\n#' st_geometry(sfc)\n#' st_geometry(df) <- sfc\n#' class(df)\n#' st_geometry(df)\n#' st_geometry(df) <- sfc # replaces\n#' st_geometry(df) <- NULL # remove geometry, coerce to data.frame\n`st_geometry<-` = function(x, value) UseMethod(\"st_geometry<-\")\n\n#' @export\n`st_geometry<-.data.frame` = function(x, value) {\n\tstopifnot(inherits(value, \"sfc\") || is.character(value))\n\tif (inherits(value, \"sfc\"))\n\t\tstopifnot(nrow(x) == length(value))\n\tif (is.character(value))\n\t\tst_sf(x, sf_column_name = value)\n\telse {\n\t\ta = vapply(x, function(v) inherits(v, \"sfc\"), TRUE)\n\t\tif (any(a)) {\n\t\t\tw = which(a)\n\t\t\tsf_col = attr(x, \"sf_column\")\n\t\t\tif (! is.null(sf_col))\n\t\t\t\tx[[ sf_col ]] = value\n\t\t\telse {\n\t\t\t\tif (length(w) > 1)\n\t\t\t\t\twarning(\"overwriting first sfc column\")\n\t\t\t\tx[[ which(a)[1L] ]] = value\n\t\t\t}\n\t\t} else\n\t\t\tx$geometry = value\n\t\tst_sf(x)\n\t}\n}\n\n\n#' @export\n`st_geometry<-.sf` = function(x, value) {\n\tif (! is.null(value)) {\n\t\tstopifnot(is.character(value) || inherits(value, \"sfc\"))\n\t\tif (inherits(value, \"sfc\"))\n\t\t\tstopifnot(nrow(x) == length(value))\n\t}\n\n\tif (!is.null(value) && is.character(value)) { # set flag to another column:\n\t\tif (!(value %in% names(x)))\n\t\t\tnames(x)[names(x) == attr(x, \"sf_column\")] = value\n\t\tattr(x, \"sf_column\") <- value\n\t} else # replace, remove, or set list-column\n\t\tx[[attr(x, \"sf_column\")]] <- value\n\n\tif (is.null(value))\n\t\tstructure(x, sf_column = NULL, agr = NULL, class = setdiff(class(x), \"sf\"))\n\telse\n\t\tx\n}\n\n#' @name st_geometry\n#' @export\n#' @examples\n#' sf <- st_set_geometry(df, sfc) # set geometry, return sf\n#' st_set_geometry(sf, NULL) # remove geometry, coerce to data.frame\nst_set_geometry = function(x, value) {\n\tst_geometry(x) = value\n\tx\n}\n\n#' @export\nst_as_sfc.sf = function(x, ...) st_geometry(x)\n\nlist_column_to_sfc = function(x) {\n\tif (is.list(x) && !inherits(x, \"data.frame\")) {\n\t\tif (inherits(try(y <- st_as_sfc(x), silent = TRUE), \"try-error\"))\n\t\t\tx\n\t\telse\n\t\t\ty\n\t} else\n\t\tx\n}\n\n#' Create sf object\n#'\n#' Create sf, which extends data.frame-like objects with a simple feature list column.\n#' To convert a data frame object to `sf`, use [st_as_sf()]\n#' @name sf\n#' @aliases st_sf\n#' @param ... column elements to be binded into an \\code{sf} object or a single \\code{list} or \\code{data.frame} with such columns; at least one of these columns shall be a geometry list-column of class \\code{sfc} or be a list-column that can be converted into an \\code{sfc} by \\link{st_as_sfc}.\n#' @param crs coordinate reference system, something suitable as input to \\link{st_crs}\n#' @param agr character vector; see details below.\n#' @param row.names row.names for the created \\code{sf} object\n#' @param stringsAsFactors logical; see \\link{st_read}\n#' @param precision numeric; see \\link{st_as_binary}\n#' @param sf_column_name character; name of the active list-column with simple feature geometries; in case\n#' there is more than one and \\code{sf_column_name} is \\code{NULL}, the first one is taken.\n#' @param sfc_last logical; if \\code{TRUE}, \\code{sfc} columns are always put last, otherwise column order is left unmodified.\n#' @param check_ring_dir see \\link{st_read}\n#' @details \\code{agr}, attribute-geometry-relationship, specifies for each non-geometry attribute column how it relates to the geometry, and can have one of following values: \"constant\", \"aggregate\", \"identity\". \"constant\" is used for attributes that are constant throughout the geometry (e.g. land use), \"aggregate\" where the attribute is an aggregate value over the geometry (e.g. population density or population count), \"identity\" when the attributes uniquely identifies the geometry of particular \"thing\", such as a building ID or a city name. The default value, \\code{NA_agr_}, implies we don't know.\n#'\n#' When a single value is provided to \\code{agr}, it is cascaded across all input columns; otherwise, a named vector like \\code{c(feature1='constant', ...)} will set \\code{agr} value to \\code{'constant'} for the input column named \\code{feature1}. See \\code{demo(nc)} for a worked example of this.\n#'\n#' When confronted with a data.frame-like object, \\code{st_sf} will try to find a geometry column of class \\code{sfc}, and otherwise try to convert list-columns when available into a geometry column, using \\link{st_as_sfc}.\n#' @examples\n#' g = st_sfc(st_point(1:2))\n#' st_sf(a=3,g)\n#' st_sf(g, a=3)\n#' st_sf(a=3, st_sfc(st_point(1:2))) # better to name it!\n#' # create empty structure with preallocated empty geometries:\n#' nrows <- 10\n#' geometry = st_sfc(lapply(1:nrows, function(x) st_geometrycollection()))\n#' df <- st_sf(id = 1:nrows, geometry = geometry)\n#' @export\nst_sf = function(..., agr = NA_agr_, row.names,\n\t\tstringsAsFactors = sf_stringsAsFactors(), crs, precision,\n\t\tsf_column_name = NULL, check_ring_dir = FALSE, sfc_last = TRUE) {\n\tx = list(...)\n\tif (length(x) == 1L && (inherits(x[[1L]], \"data.frame\") || (is.list(x) && !inherits(x[[1L]], \"sfc\"))))\n\t\tx = x[[1L]]\n\n\t# find the sfc column(s):\n\tall_sfc_columns = vapply(x, function(x) inherits(x, \"sfc\"), TRUE)\n\tif (! any(all_sfc_columns)) { # try to create sfc from list-columns:\n\t\txlst = lapply(x, list_column_to_sfc)\n\t\tall_sfc_columns = vapply(xlst, function(x) inherits(x, \"sfc\"), TRUE)\n\t\tif (! any(all_sfc_columns))\n\t\t\tstop(\"no simple features geometry column present\")\n\t\tx[all_sfc_columns] = xlst[all_sfc_columns]\n\t}\n\n\tall_sfc_columns = which(unlist(all_sfc_columns))\n\n\t# set names if not present:\n\tall_sfc_names = if (!is.null(names(x)) && any(nzchar(names(x)[all_sfc_columns])))\n\t\tnames(x)[all_sfc_columns]\n\telse {\n\t\tobject = as.list(substitute(list(...)))[-1L]\n\t\targ_nm = sapply(object, function(x) deparse(x))\n\t\tif (identical(arg_nm, \".\"))\n\t\t\targ_nm = \"geometry\"\n\t\tmake.names(arg_nm[all_sfc_columns])\n\t}\n\n\tif (! is.null(sf_column_name)) {\n\t\tstopifnot(sf_column_name %in% all_sfc_names)\n\t\tsf_column = match(sf_column_name, all_sfc_names)\n\t\tsfc_name = sf_column_name\n\t} else {\n\t\tsf_column = all_sfc_columns[1L]\n\t\tsfc_name = all_sfc_names[1L]\n\t}\n\n\tif (missing(row.names))\n\t\trow.names = seq_along(x[[sf_column]])\n\n\tdf = if (inherits(x, c(\"tbl_df\", \"tbl\"))) # no worries:\n\t\t\tx\n\t\telse if (length(x) == 1) # ONLY one sfc\n\t\t\tdata.frame(row.names = row.names)\n\t\telse if (!sfc_last && inherits(x, \"data.frame\"))\n\t\t\tx\n\t\telse if (sfc_last && inherits(x, \"data.frame\"))\n\t\t\tx[-all_sfc_columns]\n\t\telse if (inherits(x[[1]], c(\"tbl_df\", \"tbl\")))\n\t\t\tx[[1]]\n\t\telse\n\t\t\tcbind(data.frame(row.names = row.names),\n\t\t\t\tas.data.frame(x[-all_sfc_columns],\n\t\t\t\t\tstringsAsFactors = stringsAsFactors, optional = TRUE))\n\n\tif (check_ring_dir) { # process:\n\t\tfor (i in seq_along(all_sfc_names))\n\t\t\tdf[[ all_sfc_names[i] ]] = st_sfc(x[[ all_sfc_columns[i] ]],\n\t\t\t\tcheck_ring_dir = check_ring_dir)\n\t} else { # copy:\n\t\tfor (i in seq_along(all_sfc_names))\n\t\t\tdf[[ all_sfc_names[i] ]] = x[[ all_sfc_columns[i] ]]\n\t}\n\n\tif (! missing(precision))\n\t\tattr(df[[sfc_name]], \"precision\") = precision\n\n\t# add attributes:\n\tattr(df, \"sf_column\") = sfc_name\n\tif (! inherits(df, \"sf\"))\n\t\tclass(df) = c(\"sf\", class(df))\n\tst_agr(df) = agr\n\tif (! missing(crs))\n\t\tst_crs(df) = crs\n\n\tif (Sys.getenv(\"ADD_SF_NAMESPACE\") == \"true\")\n\t\tattr(df, \".sf_namespace\") <- .sf_namespace\n\n\tdf\n}\n\n.sf_namespace <- function() NULL\n\n#' @name sf\n#' @param x object of class \\code{sf}\n#' @param i record selection, see \\link{[.data.frame}, or a \\code{sf} object to work with the \\code{op} argument\n#' @param j variable selection, see \\link{[.data.frame}\n#' @param drop logical, default \\code{FALSE}; if \\code{TRUE} drop the geometry column and return a \\code{data.frame}, else make the geometry sticky and return a \\code{sf} object.\n#' @param op function; geometrical binary predicate function to apply when \\code{i} is a simple feature object\n#' @details \\code{[.sf} will return a \\code{data.frame} or vector if the geometry column (of class \\code{sfc}) is dropped (\\code{drop=TRUE}), an \\code{sfc} object if only the geometry column is selected, and otherwise return an \\code{sf} object; see also \\link{[.data.frame}; for \\code{[.sf} \\code{...} arguments are passed to \\code{op}.\n#' @examples\n#' g = st_sfc(st_point(1:2), st_point(3:4))\n#' s = st_sf(a=3:4, g)\n#' s[1,]\n#' class(s[1,])\n#' s[,1]\n#' class(s[,1])\n#' s[,2]\n#' class(s[,2])\n#' g = st_sf(a=2:3, g)\n#' pol = st_sfc(st_polygon(list(cbind(c(0,3,3,0,0),c(0,0,3,3,0)))))\n#' h = st_sf(r = 5, pol)\n#' g[h,]\n#' h[g,]\n#' @export\n\"[.sf\" = function(x, i, j, ..., drop = FALSE, op = st_intersects) {\n\tnargs = nargs()\n\tagr = st_agr(x)\n\tif (!missing(i) && (inherits(i, \"sf\") || inherits(i, \"sfc\") || inherits(i, \"sfg\")))\n\t\ti = lengths(op(x, i, ...)) != 0\n\tsf_column = attr(x, \"sf_column\")\n\tgeom = st_geometry(x)\n\tif (!missing(i) && nargs > 2) { # e.g. a[3:4,] not a[3:4]\n\t\tif (is.character(i))\n\t\t\ti = match(i, row.names(x))\n\t\tgeom = geom[i]\n\t}\n\n\t# x = as.data.frame(x)\n\tclass(x) = setdiff(class(x), \"sf\") # one step down\n\tx = if (missing(j)) {\n\t\tif (nargs == 2) # `[`(x,i)\n\t\t\tx[i] # do sth else for tbl?\n\t\telse\n\t\t\tx[i, , drop = drop]\n\t} else\n\t\tx[i, j, drop = drop]\n\n\tif (!missing(j))\n\t\tagr = agr[j]\n\telse if (!missing(i) && nargs <= 2)\n\t\tagr = agr[i] # e.g., obj[\"name\"]\n\n\tif (inherits(x, \"sfc\")) # drop was TRUE, and we selected geom column only\n\t\tx\n\telse if (! drop) {\n\t\tx[[ sf_column ]] = geom\n\t\tx = st_sf(x, sf_column_name = sf_column, sfc_last = FALSE)\n\t\tst_set_agr(x, agr[match(setdiff(names(x), sf_column), names(agr))])\n\t} else { \n\t\tif (inherits(x, \"sf\"))\n\t\t\tstructure(x, class = setdiff(class(x), \"sf\"))\n\t\telse\n\t\t\tx\n\t}\n}\n\n#' @export\n\"$<-.sf\" = function(x, i, value) {\n\tif (is.null(value) && inherits(x[[i]], \"sfc\") &&\n\t\t\t((is.character(i) && i == attr(x, \"sf_column\"))\n\t\t\t\t|| (is.integer(i) && names(x)[i] == attr(x, \"sf_column\"))))\n\t\tst_set_geometry(x, NULL)\n\telse {\n\t\tx[[i]] = value\n\t\tx\n\t}\n}\n\n#' @export\n\"[<-.sf\" = function(x, i, j, value) {\n\tst_as_sf(st_set_agr(NextMethod()))\n}\n\n#' @export\n\"[[<-.sf\" = function(x, i, value) {\n\tagr = st_agr(x)\n\tsetting_geom = (i == attr(x, \"sf_column\")) || inherits(value, \"sfc\")\n\tif (! setting_geom) { # need to handle agr:\n\t\tix = if (is.character(i))\n\t\t\t\twhich(i == names(x))\n\t\t\telse\n\t\t\t\ti\n\t\tif (is.null(value)) # remove\n\t\t\tagr = agr[-ix]\n\t\telse {\n\t\t\tif (length(ix) == 0 || ix > length(names(x))) # add:\n\t\t\t\tagr = st_agr(c(as.character(agr), NA_character_))\n\t\t\telse # replace:\n\t\t\t\tagr[ix] = NA\n\t\t}\n\t}\n\tx = structure(NextMethod(), class = c(\"sf\", setdiff(class(x), \"sf\")))\n\tif (! setting_geom)\n\t\tst_agr(x) = agr\n\tx\n}\n\n#' @rdname sf\n#' @param n maximum number of features to print; can be set globally by \\code{options(sf_max_print=...)}\n#' @export\nprint.sf = function(x, ..., n = getOption(\"sf_max_print\", default = 10)) {\n\n\tgeoms = which(vapply(x, function(col) inherits(col, \"sfc\"), TRUE))\n\tnf = length(x) - length(geoms)\n\tapp = paste(\"and\", nf, ifelse(nf == 1, \"field\", \"fields\"))\n\tif (any(!is.na(st_agr(x))))\n\t\tapp = paste0(app, \"\\n\", \"Attribute-geometry relationship\", ifelse(nf > 1, \"s: \", \": \"), summarize_agr(x))\n\tif (length(geoms) > 1)\n\t\tapp = paste0(app, \"\\n\", \"Active geometry column: \", attr(x, \"sf_column\"))\n\tprint(st_geometry(x), n = 0, what = \"Simple feature collection with\", append = app)\n\tif (n > 0) {\n\t\tif (inherits(x, c(\"tbl_df\", \"tbl\")))\n\t\t\tNextMethod()\n\t\telse {\n\t\t\ty <- x\n\t\t\tif (nrow(y) > n) {\n\t\t\t\tcat(paste(\"First\", n, \"features:\\n\"))\n\t\t\t\ty <- x[1:n, , drop = FALSE]\n\t\t\t}\n\t\t\tprint.data.frame(y, ...)\n\t\t}\n\t}\n\tinvisible(x)\n}\n\n#' merge method for sf and data.frame object\n#'\n#' merge method for sf and data.frame object\n#' @param x object of class \\code{sf}\n#' @param y object of class \\code{data.frame}\n#' @param ... arguments passed on to \\code{merge.data.frame}\n#' @export\n#' @examples\n#' a = data.frame(a = 1:3, b = 5:7)\n#' st_geometry(a) = st_sfc(st_point(c(0,0)), st_point(c(1,1)), st_point(c(2,2)))\n#' b = data.frame(x = c(\"a\", \"b\", \"c\"), b = c(2,5,6))\n#' merge(a, b)\n#' merge(a, b, all = TRUE)\nmerge.sf = function(x, y, ...) {\n\tif (inherits(y, \"sf\"))\n\t\tstop(\"merge on two sf objects not supported\")\n\tsf_column = attr(x, \"sf_column\")\n\tret = NextMethod() # if data.table, drops sf_column attribute;\n\tclass(ret) = setdiff(class(ret), \"sf\")\n\tg = ret[[sf_column]] # may have NULL values in it\n\tret[[sf_column]] = st_sfc(g) # fix NULL values\n\tst_set_geometry(ret, sf_column) # FIXME: set agr\n}\n\n#' @export\nas.data.frame.sf = function(x, ...) {\n\tclass(x) <- setdiff(class(x), \"sf\")\n\tNextMethod()\n}\n\n#' @export\nduplicated.sf <- function(x, incomparables = FALSE, fromLast = FALSE, ...) {\n  if (length(x) != 1L) {\n    if (any(i <- vapply(x, is.factor, NA))) {\n      for (j in names(i[i])) {\n        x[[j]] <- lapply(x[[j]], as.numeric)\n      }\n    }\n    if (any(i <- (lengths(lapply(x, dim)) == 2L))) {\n      for (j in names(i[i])) {\n        x[[j]] <- lapply(x[[j]], split.data.frame, seq_len(nrow(x)))\n      }\n    }\n  }\n  NextMethod()\n}\n\n#' @export\n#' @name st_geometry\n#' @details if \\code{x} is of class \\code{sf}, \\code{st_drop_geometry} drops the geometry of its argument, and reclasses it accordingly; otherwise it returns \\code{x} unmodified. \nst_drop_geometry = function(x, ...) UseMethod(\"st_drop_geometry\")\n\n#' @export\n#' @name st_geometry\nst_drop_geometry.sf = function(x, ...) {\n\tst_set_geometry(x, NULL)\n}\n\n#' @export\n#' @name st_geometry\nst_drop_geometry.default = function(x, ...) {\n\tx\n}\n\n#' transform method for sf objects\n#' \n#' Can be used to create or modify attribute variables; for transforming geometries see \n#' \\link{st_transform}, and all other functions starting with \\code{st_}.\n#' \n#' @param _data object of class \\code{sf}\n#' @param ... Further arguments of the form `new_variable = expression`\n#'\n#' @export\n#' @examples\n#' a = data.frame(x1 = 1:3, x2 = 5:7)\n#' st_geometry(a) = st_sfc(st_point(c(0,0)), st_point(c(1,1)), st_point(c(2,2)))\n#' transform(a, x1_sq = x1^2)\n#' transform(a, x1_x2 = x1*x2)\ntransform.sf <- function (`_data`, ...) {\n  st_as_sf(NextMethod(), agr = st_agr(`_data`), sf_column_name = attr(`_data`, \"sf_column\"))\n}\n"
  },
  {
    "path": "R/sfc.R",
    "content": "#' @export\nstr.sfc <- function(object, ...) {\n\tn <- length(object)\n\tcat(paste0(class(object)[1], \" of length \", n))\n\tif (n > 0) {\n\t\tcat(\"; first list element: \")\n\t\tstr(object[[1]], ...)\n\t}\n}\n\n#' @export\nformat.sfc = function(x, ..., width = 30) {\n\tvapply(x, format, \"\", ..., width = width)\n}\n\n#' Create simple feature geometry list column\n#'\n#' Create simple feature geometry list column, set class, and add coordinate reference system and precision.\n#' For data.frame alternatives see [st_sf()]. To convert a foreign object to `sfc`, see [st_as_sfc()]\n#'\n#' @name sfc\n#' @aliases sfc_POINT sfc_LINESTRING sfc_POLYGON sfc_MULTIPOINT sfc_MULTILINESTRING sfc_MULTIPOLYGON sfc_GEOMETRYCOLLECTION\n#' @param ... input: zero or more simple feature geometries (objects of class \\code{sfg}), or a single list of such objects; \\code{NULL} values will get replaced by empty geometries.\n#' @param crs coordinate reference system: integer with the EPSG code, or character with proj4string\n#' @param precision numeric; see \\link{st_as_binary}\n#' @param check_ring_dir see \\link{st_read}\n#' @param dim character; if this function is called without valid geometries, this argument may carry the right dimension to set empty geometries\n#' @param recompute_bbox logical; use \\code{TRUE} to force recomputation of the bounding box\n#' @param oriented logical; if \\code{TRUE}, the ring is oriented such that left of the edges is inside the polygon; this is\n#' needed for convering polygons larger than half the globe to s2\n#' @param fall_back_class character; class for return object when no geometries are provided as input\n#' @return an object of class \\code{sfc}, which is a classed list-column with simple feature geometries.\n#'\n#' @details A simple feature geometry list-column is a list of class\n#' \\code{c(\"stc_TYPE\", \"sfc\")} which most often contains objects of identical type;\n#' in case of a mix of types or an empty set, \\code{TYPE} is set to the\n#' superclass \\code{GEOMETRY}.\n#' @examples\n#' pt1 = st_point(c(0,1))\n#' pt2 = st_point(c(1,1))\n#' (sfc = st_sfc(pt1, pt2))\n#' sfc[sfc[1], op = st_is_within_distance, dist = 0.5]\n#' d = st_sf(data.frame(a=1:2, geom=sfc))\n#' @export\nst_sfc = function(..., crs = NA_crs_, precision = 0.0, check_ring_dir = FALSE, dim,\n\t\t\t\t  recompute_bbox = FALSE, oriented = NA, fall_back_class = c(\"sfc_GEOMETRY\", \"sfc\")) {\n\tlst = list(...)\n\t# if we have only one arg, which is already a list with sfg's, but NOT a geometrycollection:\n\t# (this is the old form of calling st_sfc; it is way faster to call st_sfc(lst) if lst\n\t# already contains a zillion sfg objects, than do.call(st_sfc, lst) ...\n\tif (length(lst) && inherits(lst[[1]], \"sf\"))\n\t\tstop(\"use st_as_sfc() to extract geometries from an sf object\")\n\tif (length(lst) == 1 && is.list(lst[[1]]) && !inherits(lst[[1]], \"sfg\")\n\t\t\t&& (length(lst[[1]]) == 0 || inherits(lst[[1]][[1]], \"sfg\") || is.null(lst[[1]][[1]])))\n\t\tlst = lst[[1]]\n\tstopifnot(is.numeric(crs) || is.character(crs) || inherits(crs, \"crs\"))\n\n\t# check for NULLs:\n\ta = attributes(lst)\n\tis_null = sfc_is_null(lst)\n\tlst = unclass(lst)\n\tlst = lst[! is_null]\n\tattributes(lst) = a\n\n\tdims_and_types = sfc_unique_sfg_dims_and_types(lst)\n\t\n\tcls = if (length(lst) == 0) # empty set: no geometries to learn from\n\t\t\tfall_back_class\n\t\telse {\n\t\t\t# class: do we have a mix of geometry types?\n\t\t\tsingle = if (!is.null(attr(lst, \"single_type\"))) # set by CPL_read_wkb:\n\t\t\t\t\tattr(lst, \"single_type\")\n\t\t\t\telse\n\t\t\t\t\tlength(dims_and_types[[2]]) == 1L\n\t\t\tattr(lst, \"single_type\") = NULL # clean up\n\t\t\tif (single)\n\t\t\t\tc(paste0(\"sfc_\", dims_and_types[[2]][1]), \"sfc\")\n\t\t\telse\n\t\t\t\tc(\"sfc_GEOMETRY\", \"sfc\")    # the mix\n\t\t}\n\n\tif (any(is_null)) {\n\t\tif (missing(dim)) {\n\t\t\tdim = if (length(lst) == 0) # we have no clue:\n\t\t\t\t\t\"XY\"\n\t\t\t\telse\n\t\t\t\t\tdims_and_types[[1]][1]\n\t\t}\n\t\tret = vector(\"list\", length(is_null))\n\t\tret[!is_null] = lst\n\t\tret[ is_null] = list(typed_empty(cls, nchar(dim), dim = dim))\n\t\tattributes(ret) = attributes(lst)\n\t\tlst = ret\n\t\tdims_and_types = sfc_unique_sfg_dims_and_types(lst)\n\t}\n\n\t# set class:\n\tclass(lst) = cls\n\n\t# set precision\n\tif (! missing(precision) || is.null(attr(lst, \"precision\")))\n\t\tattr(lst, \"precision\") = precision\n\n\t# compute bbox, if not set:\n\tbb = attr(lst, \"bbox\")\n\tif (is.null(bb) || anyNA(bb) || recompute_bbox)\n\t\tattr(lst, \"bbox\") = compute_bbox(lst)\n\n\t# compute z_range, if dims permit and not set\n\tzr = attr(lst, \"z_range\")\n\tif (is.null(zr) || anyNA(zr)) {\n\t\tu <- dims_and_types[[1]]\n\t\tif( \"XYZM\" %in% u ) {\n\t\t\tattr(lst, \"z_range\") = compute_z_range(lst)\n\t\t\tattr(lst, \"m_range\") = compute_m_range(lst)\n\t\t} else if ( \"XYZ\" %in% u ) {\n\t\t\tattr(lst, \"z_range\") = compute_z_range(lst)\n\t\t} else if (\"XYM\" %in% u ) {\n\t\t\tattr(lst, \"m_range\") = compute_m_range(lst)\n\t\t}\n\t}\n\n\t# check ring directions:\n\tif (check_ring_dir) # also GEOMETRYCOLLECTION?\n\t\tlst = check_ring_dir(lst)\n\n\t# get & set crs:\n\tif (is.na(crs) && !is.null(attr(lst, \"crs\")))\n\t\tcrs = attr(lst, \"crs\")\n\tst_crs(lst) = crs\n\n\t# set classes attr in case of GEOMETRY\n\tattr(lst, \"classes\") = if (inherits(lst, \"sfc_GEOMETRY\")) # recompute, as NULL's may have been substituted:\n\t\tvapply(lst, class, rep(NA_character_, 3))[2L,]\n\t\t# else NULL: removes when present; #2567\n\n\t# set n_empty, check XY* is uniform:\n\tif (is.null(attr(lst, \"n_empty\")) || any(is_null)) { # n_empty is set by CPL_read_wkb:\n\t\tattr(lst, \"n_empty\") = sum(sfc_is_empty(lst))\n# \t\thttps://github.com/r-spatial/sf/issues/1592 :\n#\t\tif (length(u <- unique(sfg_classes[1L,])) > 1)\n#\t\t\tstop(paste(\"found multiple dimensions:\", paste(u, collapse = \" \")))\n\t}\n\tif (isTRUE(oriented))\n\t\tattr(lst, \"oriented\") = TRUE\n\n\tlst\n}\n\n#' @name sfc\n#' @param x object of class \\code{sfc}\n#' @param i record selection. Might also be an \\code{sfc}/\\code{sf} object to work with the \\code{op} argument\n#' @param j ignored if `op` is specified\n#' @param op function, geometrical binary predicate function to apply when\n#'   \\code{i} is a \\code{sf}/\\code{sfc} object. Additional arguments can be\n#'   specified using \\code{...}, see examples.\n#' @details if `x` has a `dim` attribute (i.e. is an `array` or `matrix`) then `op` cannot be used.\n#' @export\n\"[.sfc\" = function(x, i, j, ..., op = st_intersects) {\n\tprecision = st_precision(x)\n\tcrs = st_crs(x)\n\tdim = if (length(x)) class(x[[1]])[1] else \"XY\"\n\tif (!missing(i) && inherits(i, c(\"sf\", \"sfc\", \"sfg\")))\n\t\ti = lengths(op(x, i, ...)) != 0\n\tst_sfc(unclass(x)[i], crs = crs, precision = precision, dim = dim, fall_back_class = class(x))\n}\n\n#' @export\n\"[<-.sfc\" = function (x, i, j, ..., value) {\n\tif (is.null(value) || inherits(value, \"sfg\"))\n\t\tvalue = list(value)\n\tret = st_sfc(NextMethod(), recompute_bbox = TRUE)\n\tstructure(ret, n_empty = sum(sfc_is_empty(ret)))\n}\n\n#' @export\nc.sfc = function(..., recursive = FALSE) {\n\tlst = list(...)\n\tchk_equal_crs(lst)\n\tclasses = sapply(lst, function(x) class(x)[1])\n\tle = lengths(lst)\n\tif (any(le > 0))\n\t\tclasses = classes[le > 0] # removes the empty set GEOMETRY objects\n\tucls = unique(classes)\n\tcls = if (length(ucls) > 1) # a mix:\n\t\t\tc(\"sfc_GEOMETRY\", \"sfc\")\n\t\telse\n\t\t\tc(ucls, \"sfc\")\n\n\tret = unlist(lapply(lst, unclass), recursive = FALSE)\n\tattributes(ret) = attributes(lst[[1]]) # crs\n\tclass(ret) = cls\n\tattr(ret, \"bbox\") = compute_bbox(ret) # dispatch on class\n\tattr(ret, \"n_empty\") = sum(sapply(lst, attr, which = \"n_empty\"))\n\tif (inherits(ret, \"sfc_GEOMETRY\"))\n\t\tattr(ret, \"classes\") = vapply(ret, class, rep(\"\", 3))[2L,]\n\tret\n}\n\n#' @export\nprint.sfc = function(x, ..., n = 5L, what = \"Geometry set for\", append = \"\") {\n\tsep = if (length(x) != 1) \"s\" else \"\"\n\tcls = substr(class(x)[1], 5, nchar(class(x)[1]))\n\tcat(paste0(what, \" \", length(x), \" feature\", sep, \" \", append))\n\tif (! is.null(attr(x, \"n_empty\"))) {\n\t\tne = attr(x, \"n_empty\")\n\t\tif (ne > 0)\n\t\t\tcat(paste0(\" (with \", ne, ifelse(ne > 1, \" geometries \", \" geometry \"), \"empty)\"))\n\t}\n\tif (!is.null(dim(x)))\n\t\tcat(paste0(\" [dim: \", paste(dim(x), collapse = \" x \"), \"]\"))\n\tcat(\"\\n\")\n\tif (length(x) || !inherits(x, \"sfc_GEOMETRY\"))\n\t\tcat(paste0(\"Geometry type: \", cls, \"\\n\"))\n\tif (length(x)) {\n\t\tu = sort(unique(sapply(x, function(x) class(x)[1])))\n\t\tcat(paste0(\"Dimension:     \", paste(u, collapse = \", \"), \"\\n\"))\n\t}\n\tcat(    paste0(\"Bounding box:  \"))\n\tbb = signif(attr(x, \"bbox\"), options(\"digits\")$digits)\n\tcat(paste(paste(names(bb), bb[], sep = \": \"), collapse = \" \"))\n\tcat(\"\\n\")\n\tif( !is.null( attr(x, \"z_range\"))) {\n\t\tcat(paste0(\"z_range:       \"))\n\t\tzb = signif(attr(x, \"z_range\"), options(\"digits\")$digits)\n\t\tcat(paste(paste(names(zb), zb[], sep = \": \"), collapse = \" \"))\n\t\tcat(\"\\n\")\n\t}\n\tif( !is.null( attr(x, \"m_range\"))) {\n\t\tcat(paste0(\"m_range:       \"))\n\t\tmb = signif(attr(x, \"m_range\"), options(\"digits\")$digits)\n\t\tcat(paste(paste(names(mb), mb[], sep = \": \"), collapse = \" \"))\n\t\tcat(\"\\n\")\n\t}\n\t# attributes: epsg, proj4string, precision\n\tcrs = st_crs(x)\n\tif (is.na(crs))\n\t\tcat(paste0(\"CRS:           NA\\n\"))\n\telse {\n\t\tp = crs_parameters(crs)\n\t\tif (p$Name == \"unknown\") {\n\t\t\tif (is.character(crs$input) && !is.na(crs$input) && crs$input != \"unknown\")\n\t\t\t\tp$Name = crs$input\n\t\t\telse\n\t\t\t\tp$Name = crs$proj4string\n\t\t}\n\t\tif (p$IsGeographic)\n\t\t\tcat(paste0(\"Geodetic CRS:  \", p$Name, \"\\n\"))\n\t\telse\n\t\t\tcat(paste0(\"Projected CRS: \", p$Name, \"\\n\"))\n\t}\n\tif (attr(x, \"precision\") != 0.0) {\n\t\tcat(    paste0(\"Precision:     \"))\n\t\tif (attr(x, \"precision\") < 0.0)\n\t\t\tcat(\"float (single precision)\\n\")\n\t\telse\n\t\t\tcat(paste(attr(x, \"precision\"), \"\\n\"))\n\t} # else cat(\"double (default; no precision model)\\n\")\n\tif (length(x) > n && n > 0)\n\t\tcat(paste0(\"First \", n, \" geometries:\\n\"))\n\tfor (i in seq_len(min(n, length(x))))\n\t\tif (inherits(x[[i]], \"sfg\"))\n\t\t\tprint(x[[i]], width = 50, crs = crs)\n\t\telse\n\t\t\tprint(x[[i]], crs = crs)\n\tinvisible(x)\n}\n\n#' Summarize simple feature column\n#'\n#' Summarize simple feature column\n#' @param object object of class \\code{sfc}\n#' @param ... ignored\n#' @param maxsum maximum number of classes to summarize the simple feature column to\n#' @param maxp4s maximum number of characters to print from the PROJ string\n#' @method summary sfc\n#' @export\nsummary.sfc = function(object, ..., maxsum = 7L, maxp4s = 10L) {\n\tu = factor(vapply(object, function(x) WKT_name(x, FALSE), \"\"))\n    epsg = paste0(\"epsg:\", st_crs(object)$epsg)\n\tlevels(u) = c(levels(u), epsg)\n    p4s = attr(object, \"crs\")$proj4string\n\tif (!is.na(p4s)) {\n\t\tif (nchar(p4s) > maxp4s)\n\t\t\tp4s = paste0(substr(p4s, 1L, maxp4s), \"...\")\n\t\tlevels(u) = c(levels(u), p4s)\n\t}\n    summary(u, maxsum = maxsum, ...)\n}\n\n#' @export\nas.data.frame.sfc = function(x, ...) {\n\tret = data.frame(row.names = seq_along(x))\n\tret$geometry = x\n\tret\n}\n\n\n#' @name st_geometry\n#' @export\nst_geometry.sfc = function(obj, ...) obj\n\n#' Return geometry type of an object\n#'\n#' Return geometry type of an object, as a factor\n#' @param x object of class \\link{sf} or \\link{sfc}\n#' @param by_geometry logical; if \\code{TRUE}, return geometry type of each geometry,\n#' else return geometry type of the set\n#' @return a factor with the geometry type of each simple feature geometry\n#' in \\code{x}, or that of the whole set\n#' @export\nst_geometry_type = function(x, by_geometry = TRUE) {\n\tx = st_geometry(x)\n\tf = if (by_geometry)\n\t\t\tvapply(x, function(y) class(y)[2], \"\")\n\t\telse\n\t\t\tsubstring(class(x)[1], 5)\n\tfactor(f, levels =\n\t\tc(\"GEOMETRY\",\n\t\t\"POINT\",\n\t\t\"LINESTRING\",\n\t\t\"POLYGON\",\n\t\t\"MULTIPOINT\",\n\t\t\"MULTILINESTRING\",\n\t\t\"MULTIPOLYGON\",\n\t\t\"GEOMETRYCOLLECTION\",\n\t\t\"CIRCULARSTRING\",\n\t\t\"COMPOUNDCURVE\",\n\t\t\"CURVEPOLYGON\",\n\t\t\"MULTICURVE\",\n\t\t\"MULTISURFACE\",\n\t\t\"CURVE\",\n\t\t\"SURFACE\",\n\t\t\"POLYHEDRALSURFACE\",\n\t\t\"TIN\",\n\t\t\"TRIANGLE\"))\n}\n\n#' Drop or add Z and/or M dimensions from feature geometries\n#'\n#' Drop Z and/or M dimensions from feature geometries, resetting classes appropriately\n#' @param x object of class \\code{sfg}, \\code{sfc} or \\code{sf}\n#' @param ... ignored\n#' @param drop logical; drop, or (`FALSE`) add?\n#' @param what character which dimensions to drop or add\n#' @details Only combinations \\code{drop=TRUE}, \\code{what = \"ZM\"}, and \\code{drop=FALSE}, \\code{what=\"Z\"} are supported so far.\n#' In the latter case, \\code{x} should have \\code{XY} geometry, and zero values are added for the \\code{Z} dimension.\n#' @examples\n#' st_zm(st_linestring(matrix(1:32,8)))\n#' x = st_sfc(st_linestring(matrix(1:32,8)), st_linestring(matrix(1:8,2)))\n#' st_zm(x)\n#' a = st_sf(a = 1:2, geom=x)\n#' st_zm(a)\n#' @export\nst_zm <- function(x, ..., drop = TRUE, what = \"ZM\") UseMethod(\"st_zm\")\n\n#' @export\nst_zm.sf <- function(x, ..., drop = TRUE, what = \"ZM\") {\n\tst_geometry(x) = st_zm(st_geometry(x), drop = drop, what = what)\n\tx\n}\n\n#' @export\nst_zm.sfc <- function(x, ..., drop = TRUE, what = \"ZM\") {\n\tst_sfc(lapply(x, st_zm, drop = drop, what = what), crs = st_crs(x))\n}\n\n#' @export\nst_zm.sfg <- function(x, ..., drop = TRUE, what = \"ZM\") {\n\tif (drop && what == \"ZM\") {\n\t\tret = if (is.list(x))\n\t\t\tlapply(x, st_zm, drop = drop, what = what)\n\t\telse if (is.matrix(x))\n\t\t\tx[, 1:2, drop = FALSE]\n\t\telse\n\t\t\tx[1:2]\n\t\tstructure(ret, class = c(\"XY\", class(x)[2:3]))\n\t} else if (!drop && what == \"Z\") {\n\t\tif (class(x)[1] != \"XY\")\n\t\t\tstop(\"adding Z only supported for XY geometries\")\n\t\tret = if (is.list(x))\n\t\t\tlapply(x, st_zm, drop = drop, what = what)\n\t\telse if (is.matrix(x))\n\t\t\tcbind(unclass(x), 0)\n\t\telse\n\t\t\tc(unclass(x), 0)\n\t\tstructure(ret, class = c(\"XYZ\", class(x)[2:3]))\n\t} else\n\t\tstop(\"this combination of `x', `drop' and `what' is not implemented\")\n}\n\n#' @export\nst_zm.list <- function(x, ..., drop = TRUE, what = \"ZM\")\n\tlapply(x, st_zm, drop = drop, what = what)\n\n#' @export\nst_zm.matrix <- function(x, ..., drop = TRUE, what = \"ZM\")  {\n\tif (drop && what == \"ZM\") {\n\t\tx[,1:2]\n\t} else if (!drop && what == \"Z\") {\n\t\tcbind(unclass(x), 0)\n\t} else\n\t\tstop(\"this combination of drop and what is not implemented\")\n}\n\n#' Get precision\n#'\n#' @param x object of class \\code{sfc} or \\code{sf}\n#' @export\nst_precision <- function(x) {\n  UseMethod(\"st_precision\")\n}\n\n#' @export\nst_precision.sf <- function(x) {\n  x <- st_geometry(x)\n  st_precision(x)\n}\n\n#' @export\nst_precision.sfc <- function(x) {\n  attr(x, \"precision\")\n}\n\n#' Set precision\n#'\n#' @rdname st_precision\n#' @param precision numeric, or object of class \\code{units} with distance units (but see details); see \\link{st_as_binary} for how to do this.\n#' @details If \\code{precision} is a \\code{units} object, the object on which we set precision must have a coordinate reference system with compatible distance units.\n#'\n#' Setting a \\code{precision} has no direct effect on coordinates of geometries, but merely set an attribute tag to an \\code{sfc} object.\n#' The effect takes place in \\link{st_as_binary} or, more precise, in the C++ function \\code{CPL_write_wkb}, where simple feature geometries are being serialized to well-known-binary (WKB).\n#' This happens always when routines are called in GEOS library (geometrical operations or predicates), for writing geometries using \\link{st_write} or \\link{write_sf}, \\code{st_make_valid} in package \\code{lwgeom}; also \\link{aggregate} and \\link{summarise} by default union geometries, which calls a GEOS library function.\n#' Routines in these libraries receive rounded coordinates, and possibly return results based on them. \\link{st_as_binary} contains an example of a roundtrip of \\code{sfc} geometries through WKB, in order to see the rounding happening to R data.\n#'\n#' The reason to support precision is that geometrical operations in GEOS or liblwgeom may work better at reduced precision. For writing data from R to external resources it is harder to think of a good reason to limiting precision.\n#'\n#' @seealso \\link{st_as_binary} for an explanation of what setting precision does, and the examples therein.\n#' @examples\n#' x <- st_sfc(st_point(c(pi, pi)))\n#' st_precision(x)\n#' st_precision(x) <- 0.01\n#' st_precision(x)\n#' @export\nst_set_precision <- function(x, precision) {\n    UseMethod(\"st_set_precision\")\n}\n\n#' @export\nst_set_precision.sfc <- function(x, precision) {\n    if (length(precision) != 1) {\n        stop(\"Precision applies to all dimensions and must be of length 1.\", call. = FALSE)\n    }\n\n\tif (inherits(precision, \"units\")) {\n\t\tu = st_crs(x)$ud_unit\n\t\tif (is.null(u))\n\t\t\tstop(\"cannot use precision expressed as units when target object has no units (CRS) set\")\n\t\tunits(precision) = 1/u # convert\n\t\tprecision = as.numeric(precision)\n\t}\n\n    if (is.na(precision) || !is.numeric(precision)) {\n        stop(\"Precision must be numeric\", call. = FALSE)\n    }\n    structure(x, precision = precision)\n}\n\n#' @export\nst_set_precision.sf <- function(x, precision) {\n    st_geometry(x) <- st_set_precision(st_geometry(x), precision)\n    return(x)\n}\n\n#' @name st_precision\n#' @param value precision value\n#' @export\n\"st_precision<-\" <- function(x, value) {\n    st_set_precision(x, value)\n}\n\ntyped_empty = function(cls, ncol = 2, dim = \"XY\") {\n\tswitch(cls[1],\n\t\tsfc_POINT = st_point(rep(NA_real_, ncol), dim = dim),\n\t\tsfc_MULTIPOINT = st_multipoint(matrix(numeric(0), ncol = ncol), dim = dim),\n\t\tsfc_LINESTRING = st_linestring(matrix(numeric(0), ncol = ncol), dim = dim),\n\t\tsfc_MULTILINESTRING = st_multilinestring(dim = dim),\n\t\tsfc_POLYGON = st_polygon(dim = dim),\n\t\tsfc_MULTIPOLYGON = st_multipolygon(dim = dim),\n\t\tst_geometrycollection(dims = dim))\n}\n\n#' retrieve coordinates in matrix form\n#'\n#' retrieve coordinates in matrix form\n#' @param x object of class sf, sfc or sfg\n#' @param ... ignored\n#' @return matrix with coordinates (X, Y, possibly Z and/or M) in rows, possibly followed by integer indicators \\code{L1},...,\\code{L3} that point out to which structure the coordinate belongs; for \\code{POINT} this is absent (each coordinate is a feature), for \\code{LINESTRING} \\code{L1} refers to the feature, for \\code{MULTILINESTRING} \\code{L1} refers to the part and \\code{L2} to the simple feature, for \\code{POLYGON} \\code{L1} refers to the main ring or holes and \\code{L2} to the simple feature, for \\code{MULTIPOLYGON} \\code{L1} refers to the main ring or holes, \\code{L2} to the ring id in the \\code{MULTIPOLYGON}, and \\code{L3} to the simple feature.\n#' \n#' For \\code{POLYGONS}, \\code{L1} can be used to identify exterior rings and inner holes. \n#' The exterior ring is when \\code{L1} is equal to 1. Interior rings are identified \n#' when \\code{L1} is greater than 1. \\code{L2} can be used to differentiate between the \n#' feature. Whereas for \\code{MULTIPOLYGON}, \\code{L3} refers to the \\code{MULTIPOLYGON}\n#' feature and \\code{L2} refers to the component \\code{POLYGON}.\n#' \n#' @export\nst_coordinates = function(x, ...) UseMethod(\"st_coordinates\")\n\n#' @export\nst_coordinates.sf = function(x, ...) st_coordinates(st_geometry(x))\n\n#' @export\nst_coordinates.sfg = function(x, ...) st_coordinates(st_geometry(x))\n\n#' @export\nst_coordinates.sfc = function(x, ...) {\n\tif (length(x) == 0)\n\t\treturn(matrix(nrow = 0, ncol = 2))\n\n\tret = switch(class(x)[1],\n\t\tsfc_POINT = matrix(unlist(x, use.names = FALSE), nrow = length(x), byrow = TRUE,\n\t\t     dimnames = NULL),\n\t\tsfc_MULTIPOINT = ,\n\t\tsfc_LINESTRING = coord_2(x),\n\t\tsfc_MULTILINESTRING = ,\n\t\tsfc_POLYGON = coord_3(x),\n\t\tsfc_MULTIPOLYGON = coord_4(x),\n\t\tstop(paste(\"not implemented for objects of class\", class(x)[1]))\n\t)\n\tDims = class(x[[1]])[1]\n\tncd = nchar(Dims)\n\tcolnames(ret)[1:ncd] = vapply(seq_len(ncd), function(i) substr(Dims, i, i), \"\")\n\tret\n}\n\ncoord_2 = function(x) { # x is a list with matrices\n\tcbind(do.call(rbind, x), L1 = rep(seq_along(x), times = vapply(x, nrow, 0L)))\n}\n\ncoord_3 = function(x) { # x is a list of lists with matrices\n\tx = lapply(x, coord_2)\n\tcbind(do.call(rbind, x), L2 = rep(seq_along(x), times = vapply(x, nrow, 0L)))\n}\n\ncoord_4 = function(x) { # x is a list of lists of lists with matrices\n\tx = lapply(x, coord_3)\n\tcbind(do.call(rbind, x), L3 = rep(seq_along(x), times = vapply(x, nrow, 0L)))\n}\n\n#' @export\nrep.sfc = function(x, ...) {\n\tst_sfc(NextMethod(), crs = st_crs(x))\n}\n\ncheck_ring_dir = function(x) {\n\tcheck_polygon = function(pol) {\n\t\tsa = sapply(pol, CPL_signed_area)\n\t\trevert = if (length(sa))\n\t\t\t\tc(sa[1] < 0, sa[-1] > 0)\n\t\t\telse\n\t\t\t\tlogical(0)\n\t\tpol[revert] = lapply(pol[revert], function(m) m[nrow(m):1,])\n\t\tpol\n\t}\n\tcls = if (inherits(x, \"sfg\"))\n\t\t\tclass(x)[2]\n\t\telse\n\t\t\tclass(x)[1]\n\tret = switch(cls,\n\t\tPOLYGON = check_polygon(x),\n\t\tMULTIPOLYGON = ,\n\t\tsfc_POLYGON = lapply(x, check_polygon),\n\t\tsfc_MULTIPOLYGON = lapply(x, function(y) structure(lapply(y, check_polygon), class = class(y))),\n\t\tstop(paste(\"check_ring_dir: not supported for class\", class(x)[1]))\n\t)\n\tattributes(ret) = attributes(x)\n\tret\n}\n\n#' @name st_as_sfc\n#' @export\nst_as_sfc.list = function(x, ..., crs = NA_crs_) {\n\n\tif (length(x) == 0)\n\t\treturn(st_sfc(crs = crs))\n\n\tif (is.raw(x[[1]]))\n\t\tst_as_sfc.WKB(structure(x, class = \"WKB\"), ..., crs = crs)\n\telse if (inherits(x[[1]], \"sfg\"))\n\t\tst_sfc(x, crs = crs)\n\telse if (is.character(x[[1]])) { # hex wkb or wkt:\n\t\tch12 = substr(x[[1]], 1, 2)\n\t\tif (ch12 == \"0x\" || ch12 == \"00\" || ch12 == \"01\") # hex wkb\n\t\t\tst_as_sfc.WKB(structure(x, class = \"WKB\"), ..., crs = crs)\n\t\telse\n\t\t\tst_as_sfc(unlist(x), ..., crs = crs) # wkt\n\t} else\n\t\tstop(paste(\"st_as_sfc.list: don't know what to do with list with elements of class\", class(x[[1]])))\n}\n\n#' @name st_as_sfc\n#' @export\nst_as_sfc.blob = function(x, ...) {\n\tst_as_sfc.list(x, ...)\n}\n\n#' @name st_as_sfc\n#' @export\nst_as_sfc.bbox = function(x, ...) {\n\tif (st_is_full(x))\n\t\tst_as_sfc(\"POLYGON FULL\", crs = st_crs(x))\n\telse {\n\t\tbox = st_polygon(list(matrix(x[c(1, 2, 3, 2, 3, 4, 1, 4, 1, 2)], ncol = 2, byrow = TRUE)))\n\t\tst_sfc(box, crs = st_crs(x), oriented = TRUE)\n\t}\n}\n\nPOLYGON_FULL = matrix(c(0,-90,0,-90), 2, byrow = TRUE)\n\n#' predicate whether a geometry is equal to a POLYGON FULL\n#'\n#' predicate whether a geometry is equal to a POLYGON FULL\n#' @param x object of class `sfg`, `sfc` or `sf`\n#' @param ... ignored, except when it contains a `crs` argument to inform unspecified `is_longlat`\n#' @returns logical, indicating whether geometries are POLYGON FULL (a spherical\n#' polygon covering the entire sphere)\n#' @export\nst_is_full = function(x, ...) UseMethod(\"st_is_full\")\n\n#' @export\n#' @name st_is_full\n#' @param is_longlat logical; output of \\link{st_is_longlat} of the parent `sfc` object\nst_is_full.sfg = function(x, ..., is_longlat = NULL) {\n\tif (identical(is_longlat, FALSE)) # we know these are Cartesian coordinates:\n\t\tFALSE\n\telse\n\t\tsf_use_s2() && inherits(x, \"POLYGON\") &&\n\t\tlength(x) == 1 && nrow(x[[1]]) == 2 && identical(x[[1]], POLYGON_FULL)\n}\n\n#' @export\n#' @name st_is_full\nst_is_full.sfc = function(x, ...) {\n\tif (sf_use_s2() && inherits(x, c(\"sfc_POLYGON\", \"sfc_GEOMETRY\")))\n\t\tsfc_is_full(x)\n\telse\n\t\trep_len(FALSE, length(x))\n}\n\n#' @export\n#' @name st_is_full\nst_is_full.sf = function(x, ...) {\n\tst_is_full(st_geometry(x), ...)\n}\n\n#' @export\n#' @name st_is_full\nst_is_full.bbox = function(x, ...) {\n\tisTRUE(sf_use_s2() && st_is_longlat(x) && all(x == c(-180,-90,180,90)))\n}\n\n#' @export\nunique.sfc = function(x, ...) {\n\tst_sfc(unique(unclass(x),...), crs = st_crs(x), precision = st_precision(x))\n}\n\n#' @export\nxtfrm.sfc = function(x) {\n\td = st_dimension(x, FALSE)\n\tne = !st_is_empty(x)\n\tv = vector(\"double\", length(x))\n\tif (0 %in% d)\n\t\tv[d == 0] = 0 # or # of pts in MULTIPOINT?\n\tif (1 %in% d) {\n\t\tl = st_length(x[d == 1])\n\t\tif (max(l) > 1)\n\t\t\tl = l / max(l)\n\t\tv[d == 1] = l\n\t}\n\tif (2 %in% d) {\n\t\ta = st_area(x[d == 2])\n\t\tif (max(a) > 1)\n\t\t\ta = a / max(a)\n\t\tv[d == 2] = a\n\t}\n\txtfrm(ne + d * 2.1 + v)\n}\n"
  },
  {
    "path": "R/sfg.R",
    "content": "# dim: what does the third dimension, if present, refer to? (XYZ or XYM)\ngetClassDim = function(x, d, dim = \"XYZ\", type) {\n\ttype = toupper(type)\n\tif (d == 2)\n\t\tc(\"XY\", type, \"sfg\")\n\telse if (d == 3) {\n\t\tstopifnot(dim %in% c(\"XYZ\", \"XYM\"))\n\t\tc(dim, type, \"sfg\")\n\t} else if (d == 4)\n\t\tc(\"XYZM\", type, \"sfg\")\n\telse stop(paste(d, \"is an illegal number of columns for a\", type))\n}\n\nvalid_numeric_matrix = function(x) {\n\tstopifnot(is.numeric(x), is.matrix(x), !anyNA(x))\n}\n\nMtrx = function(x, dim = \"XYZ\", type) {\n\tvalid_numeric_matrix(x)\n\tstructure(x, class = getClassDim(x, ncol(x), dim, type))\n}\n\n# creates object of class c(dim, type, \"sfg\") from list x, possibly checking rings are closed\nMtrxSet = function(x, dim = \"XYZ\", type, needClosed = FALSE) {\n\tstopifnot(is.list(x))\n\tif (length(x) > 0) { # list()\n\t\tlapply(x, valid_numeric_matrix)\n\t\tnc = unique(vapply(x, ncol, 0L))\n\t\tif (length(nc) != 1)\n\t\t\tstop(\"matrices have unequal numbers of columns\")\n\t\tNotClosed = function(y) any(y[1, ] != y[nrow(y), ])\n\t\tif (needClosed && any(vapply(x, NotClosed, TRUE)))\n\t\t\tstop(\"polygons not (all) closed\")\n\t\tstructure(x, class = getClassDim(x, nc, dim, type))\n\t} else\n\t\tstructure(x, class = getClassDim(x, nchar(dim), dim, type))\n}\n\n# creates object of class c(dim, type, \"sfg\") from list x, d, possibly checking rings are closed\nMtrxSetSet = function(x, dim = \"XYZ\", type, needClosed = FALSE) {\n\tstopifnot(is.list(x), vapply(x, is.list, TRUE))\n\tif (length(x)) {\n\t\tnc = unique(unlist(lapply(x, function(y) vapply(y, ncol, 0L))))\n\t\tif (length(nc) != 1)\n\t\t\tstop(\"matrices have unequal numbers of columns\")\n\t\tlapply(x, function(y) lapply(y, valid_numeric_matrix))\n\t\tNotClosed = function(y) any(y[1, ] != y[nrow(y), ])\n\t\tif (needClosed && any(unlist(lapply(x, function(y) vapply(y, NotClosed, TRUE)))))\n\t\t\tstop(\"polygons not (all) closed\")\n\t\tstructure(x, class = getClassDim(x, nc, dim, type))\n\t} else \n\t\tstructure(x, class = getClassDim(x, nchar(dim), dim, type))\n}\n\n#return \"XY\", \"XYZ\", \"XYM\", or \"XYZM\"\nDimension = function(x) {\n\tstopifnot(inherits(x, \"sfg\"))\n\tclass(x)[1]\n}\n\n## internal function to get a list of sfg POINT for st_as_sf(, coords = ...)\n## src/sfg.cpp\n## https://github.com/r-spatial/sf/issues/700\npoints_rcpp <- function(pts, gdim = \"XY\", ...) {\n\tstopifnot(gdim %in% c(\"XY\", \"XYZ\", \"XYZM\", \"XYM\"))\n\tif (dim(pts)[2L] == 2L && nchar(gdim) > 2L) gdim = \"XY\"\n\tstopifnot(dim(pts)[2] == nchar(gdim))\n\tpoints_cpp(pts, gdim)\n}\n\n#' Create simple feature from a numeric vector, matrix or list\n#'\n#' Create simple feature from a numeric vector, matrix or list\n#' @param x for \\code{st_point}, numeric vector (or one-row-matrix) of length 2, 3 or 4; for \\code{st_linestring} and \\code{st_multipoint}, numeric matrix with points in rows; for \\code{st_polygon} and \\code{st_multilinestring}, list with numeric matrices with points in rows; for \\code{st_multipolygon}, list of lists with numeric matrices; for \\code{st_geometrycollection} list with (non-geometrycollection) simple feature geometry (sfg) objects; see examples below\n#' @param dim character, indicating dimensions: \"XY\", \"XYZ\", \"XYM\", or \"XYZM\"; only really needed for three-dimensional points (which can be either XYZ or XYM) or empty geometries; see details\n#' @name st\n#' @details \"XYZ\" refers to coordinates where the third dimension represents altitude, \"XYM\" refers to three-dimensional coordinates where the third dimension refers to something else (\"M\" for measure); checking of the sanity of \\code{x} may be only partial.\n#' @return object of the same nature as \\code{x}, but with appropriate class attribute set\n#' @examples\n#' (p1 = st_point(c(1,2)))\n#' class(p1)\n#' st_bbox(p1)\n#' (p2 = st_point(c(1,2,3)))\n#' class(p2)\n#' (p3 = st_point(c(1,2,3), \"XYM\"))\n#' pts = matrix(1:10, , 2)\n#' (mp1 = st_multipoint(pts))\n#' pts = matrix(1:15, , 3)\n#' (mp2 = st_multipoint(pts))\n#' (mp3 = st_multipoint(pts, \"XYM\"))\n#' pts = matrix(1:20, , 4)\n#' (mp4 = st_multipoint(pts))\n#' pts = matrix(1:10, , 2)\n#' (ls1 = st_linestring(pts))\n#' pts = matrix(1:15, , 3)\n#' (ls2 = st_linestring(pts))\n#' (ls3 = st_linestring(pts, \"XYM\"))\n#' pts = matrix(1:20, , 4)\n#' (ls4 = st_linestring(pts))\n#' outer = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\n#' hole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\n#' hole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\n#' pts = list(outer, hole1, hole2)\n#' (ml1 = st_multilinestring(pts))\n#' pts3 = lapply(pts, function(x) cbind(x, 0))\n#' (ml2 = st_multilinestring(pts3))\n#' (ml3 = st_multilinestring(pts3, \"XYM\"))\n#' pts4 = lapply(pts3, function(x) cbind(x, 0))\n#' (ml4 = st_multilinestring(pts4))\n#' outer = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\n#' hole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\n#' hole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\n#' pts = list(outer, hole1, hole2)\n#' (pl1 = st_polygon(pts))\n#' pts3 = lapply(pts, function(x) cbind(x, 0))\n#' (pl2 = st_polygon(pts3))\n#' (pl3 = st_polygon(pts3, \"XYM\"))\n#' pts4 = lapply(pts3, function(x) cbind(x, 0))\n#' (pl4 = st_polygon(pts4))\n#' pol1 = list(outer, hole1, hole2)\n#' pol2 = list(outer + 12, hole1 + 12)\n#' pol3 = list(outer + 24)\n#' mp = list(pol1,pol2,pol3)\n#' (mp1 = st_multipolygon(mp))\n#' pts3 = lapply(mp, function(x) lapply(x, function(y) cbind(y, 0)))\n#' (mp2 = st_multipolygon(pts3))\n#' (mp3 = st_multipolygon(pts3, \"XYM\"))\n#' pts4 = lapply(mp2, function(x) lapply(x, function(y) cbind(y, 0)))\n#' (mp4 = st_multipolygon(pts4))\n#' (gc = st_geometrycollection(list(p1, ls1, pl1, mp1)))\n#' st_geometrycollection() # empty geometry\n#' @export\nst_point = function(x = c(NA_real_, NA_real_), dim = \"XYZ\") {\n\tstopifnot(is.numeric(x) && length(x) >= 2)\n\tif (is.matrix(x))\n\t\tstopifnot(nrow(x) == 1) # because we want to be able to call rbind on points\n\tif (any(is.na(x)))\n\t\tx = rep(NA_real_, length(x))\n\tstructure(x, class = getClassDim(x, length(x), dim, \"POINT\"))\n}\n#' @name st\n#' @export\nst_multipoint = function(x = matrix(numeric(0), 0, 2), dim = \"XYZ\") Mtrx(x, dim, type = \"MULTIPOINT\")\n#' @name st\n#' @export\nst_linestring = function(x = matrix(numeric(0), 0, 2), dim = \"XYZ\") Mtrx(x, dim, type = \"LINESTRING\")\n#' @name st\n#' @export\nst_polygon = function(x = list(), dim = if(length(x)) \"XYZ\" else \"XY\") {\n\tMtrxSet(x, dim, type = \"POLYGON\", needClosed = TRUE)\n}\n#' @name st\n#' @export\nst_multilinestring = function(x = list(), dim = if (length(x)) \"XYZ\" else \"XY\")\n\tMtrxSet(x, dim, type = \"MULTILINESTRING\", needClosed = FALSE)\n#' @name st\n#' @export\nst_multipolygon = function(x = list(), dim = if (length(x)) \"XYZ\" else \"XY\")\n\tMtrxSetSet(x, dim, type = \"MULTIPOLYGON\", needClosed = TRUE)\n#' @name st\n#' @param dims character; specify dimensionality in case of an empty (NULL) geometrycollection, in which case \\code{x} is the empty \\code{list()}.\n#' @export\nst_geometrycollection = function(x = list(), dims = \"XY\") {\n\tcls = vapply(x, class, rep(\"\", 3))\n\tif (length(cls)) {\n\t\tif (!is.matrix(cls) || !is.character(cls) || nrow(cls) != 3)\n\t\t\tstop(\"st_geometrycollection parameter x error: list elements should be simple features\")\n\t\tstopifnot(all(cls[3,] == \"sfg\"))\n\t\tstopifnot(all(cls[2,] != \"GEOMETRYCOLLECTION\")) # can't recurse!\n\t\t# check all dimensions are equal:\n\t\tdims = unique(cls[1,])\n\t\tif (length(dims) > 1)\n\t\t\tstop(paste(\"multiple dimensions found:\", paste(dims, collapse = \", \")))\n\t}\n\tstructure(x, class = c(dims, \"GEOMETRYCOLLECTION\", \"sfg\")) # TODO: no Z/M/ZM modifier here??\n}\n\nPOINT2MULTIPOINT = function(x, dim = \"XYZ\") {\n\tif (length(x) == 3) # disambiguate Z/M:\n\t\tdim = class(x)[1]\n\tst_multipoint(matrix(unclass(x), 1), dim = dim)\n}\nLINESTRING2MULTILINESTRING = function(x, dim = \"XYZ\") {\n\tif (ncol(x) == 3) # disambiguate Z/M:\n\t\tdim = class(x)[1]\n\tst_multilinestring(list(unclass(x)), dim = dim)\n}\nPOLYGON2MULTIPOLYGON = function(x, dim = \"XYZ\") {\n\tif (st_is_empty(x)) {\n\t\treturn(st_multipolygon(dim = class(x)[1]))\n\t}\n\tif (ncol(x[[1]]) == 3) # disambiguate Z/M:\n\t\tdim = class(x)[1]\n\tst_multipolygon(list(unclass(x)), dim = dim)\n}\n\n#' @name st\n#' @param width integer; number of characters to be printed (max 30; 0 means print everything)\n#' @export\nprint.sfg = function(x, ..., width = 0) { # avoids having to write print methods for 68 classes:\n\tf = format(x, ..., width = width)\n\tmessage(f)\n\tinvisible(x)\n}\n\n#' @name st\n#' @param n integer; number of elements to be selected\n#' @export\nhead.sfg = function(x, n = 10L, ...) {\n\tstructure(head(unclass(x), n = n, ...), class = class(x))\n}\n\n#\nget_start = function(x, n = 30) {\n\tif (is.list(x)) # recurse into first element:\n\t\tstructure(lapply(x, get_start, n = n), class = class(x))\n\telse # matrix:\n\t\thead(x, round(n/3))\n}\n\n\n#' @name st\n#' @export\nformat.sfg = function(x, ..., width = 30) {\n\tif (is.null(width))\n\t\twidth = 30\n\tif (object.size(x) > 1000 && width > 0)\n\t\tx = get_start(x, n = width)\n\tpr = st_as_text(x, ...)\n\tif (width > 0 && nchar(pr) > width)\n\t\tpaste0(substr(pr, 1, width - 3), \"...\")\n\telse\n\t\tpr\n}\n\n#' @export\n#' @name st\n#' @param ... objects to be pasted together into a single simple feature\n#' @param recursive logical; ignored\n#' @param flatten logical; if `TRUE`, try to simplify results; if `FALSE`, return geometrycollection containing all objects\n#' @examples\n#' c(st_point(1:2), st_point(5:6))\n#' c(st_point(1:2), st_multipoint(matrix(5:8,2)))\n#' c(st_multipoint(matrix(1:4,2)), st_multipoint(matrix(5:8,2)))\n#' c(st_linestring(matrix(1:6,3)), st_linestring(matrix(11:16,3)))\n#' c(st_multilinestring(list(matrix(1:6,3))), st_multilinestring(list(matrix(11:16,3))))\n#' pl = list(rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0)))\n#' c(st_polygon(pl), st_polygon(pl))\n#' c(st_polygon(pl), st_multipolygon(list(pl)))\n#' c(st_linestring(matrix(1:6,3)), st_point(1:2))\n#' c(st_geometrycollection(list(st_point(1:2), st_linestring(matrix(1:6,3)))),\n#'   st_geometrycollection(list(st_multilinestring(list(matrix(11:16,3))))))\n#' c(st_geometrycollection(list(st_point(1:2), st_linestring(matrix(1:6,3)))),\n#'   st_multilinestring(list(matrix(11:16,3))), st_point(5:6),\n#'   st_geometrycollection(list(st_point(10:11))))\n#' @details When \\code{flatten=TRUE}, this method may merge points into a multipoint structure, and may not preserve order, and hence cannot be reverted. When given fish, it returns fish soup.\nc.sfg = function(..., recursive = FALSE, flatten = TRUE) {\n\n\tstopifnot(! recursive)\n\tPaste0 = function(lst) lapply(lst, unclass)\n\tPaste1 = function(lst) do.call(c, lapply(lst, unclass))\n\tlst = list(...)\n\tif (flatten) {\n\t\tcls = vapply(lst, function(x) class(x)[2], \"\")\n\t\tucls = unique(cls)\n\t\tif (length(ucls) == 1) {\n\t\t\tswitch(ucls,\n\t\t\t\tPOINT = st_multipoint(na.omit(do.call(rbind, lst))),\n\t\t\t\t# CURVE = st_multicurve(Paste0(lst))\n\t\t\t\t# CIRCULARSTRING = st_geometrycollection(lst), # FIXME??\n\t\t\t\tLINESTRING = st_multilinestring(Paste0(lst)),\n\t\t\t\t# SURFACE = st_multisurface(Paste0(lst)),\n\t\t\t\tPOLYGON = st_multipolygon(Paste0(lst)),\n\t\t\t\t# TRIANGLE = st_geometrycollection(lst),\n\t\t\t\tMULTIPOINT = st_multipoint(do.call(rbind, lst)),\n\t\t\t\tMULTILINESTRING = st_multilinestring(Paste1(lst)),\n\t\t\t\t# MULTICURVE = st_multicurve(Paste1(lst)),\n\t\t\t\tMULTIPOLYGON = st_multipolygon(Paste1(lst)),\n\t\t\t\t# MULTISURFACE = st_multisurface(Paste1(lst)),\n\t\t\t\t# POLYHEDRALSURFACE = st_polyhedralsurface(Paste1(lst)),\n\t\t\t\t# TIN = st_tin(Paste1(lst)),\n\t\t\t\tGEOMETRYCOLLECTION = st_geometrycollection(Paste1(lst)),\n\t\t\t\tstop(paste(\"type\", cls, \"not supported\"))\n\t\t\t)\n\t\t} else if (all(ucls %in% c(\"POINT\", \"MULTIPOINT\")))\n\t\t\tst_multipoint(do.call(rbind, lst))\n\t\telse if (all(cls %in% c(\"LINESTRING\", \"MULTILINESTRING\"))) {\n\t\t\tls = which(cls == \"LINESTRING\")\n\t\t\tmls = st_multilinestring(lst[ls])\n\t\t\tst_multilinestring(c(unlist(lst[-ls], FALSE), unclass(mls)))\n\t\t} else if (all(cls %in% c(\"POLYGON\", \"MULTIPOLYGON\"))) {\n\t\t\tpo = which(cls == \"POLYGON\")\n\t\t\tmpo = st_multipolygon(lst[po])\n\t\t\tst_multipolygon(c(unlist(lst[-po], FALSE), unclass(mpo)))\n\t\t} else {\n\t\t\t# unfold GC objects first, then\n\t\t\tgc = (cls == \"GEOMETRYCOLLECTION\")\n\t\t\tret = lst[!gc]\n\t\t\tif (any(gc)) { # append the _contents_ of GC's to the non-GC elements:\n\t\t\t\twgc = which(gc)\n\t\t\t\tfor (i in seq_len(length(wgc)))\n\t\t\t\t\tret = append(ret, lst[[wgc[i]]])\n\t\t\t}\n\t\t\tst_geometrycollection(ret)\n\t\t}\n\t} else # !flatten:\n\t\tst_geometrycollection(lst) # breaks if one of them is a GC\n}\n\n#' @name st\n#' @method as.matrix sfg\n#' @export\n#' @return as.matrix returns the set of points that form a geometry as a single matrix, where each point is a row; use \\code{unlist(x, recursive = FALSE)} to get sets of matrices.\nas.matrix.sfg = function(x, ...) {\n\tswitch(class(x)[2],\n\t\tPOINT = matrix(x, 1),\n\t\tMULTIPOINT = as.matrix(unclass(x)),\n\t\tLINESTRING = as.matrix(unclass(x)),\n\t\tPOLYGON = do.call(rbind, x),\n\t\tMULTILINESTRING = do.call(rbind, x),\n\t\tMULTIPOLYGON = do.call(rbind, lapply(x, function(y) do.call(rbind, y))),\n\t\tGEOMETRYCOLLECTION = do.call(rbind, lapply(x, as.matrix)),\n\t\tNextMethod()\n\t)\n}\n"
  },
  {
    "path": "R/sgbp.R",
    "content": "sgbp = function(x, predicate, region.id, ncol, sparse = TRUE, remove_self = FALSE, \n\t\t\t\tretain_unique = FALSE) {\n\tif (remove_self || retain_unique) {\n\t\tif (length(x) != ncol)\n\t\t\tstop(\"remove_self or retain_unique only work for square sparse matrices\")\n\t\tx = if (retain_unique) # (includes doing remove_self)\n\t\t\t\tmapply(function(x, y) { x[x > y] }, x, seq_along(x), SIMPLIFY = FALSE)\n\t\t\telse # remove_self \n\t\t\t\tmapply(setdiff, x, seq_along(x), SIMPLIFY = FALSE)\n\t}\n\tret = structure(x,\n\t\tpredicate = predicate,\n\t\tregion.id = region.id,\n\t\tremove_self = remove_self,\n\t\tretain_unique = retain_unique,\n\t\tncol = ncol,\n\t\tclass = c(\"sgbp\", \"list\"))\n\tif (! sparse)\n\t\tas.matrix(ret)\n\telse\n\t\tret\n}\n\n#' Methods for dealing with sparse geometry binary predicate lists\n#' \n#' Methods for dealing with sparse geometry binary predicate lists\n#' @name sgbp\n#' @export\n#' @param x object of class \\code{sgbp}\n#' @param ... ignored\n#' @param n integer; maximum number of items to print\n#' @param max_nb integer; maximum number of neighbours to print for each item\n#' @details \\code{sgbp} are sparse matrices, stored as a list with integer vectors holding the ordered \\code{TRUE} indices of each row. This means that for a dense, \\eqn{m \\times n}{m x n} matrix \\code{Q} and a list \\code{L}, if \\code{Q[i,j]} is \\code{TRUE} then \\eqn{j} is an element of \\code{L[[i]]}. Reversed: when \\eqn{k} is the value of \\code{L[[i]][j]}, then \\code{Q[i,k]} is \\code{TRUE}.\nprint.sgbp = function(x, ..., n = 10, max_nb = 10) {\n\tn = min(length(x), n)\n\thd = paste0(\"Sparse geometry binary predicate list of length \", length(x), \", \",\n\t \t\"where the predicate was `\", attr(x, \"predicate\"), \"'\")\n\tif (isTRUE(attr(x, \"retain_unique\")))\n\t\thd = paste0(hd, \", with retain_unique = TRUE\")\n\telse if (isTRUE(attr(x, \"remove_self\")))\n\t\thd = paste0(hd, \", with remove_self = TRUE\")\n\tcat(strwrap(hd), sep = \"\\n\")\n\tif (n < length(x))\n\t\tcat(\"first \", n, \" elements:\\n\", sep = \"\")\n\tnbh = function(i, m) {\n\t\tX = x[[i]]\n\t\tend = if (length(X) > m) \", ...\" else \"\"\n\t\tcat(\" \", i, \": \", sep = \"\")\n\t\tif (length(X))\n\t\t\tcat(paste(head(X, m), collapse = \", \"), end, \"\\n\", sep = \"\")\n\t\telse\n\t\t\tcat(\"(empty)\\n\")\n\t}\n\tlapply(1:n, nbh, m = max_nb)\n\tinvisible(x)\n}\n\n#' @name sgbp\n#' @export\nt.sgbp = function(x) {\n\tm = attr(x, \"ncol\")\n\tstructure(sgbp(CPL_transpose_sparse_incidence(x, m),\n\t\tpredicate = attr(x, \"predicate\"),\n\t\tregion.id = as.character(1:m),\n\t\tncol = length(x)),\n\t\tdim = NULL)\n}\n\n#' @name sgbp\n#' @export\nas.matrix.sgbp = function(x, ...) {\n\tnc = attr(x, \"ncol\")\n\tget_vec = function(x, n) { v = rep(FALSE, n); v[x] = TRUE; v }\n\tdo.call(rbind, lapply(x, get_vec, n = nc))\n}\n\n#' @name sgbp\n#' @export\ndim.sgbp = function(x) {\n\tc(length(x), attr(x, \"ncol\"))\n}\n\n#' @name sgbp\n#' @param e1 object of class `sgbp`\n#' @param e2 object of class `sgbp`\n#' @export\n#' @details `==` compares only the dimension and index values, not the attributes of two `sgbp` object; use `identical` to check for equality of everything.\nOps.sgbp = function(e1, e2) {\n\tswitch(.Generic, \n\t   \"!\" = {\n\t\t\tnc = 1:attr(e1, \"ncol\")\n\t\t\tsgbp(lapply(e1, function(x) setdiff(nc, x)),\n\t\t\t\tpredicate = paste0(\"!\", attr(e1, \"predicate\")),\n\t\t\t\tregion.id = attr(e1, \"region.id\"),\n\t\t\t\tncol = attr(e1, \"ncol\"))\n\t   },\n\t   \"==\" = (length(e1) == length(e2)) && all(mapply(function(x,y) identical(x, y), e1, e2)), \n\t   \"!=\" = return(!(e1 == e2)),\n\t\tstop(\"only operators !, == and != are supported for sgbp objects\")\n\t)\n}\n\n#' @name sgbp\n#' @export\nas.data.frame.sgbp = function(x, ...) {\n\tdata.frame(row.id = rep(seq_along(x), lengths(x)), col.id = unlist(x))\n}\n\nsetOldClass(\"sgbp\")\n\nsetAs(\"sgbp\", \"sparseMatrix\", function(from) {\n\tif (! requireNamespace(\"Matrix\", quietly = TRUE))\n\t\tstop(\"package Matrix required, please install it first\")\n\tidx = as.data.frame(from)\n\tMatrix::sparseMatrix(i = idx$row.id, j = idx$col.id, x = 1)\n})\n"
  },
  {
    "path": "R/shift_longitude.R",
    "content": "#' Shift or re-center geographical coordinates for a Pacific view\n#'\n#' @description\n#'   All longitudes < 0 are added to 360, to avoid for instance parts of Alaska\n#'   being represented on the far left and right of a plot because they have\n#'   values straddling 180 degrees. In general, using a projected\n#'   coordinate reference system is to be preferred, but this method permits a\n#'   geographical coordinate reference system to be used. This is the sf\n#'   equivalent of [recenter][sp::recenter] in the sp package and\n#'   `ST_ShiftLongitude` in PostGIS.\n#'\n#' @param x object of class `sf` or `sfc`\n#' @param ... ignored\n#'\n#' @export\nst_shift_longitude = function(x) {\n\tll = st_is_longlat(x)\n\tif (!isTRUE(ll))\n\t\tstop(\"'st_shift_longitude' requires non-projected geographic coordinates\",\n\t\t\t call. = FALSE)\n\n\tUseMethod(\"st_shift_longitude\")\n}\n\n#' @name st_shift_longitude\n#' @export\n#' @examples\n#' ## sfc\n#' pt1 = st_point(c(-170, 50))\n#' pt2 = st_point(c(170, 50))\n#' (sfc = st_sfc(pt1, pt2))\n#' sfc = st_set_crs(sfc, 4326)\n#' st_shift_longitude(sfc)\n#'\nst_shift_longitude.sfc = function(x, ...) {\n\txcrs = st_crs(x)\n\tg = (x + c(360, 90)) %% c(360) - c(0, 90)\n\tst_set_crs(g, xcrs)\n}\n\n#' @name st_shift_longitude\n#' @export\n#' @examples\n#' ## sf\n#' d = st_as_sf(data.frame(id = 1:2, geometry = sfc))\n#' st_shift_longitude(d)\nst_shift_longitude.sf = function(x, ...) {\n\tst_geometry(x) = st_shift_longitude(st_geometry(x))\n\tx\n}\n"
  },
  {
    "path": "R/sp.R",
    "content": "## Method coordinates\n## @name coordinates\n## @exportMethod coordinates\n#if (!isGeneric(\"coordinates\"))\n#    setGeneric(\"coordinates\", function(obj, ...)\n#\t\tstandardGeneric(\"coordinates\"))\n#\n#setMethod(\"coordinates\", \"sfc_POINT\",\n#\tfunction(obj, ...)\n#\t\tdo.call(rbind, obj)\n#)\n#\n#setMethod(\"coordinates\", \"sfc\",\n#\tfunction(obj, ...)\n#\t\tstop(\"coordinates for this object type not implemented\")\n#)\n#\n#setMethod(\"coordinates\", \"sf\",\n#\tfunction(obj, ...)\n#\t\tcoordinates(st_geometry(obj), ...)\n#)\n\n\n#' @rdname st_as_sf\n#' @examples\n#' if (require(sp, quietly = TRUE)) {\n#' x = rbind(c(-1,-1), c(1,-1), c(1,1), c(-1,1), c(-1,-1))\n#' x1 = 0.1 * x + 0.1\n#' x2 = 0.1 * x + 0.4\n#' x3 = 0.1 * x + 0.7\n#' y = x + 3\n#' y1 = x1 + 3\n#' y3 = x3 + 3\n#' m = matrix(c(3, 0), 5, 2, byrow = TRUE)\n#' z = x + m\n#' z1 = x1 + m\n#' z2 = x2 + m\n#' z3 = x3 + m\n#' p1 = Polygons(list( Polygon(x[5:1,]), Polygon(x2), Polygon(x3),\n#'    Polygon(y[5:1,]), Polygon(y1), Polygon(x1), Polygon(y3)), \"ID1\")\n#' p2 = Polygons(list( Polygon(z[5:1,]), Polygon(z2), Polygon(z3), Polygon(z1)),\n#'   \"ID2\")\n#' r = SpatialPolygons(list(p1,p2))\n#' a = suppressWarnings(st_as_sf(r))\n#' summary(a)\n#' demo(meuse, ask = FALSE, echo = FALSE)\n#' summary(st_as_sf(meuse))\n#' summary(st_as_sf(meuse.grid))\n#' summary(st_as_sf(meuse.area))\n#' summary(st_as_sf(meuse.riv))\n#' summary(st_as_sf(as(meuse.riv, \"SpatialLines\")))\n#' pol.grd = as(meuse.grid, \"SpatialPolygonsDataFrame\")\n#' # summary(st_as_sf(pol.grd))\n#' # summary(st_as_sf(as(pol.grd, \"SpatialLinesDataFrame\")))\n#' }\n#' @export\nst_as_sf.Spatial = function(x, ...) {\n\tif (\"data\" %in% slotNames(x)) {\n                if (!isTRUE(all.equal(row.names(x@data), row.names(x))))\n                    row.names(x@data) <- row.names(x)\n\t\tdf = x@data\n\t} else {\n\t\tdf = data.frame(row.names = row.names(x)) # empty\n        }\n\tif (\"geometry\" %in% names(df))\n\t\twarning(\"column \\\"geometry\\\" will be overwritten by geometry column\")\n\tif (! requireNamespace(\"sp\", quietly = TRUE))\n\t\tstop(\"package sp required, please install it first\")\n\tif (sp::gridded(x) && sp::fullgrid(x))\n\t\tsp::fullgrid(x) = FALSE\n\tdf$geometry = st_as_sfc(sp::geometry(x), ...)\n\tst_as_sf(df)\n}\n\n\n#' Convert foreign geometry object to an sfc object\n#'\n#' Convert foreign geometry object to an sfc object\n#' @param x object to convert\n#' @param ... further arguments\n#' @param precision precision value; see \\link{st_as_binary}\n#' @param forceMulti logical; if \\code{TRUE}, force coercion into \\code{MULTIPOLYGON} or \\code{MULTILINE} objects, else autodetect\n#' @export\nst_as_sfc = function(x, ...) UseMethod(\"st_as_sfc\")\n\nhandle_bbox = function(sfc, sp) {\n\tbb = structure(bb_wrap(as.vector(sp::bbox(sp)[1:2,])), class = \"bbox\")\n\tstructure(sfc, \"bbox\" = bb)\n}\n\n#' @rdname st_as_sfc\n#' @export\nst_as_sfc.SpatialPoints = function(x, ..., precision = 0.0) {\n\tcc = x@coords\n\tdimnames(cc) = NULL\n\tlst = lapply(seq_len(nrow(cc)), function(x) st_point(cc[x,]))\n\thandle_bbox(do.call(st_sfc, append(lst, list(crs = st_crs(x@proj4string), \n\t\tprecision = precision))), x)\n}\n\n#' @rdname st_as_sfc\n#' @export\nst_as_sfc.SpatialPixels = function(x, ..., precision = 0.0) {\n\thandle_bbox(st_as_sfc(as(x, \"SpatialPoints\"), precision = precision), x)\n}\n\n\n#' @rdname st_as_sfc\n#' @export\nst_as_sfc.SpatialMultiPoints = function(x, ..., precision = 0.0) {\n\tlst = lapply(x@coords, st_multipoint)\n\thandle_bbox(do.call(st_sfc, append(lst, list(crs = st_crs(x@proj4string),\n\t\tprecision = precision))), x)\n}\n\n#' @rdname st_as_sfc\n#' @export\nst_as_sfc.SpatialLines = function(x, ..., precision = 0.0, forceMulti = FALSE) {\n\tlst = if (forceMulti || any(sapply(x@lines, function(x) length(x@Lines)) != 1))\n\t\tlapply(x@lines, function(y) {\n                    crd_list <- lapply(y@Lines, function(z) z@coords)\n                    crd_list1 <- lapply(crd_list, function(z) {\n                         if (nrow(z) < 2L) res <- z[0,]\n                         else res <- z\n                         res\n                    })\n                    st_multilinestring(crd_list1)\n                })\n\telse\n\t\tlapply(x@lines, function(y) {\n                    crds = y@Lines[[1]]@coords\n                    if (nrow(crds) < 2L) res = st_linestring()\n                    else res = st_linestring(crds)\n                    res\n                })\n\thandle_bbox(do.call(st_sfc, append(lst, list(crs = st_crs(x@proj4string),\n\t\tprecision = precision))), x)\n}\n\n#' @rdname st_as_sfc\n#' @export\n\nst_as_sfc.SpatialPolygons = function(x, ..., precision = 0.0, forceMulti = FALSE) {\n\tlst = if (forceMulti || any(sapply(x@polygons, function(x) moreThanOneOuterRing(x@Polygons)))) {\n\t\tif (is.null(comment(x)) || comment(x) == \"FALSE\") {\n#\t\t\tif (!requireNamespace(\"rgeos\", quietly = TRUE))\n#\t\t\t\tstop(\"package rgeos required for finding out which hole belongs to which exterior ring\")\n#\t\t\tx = rgeos::createSPComment(x)\n\t\t\t# https://github.com/r-spatial/sf/pull/1869/files/7f1921c9acc1000b92a81b3a0aa7126330d4ef12..cfa303c8fcdd0b9a7ea33eae402c1135bb8e50ba :\n\t\t\t# warning(\"no comment found showing which hole belongs to which exterior ring\")\n\t\t\t# (warning causes revdep problem in pkg amt)\n\t\t\tprocess_pl_comment <- function(pl) {\n\t\t\t\tID <- slot(pl, \"ID\")\n\t\t\t\tcrds <- lapply(slot(pl, \"Polygons\"), function(xx) slot(xx, \"coords\"))\n\t\t\t\tholes <- sapply(slot(pl, \"Polygons\"), slot, \"hole\")\n\t\t\t\traw0 <- st_sfc(lapply(crds, function(x) st_polygon(list(x))))\n\t\t\t\tif (!any(holes)) {\n\t\t\t\t\tval <- st_union(st_make_valid(raw0))\n\t\t\t\t} else {\n\t\t\t\t\twkts <- vector(\"list\", sum(!holes))\n\t\t\t\t\tfor (i in seq_along(wkts)) {\n\t\t\t\t\t\twkts[[i]] <- st_as_text(raw0[!holes][i])\n\t\t\t\t\t}\n\t\t\t\t\tcp0 <- st_contains(raw0[!holes], raw0[holes])\n\t\t\t\t\tareas <- sapply(slot(pl, \"Polygons\"), slot, \"area\")\n\t\t\t\t\thole_assigned <- rep(FALSE, sum(holes))\n\t\t\t\t\tnames(cp0) <- seq_along(cp0)\n                                        cp1 <- cp0[order(areas[!holes])]\n\t\t\t\t\tfor (i in seq_along(cp1)) {\n                                          cp1i <- cp1[[i]]\n\t\t\t\t\t  tgt <- as.integer(names(cp1[i]))\n                                          if (length(cp1i) > 0L) {\n                                            for (j in cp1i) {\n\t\t\t\t\t      wkts[[tgt]] <- paste(sub(\"))\", \"),\", wkts[[tgt]]), sub(\"POLYGON \\\\(\", \"\", st_as_text(raw0[holes][j])))\n\t\t\t\t\t      hole_assigned[j] <- TRUE\n\t\t\t\t\t    }\n                                          }\n\t\t\t\t\t  for (ii in i:length(cp1)) {\n                                            for (j in cp1i) {\n\t\t\t\t\t      cp1[[ii]] <- setdiff(cp1[[ii]], j)\n\t\t\t\t\t    }\n\t\t\t\t\t  }\n\t\t\t\t\t}\n\t\t\t\t\tif (any(!hole_assigned))\n\t\t\t\t\t  warning(\"orphaned hole, cannot find containing polygon\")\n\t\t\t\t\traw0 <- st_as_sfc(wkts)\n                                        raw1 <- st_make_valid(raw0)\n                                        if (any(st_is(raw1, \"GEOMETRYCOLLECTION\"))) \n                                          raw1 <- st_collection_extract(raw1, \"POLYGON\")\n\t\t\t\t\tval <- st_union(raw1)\n\t\t\t\t}\n\t\t\t\tif (inherits(val, \"sfc_GEOMETRYCOLLECTION\"))\n\t\t\t\t\tval = st_collection_extract(val, \"POLYGON\")\n\t\t\t\tres <- slot(as(val, \"Spatial\"), \"polygons\")[[1]]\n\t\t\t\tslot(res, \"ID\") <- ID\n\t\t\t\tres\n\t\t\t}\n#\t\t\tprocess_pl_comment <- function(pl) {\n#\t\t\t\tID <- slot(pl, \"ID\")\n#\t\t\t\tcrds <- lapply(slot(pl, \"Polygons\"), function(xx) slot(xx, \"coords\"))\n#\t\t\t\traw <- st_sfc(st_polygon(crds))\n#\t\t\t\tval <- st_make_valid(raw)\n#\t\t\t\tif (inherits(val, \"sfc_GEOMETRYCOLLECTION\"))\n#\t\t\t\t\tval = st_collection_extract(val, \"POLYGON\")\n#\t\t\t\tres <- slot(as(val, \"Spatial\"), \"polygons\")[[1]]\n#\t\t\t\tslot(res, \"ID\") <- ID\n#\t\t\t\tres\n#\t\t\t}\n\t\t\tslot(x, \"polygons\") <- lapply(slot(x, \"polygons\"), process_pl_comment)\n\t\t\tcomment(x) <- \"TRUE\"\n\t\t}\n\t\tlapply(x@polygons, function(y)\n\t\t\tst_multipolygon(Polygons2MULTIPOLYGON(y@Polygons, comment(y))))\n\t} else\n\t\tlapply(x@polygons, function(y) st_polygon(Polygons2POLYGON(y@Polygons)))\n\thandle_bbox(do.call(st_sfc, append(lst, list(crs = st_crs(x@proj4string),\n\t\tprecision = precision))), x)\n}\n\nmoreThanOneOuterRing = function(PolygonsLst) {\n\tholes = sapply(PolygonsLst, function(x) x@hole)\n\tlength(holes) - length(which(holes)) > 1\n}\n\nPolygons2MULTIPOLYGON = function(PolygonsLst, cmt) {\n\tidx = scan(text = cmt, quiet = TRUE)\n\t# idx tells which outer rings (0) enclose which holes (idx == which(idx == 0))\n\touter_rings = which(idx == 0)\n\t# loop over outer_rings:\n\tlapply(outer_rings, function(x) Polygons2POLYGON(PolygonsLst[c(x, which(idx == x))]))\n}\n\nPolygons2POLYGON = function(PolygonsLst) {\n\t# here we have one outer ring, followed by (0+) holes inside this ring\n\tlapply(PolygonsLst, function(x) x@coords)\n}\n\n#' @name as\n#' @rdname coerce-methods\n#' @aliases Spatial sf-method\nsetAs(\"Spatial\", \"sf\", function(from) st_as_sf(from))\n\n#' @name as\n#' @rdname coerce-methods\n#' @aliases coerce Spatial sfc-method\nsetAs(\"Spatial\", \"sfc\", function(from) st_as_sfc(from))\n\n#' @name as\n#' @rdname coerce-methods\n#' @aliases coerce Spatial-method\nsetAs(\"sf\", \"Spatial\", function(from) {\n\tif (!requireNamespace(\"sp\", quietly = TRUE))\n\t\tstop(\"package sp required, please install it first\")\n\tgeom = st_geometry(from)\n\tfrom[[attr(from, \"sf_column\")]] = NULL # remove sf column list\n\tsp::addAttrToGeom(as_Spatial(geom, IDs = row.names(from)),\n\t\tdata.frame(from), match.ID = FALSE)\n})\n\n#' @name as\n#' @rdname coerce-methods\n#' @aliases coerce Spatial-method\nsetAs(\"sfc\", \"Spatial\", function(from) as_Spatial(from))\n\n# create empy class\nsetOldClass(\"XY\")\nsetAs(\"XY\", \"Spatial\", function(from) as(st_sfc(from), \"Spatial\"))\n\n#' Methods to coerce simple features to `Spatial*` and `Spatial*DataFrame` objects\n#'\n#' [as_Spatial()] allows to convert `sf` and `sfc` to `Spatial*DataFrame` and\n#' `Spatial*` for `sp` compatibility. You can also use `as(x, \"Spatial\")` To transform\n#' `sp` objects to `sf` and `sfc` with `as(x, \"sf\")`.\n#' @rdname coerce-methods\n#' @name as_Spatial\n#' @param from object of class `sf`, `sfc_POINT`, `sfc_MULTIPOINT`, `sfc_LINESTRING`,\n#' `sfc_MULTILINESTRING`, `sfc_POLYGON`, or `sfc_MULTIPOLYGON`.\n#' @param cast logical; if `TRUE`, [st_cast()] `from` before converting, so that e.g.\n#' `GEOMETRY` objects with a mix of `POLYGON` and `MULTIPOLYGON` are cast to `MULTIPOLYGON`.\n#' @param IDs character vector with IDs for the `Spatial*` geometries\n#' @details Package \\code{sp} supports three dimensions for `POINT` and `MULTIPOINT` (`SpatialPoint*`).\n#' Other geometries must be two-dimensional (`XY`). Dimensions can be dropped using\n#' [st_zm()] with `what = \"M\"` or `what = \"ZM\"`.\n#'\n#' For converting simple features (i.e., \\code{sf} objects) to their \\code{Spatial} counterpart, use \\code{as(obj, \"Spatial\")}\n#' @return geometry-only object deriving from `Spatial`, of the appropriate class\n#' @export\n#' @examples\n#' nc <- st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\n#' if (require(sp, quietly = TRUE)) {\n#' # convert to SpatialPolygonsDataFrame\n#' spdf <- as_Spatial(nc)\n#' # identical to\n#' spdf <- as(nc, \"Spatial\")\n#' # convert to SpatialPolygons\n#' as(st_geometry(nc), \"Spatial\")\n#' # back to sf\n#' as(spdf, \"sf\")\n#' }\nas_Spatial = function(from, cast = TRUE, IDs = paste0(\"ID\", seq_along(from))) {\n\tif (inherits(from, \"sf\")) {\n\t\tgeom = st_geometry(from)\n\t\tfrom[[attr(from, \"sf_column\")]] = NULL # remove sf column list\n\t\tif (ncol(from))\n\t\t\tsp::addAttrToGeom(as_Spatial(geom, cast = cast, IDs = row.names(from)),\n\t\t\t\t\t\t  data.frame(from), match.ID = FALSE)\n\t\telse {\n\t\t\tif (missing(IDs))\n\t\t\t\tIDs = paste0(\"ID\", seq_along(geom))\n\t\t\tas_Spatial(geom, cast, IDs)\n\t\t}\n\t} else {\n\t\t.as_Spatial(from, cast, IDs)\n\t}\n}\n\n.as_Spatial = function(from, cast = TRUE, IDs = paste0(\"ID\", seq_along(from))) {\n\tif (cast)\n\t\tfrom = st_cast(from)\n\tzm = class(from[[1]])[1]\n\tif (zm %in% c(\"XYM\", \"XYZM\"))\n\t\tstop(\"geometries containing M not supported by sp\\n\",\n\t\t\t 'use `st_zm(..., what = \"M\")`')\n\tif (any(st_is_empty(from)))\n\t\tstop(\"empty geometries are not supported by sp classes: conversion failed\")\n\tStopZ = function(zm) { \n\t\tif (zm == \"XYZ\")\n\t\t\tstop(\"sp supports Z dimension only for POINT and MULTIPOINT.\\n\",\n\t\t\t\t 'use `st_zm(...)` to coerce to XY dimensions')\n\t}\n\tswitch(class(from)[1],\n\t\t\"sfc_POINT\" = sfc2SpatialPoints(from),\n#\t\t\"sfc_POINT\" = sfc2SpatialPoints(from, IDs),\n\t\t\"sfc_MULTIPOINT\" = sfc2SpatialMultiPoints(from),\n\t\t\"sfc_LINESTRING\" = , \"sfc_MULTILINESTRING\" = { StopZ(zm); sfc2SpatialLines(from, IDs) },\n\t\t\"sfc_POLYGON\" = , \"sfc_MULTIPOLYGON\" = { StopZ(zm); sfc2SpatialPolygons(from, IDs) },\n\t\tstop(paste(\"conversion from feature type\", class(from)[1], \"to sp is not supported\"))\n\t)\n}\n\nsfc2SpatialPoints = function(from, IDs) {\n\tif (!requireNamespace(\"sp\", quietly = TRUE))\n\t\tstop(\"package sp required, please install it first\")\n\tsp::SpatialPoints(do.call(rbind, from), proj4string = as(st_crs(from), \"CRS\"))\n}\n\nsfc2SpatialMultiPoints = function(from) {\n\tif (!requireNamespace(\"sp\", quietly = TRUE))\n\t\tstop(\"package sp required, please install it first\")\n\tsp::SpatialMultiPoints(lapply(from, unclass), \n\t\tproj4string = as(st_crs(from), \"CRS\"))\n}\n\nsfc2SpatialLines = function(from, IDs = paste0(\"ID\", seq_along(from))) {\n\tif (!requireNamespace(\"sp\", quietly = TRUE))\n\t\tstop(\"package sp required, please install it first\")\n\tl = if (class(from)[1]  == \"sfc_MULTILINESTRING\")\n\t\tlapply(from, function(x) sp::Lines(lapply(x, function(y) sp::Line(unclass(y))), \"ID\"))\n\telse\n\t\tlapply(from, function(x) sp::Lines(list(sp::Line(unclass(x))), \"ID\"))\n\tfor (i in seq_along(from))\n\t\tl[[i]]@ID = IDs[i]\n\tsp::SpatialLines(l, proj4string = as(st_crs(from), \"CRS\"))\n}\n\nsfc2SpatialPolygons = function(from, IDs = paste0(\"ID\", seq_along(from))) {\n\tif (!requireNamespace(\"sp\", quietly = TRUE))\n\t\tstop(\"package sp required, please install it first\")\n\tl = if (class(from)[1] == \"sfc_MULTIPOLYGON\")\n\t\tlapply(from, function(x)  # for each sfc item, return a Polygons\n\t\t\t\tsp::Polygons(unlist(lapply(x, function(y) # to each sub-polygon,\n\t\t\t\t\tlapply(seq_along(y), function(i) sp::Polygon(y[[i]], i > 1))),\n\t\t\t\t\t\trecursive = FALSE), \"ID\"))\n\telse lapply(from, function(x)\n\t\tsp::Polygons(lapply(seq_along(x), function(i) sp::Polygon(x[[i]], i > 1)), \"ID\"))\n\n\t# set comment: ?Polygons: \"Exterior rings are coded zero, while interior rings are\n\t# coded with the 1-based index of the exterior ring to which they belong.\":\n\tfor (i in seq_along(from)) {\n\t\tl[[i]]@ID = IDs[i]\n\t\tif (class(from)[1] == \"sfc_MULTIPOLYGON\")\n\t\t\tcomm = get_comment(from[[i]])\n\t\telse\n\t\t\tcomm = c(0, rep(1, length(from[[i]])-1))\n\t\tcomment(l[[i]]) = paste(as.character(comm), collapse = \" \")\n\t}\n\tsp::SpatialPolygons(l, proj4string = as(st_crs(from), \"CRS\"))\n}\n\nget_comment = function(mp) { # for MULTIPOLYGON\n\tl = lapply(mp, function(from) c(0, rep(1, length(from) - 1)))\n\toffset = 0\n\tfor (i in seq_along(l)) {\n\t\tl[[i]] = l[[i]] + offset\n\t\toffset = offset + length(l[[i]])\n\t\tl[[i]][1] = 0\n\t}\n\tunlist(l)\n}\n\n#' @name as\n#' @rdname coerce-methods\n#' @aliases coerce crs CRS-method\nsetAs(\"crs\", \"CRS\", function(from) CRS_from_crs(from))\nCRS_from_crs = function(from) {\n\tif (! requireNamespace(\"sp\", quietly = TRUE))\n\t\tstop(\"package sp required, please install it first\")\n\tnm <- \"CRS\"\n\tattr(nm, \"package\") <- \"sp\" # See ?new:\n\tobj <- new(nm, projargs = from$proj4string)\n\tif (!is.na(from$wkt) && CPL_proj_version() >= \"6.0.0\" && CPL_gdal_version() >= \"3.0.0\")\n\t\tcomment(obj) <- from$wkt\n\tobj\n\t# we don't use sp::CRS(SRS_string = from$wkt) as rgdal may not be available,\n\t# which would break, and from$wkt has already been validated by GDAL:\n}\n"
  },
  {
    "path": "R/spatstat.R",
    "content": "# window_polygons_from_edges = function(w) {\n#\tmw = as.matrix(w$ends)\n#\tlst1 = lapply(seq_len(NROW(mw)), function(i) st_linestring(matrix(mw[i,], 2, byrow = TRUE)))\n#\tp0 = st_polygonize(do.call(c, do.call(st_sfc, lst1)))\n#\tif (length(p0) > 1) # multiple POLYGONs, returned as sfc_\n#\t\tdo.call(c, st_collection_extract(p0, \"POLYGON\")) # MULTIPOLYGON\n#\telse\n#\t\tst_cast(p0, \"POLYGON\")\n# }\n\nwrp = function(x) paste(strwrap(x), collapse = \"\\n\")\n\ncheck_spatstat_ll = function(x) {\n\tif (isTRUE(st_is_longlat(x)))\n\t\tstop(wrp(\"Only projected coordinates may be converted to spatstat class objects\"), call. = FALSE)\n}\n\ncheck_spatstat <- function(pkg, X = NULL) {\n\tif (!requireNamespace(pkg, quietly = TRUE))\n\t\tstop(\"package \", pkg, \" required, please install it (or the full spatstat package) first\", call. = FALSE)\n\tspst_ver <- try(packageVersion(\"spatstat\"), silent = TRUE)\n\tif (!inherits(spst_ver, \"try-error\") && spst_ver < \"2.0-0\")\n\t\tstop(wrp(paste0(\"You have an old version of spatstat installed that is incompatible with \", pkg, \n\t\t\t\". Please update spatstat (or uninstall it).\")), call. = FALSE)\n\tif (!is.null(X))\n\t\tcheck_spatstat_ll(X)\n}\n\n#' @name st_as_sf\n#' @export\n#' @examples\n#' if (require(spatstat.geom)) {\n#'   g = st_as_sf(gorillas)\n#'   # select only the points:\n#'   g[st_is(g, \"POINT\"),]\n#' }\nst_as_sf.ppp = function(x, ...) {\n\tcheck_spatstat(\"spatstat.geom\")\n\t# window:\n\twin = st_sf(label = \"window\", geom = st_as_sfc(spatstat.geom::as.owin(x)))\n\n\t# points:\n\tm = as.matrix(data.frame(x$x, x$y))\n\tpointwork = st_sfc(lapply(seq_len(NROW(m)), function(i) st_point(m[i,])))\n\tpoints_sf = st_sf(label = rep(\"point\", NROW(m)), geom = pointwork)\n\n\t# merge window and points:\n\tret = rbind(win, points_sf)\n\tif (spatstat.geom::is.marked(x)) {\n\t\t# add marks:\n\t\tm = as.data.frame(spatstat.geom::marks(x))\n\t\tcbind.sf(m[c(NA, seq_len(nrow(m))), , drop = FALSE], ret)\n\t} else\n\t\tret\n}\n\n#' @export\nst_as_sf.ppplist = function(x, ...) {\n\t.Deprecated(msg = \"see https://github.com/r-spatial/sf/issues/1926\") # sf 1.0-13, Mar 27 2023\n\tw = st_geometry(st_as_sf(x[[1]]))[1]\n\tsim = st_sfc(lapply(x, function(p) do.call(c, st_geometry(st_as_sf(p))[-1])))\n\tst_sf(label = c(\"window\", names(x)), geom = c(w, sim))\n}\n\n\n#' @name st_as_sf\n#' @export\nst_as_sf.psp = function(x, ...) {\n\tcheck_spatstat(\"spatstat.geom\")\n\t# line segments:\n\tm = as.matrix(x$ends)\n\tlst1 = lapply(seq_len(NROW(m)), function(i) st_linestring(matrix(m[i,], 2, byrow = TRUE)))\n\n\t# window:\n\twin = st_as_sfc(spatstat.geom::as.owin(x))[[1]]\n\n\tlabel = c(\"window\", rep(\"segment\", NROW(m)))\n\tret = st_sf(label = label, geom = st_sfc(c(list(win), lst1)))\n\tif (spatstat.geom::is.marked(x)) { # add marks:\n\t\tm = as.data.frame(spatstat.geom::marks(x))\n\t\tcbind.sf(m[c(NA, seq_len(nrow(m))), , drop = FALSE], ret)\n\t} else\n\t\tret\n}\n\n# 111117 from psp to SpatialLines, Rolf Turner, Adrian Baddeley, Mathieu Rajerison\n#' @export\nst_as_sfc.psp <- function(x, ...) {\n\n#\tends2line <- function(x) matrix(x, ncol=2, byrow=TRUE)\n#\tmunch <- function(z) { list(ends2line(as.numeric(z[1:4]))) }\n#\tends <- as.data.frame(x)[,1:4]\n#\ty <- lapply(seq_len(nrow(ends)), function(i) munch(ends[i,]))\n#\tst_sfc(st_multilinestring(y))\n\tst_geometry(st_as_sf(x, ...))\n}\n\n\n#' @name st_as_sf\n#' @export\n#' @examples\n#' if (require(spatstat.linnet)) {\n#'  data(chicago)\n#'  plot(st_as_sf(chicago)[\"label\"])\n#'  plot(st_as_sf(chicago)[-1,\"label\"])\n#' }\nst_as_sf.lpp = function(x, ...) {\n\tcheck_spatstat(\"spatstat.linnet\")\n\t# lines, polygon:\n\tlinework_sf = st_as_sf(spatstat.geom::as.psp(spatstat.geom::domain(x)))\n\t# points:\n\tm = as.matrix(as.data.frame(x$data)[1:2])\n\tpointwork = st_sfc(lapply(seq_len(NROW(m)), function(i) st_point(m[i,])))\n\tsf = rbind(linework_sf, st_sf(label = rep(\"point\", NROW(m)), geom = pointwork))\n\t# de-select point coordinates\n\tm = as.data.frame(x$data)[c(rep(NA,nrow(linework_sf)),seq_len(nrow(m))), -(1:2)]\n\tstructure(cbind.sf(sf, m), row.names = seq_len(nrow(m)))\n}\n\n# as.ppp etc methods: from maptools/pkg/R/spatstat1.R\n\nas.ppp.sfc = function(X, W = NULL, ..., check = TRUE) {\n\tcheck_spatstat(\"spatstat.geom\", X)\n\td = st_dimension(X)\n\tif (is.null(W)) {\n\t\tif (d[1] == 2 && all(d[-1] == 0)) {\n\t\t\tW = spatstat.geom::as.owin(X[1])\n\t\t\tX = X[-1]\n\t\t} else if (all(d == 0)) { # no window in first feature geometry:\n\t\t\tbb <- st_bbox(X)\n\t\t\tW = spatstat.geom::owin(bb[c(\"xmin\", \"xmax\")], bb[c(\"ymin\", \"ymax\")])\n\t\t\tif (missing(check))\n\t\t\t\tcheck = FALSE\n\t\t} else\n\t\t\tstop(\"sfc object does not consist of points, or a window followed by points\")\n\t}\n\tcc = st_coordinates(X)\n\tspatstat.geom::ppp(cc[,1], cc[,2], window = W, marks = NULL, check = check)\n}\n\nas.ppp.sf = function(X, ...) {\n\tcheck_spatstat(\"spatstat.geom\", X)\n\tpp = spatstat.geom::as.ppp(st_geometry(X), ...)\n\tif (st_dimension(X[1,]) == 2)\n\t\tX = X[-1,]\n\tst_geometry(X) = NULL # remove geometry column\n\n\tif (ncol(X) == 0) {\n\t\tpp\n\t} else {\n\t\tspatstat.geom::setmarks(pp, X)\n\t}\n}\n\nas.owin.POLYGON = function(W, ..., fatal, check_polygons = TRUE) {\n\tcheck_spatstat(\"spatstat.geom\", W)\n\tif (check_polygons)\n\t\tW = check_ring_dir(W)\n\tbb = st_bbox(W)\n\tspatstat.geom::owin(bb[c(\"xmin\", \"xmax\")], bb[c(\"ymin\", \"ymax\")], poly = W)\n}\n\nas.owin.MULTIPOLYGON = function(W, ..., fatal, check_polygons = TRUE) {\n\tcheck_spatstat(\"spatstat.geom\", W)\n\tif (check_polygons)\n\t\tW = check_ring_dir(W)\n\tbb = st_bbox(W)\n\tspatstat.geom::owin(bb[c(\"xmin\", \"xmax\")], bb[c(\"ymin\", \"ymax\")], \n\t\tpoly = unlist(W, recursive = FALSE))\n}\n\nas.owin.sfc_POLYGON = function(W, ..., fatal, check_polygons = TRUE) {\n\tcheck_spatstat_ll(W)\n\tif (check_polygons)\n\t\tW = check_ring_dir(W)\n\tas.owin.MULTIPOLYGON(W, check_polygons = FALSE)\n\t# I know, this looks wrong, but isn't: sfc_POLYGON is a logically a MULTIPOLYGON\n}\n\nas.owin.sfc_MULTIPOLYGON = function(W, ..., fatal, check_polygons = TRUE) {\n\tcheck_spatstat_ll(W)\n\tif (check_polygons)\n\t\tW = check_ring_dir(W)\n\tas.owin.sfc_POLYGON(st_cast(W, \"POLYGON\"), check_polygons = FALSE)\n}\n\nas.owin.sfc = function(W, ...) {\n\tif (!all(st_dimension(W) == 2))\n\t\tstop(\"as.owin.sfc needs polygonal geometries\")\n\tas.owin.sfc_MULTIPOLYGON(st_cast(W, \"MULTIPOLYGON\"), ...)\n}\n\nas.owin.sf = function(W, ...) {\n\tas.owin.sfc(st_geometry(W), ...)\n}\n\n#' @export\nst_as_sfc.owin = function(x, ..., crs = NA) {\n# FROM: methods for coercion to Spatial Polygons by Adrian Baddeley, pkg maptools\n\tcheck_spatstat(\"spatstat.geom\")\n\t# Check internal spatstat multiplier:\n\tmult <- x$units$multiplier\n\tif(is.null(mult)){\n\t\tmult <- 1\n\t}\n\tif(mult!=1){\n\t\twarning(\"The spatstat object has an measurement unit multiplier != 1. Consider rescaling before converting.\")\n\t}\n\t# Enforce polygonal format and proceed from there:\n\tx <- spatstat.geom::as.polygonal(x)\n\tclosering <- function(df) { df[c(seq(nrow(df)), 1), ] }\n\tpieces <- lapply(x$bdry,\n\t\tfunction(p) st_polygon(list(closering(cbind(p$x,p$y)))))\n\th = sapply(x$bdry, spatstat.utils::is.hole.xypolygon)   # holes\n\tholes = do.call(st_sfc, pieces[h])\n\texteriors = pieces = do.call(st_sfc, pieces[!h])\n\t# assign each hole to the smallest exterior it is covered by:\n\tcb = st_covered_by(holes, pieces)\n\tfor (i in seq_along(cb)) {\n\t\tw = which.min(st_area(exteriors[ cb[[i]] ]))\n\t\tpieces[[w]] = st_polygon(c(unclass(pieces[[w]]), unclass(holes[[i]])))\n\t}\n\tst_crs(pieces) = crs\n\tif (length(pieces) > 1) # multiple POLYGONs, collapse:\n\t\tst_sfc(do.call(c, pieces))\n\telse\n\t\tpieces\n}\n\n#' @export\nst_as_sf.owin = function(x, ...) {\n\tst_sf(geom = st_as_sfc(x, ...))\n}\n\n\n#' @export\nst_as_sfc.tess <- function(x, ...) {\n\tcheck_spatstat(\"spatstat.geom\")\n\tstopifnot(spatstat.geom::is.tess(x))\n\ty <- spatstat.geom::tiles(x)\n\tnam <- names(y)\n\tz <- list()\n\tfor(i in seq_along(y)) {\n\t\tzi <- try(st_as_sfc(y[[i]], nam[i]), silent=TRUE)\n\t\tif (inherits(zi, \"try-error\"))\n\t\t\twarning(paste(\"tile\", i, \"defective\\n\", as.character(zi)))\n\t\telse\n\t\t\tz[[i]] <- zi\n\t}\n\tdo.call(c, z)\n}\n\n# methods for 'as.psp' for sp classes by Adrian Baddeley\nas.psp.LINESTRING <- function(from, ..., window=NULL, marks=NULL, fatal) {\n\tcheck_spatstat(\"spatstat.geom\")\n\txy <- unclass(from)\n\tdf <- as.data.frame(cbind(xy[-nrow(xy), , drop=FALSE], xy[-1, , drop=FALSE]))\n\tif (is.null(window)) {\n\t\txrange <- range(xy[,1])\n\t\tyrange <- range(xy[,2])\n\t\twindow <- spatstat.geom::owin(xrange, yrange)\n\t}\n\tspatstat.geom::as.psp(df, window=window, marks=marks)\n}\n\nas.psp.MULTILINESTRING <- function(from, ..., window=NULL, marks=NULL, fatal) {\n\tcheck_spatstat(\"spatstat.geom\")\n\ty <- lapply(from, as.psp.LINESTRING, window=window)\n\tz <- do.call(spatstat.geom::superimpose,c(y,list(W=window)))\n\tif(!is.null(marks))\n\t\tspatstat.geom::setmarks(z, marks)\n\telse\n\t\tz\n}\n\nas.psp.sfc_MULTILINESTRING <- function(from, ..., window=NULL, marks=NULL,\n\t\t\tcharacterMarks=FALSE, fatal) {\n\n\tcheck_spatstat(\"spatstat.geom\", from)\n\tif(is.null(window)) {\n\t\tbb = st_bbox(from)\n\t\twindow = spatstat.geom::owin(bb[c(\"xmin\", \"xmax\")], bb[c(\"ymin\", \"ymax\")]) \n\t}\n\tlin <- unclass(from)\n\ty <- lapply(lin, as.psp.MULTILINESTRING, window=window)\n\tz <- do.call(spatstat.geom::superimpose, c(y, list(W = window)))\n\tif(!is.null(marks))\n\t\tspatstat.geom::setmarks(z, marks)\n\telse\n\t\tz\n}\n\nas.psp.sfc = function(from, ...) {\n\tas.psp.sfc_MULTILINESTRING(st_cast(from, \"MULTILINESTRING\"))\n}\n\nas.psp.sf <- function(from, ..., window=NULL, marks=NULL, fatal) {\n\tcheck_spatstat(\"spatstat.geom\", from)\n\n\ty <- st_geometry(from)\n\tif (!inherits(y, \"sfc_MULTILINESTRING\"))\n\t\tstop(\"geometries should be of type LINESTRING\")\n\tz <- spatstat.geom::as.psp(y, window=window, marks=marks)\n\tif(is.null(marks)) {\n\t\t# extract marks from first column of data frame\n\t\tst_geometry(from) = NULL # remove geometry column\n\t\tnseg.LINESTRING  <- function(x) { nrow(x) - 1 }\n\t\tnseg.MULTILINESTRING <- function(x) { sum(unlist(lapply(x, nseg.LINESTRING))) }\n\t\tnrep <- unlist(lapply(y, nseg.MULTILINESTRING))\n\t\tspatstat.geom::setmarks(z, from[rep(seq_len(nrow(from)), nrep),])\n\t} else\n\t\tz\n}\n"
  },
  {
    "path": "R/stars.R",
    "content": "#' functions to interact with gdal not meant to be called directly by users (but e.g. by stars::read_stars)\n#'\n#' @param x character vector, possibly of length larger than 1 when more than one raster is read\n#' @param ... ignored\n#' @param options character; raster layer read options\n#' @param driver character; driver short name; when empty vector, driver is auto-detected.\n#' @param read_data logical; if \\code{FALSE}, only the imagery metadata is returned\n#' @param NA_value (double) non-NA value to use for missing values; if \\code{NA}, when writing missing values are not specially flagged in output dataset, when reading the default (dataset) missing values are used (if present / set).\n#' @param RasterIO_parameters list with named parameters to GDAL's RasterIO; see the stars::read_stars documentation.\n#' @details These functions are exported for the single purpose of being used by package stars, they are not meant to be used directly and may change or disappear without prior notice or deprecation warnings.\n#' @name gdal\n#' @keywords internal\n#' @export\ngdal_read = function(x, ..., options = character(0), driver = character(0), read_data = TRUE, NA_value = NA_real_,\n\t\tRasterIO_parameters = list()) {\n\tif (is.numeric(read_data)) {\n\t\tmax_cells = as.double(read_data)\n\t\tread_data = FALSE\n\t} else\n\t\tmax_cells = as.double(-1.)\n\tCPL_read_gdal(as.character(x), as.character(options), as.character(driver), \n\t\tas.logical(read_data), as.double(NA_value), RasterIO_parameters, max_cells)\n}\n\n#' @rdname gdal\n#' @export\n#' @param type gdal write type\n#' @param geotransform length 6 numeric vector with GDAL geotransform parameters.\n#' @param update logical; \\code{TRUE} if in an existing raster file pixel values shall be updated.\n#' @param scale_offset length 2 numeric; contains scale and offset values\ngdal_write = function(x, ..., file, driver = \"GTiff\", options = character(0), type = \"Float32\", \n\t\tNA_value = NA_real_, geotransform, update = FALSE, scale_offset = c(1.0, 0.0)) {\n\n\tif (!requireNamespace(\"stars\", quietly = TRUE))\n\t\tstop(\"stars required: install that first\") # nocov\n\n\tif (any(scale_offset != c(1.0, 0.0)) && packageVersion(\"sf\") <= \"1.0-9\")\n\t\twarning(\"handling scale_offset requires sf > 1.0-9\")\n\td = stars::st_dimensions(x)\n\txydims = attr(d, \"raster\")$dimensions\n\tif (!isTRUE(all.equal(match(xydims, names(d)), 1:2)))\n\t\tstop(\"x and y raster dimensions need to be in place 1 and 2\")\n\tfrom = c(d[[1]]$from, d[[2]]$from) - 1\n\tdims = c(d[[1]]$to, d[[2]]$to)\n\tif (length(d) == 3)\n\t\tdims = c(dims, d[[3]]$to - d[[3]]$from + 1)\n\n\tif (inherits(x, \"stars_proxy\")) {\n\t\tmat = matrix(0, 0, 0) # nocov start\n\t\tonly_create = TRUE # don't write any pixel data\n\t\tif (!all(from == 0))\n\t\t\twarning(\"writing raster to original size\") # otherwise, geotransform needs to be modified\n\t\tfrom = c(0, 0) # nocov end\n\t} else {\n\t\tmat = x[[1]]\n\t\tdm = dim(mat)\n\t\tif (is.factor(mat)) {\n\t\t\trgba = NULL\n\t\t\tex = attr(mat, \"exclude\")\n\t\t\tif (is.null(ex))\n\t\t\t\tlev = c(\"\", levels(mat)) # add \"\" for value 0: R factors start at 1\n\t\t\telse {\n\t\t\t\tif (any(ex)) {\n\t\t\t\t\tlev = vector(\"character\", length(ex)) # fills with \"\"\n\t\t\t\t\tlev[!ex] = levels(mat)\n\t\t\t\t\trgba = if (!is.null(co <- attr(mat, \"rgba\"))) {\n\t\t\t\t\t\tn = length(ex)\n\t\t\t\t\t\tcoltab = cbind(rep(0., n), rep(0, n), rep(0, n), rep(255, n))\n\t\t\t\t\t\tcoltab[!ex,] = co\n\t\t\t\t\t\tcoltab \n\t\t\t\t\t}\n\t\t\t\t\tvalues = which(!ex) - 1\n\t\t\t\t\tmat = values[as.numeric(mat)]\n\t\t\t\t} else\n\t\t\t\t\tlev = levels(mat)\n\t\t\t}\n\t\t\tmat = structure(mat, class = NULL, levels = lev, dim = dm, rgba = rgba)\n\t\t}\n\t\tonly_create = FALSE # write x too\n\t\tif (! update) {\n\t\t\tif (!all(from == 0))\n\t\t\t\tstop(\"cannot write sub-rasters only\")\n\t\t\tif (!all(dims == dm))\n\t\t\t\tstop(\"dimensions don't match\")\n\t\t}\n\t\tdim(mat) = c(dm[1], prod(dm[-1])) # flatten to 2-D matrix\n\t}\n\tif (length(dims) == 2)\n\t\tdims = c(dims, 1) # one band\n\telse if (is.character(d[[3]]$values)) # add band descriptions?\n\t\tattr(mat, \"descriptions\") = d[[3]]$values\n\n\tCPL_write_gdal(mat, file, driver, options, type, dims, from, geotransform,\n\t\tst_crs(x)[[2]], as.double(NA_value), scale_offset, create = !update, \n\t\tonly_create = only_create)\n}\n\n#' @param gt double vector of length 6\n#' @rdname gdal\n#' @details gdal_inv_geotransform returns the inverse geotransform\n#' @export\ngdal_inv_geotransform = function(gt)\n\tCPL_inv_geotransform(as.double(gt))\n\n## @param x two-column matrix with columns and rows, as understood by GDAL; 0.5 refers to the first cell's center; \n## FIXME: this is now duplicate in sf and stars\nxy_from_colrow = function(x, geotransform, inverse = FALSE) {\n# http://www.gdal.org/classGDALDataset.html , search for geotransform:\n# 0-based indices:\n# Xp = geotransform[0] + P*geotransform[1] + L*geotransform[2];\n# Yp = geotransform[3] + P*geotransform[4] + L*geotransform[5];\n\tif (inverse) {\n\t\tgeotransform = gdal_inv_geotransform(geotransform) # nocov start\n\t\tif (anyNA(geotransform))\n\t\t\tstop(\"geotransform not invertible\") # nocov end\n\t}\n\tstopifnot(ncol(x) == 2)\n\tmatrix(geotransform[c(1, 4)], nrow(x), 2, byrow = TRUE) + \n\t\tx %*% matrix(geotransform[c(2, 3, 5, 6)], nrow = 2, ncol = 2)\n}\n\n# convert x/y gdal dimensions into a list of points, or a list of square polygons\n#' @export\nst_as_sfc.dimensions = function(x, ..., as_points = NA, use_cpp = TRUE, which = seq_len(prod(dim(x))),\n\t\tgeotransform) {\n\n\tif (is.na(as_points))\n\t\tstop(\"as_points should be set to TRUE (`points') or FALSE (`polygons')\")\n\n\txy2sfc = function(cc, dm, as_points) { # form points or polygons from a matrix with corner points\n\t\tif (as_points)\n\t\t\tunlist(apply(cc, 1, function(x) list(st_point(x))), recursive = FALSE)[which]\n\t\telse {\n\t\t\tstopifnot(prod(dm) == nrow(cc))\n\t\t\tlst = vector(\"list\", length = prod(dm - 1))\n\t\t\tfor (y in 1:(dm[2]-1)) {\n\t\t\t\tfor (x in 1:(dm[1]-1)) {\n\t\t\t\t\ti1 = (y - 1) * dm[1] + x      # top-left\n\t\t\t\t\ti2 = (y - 1) * dm[1] + x + 1  # top-right\n\t\t\t\t\ti3 = (y - 0) * dm[1] + x + 1  # bottom-right\n\t\t\t\t\ti4 = (y - 0) * dm[1] + x      # bottlom-left\n\t\t\t\t\tlst[[ (y-1)*(dm[1]-1) + x ]] = st_polygon(list(cc[c(i1,i2,i3,i4,i1),]))\n\t\t\t\t}\n\t\t\t}\n\t\t\tlst[which]\n\t\t}\n\t}\n\n\traster = attr(x, \"raster\")\n\txy_names = raster$dimensions\n\txd = x[[ xy_names[1] ]]\n\tyd = x[[ xy_names[2] ]]\n\tcc = if (!is.na(xd$offset) && !is.na(yd$offset)) {\n\t\txy = if (as_points) # grid cell centres:\n\t\t\t\texpand.grid(x = seq(xd$from, xd$to) - 0.5, y = seq(yd$from, yd$to) - 0.5)\n\t\t\telse # grid corners: from 0 to n\n\t\t\t\texpand.grid(x = seq(xd$from - 1, xd$to), y = seq(yd$from - 1, yd$to))\n\t\txy_from_colrow(as.matrix(xy), geotransform)\n\t} else if (is.null(xd$values) || is.null(yd$values)) { # only one of [xd|yd] has $values:\n\t\tif (!requireNamespace(\"stars\", quietly = TRUE)) # nocov start\n\t\t\tstop(\"stars required: install that first\")\n\t\tif (! as_points)\n\t\t\tstop(\"st_as_sfc(): mixed regular and rectilinear dimensions only supported if as_points = TRUE\")\n\t\tas.matrix(st_coordinates(x)) # nocov end\n\t} else { # both xd and yd have $values:\n\t\texpand = function(x) { # might fail on the poles or dateline\n\t\t\td = diff(x)\n\t\t\tc(x[1] - 0.5 * d[1], x + 0.5 * c(d, tail(d, 1)))\n\t\t}\n\t\tif (raster$curvilinear) { # expand jointly:\n\t\t\tif (!as_points && all(dim(xd$values) == dim(x)[xy_names])) { # expand from points to cells/polygons: \n\t\t\t\txd$values = apply((apply(xd$values, 1, expand)), 1, expand)\n\t\t\t\tyd$values = apply((apply(yd$values, 1, expand)), 1, expand)\n\t\t\t}\n\t\t\tcbind(as.vector(xd$values), as.vector(yd$values))\n\t\t} else { # rectlinear: expand independently\n\t\t\tif (! as_points) {\n\t\t\t\txd$values = if (inherits(xd$values, \"intervals\"))\n\t\t\t\t\t\tc(xd$values$start, tail(xd$values$end, 1))\n\t\t\t\t\telse\n\t\t\t\t\t\texpand(xd$values)\n\t\t\t\tyd$values = if (inherits(yd$values, \"intervals\"))\n\t\t\t\t\t\tc(yd$values$start, tail(yd$values$end, 1))\n\t\t\t\t\telse\n\t\t\t\t\t\texpand(yd$values)\n\t\t\t} else {\n\t\t\t\tif (inherits(xd$values, \"intervals\"))\n\t\t\t\t\txd$values = 0.5 * (xd$values$start + xd$values$end)\n\t\t\t\tif (inherits(yd$values, \"intervals\"))\n\t\t\t\t\tyd$values = 0.5 * (yd$values$start + yd$values$end)\n\t\t\t}\n\t\t\tas.matrix(expand.grid(x = xd$values, y = yd$values))\n\t\t}\n\t}\n\tdims = dim(x) + !as_points\n\tif (use_cpp) {\n\t\tbb = if (cc_has_NAs <- anyNA(cc))\n\t\t\t\tbbox.Mtrx(na.omit(cc))\n\t\t\telse\n\t\t\t\tbbox.Mtrx(cc)\n\t\tstructure(CPL_xy2sfc(cc, as.integer(dims), as_points, as.integer(which), cc_has_NAs), \n\t\t\tcrs = st_crs(xd$refsys), n_empty = 0L, bbox = bb)\n\t} else\n\t\tst_sfc(xy2sfc(cc, dims, as_points), crs = xd$refsys)\n}\n\n\n#' @details gdal_crs reads coordinate reference system from GDAL data set\n#' @param file character; file name\n#' @return object of class \\code{crs}, see \\link{st_crs}.\n#' @rdname gdal\n#' @export\ngdal_crs = function(file, options = character(0)) {\n\tst_crs(CPL_get_crs(file, options)$crs)\n}\n\n#' @details get_metadata gets metadata of a raster layer\n#' @rdname gdal\n#' @export\n#' @param domain_item character vector of length 0, 1 (with domain), or 2 (with domain and item); use \\code{\"\"} for the default domain, use \\code{NA_character_} to query the domain names.\n#' @param parse logical; should metadata be parsed into a named list (\\code{TRUE}) or returned as character data?\n#' @return named list with metadata items\n#' @examples\n#' \\dontrun{\n#'   f = system.file(\"tif/L7_ETMs.tif\", package=\"stars\")\n#'   f = system.file(\"nc/avhrr-only-v2.19810901.nc\", package = \"stars\")\n#'   gdal_metadata(f)\n#'   gdal_metadata(f, NA_character_)\n#'   try(gdal_metadata(f, \"wrongDomain\"))\n#'   gdal_metadata(f, c(\"\", \"AREA_OR_POINT\"))\n#' }\ngdal_metadata = function(file, domain_item = character(0), options = character(0), parse = TRUE) {\n\tstopifnot(is.character(file))\n\tstopifnot(is.character(domain_item))\n\tstopifnot(length(domain_item) <= 2)\n\tstopifnot(is.character(options))\n\tif (length(domain_item) >= 1 && !is.na(domain_item[1]) &&\n\t\t\t!(domain_item[1] %in% CPL_get_metadata(file, NA_character_, options)))\n\t\tstop(\"domain_item[1] not found in available metadata domains\")\n\tp = CPL_get_metadata(file, domain_item, options)\n\tif (!is.na(domain_item[1]) && parse)\n\t\tsplit_strings(p)\n\telse\n\t\tp\n}\n\nsplit_strings = function(md, split = \"=\") {\n\tsplt = strsplit(md, split)\n\tlst = lapply(splt, function(x) if (length(x) <= 1) NA_character_ else x[[2]])\n\tstructure(lst, names = sapply(splt, function(x) x[[1]]), class = \"gdal_metadata\")\n}\n\n#' @param name logical; retrieve name of subdataset? If \\code{FALSE}, retrieve description\n#' @export\n#' @return \\code{gdal_subdatasets} returns a zero-length list if \\code{file} does not have subdatasets, and else a named list with subdatasets.\n#' @rdname gdal\n#' @details gdal_subdatasets returns the subdatasets of a gdal dataset\ngdal_subdatasets = function(file, options = character(0), name = TRUE) {\n\tif (!(\"SUBDATASETS\" %in% CPL_get_metadata(file, NA_character_, options)))\n\t\tlist()\n\telse {\n\t\tmd = gdal_metadata(file, \"SUBDATASETS\", options, TRUE)\n\t\tif (name)\n\t\t\tmd[seq(1, length(md), by = 2)]\n\t\telse\n\t\t\tmd[seq(2, length(md), by = 2)]\n\t}\n}\n\n#' @param use_integer boolean; if \\code{TRUE}, raster values are read as (and rounded to) unsigned 32-bit integers values; if \\code{FALSE} they are read as 32-bit floating points numbers. The former is supposedly faster.\n#' @param mask stars object with NA mask (0 where NA), or NULL\n#' @param breaks numeric vector with break values for contour polygons (or lines)\n#' @param use_contours logical;\n#' @param contour_lines logical;\n#' @param connect8 logical; if \\code{TRUE} use 8 connection algorithm, rather than 4\n#' @rdname gdal\n#' @export\ngdal_polygonize = function(x, mask = NULL, file = tempfile(), driver = \"GTiff\", use_integer = TRUE,\n\t\tgeotransform, breaks = classInt::classIntervals(na.omit(as.vector(x[[1]])))$brks, \n\t\tuse_contours = FALSE, contour_lines = FALSE, connect8 = FALSE, ...) {\n\tgdal_write(x, file = file, driver = driver, geotransform = geotransform) # nocov start\n\ton.exit(unlink(file))\n\tmask_name = if (!is.null(mask)) {\n\t\t\tmask_name = tempfile()\n\t\t\tgdal_write(mask, file = mask_name, driver = driver, geotransform = geotransform)\n\t\t\ton.exit(unlink(mask_name))\n\t\t\tmask_name\n\t\t} else\n\t\t\tcharacter(0)\n\tcontour_options = if (use_contours) { # construct contour_options:\n\t\t\tnbreaks = breaks\n\t\t\tif (max(breaks) == max(x[[1]], na.rm = TRUE)) # expand, because GDAL will not include interval RHS\n\t\t\t\tnbreaks[length(nbreaks)] = breaks[length(breaks)] * 1.01\n\t\t\tc(paste0(\"FIXED_LEVELS=\", paste0(nbreaks, collapse = \",\")),\n\t\t\t\"ELEV_FIELD=0\", \"ELEV_FIELD_MIN=1\", \"ELEV_FIELD_MAX=2\",\n\t\t\tpaste0(\"POLYGONIZE=\", ifelse(contour_lines, \"NO\", \"YES\")))\n\t\t} else\n\t\t\tcharacter(0)\n\n\toptions = if (connect8)\n\t\t\t\"8CONNECTED=8\"\n\t\telse\n\t\t\tcharacter(0)\n\n\tmem = ifelse(compareVersion(sf_extSoftVersion()[\"GDAL\"], \"3.11.0\") >= 0, \"MEM\", \"Memory\")\n\tpol = CPL_polygonize(file, mask_name, \"GTiff\", mem, \"foo\", options, 0, \n\t\tcontour_options, use_contours, use_integer)\n\tout = process_cpl_read_ogr(pol, quiet = TRUE)\n\tnames(out)[1] = names(x)[1]\n\tif (! contour_lines && use_contours) {\n#\t\tif (out$Min[1] == 0 && out$Min[1] > min(breaks))\n#\t\t\tout$Min[1] = -Inf\n#\n# https://github.com/r-spatial/sf/pull/1608 : \n\n\t\ti <- match(out$Max[1], sort(breaks))\n\t\tout$Min[1] = if (!is.na(i) && i > 1)\n\t\t\t\tsort(breaks)[i - 1]\n\t\t\telse \n\t\t\t\t-Inf\n\n\t\tout$Max[out$Max == 2^32 - 1] = Inf\n\t\tf = paste0(\"[\", out$Min, \",\", out$Max, \")\")\n\t\tout[[1]] = factor(f, levels = f)\n\t} else\n\t\tout$Min = out$Max = NULL\n\tout # nocov end\n}\n\n#' @param sf object of class \\code{sf}\n#' @name gdal\n#' @export\ngdal_rasterize = function(sf, x, gt, file, driver = \"GTiff\", options = character()) {\n\tgdal_write(x, file = file, driver = driver, geotransform = gt)\n\tgeoms = which(sapply(sf, inherits, \"sfc\"))\n\tvalues = as.double(t(as.matrix(as.data.frame(sf)[-geoms])))\n\tCPL_rasterize(file, driver, st_geometry(sf), values, options, NA_real_);\n}\n\n#' @export\n#' @rdname gdal\n#' @param f gdal raster data source filename\n#' @param pts points matrix\n#' @param resampling character; resampling method; for method cubic or cubicspline, \n#' `stars_proxy` objects should be used and GDAL should have version >= 3.10.0\ngdal_extract = function(f, pts, resampling = c(\"nearest\", \"bilinear\", \"cubic\", \"cubicspline\")) {\n\tCPL_extract(f, pts, match.arg(resampling))\n}\n\n#' @rdname gdal\n#' @param file file name\n#' @param array_name array name\n#' @param offset offset (pixels)\n#' @param count number of pixels to read\n#' @param step step size (pixels)\n#' @param proxy logical; return proxy object?\n#' @param debug logical; print debug messages?\n#' @export\ngdal_read_mdim = function(file, array_name = character(0), options = character(0),\n\t\t\t\t\t\t  offset = integer(0), count = integer(0), step = integer(0), \n\t\t\t\t\t\t  proxy = FALSE, debug = FALSE) {\n\tCPL_read_mdim(file, array_name, options, offset, count, step, proxy, debug)\n}\n\n#' @rdname gdal\n#' @param dimx integer named vector with dimensions of object\n#' @param cdl list with variables, each having a named dim attribute\n#' @param wkt character; WKT of crs\n#' @param xy character; names of the spatial x and y dimension\n#' @param root_group_options character; driver specific options regarding the creation of the root group\n#' @param options character; driver specific options regarding reading or creating the dataset\n#' @param as_float logical; when \\code{TRUE} write 4-byte floating point numbers, when \\code{FALSE} write 8-byte doubles.\n#' @export\ngdal_write_mdim = function(file, driver, dimx, cdl, wkt, xy, ...,\n\t\t\t\t\t\t   root_group_options = character(0), options = character(0),\n\t\t\t\t\t\t   as_float = TRUE) {\n    CPL_write_mdim(file, driver, dimx, cdl, wkt, xy, root_group_options, options, as_float)\n}\n\n\n#' @name gdal\n#' @param f character; file name\n#' @param nxy integer vector of length 2\n#' @param values fill value\n#' @param crs object of class \\code{crs}\n#' @param xlim numeric\n#' @param ylim numeric\n#' @export\ngdal_create = function(f, nxy, values, crs, xlim, ylim) {\n\tCPL_create(as.character(f), as.integer(nxy), as.double(values), crs$wkt, as.double(xlim), as.double(ylim))\n}\n\n#' Add or remove overviews to/from a raster image\n#'\n#' add or remove overviews to/from a raster image\n#' @param file character; file name\n#' @param overviews integer; overview levels\n#' @param method character; method to create overview; one of: nearest, average, rms, gauss, cubic, cubicspline, lanczos, average_mp, average_magphase, mode\n#' @param layers integer; layers to create overviews for (default: all)\n#' @param options character; dataset opening options\n#' @param config_options named character vector with GDAL config options, like \\code{c(option1=value1, option2=value2)}\n#' @param clean logical; if \\code{TRUE} only remove overviews, do not add\n#' @param read_only logical; if \\code{TRUE}, add overviews to another file with extension \\code{.ovr} added to \\code{file}\n#' @return \\code{TRUE}, invisibly, on success\n#' @seealso \\link{gdal_utils} for access to other gdal utilities that have a C API\n#' @export\ngdal_addo = function(file, overviews = c(2,4,8,16), method = \"NEAREST\", layers = integer(0), \n\t\t\t\t\t options = character(0), config_options = character(0), clean = FALSE, read_only = FALSE) {\n\tstopifnot(length(method) == 1, is.character(method), is.numeric(overviews), is.character(config_options))\n\tinvisible(CPL_gdaladdo(file, method, as.integer(overviews), as.integer(layers), as.character(options), \n\t\t\t\t config_options, as.logical(clean)[1], as.logical(read_only)[1]))\n}\n\n#' List GDAL compressors and decompressors\n#'\n#' List GDAL compressors and decompressors\n#' @return named list with two character vectors, containing compressors and decompressors\n#' @export\ngdal_compressors = function() {\n\tCPL_compressors()\n}\n"
  },
  {
    "path": "R/terra.R",
    "content": "# see https://github.com/r-spatial/sf/issues/1567\n#' @export\nst_as_sf.SpatVector = function(x, ..., hex = TRUE, crs = st_crs(x)) {\n\tif(!requireNamespace(\"terra\", quietly = TRUE))\n\t\tstop(\"package terra required, please install it first\")\n\tif (!utils::packageVersion(\"terra\") >= \"1.1-5\")\n\t\tstop(\"package terra version 1.1-5 required\")\n\td <- terra::as.data.frame(x, geom = \"hex\")\n\td$geometry <- structure(as.list(d$geometry), class = \"WKB\")\n\tst_as_sf(d, crs = crs)\n}\n\n#' @export\nst_crs.SpatRaster = function(x, ...) {\n\tif (!requireNamespace(\"terra\", quietly = TRUE))\n\t\tstop(\"package terra required, please install it first\") # nocov\n\tstring = terra::crs(x)\n\tif (string == \"\") \n\t\tNA_crs_\n\telse\n\t\tst_crs(string)\n}\n\n#' @export\nst_crs.SpatVector = st_crs.SpatRaster\n\n#' @export\nst_bbox.SpatExtent = function(obj, ..., crs = NA_crs_) {\n\tif (!requireNamespace(\"terra\", quietly = TRUE))\n\t\tstop(\"package terra required, please install it first\") # nocov\n\tbb = as.vector(obj)[c(1,3,2,4)]\n\tnames(bb) = c(\"xmin\", \"ymin\", \"xmax\", \"ymax\")\n\tst_bbox(bb, crs = crs)\n}\n\n#' @export\nst_bbox.SpatRaster = function(obj, ...) {\n\tif (!requireNamespace(\"terra\", quietly = TRUE))\n\t\tstop(\"package terra required, please install it first\") # nocov\n\tst_bbox(terra::ext(obj), crs = st_crs(obj))\n}\n\n#' @export\nst_bbox.SpatVector = function(obj, ...) {\n\tif (!requireNamespace(\"terra\", quietly = TRUE))\n\t\tstop(\"package terra required, please install it first\") # nocov\n    bb = as.vector(terra::ext(obj))[c(1,3,2,4)]\n    names(bb) = c(\"xmin\", \"ymin\", \"xmax\", \"ymax\")\n    st_bbox(bb, crs = st_crs(obj))\n}\n"
  },
  {
    "path": "R/tidyverse-vctrs.R",
    "content": "types = c(\"POINT\", \"MULTIPOINT\", \"LINESTRING\", \"MULTILINESTRING\", \n            \"POLYGON\", \"MULTIPOLYGON\", \"GEOMETRYCOLLECTION\", \"GEOMETRY\",\n\t\t\t\"MULTISURFACE\", \"CURVEPOLYGON\")\nsfc_types = paste0(\"sfc_\", types)\n\n# All S3 methods in this file are registered lazily when vctrs is loaded\nregister_vctrs_methods = function() {\n  # Register vec_proxy, vec_restore, vec_ptype for all types\n  for (type in sfc_types) {\n    s3_register(\"vctrs::vec_proxy\", type)\n    s3_register(\"vctrs::vec_proxy_order\", type)\n    s3_register(\"vctrs::vec_restore\", type)\n    s3_register(\"vctrs::vec_ptype\", type)\n  }\n  \n  # Register vec_ptype2 for all pairs\n  for (i in seq_along(sfc_types)) {\n    for (j in seq_along(sfc_types)) {\n      s3_register(\"vctrs::vec_ptype2\", paste0(sfc_types[i], \".\", sfc_types[j]))\n    }\n  }\n  \n  # Register vec_cast for all pairs\n  for (i in seq_along(sfc_types)) {\n    for (j in seq_along(sfc_types)) {\n      s3_register(\"vctrs::vec_cast\", paste0(sfc_types[i], \".\", sfc_types[j]))\n    }\n  }\n  s3_register(\"vctrs::vec_proxy\", \"sf\")\n  s3_register(\"vctrs::vec_restore\", \"sf\")\n  s3_register(\"vctrs::vec_ptype2\", \"sf.sf\")\n  s3_register(\"vctrs::vec_ptype2\", \"sf.data.frame\")\n  s3_register(\"vctrs::vec_ptype2\", \"data.frame.sf\")\n  s3_register(\"vctrs::vec_ptype2\", \"sf.tbl_df\")\n  s3_register(\"vctrs::vec_ptype2\", \"tbl_df.sf\")\n  s3_register(\"vctrs::vec_cast\", \"sf.sf\")\n  s3_register(\"vctrs::vec_cast\", \"data.frame.sf\")\n  s3_register(\"vctrs::vec_cast\", \"sf.data.frame\")\n  s3_register(\"vctrs::vec_cast\", \"sf.tbl_df\")\n  s3_register(\"vctrs::vec_cast\", \"tbl_df.sf\")\n}\n\nvec_proxy_sfc = function(x) sf_unstructure(x)\n\nvec_restore_sfc = function(x, to) {\n\tst_sfc(\n\t\tx,\n\t\tcrs = st_crs(to),\n\t\tprecision = st_precision(to),\n\t\tfall_back_class = class(to)\n\t)\n}\n\nvec_ptype_sfc = function(x) {\n\tst_sfc(\n\t\tcrs = st_crs(x),\n\t\tprecision = st_precision(x),\n\t\tfall_back_class = class(x)\n\t)\n}\n\n#vec_proxy_order_sfc = function(x, ...) {\n  # Same as `vctrs:::vec_proxy_order.list()`.\n  # Allows sfc columns to be \"sorted\" by first appearance.\n#  xtfrm(x)\n#}\n\nvec_proxy_order_sfc = function(x, ...) {\n  # Same as `vctrs:::vec_proxy_order.list()`.\n  # Allows sfc columns to be \"sorted\" by first appearance.\n  x = sf_unstructure(x)\n  out = vctrs::vec_duplicate_id(x)\n  if (vctrs::vec_any_missing(x)) {\n    missing = vctrs::vec_detect_missing(x)\n    out = vctrs::vec_assign(out, missing, NA_integer_)\n  }\n  out\n}\n\n# sfc single methods:\nfor (type in sfc_types) {\n  assign(paste0(\"vec_proxy.\", type), function(x, y, ...) vec_proxy_sfc(x))\n  assign(paste0(\"vec_proxy_order.\", type), function(x, y, ...) vec_proxy_order_sfc(x))\n  assign(paste0(\"vec_restore.\", type), function(x, to, ...) vec_restore_sfc(x, to))\n  assign(paste0(\"vec_ptype.\", type), function(x, ...) vec_ptype_sfc(x))\n}\n\n# Single implementation that works for all type pairs\nvec_ptype2_impl = function(x, y) {\n  check_same_crs(x, y)\n  check_same_precision(x, y)\n  if (identical(class(x), class(y)))\n    x\n  else # return empty sfc_GEOMETRY for mixed types\n    st_sfc(crs = st_crs(x), precision = st_precision(x))\n}\n\n# Then assign to all pairs\nfor (type1 in sfc_types) {\n  for (type2 in sfc_types) {\n    assign(paste0(\"vec_ptype2.\", type1, \".\", type2), \n           function(x, y, ...) vec_ptype2_impl(x, y))\n  }\n}\n\nfor (type1 in sfc_types) {\n  for (type2 in sfc_types) {\n\tif (type1 == type2)\n      assign(paste0(\"vec_cast.\", type1, \".\", type2), \n             function(x, to, ...) vec_cast_sfc_sfc(x, to))\n\telse \n      assign(paste0(\"vec_cast.\", type1, \".\", type2), \n             function(x, to, ...) vec_cast_to_geometry(x, to))\n  }\n}\n\nvec_cast_sfc_sfc = function(x, to) {\n\tcheck_same_crs(x, to)\n\tcheck_same_precision(x, to)\n\tx\n}\n\nvec_cast_to_geometry = function(x, to) {\n\tcheck_same_crs(x, to)\n\tcheck_same_precision(x, to)\n\tst_cast(x, \"GEOMETRY\")\n}\n\n## sf methods:\nsf_unstructure = function(x) {\n\tif (is.data.frame(x)) {\n\t\tx = vctrs::new_data_frame(x, row.names = .row_names_info(x, 0L))\n\t} else if (!is.null(dim(x))) {\n\t\tattributes(x) = list(dim = dim(x), dimnames = dimnames(x))\n\t} else {\n\t\tattributes(x) = list(names = names(x))\n\t}\n\tx\n}\n\nvec_proxy.sf = function(x, ...) {\n  # Strip attributes to ensure `vec_restore()`'s call to `st_as_sf()` uses the\n  # data frame S3 method, and can't use any information from `x`'s original\n  # `sf` state\n  sf_unstructure(x)\n}\n\nvec_restore.sf = function(x, to, ...) {\n  # Due to the way `vec_ptype()` works, `vec_df_restore()` will preemptively\n  # restore the `to` attributes by straight up copying them over. We really\n  # don't want that! `sf::st_as_sf()` needs to S3 dispatch to the data frame\n  # method. If `to` attributes are preemptively restored (including the class)\n  # then it will instead dispatch on the sf method, and will \"reuse\"\n  # attributes from `x`, which is incorrect. It should only use `to`\n  # attributes when restoring. See TODO in `vec_df_restore()`.\n  x = sf_unstructure(x)\n\n  sf_column_name = attr(to, \"sf_column\")\n  crs = st_crs(to)\n  prec = st_precision(to)\n  if (inherits(to, \"tbl_df\"))\n    x = tibble::as_tibble(x)\n\n  st_as_sf(\n    x,\n    sf_column_name = sf_column_name,\n    crs = crs,\n    precision = prec,\n    stringsAsFactors = FALSE\n  )\n}\n\nsf_ptype2 = function(x, y, ...) {\n  data = vctrs::df_ptype2(x, y, ...)\n\n  # Take active geometry from left-hand side\n  sf_column_name = attr(x, \"sf_column\")\n\n  # CRS and precision must match\n  check_same_crs(x, y)\n  check_same_precision(x, y)\n\n  st_as_sf(data, sf_column_name = sf_column_name)\n}\n\nvec_ptype2.sf.sf = function(x, y, ...) {\n  sf_ptype2(x, y, ...)\n}\n\nvec_ptype2.sf.data.frame = function(x, y, ...) {\n  vctrs::df_ptype2(x, y, ...)\n}\nvec_ptype2.data.frame.sf = function(x, y, ...) {\n  vctrs::df_ptype2(x, y, ...)\n}\n\nvec_ptype2.sf.tbl_df = function(x, y, ...) {\n  vctrs::tib_ptype2(x, y, ...)\n}\nvec_ptype2.tbl_df.sf = function(x, y, ...) {\n  vctrs::tib_ptype2(x, y, ...)\n}\n\n#sf_cast = function(x, to, ...) {\n#  data = vctrs::df_cast(x, to, ...)\n#\n#  sf_column_name = attr(to, \"sf_column\")\n#  crs = st_crs(to)\n#  prec = st_precision(to)\n#\n#  st_as_sf(\n#    data,\n#    sf_column_name = sf_column_name,\n#    crs = crs,\n#    precision = prec,\n#    stringsAsFactors = FALSE\n#  )\n#}\n\nsf_cast = function(x, to, ...) {\n  data = vctrs::df_cast(x, to, ...)\n\n  # CRS and precision must match\n  check_same_crs(x, to)\n  check_same_precision(x, to)\n  if (inherits(to, \"tbl_df\"))\n    data = tibble::as_tibble(data)\n\n  sf_column_name = attr(to, \"sf_column\")\n\n  st_as_sf(data, sf_column_name = sf_column_name)\n}\n\n# Because `vec_ptype2.sf.sf()` returns a sf\nvec_cast.sf.sf = function(x, to, ...) {\n  sf_cast(x, to, ...)\n}\n\n# Because `vec_ptype2.sf.data.frame()` returns a data frame\nvec_cast.data.frame.sf = function(x, to, ...) {\n  vctrs::df_cast(x, to, ...)\n}\n# Opt out of `vec_default_cast()` support for data.frame -> sf.\n# Would never be called automatically, and likely not meaningful.\nvec_cast.sf.data.frame = function(x, to, ..., x_arg = \"\", to_arg = \"\") {\n  vctrs::stop_incompatible_cast(x, to, x_arg = x_arg, to_arg = to_arg)\n}\n\n# Because `vec_ptype2.sf.tbl_df()` returns a tibble\nvec_cast.tbl_df.sf = function(x, to, ...) {\n  vctrs::tib_cast(x, to, ...)\n}\n# Opt out of `vec_default_cast()` support for tibble -> sf.\n# Would never be called automatically, and likely not meaningful.\nvec_cast.sf.tbl_df = function(x, to, ..., x_arg = \"\", to_arg = \"\") {\n  vctrs::stop_incompatible_cast(x, to, x_arg = x_arg, to_arg = to_arg)\n}\n\n# Take conservative approach of requiring equal CRS\ncheck_same_crs = function(x, y) {\n  lhs = st_crs(x)\n  rhs = st_crs(y)\n  \n  if (lhs != rhs)\n    stop(paste(\"CRS mismatch:\",  lhs$input, \"vs\", rhs$input), \n         call. = FALSE)\n  invisible()\n}\n\ncheck_same_precision = function(x, y) {\n  lhs = st_precision(x)\n  rhs = st_precision(y)\n  \n  if (lhs != rhs) \n    stop(paste(\"Precision mismatch:\", lhs, \"vs\", rhs), call. = FALSE)\n  invisible()\n}\n"
  },
  {
    "path": "R/tidyverse.R",
    "content": "## dplyr methods: ------\n#group_map.sf <- function(.tbl, .f, ...) {\n#\t st_as_sf(NextMethod()) # nocov\n#}\n\n# This is currently only used in `bind_rows()` and `bind_cols()`\n# because sf overrides all default implementations\ndplyr_reconstruct.sf = function(data, template) {\n\tsfc_name = attr(template, \"sf_column\")\n\tif (inherits(template, \"tbl_df\"))\n\t\tdata = dplyr::as_tibble(data)\n\t# Return a bare data frame if the geometry column is no longer there\n\tif (sfc_name %in% names(data)) # reconstruct sf:\n\t\tst_as_sf(\n\t\t\tdata,\n\t\t\tsf_column_name = sfc_name,\n\t\t\tcrs = st_crs(template),\n\t\t\tprecision = st_precision(template)\n\t\t)\n\telse\n\t\tdata\n}\n\n#' Tidyverse methods for sf objects\n#'\n#' Tidyverse methods for sf objects. Geometries are sticky, use \\link{as.data.frame} to let \\code{dplyr}'s own methods drop them.\n#' Use these methods after loading the tidyverse package with the generic (or after loading package tidyverse).\n#' @param .data data object of class \\link{sf}\n#' @param .dots see corresponding function in package \\code{dplyr}\n#' @param ... other arguments\n#' @name tidyverse\n#' @examples\n#' if (require(dplyr, quietly = TRUE)) {\n#'  nc = read_sf(system.file(\"shape/nc.shp\", package=\"sf\"))\n#'  nc |> filter(AREA > .1) |> plot()\n#'  # plot 10 smallest counties in grey:\n#'  st_geometry(nc) |> plot()\n#'  nc |> select(AREA) |> arrange(AREA) |> slice(1:10) |> plot(add = TRUE, col = 'grey')\n#'  title(\"the ten counties with smallest area\")\n#'  nc2 <- nc |> mutate(area10 = AREA/10)\n#'  nc |> slice(1:2)\n#' }\nfilter.sf <- function(.data, ..., .dots) {\n\tagr = st_agr(.data)\n\tclass(.data) <- setdiff(class(.data), \"sf\")\n\t.re_sf(NextMethod(), sf_column_name = attr(.data, \"sf_column\"), agr)\n}\n\n#' @name tidyverse\n#' @examples\n#' # plot 10 smallest counties in grey:\n#' if (require(dplyr, quietly = TRUE)) {\n#'  st_geometry(nc) |> plot()\n#'  nc |> select(AREA) |> arrange(AREA) |> slice(1:10) |> plot(add = TRUE, col = 'grey')\n#'  title(\"the ten counties with smallest area\")\n#' }\narrange.sf <- function(.data, ..., .dots) {\n\tsf_column_name = attr(.data, \"sf_column\")\n\tclass(.data) = setdiff(class(.data), \"sf\")\n\tst_as_sf(NextMethod(), sf_column_name = sf_column_name)\n}\n\n#' @name tidyverse\n#' @param add see corresponding function in dplyr\n#' @examples\n#' if (require(dplyr, quietly = TRUE)) {\n#'  nc$area_cl = cut(nc$AREA, c(0, .1, .12, .15, .25))\n#'  nc |> group_by(area_cl) |> class()\n#' }\ngroup_by.sf <- function(.data, ..., add = FALSE) {\n\tsf_column_name = attr(.data, \"sf_column\")\n\tclass(.data) <- setdiff(class(.data), \"sf\")\n\tst_as_sf(NextMethod(), sf_column_name = sf_column_name)\n}\n\n#' @name tidyverse\nungroup.sf <- function(x, ...) {\n\tsf_column_name = attr(x, \"sf_column\")\n\tclass(x) <- setdiff(class(x), \"sf\")\n\tst_as_sf(NextMethod(), sf_column_name = sf_column_name)\n}\n\n#' @name tidyverse\nrowwise.sf <- function(x, ...) {\n\tsf_column_name = attr(x, \"sf_column\")\n\tclass(x) <- setdiff(class(x), \"sf\")\n\tst_as_sf(NextMethod(), sf_column_name = sf_column_name)\n}\n\n.re_sf = function(x, sf_column_name, agr, geom = NULL) {\n\tstopifnot(!inherits(x, \"sf\"), !missing(sf_column_name), !missing(agr))\n\t# non-geom attribute names\n\tatt = names(x)[!sapply(x, inherits, what = \"sfc\")]\n\tagr = setNames(agr[att], att) # NA's new columns\n\tif (!is.null(geom)) {\n\t\tstopifnot(length(geom) == nrow(x))\n\t\tx[[ sf_column_name ]] = geom\n\t}\n\tstructure(x,\n\t\tsf_column = sf_column_name,\n\t\tagr = agr,\n\t\tclass = c(\"sf\", class(x)))\n}\n\n#' @name tidyverse\n#' @examples\n#' if (require(dplyr, quietly = TRUE)) {\n#'  nc2 <- nc |> mutate(area10 = AREA/10)\n#' }\nmutate.sf <- function(.data, ..., .dots) {\n\t#st_as_sf(NextMethod(), sf_column_name = attr(.data, \"sf_column\"))\n\tagr = st_agr(.data)\n\tsf_column_name = attr(.data, \"sf_column\")\n\tclass(.data) <- setdiff(class(.data), \"sf\")\n\t.re_sf(NextMethod(), sf_column_name = sf_column_name, agr)\n}\n\n\n#' @name tidyverse\n#' @examples\n#' if (require(dplyr, quietly = TRUE)) {\n#'  nc |> transmute(AREA = AREA/10) |> class()\n#' }\ntransmute.sf <- function(.data, ..., .dots) {\n\tsf_column_name = attr(.data, \"sf_column\")\n\tagr = st_agr(.data)\n\tgeom = st_geometry(.data)\n\tclass(.data) = setdiff(class(.data), \"sf\")\n\t.re_sf(NextMethod(), sf_column_name = sf_column_name, agr, geom)\n}\n\n#' @name tidyverse\n#' @examples\n#' if (require(dplyr, quietly = TRUE)) {\n#'  nc |> select(SID74, SID79) |> names()\n#'  nc |> select(SID74, SID79) |> class()\n#' }\n#' @details \\code{select} keeps the geometry regardless whether it is selected or not; to deselect it, first pipe through \\code{as.data.frame} to let dplyr's own \\code{select} drop it.\nselect.sf <- function(.data, ...) {\n\n\tif (!requireNamespace(\"tidyselect\", quietly = TRUE))\n\t\tstop(\"tidyselect required: install that first\") # nocov\n\tloc = tidyselect::eval_select(quote(c(...)), .data)\n\n\tsf_column = attr(.data, \"sf_column\")\n\tsf_column_loc = match(sf_column, names(.data))\n\n\tif (length(sf_column_loc) != 1 || is.na(sf_column_loc))\n\t\tstop(\"internal error: can't find sf column\") # nocov\n\n\tagr = st_agr(.data)\n\t#vars = names(.data)[setdiff(loc, sf_column_loc)] # see #1886, change into:\n\tlloc = loc\n\tif (sf_column_loc %in% loc)\n\t\tlloc = lloc[loc != sf_column_loc]\n\tvars = names(.data)[lloc]\n\n\tsf_column_loc_loc = match(sf_column_loc, loc)\n\tif (is.na(sf_column_loc_loc)) {\n\t\t# The sf column was subsetted out, select it back in\n\t\tnew_agr = setNames(agr[vars], names(loc))\n\t\tloc = c(loc, sf_column_loc)\n\t\tnames(loc)[[length(loc)]] = sf_column\n\t} else {\n\t\t# The sf column was not subsetted out but it might have been renamed\n\t\tsf_column = names(loc[sf_column_loc_loc])\n\t\tnew_agr = setNames(agr[vars], setdiff(names(loc), sf_column))\n\t}\n\n\tret = .data\n\tclass(ret) = setdiff(class(ret), \"sf\")\n\tret = ret[loc]\n\tnames(ret) = names(loc)\n\n\tst_set_agr(st_as_sf(ret, sf_column_name = sf_column), new_agr)\n}\n\n\n#' @name tidyverse\n#' @examples\n#' if (require(dplyr, quietly = TRUE)) {\n#'  nc2 <- nc |> rename(area = AREA)\n#' }\nrename.sf <- function(.data, ...) {\n\n\tif (!requireNamespace(\"tidyselect\", quietly = TRUE))\n\t\tstop(\"tidyselect required: install that first\") # nocov\n\tloc = tidyselect::eval_rename(quote(c(...)), .data)\n\n\tsf_column = attr(.data, \"sf_column\")\n\tsf_column_loc = match(sf_column, names(.data))\n\n\tif (length(sf_column_loc) != 1 || is.na(sf_column_loc))\n\t\tstop(\"internal error: can't find sf column\") # nocov\n\n\tagr = st_agr(.data)\n\tagr_loc = match(names(agr), setdiff(names(.data), sf_column))\n\n\tif (anyNA(agr_loc))\n\t\tstop(\"internal error: can't find `agr` columns\") # nocov\n\n\tvars_loc = loc[loc %in% agr_loc]\n\n\t# https://github.com/r-spatial/sf/issues/1472\n\t# but only fixes for the single sfc column case\n\tsfcs = which(sapply(.data, inherits, \"sfc\"))\n\tif (length(vars_loc) == 1 && any(vars_loc > sfcs[1])) {\n\t\tw = which(vars_loc > sfcs)\n\t\tvars_loc[w] = vars_loc[w] - 1\n\t}\n\n\tnames(agr)[vars_loc] = names(vars_loc)\n\n\tsf_column_loc_loc = match(sf_column_loc, loc)\n\tif (!is.na(sf_column_loc_loc))\n\t\tsf_column = names(loc[sf_column_loc_loc])\n\n\tret = .data\n\tclass(ret) = setdiff(class(ret), \"sf\")\n\tnames(ret)[loc] = names(loc)\n\n\tst_set_agr(st_as_sf(ret, sf_column_name = sf_column), agr)\n}\n\n#' @name tidyverse\n#' @param .fn,.cols see original docs\nrename_with.sf = function(.data, .fn, .cols, ...) {\n\tif (!requireNamespace(\"rlang\", quietly = TRUE))\n\t\tstop(\"rlang required: install that first\") # nocov\n\t.fn = rlang::as_function(.fn)\n\tis_tibble = inherits(.data, \"tbl\")\n\t\n\tsf_column = attr(.data, \"sf_column\")\n\tsf_column_loc = match(sf_column, names(.data))\n\t\n\tif (length(sf_column_loc) != 1 || is.na(sf_column_loc))\n\t\tstop(\"internal error: can't find sf column\") # nocov\n\t\n\tagr = st_agr(.data)\n\t\n\t.data = as.data.frame(.data)\n\tret = if (missing(.cols)) {\n\t\tif (!requireNamespace(\"tidyselect\", quietly = TRUE)) {\n\t\t\tstop(\"tidyselect required: install that first\") # nocov\n\t\t}\n\t\tdplyr::rename_with(\n\t\t\t.data = .data,\n\t\t\t.fn = .fn,\n\t\t\t.cols = tidyselect::everything(), \n\t\t\t...\n\t\t)\n\t} else {\n\t\tdplyr::rename_with(\n\t\t\t.data = .data,\n\t\t\t.fn = .fn,\n\t\t\t.cols = {{ .cols }}, \n\t\t\t...\n\t\t)\n\t}\n\tif (is_tibble)\n\t\tret = dplyr::as_tibble(ret)\n\tret = st_as_sf(ret, sf_column_name = names(ret)[sf_column_loc])\n\t\n\tnames(agr) = .fn(names(agr), ...)\n\tst_agr(ret) = agr\n\tret\n}\n\n\n#' @name tidyverse\n#' @examples\n#' if (require(dplyr, quietly = TRUE)) {\n#'  nc |> slice(1:2)\n#' }\nslice.sf <- function(.data, ..., .dots) {\n\tclass(.data) <- setdiff(class(.data), \"sf\")\n\tsf_column <- attr(.data, \"sf_column\")\n\tst_as_sf(NextMethod(), sf_column_name = sf_column)\n}\n\n\n#' @name tidyverse\n#' @aliases summarise\n#' @param do_union logical; in case \\code{summary} does not create a geometry column, should geometries be created by unioning using \\link{st_union}, or simply by combining using \\link{st_combine}? Using \\link{st_union} resolves internal boundaries, but in case of unioning points, this will likely change the order of the points; see Details.\n#' @param is_coverage logical; if \\code{do_union} is \\code{TRUE}, use an optimized algorithm for features that form a polygonal coverage (have no overlaps)\n#' @return an object of class \\link{sf}\n#' @details\n#' In case one or more of the arguments (expressions) in the \\code{summarise} call creates a geometry list-column, the first of these will be the (active) geometry of the returned object. If this is not the case, a geometry column is created, depending on the value of \\code{do_union}.\n#'\n#' In case \\code{do_union} is \\code{FALSE}, \\code{summarise} will simply combine geometries using \\link{c.sfg}. When polygons sharing a boundary are combined, this leads to geometries that are invalid; see for instance \\url{https://github.com/r-spatial/sf/issues/681}.\n#' @examples\n#' if (require(dplyr, quietly = TRUE)) {\n#'  nc$area_cl = cut(nc$AREA, c(0, .1, .12, .15, .25))\n#'  nc.g <- nc |> group_by(area_cl)\n#'  nc.g |> summarise(mean(AREA))\n#'  nc.g |> summarise(mean(AREA)) |> plot(col = grey(3:6 / 7))\n#'  nc |> as.data.frame() |> summarise(mean(AREA))\n#'  # counting geometries (after duplicating each row):\n#'  nc.dupl <- nc[rep(seq_along(nc), each = 2), ]\n#'  nc.dupl |> summarise(n = n(), .by = \"geometry\")\n#' }\nsummarise.sf <- function(.data, ..., .dots, do_union = TRUE, is_coverage = FALSE) {\n\tsf_column = attr(.data, \"sf_column\")\n\tprecision = st_precision(.data)\n\tcrs = st_crs(.data)\n\tgeom = st_geometry(.data)\n\tclass(.data) = setdiff(class(.data), \"sf\")\n\tret = NextMethod()\n\tif (!missing(do_union))\n\t\tret$do_union = NULL\n\tif (!missing(is_coverage))\n\t\tret$is_coverage = NULL\n\n\tif (! any(sapply(ret, inherits, what = \"sfc\"))) {\n\t\tgeom = if (inherits(.data, \"grouped_df\") || inherits(.data, \"grouped_dt\")) {\n\t\t\t\tif (!requireNamespace(\"dplyr\", quietly = TRUE))\n\t\t\t\t\tstop(\"dplyr required: install that first\") # nocov\n\t\t\t\ti = dplyr::group_indices(.data)\n\t\t\t\t# geom = st_geometry(.data)\n\t\t\t\tgeom = if (do_union)\n\t\t\t\t\t\tlapply(sort(unique(i)), function(x) {\n\t\t\t\t\t\t\tif (x == 1)\n\t\t\t\t\t\t\t\tst_union(geom[i == x], is_coverage = is_coverage)\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tsuppressMessages(st_union(geom[i == x], is_coverage = is_coverage))\n\t\t\t\t\t\t})\n\t\t\t\t\telse\n\t\t\t\t\t\tlapply(sort(unique(i)), function(x) st_combine(geom[i == x]))\n\t\t\t\tgeom = unlist(geom, recursive = FALSE)\n\t\t\t\tif (is.null(geom))\n\t\t\t\t\tgeom = list() #676 #nocov\n\t\t\t\tdo.call(st_sfc, c(geom, crs = list(crs), precision = precision))\n\t\t\t} else { # single group:\n\t\t\t\tif (nrow(ret) > 1)\n\t\t\t\t\tstop(paste0(\"when using .by, also add across(\", sf_column, \", st_union) as argument\")) # https://github.com/r-spatial/sf/issues/2207\n\t\t\t\tif (do_union)\n\t\t\t\t\tst_union(geom, is_coverage = is_coverage)\n\t\t\t\telse\n\t\t\t\t\tst_combine(geom)\n\t\t\t}\n\t\tret[[ sf_column ]] = geom\n\t}\n\t# need to re-sort out the geometry column class now:\n\tst_as_sf(structure(ret, sf_column = NULL))\n}\n\n#' @name tidyverse\n#' @param wt see original function docs\n#' @param sort see original function docs\n#' @param name see original function docs\n#' @param name see original function docs\n#' @param .drop_geometry logical; if `TRUE`, remove geometry column before computing counts\n#' @examples\n#' if (require(dplyr, quietly = TRUE)) {\n#'   nc$area_cl <- cut(nc$AREA, c(0, .1, .12, .15, .25))\n#'   nc |> count(area_cl, .drop_geometry = TRUE)\n#' }\n#' @details The functions \\code{count} and \\code{tally} drop all geometries.\n#' For counting geometries use \\code{summarise(.data, n = n(), .by = \"geometry\")}.\ncount.sf <- function(x, ..., wt = NULL, sort = FALSE, name = \"n\", .drop_geometry = FALSE) {\n\tif (!requireNamespace(\"dplyr\", quietly = TRUE))\n\t\tstop(\"dplyr required: install that first\") # nocov\n\tif (isTRUE(.drop_geometry))\n\t\tx <- st_drop_geometry(x)\n\tNextMethod()\n}\n\n#' @name tidyverse\n#' @param .keep_all see corresponding function in dplyr\n#' @param exact logical; if `TRUE` use \\link{st_equals_exact} for geometry comparisons\n#' @param par numeric; passed on to \\link{st_equals_exact}\n#' @examples\n#' if (require(dplyr, quietly = TRUE)) {\n#'  nc[c(1:100, 1:10), ] |> distinct() |> nrow()\n#' }\n#' @details \\code{distinct} gives distinct records for which all attributes and geometries are distinct; \\link{st_equals} is used to find out which geometries are distinct.\ndistinct.sf <- function(.data, ..., .keep_all = FALSE, exact = FALSE, par = 0.) {\n\tsf_column = attr(.data, \"sf_column\")\n\tgeom = st_geometry(.data)\n\teq = if (exact)\n\t\t\tsapply(st_equals_exact(.data, par = par), head, n = 1)\n\t\telse \n\t\t\tsapply(st_equals(.data), head, n = 1)\n\tif (is.list(eq) && length(eq) == 0) # empty list: geometry was empty set\n\t\teq = integer(0)\n\tempties = which(lengths(eq) == 0)\n\teq[ empties ] = empties[1] # first empty record\n\t.data[[ sf_column ]] = unlist(eq)\n\tclass(.data) = setdiff(class(.data), \"sf\")\n\n\tif (!requireNamespace(\"dplyr\", quietly = TRUE))\n\t\tstop(\"dplyr required: install that first\") # nocov\n\tif (!requireNamespace(\"rlang\", quietly = TRUE))\n\t\tstop(\"rlang required: install first?\")\n\n\t.data = dplyr::distinct(.data, ..., .keep_all = .keep_all)\n\tif (is.null(.data[[ sf_column ]]))\n\t\t.data\n\telse {\n\t\t.data[[ sf_column ]] = geom[ .data[[ sf_column ]] ]\n\t\tst_as_sf(.data, sf_column_name = sf_column)\n\t}\n}\n\n## tidyr methods: --------\n\n#' @name tidyverse\n#' @param data see original function docs\n#' @param key see original function docs\n#' @param value see original function docs\n#' @param na.rm see original function docs\n#' @param factor_key see original function docs\n#' @examples\n#' if (require(tidyr, quietly = TRUE) && require(dplyr, quietly = TRUE) && \"geometry\" %in% names(nc)) {\n#'  nc |> select(SID74, SID79) |> gather(\"VAR\", \"SID\", -geometry) |> summary()\n#' }\ngather.sf <- function(data, key, value, ..., na.rm = FALSE, convert = FALSE, factor_key = FALSE) {\n\n\tif (! requireNamespace(\"rlang\", quietly = TRUE))\n\t\tstop(\"rlang required: install first?\")\n\n\tkey = rlang::enquo(key)\n\tvalue = rlang::enquo(value)\n\n\tif (!requireNamespace(\"tidyr\", quietly = TRUE))\n\t\tstop(\"tidyr required: install first?\")\n\n\tclass(data) <- setdiff(class(data), \"sf\")\n    st_as_sf(tidyr::gather(data, !!key, !!value, ...,\n\t\tna.rm = na.rm, convert = convert, factor_key = factor_key),\n\t\tsf_column_name = attr(data, \"sf_column\"))\n}\n\n#' @name tidyverse\n#' @param data see original function docs\n#' @param cols see original function docs\n#' @param names_to,names_pattern,names_ptypes,names_transform see [tidyr::pivot_longer()]\n#' @param values_to,values_drop_na,values_ptypes,values_transform See [tidyr::pivot_longer()]\npivot_longer.sf <- function (data, cols, names_to = \"name\", names_prefix = NULL,\n\t\tnames_sep = NULL, names_pattern = NULL, names_ptypes = NULL,\n\t\tnames_transform = NULL, names_repair = \"check_unique\",\n\t\tvalues_to = \"value\", values_drop_na = FALSE, values_ptypes = NULL,\n\t\tvalues_transform = NULL, ...) {\n\n  sf_column_name = attr(data, \"sf_column\")\n  data = as.data.frame(data)\n\n# instead of:\n#\tst_as_sf(NextMethod(), sf_column_name = sf_column_name)\n# we avoid NextMethod(); for the reason\n# see https://github.com/tidyverse/tidyr/issues/1171:\n  if (!requireNamespace(\"tidyr\", quietly = TRUE))\n    stop(\"tidyr required: install first?\")\n  out <- tidyr::pivot_longer(\n    data = data,\n    cols = {{ cols }},\n    names_to = names_to,\n    names_prefix = names_prefix,\n    names_sep = names_sep,\n    names_pattern = names_pattern,\n    names_ptypes = names_ptypes,\n    names_transform = names_transform,\n    names_repair = names_repair,\n    values_to = values_to,\n    values_drop_na = values_drop_na,\n    values_ptypes = values_ptypes,\n    values_transform = values_transform,\n    ...\n  )\n  st_as_sf(out, sf_column_name = sf_column_name)\n}\n\nglobalVariables(c(\"name\", \"value\"))\n# https://github.com/r-spatial/sf/issues/1915\n#' @name tidyverse\n#' @param id_cols,id_expand,names_from,names_sort,names_glue,names_vary,names_expand see [tidyr::pivot_wider()]\n# names_prefix,names_sep and names_repair are shared between pivot_longer() and pivot_wider()\n#' @param names_prefix,names_sep,names_repair see original function docs.\n#' @param values_from,values_fill,values_fn,unused_fn see [tidyr::pivot_wider()]\npivot_wider.sf = function(data, \n\t\t\t\t\t\t  ..., \n\t\t\t\t\t\t  id_cols = NULL, \n\t\t\t\t\t\t  id_expand = FALSE, \n\t\t\t\t\t\t  names_from = name, \n\t\t\t\t\t\t  names_prefix = \"\", \n\t\t\t\t\t\t  names_sep = \"_\", \n\t\t\t\t\t\t  names_glue = NULL, \n\t\t\t\t\t\t  names_sort = FALSE, \n\t\t\t\t\t\t  names_vary = \"fastest\", \n\t\t\t\t\t\t  names_expand = FALSE, \n\t\t\t\t\t\t  names_repair = \"check_unique\", \n\t\t\t\t\t\t  values_from = value, \n\t\t\t\t\t\t  values_fill = NULL, \n\t\t\t\t\t\t  values_fn = NULL, \n\t\t\t\t\t\t  unused_fn = NULL) {\n\n\tagr = st_agr(data)\n\tsf_column_name = attr(data, \"sf_column\")\n\tdata = as.data.frame(data)\n\tif (!requireNamespace(\"tidyr\", quietly = TRUE))\n\t\tstop(\"tidyr required: install first?\")\n\tret = tidyr::pivot_wider(\n\t\tdata = data, \n\t\t..., \n\t\tid_cols = {{ id_cols }}, \n\t\tid_expand = id_expand, \n\t\tnames_from = {{ names_from }}, \n\t\tnames_prefix = names_prefix, \n\t\tnames_sep = names_sep, \n\t\tnames_glue = names_glue, \n\t\tnames_sort = names_sort, \n\t\tnames_vary = names_vary, \n\t\tnames_expand = names_expand, \n\t\tnames_repair = names_repair, \n\t\tvalues_from = {{ values_from }}, \n\t\tvalues_fill = values_fill, \n\t\tvalues_fn = values_fn, \n\t\tunused_fn = unused_fn\n\t)\n\tst_as_sf(ret, sf_column_name = sf_column_name, agr = agr)\n}\n\n\n\n#' @name tidyverse\n#' @param fill see original function docs\n#' @param drop see original function docs\n#' @examples\n#' if (require(tidyr, quietly = TRUE) && require(dplyr, quietly = TRUE) && \"geometry\" %in% names(nc)) {\n#'  nc$row = 1:100 # needed for spread to work\n#'  nc |> select(SID74, SID79, geometry, row) |>\n#'\t\tgather(\"VAR\", \"SID\", -geometry, -row) |>\n#'\t\tspread(VAR, SID) |> head()\n#' }\nspread.sf <- function(data, key, value, fill = NA, convert = FALSE, drop = TRUE,\n\t        sep = NULL) {\n\n\tif (!requireNamespace(\"rlang\", quietly = TRUE))\n\t\tstop(\"rlang required: install first?\")\n\tkey = rlang::enquo(key)\n\tvalue = rlang::enquo(value)\n\n\tclass(data) <- setdiff(class(data), \"sf\")\n\tst_as_sf(tidyr::spread(data, !!key, !!value, fill = fill, convert = convert,\n\t\tdrop = drop, sep = sep), sf_column_name = attr(data, \"sf_column\"))\n}\n\n#' @name tidyverse\n#' @param tbl see original function docs\n#' @param size see original function docs\n#' @param replace see original function docs\n#' @param weight see original function docs\n#' @param .env see original function docs\nsample_n.sf <- function(tbl, size, replace = FALSE, weight = NULL, .env = parent.frame()) {\n\tst_sf(NextMethod(), sf_column_name = attr(tbl, \"sf_column\"))\n}\n\n#' @name tidyverse\nsample_frac.sf <- function(tbl, size = 1, replace = FALSE, weight = NULL, .env = parent.frame()) {\n\tst_sf(NextMethod(), sf_column_name = attr(tbl, \"sf_column\"))\n}\n#' @name tidyverse\n#' @param .tbl see original function docs\n#' @param .keep see original function docs\ngroup_split.sf <- function(.tbl, ..., .keep = TRUE) {\n\tclass(.tbl) = setdiff(class(.tbl), \"sf\")\n\tif (inherits(.tbl, \"rowwise_df\")) {\n\t\tlapply(dplyr::group_split(.tbl, ...), st_as_sf)\n\t} else {\n\t\tlapply(dplyr::group_split(.tbl, ..., .keep = .keep), st_as_sf)\t\n\t}\n}\n#' @name tidyverse\n#' @examples\n#' if (require(tidyr, quietly = TRUE) && require(dplyr, quietly = TRUE)) {\n#'  storms.sf = st_as_sf(storms, coords = c(\"long\", \"lat\"), crs = 4326)\n#'  x <- storms.sf |> group_by(name, year) |> nest()\n#'  trs = lapply(x$data, function(tr) st_cast(st_combine(tr), \"LINESTRING\")[[1]]) |>\n#'     st_sfc(crs = 4326)\n#'  trs.sf = st_sf(x[,1:2], trs)\n#'  plot(trs.sf[\"year\"], axes = TRUE)\n#' }\n#' @details \\code{nest} assumes that a simple feature geometry list-column was among the columns that were nested.\nnest.sf = function(.data, ...) {\n\n\tif (!requireNamespace(\"rlang\", quietly = TRUE))\n\t\tstop(\"rlang required: install first?\")\n\tif (!requireNamespace(\"tidyr\", quietly = TRUE))\n\t\tstop(\"tidyr required: install first?\")\n\n\tclass(.data) <- setdiff(class(.data), \"sf\")\n\tret = tidyr::nest(.data, ...)\n\tlst = which(sapply(ret, inherits, \"list\"))[1]\n\t# re-sf:\n\tret[[lst]] = lapply(ret[[lst]], st_as_sf, sf_column_name = attr(.data, \"sf_column\"))\n\tret\n}\n\n\n#' @name tidyverse\n#' @param col see \\link[tidyr]{separate}\n#' @param into see \\link[tidyr]{separate}\n#' @param remove see \\link[tidyr]{separate}\n#' @param extra see \\link[tidyr]{separate}\nseparate.sf = function(data, col, into, sep = \"[^[:alnum:]]+\", remove = TRUE,\n\tconvert = FALSE, extra = \"warn\", fill = \"warn\", ...) {\n\n\tif (!requireNamespace(\"rlang\", quietly = TRUE))\n\t\tstop(\"rlang required: install first?\")\n\tcol = rlang::enquo(col)\n\n\tif (!requireNamespace(\"tidyr\", quietly = TRUE))\n\t\tstop(\"tidyr required: install first?\")\n\n\tclass(data) <- setdiff(class(data), \"sf\")\n\tst_as_sf(tidyr::separate(data, !!col, into = into,\n\t\tsep = sep, remove = remove, convert = convert, extra = extra, fill = fill, ...),\n\t\t\tsf_column_name = attr(data, \"sf_column\"))\n}\n\n#' @name tidyverse\n#' @param sep see \\link[tidyr]{separate_rows}\n#' @param convert see \\link[tidyr]{separate_rows}\nseparate_rows.sf <- function(data, ..., sep = \"[^[:alnum:]]+\", convert = FALSE) {\n\tif (!requireNamespace(\"tidyr\", quietly = TRUE))\n\t\tstop(\"tidyr required: install first?\")\n\tclass(data) <- setdiff(class(data), \"sf\")\n\tret = tidyr::separate_rows(data, ..., sep = sep, convert = convert)\n\tst_as_sf(ret, sf_column_name = attr(data, \"sf_column\"))\n}\n\n#' @name tidyverse\nunite.sf <- function(data, col, ..., sep = \"_\", remove = TRUE) {\n\tclass(data) <- setdiff(class(data), \"sf\")\n\tif (!requireNamespace(\"rlang\", quietly = TRUE))\n\t\tstop(\"rlang required: install first?\")\n\tcol = rlang::enquo(col)\n\tst_as_sf(tidyr::unite(data, !!col, ..., sep = sep, remove = remove),\n\t\tsf_column_name = attr(data, \"sf_column\"))\n}\n\n#' @name tidyverse\n#' @param .preserve see \\link[tidyr:nest]{unnest}\nunnest.sf = function(data, ..., .preserve = NULL) {\n\t# nocov start\n\tsf_column_name = attr(data, \"sf_column\", exact = TRUE)\n\tif (!requireNamespace(\"tidyr\", quietly = TRUE))\n\t\tstop(\"unnest requires tidyr; install that first\")\n\tclass(data) = setdiff(class(data), \"sf\")\n\tst_sf(NextMethod(), sf_column_name = sf_column_name)\n\t# nocov end\n}\n\n#' @name tidyverse\ndrop_na.sf <- function(x, ...) {\n\tsf_column_name = attr(x, \"sf_column\")\n\tclass(x) <- setdiff(class(x), \"sf\")\n\tst_as_sf(NextMethod(), sf_column_name = sf_column_name)\n}\n\n## tibble methods: -------\n\n#' Summarize simple feature type for tibble\n#'\n#' Summarize simple feature type / item for tibble\n#' @param x object of class `sfc`\n#' @param ... ignored\n#' @name tibble\n#' @details see \\link[pillar]{type_sum}\ntype_sum.sfc <- function(x, ...) {\n\tcls = substring(class(x)[1], 5)\n\tu = st_crs(x)$ud_unit\n\tif (!is.null(u)) # add [units]:\n\t\tcls = paste0(cls, \" [\", enc2utf8(as.character(units(u))), \"]\")\n\tcls\n}\n\n#' @rdname tibble\nobj_sum.sfc <- function(x) {\n\tvapply(x, function(sfg) format(sfg, width = 15L), \"\")\n}\n\n#' @rdname tibble\npillar_shaft.sfc <- function(x, ...) {\n\tdigits = options(\"pillar.sigfig\")$pillar.sigfig\n\tif (is.null(digits))\n\t\tdigits = options(\"digits\")$digits\n\tout <- format(x, width = 100, digits = digits, ...)\n\tif (!inherits(x, \"sfc_GEOMETRY\") && !inherits(x, \"sfc_GEOMETRYCOLLECTION\"))\n\t\tout <- sub(\"[A-Z]+ \", \"\", out)\n\tpillar::new_pillar_shaft_simple(out, align = \"right\", min_width = 25)\n}\n\n#nocov start\nregister_all_s3_methods = function() {\n\ts3_register(\"dplyr::dplyr_reconstruct\", \"sf\")\n\ts3_register(\"dplyr::anti_join\", \"sf\")\n\ts3_register(\"dplyr::arrange\", \"sf\")\n\ts3_register(\"dplyr::count\", \"sf\")\n\ts3_register(\"dplyr::distinct\", \"sf\")\n\ts3_register(\"dplyr::filter\", \"sf\")\n\ts3_register(\"dplyr::full_join\", \"sf\")\n\ts3_register(\"dplyr::group_by\", \"sf\")\n\ts3_register(\"dplyr::group_split\", \"sf\")\n\ts3_register(\"dplyr::inner_join\", \"sf\")\n\ts3_register(\"dplyr::left_join\", \"sf\")\n\ts3_register(\"dplyr::mutate\", \"sf\")\n\ts3_register(\"dplyr::rename\", \"sf\")\n\ts3_register(\"dplyr::rename_with\", \"sf\")\n\ts3_register(\"dplyr::right_join\", \"sf\")\n\ts3_register(\"dplyr::rowwise\", \"sf\")\n\ts3_register(\"dplyr::sample_frac\", \"sf\")\n\ts3_register(\"dplyr::sample_n\", \"sf\")\n\ts3_register(\"dplyr::select\", \"sf\")\n\ts3_register(\"dplyr::semi_join\", \"sf\")\n\ts3_register(\"dplyr::slice\", \"sf\")\n\ts3_register(\"dplyr::summarise\", \"sf\")\n\ts3_register(\"dplyr::transmute\", \"sf\")\n\ts3_register(\"dplyr::ungroup\", \"sf\")\n\ts3_register(\"tidyr::drop_na\", \"sf\")\n\ts3_register(\"tidyr::gather\", \"sf\")\n\ts3_register(\"tidyr::pivot_longer\", \"sf\")\n\ts3_register(\"tidyr::pivot_wider\", \"sf\")\n\ts3_register(\"tidyr::spread\", \"sf\")\n\ts3_register(\"tidyr::nest\", \"sf\")\n\ts3_register(\"tidyr::separate\", \"sf\")\n\ts3_register(\"tidyr::separate_rows\", \"sf\")\n\ts3_register(\"tidyr::unite\", \"sf\")\n\ts3_register(\"tidyr::unnest\", \"sf\")\n\ts3_register(\"pillar::obj_sum\", \"sfc\")\n\ts3_register(\"pillar::type_sum\", \"sfc\")\n\ts3_register(\"pillar::pillar_shaft\", \"sfc\")\n\ts3_register(\"spatstat.geom::as.ppp\", \"sfc\")\n\ts3_register(\"spatstat.geom::as.ppp\", \"sf\")\n\ts3_register(\"spatstat.geom::as.owin\", \"POLYGON\")\n\ts3_register(\"spatstat.geom::as.owin\", \"MULTIPOLYGON\")\n\ts3_register(\"spatstat.geom::as.owin\", \"sfc_POLYGON\")\n\ts3_register(\"spatstat.geom::as.owin\", \"sfc_MULTIPOLYGON\")\n\ts3_register(\"spatstat.geom::as.owin\", \"sfc\")\n\ts3_register(\"spatstat.geom::as.owin\", \"sf\")\n\ts3_register(\"spatstat.geom::as.psp\", \"LINESTRING\")\n\ts3_register(\"spatstat.geom::as.psp\", \"MULTILINESTRING\")\n\ts3_register(\"spatstat.geom::as.psp\", \"sfc_MULTILINESTRING\")\n\ts3_register(\"spatstat.geom::as.psp\", \"sfc\")\n\ts3_register(\"spatstat.geom::as.psp\", \"sf\")\n\ts3_register(\"s2::as_s2_geography\", \"sfg\")\n\ts3_register(\"s2::as_s2_geography\", \"sfc\")\n\ts3_register(\"s2::as_s2_geography\", \"sf\")\n\tregister_vctrs_methods()\n}\n# nocov end\n"
  },
  {
    "path": "R/transform.R",
    "content": "chk_pol = function(x, dim = class(x)[1]) {\n\tPolClose = function(y) {\n\t\tif (any(head(y[[1]], 1) != tail(y[[1]], 1))) # close\n\t\t\ty[[1]] = rbind(y[[1]], head(y[[1]], 1))\n\t\telse if (nrow(y[[1]]) == 3) # closed, but line\n\t\t\treturn(st_polygon(dim = dim))\n\t\ty\n\t}\n\tif (length(x) > 0 && nrow(x[[1]]) > 2)\n\t\tPolClose(x)\n\telse\n\t\tst_polygon(dim = dim)\n}\n\nchk_mpol = function(x) {\n\tcln = lapply(x, function(y) unclass(chk_pol(y, class(x)[1])))\n\tempty = if (length(cln))\n\t\t\tlengths(cln) == 0\n\t\telse\n\t\t\tTRUE\n\t# print(empty)\n\tst_multipolygon(cln[!empty], dim = class(x)[1])\n}\n\nsanity_check = function(x) {\n\td = st_dimension(x) # flags empty geoms as NA\n\tif (any(d == 2, na.rm = TRUE)) { # the polygon stuff\n\t\tx = st_cast(x[d == 2]) # convert GEOMETRY to POLYGON or MULTIPOLYGON, if possible\n\t\tif (inherits(x, \"sfc_POLYGON\"))\n\t\t\tst_sfc(lapply(x, chk_pol), crs = st_crs(x))\n\t\telse if (inherits(x, \"sfc_MULTIPOLYGON\"))\n\t\t\tst_sfc(lapply(x, chk_mpol), crs = st_crs(x))\n\t\telse\n\t\t\tstop(paste(\"no check implemented for\", class(x)[1]))\n\t} else\n\t\tx # nocov\n}\n\n#' @export\n#' @name st_transform\n#' @param src source crs\n#' @param dst destination crs\n#' @details \\code{st_can_transform} returns a boolean indicating whether\n#' coordinates with CRS src can be transformed into CRS dst\nst_can_transform = function(src, dst) {\n\tCPL_can_transform(st_crs(src), st_crs(dst))\n}\n\n#' Transform or convert coordinates of simple feature\n#'\n#' Transform or convert coordinates of simple feature\n#'\n#' @param x object of class sf, sfc or sfg\n#' @param crs target coordinate reference system: object of class `crs`, or input string for \\link{st_crs}\n#' @param ... ignored\n#' @param aoi area of interest, in degrees: \n#' WestLongitude, SouthLatitude, EastLongitude, NorthLatitude\n#' @param pipeline character; coordinate operation pipeline, for overriding the default operation\n#' @param reverse boolean; has only an effect when \\code{pipeline} is defined:\n#' if \\code{TRUE}, the inverse operation of the pipeline is applied\n#' @param desired_accuracy numeric; Only coordinate operations that offer an accuracy of \n#' at least the one specified will be considered; a negative value disables this feature\n#' (requires GDAL >= 3.3)\n#' @param allow_ballpark logical; are ballpark (low accuracy) transformations allowed? \n#' (requires GDAL >= 3.3)\n#' @param partial logical; allow for partial projection, if not all points of a geometry can be projected (corresponds to setting environment variable \\code{OGR_ENABLE_PARTIAL_REPROJECTION} to \\code{TRUE})\n#' @param check logical; if \\code{TRUE}, perform a sanity check on resulting polygons\n#' @details Transforms coordinates of object to new projection. \n#' Features that cannot be transformed are returned as empty geometries.\n#' Transforms using the \\code{pipeline=} argument may fail if there is\n#' ambiguity in the axis order of the specified coordinate reference system;\n#' if you need the traditional GIS order, use \\code{\"OGC:CRS84\"}, not\n#' \\code{\"EPSG:4326\"}. Extra care is needed with the ESRI Shapefile format,\n#' because WKT1 does not store axis order unambiguously.\n#'\n#' @seealso \\link[lwgeom]{st_transform_proj}, part of package lwgeom.\n#' \n#' \\link{sf_project} projects a matrix of coordinates, bypassing GDAL altogether\n#' @examples\n#' p1 = st_point(c(7,52))\n#' p2 = st_point(c(-30,20))\n#' sfc = st_sfc(p1, p2, crs = 4326)\n#' sfc\n#' st_transform(sfc, 3857)\n#' @export\nst_transform = function(x, crs, ...) UseMethod(\"st_transform\")\n\n#' @name st_transform\n#' @export\n#' @examples\n#' st_transform(st_sf(a=2:1, geom=sfc), \"EPSG:3857\")\n#' if (compareVersion(sf_extSoftVersion()[\"GDAL\"], \"3.0.0\") >= 0) {\n#'   st_transform(sfc, pipeline =\n#' \t  \"+proj=pipeline +step +proj=axisswap +order=2,1\") # reverse axes\n#'   st_transform(sfc, pipeline =\n#' \t  \"+proj=pipeline +step +proj=axisswap +order=2,1\", reverse = TRUE) # also reverse axes\n#' }\nst_transform.sfc = function(x, crs = st_crs(x), ..., \n\t\taoi = numeric(0), pipeline = character(0), reverse = FALSE,\n\t\tdesired_accuracy = -1.0, allow_ballpark = TRUE,\n\t\tpartial = TRUE, check = FALSE) {\n\n\tstopifnot(is.character(pipeline), length(pipeline) %in% 0:1)\n\n\tcrs_missing = missing(crs)\n\tif (length(pipeline) == 0) {\n\t\tif (is.na(st_crs(x)))\n\t\t\tstop(\"cannot transform sfc object with missing crs\")\n\t\tif (missing(crs))\n\t\t\tstop(\"argument crs cannot be missing\")\n\t} else \n\t\tstopifnot(length(pipeline) == 1)\n\n\tcrs_input = crs\n\tcrs = make_crs(crs)\n\n\tif (crs_parameters(crs)$is_geocentric && length(x) && Dimension(x[[1]]) == \"XY\") # add z:\n\t\tx = st_zm(x, drop = FALSE, what = \"Z\")\n\n\tif (partial) {\n\t\torig = Sys.getenv(\"OGR_ENABLE_PARTIAL_REPROJECTION\")\n\t\tif (orig != \"\")\n\t\t\ton.exit(Sys.setenv(OGR_ENABLE_PARTIAL_REPROJECTION = orig))\n\t\tSys.setenv(OGR_ENABLE_PARTIAL_REPROJECTION = \"TRUE\")\n\t}\n\n\tif (length(pipeline)) {\n\t\tif (!crs_missing) { # verify pipeline is a legitimate option:\n\t\t\tif (!(pipeline %in% sf_proj_pipelines(st_crs(x), crs)$definition)) {\n\t\t\t\twarning(\"pipeline not found in PROJ-suggested candidate transformations; setting crs = NA\")\n\t\t\t\tcrs = NA_crs_ \n\t\t\t}\n\t\t} else\n\t\t\tcrs = NA_crs_  # to avoid st_crs(x) is crs of the returned object\n\t}\n\tret = st_sfc(structure(CPL_transform(x, crs, aoi, pipeline, reverse, desired_accuracy,\n\t\t\tallow_ballpark), single_type = NULL, crs = crs)) # hard-sets crs to new crs\n\tif (check)\n\t\tsanity_check(ret)\n\telse\n\t\tret\n}\n\n#' @name st_transform\n#' @export\n#' @examples\n#' nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\n#' st_area(nc[1,]) # area from long/lat\n#' st_area(st_transform(nc[1,], 32119)) # NC state plane, m\n#' st_area(st_transform(nc[1,], 2264)) # NC state plane, US foot\n#' library(units)\n#' set_units(st_area(st_transform(nc[1,], 2264)), m^2)\nst_transform.sf = function(x, crs = st_crs(x), ...) {\n\tx[[ attr(x, \"sf_column\") ]] = if (missing(crs))\n\t\t\tst_transform(st_geometry(x), ...)\n\t\telse\n\t\t\tst_transform(st_geometry(x), crs = crs, ...)\n\tx\n}\n\n#' @name st_transform\n#' @export\n#' @details The \\code{st_transform} method for \\code{sfg} objects assumes that the CRS of the object is available as an attribute of that name.\n#' @examples\n#' st_transform(structure(p1, proj4string = \"EPSG:4326\"), \"EPSG:3857\")\nst_transform.sfg = function(x, crs = st_crs(x), ...) {\n\tx = st_sfc(x, crs = attr(x, \"proj4string\"))\n\tif (missing(crs))\n\t\tstop(\"argument crs cannot be missing\")\n\tcrs = make_crs(crs)\n\tstructure(st_transform(x, crs = crs, ...)[[1]], crs = crs)\n}\n\n#' @name st_transform\n#' @export\n#' @param densify integer, number of points for discretizing lines between bounding box corner points; see Details\n#' @details the method for `bbox` objects densifies lines for geographic coordinates along Cartesian lines, not great circle arcs\nst_transform.bbox = function(x, crs, ..., densify = 21) {\n        if (compareVersion(sf_extSoftVersion()[\"GDAL\"], \"3.4.0\") >= 0)\n\t\tst_bbox(CPL_transform_bounds(x, st_crs(crs), densify), crs = crs)\n\telse\n\t\tstop(\"method not available for GDAL: \", sf_extSoftVersion()[\"GDAL\"])\n}\n\n#' @name st_transform\n#' @export\nst_wrap_dateline = function(x, options, quiet) UseMethod(\"st_wrap_dateline\")\n\n#' @name st_transform\n#' @param options character; should have \"WRAPDATELINE=YES\" to function; another parameter that is used is \"DATELINEOFFSET=10\" (where 10 is the default value)\n#' @param quiet logical; print options after they have been parsed?\n#' @export\n#' @examples\n#' st_wrap_dateline(st_sfc(st_linestring(rbind(c(-179,0),c(179,0))), crs = 4326))\n#' @details For a discussion of using \\code{options}, see \\url{https://github.com/r-spatial/sf/issues/280} and \\url{https://github.com/r-spatial/sf/issues/1983}\n#' @seealso \\link{st_break_antimeridian}\nst_wrap_dateline.sfc = function(x, options = \"WRAPDATELINE=YES\", quiet = TRUE) {\n\tif (is.na(st_crs(x)))\n\t\twarning(\"crs not set: assuming geographic coordinates\")\n\telse\n\t\tstopifnot(st_is_longlat(x))\n\tstopifnot(is.character(options))\n\tstopifnot(is.logical(quiet), length(quiet) == 1)\n\tst_sfc(CPL_wrap_dateline(x, options, quiet), crs = st_crs(x))\n}\n\n#' @name st_transform\n#' @export\nst_wrap_dateline.sf = function(x, options = \"WRAPDATELINE=YES\", quiet = TRUE) {\n\tst_set_geometry(x, st_sfc(CPL_wrap_dateline(st_geometry(x), options, quiet), crs = st_crs(x)))\n}\n\n#' @name st_transform\n#' @export\nst_wrap_dateline.sfg = function(x, options = \"WRAPDATELINE=YES\", quiet = TRUE) {\n\tst_sfc(CPL_wrap_dateline(st_geometry(x), options, quiet), crs = st_crs(x))[[1]]\n}\n"
  },
  {
    "path": "R/valid.R",
    "content": "#' @name valid\n#' @param NA_on_exception logical; if TRUE, for polygons that would otherwise raise a GEOS error (exception, e.g. for a POLYGON having more than zero but less than 4 points, or a LINESTRING having one point) return an \\code{NA} rather than raising an error, and suppress warning messages (e.g. about self-intersection); if FALSE, regular GEOS errors and warnings will be emitted.\n#' @param reason logical; if \\code{TRUE}, return a character with, for each geometry, the reason for invalidity, \\code{NA} on exception, or \\code{\"Valid Geometry\"} otherwise.\n#' @return \\code{st_is_valid} returns a logical vector indicating for each geometries of \\code{x} whether it is valid. \\code{st_make_valid} returns an object with a topologically valid geometry.\n#' @export\n#' @examples\n#' p1 = st_as_sfc(\"POLYGON((0 0, 0 10, 10 0, 10 10, 0 0))\")\n#' st_is_valid(p1)\n#' st_is_valid(st_sfc(st_point(0:1), p1[[1]]), reason = TRUE)\nst_is_valid = function(x, ...) UseMethod(\"st_is_valid\")\n\n#' @export\n#' @name valid\nst_is_valid.sfc = function(x, ..., NA_on_exception = TRUE, reason = FALSE) {\n\tif (sf_use_s2() && isTRUE(st_is_longlat(x))) {\n\t\tif (reason) {\n\t\t\tr = s2::s2_is_valid_detail(x)\n\t\t\tr$reason[r$is_valid] = \"Valid Geometry\"\n\t\t\tr$reason\n\t\t} else\n\t\t\ts2::s2_is_valid(x)\n\t} else if (reason) {\n\t\tif (NA_on_exception) {\n\t\t\tret = rep(NA_character_, length(x))\n\t\t\tnot_na = !is.na(st_is_valid(x, reason = FALSE))\n\t\t\tret[not_na] = CPL_geos_is_valid_reason(x[not_na])\n\t\t\tret\n\t\t} else\n\t\t\tCPL_geos_is_valid_reason(x)\n\t} else\n\t\tCPL_geos_is_valid(x, as.logical(NA_on_exception))\n}\n\n#' @export\n#' @name valid\nst_is_valid.sf = function(x, ...) {\n\tst_is_valid(st_geometry(x), ...)\n}\n\n#' @name valid\n#' @export\nst_is_valid.sfg = function(x, ...) {\n\tst_is_valid(st_geometry(x), ...)\n}\n\n#' Check validity or make an invalid geometry valid\n#'\n#' Checks whether a geometry is valid, or makes an invalid geometry valid\n#' @name valid\n#' @param x object of class \\code{sfg}, \\code{sfc} or \\code{sf}\n#' @return Object of the same class as \\code{x}\n#' @details For projected geometries, \\code{st_make_valid} uses the \\code{lwgeom_makevalid} method also used by the PostGIS command \\code{ST_makevalid} if the GEOS version linked to is smaller than 3.8.0, and otherwise the version shipped in GEOS; for geometries having ellipsoidal coordinates \\code{s2::s2_rebuild} is being used.\n#' @examples\n#' library(sf)\n#' x = st_sfc(st_polygon(list(rbind(c(0,0),c(0.5,0),c(0.5,0.5),c(0.5,0),c(1,0),c(1,1),c(0,1),c(0,0)))))\n#' suppressWarnings(st_is_valid(x))\n#' y = st_make_valid(x)\n#' st_is_valid(y)\n#' y |> st_cast()\n#' @export\nst_make_valid = function(x, ...) UseMethod(\"st_make_valid\")\n\n#' @export\n#' @name valid\nst_make_valid.sfg = function(x, ...) {\n\tst_make_valid(st_geometry(x), ...)[[1]]\n}\n\n#' @name valid\n#' @export\n#' @param ... passed on to \\link[s2]{s2_options}\n#' @param oriented logical; only relevant if \\code{st_is_longlat(x)} is \\code{TRUE}; see \\link{s2}\n#' @param s2_options only relevant if \\code{st_is_longlat(x)} is \\code{TRUE}; options for \\link[s2]{s2_rebuild}, see \\link[s2]{s2_options} and Details.\n#' @param geos_method character; either \"valid_linework\" (Original method, combines all rings into a set of noded lines and then extracts valid polygons from that linework) or \"valid_structure\" (Structured method, first makes all rings valid then merges shells and subtracts holes from shells to generate valid result. Assumes that holes and shells are correctly categorized.) (requires GEOS >= 3.10.1)\n#' @param geos_keep_collapsed logical; When this parameter is not set to \\code{FALSE}, the \"valid_structure\" method will keep any component that has collapsed into a lower dimensionality. For example, a ring collapsing to a line, or a line collapsing to a point (requires GEOS >= 3.10.1)\n#' @details if \\code{s2_options} is not specified and \\code{x} has a non-zero precision set, then this precision value will be used as the value in \\code{s2_snap_precision}, passed on to \\code{s2_options}, rather than the 1e7 default.\nst_make_valid.sfc = function(x, ..., oriented = FALSE, s2_options = s2::s2_options(snap = s2::s2_snap_precision(1e7), ...),\n\t\t\t\t\t\t\t geos_method = \"valid_structure\", geos_keep_collapsed = TRUE) {\n\tcrs = st_crs(x)\n\tif (sf_use_s2() && isTRUE(st_is_longlat(x))) {\n\t\tif (!missing(geos_method) || !missing(geos_keep_collapsed))\n\t\t\twarning(\"arguments geos_method and geos_keep_collapsed are ignored for geodetic coordinates as sf_use_s2() is TRUE\")\n\t\ts2 = s2::as_s2_geography(st_as_binary(st_set_precision(x, 0.0)), oriented = oriented, check = FALSE)\n\t\tif (st_precision(x) != 0 && missing(s2_options))\n\t\t\ts2_options = s2::s2_options(snap = s2::s2_snap_precision(st_precision(x)), ...)\n\t\tfull = st_is_full(x) # workaround, see https://github.com/r-spatial/s2/issues/262\n\t\ts2 = s2::s2_rebuild(s2, s2_options)\n\t\tret = st_as_sfc(s2, crs = crs)\n\t\tret[full] = st_polygon(list(POLYGON_FULL))\n\t\tret\n\t} else if (compareVersion(CPL_geos_version(), \"3.8.0\") == -1) {\n\t\tif (!missing(geos_method) || !missing(geos_keep_collapsed))\n\t\t\twarning(\"ignoring arguments geos_method and geos_keep_collapsed, as these require GEOS >= 3.8.0\")\n\t\tif (!requireNamespace(\"lwgeom\", quietly = TRUE))\n\t\t\tstop(\"package lwgeom required, please install it first\") # nocov\n\t\tst_sfc(lwgeom::lwgeom_make_valid(x), crs = crs)\n\t} else\n\t\tst_sfc(CPL_geos_make_valid(x, geos_method, geos_keep_collapsed), crs = crs)\n}\n\n#' @export\nst_make_valid.sf = function(x, ...) {\n\tst_set_geometry(x, st_make_valid(st_geometry(x), ...))\n}\n"
  },
  {
    "path": "R/wkb.R",
    "content": "# convert character string, as typically PostgreSQL returned blobs, to raw vector;\n# skips a leading \"0x\", as this is created by PostGIS when using ST_asBinary()\n#\n# most wkb read/write stuff was modified & extended from Ian Cook's wkb package,\n# https://cran.r-project.org/web/packages/wkb/index.html\n#\nhex_to_raw = function(y) {\n\tstopifnot((nchar(y) %% 2) == 0)\n\tif (startsWith(y, \"0x\"))\n\t\ty = substr(y, 3, nchar(y))\n\tas.raw(as.numeric(paste0(\"0x\", vapply(seq_len(nchar(y)/2),\n\t\tfunction(x) substr(y, (x-1)*2+1, x*2), \"\")))) # SLOW, hence the Rcpp implementation\n}\n\nskip0x = function(x) {\n\tif (is.na(x))\n\t\t\"010700000000000000\" # empty GeometryCollection, st_as_binary(st_geometrycollection())\n\telse if (startsWith(x, \"0x\"))\n\t\tsubstr(x, 3, nchar(x))\n\telse\n\t\tx\n}\n\n#' @name st_as_sfc\n#' @param EWKB logical; if `TRUE`, parse as EWKB (extended WKB; PostGIS: ST_AsEWKB), otherwise as ISO WKB (PostGIS: ST_AsBinary)\n#' @param spatialite logical; if \\code{TRUE}, WKB is assumed to be in the spatialite dialect, see \\url{https://www.gaia-gis.it/gaia-sins/BLOB-Geometry.html}; this is only supported in native endian-ness (i.e., files written on system with the same endian-ness as that on which it is being read).\n#' @param pureR logical; if `TRUE`, use only R code, if `FALSE`, use compiled (C++) code; use `TRUE` when the endian-ness of the binary differs from the host machine (\\code{.Platform$endian}).\n#' @details When converting from WKB, the object \\code{x} is either a character vector such as typically obtained from PostGIS (either with leading \"0x\" or without), or a list with raw vectors representing the features in binary (raw) form.\n#' @examples\n#' wkb = structure(list(\"01010000204071000000000000801A064100000000AC5C1441\"), class = \"WKB\")\n#' st_as_sfc(wkb, EWKB = TRUE)\n#' wkb = structure(list(\"0x01010000204071000000000000801A064100000000AC5C1441\"), class = \"WKB\")\n#' st_as_sfc(wkb, EWKB = TRUE)\n#' @export\nst_as_sfc.WKB = function(x, ..., EWKB = FALSE, spatialite = FALSE, pureR = FALSE, crs = NA_crs_) {\n\tif (EWKB && spatialite)\n\t\tstop(\"arguments EWKB and spatialite cannot both be TRUE\")\n\tif (spatialite && pureR)\n\t\tstop(\"pureR implementation for spatialite reading is not available\")\n    if (all(vapply(x, is.character, TRUE))) {\n\t\tx <- if (pureR)\n\t\t\t\tstructure(lapply(x, hex_to_raw), class = \"WKB\")\n\t\t\telse\n\t\t\t\tstructure(CPL_hex_to_raw(vapply(x, skip0x, USE.NAMES = FALSE, \"\")), class = \"WKB\")\n\t} else # direct call with raw:\n\t\tstopifnot(inherits(x, \"WKB\"), vapply(x, is.raw, TRUE)) # WKB as raw\n\tif (any(lengths(x) == 0))\n\t\tstop(\"cannot read WKB object from zero-length raw vector\")\n\tret = if (pureR)\n\t\t\tR_read_wkb(x, readWKB, EWKB = EWKB)\n\t\telse\n\t\t\tCPL_read_wkb(x, EWKB, spatialite)\n\tif (is.na(crs) && (EWKB || spatialite) && !is.null(attr(ret, \"srid\")) && attr(ret, \"srid\") != 0)\n\t\tcrs = attr(ret, \"srid\")\n\tif (! is.na(st_crs(crs))) {\n\t\tattr(ret, \"srid\") = NULL # remove\n\t\tst_sfc(ret, crs = crs)\n\t} else\n\t\tst_sfc(ret) # leave attr srid in place: PostGIS srid that is not an EPSG code\n}\n\n#' @export\n#' @examples\n#' st_as_sfc(st_as_binary(st_sfc(st_point(0:1)))[[1]], crs = 4326)\n#' @name st_as_sfc\nst_as_sfc.raw = function(x, ...) {\n\tst_as_sfc(structure(list(x), class = \"WKB\"), ...)\n}\n\nR_read_wkb = function(x, readWKB, EWKB = EWKB) {\n\tret = lapply(x, readWKB, EWKB = EWKB)\n\tsrid = attr(ret[[1]], \"srid\")\n\tret = lapply(ret, function(x) { attr(x, \"srid\") = NULL; x })\n\tattr(ret, \"srid\") = srid\n\tret\n}\n\nsf.tp = toupper(c(\n\t# \"Geometry\",          # 0\n\t\"Point\",               # 1\n\t\"LineString\",          # 2\n\t\"Polygon\",             # 3\n\t\"MultiPoint\",          # 4\n\t\"MultiLineString\",     # 5\n\t\"MultiPolygon\",        # 6\n\t\"GeometryCollection\",  # 7\n\t\"CircularString\",      # 8 x\n\t\"CompoundCurve\",       # 9 x\n\t\"CurvePolygon\",        # 10 x\n\t\"MultiCurve\",          # 11 x\n\t\"MultiSurface\",        # 12 x\n\t\"Curve\",               # 13 x *\n\t\"Surface\",             # 14 x *\n\t\"PolyhedralSurface\",   # 15\n\t\"TIN\",                 # 16\n\t\"Triangle\"             # 17\n\t)) # \"Geometry\" = 0, should not be matched, is a superclass only\n\t   # x: not described in ISO document\n\t   # *: GDAL support see https://trac.osgeo.org/gdal/ticket/6401\n\nreadWKB = function(x, EWKB = FALSE) {\n\tstopifnot(inherits(x, \"raw\"))\n\trc <- rawConnection(x, \"r\")\n\ton.exit(close(rc))\n\tseek(rc, 0L)\n\t# read data:\n\treadData(rc, EWKB = EWKB)\n}\n\nparseTypeEWKB = function(wkbType, endian) {\n\t# following the OGC doc, 3001 is POINT with ZM; turns out, PostGIS does sth else -\n\t# read WKB, as well as EWKB; this post is more inormative of what is going on:\n\t# https://lists.osgeo.org/pipermail/postgis-devel/2004-December/000710.html\n\t# (without SRID, Z, M and ZM this all doesn't matter)\n\t# comparison ISO WKB and EWKB:\n\t# https://lists.osgeo.org/pipermail/postgis-devel/2004-December/000695.html\n\tstopifnot(length(wkbType) == 4)\n\tif (endian == \"little\") {\n\t\tsf_type = as.numeric(wkbType[1])\n\t\tinfo = as.raw(as.integer(wkbType[4]) %/% 2^4)\n\t} else {\n\t\tsf_type = as.numeric(wkbType[4])\n\t\tinfo = as.raw(as.integer(wkbType[1]) %/% 2^4)\n\t}\n\ttp = sf.tp[sf_type]\n\tstopifnot(!is.na(tp))\n\thas_srid = as.logical(info & as.raw(2)) # 2-bit is \"on\"?\n\tzm = if ((info & as.raw(12)) == as.raw(12))\n\t\t\"XYZM\"\n\telse if (info & as.raw(8))\n\t\t\"XYZ\"\n\telse if (info & as.raw(4))\n\t\t\"XYM\"\n\telse if (info == as.raw(0) || info == as.raw(2))\n\t\t\"XY\"\n\telse\n\t\tstop(paste(\"unknown value for info:\", info))\n\tlist(dims = nchar(zm), zm = zm, tp = tp, has_srid = has_srid)\n}\n\nparseTypeISO = function(wkbType) {\n\ttp = sf.tp[wkbType %% 1000]\n\tstopifnot(!is.na(tp))\n\tdd = wkbType %/% 1000\n\tzm = if (dd == 0)\n\t\t\"XY\"\n\telse if (dd == 1)\n\t\t\"XYZ\"\n\telse if (dd == 2)\n\t\t\"XYM\"\n\telse if (dd == 3)\n\t\t\"XYZM\"\n\telse\n\t\tstop(paste(\"unknown value for wkbType:\", wkbType))\n\tlist(dims = nchar(zm), zm = zm, tp = tp, has_srid = FALSE)\n}\n\nreadData = function(rc, EWKB = FALSE) {\n\t# read byte order:\n\tbyteOrder <- readBin(rc, what = \"raw\", size = 1L)\n\tstopifnot(byteOrder %in% c(as.raw(0L), as.raw(1L)))\n\tendian = ifelse(byteOrder == as.raw(1L), \"little\", \"big\")\n\t# read wkbType:\n\tsrid = NA_integer_\n\tif (EWKB) {\n\t\twkbType <- readBin(rc, what = \"raw\", n = 4L, size = 1L, endian = endian)\n\t\tpt <- parseTypeEWKB(wkbType, endian)\n\t\tif (pt$has_srid)\n\t\t\tsrid <- readBin(rc, what = \"integer\", size = 4L, endian = endian)\n\t} else {\n\t\twkbType <- readBin(rc, what = \"integer\", n = 1L, size = 4L, endian = endian)\n\t\tpt <- parseTypeISO(wkbType)\n\t}\n\t# read data part:\n\tret = switch(pt$tp,\n\t\tPOINT = readPoint(rc, pt$dims, endian),\n\t\tCURVE = ,\n\t\tCIRCULARSTRING = ,\n\t\tLINESTRING = readMatrix(rc, pt$dims, endian),\n\t\tSURFACE = ,\n\t\tPOLYGON = ,\n\t\tTRIANGLE = readMatrixList(rc, pt$dims, endian),\n\t\tMULTIPOINT = readMPoints(rc, pt$dims, endian, EWKB),\n\t\tMULTILINESTRING = ,\n\t\tMULTICURVE = ,\n\t\tMULTIPOLYGON = ,\n\t\tMULTISURFACE = ,\n\t\tPOLYHEDRALSURFACE = ,\n\t\tTIN = lapply(readGC(rc, pt$dims, endian, EWKB), unclass),\n\t\tGEOMETRYCOLLECTION = readGC(rc, pt$dims, endian, EWKB),\n\t\tCURVEPOLYGON = readGC(rc, pt$dims, endian, EWKB),\n\t\tstop(paste(\"type\", pt$tp, \"unsupported\")))\n\tclass(ret) <- c(pt$zm, pt$tp, \"sfg\")\n\tif (!is.na(srid))\n\t\tattr(ret, \"srid\") <- srid\n\tret\n}\n\nreadPoint = function(rc, dims, endian) {\n\treadBin(rc, what = \"double\", n = as.integer(dims), size = 8L, endian = endian)\n}\nreadMPoints = function(rc, dims, endian, EWKB) {\n\tnpts = readBin(rc, what = \"integer\", n = 1L, size = 4L, endian = endian)\n\tdo.call(rbind, lapply(seq_len(npts), function(x) readData(rc, EWKB)))\n}\nreadMatrix = function(rc, dims, endian) {\n\tnpts = readBin(rc, what = \"integer\", n = 1L, size = 4L, endian = endian)\n\tm = readBin(rc, what = \"double\", n = as.integer(npts * dims), size = 8L, endian = endian)\n\tt(matrix(m, nrow = dims)) # x1 y1, x2 y2 etc -> t()\n}\nreadMatrixList = function(rc, dims, endian) {\n\tnmtrx = readBin(rc, what = \"integer\", n = 1L, size = 4L, endian = endian)\n\tlapply(seq_len(nmtrx), function(x) readMatrix(rc, dims, endian))\n}\n#readMatrixListList = function(rc, dims, endian) {\n#\tnmtrxl = readBin(rc, what = \"integer\", n = 1L, size = 4L, endian = endian)\n#\tlapply(seq_len(nmtrxl), function(x) readMatrixList(rc, dims, endian))\n#}\nreadGC = function(rc, dims, endian, EWKB) {\n\tngc = readBin(rc, what = \"integer\", n = 1L, size = 4L, endian = endian)\n\tlapply(seq_len(ngc), function(x) readData(rc, EWKB))\n}\n\n#' Convert sfc object to an WKB object\n#'\n#' Convert sfc object to an WKB object\n#' @param x object to convert\n#' @param ... ignored\n#' @name st_as_binary\n#' @export\nst_as_binary = function(x, ...) UseMethod(\"st_as_binary\")\n\n#' @name st_as_binary\n#' @param endian character; either \"big\" or \"little\"; default: use that of platform\n#' @param EWKB logical; use EWKB (PostGIS), or (default) ISO-WKB?\n#' @param pureR logical; use pure R solution, or C++?\n#' @param precision numeric; if zero, do not modify; to reduce precision: negative values convert to float (4-byte real); positive values convert to round(x*precision)/precision. See details.\n#' @param hex logical; return as (unclassed) hexadecimal encoded character vector?\n#' @param srid integer; override srid (can be used when the srid is unavailable locally).\n#' @details \\code{st_as_binary} is called on sfc objects on their way to the GDAL or GEOS libraries, and hence does rounding (if requested) on the fly before e.g. computing spatial predicates like \\link{st_intersects}. The examples show a round-trip of an \\code{sfc} to and from binary.\n#'\n#' For the precision model used, see also \\url{https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/PrecisionModel.html}. There, it is written that: ``... to specify 3 decimal places of precision, use a scale factor of 1000. To specify -3 decimal places of precision (i.e. rounding to the nearest 1000), use a scale factor of 0.001.''. Note that ALL coordinates, so also Z or M values (if present) are affected.\n#' @export\n#' @examples\n#' # examples of setting precision:\n#' st_point(c(1/3, 1/6)) |> st_sfc(precision = 1000) |> st_as_binary() |> st_as_sfc()\n#' st_point(c(1/3, 1/6)) |> st_sfc(precision =  100) |> st_as_binary() |> st_as_sfc()\n#' st_point(1e6 * c(1/3, 1/6)) |> st_sfc(precision = 0.01) |> st_as_binary() |> st_as_sfc()\n#' st_point(1e6 * c(1/3, 1/6)) |> st_sfc(precision = 0.001) |> st_as_binary() |> st_as_sfc()\nst_as_binary.sfc = function(x, ..., EWKB = FALSE, endian = .Platform$endian, pureR = FALSE,\n\t\tprecision = attr(x, \"precision\"), hex = FALSE) {\n\tstopifnot(endian %in% c(\"big\", \"little\"))\n\tif (pureR && precision != 0.0)\n\t\tstop(\"for non-zero precision values, use pureR = FALSE\")\n\tret = if (pureR)\n\t\tstructure(lapply(x, st_as_binary.sfg, EWKB = EWKB, pureR = pureR, endian = endian), class = \"WKB\")\n\telse {\n\t\tstopifnot(endian == .Platform$endian)\n\t\tattr(x, \"precision\") = precision\n\t\tstructure(CPL_write_wkb(x, EWKB), class = \"WKB\")\n\t}\n\tif (hex)\n\t\tvapply(ret, CPL_raw_to_hex, \"\")\n\telse\n\t\tret\n}\n\ncreateType = function(x, endian, EWKB = FALSE) {\n\tdims = x[1]  # \"XY\", \"XYZ\", \"XYM\", or \"XYZM\"\n\tcl = x[2]\n\tm = match(cl, sf.tp)\n\tif (is.na(m))\n\t\tstop(paste(\"Class\", cl, \"not matched\"))\n\t# return:\n\tif (! EWKB) # ISO: add 1000s\n\t\tas.integer(m + switch(dims, \"XYZ\" = 1000, \"XYM\" = 2000, \"XYZM\" = 3000, 0))\n\telse { # EWKB: set higher bits\n\t\tret = raw(4)\n\t\tret[1] = as.raw(m) # set up little-endian\n\t\tret[4] = as.raw(switch(dims, \"XYZ\" = 0x80, \"XYM\" = 0x40, \"XYZM\" = 0xC0, 0))\n\t\tif (endian == \"big\")\n\t\t\trev(ret)\n\t\telse\n\t\t\tret\n\t}\n}\n\n#' @name st_as_binary\n#' @export\nst_as_binary.sfg = function(x, ..., endian = .Platform$endian, EWKB = FALSE, pureR = FALSE,\n\t\thex = FALSE, srid = 0) {\n# if pureR, it's done here, if not, it's done in st_as_binary.sfc\n\tstopifnot(endian %in% c(\"big\", \"little\"))\n\tif (! pureR)\n\t\tst_as_binary.sfc(st_sfc(x), endian == endian, EWKB = EWKB, pureR = pureR, hex = hex, srid = srid, ...)[[1]]\n\telse {\n\t\trc <- rawConnection(raw(0), \"r+\")\n\t\ton.exit(close(rc))\n\t\twriteData(x, rc, endian, EWKB)\n\t\tr = rawConnectionValue(rc)\n\t\tif (hex)\n\t\t\tr = rawToHex(r)\n\t\tr\n\t}\n}\n\n#' Convert raw vector(s) into hexadecimal character string(s)\n#'\n#' Convert raw vector(s) into hexadecimal character string(s)\n#' @param x raw vector, or list with raw vectors\n#' @export\nrawToHex = function(x) {\n\tif (is.raw(x))\n\t\tCPL_raw_to_hex(x)\n\telse if (is.list(x) && all(vapply(x, is.raw, TRUE)))\n\t\tvapply(x, function(rw) CPL_raw_to_hex(rw), \"\")\n\telse\n\t\tstop(paste(\"not implemented for objects of class\", class(x)))\n}\n\nwriteData = function(x, rc, endian, EWKB = FALSE) {\n\tif (endian == \"big\")\n\t\twriteBin(as.raw(0L), rc)\n\telse\n\t\twriteBin(as.raw(1L), rc)\n\tif (EWKB)\n\t\twriteBin(createType(class(x), endian, TRUE), rc, size = 1L, endian = endian)\n\telse\n\t\twriteBin(createType(class(x)), rc, size = 4L, endian = endian)\n\t# TODO (?): write SRID in case of EWKB?\n\t# write out x:\n\tswitch(class(x)[2],\n\t\tPOINT = writeBin(as.vector(as.double(x)), rc, size = 8L, endian = endian),\n\t\tLINESTRING = writeMatrix(x, rc, endian),\n\t\tPOLYGON = ,\n\t\tTRIANGLE = writeMatrixList(x, rc, endian),\n\t\tMULTIPOINT = writeMPoints(x, rc, endian, EWKB),\n\t\tPOLYHEDRALSURFACE = ,\n\t\tTIN = ,\n\t\tMULTILINESTRING = ,\n\t\tMULTIPOLYGON = writeMulti(x, rc, endian, EWKB),\n\t\tGEOMETRYCOLLECTION = writeGC(x, rc, endian, EWKB),\n\t\tstop(paste(\"unimplemented class to write:\", class(x)[2]))\n\t)\n}\n\nwriteMulti = function(x, rc, endian, EWKB) {\n\tunMulti = if (inherits(x, \"MULTILINESTRING\"))\n\t\tst_linestring\n\telse # MULTIPOLYGON, POLYHEDRALSURFACE, TIN:\n\t\tst_polygon\n\twriteBin(as.integer(length(x)), rc, size = 4L, endian = endian)\n\tlapply(lapply(x, unMulti, class(x)[1]), writeData, rc = rc, endian = endian, EWKB = EWKB)\n}\nwriteGC = function(x, rc, endian, EWKB) {\n\twriteBin(as.integer(length(x)), rc, size = 4L, endian = endian)\n\tlapply(x, writeData, rc = rc, endian = endian, EWKB = EWKB)\n}\nwriteMatrix = function(x, rc, endian) {\n\twriteBin(as.integer(nrow(x)), rc, size = 4L, endian = endian)\n\twriteBin(as.double(as.vector(t(x))), rc, size = 8L, endian = endian)\n}\nwriteMatrixList = function(x, rc, endian) {\n\twriteBin(as.integer(length(x)), rc, size = 4L, endian = endian)\n\tlapply(x, function(y) writeMatrix(y, rc, endian))\n}\nwriteMPoints = function(x, rc, endian, EWKB) {\n\twriteBin(as.integer(nrow(x)), rc, size = 4L, endian = endian)\n\tif (nrow(x))\n\t\tapply(x, 1, function(y) writeData(st_point(y, class(x)[1]), rc, endian, EWKB))\n}\n"
  },
  {
    "path": "R/wkt.R",
    "content": "# composed, WKT class name: \"XYZ\", \"POINT\" -> \"POINT Z\"\nWKT_name = function(x, EWKT = TRUE) {\n\tcls = class(x)\n\tzm = substr(cls[1], 3, 4)\n\n\tretval = if (zm == \"\")\n\t\tcls[2]\n\telse\n\t\tpaste(cls[2], substr(cls[1], 3, 4))\n\n\tif (EWKT && !is.null(attr(x, \"epsg\")) && !is.na(attr(x, \"epsg\")))\n\t\tpaste0(\"SRID=\", attr(x, \"epsg\"), \";\", retval)\n\telse\n\t\tretval\n}\n\nempty = \"EMPTY\"\n\n# skip leading white space; ... passes on digits:\nfmt = function(x, ...) sub(\"^[ ]+\", \"\", sapply(unclass(x), format, ...))\n\n# print helper functions\nprnt.POINT = function(x, ..., EWKT = TRUE) {\n\tpt = if (any(!is.finite(x)))\n\t\tempty\n\telse\n\t\tpaste0(\"(\", paste0(fmt(x, ...), collapse = \" \"), \")\")\n\tpaste(WKT_name(x, EWKT = EWKT), pt)\n}\n\nprnt.Matrix = function(x, nested_parens = FALSE, ...) {\n\tpf = function(x, ..., collapse) paste0(fmt(x, ...), collapse = collapse)\n\tif (nrow(x) == 0)\n\t\tempty\n\telse if (nested_parens)\n\t\tpaste0(\"((\", paste0(apply(x, 1, pf, collapse = \" \", ...), collapse = \"), (\"), \"))\")\n\telse\n\t\tpaste0(\"(\", paste0(apply(x, 1, pf, collapse = \" \", ...), collapse = \", \"), \")\")\n}\n\nprnt.MatrixList = function(x, ...) {\n\tif (length(x) == 0)\n\t\tempty\n\telse\n\t\tpaste0(\"(\", paste0(unlist(lapply(x, prnt.Matrix, ...)), collapse = \", \"), \")\")\n}\n\nprnt.MatrixListList = function(x, ...) {\n\tif (length(x) == 0)\n\t\tempty\n\telse\n\t\tpaste0(\"(\", paste0(unlist(lapply(x, prnt.MatrixList, ...)), collapse = \", \"), \")\")\n}\n\nprnt.MULTIPOINT = function(x, ..., EWKT = TRUE, nested_parens = FALSE) {\n\tpaste(WKT_name(x, EWKT = EWKT),\n\t\t  prnt.Matrix(x, nested_parens = nested_parens, ...))\n}\nprnt.LINESTRING = function(x, ..., EWKT = TRUE) paste(WKT_name(x, EWKT = EWKT), prnt.Matrix(x, ...))\n\nprnt.POLYGON = function(x, ..., EWKT = TRUE) {\n\tif (st_is_full(x, ...))\n\t\t\"POLYGON FULL\"\n\telse\n\t\tpaste(WKT_name(x, EWKT = EWKT), prnt.MatrixList(x, ...))\n}\n\nprnt.MULTILINESTRING = function(x, ..., EWKT = TRUE) paste(WKT_name(x, EWKT = EWKT), prnt.MatrixList(x, ...))\nprnt.MULTIPOLYGON = function(x, ..., EWKT = TRUE) paste(WKT_name(x, EWKT = EWKT), prnt.MatrixListList(x, ...))\nprnt.GEOMETRYCOLLECTION = function(x, ..., EWKT = TRUE) {\n\tbody = if (length(x) == 0)\n\t\tempty\n\telse\n\t\tpaste0(\"(\", paste0(vapply(x, st_as_text, \"\", ...), collapse=\", \"), \")\")\n\tpaste(WKT_name(x, EWKT = EWKT), body)\n}\n\n#' Return Well-known Text representation of simple feature geometry or coordinate reference system\n#'\n#' Return Well-known Text representation of simple feature geometry or coordinate reference system\n#' @param x object of class \\code{sfg}, \\code{sfc} or \\code{crs}\n#' @param ... modifiers; in particular \\code{digits} can be passed to control the number of digits used\n#' @name st_as_text\n#' @details The returned WKT representation of simple feature geometry conforms to the\n#' \\href{https://en.wikipedia.org/wiki/Simple_Features}{simple features access} specification and extensions\n#' (known as EWKT, supported by PostGIS and other simple features implementations for addition of \n#' a SRID to a WKT string).\n#' @note To improve conversion performance, the lwgeom package can be used (it must be installed\n#' beforehand) and set the \\code{Sys.setenv(\"LWGEOM_WKT\" = \"true\")} environment variable. This\n#' will also result in faster printing of complex geometries. Note that the representation as WKT is\n#' different from the sf package and may cause reproducibility problems. An alternative solution is\n#' to use the [lwgeom::st_astext()] or [wk::as_wkt()] functions.\n#'\n#' @export\nst_as_text = function(x, ...) UseMethod(\"st_as_text\")\n\n#' @name st_as_text\n#' @export\n#' @examples\n#' st_as_text(st_point(1:2))\n#' st_as_text(st_sfc(st_point(c(-90,40)), crs = 4326), EWKT = TRUE)\nst_as_text.sfg = function(x, ...) {\n\tif (Sys.getenv(\"LWGEOM_WKT\") == \"true\" && requireNamespace(\"lwgeom\", quietly = TRUE) && utils::packageVersion(\"lwgeom\") >= \"0.1-5\")\n\t\tlwgeom::st_astext(x, ...)\n\telse\n\t  switch(class(x)[2],\n\t\tPOINT = prnt.POINT(x, ...),\n\t\tMULTIPOINT =        prnt.MULTIPOINT(x, ..., nested_parens = TRUE),\n\t\tLINESTRING =        prnt.LINESTRING(x, ...),\n\t\tPOLYGON =           prnt.POLYGON(x, ...),\n\t\tMULTILINESTRING =   prnt.MULTILINESTRING(x, ...),\n\t\tMULTIPOLYGON =      prnt.MULTIPOLYGON(x, ...),\n\t\tGEOMETRYCOLLECTION =prnt.GEOMETRYCOLLECTION(x, ...),\n\t\tCIRCULARSTRING =    prnt.MULTIPOINT(x, ...),\n\t\tCOMPOUNDCURVE =     prnt.GEOMETRYCOLLECTION(x, ...),\n\t\tCURVE =             prnt.MULTIPOINT(x, ...),\n\t\tCURVEPOLYGON =      prnt.GEOMETRYCOLLECTION(x, ...),\n\t\tMULTICURVE =        prnt.GEOMETRYCOLLECTION(x, ...),\n\t\tMULTISURFACE =      prnt.GEOMETRYCOLLECTION(x, ...),\n\t\tPOLYHEDRALSURFACE = prnt.MULTIPOLYGON(x, ...),\n\t\tTRIANGLE =          prnt.POLYGON(x, ...),\n\t\tTIN =                prnt.MULTIPOLYGON(x, ...),\n\t\tstop(paste(\"no print method available for object of class\", class(x)[2])) # nocov\n\t)\n}\n\n#' @name st_as_text\n#' @param EWKT logical; if TRUE, print SRID=xxx; before the WKT string if \\code{epsg} is available\n#' @export\nst_as_text.sfc = function(x, ..., EWKT = FALSE) {\n\tif (Sys.getenv(\"LWGEOM_WKT\") == \"true\" && requireNamespace(\"lwgeom\", quietly = TRUE) && utils::packageVersion(\"lwgeom\") >= \"0.1-5\")\n\t\tlwgeom::st_astext(x, ..., EWKT = EWKT)\n\telse {\n\t\tif (EWKT) {\n\t\t\tepsg = attr(x, \"crs\")$epsg\n\t\t\tif (!is.na(epsg) && epsg != 0)\n\t\t\t\tx = lapply(x, function(sfg) structure(sfg, epsg = epsg))\n\t\t}\n\t\tvapply(x, st_as_text, \"\", ..., EWKT = EWKT)\n\t}\n}\n\n#' @name st_as_sfc\n#' @rdname st_as_sfc\n#' @md\n#' @details If `x` is a character vector, it should be a vector containing\n#' [well-known-text](https://www.ogc.org/standards/wkt-crs/), or\n#' Postgis EWKT or GeoJSON representations of a single geometry for each vector element.\n#' @param crs integer or character; coordinate reference system for the\n#' @param GeoJSON logical; if \\code{TRUE}, try to read geometries from GeoJSON text strings\n#' geometry, see [st_crs()]\n#' @export\n#' @examples\n#' st_as_sfc(\"SRID=3978;LINESTRING(1663106 -105415,1664320 -104617)\")\nst_as_sfc.character = function(x, crs = NA_integer_, ..., GeoJSON = FALSE) {\n\tif (length(x) == 0)\n\t\tst_sfc(crs = crs)\n\telse if (GeoJSON) {\n\t\tret = st_geometry(do.call(rbind, lapply(x, st_read, quiet = TRUE)))\n\t\tif (is.na(st_crs(ret)))\n\t\t\tst_set_crs(ret, crs)\n\t\telse\n\t\t\tret\n\t} else {\n\t\tif (all(is_ewkt(x)) && is.na(crs)) {\n\t\t\t# EWKT\n\t\t\tcrs = get_crs_ewkt(x)\n\t\t\tcrs = unique(crs)\n\t\t\tif (length(crs) != 1) {\n\t\t\t\tstop(\"sf does not support multiple crs (\",\n\t\t\t\t\t paste(crs, collapse = \", \"),\n\t\t\t\t\t \") within a single geometry column.\",\n\t\t\t\t\t \"You can override the crs from the string by using the \",\n\t\t\t\t\t \"`crs` option from `st_as_sfc()`.\",\n\t\t\t\t\t call. = FALSE)\n\t\t\t}\n\t\t\tx = ewkt_to_wkt(x)\n\t\t}\n\t\tif (sf_use_s2() && !identical(st_is_longlat(crs), FALSE) && any(full <- (x == \"POLYGON FULL\")))\n\t\t\tx[full] = \"POLYGON((0 -90,0 -90))\" # s2 struct for POLYGON FULL\n\t\tret = st_sfc(CPL_sfc_from_wkt(x))\n\t\tst_crs(ret) = crs\n\t\tret\n\t}\n}\n#' @name st_as_sfc\n#' @details If \\code{x} is a \\code{factor}, it is converted to \\code{character}.\n#' @export\nst_as_sfc.factor = function(x, ...) {\n\tst_as_sfc(as.character(x), ...)\n}\n\nis_ewkt = function(x) {\n\tgrepl(\"^SRID=(\\\\d+);\", x)\n}\n\nget_crs_ewkt = function(x) {\n\tas.numeric(gsub(\"^SRID=(\\\\d+);.+$\", \"\\\\1\", x))\n}\n\newkt_to_wkt = function(x) {\n\tgsub(\"^SRID=(\\\\d+);(.+)$\", \"\\\\2\", x)\n}\n"
  },
  {
    "path": "R/z_range.R",
    "content": "\n#' @name st_z_range\n#' @param x object of class \\code{z_range}\n#' @export\nis.na.z_range = function(x) identical(x, NA_z_range_)\n\nzb_wrap = function(zb) {\n\tstopifnot(is.numeric(zb), length(zb) == 2)\n\tstructure(zb, names = c(\"zmin\", \"zmax\"), class = \"z_range\")\n}\n\nz_range.Set = function(obj, ...) {\n\tsel = vapply(obj, function(x) { length(x) && !all(is.na(x)) }, TRUE)\n\tif (! any(sel))\n\t\tNA_z_range_\n\telse\n\t\tzb_wrap(CPL_get_z_range(unclass(obj)[sel], 0))\n}\nz_range.Mtrx = function(obj, ...) {\n\tif (length(obj) == 0)\n\t\tNA_z_range_\n\telse\n\t\tzb_wrap(CPL_get_z_range(list(obj), 1)) # note the list()\n}\nz_range.MtrxSet = function(obj, ...) {\n\tif (length(obj) == 0)\n\t\tNA_z_range_\n\telse\n\t\tzb_wrap(CPL_get_z_range(obj, 1))\n}\nz_range.MtrxSetSet = function(obj, ...) {\n\tif (length(obj) == 0)\n\t\tNA_z_range_\n\telse\n\t\tzb_wrap(CPL_get_z_range(obj, 2))\n}\nz_range.MtrxSetSetSet = function(obj, ...) {\n\tif (length(obj) == 0)\n\t\tNA_z_range_\n\telse\n\t\tzb_wrap(CPL_get_z_range(obj, 3))\n}\n\n#' Return 'z' range of a simple feature or simple feature set\n#'\n#' Return 'z' range of a simple feature or simple feature set\n#' @param obj object to compute the z range from\n#' @param ... ignored\n#' @export\n#' @return a numeric vector of length two, with \\code{zmin} and \\code{zmax} values;\n#' if \\code{obj} is of class \\code{sf} or \\code{sfc} the object\n#' returned has a class \\code{z_range}\n#' @name st_z_range\n#' @examples\n#' a = st_sf(a = 1:2, geom = st_sfc(st_point(0:2), st_point(1:3)), crs = 4326)\n#' st_z_range(a)\nst_z_range = function(obj, ...) UseMethod(\"st_z_range\")\n\n#' @export\n#' @name st_z_range\nst_z_range.POINT = function(obj, ...) zb_wrap(c(obj[3L], obj[3L]))\n#' @export\n#' @name st_z_range\nst_z_range.MULTIPOINT = z_range.Mtrx\n#' @export\n#' @name st_z_range\nst_z_range.LINESTRING = z_range.Mtrx\n#' @export\n#' @name st_z_range\nst_z_range.POLYGON = z_range.MtrxSet\n#' @export\n#' @name st_z_range\nst_z_range.MULTILINESTRING = z_range.MtrxSet\n#' @export\n#' @name st_z_range\nst_z_range.MULTIPOLYGON = z_range.MtrxSetSet\n\nz_range_list = function(obj, ...) {\n\ts = vapply(obj, st_z_range, c(0.,0.)) # dispatch on class\n\tif (length(s) == 0 || all(is.na(s[1L,])))\n\t\tNA_z_range_\n\telse\n\t\tzb_wrap(c(min(s[1L,], na.rm = TRUE), max(s[2L,], na.rm = TRUE)))\n}\n\n#' @name st_z_range\n#' @export\nst_z_range.GEOMETRYCOLLECTION = z_range_list\n\n#' @name st_z_range\n#' @export\nst_z_range.MULTISURFACE = z_range_list\n\n#' @name st_z_range\n#' @export\nst_z_range.MULTICURVE = z_range_list\n\n#' @name st_z_range\n#' @export\nst_z_range.CURVEPOLYGON = z_range_list\n\n#' @name st_z_range\n#' @export\nst_z_range.COMPOUNDCURVE = z_range_list\n\n#' @name st_z_range\n#' @export\nst_z_range.POLYHEDRALSURFACE = z_range.MtrxSetSet\n\n#' @name st_z_range\n#' @export\nst_z_range.TIN = z_range.MtrxSetSet\n\n#' @name st_z_range\n#' @export\nst_z_range.TRIANGLE = z_range.MtrxSet\n\n#' @name st_z_range\n#' @export\nst_z_range.CIRCULARSTRING = function(obj, ...) {\n\t# this is of course wrong:\n\tst_z_range(st_cast(obj, \"LINESTRING\")) # nocov\n}\n\n#' @export\nprint.z_range = function(x, ...) {\n\tx = structure(x, crs = NULL, class = NULL) # nocov\n\tprint(set_units(x, attr(x, \"units\"), mode = \"standard\")) # nocov\n}\n\ncompute_z_range = function(obj) {\n\tswitch(class(obj)[1],\n\t\t   sfc_POINT = zb_wrap(z_range.Set(obj)),\n\t\t   sfc_MULTIPOINT = zb_wrap(z_range.MtrxSet(obj)),\n\t\t   sfc_LINESTRING = zb_wrap(z_range.MtrxSet(obj)),\n\t\t   sfc_POLYGON = zb_wrap(z_range.MtrxSetSet(obj)),\n\t\t   sfc_MULTILINESTRING = zb_wrap(z_range.MtrxSetSet(obj)),\n\t\t   sfc_MULTIPOLYGON = zb_wrap(z_range.MtrxSetSetSet(obj)),\n\t\t   z_range_list(obj)\n\t)\n}\n\n#' @name st_z_range\n#' @export\nst_z_range.sfc = function(obj, ...) {\n\ta = attr(obj, \"z_range\")\n\tif(is.null(a)) return( NULL ) ## TODO return null?\n\tstructure(a, crs = st_crs(obj))\n}\n#' @name st_z_range\n#' @export\nst_z_range.sf = function(obj, ...) st_z_range(st_geometry(obj))\n\n#' @name st_z_range\n#' @param crs object of class \\code{crs}, or argument to \\link{st_crs}, specifying the CRS of this bounding box.\n#' @examples\n#' st_z_range(c(zmin = 16.1, zmax = 16.6), crs = st_crs(4326))\n#' @export\nst_z_range.numeric = function(obj, ..., crs = NA_crs_) {\n\tstructure(zb_wrap(obj[c(\"zmin\", \"zmax\")]), crs = st_crs(crs)) # nocov\n}\n\n#' @export\nst_z_range.z_range = function(obj, ...) obj # nocov\n\n\n#' @export\n\"$.z_range\" = function(x, name) { # nocov start\n\tswitch(name,\n\t\t   zmin = x[\"zmin\"],\n\t\t   zmax = x[\"zmax\"],\n\t\t   stop(\"unsupported name\")\n\t)\n} # nocov end\n\n#' @name st_z_range\n#' @details \\code{NA_z_range_} represents the missing value for a \\code{z_range} object\n#' @export\nNA_z_range_ = structure(rep(NA_real_, 2),\n\t\t\t\t\t names = c(\"zmin\", \"zmax\"),\n\t\t\t\t\t crs = NA_crs_,\n\t\t\t\t\t class = \"z_range\")\n"
  },
  {
    "path": "README.md",
    "content": "<!-- badges: start -->\n[![R-CMD-check](https://github.com/r-spatial/sf/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/r-spatial/sf/actions/workflows/R-CMD-check.yaml)\n[![tic-db](https://github.com/r-spatial/sf/actions/workflows/tic-db.yml/badge.svg)](https://github.com/r-spatial/sf/actions/workflows/tic-db.yml)\n[![Coverage Status](https://img.shields.io/codecov/c/github/r-spatial/sf/main.svg)](https://app.codecov.io/gh/r-spatial/sf)\n[![License](http://img.shields.io/badge/license-GPL%20%28%3E=%202%29-brightgreen.svg?style=flat)](http://www.gnu.org/licenses/gpl-2.0.html)\n[![CRAN](https://www.r-pkg.org/badges/version/sf)](https://cran.r-project.org/package=sf)\n[![cran checks](https://badges.cranchecks.info/worst/sf.svg)](https://cran.r-project.org/web/checks/check_results_sf.html)\n[![Downloads](https://cranlogs.r-pkg.org/badges/sf?color=brightgreen)](https://www.r-pkg.org/pkg/sf)\n[![status](https://tinyverse.netlify.app/badge/sf)](https://CRAN.R-project.org/package=sf)\n<!-- badges: end -->\n\n# Simple Features for R\n\n<a href=\"https://gist.github.com/edzer/f461a3a95570c4ab7edf3125c2f19d20\"><img align=\"right\" src=\"https://user-images.githubusercontent.com/520851/34887433-ce1d130e-f7c6-11e7-83fc-d60ad4fae6bd.gif\" /></a>\n\nA package that provides [simple features access](https://en.wikipedia.org/wiki/Simple_Features) for R. \n\n[Blogs, links](#blogs-presentations-vignettes-sp-sf-wiki) • [Cheatsheet](#cheatsheet) • [Installing](#installing)\n• [Contributing](#contributing) • [Acknowledgment](#acknowledgment) • [How to cite](#how-to-cite)\n\nPackage sf:\n\n* represents simple features as records in a `data.frame` or `tibble` with a geometry list-column\n* represents natively in R all 17 simple feature types for all dimensions (XY, XYZ, XYM, XYZM)\n* interfaces to [GEOS](https://libgeos.org) for geometrical operations on projected coordinates, and (through R package [s2](https://cran.r-project.org/package=s2)) to [s2geometry](http://s2geometry.io/) for geometrical operations on ellipsoidal coordinates\n* interfaces to [GDAL](https://gdal.org/), supporting all driver options, `Date` and `POSIXct` and list-columns\n* interfaces to [PRØJ](http://proj.org/) for coordinate reference system conversion and transformation\n* uses [well-known-binary](https://en.wikipedia.org/wiki/Well-known_text#Well-known_binary) serialisations written in C++/Rcpp for fast I/O with GDAL and GEOS \n* reads from and writes to spatial databases such as [PostGIS](http://postgis.net/) using [DBI](https://cran.r-project.org/package=DBI)\n* is extended by \n    * [lwgeom](https://github.com/r-spatial/lwgeom/) for selected liblwgeom/PostGIS functions\n    * [stars](https://github.com/r-spatial/stars/) for raster data, and raster or vector data cubes (spatial time series)\n    * [sfnetworks](https://luukvdmeer.github.io/sfnetworks/) for geospatial network data\n\n<a href=\"https://gist.github.com/edzer/442d74a5775abcd5068cf3e73b23687b\"><img align=\"left\" src=\"https://user-images.githubusercontent.com/520851/50280460-e35c1880-044c-11e9-9ed7-cc46754e49db.jpg\" /></a>\n\n(Illustration (c) 2018 by <a href=\"https://twitter.com/allison_horst/status/1071456081308614656\">Allison Horst</a>)\n\n## Books, journal articles, blogs, presentations, vignettes, sp-sf wiki\n\n* an open access [R Journal article](https://journal.r-project.org/archive/2018/RJ-2018-009/index.html) summarizes the package\n* two books: [Spatial Data Science: with applications in R](https://r-spatial.org/book/), [Geocomputation with R](https://r.geocompx.org/)\n* package vignettes: [first](https://r-spatial.github.io/sf/articles/sf1.html), [second](https://r-spatial.github.io/sf/articles/sf2.html), [third](https://r-spatial.github.io/sf/articles/sf3.html), [fourth](https://r-spatial.github.io/sf/articles/sf4.html), [fifth](https://r-spatial.github.io/sf/articles/sf5.html), [sixth](https://r-spatial.github.io/sf/articles/sf6.html), [seventh](https://r-spatial.github.io/sf/articles/sf7.html)\n* blog posts: [first](https://r-spatial.org/r/2016/02/15/simple-features-for-r.html), [second](https://r-spatial.org/r/2016/07/18/sf2.html), [third](https://r-spatial.org/r/2016/11/02/sfcran.html), [fourth](https://r-spatial.org/r/2017/01/12/newssf.html)\n* the original R Consortium ISC [proposal](PROPOSAL.md), the R Consortium [blog post](https://www.r-consortium.org/blog/2017/01/03/simple-features-now-on-cran)\n* presentations: [rstudio::conf 2018](https://edzer.github.io/rstudio_conf/#1) ([video](https://posit.co/resources/videos/tidy-spatial-data-analysis/)), [UseR! 2016](http://pebesma.staff.ifgi.de/pebesma_sfr.pdf)\n* wiki page describing [sp-sf migration](https://github.com/r-spatial/sf/wiki/Migrating)\n\n## Cheatsheet\n[CC 4.0](https://creativecommons.org/licenses/by/4.0/) BY [Ryan Garnett](https://github.com/ryangarnett)  \n\n<a href=\"https://github.com/rstudio/cheatsheets/blob/main/sf.pdf\"><img src=\"https://raw.githubusercontent.com/rstudio/cheatsheets/main/pngs/sf.png\" /></a>\n\n## Installing\n\nInstall either from CRAN with:\n```r\ninstall.packages(\"sf\")\n```\nThis will install binary packages on Windows and MacOS, unless you configured R such that it tries to install source packages; in that case, see below.\n\nInstall development versions from GitHub with:\n```r\nlibrary(remotes)\ninstall_github(\"r-spatial/sf\")\n```\n\n### Windows\n\nInstalling sf from source works under Windows when [Rtools](https://cran.r-project.org/bin/windows/Rtools/) is installed.\n\n### MacOS\n\nMacOS users are strongly encouraged to install the `sf` binary packages from CRAN, unless they are familiar with compilers, linking, C++ source code, and homebrew. If you experience that R tries to install `sf` from source (or otherwise your install fails but you don't understand what is going on) try again by explicitly installing the binary, using\n\n```r\ninstall.packages(\"sf\", type = \"binary\")\n```\n\nThe remainder of this section is for those who understand what source installs mean, and imply.\n\nPerhaps the easiest way of an install from source is to first install `gdal` using Homebrew. Recent versions of Homebrew include a full-featured up-to-date [gdal formula](https://github.com/Homebrew/homebrew-core/blob/master/Formula/g/gdal.rb), which installs `proj` and `gdal` at the same time:\n\n```\nbrew install pkg-config\nbrew install gdal\n```\n\nOnce gdal is installed, you may be able to install `sf` package from source in R. With the current version of `proj` on homebrew, installation requires additional configuration:\n\n```r\ninstall.packages(\"sf\", type = \"source\", configure.args = \"--with-proj-lib=$(brew --prefix)/lib/\")\n```\n\nOr the development version:\n\n```r\nlibrary(remotes)\ninstall_github(\"r-spatial/sf\", configure.args = \"--with-proj-lib=$(brew --prefix)/lib/\")\n```\n\nAlternatively, [these instructions](https://stat.ethz.ch/pipermail/r-sig-mac/2017-June/012429.html) explain how to install gdal using kyngchaos frameworks.\n\nFor Mac OS 11 Big Sur source install instruction, see [here](https://github.com/r-spatial/sf/issues/1536#issuecomment-727342736)\n\n### Linux\n\nFor Unix-alikes, GDAL (>= 2.0.1), GEOS (>= 3.4.0) and PROJ (>= 4.8.0) are required.\n\n#### Ubuntu\n\nDependencies for recent versions of Ubuntu (18.04 and later) are available in the official repositories; you can install them with:\n\n```sh\nsudo apt -y update && apt install -y libudunits2-dev libgdal-dev libgeos-dev libproj-dev libsqlite3-dev\n```\n\nHowever, to get more up-to-date versions of dependencies such as GDAL, GEOS and PROJ we recommend adding the [ubuntugis-unstable](http://ppa.launchpad.net/ubuntugis/ubuntugis-unstable/ubuntu/) PPA to the package repositories and installing them as follows:\n\n```sh\nsudo add-apt-repository ppa:ubuntugis/ubuntugis-unstable\nsudo apt update\nsudo apt install libudunits2-dev libgdal-dev libgeos-dev libproj-dev libsqlite3-dev\n```\n\nAdding this PPA is required for installing `sf` on older versions of Ubuntu (e.g. Xenial).\n\nAnother option, for advanced users, is to install dependencies from source; see e.g. an older [Travis](https://github.com/r-spatial/sf/blob/593ee48b34001fe3b383ea73ea57063ecf690732/.travis.yml) config file for hints.\n\n#### Fedora\nThe following command installs all required dependencies:\n```sh\nsudo dnf install gdal-devel proj-devel geos-devel sqlite-devel udunits2-devel\n```\n\n#### Arch\n\nGet gdal, proj, geos and podofo from the main repos, and udunits from the AUR:\n\n```\npacman -S gdal proj geos arrow podofo\nyay/pacaur/yaourt/whatever -S udunits\n```\n\n#### `renv` or `conda`\n\nThere are several reports that `sf` fails to install as a source package when R is used with `renv`, or when R is installed in a `conda` environment. If you experience this, please only raise an issue here if the problem persists without `renv` or `conda`, and otherwise \n\n* try to sort this out with the `renv` developers or the `conda` maintainers, or\n* try to use binary installs of the `sf` package, e.g. from [r2u](https://github.com/eddelbuettel/r2u), or the Posit package manager\n\n#### Other\n\nTo install on Debian, the [rocker geospatial](https://github.com/rocker-org/geospatial) Dockerfiles may be helpful. Ubuntu Dockerfiles are found [here](https://github.com/r-spatial/sf/tree/main/inst/docker).\n\n### Support for (Geo)Parquet and Arrow\n\n`sf` links to GDAL, but does not control how GDAL was configured and built. Not every GDAL installation has built-in support for GeoParquet or Arrow. Please see [this issue](https://github.com/r-spatial/sf/issues/2585), or configure and compile GDAL with Parquet support e.g. using [this Dockerfile](https://github.com/r-spatial/sf/tree/main/inst/docker/parquet).\n\n### Multiple GDAL, GEOS and/or PROJ versions on your system\n\nIf you use dynamic linking (installation from source) and have multiple versions of these libraries installed (e.g. one from ubuntugis-unstable, another installed from source in `/usr/local/lib`) then this will in general not work, even when setting `LD_LIBRARY_PATH` manually. See [here](https://github.com/r-spatial/sf/issues/844) for the reason why. \n\n### lwgeom\n\nFunctions and methods that require `liblwgeom`, including ellipsoidal (not spherical or Euclidean) metrics (area, distances), are provided by and used from [lwgeom](https://github.com/r-spatial/lwgeom), which is also on [CRAN](https://cran.r-project.org/package=lwgeom).\n\n## Contributing\n\n* Contributions of all sorts are most welcome, issues and pull requests are the preferred ways of sharing them.\n* When contributing pull requests, please adhere to the package style (in package code use `=` rather than `<-`; don't change indentation; tab stops of 4 spaces are preferred).\n* This project is released with a [Contributor Code of Conduct](CONDUCT.md). By participating in this project, you agree to abide by its terms.\n\n## How to cite\n\nPackage `sf` can be cited as: \n\n* Edzer Pebesma, 2018.  Simple Features for R: Standardized Support\nfor Spatial Vector Data. The R Journal [10:1, 439-446.](https://journal.r-project.org/archive/2018/RJ-2018-009/index.html)\n\n* Pebesma, E.; Bivand, R. (2023). [Spatial Data Science: With Applications in R](https://r-spatial.org/book/) \n(1st ed.). 314 pages. [Chapman and Hall/CRC](https://doi.org/10.1201/9780429459016).\n\n## Acknowledgment\n\nThis project gratefully acknowledges financial [support](https://www.r-consortium.org/projects) from the\n\n<a href=\"https://r-consortium.org/all-projects/2016-group-1.html#simple-features-for-r\">\n<img src=\"https://r-consortium.org/images/RConsortium_Horizontal_Pantone.webp\" width=\"300\">\n</a>\n<!--\n<img src=\"http://pebesma.staff.ifgi.de/RConsortium_Horizontal_Pantone.png\" width=\"300\">\n-->\n\n"
  },
  {
    "path": "_pkgdown.yml",
    "content": "url: https://r-spatial.github.io/sf/\n\ntemplate:\n  bootstrap: 5\n\nnavbar:\n  structure:\n    left:  [reference, articles, book, news]\n    right: [search, github]\n  components:\n    book:\n      text: Book\n      href: https://r-spatial.org/book/\n"
  },
  {
    "path": "cleanup",
    "content": "#!/bin/sh\nrm -fr src/Makevars config.log config.status autom4te.cache src/*.o src/*.so\nrm -fr vignette/nc*\nrm -fr proj_conf_test*\nrm -fr Rplots.pdf */Rplots.pdf\n"
  },
  {
    "path": "codecov.yml",
    "content": "comment: false\nignore:\n  - \"inst/include/sf_RcppExports.h\" \n  - \"sf/R/stars.R\"\n  - \"sf/R/gdal_utils.R\"\n  - \"sf/src/raster2sf.cpp\"\n  - \"sf/src/gdal_utils.cpp\"\n  - \"sf/src/stars.cpp\"\n\ncoverage:\n  status:\n    patch:\n      default:\n        target: 0\n        threshold: 100\n    project:\n      default:\n        target: 70\n        threshold: 100\n"
  },
  {
    "path": "configure",
    "content": "#! /bin/sh\n# Guess values for system-dependent variables and create Makefiles.\n# Generated by GNU Autoconf 2.71.\n#\n#\n# Copyright (C) 1992-1996, 1998-2017, 2020-2021 Free Software Foundation,\n# Inc.\n#\n#\n# This configure script is free software; the Free Software Foundation\n# gives unlimited permission to copy, distribute and modify it.\n## -------------------- ##\n## M4sh Initialization. ##\n## -------------------- ##\n\n# Be more Bourne compatible\nDUALCASE=1; export DUALCASE # for MKS sh\nas_nop=:\nif test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1\nthen :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on ${1+\"$@\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '${1+\"$@\"}'='\"$@\"'\n  setopt NO_GLOB_SUBST\nelse $as_nop\n  case `(set -o) 2>/dev/null` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac\nfi\n\n\n\n# Reset variables that may have inherited troublesome values from\n# the environment.\n\n# IFS needs to be set, to space, tab, and newline, in precisely that order.\n# (If _AS_PATH_WALK were called with IFS unset, it would have the\n# side effect of setting IFS to empty, thus disabling word splitting.)\n# Quoting is to prevent editors from complaining about space-tab.\nas_nl='\n'\nexport as_nl\nIFS=\" \"\"\t$as_nl\"\n\nPS1='$ '\nPS2='> '\nPS4='+ '\n\n# Ensure predictable behavior from utilities with locale-dependent output.\nLC_ALL=C\nexport LC_ALL\nLANGUAGE=C\nexport LANGUAGE\n\n# We cannot yet rely on \"unset\" to work, but we need these variables\n# to be unset--not just set to an empty or harmless value--now, to\n# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct\n# also avoids known problems related to \"unset\" and subshell syntax\n# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).\nfor as_var in BASH_ENV ENV MAIL MAILPATH CDPATH\ndo eval test \\${$as_var+y} \\\n  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :\ndone\n\n# Ensure that fds 0, 1, and 2 are open.\nif (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi\nif (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi\nif (exec 3>&2)            ; then :; else exec 2>/dev/null; fi\n\n# The user is always right.\nif ${PATH_SEPARATOR+false} :; then\n  PATH_SEPARATOR=:\n  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {\n    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||\n      PATH_SEPARATOR=';'\n  }\nfi\n\n\n# Find who we are.  Look in the path if we contain no directory separator.\nas_myself=\ncase $0 in #((\n  *[\\\\/]* ) as_myself=$0 ;;\n  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    test -r \"$as_dir$0\" && as_myself=$as_dir$0 && break\n  done\nIFS=$as_save_IFS\n\n     ;;\nesac\n# We did not find ourselves, most probably we were run as `sh COMMAND'\n# in which case we are not to be found in the path.\nif test \"x$as_myself\" = x; then\n  as_myself=$0\nfi\nif test ! -f \"$as_myself\"; then\n  printf \"%s\\n\" \"$as_myself: error: cannot find myself; rerun with an absolute file name\" >&2\n  exit 1\nfi\n\n\n# Use a proper internal environment variable to ensure we don't fall\n  # into an infinite loop, continuously re-executing ourselves.\n  if test x\"${_as_can_reexec}\" != xno && test \"x$CONFIG_SHELL\" != x; then\n    _as_can_reexec=no; export _as_can_reexec;\n    # We cannot yet assume a decent shell, so we have to provide a\n# neutralization value for shells without unset; and this also\n# works around shells that cannot unset nonexistent variables.\n# Preserve -v and -x to the replacement shell.\nBASH_ENV=/dev/null\nENV=/dev/null\n(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV\ncase $- in # ((((\n  *v*x* | *x*v* ) as_opts=-vx ;;\n  *v* ) as_opts=-v ;;\n  *x* ) as_opts=-x ;;\n  * ) as_opts= ;;\nesac\nexec $CONFIG_SHELL $as_opts \"$as_myself\" ${1+\"$@\"}\n# Admittedly, this is quite paranoid, since all the known shells bail\n# out after a failed `exec'.\nprintf \"%s\\n\" \"$0: could not re-execute with $CONFIG_SHELL\" >&2\nexit 255\n  fi\n  # We don't want this to propagate to other subprocesses.\n          { _as_can_reexec=; unset _as_can_reexec;}\nif test \"x$CONFIG_SHELL\" = x; then\n  as_bourne_compatible=\"as_nop=:\nif test \\${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1\nthen :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on \\${1+\\\"\\$@\\\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '\\${1+\\\"\\$@\\\"}'='\\\"\\$@\\\"'\n  setopt NO_GLOB_SUBST\nelse \\$as_nop\n  case \\`(set -o) 2>/dev/null\\` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac\nfi\n\"\n  as_required=\"as_fn_return () { (exit \\$1); }\nas_fn_success () { as_fn_return 0; }\nas_fn_failure () { as_fn_return 1; }\nas_fn_ret_success () { return 0; }\nas_fn_ret_failure () { return 1; }\n\nexitcode=0\nas_fn_success || { exitcode=1; echo as_fn_success failed.; }\nas_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }\nas_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }\nas_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }\nif ( set x; as_fn_ret_success y && test x = \\\"\\$1\\\" )\nthen :\n\nelse \\$as_nop\n  exitcode=1; echo positional parameters were not saved.\nfi\ntest x\\$exitcode = x0 || exit 1\nblah=\\$(echo \\$(echo blah))\ntest x\\\"\\$blah\\\" = xblah || exit 1\ntest -x / || exit 1\"\n  as_suggested=\"  as_lineno_1=\";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested\" as_lineno_1a=\\$LINENO\n  as_lineno_2=\";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested\" as_lineno_2a=\\$LINENO\n  eval 'test \\\"x\\$as_lineno_1'\\$as_run'\\\" != \\\"x\\$as_lineno_2'\\$as_run'\\\" &&\n  test \\\"x\\`expr \\$as_lineno_1'\\$as_run' + 1\\`\\\" = \\\"x\\$as_lineno_2'\\$as_run'\\\"' || exit 1\"\n  if (eval \"$as_required\") 2>/dev/null\nthen :\n  as_have_required=yes\nelse $as_nop\n  as_have_required=no\nfi\n  if test x$as_have_required = xyes && (eval \"$as_suggested\") 2>/dev/null\nthen :\n\nelse $as_nop\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nas_found=false\nfor as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n  as_found=:\n  case $as_dir in #(\n\t /*)\n\t   for as_base in sh bash ksh sh5; do\n\t     # Try only shells that exist, to save several forks.\n\t     as_shell=$as_dir$as_base\n\t     if { test -f \"$as_shell\" || test -f \"$as_shell.exe\"; } &&\n\t\t    as_run=a \"$as_shell\" -c \"$as_bourne_compatible\"\"$as_required\" 2>/dev/null\nthen :\n  CONFIG_SHELL=$as_shell as_have_required=yes\n\t\t   if as_run=a \"$as_shell\" -c \"$as_bourne_compatible\"\"$as_suggested\" 2>/dev/null\nthen :\n  break 2\nfi\nfi\n\t   done;;\n       esac\n  as_found=false\ndone\nIFS=$as_save_IFS\nif $as_found\nthen :\n\nelse $as_nop\n  if { test -f \"$SHELL\" || test -f \"$SHELL.exe\"; } &&\n\t      as_run=a \"$SHELL\" -c \"$as_bourne_compatible\"\"$as_required\" 2>/dev/null\nthen :\n  CONFIG_SHELL=$SHELL as_have_required=yes\nfi\nfi\n\n\n      if test \"x$CONFIG_SHELL\" != x\nthen :\n  export CONFIG_SHELL\n             # We cannot yet assume a decent shell, so we have to provide a\n# neutralization value for shells without unset; and this also\n# works around shells that cannot unset nonexistent variables.\n# Preserve -v and -x to the replacement shell.\nBASH_ENV=/dev/null\nENV=/dev/null\n(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV\ncase $- in # ((((\n  *v*x* | *x*v* ) as_opts=-vx ;;\n  *v* ) as_opts=-v ;;\n  *x* ) as_opts=-x ;;\n  * ) as_opts= ;;\nesac\nexec $CONFIG_SHELL $as_opts \"$as_myself\" ${1+\"$@\"}\n# Admittedly, this is quite paranoid, since all the known shells bail\n# out after a failed `exec'.\nprintf \"%s\\n\" \"$0: could not re-execute with $CONFIG_SHELL\" >&2\nexit 255\nfi\n\n    if test x$as_have_required = xno\nthen :\n  printf \"%s\\n\" \"$0: This script requires a shell more modern than all\"\n  printf \"%s\\n\" \"$0: the shells that I found on your system.\"\n  if test ${ZSH_VERSION+y} ; then\n    printf \"%s\\n\" \"$0: In particular, zsh $ZSH_VERSION has bugs and should\"\n    printf \"%s\\n\" \"$0: be upgraded to zsh 4.3.4 or later.\"\n  else\n    printf \"%s\\n\" \"$0: Please tell bug-autoconf@gnu.org about your system,\n$0: including any error possibly output before this\n$0: message. Then install a modern shell, or manually run\n$0: the script under such a shell if you do have one.\"\n  fi\n  exit 1\nfi\nfi\nfi\nSHELL=${CONFIG_SHELL-/bin/sh}\nexport SHELL\n# Unset more variables known to interfere with behavior of common tools.\nCLICOLOR_FORCE= GREP_OPTIONS=\nunset CLICOLOR_FORCE GREP_OPTIONS\n\n## --------------------- ##\n## M4sh Shell Functions. ##\n## --------------------- ##\n# as_fn_unset VAR\n# ---------------\n# Portably unset VAR.\nas_fn_unset ()\n{\n  { eval $1=; unset $1;}\n}\nas_unset=as_fn_unset\n\n\n# as_fn_set_status STATUS\n# -----------------------\n# Set $? to STATUS, without forking.\nas_fn_set_status ()\n{\n  return $1\n} # as_fn_set_status\n\n# as_fn_exit STATUS\n# -----------------\n# Exit the shell with STATUS, even in a \"trap 0\" or \"set -e\" context.\nas_fn_exit ()\n{\n  set +e\n  as_fn_set_status $1\n  exit $1\n} # as_fn_exit\n# as_fn_nop\n# ---------\n# Do nothing but, unlike \":\", preserve the value of $?.\nas_fn_nop ()\n{\n  return $?\n}\nas_nop=as_fn_nop\n\n# as_fn_mkdir_p\n# -------------\n# Create \"$as_dir\" as a directory, including parents if necessary.\nas_fn_mkdir_p ()\n{\n\n  case $as_dir in #(\n  -*) as_dir=./$as_dir;;\n  esac\n  test -d \"$as_dir\" || eval $as_mkdir_p || {\n    as_dirs=\n    while :; do\n      case $as_dir in #(\n      *\\'*) as_qdir=`printf \"%s\\n\" \"$as_dir\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; #'(\n      *) as_qdir=$as_dir;;\n      esac\n      as_dirs=\"'$as_qdir' $as_dirs\"\n      as_dir=`$as_dirname -- \"$as_dir\" ||\n$as_expr X\"$as_dir\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_dir\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf \"%s\\n\" X\"$as_dir\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n      test -d \"$as_dir\" && break\n    done\n    test -z \"$as_dirs\" || eval \"mkdir $as_dirs\"\n  } || test -d \"$as_dir\" || as_fn_error $? \"cannot create directory $as_dir\"\n\n\n} # as_fn_mkdir_p\n\n# as_fn_executable_p FILE\n# -----------------------\n# Test if FILE is an executable regular file.\nas_fn_executable_p ()\n{\n  test -f \"$1\" && test -x \"$1\"\n} # as_fn_executable_p\n# as_fn_append VAR VALUE\n# ----------------------\n# Append the text in VALUE to the end of the definition contained in VAR. Take\n# advantage of any shell optimizations that allow amortized linear growth over\n# repeated appends, instead of the typical quadratic growth present in naive\n# implementations.\nif (eval \"as_var=1; as_var+=2; test x\\$as_var = x12\") 2>/dev/null\nthen :\n  eval 'as_fn_append ()\n  {\n    eval $1+=\\$2\n  }'\nelse $as_nop\n  as_fn_append ()\n  {\n    eval $1=\\$$1\\$2\n  }\nfi # as_fn_append\n\n# as_fn_arith ARG...\n# ------------------\n# Perform arithmetic evaluation on the ARGs, and store the result in the\n# global $as_val. Take advantage of shells that can avoid forks. The arguments\n# must be portable across $(()) and expr.\nif (eval \"test \\$(( 1 + 1 )) = 2\") 2>/dev/null\nthen :\n  eval 'as_fn_arith ()\n  {\n    as_val=$(( $* ))\n  }'\nelse $as_nop\n  as_fn_arith ()\n  {\n    as_val=`expr \"$@\" || test $? -eq 1`\n  }\nfi # as_fn_arith\n\n# as_fn_nop\n# ---------\n# Do nothing but, unlike \":\", preserve the value of $?.\nas_fn_nop ()\n{\n  return $?\n}\nas_nop=as_fn_nop\n\n# as_fn_error STATUS ERROR [LINENO LOG_FD]\n# ----------------------------------------\n# Output \"`basename $0`: error: ERROR\" to stderr. If LINENO and LOG_FD are\n# provided, also output the error to LOG_FD, referencing LINENO. Then exit the\n# script with STATUS, using 1 if that was 0.\nas_fn_error ()\n{\n  as_status=$1; test $as_status -eq 0 && as_status=1\n  if test \"$4\"; then\n    as_lineno=${as_lineno-\"$3\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n    printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: error: $2\" >&$4\n  fi\n  printf \"%s\\n\" \"$as_me: error: $2\" >&2\n  as_fn_exit $as_status\n} # as_fn_error\n\nif expr a : '\\(a\\)' >/dev/null 2>&1 &&\n   test \"X`expr 00001 : '.*\\(...\\)'`\" = X001; then\n  as_expr=expr\nelse\n  as_expr=false\nfi\n\nif (basename -- /) >/dev/null 2>&1 && test \"X`basename -- / 2>&1`\" = \"X/\"; then\n  as_basename=basename\nelse\n  as_basename=false\nfi\n\nif (as_dir=`dirname -- /` && test \"X$as_dir\" = X/) >/dev/null 2>&1; then\n  as_dirname=dirname\nelse\n  as_dirname=false\nfi\n\nas_me=`$as_basename -- \"$0\" ||\n$as_expr X/\"$0\" : '.*/\\([^/][^/]*\\)/*$' \\| \\\n\t X\"$0\" : 'X\\(//\\)$' \\| \\\n\t X\"$0\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf \"%s\\n\" X/\"$0\" |\n    sed '/^.*\\/\\([^/][^/]*\\)\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n\n# Avoid depending upon Character Ranges.\nas_cr_letters='abcdefghijklmnopqrstuvwxyz'\nas_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'\nas_cr_Letters=$as_cr_letters$as_cr_LETTERS\nas_cr_digits='0123456789'\nas_cr_alnum=$as_cr_Letters$as_cr_digits\n\n\n  as_lineno_1=$LINENO as_lineno_1a=$LINENO\n  as_lineno_2=$LINENO as_lineno_2a=$LINENO\n  eval 'test \"x$as_lineno_1'$as_run'\" != \"x$as_lineno_2'$as_run'\" &&\n  test \"x`expr $as_lineno_1'$as_run' + 1`\" = \"x$as_lineno_2'$as_run'\"' || {\n  # Blame Lee E. McMahon (1931-1989) for sed's syntax.  :-)\n  sed -n '\n    p\n    /[$]LINENO/=\n  ' <$as_myself |\n    sed '\n      s/[$]LINENO.*/&-/\n      t lineno\n      b\n      :lineno\n      N\n      :loop\n      s/[$]LINENO\\([^'$as_cr_alnum'_].*\\n\\)\\(.*\\)/\\2\\1\\2/\n      t loop\n      s/-\\n.*//\n    ' >$as_me.lineno &&\n  chmod +x \"$as_me.lineno\" ||\n    { printf \"%s\\n\" \"$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell\" >&2; as_fn_exit 1; }\n\n  # If we had to re-execute with $CONFIG_SHELL, we're ensured to have\n  # already done that, so ensure we don't try to do so again and fall\n  # in an infinite loop.  This has already happened in practice.\n  _as_can_reexec=no; export _as_can_reexec\n  # Don't try to exec as it changes $[0], causing all sort of problems\n  # (the dirname of $[0] is not the place where we might find the\n  # original and so on.  Autoconf is especially sensitive to this).\n  . \"./$as_me.lineno\"\n  # Exit status is that of the last command.\n  exit\n}\n\n\n# Determine whether it's possible to make 'echo' print without a newline.\n# These variables are no longer used directly by Autoconf, but are AC_SUBSTed\n# for compatibility with existing Makefiles.\nECHO_C= ECHO_N= ECHO_T=\ncase `echo -n x` in #(((((\n-n*)\n  case `echo 'xy\\c'` in\n  *c*) ECHO_T='\t';;\t# ECHO_T is single tab character.\n  xy)  ECHO_C='\\c';;\n  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null\n       ECHO_T='\t';;\n  esac;;\n*)\n  ECHO_N='-n';;\nesac\n\n# For backward compatibility with old third-party macros, we provide\n# the shell variables $as_echo and $as_echo_n.  New code should use\n# AS_ECHO([\"message\"]) and AS_ECHO_N([\"message\"]), respectively.\nas_echo='printf %s\\n'\nas_echo_n='printf %s'\n\n\nrm -f conf$$ conf$$.exe conf$$.file\nif test -d conf$$.dir; then\n  rm -f conf$$.dir/conf$$.file\nelse\n  rm -f conf$$.dir\n  mkdir conf$$.dir 2>/dev/null\nfi\nif (echo >conf$$.file) 2>/dev/null; then\n  if ln -s conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s='ln -s'\n    # ... but there are two gotchas:\n    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.\n    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.\n    # In both cases, we have to default to `cp -pR'.\n    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||\n      as_ln_s='cp -pR'\n  elif ln conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s=ln\n  else\n    as_ln_s='cp -pR'\n  fi\nelse\n  as_ln_s='cp -pR'\nfi\nrm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file\nrmdir conf$$.dir 2>/dev/null\n\nif mkdir -p . 2>/dev/null; then\n  as_mkdir_p='mkdir -p \"$as_dir\"'\nelse\n  test -d ./-p && rmdir ./-p\n  as_mkdir_p=false\nfi\n\nas_test_x='test -x'\nas_executable_p=as_fn_executable_p\n\n# Sed expression to map a string onto a valid CPP name.\nas_tr_cpp=\"eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'\"\n\n# Sed expression to map a string onto a valid variable name.\nas_tr_sh=\"eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'\"\n\n\ntest -n \"$DJDIR\" || exec 7<&0 </dev/null\nexec 6>&1\n\n# Name of the host.\n# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,\n# so uname gets run too.\nac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`\n\n#\n# Initializations.\n#\nac_default_prefix=/usr/local\nac_clean_files=\nac_config_libobj_dir=.\nLIBOBJS=\ncross_compiling=no\nsubdirs=\nMFLAGS=\nMAKEFLAGS=\n\n# Identity of this package.\nPACKAGE_NAME=''\nPACKAGE_TARNAME=''\nPACKAGE_VERSION=''\nPACKAGE_STRING=''\nPACKAGE_BUGREPORT=''\nPACKAGE_URL=''\n\nac_unique_file=\"src/wkb.cpp\"\n# Factoring default headers for most tests.\nac_includes_default=\"\\\n#include <stddef.h>\n#ifdef HAVE_STDIO_H\n# include <stdio.h>\n#endif\n#ifdef HAVE_STDLIB_H\n# include <stdlib.h>\n#endif\n#ifdef HAVE_STRING_H\n# include <string.h>\n#endif\n#ifdef HAVE_INTTYPES_H\n# include <inttypes.h>\n#endif\n#ifdef HAVE_STDINT_H\n# include <stdint.h>\n#endif\n#ifdef HAVE_STRINGS_H\n# include <strings.h>\n#endif\n#ifdef HAVE_SYS_TYPES_H\n# include <sys/types.h>\n#endif\n#ifdef HAVE_SYS_STAT_H\n# include <sys/stat.h>\n#endif\n#ifdef HAVE_UNISTD_H\n# include <unistd.h>\n#endif\"\n\nac_header_c_list=\nac_subst_vars='LTLIBOBJS\nLIBOBJS\nGEOS_CONFIG\nPROJ_LIBS\nPROJ_CPPFLAGS\nSQLITE3_LIBS\nOBJEXT\nEXEEXT\nac_ct_CC\nCPPFLAGS\nLDFLAGS\nCFLAGS\nCC\nPKG_LIBS\nPKG_CPPFLAGS\nGDAL_CONFIG\ntarget_alias\nhost_alias\nbuild_alias\nLIBS\nECHO_T\nECHO_N\nECHO_C\nDEFS\nmandir\nlocaledir\nlibdir\npsdir\npdfdir\ndvidir\nhtmldir\ninfodir\ndocdir\noldincludedir\nincludedir\nrunstatedir\nlocalstatedir\nsharedstatedir\nsysconfdir\ndatadir\ndatarootdir\nlibexecdir\nsbindir\nbindir\nprogram_transform_name\nprefix\nexec_prefix\nPACKAGE_URL\nPACKAGE_BUGREPORT\nPACKAGE_STRING\nPACKAGE_VERSION\nPACKAGE_TARNAME\nPACKAGE_NAME\nPATH_SEPARATOR\nSHELL'\nac_subst_files=''\nac_user_opts='\nenable_option_checking\nwith_gdal_config\nwith_data_copy\nwith_proj_data\nwith_sqlite3_lib\nwith_proj_include\nwith_proj_api\nwith_proj_lib\nwith_proj_share\nwith_geos_config\n'\n      ac_precious_vars='build_alias\nhost_alias\ntarget_alias\nCC\nCFLAGS\nLDFLAGS\nLIBS\nCPPFLAGS'\n\n\n# Initialize some variables set by options.\nac_init_help=\nac_init_version=false\nac_unrecognized_opts=\nac_unrecognized_sep=\n# The variables have the same names as the options, with\n# dashes changed to underlines.\ncache_file=/dev/null\nexec_prefix=NONE\nno_create=\nno_recursion=\nprefix=NONE\nprogram_prefix=NONE\nprogram_suffix=NONE\nprogram_transform_name=s,x,x,\nsilent=\nsite=\nsrcdir=\nverbose=\nx_includes=NONE\nx_libraries=NONE\n\n# Installation directory options.\n# These are left unexpanded so users can \"make install exec_prefix=/foo\"\n# and all the variables that are supposed to be based on exec_prefix\n# by default will actually change.\n# Use braces instead of parens because sh, perl, etc. also accept them.\n# (The list follows the same order as the GNU Coding Standards.)\nbindir='${exec_prefix}/bin'\nsbindir='${exec_prefix}/sbin'\nlibexecdir='${exec_prefix}/libexec'\ndatarootdir='${prefix}/share'\ndatadir='${datarootdir}'\nsysconfdir='${prefix}/etc'\nsharedstatedir='${prefix}/com'\nlocalstatedir='${prefix}/var'\nrunstatedir='${localstatedir}/run'\nincludedir='${prefix}/include'\noldincludedir='/usr/include'\ndocdir='${datarootdir}/doc/${PACKAGE}'\ninfodir='${datarootdir}/info'\nhtmldir='${docdir}'\ndvidir='${docdir}'\npdfdir='${docdir}'\npsdir='${docdir}'\nlibdir='${exec_prefix}/lib'\nlocaledir='${datarootdir}/locale'\nmandir='${datarootdir}/man'\n\nac_prev=\nac_dashdash=\nfor ac_option\ndo\n  # If the previous option needs an argument, assign it.\n  if test -n \"$ac_prev\"; then\n    eval $ac_prev=\\$ac_option\n    ac_prev=\n    continue\n  fi\n\n  case $ac_option in\n  *=?*) ac_optarg=`expr \"X$ac_option\" : '[^=]*=\\(.*\\)'` ;;\n  *=)   ac_optarg= ;;\n  *)    ac_optarg=yes ;;\n  esac\n\n  case $ac_dashdash$ac_option in\n  --)\n    ac_dashdash=yes ;;\n\n  -bindir | --bindir | --bindi | --bind | --bin | --bi)\n    ac_prev=bindir ;;\n  -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)\n    bindir=$ac_optarg ;;\n\n  -build | --build | --buil | --bui | --bu)\n    ac_prev=build_alias ;;\n  -build=* | --build=* | --buil=* | --bui=* | --bu=*)\n    build_alias=$ac_optarg ;;\n\n  -cache-file | --cache-file | --cache-fil | --cache-fi \\\n  | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)\n    ac_prev=cache_file ;;\n  -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \\\n  | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)\n    cache_file=$ac_optarg ;;\n\n  --config-cache | -C)\n    cache_file=config.cache ;;\n\n  -datadir | --datadir | --datadi | --datad)\n    ac_prev=datadir ;;\n  -datadir=* | --datadir=* | --datadi=* | --datad=*)\n    datadir=$ac_optarg ;;\n\n  -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \\\n  | --dataroo | --dataro | --datar)\n    ac_prev=datarootdir ;;\n  -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \\\n  | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)\n    datarootdir=$ac_optarg ;;\n\n  -disable-* | --disable-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*disable-\\(.*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid feature name: \\`$ac_useropt'\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`printf \"%s\\n\" \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"enable_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval enable_$ac_useropt=no ;;\n\n  -docdir | --docdir | --docdi | --doc | --do)\n    ac_prev=docdir ;;\n  -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)\n    docdir=$ac_optarg ;;\n\n  -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)\n    ac_prev=dvidir ;;\n  -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)\n    dvidir=$ac_optarg ;;\n\n  -enable-* | --enable-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*enable-\\([^=]*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid feature name: \\`$ac_useropt'\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`printf \"%s\\n\" \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"enable_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval enable_$ac_useropt=\\$ac_optarg ;;\n\n  -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \\\n  | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \\\n  | --exec | --exe | --ex)\n    ac_prev=exec_prefix ;;\n  -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \\\n  | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \\\n  | --exec=* | --exe=* | --ex=*)\n    exec_prefix=$ac_optarg ;;\n\n  -gas | --gas | --ga | --g)\n    # Obsolete; use --with-gas.\n    with_gas=yes ;;\n\n  -help | --help | --hel | --he | -h)\n    ac_init_help=long ;;\n  -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)\n    ac_init_help=recursive ;;\n  -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)\n    ac_init_help=short ;;\n\n  -host | --host | --hos | --ho)\n    ac_prev=host_alias ;;\n  -host=* | --host=* | --hos=* | --ho=*)\n    host_alias=$ac_optarg ;;\n\n  -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)\n    ac_prev=htmldir ;;\n  -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \\\n  | --ht=*)\n    htmldir=$ac_optarg ;;\n\n  -includedir | --includedir | --includedi | --included | --include \\\n  | --includ | --inclu | --incl | --inc)\n    ac_prev=includedir ;;\n  -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \\\n  | --includ=* | --inclu=* | --incl=* | --inc=*)\n    includedir=$ac_optarg ;;\n\n  -infodir | --infodir | --infodi | --infod | --info | --inf)\n    ac_prev=infodir ;;\n  -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)\n    infodir=$ac_optarg ;;\n\n  -libdir | --libdir | --libdi | --libd)\n    ac_prev=libdir ;;\n  -libdir=* | --libdir=* | --libdi=* | --libd=*)\n    libdir=$ac_optarg ;;\n\n  -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \\\n  | --libexe | --libex | --libe)\n    ac_prev=libexecdir ;;\n  -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \\\n  | --libexe=* | --libex=* | --libe=*)\n    libexecdir=$ac_optarg ;;\n\n  -localedir | --localedir | --localedi | --localed | --locale)\n    ac_prev=localedir ;;\n  -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)\n    localedir=$ac_optarg ;;\n\n  -localstatedir | --localstatedir | --localstatedi | --localstated \\\n  | --localstate | --localstat | --localsta | --localst | --locals)\n    ac_prev=localstatedir ;;\n  -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \\\n  | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)\n    localstatedir=$ac_optarg ;;\n\n  -mandir | --mandir | --mandi | --mand | --man | --ma | --m)\n    ac_prev=mandir ;;\n  -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)\n    mandir=$ac_optarg ;;\n\n  -nfp | --nfp | --nf)\n    # Obsolete; use --without-fp.\n    with_fp=no ;;\n\n  -no-create | --no-create | --no-creat | --no-crea | --no-cre \\\n  | --no-cr | --no-c | -n)\n    no_create=yes ;;\n\n  -no-recursion | --no-recursion | --no-recursio | --no-recursi \\\n  | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)\n    no_recursion=yes ;;\n\n  -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \\\n  | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \\\n  | --oldin | --oldi | --old | --ol | --o)\n    ac_prev=oldincludedir ;;\n  -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \\\n  | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \\\n  | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)\n    oldincludedir=$ac_optarg ;;\n\n  -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)\n    ac_prev=prefix ;;\n  -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)\n    prefix=$ac_optarg ;;\n\n  -program-prefix | --program-prefix | --program-prefi | --program-pref \\\n  | --program-pre | --program-pr | --program-p)\n    ac_prev=program_prefix ;;\n  -program-prefix=* | --program-prefix=* | --program-prefi=* \\\n  | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)\n    program_prefix=$ac_optarg ;;\n\n  -program-suffix | --program-suffix | --program-suffi | --program-suff \\\n  | --program-suf | --program-su | --program-s)\n    ac_prev=program_suffix ;;\n  -program-suffix=* | --program-suffix=* | --program-suffi=* \\\n  | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)\n    program_suffix=$ac_optarg ;;\n\n  -program-transform-name | --program-transform-name \\\n  | --program-transform-nam | --program-transform-na \\\n  | --program-transform-n | --program-transform- \\\n  | --program-transform | --program-transfor \\\n  | --program-transfo | --program-transf \\\n  | --program-trans | --program-tran \\\n  | --progr-tra | --program-tr | --program-t)\n    ac_prev=program_transform_name ;;\n  -program-transform-name=* | --program-transform-name=* \\\n  | --program-transform-nam=* | --program-transform-na=* \\\n  | --program-transform-n=* | --program-transform-=* \\\n  | --program-transform=* | --program-transfor=* \\\n  | --program-transfo=* | --program-transf=* \\\n  | --program-trans=* | --program-tran=* \\\n  | --progr-tra=* | --program-tr=* | --program-t=*)\n    program_transform_name=$ac_optarg ;;\n\n  -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)\n    ac_prev=pdfdir ;;\n  -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)\n    pdfdir=$ac_optarg ;;\n\n  -psdir | --psdir | --psdi | --psd | --ps)\n    ac_prev=psdir ;;\n  -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)\n    psdir=$ac_optarg ;;\n\n  -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n  | -silent | --silent | --silen | --sile | --sil)\n    silent=yes ;;\n\n  -runstatedir | --runstatedir | --runstatedi | --runstated \\\n  | --runstate | --runstat | --runsta | --runst | --runs \\\n  | --run | --ru | --r)\n    ac_prev=runstatedir ;;\n  -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \\\n  | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \\\n  | --run=* | --ru=* | --r=*)\n    runstatedir=$ac_optarg ;;\n\n  -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)\n    ac_prev=sbindir ;;\n  -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \\\n  | --sbi=* | --sb=*)\n    sbindir=$ac_optarg ;;\n\n  -sharedstatedir | --sharedstatedir | --sharedstatedi \\\n  | --sharedstated | --sharedstate | --sharedstat | --sharedsta \\\n  | --sharedst | --shareds | --shared | --share | --shar \\\n  | --sha | --sh)\n    ac_prev=sharedstatedir ;;\n  -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \\\n  | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \\\n  | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \\\n  | --sha=* | --sh=*)\n    sharedstatedir=$ac_optarg ;;\n\n  -site | --site | --sit)\n    ac_prev=site ;;\n  -site=* | --site=* | --sit=*)\n    site=$ac_optarg ;;\n\n  -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)\n    ac_prev=srcdir ;;\n  -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)\n    srcdir=$ac_optarg ;;\n\n  -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \\\n  | --syscon | --sysco | --sysc | --sys | --sy)\n    ac_prev=sysconfdir ;;\n  -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \\\n  | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)\n    sysconfdir=$ac_optarg ;;\n\n  -target | --target | --targe | --targ | --tar | --ta | --t)\n    ac_prev=target_alias ;;\n  -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)\n    target_alias=$ac_optarg ;;\n\n  -v | -verbose | --verbose | --verbos | --verbo | --verb)\n    verbose=yes ;;\n\n  -version | --version | --versio | --versi | --vers | -V)\n    ac_init_version=: ;;\n\n  -with-* | --with-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*with-\\([^=]*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid package name: \\`$ac_useropt'\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`printf \"%s\\n\" \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"with_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval with_$ac_useropt=\\$ac_optarg ;;\n\n  -without-* | --without-*)\n    ac_useropt=`expr \"x$ac_option\" : 'x-*without-\\(.*\\)'`\n    # Reject names that are not valid shell variable names.\n    expr \"x$ac_useropt\" : \".*[^-+._$as_cr_alnum]\" >/dev/null &&\n      as_fn_error $? \"invalid package name: \\`$ac_useropt'\"\n    ac_useropt_orig=$ac_useropt\n    ac_useropt=`printf \"%s\\n\" \"$ac_useropt\" | sed 's/[-+.]/_/g'`\n    case $ac_user_opts in\n      *\"\n\"with_$ac_useropt\"\n\"*) ;;\n      *) ac_unrecognized_opts=\"$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig\"\n\t ac_unrecognized_sep=', ';;\n    esac\n    eval with_$ac_useropt=no ;;\n\n  --x)\n    # Obsolete; use --with-x.\n    with_x=yes ;;\n\n  -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \\\n  | --x-incl | --x-inc | --x-in | --x-i)\n    ac_prev=x_includes ;;\n  -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \\\n  | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)\n    x_includes=$ac_optarg ;;\n\n  -x-libraries | --x-libraries | --x-librarie | --x-librari \\\n  | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)\n    ac_prev=x_libraries ;;\n  -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \\\n  | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)\n    x_libraries=$ac_optarg ;;\n\n  -*) as_fn_error $? \"unrecognized option: \\`$ac_option'\nTry \\`$0 --help' for more information\"\n    ;;\n\n  *=*)\n    ac_envvar=`expr \"x$ac_option\" : 'x\\([^=]*\\)='`\n    # Reject names that are not valid shell variable names.\n    case $ac_envvar in #(\n      '' | [0-9]* | *[!_$as_cr_alnum]* )\n      as_fn_error $? \"invalid variable name: \\`$ac_envvar'\" ;;\n    esac\n    eval $ac_envvar=\\$ac_optarg\n    export $ac_envvar ;;\n\n  *)\n    # FIXME: should be removed in autoconf 3.0.\n    printf \"%s\\n\" \"$as_me: WARNING: you should use --build, --host, --target\" >&2\n    expr \"x$ac_option\" : \".*[^-._$as_cr_alnum]\" >/dev/null &&\n      printf \"%s\\n\" \"$as_me: WARNING: invalid host type: $ac_option\" >&2\n    : \"${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}\"\n    ;;\n\n  esac\ndone\n\nif test -n \"$ac_prev\"; then\n  ac_option=--`echo $ac_prev | sed 's/_/-/g'`\n  as_fn_error $? \"missing argument to $ac_option\"\nfi\n\nif test -n \"$ac_unrecognized_opts\"; then\n  case $enable_option_checking in\n    no) ;;\n    fatal) as_fn_error $? \"unrecognized options: $ac_unrecognized_opts\" ;;\n    *)     printf \"%s\\n\" \"$as_me: WARNING: unrecognized options: $ac_unrecognized_opts\" >&2 ;;\n  esac\nfi\n\n# Check all directory arguments for consistency.\nfor ac_var in\texec_prefix prefix bindir sbindir libexecdir datarootdir \\\n\t\tdatadir sysconfdir sharedstatedir localstatedir includedir \\\n\t\toldincludedir docdir infodir htmldir dvidir pdfdir psdir \\\n\t\tlibdir localedir mandir runstatedir\ndo\n  eval ac_val=\\$$ac_var\n  # Remove trailing slashes.\n  case $ac_val in\n    */ )\n      ac_val=`expr \"X$ac_val\" : 'X\\(.*[^/]\\)' \\| \"X$ac_val\" : 'X\\(.*\\)'`\n      eval $ac_var=\\$ac_val;;\n  esac\n  # Be sure to have absolute directory names.\n  case $ac_val in\n    [\\\\/$]* | ?:[\\\\/]* )  continue;;\n    NONE | '' ) case $ac_var in *prefix ) continue;; esac;;\n  esac\n  as_fn_error $? \"expected an absolute directory name for --$ac_var: $ac_val\"\ndone\n\n# There might be people who depend on the old broken behavior: `$host'\n# used to hold the argument of --host etc.\n# FIXME: To remove some day.\nbuild=$build_alias\nhost=$host_alias\ntarget=$target_alias\n\n# FIXME: To remove some day.\nif test \"x$host_alias\" != x; then\n  if test \"x$build_alias\" = x; then\n    cross_compiling=maybe\n  elif test \"x$build_alias\" != \"x$host_alias\"; then\n    cross_compiling=yes\n  fi\nfi\n\nac_tool_prefix=\ntest -n \"$host_alias\" && ac_tool_prefix=$host_alias-\n\ntest \"$silent\" = yes && exec 6>/dev/null\n\n\nac_pwd=`pwd` && test -n \"$ac_pwd\" &&\nac_ls_di=`ls -di .` &&\nac_pwd_ls_di=`cd \"$ac_pwd\" && ls -di .` ||\n  as_fn_error $? \"working directory cannot be determined\"\ntest \"X$ac_ls_di\" = \"X$ac_pwd_ls_di\" ||\n  as_fn_error $? \"pwd does not report name of working directory\"\n\n\n# Find the source files, if location was not specified.\nif test -z \"$srcdir\"; then\n  ac_srcdir_defaulted=yes\n  # Try the directory containing this script, then the parent directory.\n  ac_confdir=`$as_dirname -- \"$as_myself\" ||\n$as_expr X\"$as_myself\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_myself\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_myself\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_myself\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf \"%s\\n\" X\"$as_myself\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n  srcdir=$ac_confdir\n  if test ! -r \"$srcdir/$ac_unique_file\"; then\n    srcdir=..\n  fi\nelse\n  ac_srcdir_defaulted=no\nfi\nif test ! -r \"$srcdir/$ac_unique_file\"; then\n  test \"$ac_srcdir_defaulted\" = yes && srcdir=\"$ac_confdir or ..\"\n  as_fn_error $? \"cannot find sources ($ac_unique_file) in $srcdir\"\nfi\nac_msg=\"sources are in $srcdir, but \\`cd $srcdir' does not work\"\nac_abs_confdir=`(\n\tcd \"$srcdir\" && test -r \"./$ac_unique_file\" || as_fn_error $? \"$ac_msg\"\n\tpwd)`\n# When building in place, set srcdir=.\nif test \"$ac_abs_confdir\" = \"$ac_pwd\"; then\n  srcdir=.\nfi\n# Remove unnecessary trailing slashes from srcdir.\n# Double slashes in file names in object file debugging info\n# mess up M-x gdb in Emacs.\ncase $srcdir in\n*/) srcdir=`expr \"X$srcdir\" : 'X\\(.*[^/]\\)' \\| \"X$srcdir\" : 'X\\(.*\\)'`;;\nesac\nfor ac_var in $ac_precious_vars; do\n  eval ac_env_${ac_var}_set=\\${${ac_var}+set}\n  eval ac_env_${ac_var}_value=\\$${ac_var}\n  eval ac_cv_env_${ac_var}_set=\\${${ac_var}+set}\n  eval ac_cv_env_${ac_var}_value=\\$${ac_var}\ndone\n\n#\n# Report the --help message.\n#\nif test \"$ac_init_help\" = \"long\"; then\n  # Omit some internal or obsolete options to make the list less imposing.\n  # This message is too long to be a string in the A/UX 3.1 sh.\n  cat <<_ACEOF\n\\`configure' configures this package to adapt to many kinds of systems.\n\nUsage: $0 [OPTION]... [VAR=VALUE]...\n\nTo assign environment variables (e.g., CC, CFLAGS...), specify them as\nVAR=VALUE.  See below for descriptions of some of the useful variables.\n\nDefaults for the options are specified in brackets.\n\nConfiguration:\n  -h, --help              display this help and exit\n      --help=short        display options specific to this package\n      --help=recursive    display the short help of all the included packages\n  -V, --version           display version information and exit\n  -q, --quiet, --silent   do not print \\`checking ...' messages\n      --cache-file=FILE   cache test results in FILE [disabled]\n  -C, --config-cache      alias for \\`--cache-file=config.cache'\n  -n, --no-create         do not create output files\n      --srcdir=DIR        find the sources in DIR [configure dir or \\`..']\n\nInstallation directories:\n  --prefix=PREFIX         install architecture-independent files in PREFIX\n                          [$ac_default_prefix]\n  --exec-prefix=EPREFIX   install architecture-dependent files in EPREFIX\n                          [PREFIX]\n\nBy default, \\`make install' will install all the files in\n\\`$ac_default_prefix/bin', \\`$ac_default_prefix/lib' etc.  You can specify\nan installation prefix other than \\`$ac_default_prefix' using \\`--prefix',\nfor instance \\`--prefix=\\$HOME'.\n\nFor better control, use the options below.\n\nFine tuning of the installation directories:\n  --bindir=DIR            user executables [EPREFIX/bin]\n  --sbindir=DIR           system admin executables [EPREFIX/sbin]\n  --libexecdir=DIR        program executables [EPREFIX/libexec]\n  --sysconfdir=DIR        read-only single-machine data [PREFIX/etc]\n  --sharedstatedir=DIR    modifiable architecture-independent data [PREFIX/com]\n  --localstatedir=DIR     modifiable single-machine data [PREFIX/var]\n  --runstatedir=DIR       modifiable per-process data [LOCALSTATEDIR/run]\n  --libdir=DIR            object code libraries [EPREFIX/lib]\n  --includedir=DIR        C header files [PREFIX/include]\n  --oldincludedir=DIR     C header files for non-gcc [/usr/include]\n  --datarootdir=DIR       read-only arch.-independent data root [PREFIX/share]\n  --datadir=DIR           read-only architecture-independent data [DATAROOTDIR]\n  --infodir=DIR           info documentation [DATAROOTDIR/info]\n  --localedir=DIR         locale-dependent data [DATAROOTDIR/locale]\n  --mandir=DIR            man documentation [DATAROOTDIR/man]\n  --docdir=DIR            documentation root [DATAROOTDIR/doc/PACKAGE]\n  --htmldir=DIR           html documentation [DOCDIR]\n  --dvidir=DIR            dvi documentation [DOCDIR]\n  --pdfdir=DIR            pdf documentation [DOCDIR]\n  --psdir=DIR             ps documentation [DOCDIR]\n_ACEOF\n\n  cat <<\\_ACEOF\n_ACEOF\nfi\n\nif test -n \"$ac_init_help\"; then\n\n  cat <<\\_ACEOF\n\nOptional Packages:\n  --with-PACKAGE[=ARG]    use PACKAGE [ARG=yes]\n  --without-PACKAGE       do not use PACKAGE (same as --with-PACKAGE=no)\n  --with-gdal-config=GDAL_CONFIG\n                          the location of gdal-config\n  --with-data-copy=yes/no local copy of data directories in package, default\n                          no\n  --with-proj-data=DIR    location of PROJ data directory\n  --with-sqlite3-lib=LIB_PATH\n                          the location of sqlite3 libraries\n  --with-proj-include=DIR location of proj header files\n  --with-proj-api=yes/no  use the deprecated proj_api.h even when PROJ 6 is\n                          available; default no\n  --with-proj-lib=LIB_PATH\n                          the location of proj libraries\n  --with-proj-share=SHARE_PATH\n                          the location of proj metadata files\n  --with-geos-config=GEOS_CONFIG\n                          the location of geos-config\n\nSome influential environment variables:\n  CC          C compiler command\n  CFLAGS      C compiler flags\n  LDFLAGS     linker flags, e.g. -L<lib dir> if you have libraries in a\n              nonstandard directory <lib dir>\n  LIBS        libraries to pass to the linker, e.g. -l<library>\n  CPPFLAGS    (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if\n              you have headers in a nonstandard directory <include dir>\n\nUse these variables to override the choices made by `configure' or to help\nit to find libraries and programs with nonstandard names/locations.\n\nReport bugs to the package provider.\n_ACEOF\nac_status=$?\nfi\n\nif test \"$ac_init_help\" = \"recursive\"; then\n  # If there are subdirs, report their specific --help.\n  for ac_dir in : $ac_subdirs_all; do test \"x$ac_dir\" = x: && continue\n    test -d \"$ac_dir\" ||\n      { cd \"$srcdir\" && ac_pwd=`pwd` && srcdir=. && test -d \"$ac_dir\"; } ||\n      continue\n    ac_builddir=.\n\ncase \"$ac_dir\" in\n.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;\n*)\n  ac_dir_suffix=/`printf \"%s\\n\" \"$ac_dir\" | sed 's|^\\.[\\\\/]||'`\n  # A \"..\" for each directory in $ac_dir_suffix.\n  ac_top_builddir_sub=`printf \"%s\\n\" \"$ac_dir_suffix\" | sed 's|/[^\\\\/]*|/..|g;s|/||'`\n  case $ac_top_builddir_sub in\n  \"\") ac_top_builddir_sub=. ac_top_build_prefix= ;;\n  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;\n  esac ;;\nesac\nac_abs_top_builddir=$ac_pwd\nac_abs_builddir=$ac_pwd$ac_dir_suffix\n# for backward compatibility:\nac_top_builddir=$ac_top_build_prefix\n\ncase $srcdir in\n  .)  # We are building in place.\n    ac_srcdir=.\n    ac_top_srcdir=$ac_top_builddir_sub\n    ac_abs_top_srcdir=$ac_pwd ;;\n  [\\\\/]* | ?:[\\\\/]* )  # Absolute name.\n    ac_srcdir=$srcdir$ac_dir_suffix;\n    ac_top_srcdir=$srcdir\n    ac_abs_top_srcdir=$srcdir ;;\n  *) # Relative name.\n    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix\n    ac_top_srcdir=$ac_top_build_prefix$srcdir\n    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;\nesac\nac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix\n\n    cd \"$ac_dir\" || { ac_status=$?; continue; }\n    # Check for configure.gnu first; this name is used for a wrapper for\n    # Metaconfig's \"Configure\" on case-insensitive file systems.\n    if test -f \"$ac_srcdir/configure.gnu\"; then\n      echo &&\n      $SHELL \"$ac_srcdir/configure.gnu\" --help=recursive\n    elif test -f \"$ac_srcdir/configure\"; then\n      echo &&\n      $SHELL \"$ac_srcdir/configure\" --help=recursive\n    else\n      printf \"%s\\n\" \"$as_me: WARNING: no configuration information is in $ac_dir\" >&2\n    fi || ac_status=$?\n    cd \"$ac_pwd\" || { ac_status=$?; break; }\n  done\nfi\n\ntest -n \"$ac_init_help\" && exit $ac_status\nif $ac_init_version; then\n  cat <<\\_ACEOF\nconfigure\ngenerated by GNU Autoconf 2.71\n\nCopyright (C) 2021 Free Software Foundation, Inc.\nThis configure script is free software; the Free Software Foundation\ngives unlimited permission to copy, distribute and modify it.\n_ACEOF\n  exit\nfi\n\n## ------------------------ ##\n## Autoconf initialization. ##\n## ------------------------ ##\n\n# ac_fn_c_try_compile LINENO\n# --------------------------\n# Try to compile conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_compile ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  rm -f conftest.$ac_objext conftest.beam\n  if { { ac_try=\"$ac_compile\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf \"%s\\n\" \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compile\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && {\n\t test -z \"$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       } && test -s conftest.$ac_objext\nthen :\n  ac_retval=0\nelse $as_nop\n  printf \"%s\\n\" \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n\tac_retval=1\nfi\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_compile\n\n# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES\n# -------------------------------------------------------\n# Tests whether HEADER exists and can be compiled using the include files in\n# INCLUDES, setting the cache variable VAR accordingly.\nac_fn_c_check_header_compile ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for $2\" >&5\nprintf %s \"checking for $2... \" >&6; }\nif eval test \\${$3+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$4\n#include <$2>\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  eval \"$3=yes\"\nelse $as_nop\n  eval \"$3=no\"\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\nfi\neval ac_res=\\$$3\n\t       { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $ac_res\" >&5\nprintf \"%s\\n\" \"$ac_res\" >&6; }\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n\n} # ac_fn_c_check_header_compile\n\n# ac_fn_c_try_link LINENO\n# -----------------------\n# Try to link conftest.$ac_ext, and return whether this succeeded.\nac_fn_c_try_link ()\n{\n  as_lineno=${as_lineno-\"$1\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n  rm -f conftest.$ac_objext conftest.beam conftest$ac_exeext\n  if { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf \"%s\\n\" \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    grep -v '^ *+' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n    mv -f conftest.er1 conftest.err\n  fi\n  printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; } && {\n\t test -z \"$ac_c_werror_flag\" ||\n\t test ! -s conftest.err\n       } && test -s conftest$ac_exeext && {\n\t test \"$cross_compiling\" = yes ||\n\t test -x conftest$ac_exeext\n       }\nthen :\n  ac_retval=0\nelse $as_nop\n  printf \"%s\\n\" \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n\tac_retval=1\nfi\n  # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information\n  # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would\n  # interfere with the next link command; also delete a directory that is\n  # left behind by Apple's compiler.  We do this before executing the actions.\n  rm -rf conftest.dSYM conftest_ipa8_conftest.oo\n  eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno\n  as_fn_set_status $ac_retval\n\n} # ac_fn_c_try_link\nac_configure_args_raw=\nfor ac_arg\ndo\n  case $ac_arg in\n  *\\'*)\n    ac_arg=`printf \"%s\\n\" \"$ac_arg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n  esac\n  as_fn_append ac_configure_args_raw \" '$ac_arg'\"\ndone\n\ncase $ac_configure_args_raw in\n  *$as_nl*)\n    ac_safe_unquote= ;;\n  *)\n    ac_unsafe_z='|&;<>()$`\\\\\"*?[ ''\t' # This string ends in space, tab.\n    ac_unsafe_a=\"$ac_unsafe_z#~\"\n    ac_safe_unquote=\"s/ '\\\\([^$ac_unsafe_a][^$ac_unsafe_z]*\\\\)'/ \\\\1/g\"\n    ac_configure_args_raw=`      printf \"%s\\n\" \"$ac_configure_args_raw\" | sed \"$ac_safe_unquote\"`;;\nesac\n\ncat >config.log <<_ACEOF\nThis file contains any messages produced by compilers while\nrunning configure, to aid debugging if configure makes a mistake.\n\nIt was created by $as_me, which was\ngenerated by GNU Autoconf 2.71.  Invocation command line was\n\n  $ $0$ac_configure_args_raw\n\n_ACEOF\nexec 5>>config.log\n{\ncat <<_ASUNAME\n## --------- ##\n## Platform. ##\n## --------- ##\n\nhostname = `(hostname || uname -n) 2>/dev/null | sed 1q`\nuname -m = `(uname -m) 2>/dev/null || echo unknown`\nuname -r = `(uname -r) 2>/dev/null || echo unknown`\nuname -s = `(uname -s) 2>/dev/null || echo unknown`\nuname -v = `(uname -v) 2>/dev/null || echo unknown`\n\n/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`\n/bin/uname -X     = `(/bin/uname -X) 2>/dev/null     || echo unknown`\n\n/bin/arch              = `(/bin/arch) 2>/dev/null              || echo unknown`\n/usr/bin/arch -k       = `(/usr/bin/arch -k) 2>/dev/null       || echo unknown`\n/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`\n/usr/bin/hostinfo      = `(/usr/bin/hostinfo) 2>/dev/null      || echo unknown`\n/bin/machine           = `(/bin/machine) 2>/dev/null           || echo unknown`\n/usr/bin/oslevel       = `(/usr/bin/oslevel) 2>/dev/null       || echo unknown`\n/bin/universe          = `(/bin/universe) 2>/dev/null          || echo unknown`\n\n_ASUNAME\n\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    printf \"%s\\n\" \"PATH: $as_dir\"\n  done\nIFS=$as_save_IFS\n\n} >&5\n\ncat >&5 <<_ACEOF\n\n\n## ----------- ##\n## Core tests. ##\n## ----------- ##\n\n_ACEOF\n\n\n# Keep a trace of the command line.\n# Strip out --no-create and --no-recursion so they do not pile up.\n# Strip out --silent because we don't want to record it for future runs.\n# Also quote any args containing shell meta-characters.\n# Make two passes to allow for proper duplicate-argument suppression.\nac_configure_args=\nac_configure_args0=\nac_configure_args1=\nac_must_keep_next=false\nfor ac_pass in 1 2\ndo\n  for ac_arg\n  do\n    case $ac_arg in\n    -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;\n    -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n    | -silent | --silent | --silen | --sile | --sil)\n      continue ;;\n    *\\'*)\n      ac_arg=`printf \"%s\\n\" \"$ac_arg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    esac\n    case $ac_pass in\n    1) as_fn_append ac_configure_args0 \" '$ac_arg'\" ;;\n    2)\n      as_fn_append ac_configure_args1 \" '$ac_arg'\"\n      if test $ac_must_keep_next = true; then\n\tac_must_keep_next=false # Got value, back to normal.\n      else\n\tcase $ac_arg in\n\t  *=* | --config-cache | -C | -disable-* | --disable-* \\\n\t  | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \\\n\t  | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \\\n\t  | -with-* | --with-* | -without-* | --without-* | --x)\n\t    case \"$ac_configure_args0 \" in\n\t      \"$ac_configure_args1\"*\" '$ac_arg' \"* ) continue ;;\n\t    esac\n\t    ;;\n\t  -* ) ac_must_keep_next=true ;;\n\tesac\n      fi\n      as_fn_append ac_configure_args \" '$ac_arg'\"\n      ;;\n    esac\n  done\ndone\n{ ac_configure_args0=; unset ac_configure_args0;}\n{ ac_configure_args1=; unset ac_configure_args1;}\n\n# When interrupted or exit'd, cleanup temporary files, and complete\n# config.log.  We remove comments because anyway the quotes in there\n# would cause problems or look ugly.\n# WARNING: Use '\\'' to represent an apostrophe within the trap.\n# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.\ntrap 'exit_status=$?\n  # Sanitize IFS.\n  IFS=\" \"\"\t$as_nl\"\n  # Save into config.log some information that might help in debugging.\n  {\n    echo\n\n    printf \"%s\\n\" \"## ---------------- ##\n## Cache variables. ##\n## ---------------- ##\"\n    echo\n    # The following way of writing the cache mishandles newlines in values,\n(\n  for ac_var in `(set) 2>&1 | sed -n '\\''s/^\\([a-zA-Z_][a-zA-Z0-9_]*\\)=.*/\\1/p'\\''`; do\n    eval ac_val=\\$$ac_var\n    case $ac_val in #(\n    *${as_nl}*)\n      case $ac_var in #(\n      *_cv_*) { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline\" >&5\nprintf \"%s\\n\" \"$as_me: WARNING: cache variable $ac_var contains a newline\" >&2;} ;;\n      esac\n      case $ac_var in #(\n      _ | IFS | as_nl) ;; #(\n      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(\n      *) { eval $ac_var=; unset $ac_var;} ;;\n      esac ;;\n    esac\n  done\n  (set) 2>&1 |\n    case $as_nl`(ac_space='\\'' '\\''; set) 2>&1` in #(\n    *${as_nl}ac_space=\\ *)\n      sed -n \\\n\t\"s/'\\''/'\\''\\\\\\\\'\\'''\\''/g;\n\t  s/^\\\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\\\)=\\\\(.*\\\\)/\\\\1='\\''\\\\2'\\''/p\"\n      ;; #(\n    *)\n      sed -n \"/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p\"\n      ;;\n    esac |\n    sort\n)\n    echo\n\n    printf \"%s\\n\" \"## ----------------- ##\n## Output variables. ##\n## ----------------- ##\"\n    echo\n    for ac_var in $ac_subst_vars\n    do\n      eval ac_val=\\$$ac_var\n      case $ac_val in\n      *\\'\\''*) ac_val=`printf \"%s\\n\" \"$ac_val\" | sed \"s/'\\''/'\\''\\\\\\\\\\\\\\\\'\\'''\\''/g\"`;;\n      esac\n      printf \"%s\\n\" \"$ac_var='\\''$ac_val'\\''\"\n    done | sort\n    echo\n\n    if test -n \"$ac_subst_files\"; then\n      printf \"%s\\n\" \"## ------------------- ##\n## File substitutions. ##\n## ------------------- ##\"\n      echo\n      for ac_var in $ac_subst_files\n      do\n\teval ac_val=\\$$ac_var\n\tcase $ac_val in\n\t*\\'\\''*) ac_val=`printf \"%s\\n\" \"$ac_val\" | sed \"s/'\\''/'\\''\\\\\\\\\\\\\\\\'\\'''\\''/g\"`;;\n\tesac\n\tprintf \"%s\\n\" \"$ac_var='\\''$ac_val'\\''\"\n      done | sort\n      echo\n    fi\n\n    if test -s confdefs.h; then\n      printf \"%s\\n\" \"## ----------- ##\n## confdefs.h. ##\n## ----------- ##\"\n      echo\n      cat confdefs.h\n      echo\n    fi\n    test \"$ac_signal\" != 0 &&\n      printf \"%s\\n\" \"$as_me: caught signal $ac_signal\"\n    printf \"%s\\n\" \"$as_me: exit $exit_status\"\n  } >&5\n  rm -f core *.core core.conftest.* &&\n    rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&\n    exit $exit_status\n' 0\nfor ac_signal in 1 2 13 15; do\n  trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal\ndone\nac_signal=0\n\n# confdefs.h avoids OS command line length limits that DEFS can exceed.\nrm -f -r conftest* confdefs.h\n\nprintf \"%s\\n\" \"/* confdefs.h */\" > confdefs.h\n\n# Predefined preprocessor variables.\n\nprintf \"%s\\n\" \"#define PACKAGE_NAME \\\"$PACKAGE_NAME\\\"\" >>confdefs.h\n\nprintf \"%s\\n\" \"#define PACKAGE_TARNAME \\\"$PACKAGE_TARNAME\\\"\" >>confdefs.h\n\nprintf \"%s\\n\" \"#define PACKAGE_VERSION \\\"$PACKAGE_VERSION\\\"\" >>confdefs.h\n\nprintf \"%s\\n\" \"#define PACKAGE_STRING \\\"$PACKAGE_STRING\\\"\" >>confdefs.h\n\nprintf \"%s\\n\" \"#define PACKAGE_BUGREPORT \\\"$PACKAGE_BUGREPORT\\\"\" >>confdefs.h\n\nprintf \"%s\\n\" \"#define PACKAGE_URL \\\"$PACKAGE_URL\\\"\" >>confdefs.h\n\n\n# Let the site file select an alternate cache file if it wants to.\n# Prefer an explicitly selected file to automatically selected ones.\nif test -n \"$CONFIG_SITE\"; then\n  ac_site_files=\"$CONFIG_SITE\"\nelif test \"x$prefix\" != xNONE; then\n  ac_site_files=\"$prefix/share/config.site $prefix/etc/config.site\"\nelse\n  ac_site_files=\"$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site\"\nfi\n\nfor ac_site_file in $ac_site_files\ndo\n  case $ac_site_file in #(\n  */*) :\n     ;; #(\n  *) :\n    ac_site_file=./$ac_site_file ;;\nesac\n  if test -f \"$ac_site_file\" && test -r \"$ac_site_file\"; then\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file\" >&5\nprintf \"%s\\n\" \"$as_me: loading site script $ac_site_file\" >&6;}\n    sed 's/^/| /' \"$ac_site_file\" >&5\n    . \"$ac_site_file\" \\\n      || { { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\nprintf \"%s\\n\" \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"failed to load site script $ac_site_file\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n  fi\ndone\n\nif test -r \"$cache_file\"; then\n  # Some versions of bash will fail to source /dev/null (special files\n  # actually), so we avoid doing that.  DJGPP emulates it as a regular file.\n  if test /dev/null != \"$cache_file\" && test -f \"$cache_file\"; then\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: loading cache $cache_file\" >&5\nprintf \"%s\\n\" \"$as_me: loading cache $cache_file\" >&6;}\n    case $cache_file in\n      [\\\\/]* | ?:[\\\\/]* ) . \"$cache_file\";;\n      *)                      . \"./$cache_file\";;\n    esac\n  fi\nelse\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: creating cache $cache_file\" >&5\nprintf \"%s\\n\" \"$as_me: creating cache $cache_file\" >&6;}\n  >$cache_file\nfi\n\n# Test code for whether the C compiler supports C89 (global declarations)\nac_c_conftest_c89_globals='\n/* Does the compiler advertise C89 conformance?\n   Do not test the value of __STDC__, because some compilers set it to 0\n   while being otherwise adequately conformant. */\n#if !defined __STDC__\n# error \"Compiler does not advertise C89 conformance\"\n#endif\n\n#include <stddef.h>\n#include <stdarg.h>\nstruct stat;\n/* Most of the following tests are stolen from RCS 5.7 src/conf.sh.  */\nstruct buf { int x; };\nstruct buf * (*rcsopen) (struct buf *, struct stat *, int);\nstatic char *e (p, i)\n     char **p;\n     int i;\n{\n  return p[i];\n}\nstatic char *f (char * (*g) (char **, int), char **p, ...)\n{\n  char *s;\n  va_list v;\n  va_start (v,p);\n  s = g (p, va_arg (v,int));\n  va_end (v);\n  return s;\n}\n\n/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default.  It has\n   function prototypes and stuff, but not \\xHH hex character constants.\n   These do not provoke an error unfortunately, instead are silently treated\n   as an \"x\".  The following induces an error, until -std is added to get\n   proper ANSI mode.  Curiously \\x00 != x always comes out true, for an\n   array size at least.  It is necessary to write \\x00 == 0 to get something\n   that is true only with -std.  */\nint osf4_cc_array ['\\''\\x00'\\'' == 0 ? 1 : -1];\n\n/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters\n   inside strings and character constants.  */\n#define FOO(x) '\\''x'\\''\nint xlc6_cc_array[FOO(a) == '\\''x'\\'' ? 1 : -1];\n\nint test (int i, double x);\nstruct s1 {int (*f) (int a);};\nstruct s2 {int (*f) (double a);};\nint pairnames (int, char **, int *(*)(struct buf *, struct stat *, int),\n               int, int);'\n\n# Test code for whether the C compiler supports C89 (body of main).\nac_c_conftest_c89_main='\nok |= (argc == 0 || f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]);\n'\n\n# Test code for whether the C compiler supports C99 (global declarations)\nac_c_conftest_c99_globals='\n// Does the compiler advertise C99 conformance?\n#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 199901L\n# error \"Compiler does not advertise C99 conformance\"\n#endif\n\n#include <stdbool.h>\nextern int puts (const char *);\nextern int printf (const char *, ...);\nextern int dprintf (int, const char *, ...);\nextern void *malloc (size_t);\n\n// Check varargs macros.  These examples are taken from C99 6.10.3.5.\n// dprintf is used instead of fprintf to avoid needing to declare\n// FILE and stderr.\n#define debug(...) dprintf (2, __VA_ARGS__)\n#define showlist(...) puts (#__VA_ARGS__)\n#define report(test,...) ((test) ? puts (#test) : printf (__VA_ARGS__))\nstatic void\ntest_varargs_macros (void)\n{\n  int x = 1234;\n  int y = 5678;\n  debug (\"Flag\");\n  debug (\"X = %d\\n\", x);\n  showlist (The first, second, and third items.);\n  report (x>y, \"x is %d but y is %d\", x, y);\n}\n\n// Check long long types.\n#define BIG64 18446744073709551615ull\n#define BIG32 4294967295ul\n#define BIG_OK (BIG64 / BIG32 == 4294967297ull && BIG64 % BIG32 == 0)\n#if !BIG_OK\n  #error \"your preprocessor is broken\"\n#endif\n#if BIG_OK\n#else\n  #error \"your preprocessor is broken\"\n#endif\nstatic long long int bignum = -9223372036854775807LL;\nstatic unsigned long long int ubignum = BIG64;\n\nstruct incomplete_array\n{\n  int datasize;\n  double data[];\n};\n\nstruct named_init {\n  int number;\n  const wchar_t *name;\n  double average;\n};\n\ntypedef const char *ccp;\n\nstatic inline int\ntest_restrict (ccp restrict text)\n{\n  // See if C++-style comments work.\n  // Iterate through items via the restricted pointer.\n  // Also check for declarations in for loops.\n  for (unsigned int i = 0; *(text+i) != '\\''\\0'\\''; ++i)\n    continue;\n  return 0;\n}\n\n// Check varargs and va_copy.\nstatic bool\ntest_varargs (const char *format, ...)\n{\n  va_list args;\n  va_start (args, format);\n  va_list args_copy;\n  va_copy (args_copy, args);\n\n  const char *str = \"\";\n  int number = 0;\n  float fnumber = 0;\n\n  while (*format)\n    {\n      switch (*format++)\n\t{\n\tcase '\\''s'\\'': // string\n\t  str = va_arg (args_copy, const char *);\n\t  break;\n\tcase '\\''d'\\'': // int\n\t  number = va_arg (args_copy, int);\n\t  break;\n\tcase '\\''f'\\'': // float\n\t  fnumber = va_arg (args_copy, double);\n\t  break;\n\tdefault:\n\t  break;\n\t}\n    }\n  va_end (args_copy);\n  va_end (args);\n\n  return *str && number && fnumber;\n}\n'\n\n# Test code for whether the C compiler supports C99 (body of main).\nac_c_conftest_c99_main='\n  // Check bool.\n  _Bool success = false;\n  success |= (argc != 0);\n\n  // Check restrict.\n  if (test_restrict (\"String literal\") == 0)\n    success = true;\n  char *restrict newvar = \"Another string\";\n\n  // Check varargs.\n  success &= test_varargs (\"s, d'\\'' f .\", \"string\", 65, 34.234);\n  test_varargs_macros ();\n\n  // Check flexible array members.\n  struct incomplete_array *ia =\n    malloc (sizeof (struct incomplete_array) + (sizeof (double) * 10));\n  ia->datasize = 10;\n  for (int i = 0; i < ia->datasize; ++i)\n    ia->data[i] = i * 1.234;\n\n  // Check named initializers.\n  struct named_init ni = {\n    .number = 34,\n    .name = L\"Test wide string\",\n    .average = 543.34343,\n  };\n\n  ni.number = 58;\n\n  int dynamic_array[ni.number];\n  dynamic_array[0] = argv[0][0];\n  dynamic_array[ni.number - 1] = 543;\n\n  // work around unused variable warnings\n  ok |= (!success || bignum == 0LL || ubignum == 0uLL || newvar[0] == '\\''x'\\''\n\t || dynamic_array[ni.number - 1] != 543);\n'\n\n# Test code for whether the C compiler supports C11 (global declarations)\nac_c_conftest_c11_globals='\n// Does the compiler advertise C11 conformance?\n#if !defined __STDC_VERSION__ || __STDC_VERSION__ < 201112L\n# error \"Compiler does not advertise C11 conformance\"\n#endif\n\n// Check _Alignas.\nchar _Alignas (double) aligned_as_double;\nchar _Alignas (0) no_special_alignment;\nextern char aligned_as_int;\nchar _Alignas (0) _Alignas (int) aligned_as_int;\n\n// Check _Alignof.\nenum\n{\n  int_alignment = _Alignof (int),\n  int_array_alignment = _Alignof (int[100]),\n  char_alignment = _Alignof (char)\n};\n_Static_assert (0 < -_Alignof (int), \"_Alignof is signed\");\n\n// Check _Noreturn.\nint _Noreturn does_not_return (void) { for (;;) continue; }\n\n// Check _Static_assert.\nstruct test_static_assert\n{\n  int x;\n  _Static_assert (sizeof (int) <= sizeof (long int),\n                  \"_Static_assert does not work in struct\");\n  long int y;\n};\n\n// Check UTF-8 literals.\n#define u8 syntax error!\nchar const utf8_literal[] = u8\"happens to be ASCII\" \"another string\";\n\n// Check duplicate typedefs.\ntypedef long *long_ptr;\ntypedef long int *long_ptr;\ntypedef long_ptr long_ptr;\n\n// Anonymous structures and unions -- taken from C11 6.7.2.1 Example 1.\nstruct anonymous\n{\n  union {\n    struct { int i; int j; };\n    struct { int k; long int l; } w;\n  };\n  int m;\n} v1;\n'\n\n# Test code for whether the C compiler supports C11 (body of main).\nac_c_conftest_c11_main='\n  _Static_assert ((offsetof (struct anonymous, i)\n\t\t   == offsetof (struct anonymous, w.k)),\n\t\t  \"Anonymous union alignment botch\");\n  v1.i = 2;\n  v1.w.k = 5;\n  ok |= v1.i != 5;\n'\n\n# Test code for whether the C compiler supports C11 (complete).\nac_c_conftest_c11_program=\"${ac_c_conftest_c89_globals}\n${ac_c_conftest_c99_globals}\n${ac_c_conftest_c11_globals}\n\nint\nmain (int argc, char **argv)\n{\n  int ok = 0;\n  ${ac_c_conftest_c89_main}\n  ${ac_c_conftest_c99_main}\n  ${ac_c_conftest_c11_main}\n  return ok;\n}\n\"\n\n# Test code for whether the C compiler supports C99 (complete).\nac_c_conftest_c99_program=\"${ac_c_conftest_c89_globals}\n${ac_c_conftest_c99_globals}\n\nint\nmain (int argc, char **argv)\n{\n  int ok = 0;\n  ${ac_c_conftest_c89_main}\n  ${ac_c_conftest_c99_main}\n  return ok;\n}\n\"\n\n# Test code for whether the C compiler supports C89 (complete).\nac_c_conftest_c89_program=\"${ac_c_conftest_c89_globals}\n\nint\nmain (int argc, char **argv)\n{\n  int ok = 0;\n  ${ac_c_conftest_c89_main}\n  return ok;\n}\n\"\n\nas_fn_append ac_header_c_list \" stdio.h stdio_h HAVE_STDIO_H\"\nas_fn_append ac_header_c_list \" stdlib.h stdlib_h HAVE_STDLIB_H\"\nas_fn_append ac_header_c_list \" string.h string_h HAVE_STRING_H\"\nas_fn_append ac_header_c_list \" inttypes.h inttypes_h HAVE_INTTYPES_H\"\nas_fn_append ac_header_c_list \" stdint.h stdint_h HAVE_STDINT_H\"\nas_fn_append ac_header_c_list \" strings.h strings_h HAVE_STRINGS_H\"\nas_fn_append ac_header_c_list \" sys/stat.h sys_stat_h HAVE_SYS_STAT_H\"\nas_fn_append ac_header_c_list \" sys/types.h sys_types_h HAVE_SYS_TYPES_H\"\nas_fn_append ac_header_c_list \" unistd.h unistd_h HAVE_UNISTD_H\"\n# Check that the precious variables saved in the cache have kept the same\n# value.\nac_cache_corrupted=false\nfor ac_var in $ac_precious_vars; do\n  eval ac_old_set=\\$ac_cv_env_${ac_var}_set\n  eval ac_new_set=\\$ac_env_${ac_var}_set\n  eval ac_old_val=\\$ac_cv_env_${ac_var}_value\n  eval ac_new_val=\\$ac_env_${ac_var}_value\n  case $ac_old_set,$ac_new_set in\n    set,)\n      { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: error: \\`$ac_var' was set to \\`$ac_old_val' in the previous run\" >&5\nprintf \"%s\\n\" \"$as_me: error: \\`$ac_var' was set to \\`$ac_old_val' in the previous run\" >&2;}\n      ac_cache_corrupted=: ;;\n    ,set)\n      { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: error: \\`$ac_var' was not set in the previous run\" >&5\nprintf \"%s\\n\" \"$as_me: error: \\`$ac_var' was not set in the previous run\" >&2;}\n      ac_cache_corrupted=: ;;\n    ,);;\n    *)\n      if test \"x$ac_old_val\" != \"x$ac_new_val\"; then\n\t# differences in whitespace do not lead to failure.\n\tac_old_val_w=`echo x $ac_old_val`\n\tac_new_val_w=`echo x $ac_new_val`\n\tif test \"$ac_old_val_w\" != \"$ac_new_val_w\"; then\n\t  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: error: \\`$ac_var' has changed since the previous run:\" >&5\nprintf \"%s\\n\" \"$as_me: error: \\`$ac_var' has changed since the previous run:\" >&2;}\n\t  ac_cache_corrupted=:\n\telse\n\t  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \\`$ac_var' since the previous run:\" >&5\nprintf \"%s\\n\" \"$as_me: warning: ignoring whitespace changes in \\`$ac_var' since the previous run:\" >&2;}\n\t  eval $ac_var=\\$ac_old_val\n\tfi\n\t{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}:   former value:  \\`$ac_old_val'\" >&5\nprintf \"%s\\n\" \"$as_me:   former value:  \\`$ac_old_val'\" >&2;}\n\t{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}:   current value: \\`$ac_new_val'\" >&5\nprintf \"%s\\n\" \"$as_me:   current value: \\`$ac_new_val'\" >&2;}\n      fi;;\n  esac\n  # Pass precious variables to config.status.\n  if test \"$ac_new_set\" = set; then\n    case $ac_new_val in\n    *\\'*) ac_arg=$ac_var=`printf \"%s\\n\" \"$ac_new_val\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    *) ac_arg=$ac_var=$ac_new_val ;;\n    esac\n    case \" $ac_configure_args \" in\n      *\" '$ac_arg' \"*) ;; # Avoid dups.  Use of quotes ensures accuracy.\n      *) as_fn_append ac_configure_args \" '$ac_arg'\" ;;\n    esac\n  fi\ndone\nif $ac_cache_corrupted; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\nprintf \"%s\\n\" \"$as_me: error: in \\`$ac_pwd':\" >&2;}\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build\" >&5\nprintf \"%s\\n\" \"$as_me: error: changes in the environment can compromise the build\" >&2;}\n  as_fn_error $? \"run \\`${MAKE-make} distclean' and/or \\`rm $cache_file'\n\t    and start over\" \"$LINENO\" 5\nfi\n## -------------------- ##\n## Main body of script. ##\n## -------------------- ##\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\n\n\n: ${R_HOME=`R RHOME`}\nif test -z \"${R_HOME}\"; then\n  echo \"could not determine R_HOME\"\n  exit 1\nfi\n\nRBIN=\"${R_HOME}/bin/R\"\n# https://github.com/r-spatial/sf/issues/1054:\n# RVER=`\"${RBIN}\" --version | head -1 | cut -f3 -d\" \"`\nRSCRIPT=\"${R_HOME}/bin/Rscript\"\nRVER=`\"${RSCRIPT}\" -e 'writeLines(paste(sep=\".\", base::version$major, base::version$minor))'`\n\nRVER_MAJOR=`echo ${RVER} | cut  -f1 -d\".\"`\nRVER_MINOR=`echo ${RVER} | cut  -f2 -d\".\"`\nRVER_PATCH=`echo ${RVER} | cut  -f3 -d\".\"`\n\n#if test [$RVER_MAJOR = \"development\"]; then\n    CXX=`\"${RBIN}\" CMD config CXX`\n#else\n#    if test [$RVER_MAJOR -lt 3] -o [$RVER_MAJOR -eq 3 -a $RVER_MINOR -lt 3]; then\n#        AC_MSG_ERROR([sf is not compatible with R versions before 3.3.0])\n#    else\n#        CXX=`\"${RBIN}\" CMD config CXX`\n#    fi\n#fi\n\n# pick all flags for testing from R\n: ${CC=`\"${RBIN}\" CMD config CC`}\n: ${CFLAGS=`\"${RBIN}\" CMD config CFLAGS`}\n: ${CPPFLAGS=`\"${RBIN}\" CMD config CPPFLAGS`}\n: ${CXXFLAGS=`\"${RBIN}\" CMD config CXXFLAGS`}\n: ${LDFLAGS=`\"${RBIN}\" CMD config LDFLAGS`}\n# AC_SUBST([CC],[\"clang\"])\n# AC_SUBST([CXX],[\"clang++\"])\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: CC: ${CC}\" >&5\nprintf \"%s\\n\" \"$as_me: CC: ${CC}\" >&6;}\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: CXX: ${CXX}\" >&5\nprintf \"%s\\n\" \"$as_me: CXX: ${CXX}\" >&6;}\n\n# AC_MSG_NOTICE([${PACKAGE_NAME}: ${PACKAGE_VERSION}])\n\nGENERIC_INSTALL_MESSAGE=\"\n*** Installing this package from source requires the prior\n*** installation of external software, see for details\n*** https://r-spatial.github.io/sf/#installing\"\n\n#GDAL\nGDAL_CONFIG=\"gdal-config\"\n\nGDAL_CONFIG_SET=\"no\"\n\n\n# Check whether --with-gdal-config was given.\nif test ${with_gdal_config+y}\nthen :\n  withval=$with_gdal_config; gdal_config=$withval\nfi\n\nif test  -n \"$gdal_config\"  ; then\n    GDAL_CONFIG_SET=\"yes\"\n    GDAL_CONFIG=\"${gdal_config}\"\n\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: gdal-config set to $GDAL_CONFIG\" >&5\nprintf \"%s\\n\" \"$as_me: gdal-config set to $GDAL_CONFIG\" >&6;}\nfi\n\nif test \"$GDAL_CONFIG_SET\" = \"no\" ; then\n  # Extract the first word of \"\"$GDAL_CONFIG\"\", so it can be a program name with args.\nset dummy \"$GDAL_CONFIG\"; ac_word=$2\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_path_GDAL_CONFIG+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  case $GDAL_CONFIG in\n  [\\\\/]* | ?:[\\\\/]*)\n  ac_cv_path_GDAL_CONFIG=\"$GDAL_CONFIG\" # Let the user override the test with a path.\n  ;;\n  *)\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_path_GDAL_CONFIG=\"$as_dir$ac_word$ac_exec_ext\"\n    printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\n  test -z \"$ac_cv_path_GDAL_CONFIG\" && ac_cv_path_GDAL_CONFIG=\"\"no\"\"\n  ;;\nesac\nfi\nGDAL_CONFIG=$ac_cv_path_GDAL_CONFIG\nif test -n \"$GDAL_CONFIG\"; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $GDAL_CONFIG\" >&5\nprintf \"%s\\n\" \"$GDAL_CONFIG\" >&6; }\nelse\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nfi\n\n\n  if test \"$GDAL_CONFIG\" = \"no\" ; then\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\n    as_fn_error $? \"gdal-config not found or not executable. ${GENERIC_INSTALL_MESSAGE}\" \"$LINENO\" 5\n  fi\nelse\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking gdal-config exists\" >&5\nprintf %s \"checking gdal-config exists... \" >&6; }\n  if test -r \"${GDAL_CONFIG}\"; then\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\n  else\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\n    as_fn_error $? \"gdal-config not found - configure argument error. ${GENERIC_INSTALL_MESSAGE}\" \"$LINENO\" 5\n  fi\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking gdal-config executable\" >&5\nprintf %s \"checking gdal-config executable... \" >&6; }\n  if test -x \"${GDAL_CONFIG}\"; then\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\n  else\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\n    as_fn_error $? \"gdal-config not executable. ${GENERIC_INSTALL_MESSAGE}\" \"$LINENO\" 5\n  fi\nfi\n\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking gdal-config usability\" >&5\nprintf %s \"checking gdal-config usability... \" >&6; }\nif test `${GDAL_CONFIG} --version`;\nthen\n\tGDAL_CPPFLAGS=`${GDAL_CONFIG} --cflags`\n\tGDAL_VERSION=`${GDAL_CONFIG} --version`\n\tGDAL_LIBS=`${GDAL_CONFIG} --libs`\n\tGDAL_DEP_LIBS=`${GDAL_CONFIG} --dep-libs`\n\tGDAL_DATADIR=`${GDAL_CONFIG} --datadir`\n\t{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\nelse\n\tas_fn_error $? \"gdal-config not found. ${GENERIC_INSTALL_MESSAGE}\" \"$LINENO\" 5\nfi\n\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: GDAL: ${GDAL_VERSION}\" >&5\nprintf \"%s\\n\" \"$as_me: GDAL: ${GDAL_VERSION}\" >&6;}\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking GDAL version >= 2.0.1\" >&5\nprintf %s \"checking GDAL version >= 2.0.1... \" >&6; }\n\nGDAL_MAJ_VER=`echo $GDAL_VERSION | cut -d \".\" -f1`\nGDAL_MIN_VER=`echo $GDAL_VERSION | cut -d \".\" -f2`\nGDAL_PATCH_VER=`echo $GDAL_VERSION | cut -d \".\" -f3`\nif test ${GDAL_MAJ_VER} -lt 2 ; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\n  as_fn_error $? \"sf is not compatible with GDAL versions below 2.0.1\" \"$LINENO\" 5\nelse\n   { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\nfi\n\n#if test [${GDAL_MAJ_VER} -eq 3] -a [${GDAL_MIN_VER} -eq 6] -a [${GDAL_PATCH_VER} -eq 0] ; then\nif test \"${GDAL_VERSION}\" = \"3.6.0\" ; then\n  as_fn_error $? \"GDAL version 3.6.0 has been withdrawn, please update GDAL\" \"$LINENO\" 5\nfi\n\nINLIBS=\"${LIBS}\"\nINCPPFLAGS=\"${CPPFLAGS}\"\nINPKG_CPPFLAGS=\"${PKG_CPPFLAGS}\"\nINPKG_LIBS=\"${PKG_LIBS}\"\n\nPKG_CPPFLAGS=\"${INPKG_CPPFLAGS} ${GDAL_CPPFLAGS}\"\n\nPKG_LIBS=\"${INPKG_LIBS} ${GDAL_LIBS}\"\n\n\n# honor PKG_xx overrides\n# for CPPFLAGS we will superfluously double R's flags\n# since we'll set PKG_CPPFLAGS with this, but that shouldn't hurt\nCPPFLAGS=\"${INCPPFLAGS} ${PKG_CPPFLAGS}\"\n\ngdalok=yes\n\n\n\n\n\n\n\n\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\nif test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}gcc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}gcc; ac_word=$2\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}gcc\"\n    printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\nprintf \"%s\\n\" \"$CC\" >&6; }\nelse\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_CC\"; then\n  ac_ct_CC=$CC\n  # Extract the first word of \"gcc\", so it can be a program name with args.\nset dummy gcc; ac_word=$2\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_ac_ct_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"gcc\"\n    printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\nprintf \"%s\\n\" \"$ac_ct_CC\" >&6; }\nelse\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\nprintf \"%s\\n\" \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nelse\n  CC=\"$ac_cv_prog_CC\"\nfi\n\nif test -z \"$CC\"; then\n          if test -n \"$ac_tool_prefix\"; then\n    # Extract the first word of \"${ac_tool_prefix}cc\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}cc; ac_word=$2\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}cc\"\n    printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\nprintf \"%s\\n\" \"$CC\" >&6; }\nelse\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nfi\n\n\n  fi\nfi\nif test -z \"$CC\"; then\n  # Extract the first word of \"cc\", so it can be a program name with args.\nset dummy cc; ac_word=$2\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\n  ac_prog_rejected=no\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    if test \"$as_dir$ac_word$ac_exec_ext\" = \"/usr/ucb/cc\"; then\n       ac_prog_rejected=yes\n       continue\n     fi\n    ac_cv_prog_CC=\"cc\"\n    printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nif test $ac_prog_rejected = yes; then\n  # We found a bogon in the path, so make sure we never use it.\n  set dummy $ac_cv_prog_CC\n  shift\n  if test $# != 0; then\n    # We chose a different compiler from the bogus one.\n    # However, it has the same basename, so the bogon will be chosen\n    # first if we set CC to just the basename; use the full file name.\n    shift\n    ac_cv_prog_CC=\"$as_dir$ac_word${1+' '}$@\"\n  fi\nfi\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\nprintf \"%s\\n\" \"$CC\" >&6; }\nelse\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$CC\"; then\n  if test -n \"$ac_tool_prefix\"; then\n  for ac_prog in cl.exe\n  do\n    # Extract the first word of \"$ac_tool_prefix$ac_prog\", so it can be a program name with args.\nset dummy $ac_tool_prefix$ac_prog; ac_word=$2\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"$ac_tool_prefix$ac_prog\"\n    printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\nprintf \"%s\\n\" \"$CC\" >&6; }\nelse\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nfi\n\n\n    test -n \"$CC\" && break\n  done\nfi\nif test -z \"$CC\"; then\n  ac_ct_CC=$CC\n  for ac_prog in cl.exe\ndo\n  # Extract the first word of \"$ac_prog\", so it can be a program name with args.\nset dummy $ac_prog; ac_word=$2\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_ac_ct_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"$ac_prog\"\n    printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\nprintf \"%s\\n\" \"$ac_ct_CC\" >&6; }\nelse\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nfi\n\n\n  test -n \"$ac_ct_CC\" && break\ndone\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\nprintf \"%s\\n\" \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nfi\n\nfi\nif test -z \"$CC\"; then\n  if test -n \"$ac_tool_prefix\"; then\n  # Extract the first word of \"${ac_tool_prefix}clang\", so it can be a program name with args.\nset dummy ${ac_tool_prefix}clang; ac_word=$2\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  if test -n \"$CC\"; then\n  ac_cv_prog_CC=\"$CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_CC=\"${ac_tool_prefix}clang\"\n    printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nCC=$ac_cv_prog_CC\nif test -n \"$CC\"; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $CC\" >&5\nprintf \"%s\\n\" \"$CC\" >&6; }\nelse\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nfi\n\n\nfi\nif test -z \"$ac_cv_prog_CC\"; then\n  ac_ct_CC=$CC\n  # Extract the first word of \"clang\", so it can be a program name with args.\nset dummy clang; ac_word=$2\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_prog_ac_ct_CC+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  if test -n \"$ac_ct_CC\"; then\n  ac_cv_prog_ac_ct_CC=\"$ac_ct_CC\" # Let the user override the test.\nelse\nas_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_prog_ac_ct_CC=\"clang\"\n    printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\nfi\nfi\nac_ct_CC=$ac_cv_prog_ac_ct_CC\nif test -n \"$ac_ct_CC\"; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC\" >&5\nprintf \"%s\\n\" \"$ac_ct_CC\" >&6; }\nelse\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nfi\n\n  if test \"x$ac_ct_CC\" = x; then\n    CC=\"\"\n  else\n    case $cross_compiling:$ac_tool_warned in\nyes:)\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet\" >&5\nprintf \"%s\\n\" \"$as_me: WARNING: using cross tools not prefixed with host triplet\" >&2;}\nac_tool_warned=yes ;;\nesac\n    CC=$ac_ct_CC\n  fi\nelse\n  CC=\"$ac_cv_prog_CC\"\nfi\n\nfi\n\n\ntest -z \"$CC\" && { { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\nprintf \"%s\\n\" \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"no acceptable C compiler found in \\$PATH\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n\n# Provide some information about the compiler.\nprintf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for C compiler version\" >&5\nset X $ac_compile\nac_compiler=$2\nfor ac_option in --version -v -V -qversion -version; do\n  { { ac_try=\"$ac_compiler $ac_option >&5\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf \"%s\\n\" \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compiler $ac_option >&5\") 2>conftest.err\n  ac_status=$?\n  if test -s conftest.err; then\n    sed '10a\\\n... rest of stderr output deleted ...\n         10q' conftest.err >conftest.er1\n    cat conftest.er1 >&5\n  fi\n  rm -f conftest.er1 conftest.err\n  printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\ndone\n\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nac_clean_files_save=$ac_clean_files\nac_clean_files=\"$ac_clean_files a.out a.out.dSYM a.exe b.out\"\n# Try to create an executable without -o first, disregard a.out.\n# It will help us diagnose broken compilers, and finding out an intuition\n# of exeext.\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking whether the C compiler works\" >&5\nprintf %s \"checking whether the C compiler works... \" >&6; }\nac_link_default=`printf \"%s\\n\" \"$ac_link\" | sed 's/ -o *conftest[^ ]*//'`\n\n# The possible output files:\nac_files=\"a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*\"\n\nac_rmfiles=\nfor ac_file in $ac_files\ndo\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;\n    * ) ac_rmfiles=\"$ac_rmfiles $ac_file\";;\n  esac\ndone\nrm -f $ac_rmfiles\n\nif { { ac_try=\"$ac_link_default\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf \"%s\\n\" \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link_default\") 2>&5\n  ac_status=$?\n  printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\nthen :\n  # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.\n# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'\n# in a Makefile.  We should not override ac_cv_exeext if it was cached,\n# so that the user can short-circuit this test for compilers unknown to\n# Autoconf.\nfor ac_file in $ac_files ''\ndo\n  test -f \"$ac_file\" || continue\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )\n\t;;\n    [ab].out )\n\t# We found the default executable, but exeext='' is most\n\t# certainly right.\n\tbreak;;\n    *.* )\n\tif test ${ac_cv_exeext+y} && test \"$ac_cv_exeext\" != no;\n\tthen :; else\n\t   ac_cv_exeext=`expr \"$ac_file\" : '[^.]*\\(\\..*\\)'`\n\tfi\n\t# We set ac_cv_exeext here because the later test for it is not\n\t# safe: cross compilers may not add the suffix if given an `-o'\n\t# argument, so we may need to know it at that point already.\n\t# Even if this section looks crufty: it has the advantage of\n\t# actually working.\n\tbreak;;\n    * )\n\tbreak;;\n  esac\ndone\ntest \"$ac_cv_exeext\" = no && ac_cv_exeext=\n\nelse $as_nop\n  ac_file=''\nfi\nif test -z \"$ac_file\"\nthen :\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nprintf \"%s\\n\" \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n{ { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\nprintf \"%s\\n\" \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error 77 \"C compiler cannot create executables\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\nelse $as_nop\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\nfi\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name\" >&5\nprintf %s \"checking for C compiler default output file name... \" >&6; }\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $ac_file\" >&5\nprintf \"%s\\n\" \"$ac_file\" >&6; }\nac_exeext=$ac_cv_exeext\n\nrm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out\nac_clean_files=$ac_clean_files_save\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for suffix of executables\" >&5\nprintf %s \"checking for suffix of executables... \" >&6; }\nif { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf \"%s\\n\" \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\nthen :\n  # If both `conftest.exe' and `conftest' are `present' (well, observable)\n# catch `conftest.exe'.  For instance with Cygwin, `ls conftest' will\n# work properly (i.e., refer to `conftest.exe'), while it won't with\n# `rm'.\nfor ac_file in conftest.exe conftest conftest.*; do\n  test -f \"$ac_file\" || continue\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;\n    *.* ) ac_cv_exeext=`expr \"$ac_file\" : '[^.]*\\(\\..*\\)'`\n\t  break;;\n    * ) break;;\n  esac\ndone\nelse $as_nop\n  { { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\nprintf \"%s\\n\" \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"cannot compute suffix of executables: cannot compile and link\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\nfi\nrm -f conftest conftest$ac_cv_exeext\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext\" >&5\nprintf \"%s\\n\" \"$ac_cv_exeext\" >&6; }\n\nrm -f conftest.$ac_ext\nEXEEXT=$ac_cv_exeext\nac_exeext=$EXEEXT\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n#include <stdio.h>\nint\nmain (void)\n{\nFILE *f = fopen (\"conftest.out\", \"w\");\n return ferror (f) || fclose (f) != 0;\n\n  ;\n  return 0;\n}\n_ACEOF\nac_clean_files=\"$ac_clean_files conftest.out\"\n# Check that the compiler produces executables we can run.  If not, either\n# the compiler is broken, or we cross compile.\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling\" >&5\nprintf %s \"checking whether we are cross compiling... \" >&6; }\nif test \"$cross_compiling\" != yes; then\n  { { ac_try=\"$ac_link\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf \"%s\\n\" \"$ac_try_echo\"; } >&5\n  (eval \"$ac_link\") 2>&5\n  ac_status=$?\n  printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\n  if { ac_try='./conftest$ac_cv_exeext'\n  { { case \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf \"%s\\n\" \"$ac_try_echo\"; } >&5\n  (eval \"$ac_try\") 2>&5\n  ac_status=$?\n  printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }; }; then\n    cross_compiling=no\n  else\n    if test \"$cross_compiling\" = maybe; then\n\tcross_compiling=yes\n    else\n\t{ { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\nprintf \"%s\\n\" \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error 77 \"cannot run C compiled programs.\nIf you meant to cross compile, use \\`--host'.\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\n    fi\n  fi\nfi\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $cross_compiling\" >&5\nprintf \"%s\\n\" \"$cross_compiling\" >&6; }\n\nrm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out\nac_clean_files=$ac_clean_files_save\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for suffix of object files\" >&5\nprintf %s \"checking for suffix of object files... \" >&6; }\nif test ${ac_cv_objext+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nrm -f conftest.o conftest.obj\nif { { ac_try=\"$ac_compile\"\ncase \"(($ac_try\" in\n  *\\\"* | *\\`* | *\\\\*) ac_try_echo=\\$ac_try;;\n  *) ac_try_echo=$ac_try;;\nesac\neval ac_try_echo=\"\\\"\\$as_me:${as_lineno-$LINENO}: $ac_try_echo\\\"\"\nprintf \"%s\\n\" \"$ac_try_echo\"; } >&5\n  (eval \"$ac_compile\") 2>&5\n  ac_status=$?\n  printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: \\$? = $ac_status\" >&5\n  test $ac_status = 0; }\nthen :\n  for ac_file in conftest.o conftest.obj conftest.*; do\n  test -f \"$ac_file\" || continue;\n  case $ac_file in\n    *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;\n    *) ac_cv_objext=`expr \"$ac_file\" : '.*\\.\\(.*\\)'`\n       break;;\n  esac\ndone\nelse $as_nop\n  printf \"%s\\n\" \"$as_me: failed program was:\" >&5\nsed 's/^/| /' conftest.$ac_ext >&5\n\n{ { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: error: in \\`$ac_pwd':\" >&5\nprintf \"%s\\n\" \"$as_me: error: in \\`$ac_pwd':\" >&2;}\nas_fn_error $? \"cannot compute suffix of object files: cannot compile\nSee \\`config.log' for more details\" \"$LINENO\" 5; }\nfi\nrm -f conftest.$ac_cv_objext conftest.$ac_ext\nfi\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext\" >&5\nprintf \"%s\\n\" \"$ac_cv_objext\" >&6; }\nOBJEXT=$ac_cv_objext\nac_objext=$OBJEXT\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking whether the compiler supports GNU C\" >&5\nprintf %s \"checking whether the compiler supports GNU C... \" >&6; }\nif test ${ac_cv_c_compiler_gnu+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n#ifndef __GNUC__\n       choke me\n#endif\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_compiler_gnu=yes\nelse $as_nop\n  ac_compiler_gnu=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\nac_cv_c_compiler_gnu=$ac_compiler_gnu\n\nfi\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu\" >&5\nprintf \"%s\\n\" \"$ac_cv_c_compiler_gnu\" >&6; }\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\nif test $ac_compiler_gnu = yes; then\n  GCC=yes\nelse\n  GCC=\nfi\nac_test_CFLAGS=${CFLAGS+y}\nac_save_CFLAGS=$CFLAGS\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g\" >&5\nprintf %s \"checking whether $CC accepts -g... \" >&6; }\nif test ${ac_cv_prog_cc_g+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  ac_save_c_werror_flag=$ac_c_werror_flag\n   ac_c_werror_flag=yes\n   ac_cv_prog_cc_g=no\n   CFLAGS=\"-g\"\n   cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_g=yes\nelse $as_nop\n  CFLAGS=\"\"\n      cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n\nelse $as_nop\n  ac_c_werror_flag=$ac_save_c_werror_flag\n\t CFLAGS=\"-g\"\n\t cat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\nint\nmain (void)\n{\n\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_g=yes\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam conftest.$ac_ext\n   ac_c_werror_flag=$ac_save_c_werror_flag\nfi\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g\" >&5\nprintf \"%s\\n\" \"$ac_cv_prog_cc_g\" >&6; }\nif test $ac_test_CFLAGS; then\n  CFLAGS=$ac_save_CFLAGS\nelif test $ac_cv_prog_cc_g = yes; then\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-g -O2\"\n  else\n    CFLAGS=\"-g\"\n  fi\nelse\n  if test \"$GCC\" = yes; then\n    CFLAGS=\"-O2\"\n  else\n    CFLAGS=\n  fi\nfi\nac_prog_cc_stdc=no\nif test x$ac_prog_cc_stdc = xno\nthen :\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C11 features\" >&5\nprintf %s \"checking for $CC option to enable C11 features... \" >&6; }\nif test ${ac_cv_prog_cc_c11+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  ac_cv_prog_cc_c11=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_c_conftest_c11_program\n_ACEOF\nfor ac_arg in '' -std=gnu11\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_c11=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam\n  test \"x$ac_cv_prog_cc_c11\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC\nfi\n\nif test \"x$ac_cv_prog_cc_c11\" = xno\nthen :\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\nprintf \"%s\\n\" \"unsupported\" >&6; }\nelse $as_nop\n  if test \"x$ac_cv_prog_cc_c11\" = x\nthen :\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\nprintf \"%s\\n\" \"none needed\" >&6; }\nelse $as_nop\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c11\" >&5\nprintf \"%s\\n\" \"$ac_cv_prog_cc_c11\" >&6; }\n     CC=\"$CC $ac_cv_prog_cc_c11\"\nfi\n  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c11\n  ac_prog_cc_stdc=c11\nfi\nfi\nif test x$ac_prog_cc_stdc = xno\nthen :\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C99 features\" >&5\nprintf %s \"checking for $CC option to enable C99 features... \" >&6; }\nif test ${ac_cv_prog_cc_c99+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  ac_cv_prog_cc_c99=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_c_conftest_c99_program\n_ACEOF\nfor ac_arg in '' -std=gnu99 -std=c99 -c99 -qlanglvl=extc1x -qlanglvl=extc99 -AC99 -D_STDC_C99=\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_c99=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam\n  test \"x$ac_cv_prog_cc_c99\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC\nfi\n\nif test \"x$ac_cv_prog_cc_c99\" = xno\nthen :\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\nprintf \"%s\\n\" \"unsupported\" >&6; }\nelse $as_nop\n  if test \"x$ac_cv_prog_cc_c99\" = x\nthen :\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\nprintf \"%s\\n\" \"none needed\" >&6; }\nelse $as_nop\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c99\" >&5\nprintf \"%s\\n\" \"$ac_cv_prog_cc_c99\" >&6; }\n     CC=\"$CC $ac_cv_prog_cc_c99\"\nfi\n  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c99\n  ac_prog_cc_stdc=c99\nfi\nfi\nif test x$ac_prog_cc_stdc = xno\nthen :\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for $CC option to enable C89 features\" >&5\nprintf %s \"checking for $CC option to enable C89 features... \" >&6; }\nif test ${ac_cv_prog_cc_c89+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  ac_cv_prog_cc_c89=no\nac_save_CC=$CC\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n$ac_c_conftest_c89_program\n_ACEOF\nfor ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std -Ae \"-Aa -D_HPUX_SOURCE\" \"-Xc -D__EXTENSIONS__\"\ndo\n  CC=\"$ac_save_CC $ac_arg\"\n  if ac_fn_c_try_compile \"$LINENO\"\nthen :\n  ac_cv_prog_cc_c89=$ac_arg\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam\n  test \"x$ac_cv_prog_cc_c89\" != \"xno\" && break\ndone\nrm -f conftest.$ac_ext\nCC=$ac_save_CC\nfi\n\nif test \"x$ac_cv_prog_cc_c89\" = xno\nthen :\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: unsupported\" >&5\nprintf \"%s\\n\" \"unsupported\" >&6; }\nelse $as_nop\n  if test \"x$ac_cv_prog_cc_c89\" = x\nthen :\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: none needed\" >&5\nprintf \"%s\\n\" \"none needed\" >&6; }\nelse $as_nop\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89\" >&5\nprintf \"%s\\n\" \"$ac_cv_prog_cc_c89\" >&6; }\n     CC=\"$CC $ac_cv_prog_cc_c89\"\nfi\n  ac_cv_prog_cc_stdc=$ac_cv_prog_cc_c89\n  ac_prog_cc_stdc=c89\nfi\nfi\n\nac_ext=c\nac_cpp='$CPP $CPPFLAGS'\nac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'\nac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'\nac_compiler_gnu=$ac_cv_c_compiler_gnu\n\n\nac_header= ac_cache=\nfor ac_item in $ac_header_c_list\ndo\n  if test $ac_cache; then\n    ac_fn_c_check_header_compile \"$LINENO\" $ac_header ac_cv_header_$ac_cache \"$ac_includes_default\"\n    if eval test \\\"x\\$ac_cv_header_$ac_cache\\\" = xyes; then\n      printf \"%s\\n\" \"#define $ac_item 1\" >> confdefs.h\n    fi\n    ac_header= ac_cache=\n  elif test $ac_header; then\n    ac_cache=$ac_item\n  else\n    ac_header=$ac_item\n  fi\ndone\n\n\n\n\n\n\n\n\nif test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes\nthen :\n\nprintf \"%s\\n\" \"#define STDC_HEADERS 1\" >>confdefs.h\n\nfi\n       for ac_header in gdal.h\ndo :\n  ac_fn_c_check_header_compile \"$LINENO\" \"gdal.h\" \"ac_cv_header_gdal_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_gdal_h\" = xyes\nthen :\n  printf \"%s\\n\" \"#define HAVE_GDAL_H 1\" >>confdefs.h\n\nelse $as_nop\n  gdalok=no\nfi\n\ndone\nif test \"${gdalok}\" = no; then\n   as_fn_error $? \"gdal.h not found in given locations. ${GENERIC_INSTALL_MESSAGE}\" \"$LINENO\" 5\nfi\n\nNEED_DEPS=no\nLIBS=\"${INLIBS} ${PKG_LIBS}\"\ncat > gdal_test.cpp <<_EOCONF\n#include <gdal.h>\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nint main(void) {\nGDALAllRegister();\n}\n#ifdef __cplusplus\n}\n#endif\n_EOCONF\n\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking GDAL: linking with --libs only\" >&5\nprintf %s \"checking GDAL: linking with --libs only... \" >&6; }\n${CXX} ${CPPFLAGS} -o gdal_test gdal_test.cpp ${LIBS} 2> errors.txt\nif test `echo $?` -ne 0 ; then\ngdalok=no\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nelse\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\nfi\n\nif test \"${gdalok}\" = no; then\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking GDAL: linking with --libs and --dep-libs\" >&5\nprintf %s \"checking GDAL: linking with --libs and --dep-libs... \" >&6; }\nLIBS=\"${LIBS} ${GDAL_DEP_LIBS}\"\ngdalok=yes\n${CXX} ${CPPFLAGS} -o gdal_test gdal_test.cpp ${LIBS} 2>> errors.txt\nif test `echo $?` -ne 0 ; then\ngdalok=no\nfi\nif test \"${gdalok}\" = yes; then\n    NEED_DEPS=yes\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\nelse\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nfi\nfi\n\nif test \"${gdalok}\" = no; then\n   cat errors.txt\n   { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: Install failure: compilation and/or linkage problems.\" >&5\nprintf \"%s\\n\" \"$as_me: Install failure: compilation and/or linkage problems.\" >&6;}\n   as_fn_error $? \"GDALAllRegister not found in libgdal. ${GENERIC_INSTALL_MESSAGE}\" \"$LINENO\" 5\nfi\n\nrm -f gdal_test errors.txt gdal_test.cpp\n\nGDAL_GE_250=\"no\"\nGDAL_MAJ_VER=`echo $GDAL_VERSION | cut -d \".\" -f1`\nGDAL_MOD_VER=`echo $GDAL_VERSION | cut -d \".\" -f2`\nif test \"${GDAL_MAJ_VER}\" = 2 ; then\n  if test \"${GDAL_MOD_VER}\" -ge 5 ; then\n    GDAL_GE_250=\"yes\"\n  fi\nelse\n  if test \"${GDAL_MAJ_VER}\" -ge 3 ; then\n    GDAL_GE_250=\"yes\"\n  fi\nfi\n\nGDAL_DATA_TEST_FILE=\"${GDAL_DATADIR}/pcs.csv\"\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking GDAL: ${GDAL_DATADIR}/pcs.csv readable\" >&5\nprintf %s \"checking GDAL: ${GDAL_DATADIR}/pcs.csv readable... \" >&6; }\nif test -r \"${GDAL_DATA_TEST_FILE}\" ; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\nelse\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\n  if test \"${GDAL_GE_250}\" = \"no\" ; then\n    as_fn_error $? \"pcs.csv not found in GDAL data directory.\" \"$LINENO\" 5\n  fi\nfi\n\n# Optional local copy of GDAL datadir and PROJ_LIB\n\ndata_copy=no\nif test \"${PROJ_GDAL_DATA_COPY}\" ; then\n    data_copy=yes\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: PROJ_GDAL_DATA_COPY used.\" >&5\nprintf \"%s\\n\" \"$as_me: PROJ_GDAL_DATA_COPY used.\" >&6;}\nelse\n\n# Check whether --with-data-copy was given.\nif test ${with_data_copy+y}\nthen :\n  withval=$with_data_copy; data_copy=$withval\nfi\n\nfi\nif test \"${data_copy}\" = \"yes\" ; then\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: Copy data for:\" >&5\nprintf \"%s\\n\" \"$as_me: Copy data for:\" >&6;}\n  proj_lib0=\"${PROJ_LIB}\"\n\n# Check whether --with-proj-data was given.\nif test ${with_proj_data+y}\nthen :\n  withval=$with_proj_data; proj_lib1=$withval\nfi\n\n  if test -n \"${proj_lib0}\" ; then\n    proj_lib=\"${proj_lib0}\"\n  else\n    proj_lib=\"${proj_lib1}\"\n  fi\n  if test -n \"${proj_lib}\" ; then\n    if test -d \"${proj_lib}\" ; then\n      cp -r \"${proj_lib}\" \"${R_PACKAGE_DIR}\"\n      { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}:   PROJ: ${proj_lib}\" >&5\nprintf \"%s\\n\" \"$as_me:   PROJ: ${proj_lib}\" >&6;}\n    else\n      as_fn_error $? \"PROJ data files not found; set environment variable PROJ_LIB=DIR or --with-proj-data=DIR.\" \"$LINENO\" 5\n    fi\n  else\n      as_fn_error $? \"PROJ data files not found; set environment variable PROJ_LIB=DIR or --with-proj-data=DIR.\" \"$LINENO\" 5\n  fi\n\n  if test -d \"${GDAL_DATADIR}\" ; then\n    cp -r \"${GDAL_DATADIR}\" \"${R_PACKAGE_DIR}\"\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}:   GDAL: ${GDAL_DATADIR}\" >&5\nprintf \"%s\\n\" \"$as_me:   GDAL: ${GDAL_DATADIR}\" >&6;}\n  else\n    as_fn_error $? \"GDAL data files not found.\" \"$LINENO\" 5\n  fi\nfi\n\n#\n# test whether PROJ is available to gdal:\n#\n\ngdal_has_proj=no\ncat > gdal_proj.cpp <<_EOCONF\n#include <gdal.h>\n#include <ogr_srs_api.h>\n#include <ogr_spatialref.h>\nint main(int argc, char *argv[]) {\n\tOGRSpatialReference *dest = new OGRSpatialReference;\n\tOGRSpatialReference *src = new OGRSpatialReference;\n    src->importFromEPSG(4326);\n    dest->importFromEPSG(3857);\n\tOGRCoordinateTransformation *ct = OGRCreateCoordinateTransformation(src, dest);\n\treturn(ct == NULL); // signals PROJ is not available through gdal\n}\n_EOCONF\n\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking GDAL: checking whether PROJ is available for linking:\" >&5\nprintf %s \"checking GDAL: checking whether PROJ is available for linking:... \" >&6; }\n${CXX} ${CPPFLAGS} -o gdal_proj gdal_proj.cpp ${LIBS} 2> errors.txt\nif test `echo $?` -ne 0 ; then\ngdal_has_proj=no\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nelse\ngdal_has_proj=yes\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\nfi\n\nif test \"${gdal_has_proj}\" = no; then\n   cat errors.txt\n   { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: Install failure: compilation and/or linkage problems.\" >&5\nprintf \"%s\\n\" \"$as_me: Install failure: compilation and/or linkage problems.\" >&6;}\n   as_fn_error $? \"cannot link projection code\" \"$LINENO\" 5\nfi\n\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking GDAL: checking whether PROJ is available for running:\" >&5\nprintf %s \"checking GDAL: checking whether PROJ is available for running:... \" >&6; }\nif test \"x$cross_compiling\" = \"xyes\"; then\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: cross compiling\" >&5\nprintf \"%s\\n\" \"cross compiling\" >&6; }\nelse\n./gdal_proj\nif test `echo $?` -ne 0 ; then\ngdal_has_proj=no\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nelse\ngdal_has_proj=yes\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\nfi\nif test \"${gdal_has_proj}\" = no; then\n   as_fn_error $? \"OGRCoordinateTransformation() does not return a coord.trans: PROJ not available?\" \"$LINENO\" 5\nfi\nfi\nrm -fr errors.txt gdal_proj.cpp gdal_proj\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: GDAL: ${GDAL_VERSION}\" >&5\nprintf \"%s\\n\" \"$as_me: GDAL: ${GDAL_VERSION}\" >&6;}\n\n\n# sqlite3\n\n# Check whether --with-sqlite3-lib was given.\nif test ${with_sqlite3_lib+y}\nthen :\n  withval=$with_sqlite3_lib; sqlite3_lib_path=$withval\nfi\n\nif test  -n \"$sqlite3_lib_path\"  ; then\n    SQLITE3_LIBS=\"-L${sqlite3_lib_path}\"\n\nfi\n\n\n#\n# PROJ\n#\n\nPROJ_CONFIG=\"pkg-config proj\"\n\nif `$PROJ_CONFIG --exists` ; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: pkg-config proj exists, will use it\" >&5\nprintf \"%s\\n\" \"$as_me: pkg-config proj exists, will use it\" >&6;}\n  proj_config_ok=yes\nelse\n  proj_config_ok=no\nfi\n\n\n# Check whether --with-proj-include was given.\nif test ${with_proj_include+y}\nthen :\n  withval=$with_proj_include; proj_include_path=$withval\nfi\n\nif test  -n \"$proj_include_path\"  ; then\n   PROJ_CPPFLAGS=\"-I${proj_include_path}\"\n\nelse\n  if test \"${proj_config_ok}\" = yes; then\n    PROJ_INCLUDE_PATH=`${PROJ_CONFIG} --cflags`\n    PROJ_CPPFLAGS=\"${PROJ_INCLUDE_PATH}\"\n\n  fi\nfi\n\n# honor PKG_xx overrides\n# for CPPFLAGS we will superfluously double R's flags\n# since we'll set PKG_CPPFLAGS with this, but that shouldn't hurt\n\n\n# Check whether --with-proj-api was given.\nif test ${with_proj_api+y}\nthen :\n  withval=$with_proj_api; proj_api=$withval\nfi\n\nPROJ6=\"no\"\nPROJH=\"no\"\nif test \"${proj_config_ok}\" = yes; then\n  PROJ_VERSION=`${PROJ_CONFIG} --modversion`\n  PROJV1=`echo \"${PROJ_VERSION}\" | cut -c 1`\n  if test \"${PROJV1}\" -ge 6; then\n    PROJ6=\"yes\"\n    PROJ_CPPFLAGS=\"${PROJ_CPPFLAGS} -DHAVE_PROJ_H\"\n    if test \"${proj_api}\" = yes; then\n        { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: using proj_api.h even with PROJ 5/6\" >&5\nprintf \"%s\\n\" \"$as_me: using proj_api.h even with PROJ 5/6\" >&6;}\n        PROJ_CPPFLAGS=\"${PROJ_CPPFLAGS} -DACCEPT_USE_OF_DEPRECATED_PROJ_API_H\"\n    else\n        { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: using proj.h.\" >&5\nprintf \"%s\\n\" \"$as_me: using proj.h.\" >&6;}\n        PROJH=\"yes\"\n    fi\n  fi\nelse\n  if test \"${PROJH}\" = no ; then\n    PROJH=yes\n           for ac_header in proj.h\ndo :\n  ac_fn_c_check_header_compile \"$LINENO\" \"proj.h\" \"ac_cv_header_proj_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_proj_h\" = xyes\nthen :\n  printf \"%s\\n\" \"#define HAVE_PROJ_H 1\" >>confdefs.h\n\nelse $as_nop\n  PROJH=no\nfi\n\ndone\n    if test \"${PROJH}\" = yes; then\n      PROJ6=\"yes\"\n      PROJ_CPPFLAGS=\"${PROJ_CPPFLAGS} -DHAVE_PROJ_H\"\n    fi\n  fi\nfi\n\nCPPFLAGS=\"${INCPPFLAGS} ${PKG_CPPFLAGS} ${PROJ_CPPFLAGS}\"\n\nif test \"${PROJH}\" = no\nthen\n  proj4ok=yes\n         for ac_header in proj_api.h\ndo :\n  ac_fn_c_check_header_compile \"$LINENO\" \"proj_api.h\" \"ac_cv_header_proj_api_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_proj_api_h\" = xyes\nthen :\n  printf \"%s\\n\" \"#define HAVE_PROJ_API_H 1\" >>confdefs.h\n\nelse $as_nop\n  proj4ok=no\nfi\n\ndone\n  if test \"${proj4ok}\" = no; then\n     as_fn_error $? \"proj_api.h not found in standard or given locations.\" \"$LINENO\" 5\n  fi\nfi\n\n# dnl ditto for a library path\n\n# Check whether --with-proj-lib was given.\nif test ${with_proj_lib+y}\nthen :\n  withval=$with_proj_lib; proj_lib_path=$withval\nfi\n\nif test  -n \"$proj_lib_path\"  ; then\n    PROJ_LIBS=\"-L${proj_lib_path} ${INPKG_LIBS} -lproj\"\n\nelse\n  if test \"${proj_config_ok}\" = yes; then\n    if test `uname` = \"Darwin\"; then\n      PROJ_LIB_PATH=`${PROJ_CONFIG} --libs --static`\n    else\n      PROJ_LIB_PATH=`${PROJ_CONFIG} --libs`\n    fi\n    PROJ_LIBS=\"${PROJ_LIB_PATH} ${INPKG_LIBS}\"\n\n\tproj_version=`${PROJ_CONFIG} --modversion`\n\t{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: PROJ: ${proj_version}\" >&5\nprintf \"%s\\n\" \"$as_me: PROJ: ${proj_version}\" >&6;}\n  else\n    PROJ_LIBS=\"${PKG_LIBS} -lproj\"\n  fi\nfi\n\nLIBS=\"${PROJ_LIBS} ${INLIBS} ${PKG_LIBS}\"\n\nif test \"${PROJH}\" = no; then\n  proj4ok=yes\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for pj_init_plus in -lproj\" >&5\nprintf %s \"checking for pj_init_plus in -lproj... \" >&6; }\nif test ${ac_cv_lib_proj_pj_init_plus+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  ac_check_lib_save_LIBS=$LIBS\nLIBS=\"-lproj  $LIBS\"\ncat confdefs.h - <<_ACEOF >conftest.$ac_ext\n/* end confdefs.h.  */\n\n/* Override any GCC internal prototype to avoid an error.\n   Use char because int might match the return type of a GCC\n   builtin and then its argument prototype would still apply.  */\nchar pj_init_plus ();\nint\nmain (void)\n{\nreturn pj_init_plus ();\n  ;\n  return 0;\n}\n_ACEOF\nif ac_fn_c_try_link \"$LINENO\"\nthen :\n  ac_cv_lib_proj_pj_init_plus=yes\nelse $as_nop\n  ac_cv_lib_proj_pj_init_plus=no\nfi\nrm -f core conftest.err conftest.$ac_objext conftest.beam \\\n    conftest$ac_exeext conftest.$ac_ext\nLIBS=$ac_check_lib_save_LIBS\nfi\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_proj_pj_init_plus\" >&5\nprintf \"%s\\n\" \"$ac_cv_lib_proj_pj_init_plus\" >&6; }\nif test \"x$ac_cv_lib_proj_pj_init_plus\" = xyes\nthen :\n  printf \"%s\\n\" \"#define HAVE_LIBPROJ 1\" >>confdefs.h\n\n  LIBS=\"-lproj $LIBS\"\n\nelse $as_nop\n  proj4ok=no\nfi\n\n  if test \"${proj4ok}\" = no; then\n     as_fn_error $? \"libproj not found in standard or given locations. ${GENERIC_INSTALL_MESSAGE}\" \"$LINENO\" 5\n  fi\ncat > proj_conf_test.c <<_EOCONF\n#include <stdio.h>\n#include <stdlib.h>\n#include <proj_api.h>\n\nint main(void) {\n    printf(\"%d\\n\", PJ_VERSION);\n    exit(0);\n}\n_EOCONF\nelse\ncat > proj_conf_test.cpp <<_EOCONF\n#include <stdio.h>\n#include <stdlib.h>\n#include <proj.h>\n\nint main(void) {\n\tproj_context_create();\n    exit(0);\n}\n_EOCONF\n  #AC_CHECK_LIB(proj,proj_context_create,,proj6ok=no)\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking PROJ: checking whether PROJ and sqlite3 are available for linking:\" >&5\nprintf %s \"checking PROJ: checking whether PROJ and sqlite3 are available for linking:... \" >&6; }\n  ${CXX} ${CPPFLAGS} -o proj_conf_test proj_conf_test.cpp ${LIBS} $SQLITE3_LIBS -lsqlite3 2> errors.txt\n  if test `echo $?` -ne 0 ; then\n    proj6ok=no\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\n  else\n    proj6ok=yes\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\n  fi\n  if test \"${proj6ok}\" = no; then\n     as_fn_error $? \"libproj or sqlite3 not found in standard or given locations. ${GENERIC_INSTALL_MESSAGE}\" \"$LINENO\" 5\n  fi\n\ncat > proj_conf_test.c <<_EOCONF\n#include <stdio.h>\n#include <stdlib.h>\n#include <proj.h>\n\nint main(void) {\n    printf(\"%d.%d.%d\\n\", PROJ_VERSION_MAJOR, PROJ_VERSION_MINOR, PROJ_VERSION_PATCH);\n    exit(0);\n}\n_EOCONF\nfi\n\n#AC_MSG_NOTICE([PKG_LIBS: ${PKG_LIBS}])\n\n${CC} ${CFLAGS} -o proj_conf_test proj_conf_test.c ${PROJ_LIBS}\n\nproj_version=`./proj_conf_test`\n\n\n# Check whether --with-proj-share was given.\nif test ${with_proj_share+y}\nthen :\n  withval=$with_proj_share; proj_share_path=$withval\nfi\n\nif test  -n \"$proj_share_path\"  ; then\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: PROJ_LIB: ${proj_share_path}\" >&5\nprintf \"%s\\n\" \"$as_me: PROJ_LIB: ${proj_share_path}\" >&6;}\nfi\n\nif test ${PROJ6} = \"no\"; then\n\ncat > proj_conf_test.c <<_EOCONF\n#include <stdio.h>\n#include <proj_api.h>\n#if PJ_VERSION <= 480\nFILE *pj_open_lib(projCtx, const char *, const char *);\n#endif\n\nint main(void) {\n#if PJ_VERSION <= 480\n    FILE *fp;\n#else\n    PAFile fp;\n#endif\n    projCtx ctx;\n    ctx = pj_get_default_ctx();\n    fp = pj_open_lib(ctx, \"epsg\", \"rb\");\n    if (fp == NULL) exit(1);\n#if PJ_VERSION <= 480\n    fclose(fp);\n#else\n    pj_ctx_fclose(ctx, fp);\n#endif\n    exit(0);\n}\n_EOCONF\n\n${CC} ${CFLAGS} -o proj_conf_test proj_conf_test.c ${PROJ_LIBS}\nif test  -n \"$proj_share_path\"  ; then\n  PROJ_LIB=\"${proj_share_path}\" ./proj_conf_test\n  proj_share=`echo $?`\nelse\n  ./proj_conf_test\n  proj_share=`echo $?`\nfi\n\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking PROJ: epsg found and readable\" >&5\nprintf %s \"checking PROJ: epsg found and readable... \" >&6; }\nif test ${proj_share} -eq 1 ; then\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\n    STOP=\"stop\"\nelse\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\nfi\n\nrm -f proj_conf_test.c proj_conf_test\n\nif test \"$STOP\" = \"stop\" ; then\n    echo \"Error: proj/epsg not found\"\n    echo \"Either install missing proj support files, for example\"\n    echo \"the proj-nad and proj-epsg RPMs on systems using RPMs,\"\n    echo \"or if installed but not autodetected, set PROJ_LIB to the\"\n    echo \"correct path, and if need be use the --with-proj-share=\"\n    echo \"configure argument.\"\n    exit 1\nfi\n\nelse # proj >= 6\n\nif test \"${PROJH}\" = no; then\n\ncat > proj_conf_test.c <<_EOCONF\n#include <stdio.h>\n#include <proj_api.h>\n\nint main(void) {\n    PAFile fp;\n    projCtx ctx;\n    ctx = pj_get_default_ctx();\n    fp = pj_open_lib(ctx, \"proj.db\", \"rb\");\n    if (fp == NULL) exit(1);\n    pj_ctx_fclose(ctx, fp);\n    exit(0);\n}\n_EOCONF\n\n${CC} ${CFLAGS} -o proj_conf_test proj_conf_test.c ${PROJ_LIBS}\nif test  -n \"$proj_share_path\"  ; then\n  PROJ_LIB=\"${proj_share_path}\" ./proj_conf_test\n  proj_share=`echo $?`\nelse\n  ./proj_conf_test\n  proj_share=`echo $?`\nfi\n\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking PROJ: proj.db found and readable\" >&5\nprintf %s \"checking PROJ: proj.db found and readable... \" >&6; }\nif test ${proj_share} -eq 1 ; then\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\n    STOP=\"stop\"\nelse\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\nfi\n\nrm -f proj_conf_test.c proj_conf_test\n\nif test \"$STOP\" = \"stop\" ; then\n    echo \"Error: proj/proj.db not found\"\n    echo \"Either install missing proj support files, set PROJ_LIB to the\"\n    echo \"correct path, and if need be use the --with-proj-share=\"\n    echo \"configure argument.\"\n    exit 1\nfi\n\ncat > proj_conf_test.c <<_EOCONF\n#include <stdio.h>\n#include <proj_api.h>\n#if PJ_VERSION <= 480\nFILE *pj_open_lib(projCtx, const char *, const char *);\n#endif\n\nint main(void) {\n#if PJ_VERSION <= 480\n    FILE *fp;\n#else\n    PAFile fp;\n#endif\n    projCtx ctx;\n    ctx = pj_get_default_ctx();\n    fp = pj_open_lib(ctx, \"conus\", \"rb\");\n    if (fp == NULL) exit(1);\n#if PJ_VERSION <= 480\n    fclose(fp);\n#else\n    pj_ctx_fclose(ctx, fp);\n#endif\n    exit(0);\n}\n_EOCONF\n\n${CC} ${CFLAGS} -o proj_conf_test proj_conf_test.c ${PROJ_LIBS}\nif test  -n \"$proj_share_path\"  ; then\n  PROJ_LIB=\"${proj_share_path}\" ./proj_conf_test\n  proj_share=`echo $?`\nelse\n  ./proj_conf_test\n  proj_share=`echo $?`\nfi\n\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking PROJ: conus found and readable\" >&5\nprintf %s \"checking PROJ: conus found and readable... \" >&6; }\nif test ${proj_share} -eq 1 ; then\n    WARN=\"warn\"\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nelse\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\nfi\n\nrm -f proj_conf_test.c proj_conf_test\n\nif test \"$WARN\" = \"warn\" ; then\n    echo \"Note: proj/conus not found\"\n    echo \"No support available in PROJ4 for NAD grid datum transformations\"\n    echo \"If required, consider re-installing from source with the contents\"\n    echo \"of proj-datumgrid-1.<latest>.zip from http://download.osgeo.org/proj/ in nad/.\"\nfi\n\nfi # PROJH = no\n\nfi # proj >= 6\n\n\n\n\n#\n# GEOS:\n#\nGEOS_CONFIG=\"geos-config\"\n\nGEOS_CONFIG_SET=\"no\"\n\n\n# Check whether --with-geos-config was given.\nif test ${with_geos_config+y}\nthen :\n  withval=$with_geos_config; geos_config=$withval\nfi\n\nif test  -n \"$geos_config\"  ; then\n    GEOS_CONFIG_SET=\"yes\"\n    GEOS_CONFIG=\"${geos_config}\"\n\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: geos-config set to $GEOS_CONFIG\" >&5\nprintf \"%s\\n\" \"$as_me: geos-config set to $GEOS_CONFIG\" >&6;}\nfi\n\nif test \"$GEOS_CONFIG_SET\" = \"no\" ; then\n  # Extract the first word of \"\"$GEOS_CONFIG\"\", so it can be a program name with args.\nset dummy \"$GEOS_CONFIG\"; ac_word=$2\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking for $ac_word\" >&5\nprintf %s \"checking for $ac_word... \" >&6; }\nif test ${ac_cv_path_GEOS_CONFIG+y}\nthen :\n  printf %s \"(cached) \" >&6\nelse $as_nop\n  case $GEOS_CONFIG in\n  [\\\\/]* | ?:[\\\\/]*)\n  ac_cv_path_GEOS_CONFIG=\"$GEOS_CONFIG\" # Let the user override the test with a path.\n  ;;\n  *)\n  as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    for ac_exec_ext in '' $ac_executable_extensions; do\n  if as_fn_executable_p \"$as_dir$ac_word$ac_exec_ext\"; then\n    ac_cv_path_GEOS_CONFIG=\"$as_dir$ac_word$ac_exec_ext\"\n    printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: found $as_dir$ac_word$ac_exec_ext\" >&5\n    break 2\n  fi\ndone\n  done\nIFS=$as_save_IFS\n\n  test -z \"$ac_cv_path_GEOS_CONFIG\" && ac_cv_path_GEOS_CONFIG=\"\"no\"\"\n  ;;\nesac\nfi\nGEOS_CONFIG=$ac_cv_path_GEOS_CONFIG\nif test -n \"$GEOS_CONFIG\"; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: $GEOS_CONFIG\" >&5\nprintf \"%s\\n\" \"$GEOS_CONFIG\" >&6; }\nelse\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nfi\n\n\n  if test \"$GEOS_CONFIG\" = \"no\" ; then\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\n    as_fn_error $? \"geos-config not found or not executable. ${GENERIC_INSTALL_MESSAGE}\" \"$LINENO\" 5\n  fi\nelse\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking geos-config exists\" >&5\nprintf %s \"checking geos-config exists... \" >&6; }\n  if test -r \"${GEOS_CONFIG}\"; then\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\n  else\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\n    as_fn_error $? \"geos-config not found - configure argument error. ${GENERIC_INSTALL_MESSAGE}\" \"$LINENO\" 5\n  fi\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking geos-config executable\" >&5\nprintf %s \"checking geos-config executable... \" >&6; }\n  if test -x \"${GEOS_CONFIG}\"; then\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\n  else\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\n    as_fn_error $? \"geos-config not executable. ${GENERIC_INSTALL_MESSAGE}\" \"$LINENO\" 5\n  fi\nfi\n\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking geos-config usability\" >&5\nprintf %s \"checking geos-config usability... \" >&6; }\nif test `${GEOS_CONFIG} --version`\nthen\n  GEOS_CLIBS=\"`${GEOS_CONFIG} --clibs`\"\n  #GEOS_DEP_CLIBS=`geos-config --static-clibs` -- this gives -m instead of -lm, which breaks clang\n  # fixed in 3.7.0 at https://github.com/libgeos/libgeos/pull/73#issuecomment-262208677\n  GEOS_DEP_CLIBS=`${GEOS_CONFIG} --static-clibs | sed 's/-m/-lm/g'`\n  GEOS_CPPFLAGS=`${GEOS_CONFIG} --cflags`\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\nelse\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\n  as_fn_error $? \"${GEOS_CONFIG} not usable\" \"$LINENO\" 5\nfi\n\nGEOS_VERSION=`${GEOS_CONFIG} --version`\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: GEOS: ${GEOS_VERSION}\" >&5\nprintf \"%s\\n\" \"$as_me: GEOS: ${GEOS_VERSION}\" >&6;}\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking GEOS version >= 3.4.0\" >&5\nprintf %s \"checking GEOS version >= 3.4.0... \" >&6; } # GDAL 2.0.1 requires GEOS 3.1.0\nGEOS_VER_DOT=`echo $GEOS_VERSION | tr -d \".[:alpha:]\"`\nif test ${GEOS_VER_DOT} -lt 340 ; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\n  as_fn_error $? \"upgrade GEOS to 3.4.0 or later\" \"$LINENO\" 5\nelse\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\nfi\n\nPKG_CPPFLAGS=\"${INPKG_CPPFLAGS} ${PROJ_CPPFLAGS} ${GDAL_CPPFLAGS} ${GEOS_CPPFLAGS}\"\n\nPKG_LIBS=\"${INPKG_LIBS} ${GDAL_LIBS}\"\n\nif test \"${NEED_DEPS}\" = yes; then\n   PKG_LIBS=\"${PKG_LIBS} ${GDAL_DEP_LIBS}\"\n\nfi\n\n# honor PKG_xx overrides\n# for CPPFLAGS we will superfluously double R's flags\n# since we'll set PKG_CPPFLAGS with this, but that shouldn't hurt\nCPPFLAGS=\"${CPPFLAGS} ${PKG_CPPFLAGS}\"\nLIBS=\"${LIBS} ${PKG_LIBS}\"\n\ngeosok=yes\n       for ac_header in geos_c.h\ndo :\n  ac_fn_c_check_header_compile \"$LINENO\" \"geos_c.h\" \"ac_cv_header_geos_c_h\" \"$ac_includes_default\"\nif test \"x$ac_cv_header_geos_c_h\" = xyes\nthen :\n  printf \"%s\\n\" \"#define HAVE_GEOS_C_H 1\" >>confdefs.h\n\nelse $as_nop\n  geosok=no\nfi\n\ndone\nif test \"${geosok}\" = no; then\n   as_fn_error $? \"geos_c.h not found in given locations. ${GENERIC_INSTALL_MESSAGE}\" \"$LINENO\" 5\nfi\n\ncat > geos_test.cpp <<_EOCONF\n#include <geos_c.h>\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nstatic void __errorHandler(const char *fmt, ...) {\n    return;\n}\nstatic void __warningHandler(const char *fmt, ...) {\n    return;\n}\nint main(void) {\n    GEOSContextHandle_t r = initGEOS_r((GEOSMessageHandler) __warningHandler, (GEOSMessageHandler) __errorHandler);\n    finishGEOS_r(r);\n}\n#ifdef __cplusplus\n}\n#endif\n_EOCONF\n\n#echo \"${CXX} ${CPPFLAGS} -o geos_test geos_test.cpp ${LIBS}\"\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking geos: linking with ${GEOS_CLIBS}\" >&5\nprintf %s \"checking geos: linking with ${GEOS_CLIBS}... \" >&6; }\n${CXX} ${CPPFLAGS} -o geos_test geos_test.cpp ${GEOS_CLIBS} 2> errors.txt\nif test `echo $?` -ne 0 ; then\n geosok=no\n { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\nelse\n PKG_LIBS=\"${PKG_LIBS} ${GEOS_CLIBS}\"\n\n { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\nfi\n\nif test \"${geosok}\" = no; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: checking geos: linking with ${GEOS_DEP_CLIBS}\" >&5\nprintf %s \"checking geos: linking with ${GEOS_DEP_CLIBS}... \" >&6; }\n  ${CXX} ${CPPFLAGS} -o geos_test geos_test.cpp ${GEOS_DEP_CLIBS} 2> errors.txt\n  if test `echo $?` -ne 0 ; then\n    geosok=no\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: no\" >&5\nprintf \"%s\\n\" \"no\" >&6; }\n    cat errors.txt\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: Install failure: compilation and/or linkage problems.\" >&5\nprintf \"%s\\n\" \"$as_me: Install failure: compilation and/or linkage problems.\" >&6;}\n    as_fn_error $? \"initGEOS_r not found in libgeos_c. ${GENERIC_INSTALL_MESSAGE}\" \"$LINENO\" 5\n  else\n    PKG_LIBS=\"${PKG_LIBS} ${GEOS_DEP_CLIBS}\"\n\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: result: yes\" >&5\nprintf \"%s\\n\" \"yes\" >&6; }\n  fi\nfi\n\nrm -f geos_test errors.txt geos_test.cpp\n\n#\n# add PROJ_LIBS\n#\nPKG_LIBS=\"${PROJ_LIBS} ${PKG_LIBS}\"\n\n\n#\n# concluding substitution\n#\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: Package CPP flags: ${PKG_CPPFLAGS}\" >&5\nprintf \"%s\\n\" \"$as_me: Package CPP flags: ${PKG_CPPFLAGS}\" >&6;}\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: Package LIBS: ${PKG_LIBS}\" >&5\nprintf \"%s\\n\" \"$as_me: Package LIBS: ${PKG_LIBS}\" >&6;}\n\nac_config_files=\"$ac_config_files src/Makevars\"\n\ncat >confcache <<\\_ACEOF\n# This file is a shell script that caches the results of configure\n# tests run on this system so they can be shared between configure\n# scripts and configure runs, see configure's option --config-cache.\n# It is not useful on other systems.  If it contains results you don't\n# want to keep, you may remove or edit it.\n#\n# config.status only pays attention to the cache file if you give it\n# the --recheck option to rerun configure.\n#\n# `ac_cv_env_foo' variables (set or unset) will be overridden when\n# loading this file, other *unset* `ac_cv_foo' will be assigned the\n# following values.\n\n_ACEOF\n\n# The following way of writing the cache mishandles newlines in values,\n# but we know of no workaround that is simple, portable, and efficient.\n# So, we kill variables containing newlines.\n# Ultrix sh set writes to stderr and can't be redirected directly,\n# and sets the high bit in the cache file unless we assign to the vars.\n(\n  for ac_var in `(set) 2>&1 | sed -n 's/^\\([a-zA-Z_][a-zA-Z0-9_]*\\)=.*/\\1/p'`; do\n    eval ac_val=\\$$ac_var\n    case $ac_val in #(\n    *${as_nl}*)\n      case $ac_var in #(\n      *_cv_*) { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline\" >&5\nprintf \"%s\\n\" \"$as_me: WARNING: cache variable $ac_var contains a newline\" >&2;} ;;\n      esac\n      case $ac_var in #(\n      _ | IFS | as_nl) ;; #(\n      BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(\n      *) { eval $ac_var=; unset $ac_var;} ;;\n      esac ;;\n    esac\n  done\n\n  (set) 2>&1 |\n    case $as_nl`(ac_space=' '; set) 2>&1` in #(\n    *${as_nl}ac_space=\\ *)\n      # `set' does not quote correctly, so add quotes: double-quote\n      # substitution turns \\\\\\\\ into \\\\, and sed turns \\\\ into \\.\n      sed -n \\\n\t\"s/'/'\\\\\\\\''/g;\n\t  s/^\\\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\\\)=\\\\(.*\\\\)/\\\\1='\\\\2'/p\"\n      ;; #(\n    *)\n      # `set' quotes correctly as required by POSIX, so do not add quotes.\n      sed -n \"/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p\"\n      ;;\n    esac |\n    sort\n) |\n  sed '\n     /^ac_cv_env_/b end\n     t clear\n     :clear\n     s/^\\([^=]*\\)=\\(.*[{}].*\\)$/test ${\\1+y} || &/\n     t end\n     s/^\\([^=]*\\)=\\(.*\\)$/\\1=${\\1=\\2}/\n     :end' >>confcache\nif diff \"$cache_file\" confcache >/dev/null 2>&1; then :; else\n  if test -w \"$cache_file\"; then\n    if test \"x$cache_file\" != \"x/dev/null\"; then\n      { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: updating cache $cache_file\" >&5\nprintf \"%s\\n\" \"$as_me: updating cache $cache_file\" >&6;}\n      if test ! -f \"$cache_file\" || test -h \"$cache_file\"; then\n\tcat confcache >\"$cache_file\"\n      else\n        case $cache_file in #(\n        */* | ?:*)\n\t  mv -f confcache \"$cache_file\"$$ &&\n\t  mv -f \"$cache_file\"$$ \"$cache_file\" ;; #(\n        *)\n\t  mv -f confcache \"$cache_file\" ;;\n\tesac\n      fi\n    fi\n  else\n    { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file\" >&5\nprintf \"%s\\n\" \"$as_me: not updating unwritable cache $cache_file\" >&6;}\n  fi\nfi\nrm -f confcache\n\ntest \"x$prefix\" = xNONE && prefix=$ac_default_prefix\n# Let make expand exec_prefix.\ntest \"x$exec_prefix\" = xNONE && exec_prefix='${prefix}'\n\n# Transform confdefs.h into DEFS.\n# Protect against shell expansion while executing Makefile rules.\n# Protect against Makefile macro expansion.\n#\n# If the first sed substitution is executed (which looks for macros that\n# take arguments), then branch to the quote section.  Otherwise,\n# look for a macro that doesn't take arguments.\nac_script='\n:mline\n/\\\\$/{\n N\n s,\\\\\\n,,\n b mline\n}\nt clear\n:clear\ns/^[\t ]*#[\t ]*define[\t ][\t ]*\\([^\t (][^\t (]*([^)]*)\\)[\t ]*\\(.*\\)/-D\\1=\\2/g\nt quote\ns/^[\t ]*#[\t ]*define[\t ][\t ]*\\([^\t ][^\t ]*\\)[\t ]*\\(.*\\)/-D\\1=\\2/g\nt quote\nb any\n:quote\ns/[\t `~#$^&*(){}\\\\|;'\\''\"<>?]/\\\\&/g\ns/\\[/\\\\&/g\ns/\\]/\\\\&/g\ns/\\$/$$/g\nH\n:any\n${\n\tg\n\ts/^\\n//\n\ts/\\n/ /g\n\tp\n}\n'\nDEFS=`sed -n \"$ac_script\" confdefs.h`\n\n\nac_libobjs=\nac_ltlibobjs=\nU=\nfor ac_i in : $LIBOBJS; do test \"x$ac_i\" = x: && continue\n  # 1. Remove the extension, and $U if already installed.\n  ac_script='s/\\$U\\././;s/\\.o$//;s/\\.obj$//'\n  ac_i=`printf \"%s\\n\" \"$ac_i\" | sed \"$ac_script\"`\n  # 2. Prepend LIBOBJDIR.  When used with automake>=1.10 LIBOBJDIR\n  #    will be set to the directory where LIBOBJS objects are built.\n  as_fn_append ac_libobjs \" \\${LIBOBJDIR}$ac_i\\$U.$ac_objext\"\n  as_fn_append ac_ltlibobjs \" \\${LIBOBJDIR}$ac_i\"'$U.lo'\ndone\nLIBOBJS=$ac_libobjs\n\nLTLIBOBJS=$ac_ltlibobjs\n\n\n\n: \"${CONFIG_STATUS=./config.status}\"\nac_write_fail=0\nac_clean_files_save=$ac_clean_files\nac_clean_files=\"$ac_clean_files $CONFIG_STATUS\"\n{ printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS\" >&5\nprintf \"%s\\n\" \"$as_me: creating $CONFIG_STATUS\" >&6;}\nas_write_fail=0\ncat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1\n#! $SHELL\n# Generated by $as_me.\n# Run this file to recreate the current configuration.\n# Compiler output produced by configure, useful for debugging\n# configure, is in config.log if it exists.\n\ndebug=false\nac_cs_recheck=false\nac_cs_silent=false\n\nSHELL=\\${CONFIG_SHELL-$SHELL}\nexport SHELL\n_ASEOF\ncat >>$CONFIG_STATUS <<\\_ASEOF || as_write_fail=1\n## -------------------- ##\n## M4sh Initialization. ##\n## -------------------- ##\n\n# Be more Bourne compatible\nDUALCASE=1; export DUALCASE # for MKS sh\nas_nop=:\nif test ${ZSH_VERSION+y} && (emulate sh) >/dev/null 2>&1\nthen :\n  emulate sh\n  NULLCMD=:\n  # Pre-4.2 versions of Zsh do word splitting on ${1+\"$@\"}, which\n  # is contrary to our usage.  Disable this feature.\n  alias -g '${1+\"$@\"}'='\"$@\"'\n  setopt NO_GLOB_SUBST\nelse $as_nop\n  case `(set -o) 2>/dev/null` in #(\n  *posix*) :\n    set -o posix ;; #(\n  *) :\n     ;;\nesac\nfi\n\n\n\n# Reset variables that may have inherited troublesome values from\n# the environment.\n\n# IFS needs to be set, to space, tab, and newline, in precisely that order.\n# (If _AS_PATH_WALK were called with IFS unset, it would have the\n# side effect of setting IFS to empty, thus disabling word splitting.)\n# Quoting is to prevent editors from complaining about space-tab.\nas_nl='\n'\nexport as_nl\nIFS=\" \"\"\t$as_nl\"\n\nPS1='$ '\nPS2='> '\nPS4='+ '\n\n# Ensure predictable behavior from utilities with locale-dependent output.\nLC_ALL=C\nexport LC_ALL\nLANGUAGE=C\nexport LANGUAGE\n\n# We cannot yet rely on \"unset\" to work, but we need these variables\n# to be unset--not just set to an empty or harmless value--now, to\n# avoid bugs in old shells (e.g. pre-3.0 UWIN ksh).  This construct\n# also avoids known problems related to \"unset\" and subshell syntax\n# in other old shells (e.g. bash 2.01 and pdksh 5.2.14).\nfor as_var in BASH_ENV ENV MAIL MAILPATH CDPATH\ndo eval test \\${$as_var+y} \\\n  && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :\ndone\n\n# Ensure that fds 0, 1, and 2 are open.\nif (exec 3>&0) 2>/dev/null; then :; else exec 0</dev/null; fi\nif (exec 3>&1) 2>/dev/null; then :; else exec 1>/dev/null; fi\nif (exec 3>&2)            ; then :; else exec 2>/dev/null; fi\n\n# The user is always right.\nif ${PATH_SEPARATOR+false} :; then\n  PATH_SEPARATOR=:\n  (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {\n    (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||\n      PATH_SEPARATOR=';'\n  }\nfi\n\n\n# Find who we are.  Look in the path if we contain no directory separator.\nas_myself=\ncase $0 in #((\n  *[\\\\/]* ) as_myself=$0 ;;\n  *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR\nfor as_dir in $PATH\ndo\n  IFS=$as_save_IFS\n  case $as_dir in #(((\n    '') as_dir=./ ;;\n    */) ;;\n    *) as_dir=$as_dir/ ;;\n  esac\n    test -r \"$as_dir$0\" && as_myself=$as_dir$0 && break\n  done\nIFS=$as_save_IFS\n\n     ;;\nesac\n# We did not find ourselves, most probably we were run as `sh COMMAND'\n# in which case we are not to be found in the path.\nif test \"x$as_myself\" = x; then\n  as_myself=$0\nfi\nif test ! -f \"$as_myself\"; then\n  printf \"%s\\n\" \"$as_myself: error: cannot find myself; rerun with an absolute file name\" >&2\n  exit 1\nfi\n\n\n\n# as_fn_error STATUS ERROR [LINENO LOG_FD]\n# ----------------------------------------\n# Output \"`basename $0`: error: ERROR\" to stderr. If LINENO and LOG_FD are\n# provided, also output the error to LOG_FD, referencing LINENO. Then exit the\n# script with STATUS, using 1 if that was 0.\nas_fn_error ()\n{\n  as_status=$1; test $as_status -eq 0 && as_status=1\n  if test \"$4\"; then\n    as_lineno=${as_lineno-\"$3\"} as_lineno_stack=as_lineno_stack=$as_lineno_stack\n    printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: error: $2\" >&$4\n  fi\n  printf \"%s\\n\" \"$as_me: error: $2\" >&2\n  as_fn_exit $as_status\n} # as_fn_error\n\n\n\n# as_fn_set_status STATUS\n# -----------------------\n# Set $? to STATUS, without forking.\nas_fn_set_status ()\n{\n  return $1\n} # as_fn_set_status\n\n# as_fn_exit STATUS\n# -----------------\n# Exit the shell with STATUS, even in a \"trap 0\" or \"set -e\" context.\nas_fn_exit ()\n{\n  set +e\n  as_fn_set_status $1\n  exit $1\n} # as_fn_exit\n\n# as_fn_unset VAR\n# ---------------\n# Portably unset VAR.\nas_fn_unset ()\n{\n  { eval $1=; unset $1;}\n}\nas_unset=as_fn_unset\n\n# as_fn_append VAR VALUE\n# ----------------------\n# Append the text in VALUE to the end of the definition contained in VAR. Take\n# advantage of any shell optimizations that allow amortized linear growth over\n# repeated appends, instead of the typical quadratic growth present in naive\n# implementations.\nif (eval \"as_var=1; as_var+=2; test x\\$as_var = x12\") 2>/dev/null\nthen :\n  eval 'as_fn_append ()\n  {\n    eval $1+=\\$2\n  }'\nelse $as_nop\n  as_fn_append ()\n  {\n    eval $1=\\$$1\\$2\n  }\nfi # as_fn_append\n\n# as_fn_arith ARG...\n# ------------------\n# Perform arithmetic evaluation on the ARGs, and store the result in the\n# global $as_val. Take advantage of shells that can avoid forks. The arguments\n# must be portable across $(()) and expr.\nif (eval \"test \\$(( 1 + 1 )) = 2\") 2>/dev/null\nthen :\n  eval 'as_fn_arith ()\n  {\n    as_val=$(( $* ))\n  }'\nelse $as_nop\n  as_fn_arith ()\n  {\n    as_val=`expr \"$@\" || test $? -eq 1`\n  }\nfi # as_fn_arith\n\n\nif expr a : '\\(a\\)' >/dev/null 2>&1 &&\n   test \"X`expr 00001 : '.*\\(...\\)'`\" = X001; then\n  as_expr=expr\nelse\n  as_expr=false\nfi\n\nif (basename -- /) >/dev/null 2>&1 && test \"X`basename -- / 2>&1`\" = \"X/\"; then\n  as_basename=basename\nelse\n  as_basename=false\nfi\n\nif (as_dir=`dirname -- /` && test \"X$as_dir\" = X/) >/dev/null 2>&1; then\n  as_dirname=dirname\nelse\n  as_dirname=false\nfi\n\nas_me=`$as_basename -- \"$0\" ||\n$as_expr X/\"$0\" : '.*/\\([^/][^/]*\\)/*$' \\| \\\n\t X\"$0\" : 'X\\(//\\)$' \\| \\\n\t X\"$0\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf \"%s\\n\" X/\"$0\" |\n    sed '/^.*\\/\\([^/][^/]*\\)\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\/\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n\n# Avoid depending upon Character Ranges.\nas_cr_letters='abcdefghijklmnopqrstuvwxyz'\nas_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'\nas_cr_Letters=$as_cr_letters$as_cr_LETTERS\nas_cr_digits='0123456789'\nas_cr_alnum=$as_cr_Letters$as_cr_digits\n\n\n# Determine whether it's possible to make 'echo' print without a newline.\n# These variables are no longer used directly by Autoconf, but are AC_SUBSTed\n# for compatibility with existing Makefiles.\nECHO_C= ECHO_N= ECHO_T=\ncase `echo -n x` in #(((((\n-n*)\n  case `echo 'xy\\c'` in\n  *c*) ECHO_T='\t';;\t# ECHO_T is single tab character.\n  xy)  ECHO_C='\\c';;\n  *)   echo `echo ksh88 bug on AIX 6.1` > /dev/null\n       ECHO_T='\t';;\n  esac;;\n*)\n  ECHO_N='-n';;\nesac\n\n# For backward compatibility with old third-party macros, we provide\n# the shell variables $as_echo and $as_echo_n.  New code should use\n# AS_ECHO([\"message\"]) and AS_ECHO_N([\"message\"]), respectively.\nas_echo='printf %s\\n'\nas_echo_n='printf %s'\n\nrm -f conf$$ conf$$.exe conf$$.file\nif test -d conf$$.dir; then\n  rm -f conf$$.dir/conf$$.file\nelse\n  rm -f conf$$.dir\n  mkdir conf$$.dir 2>/dev/null\nfi\nif (echo >conf$$.file) 2>/dev/null; then\n  if ln -s conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s='ln -s'\n    # ... but there are two gotchas:\n    # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.\n    # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.\n    # In both cases, we have to default to `cp -pR'.\n    ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||\n      as_ln_s='cp -pR'\n  elif ln conf$$.file conf$$ 2>/dev/null; then\n    as_ln_s=ln\n  else\n    as_ln_s='cp -pR'\n  fi\nelse\n  as_ln_s='cp -pR'\nfi\nrm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file\nrmdir conf$$.dir 2>/dev/null\n\n\n# as_fn_mkdir_p\n# -------------\n# Create \"$as_dir\" as a directory, including parents if necessary.\nas_fn_mkdir_p ()\n{\n\n  case $as_dir in #(\n  -*) as_dir=./$as_dir;;\n  esac\n  test -d \"$as_dir\" || eval $as_mkdir_p || {\n    as_dirs=\n    while :; do\n      case $as_dir in #(\n      *\\'*) as_qdir=`printf \"%s\\n\" \"$as_dir\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; #'(\n      *) as_qdir=$as_dir;;\n      esac\n      as_dirs=\"'$as_qdir' $as_dirs\"\n      as_dir=`$as_dirname -- \"$as_dir\" ||\n$as_expr X\"$as_dir\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$as_dir\" : 'X\\(//\\)$' \\| \\\n\t X\"$as_dir\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf \"%s\\n\" X\"$as_dir\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n      test -d \"$as_dir\" && break\n    done\n    test -z \"$as_dirs\" || eval \"mkdir $as_dirs\"\n  } || test -d \"$as_dir\" || as_fn_error $? \"cannot create directory $as_dir\"\n\n\n} # as_fn_mkdir_p\nif mkdir -p . 2>/dev/null; then\n  as_mkdir_p='mkdir -p \"$as_dir\"'\nelse\n  test -d ./-p && rmdir ./-p\n  as_mkdir_p=false\nfi\n\n\n# as_fn_executable_p FILE\n# -----------------------\n# Test if FILE is an executable regular file.\nas_fn_executable_p ()\n{\n  test -f \"$1\" && test -x \"$1\"\n} # as_fn_executable_p\nas_test_x='test -x'\nas_executable_p=as_fn_executable_p\n\n# Sed expression to map a string onto a valid CPP name.\nas_tr_cpp=\"eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'\"\n\n# Sed expression to map a string onto a valid variable name.\nas_tr_sh=\"eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'\"\n\n\nexec 6>&1\n## ----------------------------------- ##\n## Main body of $CONFIG_STATUS script. ##\n## ----------------------------------- ##\n_ASEOF\ntest $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n# Save the log message, to keep $0 and so on meaningful, and to\n# report actual input values of CONFIG_FILES etc. instead of their\n# values after options handling.\nac_log=\"\nThis file was extended by $as_me, which was\ngenerated by GNU Autoconf 2.71.  Invocation command line was\n\n  CONFIG_FILES    = $CONFIG_FILES\n  CONFIG_HEADERS  = $CONFIG_HEADERS\n  CONFIG_LINKS    = $CONFIG_LINKS\n  CONFIG_COMMANDS = $CONFIG_COMMANDS\n  $ $0 $@\n\non `(hostname || uname -n) 2>/dev/null | sed 1q`\n\"\n\n_ACEOF\n\ncase $ac_config_files in *\"\n\"*) set x $ac_config_files; shift; ac_config_files=$*;;\nesac\n\n\n\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n# Files that config.status was made for.\nconfig_files=\"$ac_config_files\"\n\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nac_cs_usage=\"\\\n\\`$as_me' instantiates files and other configuration actions\nfrom templates according to the current configuration.  Unless the files\nand actions are specified as TAGs, all are instantiated by default.\n\nUsage: $0 [OPTION]... [TAG]...\n\n  -h, --help       print this help, then exit\n  -V, --version    print version number and configuration settings, then exit\n      --config     print configuration, then exit\n  -q, --quiet, --silent\n                   do not print progress messages\n  -d, --debug      don't remove temporary files\n      --recheck    update $as_me by reconfiguring in the same conditions\n      --file=FILE[:TEMPLATE]\n                   instantiate the configuration file FILE\n\nConfiguration files:\n$config_files\n\nReport bugs to the package provider.\"\n\n_ACEOF\nac_cs_config=`printf \"%s\\n\" \"$ac_configure_args\" | sed \"$ac_safe_unquote\"`\nac_cs_config_escaped=`printf \"%s\\n\" \"$ac_cs_config\" | sed \"s/^ //; s/'/'\\\\\\\\\\\\\\\\''/g\"`\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\nac_cs_config='$ac_cs_config_escaped'\nac_cs_version=\"\\\\\nconfig.status\nconfigured by $0, generated by GNU Autoconf 2.71,\n  with options \\\\\"\\$ac_cs_config\\\\\"\n\nCopyright (C) 2021 Free Software Foundation, Inc.\nThis config.status script is free software; the Free Software Foundation\ngives unlimited permission to copy, distribute and modify it.\"\n\nac_pwd='$ac_pwd'\nsrcdir='$srcdir'\ntest -n \"\\$AWK\" || AWK=awk\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n# The default lists apply if the user does not specify any file.\nac_need_defaults=:\nwhile test $# != 0\ndo\n  case $1 in\n  --*=?*)\n    ac_option=`expr \"X$1\" : 'X\\([^=]*\\)='`\n    ac_optarg=`expr \"X$1\" : 'X[^=]*=\\(.*\\)'`\n    ac_shift=:\n    ;;\n  --*=)\n    ac_option=`expr \"X$1\" : 'X\\([^=]*\\)='`\n    ac_optarg=\n    ac_shift=:\n    ;;\n  *)\n    ac_option=$1\n    ac_optarg=$2\n    ac_shift=shift\n    ;;\n  esac\n\n  case $ac_option in\n  # Handling of the options.\n  -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)\n    ac_cs_recheck=: ;;\n  --version | --versio | --versi | --vers | --ver | --ve | --v | -V )\n    printf \"%s\\n\" \"$ac_cs_version\"; exit ;;\n  --config | --confi | --conf | --con | --co | --c )\n    printf \"%s\\n\" \"$ac_cs_config\"; exit ;;\n  --debug | --debu | --deb | --de | --d | -d )\n    debug=: ;;\n  --file | --fil | --fi | --f )\n    $ac_shift\n    case $ac_optarg in\n    *\\'*) ac_optarg=`printf \"%s\\n\" \"$ac_optarg\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"` ;;\n    '') as_fn_error $? \"missing file argument\" ;;\n    esac\n    as_fn_append CONFIG_FILES \" '$ac_optarg'\"\n    ac_need_defaults=false;;\n  --he | --h |  --help | --hel | -h )\n    printf \"%s\\n\" \"$ac_cs_usage\"; exit ;;\n  -q | -quiet | --quiet | --quie | --qui | --qu | --q \\\n  | -silent | --silent | --silen | --sile | --sil | --si | --s)\n    ac_cs_silent=: ;;\n\n  # This is an error.\n  -*) as_fn_error $? \"unrecognized option: \\`$1'\nTry \\`$0 --help' for more information.\" ;;\n\n  *) as_fn_append ac_config_targets \" $1\"\n     ac_need_defaults=false ;;\n\n  esac\n  shift\ndone\n\nac_configure_extra_args=\n\nif $ac_cs_silent; then\n  exec 6>/dev/null\n  ac_configure_extra_args=\"$ac_configure_extra_args --silent\"\nfi\n\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\nif \\$ac_cs_recheck; then\n  set X $SHELL '$0' $ac_configure_args \\$ac_configure_extra_args --no-create --no-recursion\n  shift\n  \\printf \"%s\\n\" \"running CONFIG_SHELL=$SHELL \\$*\" >&6\n  CONFIG_SHELL='$SHELL'\n  export CONFIG_SHELL\n  exec \"\\$@\"\nfi\n\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nexec 5>>config.log\n{\n  echo\n  sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX\n## Running $as_me. ##\n_ASBOX\n  printf \"%s\\n\" \"$ac_log\"\n} >&5\n\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n\n# Handling of arguments.\nfor ac_config_target in $ac_config_targets\ndo\n  case $ac_config_target in\n    \"src/Makevars\") CONFIG_FILES=\"$CONFIG_FILES src/Makevars\" ;;\n\n  *) as_fn_error $? \"invalid argument: \\`$ac_config_target'\" \"$LINENO\" 5;;\n  esac\ndone\n\n\n# If the user did not use the arguments to specify the items to instantiate,\n# then the envvar interface is used.  Set only those that are not.\n# We use the long form for the default assignment because of an extremely\n# bizarre bug on SunOS 4.1.3.\nif $ac_need_defaults; then\n  test ${CONFIG_FILES+y} || CONFIG_FILES=$config_files\nfi\n\n# Have a temporary directory for convenience.  Make it in the build tree\n# simply because there is no reason against having it here, and in addition,\n# creating and moving files from /tmp can sometimes cause problems.\n# Hook for its removal unless debugging.\n# Note that there is a small window in which the directory will not be cleaned:\n# after its creation but before its name has been assigned to `$tmp'.\n$debug ||\n{\n  tmp= ac_tmp=\n  trap 'exit_status=$?\n  : \"${ac_tmp:=$tmp}\"\n  { test ! -d \"$ac_tmp\" || rm -fr \"$ac_tmp\"; } && exit $exit_status\n' 0\n  trap 'as_fn_exit 1' 1 2 13 15\n}\n# Create a (secure) tmp directory for tmp files.\n\n{\n  tmp=`(umask 077 && mktemp -d \"./confXXXXXX\") 2>/dev/null` &&\n  test -d \"$tmp\"\n}  ||\n{\n  tmp=./conf$$-$RANDOM\n  (umask 077 && mkdir \"$tmp\")\n} || as_fn_error $? \"cannot create a temporary directory in .\" \"$LINENO\" 5\nac_tmp=$tmp\n\n# Set up the scripts for CONFIG_FILES section.\n# No need to generate them if there are no CONFIG_FILES.\n# This happens for instance with `./config.status config.h'.\nif test -n \"$CONFIG_FILES\"; then\n\n\nac_cr=`echo X | tr X '\\015'`\n# On cygwin, bash can eat \\r inside `` if the user requested igncr.\n# But we know of no other shell where ac_cr would be empty at this\n# point, so we can use a bashism as a fallback.\nif test \"x$ac_cr\" = x; then\n  eval ac_cr=\\$\\'\\\\r\\'\nfi\nac_cs_awk_cr=`$AWK 'BEGIN { print \"a\\rb\" }' </dev/null 2>/dev/null`\nif test \"$ac_cs_awk_cr\" = \"a${ac_cr}b\"; then\n  ac_cs_awk_cr='\\\\r'\nelse\n  ac_cs_awk_cr=$ac_cr\nfi\n\necho 'BEGIN {' >\"$ac_tmp/subs1.awk\" &&\n_ACEOF\n\n\n{\n  echo \"cat >conf$$subs.awk <<_ACEOF\" &&\n  echo \"$ac_subst_vars\" | sed 's/.*/&!$&$ac_delim/' &&\n  echo \"_ACEOF\"\n} >conf$$subs.sh ||\n  as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\nac_delim_num=`echo \"$ac_subst_vars\" | grep -c '^'`\nac_delim='%!_!# '\nfor ac_last_try in false false false false false :; do\n  . ./conf$$subs.sh ||\n    as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\n\n  ac_delim_n=`sed -n \"s/.*$ac_delim\\$/X/p\" conf$$subs.awk | grep -c X`\n  if test $ac_delim_n = $ac_delim_num; then\n    break\n  elif $ac_last_try; then\n    as_fn_error $? \"could not make $CONFIG_STATUS\" \"$LINENO\" 5\n  else\n    ac_delim=\"$ac_delim!$ac_delim _$ac_delim!! \"\n  fi\ndone\nrm -f conf$$subs.sh\n\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\ncat >>\"\\$ac_tmp/subs1.awk\" <<\\\\_ACAWK &&\n_ACEOF\nsed -n '\nh\ns/^/S[\"/; s/!.*/\"]=/\np\ng\ns/^[^!]*!//\n:repl\nt repl\ns/'\"$ac_delim\"'$//\nt delim\n:nl\nh\ns/\\(.\\{148\\}\\)..*/\\1/\nt more1\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\\\\n\"\\\\/\np\nn\nb repl\n:more1\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"\\\\/\np\ng\ns/.\\{148\\}//\nt nl\n:delim\nh\ns/\\(.\\{148\\}\\)..*/\\1/\nt more2\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"/\np\nb\n:more2\ns/[\"\\\\]/\\\\&/g; s/^/\"/; s/$/\"\\\\/\np\ng\ns/.\\{148\\}//\nt delim\n' <conf$$subs.awk | sed '\n/^[^\"\"]/{\n  N\n  s/\\n//\n}\n' >>$CONFIG_STATUS || ac_write_fail=1\nrm -f conf$$subs.awk\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n_ACAWK\ncat >>\"\\$ac_tmp/subs1.awk\" <<_ACAWK &&\n  for (key in S) S_is_set[key] = 1\n  FS = \"\u0007\"\n\n}\n{\n  line = $ 0\n  nfields = split(line, field, \"@\")\n  substed = 0\n  len = length(field[1])\n  for (i = 2; i < nfields; i++) {\n    key = field[i]\n    keylen = length(key)\n    if (S_is_set[key]) {\n      value = S[key]\n      line = substr(line, 1, len) \"\" value \"\" substr(line, len + keylen + 3)\n      len += length(value) + length(field[++i])\n      substed = 1\n    } else\n      len += 1 + keylen\n  }\n\n  print line\n}\n\n_ACAWK\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nif sed \"s/$ac_cr//\" < /dev/null > /dev/null 2>&1; then\n  sed \"s/$ac_cr\\$//; s/$ac_cr/$ac_cs_awk_cr/g\"\nelse\n  cat\nfi < \"$ac_tmp/subs1.awk\" > \"$ac_tmp/subs.awk\" \\\n  || as_fn_error $? \"could not setup config files machinery\" \"$LINENO\" 5\n_ACEOF\n\n# VPATH may cause trouble with some makes, so we remove sole $(srcdir),\n# ${srcdir} and @srcdir@ entries from VPATH if srcdir is \".\", strip leading and\n# trailing colons and then remove the whole line if VPATH becomes empty\n# (actually we leave an empty line to preserve line numbers).\nif test \"x$srcdir\" = x.; then\n  ac_vpsub='/^[\t ]*VPATH[\t ]*=[\t ]*/{\nh\ns///\ns/^/:/\ns/[\t ]*$/:/\ns/:\\$(srcdir):/:/g\ns/:\\${srcdir}:/:/g\ns/:@srcdir@:/:/g\ns/^:*//\ns/:*$//\nx\ns/\\(=[\t ]*\\).*/\\1/\nG\ns/\\n//\ns/^[^=]*=[\t ]*$//\n}'\nfi\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\nfi # test -n \"$CONFIG_FILES\"\n\n\neval set X \"  :F $CONFIG_FILES      \"\nshift\nfor ac_tag\ndo\n  case $ac_tag in\n  :[FHLC]) ac_mode=$ac_tag; continue;;\n  esac\n  case $ac_mode$ac_tag in\n  :[FHL]*:*);;\n  :L* | :C*:*) as_fn_error $? \"invalid tag \\`$ac_tag'\" \"$LINENO\" 5;;\n  :[FH]-) ac_tag=-:-;;\n  :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;\n  esac\n  ac_save_IFS=$IFS\n  IFS=:\n  set x $ac_tag\n  IFS=$ac_save_IFS\n  shift\n  ac_file=$1\n  shift\n\n  case $ac_mode in\n  :L) ac_source=$1;;\n  :[FH])\n    ac_file_inputs=\n    for ac_f\n    do\n      case $ac_f in\n      -) ac_f=\"$ac_tmp/stdin\";;\n      *) # Look for the file first in the build tree, then in the source tree\n\t # (if the path is not absolute).  The absolute path cannot be DOS-style,\n\t # because $ac_f cannot contain `:'.\n\t test -f \"$ac_f\" ||\n\t   case $ac_f in\n\t   [\\\\/$]*) false;;\n\t   *) test -f \"$srcdir/$ac_f\" && ac_f=\"$srcdir/$ac_f\";;\n\t   esac ||\n\t   as_fn_error 1 \"cannot find input file: \\`$ac_f'\" \"$LINENO\" 5;;\n      esac\n      case $ac_f in *\\'*) ac_f=`printf \"%s\\n\" \"$ac_f\" | sed \"s/'/'\\\\\\\\\\\\\\\\''/g\"`;; esac\n      as_fn_append ac_file_inputs \" '$ac_f'\"\n    done\n\n    # Let's still pretend it is `configure' which instantiates (i.e., don't\n    # use $as_me), people would be surprised to read:\n    #    /* config.h.  Generated by config.status.  */\n    configure_input='Generated from '`\n\t  printf \"%s\\n\" \"$*\" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'\n\t`' by configure.'\n    if test x\"$ac_file\" != x-; then\n      configure_input=\"$ac_file.  $configure_input\"\n      { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: creating $ac_file\" >&5\nprintf \"%s\\n\" \"$as_me: creating $ac_file\" >&6;}\n    fi\n    # Neutralize special characters interpreted by sed in replacement strings.\n    case $configure_input in #(\n    *\\&* | *\\|* | *\\\\* )\n       ac_sed_conf_input=`printf \"%s\\n\" \"$configure_input\" |\n       sed 's/[\\\\\\\\&|]/\\\\\\\\&/g'`;; #(\n    *) ac_sed_conf_input=$configure_input;;\n    esac\n\n    case $ac_tag in\n    *:-:* | *:-) cat >\"$ac_tmp/stdin\" \\\n      || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5 ;;\n    esac\n    ;;\n  esac\n\n  ac_dir=`$as_dirname -- \"$ac_file\" ||\n$as_expr X\"$ac_file\" : 'X\\(.*[^/]\\)//*[^/][^/]*/*$' \\| \\\n\t X\"$ac_file\" : 'X\\(//\\)[^/]' \\| \\\n\t X\"$ac_file\" : 'X\\(//\\)$' \\| \\\n\t X\"$ac_file\" : 'X\\(/\\)' \\| . 2>/dev/null ||\nprintf \"%s\\n\" X\"$ac_file\" |\n    sed '/^X\\(.*[^/]\\)\\/\\/*[^/][^/]*\\/*$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)[^/].*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\/\\)$/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  /^X\\(\\/\\).*/{\n\t    s//\\1/\n\t    q\n\t  }\n\t  s/.*/./; q'`\n  as_dir=\"$ac_dir\"; as_fn_mkdir_p\n  ac_builddir=.\n\ncase \"$ac_dir\" in\n.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;\n*)\n  ac_dir_suffix=/`printf \"%s\\n\" \"$ac_dir\" | sed 's|^\\.[\\\\/]||'`\n  # A \"..\" for each directory in $ac_dir_suffix.\n  ac_top_builddir_sub=`printf \"%s\\n\" \"$ac_dir_suffix\" | sed 's|/[^\\\\/]*|/..|g;s|/||'`\n  case $ac_top_builddir_sub in\n  \"\") ac_top_builddir_sub=. ac_top_build_prefix= ;;\n  *)  ac_top_build_prefix=$ac_top_builddir_sub/ ;;\n  esac ;;\nesac\nac_abs_top_builddir=$ac_pwd\nac_abs_builddir=$ac_pwd$ac_dir_suffix\n# for backward compatibility:\nac_top_builddir=$ac_top_build_prefix\n\ncase $srcdir in\n  .)  # We are building in place.\n    ac_srcdir=.\n    ac_top_srcdir=$ac_top_builddir_sub\n    ac_abs_top_srcdir=$ac_pwd ;;\n  [\\\\/]* | ?:[\\\\/]* )  # Absolute name.\n    ac_srcdir=$srcdir$ac_dir_suffix;\n    ac_top_srcdir=$srcdir\n    ac_abs_top_srcdir=$srcdir ;;\n  *) # Relative name.\n    ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix\n    ac_top_srcdir=$ac_top_build_prefix$srcdir\n    ac_abs_top_srcdir=$ac_pwd/$srcdir ;;\nesac\nac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix\n\n\n  case $ac_mode in\n  :F)\n  #\n  # CONFIG_FILE\n  #\n\n_ACEOF\n\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n# If the template does not know about datarootdir, expand it.\n# FIXME: This hack should be removed a few years after 2.60.\nac_datarootdir_hack=; ac_datarootdir_seen=\nac_sed_dataroot='\n/datarootdir/ {\n  p\n  q\n}\n/@datadir@/p\n/@docdir@/p\n/@infodir@/p\n/@localedir@/p\n/@mandir@/p'\ncase `eval \"sed -n \\\"\\$ac_sed_dataroot\\\" $ac_file_inputs\"` in\n*datarootdir*) ac_datarootdir_seen=yes;;\n*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting\" >&5\nprintf \"%s\\n\" \"$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting\" >&2;}\n_ACEOF\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\n  ac_datarootdir_hack='\n  s&@datadir@&$datadir&g\n  s&@docdir@&$docdir&g\n  s&@infodir@&$infodir&g\n  s&@localedir@&$localedir&g\n  s&@mandir@&$mandir&g\n  s&\\\\\\${datarootdir}&$datarootdir&g' ;;\nesac\n_ACEOF\n\n# Neutralize VPATH when `$srcdir' = `.'.\n# Shell code in configure.ac might set extrasub.\n# FIXME: do we really want to maintain this feature?\ncat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1\nac_sed_extra=\"$ac_vpsub\n$extrasub\n_ACEOF\ncat >>$CONFIG_STATUS <<\\_ACEOF || ac_write_fail=1\n:t\n/@[a-zA-Z_][a-zA-Z_0-9]*@/!b\ns|@configure_input@|$ac_sed_conf_input|;t t\ns&@top_builddir@&$ac_top_builddir_sub&;t t\ns&@top_build_prefix@&$ac_top_build_prefix&;t t\ns&@srcdir@&$ac_srcdir&;t t\ns&@abs_srcdir@&$ac_abs_srcdir&;t t\ns&@top_srcdir@&$ac_top_srcdir&;t t\ns&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t\ns&@builddir@&$ac_builddir&;t t\ns&@abs_builddir@&$ac_abs_builddir&;t t\ns&@abs_top_builddir@&$ac_abs_top_builddir&;t t\n$ac_datarootdir_hack\n\"\neval sed \\\"\\$ac_sed_extra\\\" \"$ac_file_inputs\" | $AWK -f \"$ac_tmp/subs.awk\" \\\n  >$ac_tmp/out || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n\ntest -z \"$ac_datarootdir_hack$ac_datarootdir_seen\" &&\n  { ac_out=`sed -n '/\\${datarootdir}/p' \"$ac_tmp/out\"`; test -n \"$ac_out\"; } &&\n  { ac_out=`sed -n '/^[\t ]*datarootdir[\t ]*:*=/p' \\\n      \"$ac_tmp/out\"`; test -z \"$ac_out\"; } &&\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \\`datarootdir'\nwhich seems to be undefined.  Please make sure it is defined\" >&5\nprintf \"%s\\n\" \"$as_me: WARNING: $ac_file contains a reference to the variable \\`datarootdir'\nwhich seems to be undefined.  Please make sure it is defined\" >&2;}\n\n  rm -f \"$ac_tmp/stdin\"\n  case $ac_file in\n  -) cat \"$ac_tmp/out\" && rm -f \"$ac_tmp/out\";;\n  *) rm -f \"$ac_file\" && mv \"$ac_tmp/out\" \"$ac_file\";;\n  esac \\\n  || as_fn_error $? \"could not create $ac_file\" \"$LINENO\" 5\n ;;\n\n\n\n  esac\n\ndone # for ac_tag\n\n\nas_fn_exit 0\n_ACEOF\nac_clean_files=$ac_clean_files_save\n\ntest $ac_write_fail = 0 ||\n  as_fn_error $? \"write failure creating $CONFIG_STATUS\" \"$LINENO\" 5\n\n\n# configure is writing to config.log, and then calls config.status.\n# config.status does its own redirection, appending to config.log.\n# Unfortunately, on DOS this fails, as config.log is still kept open\n# by configure, so config.status won't be able to write to it; its\n# output is simply discarded.  So we exec the FD to /dev/null,\n# effectively closing config.log, so it can be properly (re)opened and\n# appended to by config.status.  When coming back to configure, we\n# need to make the FD available again.\nif test \"$no_create\" != yes; then\n  ac_cs_success=:\n  ac_config_status_args=\n  test \"$silent\" = yes &&\n    ac_config_status_args=\"$ac_config_status_args --quiet\"\n  exec 5>/dev/null\n  $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false\n  exec 5>>config.log\n  # Use ||, not &&, to avoid exiting from the if with $? = 1, which\n  # would make configure fail if this is the last instruction.\n  $ac_cs_success || as_fn_exit 1\nfi\nif test -n \"$ac_unrecognized_opts\" && test \"$enable_option_checking\" != no; then\n  { printf \"%s\\n\" \"$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts\" >&5\nprintf \"%s\\n\" \"$as_me: WARNING: unrecognized options: $ac_unrecognized_opts\" >&2;}\nfi\n\n\n"
  },
  {
    "path": "configure.ac",
    "content": "dnl Process this file with autoconf to produce a configure script.\ndnl GDAL stuff largely copied from rgdal, (c) Roger Bivand\nAC_INIT\nAC_CONFIG_SRCDIR([src/wkb.cpp])\n\n: ${R_HOME=`R RHOME`}\nif test -z \"${R_HOME}\"; then\n  echo \"could not determine R_HOME\"\n  exit 1\nfi\n\nRBIN=\"${R_HOME}/bin/R\"\n# https://github.com/r-spatial/sf/issues/1054:\n# RVER=`\"${RBIN}\" --version | head -1 | cut -f3 -d\" \"`\nRSCRIPT=\"${R_HOME}/bin/Rscript\"\nRVER=`\"${RSCRIPT}\" -e 'writeLines(paste(sep=\".\", base::version$major, base::version$minor))'`\n\nRVER_MAJOR=`echo ${RVER} | cut  -f1 -d\".\"`\nRVER_MINOR=`echo ${RVER} | cut  -f2 -d\".\"`\nRVER_PATCH=`echo ${RVER} | cut  -f3 -d\".\"`\n\n#if test [$RVER_MAJOR = \"development\"]; then\n    CXX=`\"${RBIN}\" CMD config CXX`\n#else\n#    if test [$RVER_MAJOR -lt 3] -o [$RVER_MAJOR -eq 3 -a $RVER_MINOR -lt 3]; then\n#        AC_MSG_ERROR([sf is not compatible with R versions before 3.3.0])\n#    else\n#        CXX=`\"${RBIN}\" CMD config CXX`\n#    fi\n#fi\n\n# pick all flags for testing from R\n: ${CC=`\"${RBIN}\" CMD config CC`}\n: ${CFLAGS=`\"${RBIN}\" CMD config CFLAGS`}\n: ${CPPFLAGS=`\"${RBIN}\" CMD config CPPFLAGS`}\n: ${CXXFLAGS=`\"${RBIN}\" CMD config CXXFLAGS`}\n: ${LDFLAGS=`\"${RBIN}\" CMD config LDFLAGS`}\n# AC_SUBST([CC],[\"clang\"])\n# AC_SUBST([CXX],[\"clang++\"])\nAC_MSG_NOTICE([CC: ${CC}])\nAC_MSG_NOTICE([CXX: ${CXX}])\n\n# AC_MSG_NOTICE([${PACKAGE_NAME}: ${PACKAGE_VERSION}])\n\nGENERIC_INSTALL_MESSAGE=\"\n*** Installing this package from source requires the prior \n*** installation of external software, see for details \n*** https://r-spatial.github.io/sf/#installing\"\n\n#GDAL\nGDAL_CONFIG=\"gdal-config\"\n\nGDAL_CONFIG_SET=\"no\"\n\nAC_ARG_WITH([gdal-config],\n    AS_HELP_STRING([--with-gdal-config=GDAL_CONFIG],[the location of gdal-config]),\n           [gdal_config=$withval])\nif test [ -n \"$gdal_config\" ] ; then\n    GDAL_CONFIG_SET=\"yes\"\n    AC_SUBST([GDAL_CONFIG],[\"${gdal_config}\"])\n    AC_MSG_NOTICE(gdal-config set to $GDAL_CONFIG)\nfi\n\nif test [\"$GDAL_CONFIG_SET\" = \"no\"] ; then\n  AC_PATH_PROG([GDAL_CONFIG], [\"$GDAL_CONFIG\"],[\"no\"])\n  if test [\"$GDAL_CONFIG\" = \"no\"] ; then\n    AC_MSG_RESULT(no)\n    AC_MSG_ERROR([gdal-config not found or not executable. ${GENERIC_INSTALL_MESSAGE}])\n  fi\nelse\n  AC_MSG_CHECKING(gdal-config exists)\n  if test -r \"${GDAL_CONFIG}\"; then\n    AC_MSG_RESULT(yes)\n  else\n    AC_MSG_RESULT(no)\n    AC_MSG_ERROR([gdal-config not found - configure argument error. ${GENERIC_INSTALL_MESSAGE}])\n  fi\n  AC_MSG_CHECKING(gdal-config executable)\n  if test -x \"${GDAL_CONFIG}\"; then\n    AC_MSG_RESULT(yes)\n  else\n    AC_MSG_RESULT(no)\n    AC_MSG_ERROR([gdal-config not executable. ${GENERIC_INSTALL_MESSAGE}])\n  fi\nfi\n\nAC_MSG_CHECKING(gdal-config usability)\nif test `${GDAL_CONFIG} --version`;\nthen\n\tGDAL_CPPFLAGS=`${GDAL_CONFIG} --cflags`\n\tGDAL_VERSION=`${GDAL_CONFIG} --version`\n\tGDAL_LIBS=`${GDAL_CONFIG} --libs`\n\tGDAL_DEP_LIBS=`${GDAL_CONFIG} --dep-libs`\n\tGDAL_DATADIR=`${GDAL_CONFIG} --datadir`\n\tAC_MSG_RESULT(yes)\nelse\n\tAC_MSG_ERROR([gdal-config not found. ${GENERIC_INSTALL_MESSAGE}])\nfi\n\nAC_MSG_NOTICE([GDAL: ${GDAL_VERSION}])\nAC_MSG_CHECKING([GDAL version >= 2.0.1])\n\nGDAL_MAJ_VER=`echo $GDAL_VERSION | cut -d \".\" -f1`\nGDAL_MIN_VER=`echo $GDAL_VERSION | cut -d \".\" -f2`\nGDAL_PATCH_VER=`echo $GDAL_VERSION | cut -d \".\" -f3`\nif test ${GDAL_MAJ_VER} -lt 2 ; then\n  AC_MSG_RESULT(no)\n  AC_MSG_ERROR([sf is not compatible with GDAL versions below 2.0.1])\nelse\n   AC_MSG_RESULT(yes)\nfi\n\n#if test [${GDAL_MAJ_VER} -eq 3] -a [${GDAL_MIN_VER} -eq 6] -a [${GDAL_PATCH_VER} -eq 0] ; then\nif test \"${GDAL_VERSION}\" = \"3.6.0\" ; then\n  AC_MSG_ERROR([GDAL version 3.6.0 has been withdrawn, please update GDAL])\nfi\n\nINLIBS=\"${LIBS}\"\nINCPPFLAGS=\"${CPPFLAGS}\"\nINPKG_CPPFLAGS=\"${PKG_CPPFLAGS}\"\nINPKG_LIBS=\"${PKG_LIBS}\"\n\nAC_SUBST([PKG_CPPFLAGS], [\"${INPKG_CPPFLAGS} ${GDAL_CPPFLAGS}\"])\nAC_SUBST([PKG_LIBS], [\"${INPKG_LIBS} ${GDAL_LIBS}\"])\n\n# honor PKG_xx overrides\n# for CPPFLAGS we will superfluously double R's flags\n# since we'll set PKG_CPPFLAGS with this, but that shouldn't hurt\nCPPFLAGS=\"${INCPPFLAGS} ${PKG_CPPFLAGS}\"\n\ngdalok=yes\nAC_CHECK_HEADERS(gdal.h,,gdalok=no)\nif test \"${gdalok}\" = no; then\n   AC_MSG_ERROR([gdal.h not found in given locations. ${GENERIC_INSTALL_MESSAGE}])\nfi\n\nNEED_DEPS=no\nLIBS=\"${INLIBS} ${PKG_LIBS}\"\n[cat > gdal_test.cpp <<_EOCONF\n#include <gdal.h>\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nint main(void) {\nGDALAllRegister();\n}\n#ifdef __cplusplus\n}\n#endif\n_EOCONF]\n\nAC_MSG_CHECKING(GDAL: linking with --libs only)\n${CXX} ${CPPFLAGS} -o gdal_test gdal_test.cpp ${LIBS} 2> errors.txt\nif test `echo $?` -ne 0 ; then\ngdalok=no\nAC_MSG_RESULT(no)\nelse\nAC_MSG_RESULT(yes)\nfi\n\nif test \"${gdalok}\" = no; then\nAC_MSG_CHECKING(GDAL: linking with --libs and --dep-libs)\nLIBS=\"${LIBS} ${GDAL_DEP_LIBS}\"\ngdalok=yes\n${CXX} ${CPPFLAGS} -o gdal_test gdal_test.cpp ${LIBS} 2>> errors.txt\nif test `echo $?` -ne 0 ; then\ngdalok=no\nfi\nif test \"${gdalok}\" = yes; then\n    NEED_DEPS=yes\n    AC_MSG_RESULT(yes)\nelse\n    AC_MSG_RESULT(no)\nfi\nfi\n\nif test \"${gdalok}\" = no; then\n   cat errors.txt\n   AC_MSG_NOTICE([Install failure: compilation and/or linkage problems.])\n   AC_MSG_ERROR([GDALAllRegister not found in libgdal. ${GENERIC_INSTALL_MESSAGE}])\nfi\n\nrm -f gdal_test errors.txt gdal_test.cpp\n\nGDAL_GE_250=\"no\"\nGDAL_MAJ_VER=`echo $GDAL_VERSION | cut -d \".\" -f1`\nGDAL_MOD_VER=`echo $GDAL_VERSION | cut -d \".\" -f2`\nif test \"${GDAL_MAJ_VER}\" = 2 ; then\n  if test \"${GDAL_MOD_VER}\" -ge 5 ; then\n    GDAL_GE_250=\"yes\" \n  fi\nelse \n  if test \"${GDAL_MAJ_VER}\" -ge 3 ; then\n    GDAL_GE_250=\"yes\" \n  fi\nfi\n\nGDAL_DATA_TEST_FILE=\"${GDAL_DATADIR}/pcs.csv\"\nAC_MSG_CHECKING(GDAL: ${GDAL_DATADIR}/pcs.csv readable)\nif test -r \"${GDAL_DATA_TEST_FILE}\" ; then\n  AC_MSG_RESULT(yes)\nelse\n  AC_MSG_RESULT(no)\n  if test \"${GDAL_GE_250}\" = \"no\" ; then\n    AC_MSG_ERROR([pcs.csv not found in GDAL data directory.])\n  fi\nfi\n\n# Optional local copy of GDAL datadir and PROJ_LIB\n\ndata_copy=no\nif test \"${PROJ_GDAL_DATA_COPY}\" ; then\n    data_copy=yes\n    AC_MSG_NOTICE([PROJ_GDAL_DATA_COPY used.])\nelse\n    AC_ARG_WITH([data-copy],\n        AS_HELP_STRING([--with-data-copy=yes/no],[local copy of data directories in package, default no]),\n               [data_copy=$withval])\nfi\nif test \"${data_copy}\" = \"yes\" ; then\nAC_MSG_NOTICE([Copy data for:])\n  proj_lib0=\"${PROJ_LIB}\"\n  AC_ARG_WITH([proj-data],\n    AS_HELP_STRING([--with-proj-data=DIR],[location of PROJ data directory]),\n    [proj_lib1=$withval])\n  if test -n \"${proj_lib0}\" ; then\n    proj_lib=\"${proj_lib0}\"\n  else\n    proj_lib=\"${proj_lib1}\"\n  fi\n  if test -n \"${proj_lib}\" ; then\n    if test -d \"${proj_lib}\" ; then\n      cp -r \"${proj_lib}\" \"${R_PACKAGE_DIR}\"\n      AC_MSG_NOTICE([  PROJ: ${proj_lib}])\n    else\n      AC_MSG_ERROR([PROJ data files not found; set environment variable PROJ_LIB=DIR or --with-proj-data=DIR.])\n    fi\n  else\n      AC_MSG_ERROR([PROJ data files not found; set environment variable PROJ_LIB=DIR or --with-proj-data=DIR.])\n  fi\n\n  if test -d \"${GDAL_DATADIR}\" ; then\n    cp -r \"${GDAL_DATADIR}\" \"${R_PACKAGE_DIR}\"\n    AC_MSG_NOTICE([  GDAL: ${GDAL_DATADIR}])\n  else\n    AC_MSG_ERROR([GDAL data files not found.])\n  fi\nfi\n\n#\n# test whether PROJ is available to gdal:\n#\n\ngdal_has_proj=no\n[cat > gdal_proj.cpp <<_EOCONF\n#include <gdal.h>\n#include <ogr_srs_api.h>\n#include <ogr_spatialref.h>\nint main(int argc, char *argv[]) {\n\tOGRSpatialReference *dest = new OGRSpatialReference;\n\tOGRSpatialReference *src = new OGRSpatialReference;\n    src->importFromEPSG(4326);\n    dest->importFromEPSG(3857);\n\tOGRCoordinateTransformation *ct = OGRCreateCoordinateTransformation(src, dest);\n\treturn(ct == NULL); // signals PROJ is not available through gdal\n}\n_EOCONF]\n\nAC_MSG_CHECKING(GDAL: checking whether PROJ is available for linking:)\n${CXX} ${CPPFLAGS} -o gdal_proj gdal_proj.cpp ${LIBS} 2> errors.txt\nif test `echo $?` -ne 0 ; then\ngdal_has_proj=no\nAC_MSG_RESULT(no)\nelse\ngdal_has_proj=yes\nAC_MSG_RESULT(yes)\nfi\n\nif test \"${gdal_has_proj}\" = no; then\n   cat errors.txt\n   AC_MSG_NOTICE([Install failure: compilation and/or linkage problems.])\n   AC_MSG_ERROR([cannot link projection code])\nfi\n\nAC_MSG_CHECKING(GDAL: checking whether PROJ is available for running:)\nif test \"x$cross_compiling\" = \"xyes\"; then\nAC_MSG_RESULT(cross compiling, assuming yes)\nelse\n./gdal_proj\nif test `echo $?` -ne 0 ; then\ngdal_has_proj=no\nAC_MSG_RESULT(no)\nelse\ngdal_has_proj=yes\nAC_MSG_RESULT(yes)\nfi\nif test \"${gdal_has_proj}\" = no; then\n   AC_MSG_ERROR([OGRCoordinateTransformation() does not return a coord.trans: PROJ not available?])\nfi\nfi\nrm -fr errors.txt gdal_proj.cpp gdal_proj\nAC_MSG_NOTICE([GDAL: ${GDAL_VERSION}])\n\n\n# sqlite3\nAC_ARG_WITH([sqlite3-lib],\n    AS_HELP_STRING([--with-sqlite3-lib=LIB_PATH],[the location of sqlite3 libraries]),\n               [sqlite3_lib_path=$withval])\nif test [ -n \"$sqlite3_lib_path\" ] ; then\n    AC_SUBST([SQLITE3_LIBS], [\"-L${sqlite3_lib_path}\"])\nfi\n\n\n#\n# PROJ\n#\n\nPROJ_CONFIG=\"pkg-config proj\"\n\nif `$PROJ_CONFIG --exists` ; then\n  AC_MSG_NOTICE([pkg-config proj exists, will use it])\n  proj_config_ok=yes\nelse\n  proj_config_ok=no\nfi\n\nAC_ARG_WITH([proj-include],\n    AS_HELP_STRING([--with-proj-include=DIR],[location of proj header files]),\n    [proj_include_path=$withval])\nif test [ -n \"$proj_include_path\" ] ; then\n   AC_SUBST([PROJ_CPPFLAGS],[\"-I${proj_include_path}\"])\nelse\n  if test \"${proj_config_ok}\" = yes; then\n    PROJ_INCLUDE_PATH=`${PROJ_CONFIG} --cflags`\n    AC_SUBST([PROJ_CPPFLAGS],[\"${PROJ_INCLUDE_PATH}\"])\n  fi\nfi\n\n# honor PKG_xx overrides\n# for CPPFLAGS we will superfluously double R's flags\n# since we'll set PKG_CPPFLAGS with this, but that shouldn't hurt\n\nAC_ARG_WITH([proj-api],\n    AS_HELP_STRING([--with-proj-api=yes/no],[use the deprecated proj_api.h even when PROJ 6 is available; default no]),\n               [proj_api=$withval])\nPROJ6=\"no\"\nPROJH=\"no\"\nif test \"${proj_config_ok}\" = yes; then\n  PROJ_VERSION=`${PROJ_CONFIG} --modversion`\n  PROJV1=`echo \"${PROJ_VERSION}\" | cut -c 1`\n  if test \"${PROJV1}\" -ge 6; then\n    PROJ6=\"yes\"\n    PROJ_CPPFLAGS=\"${PROJ_CPPFLAGS} -DHAVE_PROJ_H\"\n    if test \"${proj_api}\" = yes; then\n        AC_MSG_NOTICE([using proj_api.h even with PROJ 5/6])\n        PROJ_CPPFLAGS=\"${PROJ_CPPFLAGS} -DACCEPT_USE_OF_DEPRECATED_PROJ_API_H\"\n    else\n        AC_MSG_NOTICE([using proj.h.])\n        PROJH=\"yes\"\n    fi\n  fi\nelse\n  if test \"${PROJH}\" = no ; then\n    PROJH=yes\n    AC_CHECK_HEADERS(proj.h,,PROJH=no)\n    if test \"${PROJH}\" = yes; then\n      PROJ6=\"yes\"\n      PROJ_CPPFLAGS=\"${PROJ_CPPFLAGS} -DHAVE_PROJ_H\"\n    fi\n  fi\nfi\n\nCPPFLAGS=\"${INCPPFLAGS} ${PKG_CPPFLAGS} ${PROJ_CPPFLAGS}\"\n\nif test \"${PROJH}\" = no\nthen\n  proj4ok=yes\n  AC_CHECK_HEADERS(proj_api.h,,proj4ok=no)\n  if test \"${proj4ok}\" = no; then\n     AC_MSG_ERROR([proj_api.h not found in standard or given locations.])\n  fi\nfi\n\n# dnl ditto for a library path\nAC_ARG_WITH([proj-lib],\n    AS_HELP_STRING([--with-proj-lib=LIB_PATH],[the location of proj libraries]),\n               [proj_lib_path=$withval])\nif test [ -n \"$proj_lib_path\" ] ; then\n    AC_SUBST([PROJ_LIBS], [\"-L${proj_lib_path} ${INPKG_LIBS} -lproj\"])\nelse\n  if test \"${proj_config_ok}\" = yes; then\n    if test `uname` = \"Darwin\"; then\n      PROJ_LIB_PATH=`${PROJ_CONFIG} --libs --static`\n    else\n      PROJ_LIB_PATH=`${PROJ_CONFIG} --libs`\n    fi\n    AC_SUBST([PROJ_LIBS], [\"${PROJ_LIB_PATH} ${INPKG_LIBS}\"])\n\tproj_version=`${PROJ_CONFIG} --modversion`\n\tAC_MSG_NOTICE([PROJ: ${proj_version}])\n  else\n    PROJ_LIBS=\"${PKG_LIBS} -lproj\"\n  fi\nfi\n\nLIBS=\"${PROJ_LIBS} ${INLIBS} ${PKG_LIBS}\"\n\nif test \"${PROJH}\" = no; then\n  proj4ok=yes\n  AC_CHECK_LIB(proj,pj_init_plus,,proj4ok=no)\n  if test \"${proj4ok}\" = no; then\n     AC_MSG_ERROR([libproj not found in standard or given locations. ${GENERIC_INSTALL_MESSAGE}])\n  fi\n[cat > proj_conf_test.c <<_EOCONF\n#include <stdio.h>\n#include <stdlib.h>\n#include <proj_api.h>\n\nint main(void) {\n    printf(\"%d\\n\", PJ_VERSION);\n    exit(0);\n}\n_EOCONF]\nelse\n[cat > proj_conf_test.cpp <<_EOCONF\n#include <stdio.h>\n#include <stdlib.h>\n#include <proj.h>\n\nint main(void) {\n\tproj_context_create();\n    exit(0);\n}\n_EOCONF]\n  #AC_CHECK_LIB(proj,proj_context_create,,proj6ok=no)\n  AC_MSG_CHECKING(PROJ: checking whether PROJ and sqlite3 are available for linking:)\n  ${CXX} ${CPPFLAGS} -o proj_conf_test proj_conf_test.cpp ${LIBS} $SQLITE3_LIBS -lsqlite3 2> errors.txt\n  if test `echo $?` -ne 0 ; then\n    proj6ok=no\n    AC_MSG_RESULT(no)\n  else\n    proj6ok=yes\n    AC_MSG_RESULT(yes)\n  fi\n  if test \"${proj6ok}\" = no; then\n     AC_MSG_ERROR([libproj or sqlite3 not found in standard or given locations. ${GENERIC_INSTALL_MESSAGE}])\n  fi\n\n[cat > proj_conf_test.c <<_EOCONF\n#include <stdio.h>\n#include <stdlib.h>\n#include <proj.h>\n\nint main(void) {\n    printf(\"%d.%d.%d\\n\", PROJ_VERSION_MAJOR, PROJ_VERSION_MINOR, PROJ_VERSION_PATCH);\n    exit(0);\n}\n_EOCONF]\nfi\n\n#AC_MSG_NOTICE([PKG_LIBS: ${PKG_LIBS}])\n\n${CC} ${CFLAGS} -o proj_conf_test proj_conf_test.c ${PROJ_LIBS}\n\nproj_version=`./proj_conf_test`\n\nAC_ARG_WITH([proj-share],\n    AS_HELP_STRING([--with-proj-share=SHARE_PATH],[the location of proj metadata files]),\n               [proj_share_path=$withval])\nif test [ -n \"$proj_share_path\" ] ; then\n    AC_MSG_NOTICE([PROJ_LIB: ${proj_share_path}])\nfi\n\nif test ${PROJ6} = \"no\"; then\n\n[cat > proj_conf_test.c <<_EOCONF\n#include <stdio.h>\n#include <proj_api.h>\n#if PJ_VERSION <= 480\nFILE *pj_open_lib(projCtx, const char *, const char *);\n#endif\n\nint main(void) {\n#if PJ_VERSION <= 480\n    FILE *fp;\n#else\n    PAFile fp;\n#endif\n    projCtx ctx;\n    ctx = pj_get_default_ctx();\n    fp = pj_open_lib(ctx, \"epsg\", \"rb\");\n    if (fp == NULL) exit(1);\n#if PJ_VERSION <= 480\n    fclose(fp);\n#else\n    pj_ctx_fclose(ctx, fp);\n#endif\n    exit(0);\n}\n_EOCONF]\n\n${CC} ${CFLAGS} -o proj_conf_test proj_conf_test.c ${PROJ_LIBS}\nif test [ -n \"$proj_share_path\" ] ; then\n  PROJ_LIB=\"${proj_share_path}\" ./proj_conf_test\n  proj_share=`echo $?`\nelse\n  ./proj_conf_test\n  proj_share=`echo $?`\nfi\n\nAC_MSG_CHECKING(PROJ: epsg found and readable)\nif test ${proj_share} -eq 1 ; then\n    AC_MSG_RESULT(no)\n    STOP=\"stop\"\nelse\n    AC_MSG_RESULT(yes)\nfi\n\nrm -f proj_conf_test.c proj_conf_test\n\nif test \"$STOP\" = \"stop\" ; then\n    echo \"Error: proj/epsg not found\"\n    echo \"Either install missing proj support files, for example\"\n    echo \"the proj-nad and proj-epsg RPMs on systems using RPMs,\"\n    echo \"or if installed but not autodetected, set PROJ_LIB to the\"\n    echo \"correct path, and if need be use the --with-proj-share=\"\n    echo \"configure argument.\"\n    exit 1\nfi\n\nelse # proj >= 6\n\nif test \"${PROJH}\" = no; then\n\n[cat > proj_conf_test.c <<_EOCONF\n#include <stdio.h>\n#include <proj_api.h>\n\nint main(void) {\n    PAFile fp;\n    projCtx ctx;\n    ctx = pj_get_default_ctx();\n    fp = pj_open_lib(ctx, \"proj.db\", \"rb\");\n    if (fp == NULL) exit(1);\n    pj_ctx_fclose(ctx, fp);\n    exit(0);\n}\n_EOCONF]\n\n${CC} ${CFLAGS} -o proj_conf_test proj_conf_test.c ${PROJ_LIBS}\nif test [ -n \"$proj_share_path\" ] ; then\n  PROJ_LIB=\"${proj_share_path}\" ./proj_conf_test\n  proj_share=`echo $?`\nelse\n  ./proj_conf_test\n  proj_share=`echo $?`\nfi\n\nAC_MSG_CHECKING(PROJ: proj.db found and readable)\nif test ${proj_share} -eq 1 ; then\n    AC_MSG_RESULT(no)\n    STOP=\"stop\"\nelse\n    AC_MSG_RESULT(yes)\nfi\n\nrm -f proj_conf_test.c proj_conf_test\n\nif test \"$STOP\" = \"stop\" ; then\n    echo \"Error: proj/proj.db not found\"\n    echo \"Either install missing proj support files, set PROJ_LIB to the\"\n    echo \"correct path, and if need be use the --with-proj-share=\"\n    echo \"configure argument.\"\n    exit 1\nfi\n\n[cat > proj_conf_test.c <<_EOCONF\n#include <stdio.h>\n#include <proj_api.h>\n#if PJ_VERSION <= 480\nFILE *pj_open_lib(projCtx, const char *, const char *);\n#endif\n\nint main(void) {\n#if PJ_VERSION <= 480\n    FILE *fp;\n#else\n    PAFile fp;\n#endif\n    projCtx ctx;\n    ctx = pj_get_default_ctx();\n    fp = pj_open_lib(ctx, \"conus\", \"rb\");\n    if (fp == NULL) exit(1);\n#if PJ_VERSION <= 480\n    fclose(fp);\n#else\n    pj_ctx_fclose(ctx, fp);\n#endif\n    exit(0);\n}\n_EOCONF]\n\n${CC} ${CFLAGS} -o proj_conf_test proj_conf_test.c ${PROJ_LIBS}\nif test [ -n \"$proj_share_path\" ] ; then\n  PROJ_LIB=\"${proj_share_path}\" ./proj_conf_test\n  proj_share=`echo $?`\nelse\n  ./proj_conf_test\n  proj_share=`echo $?`\nfi\n\nAC_MSG_CHECKING(PROJ: conus found and readable)\nif test ${proj_share} -eq 1 ; then\n    WARN=\"warn\"\n    AC_MSG_RESULT(no)\nelse\n    AC_MSG_RESULT(yes)\nfi\n\nrm -f proj_conf_test.c proj_conf_test\n\nif test \"$WARN\" = \"warn\" ; then\n    echo \"Note: proj/conus not found\"\n    echo \"No support available in PROJ4 for NAD grid datum transformations\"\n    echo \"If required, consider re-installing from source with the contents\"\n    echo \"of proj-datumgrid-1.<latest>.zip from http://download.osgeo.org/proj/ in nad/.\"\nfi\n\nfi # PROJH = no\n\nfi # proj >= 6\n\n\n\n\n#\n# GEOS:\n#\nGEOS_CONFIG=\"geos-config\"\n\nGEOS_CONFIG_SET=\"no\"\n\nAC_ARG_WITH([geos-config],\n    AS_HELP_STRING([--with-geos-config=GEOS_CONFIG],[the location of geos-config]),\n           [geos_config=$withval])\nif test [ -n \"$geos_config\" ] ; then\n    GEOS_CONFIG_SET=\"yes\"\n    AC_SUBST([GEOS_CONFIG],[\"${geos_config}\"])\n    AC_MSG_NOTICE(geos-config set to $GEOS_CONFIG)\nfi\n\nif test [\"$GEOS_CONFIG_SET\" = \"no\"] ; then\n  AC_PATH_PROG([GEOS_CONFIG], [\"$GEOS_CONFIG\"],[\"no\"])\n  if test [\"$GEOS_CONFIG\" = \"no\"] ; then\n    AC_MSG_RESULT(no)\n    AC_MSG_ERROR([geos-config not found or not executable. ${GENERIC_INSTALL_MESSAGE}])\n  fi\nelse\n  AC_MSG_CHECKING(geos-config exists)\n  if test -r \"${GEOS_CONFIG}\"; then\n    AC_MSG_RESULT(yes)\n  else\n    AC_MSG_RESULT(no)\n    AC_MSG_ERROR([geos-config not found - configure argument error. ${GENERIC_INSTALL_MESSAGE}])\n  fi\n  AC_MSG_CHECKING(geos-config executable)\n  if test -x \"${GEOS_CONFIG}\"; then\n    AC_MSG_RESULT(yes)\n  else\n    AC_MSG_RESULT(no)\n    AC_MSG_ERROR([geos-config not executable. ${GENERIC_INSTALL_MESSAGE}])\n  fi\nfi\n\nAC_MSG_CHECKING(geos-config usability)\nif test `${GEOS_CONFIG} --version`\nthen\n  GEOS_CLIBS=\"`${GEOS_CONFIG} --clibs`\"\n  #GEOS_DEP_CLIBS=`geos-config --static-clibs` -- this gives -m instead of -lm, which breaks clang\n  # fixed in 3.7.0 at https://github.com/libgeos/libgeos/pull/73#issuecomment-262208677\n  GEOS_DEP_CLIBS=`${GEOS_CONFIG} --static-clibs | sed 's/-m/-lm/g'`\n  GEOS_CPPFLAGS=`${GEOS_CONFIG} --cflags`\n  AC_MSG_RESULT(yes)\nelse\n  AC_MSG_RESULT(no)\n  AC_MSG_ERROR([${GEOS_CONFIG} not usable])\nfi\n\nGEOS_VERSION=`${GEOS_CONFIG} --version`\nAC_MSG_NOTICE([GEOS: ${GEOS_VERSION}])\nAC_MSG_CHECKING([GEOS version >= 3.4.0]) # GDAL 2.0.1 requires GEOS 3.1.0\nGEOS_VER_DOT=`echo $GEOS_VERSION | tr -d \".[[:alpha:]]\"`\nif test ${GEOS_VER_DOT} -lt 340 ; then\n  AC_MSG_RESULT(no)\n  AC_MSG_ERROR([upgrade GEOS to 3.4.0 or later])\nelse\n  AC_MSG_RESULT(yes)\nfi\n\nAC_SUBST([PKG_CPPFLAGS], [\"${INPKG_CPPFLAGS} ${PROJ_CPPFLAGS} ${GDAL_CPPFLAGS} ${GEOS_CPPFLAGS}\"])\nAC_SUBST([PKG_LIBS], [\"${INPKG_LIBS} ${GDAL_LIBS}\"])\nif test \"${NEED_DEPS}\" = yes; then\n   AC_SUBST([PKG_LIBS], [\"${PKG_LIBS} ${GDAL_DEP_LIBS}\"])\nfi\n\n# honor PKG_xx overrides\n# for CPPFLAGS we will superfluously double R's flags\n# since we'll set PKG_CPPFLAGS with this, but that shouldn't hurt\nCPPFLAGS=\"${CPPFLAGS} ${PKG_CPPFLAGS}\"\nLIBS=\"${LIBS} ${PKG_LIBS}\"\n\ngeosok=yes\nAC_CHECK_HEADERS(geos_c.h,,geosok=no)\nif test \"${geosok}\" = no; then\n   AC_MSG_ERROR([geos_c.h not found in given locations. ${GENERIC_INSTALL_MESSAGE}])\nfi\n\n[cat > geos_test.cpp <<_EOCONF\n#include <geos_c.h>\n#ifdef __cplusplus\nextern \"C\" {\n#endif\nstatic void __errorHandler(const char *fmt, ...) {\n    return;\n}\nstatic void __warningHandler(const char *fmt, ...) {\n    return;\n}\nint main(void) {\n    GEOSContextHandle_t r = initGEOS_r((GEOSMessageHandler) __warningHandler, (GEOSMessageHandler) __errorHandler);\n    finishGEOS_r(r);\n}\n#ifdef __cplusplus\n}\n#endif\n_EOCONF]\n\n#echo \"${CXX} ${CPPFLAGS} -o geos_test geos_test.cpp ${LIBS}\"\nAC_MSG_CHECKING(geos: linking with ${GEOS_CLIBS})\n${CXX} ${CPPFLAGS} -o geos_test geos_test.cpp ${GEOS_CLIBS} 2> errors.txt\nif test `echo $?` -ne 0 ; then\n geosok=no\n AC_MSG_RESULT(no)\nelse\n AC_SUBST([PKG_LIBS], [\"${PKG_LIBS} ${GEOS_CLIBS}\"])\n AC_MSG_RESULT(yes)\nfi\n\nif test \"${geosok}\" = no; then\n  AC_MSG_CHECKING(geos: linking with ${GEOS_DEP_CLIBS})\n  ${CXX} ${CPPFLAGS} -o geos_test geos_test.cpp ${GEOS_DEP_CLIBS} 2> errors.txt\n  if test `echo $?` -ne 0 ; then\n    geosok=no\n    AC_MSG_RESULT(no)\n    cat errors.txt\n    AC_MSG_NOTICE([Install failure: compilation and/or linkage problems.])\n    AC_MSG_ERROR([initGEOS_r not found in libgeos_c. ${GENERIC_INSTALL_MESSAGE}])\n  else\n    AC_SUBST([PKG_LIBS], [\"${PKG_LIBS} ${GEOS_DEP_CLIBS}\"])\n    AC_MSG_RESULT(yes)\n  fi\nfi\n\nrm -f geos_test errors.txt geos_test.cpp\n\n#\n# add PROJ_LIBS\n#\nAC_SUBST([PKG_LIBS], [\"${PROJ_LIBS} ${PKG_LIBS}\"])\n\n#\n# concluding substitution\n#\nAC_MSG_NOTICE([Package CPP flags: ${PKG_CPPFLAGS}])\nAC_MSG_NOTICE([Package LIBS: ${PKG_LIBS}])\n\nAC_CONFIG_FILES(src/Makevars)\nAC_OUTPUT\n"
  },
  {
    "path": "demo/00Index",
    "content": "affine\t\tdemo script for affine transformations\nbasic\t\tsimple feature test script\nggplot\t\tshows use of geom_sf\nmeuse_sf\tcreate meuse simple feature table from data.frame\nnc\t\t\tload (read) North Carolina sids data set from a geopackage file\ntwitter\t\ttwitter globe demo\n"
  },
  {
    "path": "demo/affine.R",
    "content": "library(sf)\n\na = 0.95\nb = 0.8\nang = 3 * pi / 180\nrot = function(a) matrix(c(cos(a), sin(a), -sin(a), cos(a)), 2, 2)\nn = 12\ndrift = c(.12, .07)\n\nouter = rbind(c(-1,-1), c(1, -1), c(1, 1), c(-1, 1), c(-1, -1))\nhole = a * outer[5:1,]\n\n# only shift:\np = st_sfc(lapply(0:n, \n\tfunction(i) { st_polygon(list(outer, hole)) * rot(0) * b^i + drift * i * b ^ i } ))\nplot(p, col = grey(0:n/n), border = 0)\n\n# shift + rotate:\np = st_sfc(lapply(0:n, \n\tfunction(i) { st_polygon(list(outer, hole)) * rot(i * ang) * b ^ i + drift * i * b ^ i } ))\np\nplot(p, col = grey(0:n/n), border = 0)\ng = st_geometrycollection(p)\nplot(g)\nmp = st_multipolygon(p)\nopar = par(mfrow = c(2,2), mar = rep(0,4))\nplot(mp * rot(10))\nplot(mp * rot(20))\nplot(mp * rot(30))\nplot(mp * rot(40))\npar(opar)\n"
  },
  {
    "path": "demo/basic.R",
    "content": "## ----error=TRUE----------------------------------------------------------\nlibrary(sf)\n(p1 = st_point(c(1,2)))\nclass(p1)\nst_bbox(p1)\n(p2 = st_point(c(1,2,3)))\nclass(p2)\n(p3 = st_point(c(1,2,3), \"XYM\"))\n(p4 = st_point(c(1,2,3,4)))\nattr(try(st_point(1)), \"condition\") # Error:\nattr(try(st_point(1:5)), \"condition\") # Error:\n\n## ----error=TRUE----------------------------------------------------------\npts = matrix(1:10, , 2)\n(mp1 = st_multipoint(pts))\npts = matrix(1:15, , 3)\n(mp2 = st_multipoint(pts))\n(mp3 = st_multipoint(pts, \"XYM\"))\npts = matrix(1:20, , 4)\n(mp4 = st_multipoint(pts))\nattr(try(st_multipoint(1)), \"condition\") # Error:\nattr(try(st_multipoint(1:5)), \"condition\") # Error:\nst_bbox(mp1)\n\n## ----error=TRUE----------------------------------------------------------\npts = matrix(1:10, , 2)\n(ls1 = st_linestring(pts))\npts = matrix(1:15, , 3)\n(ls2 = st_linestring(pts))\n(ls3 = st_linestring(pts, \"XYM\"))\npts = matrix(1:20, , 4)\n(ls4 = st_linestring(pts))\nattr(try(st_linestring(pts[1,])), \"condition\") # Error:\nattr(try(st_linestring(matrix(1:10, 2))), \"condition\")# Error:\nst_bbox(ls1)\n\n## ----error=TRUE----------------------------------------------------------\nouter = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\nhole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\nhole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\npts = list(outer, hole1, hole2)\n(ml1 = st_multilinestring(pts))\npts3 = lapply(pts, function(x) cbind(x, 0))\n(ml2 = st_multilinestring(pts3))\n(ml3 = st_multilinestring(pts3, \"XYM\"))\npts4 = lapply(pts3, function(x) cbind(x, 0))\n(ml4 = st_multilinestring(pts4))\nst_bbox(ml1)\n\n## ----error=TRUE----------------------------------------------------------\nouter = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\nouter\nhole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\nhole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\npts = list(outer, hole1, hole2)\n(pl1 = st_polygon(pts))\npts3 = lapply(pts, function(x) cbind(x, 0))\n(pl2 = st_polygon(pts3))\n(pl3 = st_polygon(pts3, \"XYM\"))\npts4 = lapply(pts3, function(x) cbind(x, 0))\n(pl4 = st_polygon(pts4))\nst_bbox(pl1)\n\n## ----error=TRUE----------------------------------------------------------\nouter = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\nouter\nhole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\nhole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\npol1 = list(outer, hole1, hole2)\npol2 = list(outer + 12, hole1 + 12)\npol3 = list(outer + 24)\nmp = list(pol1,pol2,pol3)\n(mp1 = st_multipolygon(mp))\npts3 = lapply(mp, function(x) lapply(x, function(y) cbind(y, 0)))\n(mp2 = st_multipolygon(pts3))\n(mp3 = st_multipolygon(pts3, \"XYM\"))\npts4 = lapply(mp2, function(x) lapply(x, function(y) cbind(y, 0)))\n(mp4 = st_multipolygon(pts4))\nst_bbox(mp1)\n\n## ----error=TRUE----------------------------------------------------------\nouter = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\nouter\nhole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\nhole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\npol1 = list(outer, hole1, hole2)\npol2 = list(outer + 12, hole1 + 12)\npol3 = list(outer + 24)\nmp = list(pol1,pol2,pol3)\nmp1 = st_multipolygon(mp)\n(gc = st_geometrycollection(list(p1, ls1, pl1, mp1)))\nst_bbox(gc)\nattr(try(st_geometrycollection(list(mp3, pl1))), \"condition\") # Error:\n"
  },
  {
    "path": "demo/ggplot.R",
    "content": "library(sf)\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\n\n# single map:\nlibrary(ggplot2)\nggplot(nc) + geom_sf(aes(fill = SID79))\n\n# multiple plot with facet_grid:\nlibrary(dplyr)\nlibrary(tidyr)\n\nnc$row = 1:100\nnc.g <- nc %>% select(SID74, SID79, row) %>% gather(VAR, SID, -row, -geometry)\nggplot(nc.g) + geom_sf(aes(fill = SID)) + facet_grid(. ~ VAR)\nggplot(nc.g) + geom_sf(aes(fill = SID)) + facet_grid(VAR ~ .)\n\n"
  },
  {
    "path": "demo/meuse_sf.R",
    "content": "data(meuse, package = \"sp\") # load data.frame from sp\nlibrary(sf)\nmeuse_sf = st_as_sf(meuse, coords = c(\"x\", \"y\"), crs = 28992)\nmeuse_sf[1:5,]\nsummary(meuse_sf[1:5,])\n"
  },
  {
    "path": "demo/nc.R",
    "content": "## this object was created as follows:\nlibrary(sf)\n# nc = st_read(system.file(\"shapes/\", package=\"maptools\"), \"sids\")\n# st_crs(nc) = 4267 # \"+proj=longlat +ellps=clrk66\" or \"+proj=longlat +datum=NAD27\"\n# print(nc, n = 3)\n# st_write(nc, \"nc.gpkg\", \"nc.gpkg\", driver = \"GPKG\")\n\n# description of the dataset, see vignette in package spdep:\n# https://cran.r-project.org/web/packages/spdep/vignettes/sids.pdf\n\ndatasource = { if (\"GPKG\" %in% st_drivers()$name)\n\tsystem.file(\"gpkg/nc.gpkg\", package=\"sf\")\nelse\n\tsystem.file(\"shape/nc.shp\", package=\"sf\")\n}\n\nagr = c(AREA = \"aggregate\", PERIMETER = \"aggregate\", CNTY_ = \"identity\",\n\t\tCNTY_ID = \"identity\", NAME = \"identity\", FIPS = \"identity\", FIPSNO = \"identity\",\n\t\tCRESS_ID = \"identity\", BIR74 = \"aggregate\", SID74 = \"aggregate\", NWBIR74 = \"aggregate\",\n\t\tBIR79 = \"aggregate\", SID79 = \"aggregate\", NWBIR79  = \"aggregate\")\n\nnc = st_read(datasource, agr = agr, quiet = TRUE)\n"
  },
  {
    "path": "demo/twitter.R",
    "content": "# see https://gist.github.com/edzer/9c5c24434ffcaf42917796a98c4dd9a6\nlibrary(sf)\ndata(wrld_simpl, package = \"maptools\")\nw <- st_as_sf(wrld_simpl)\nw = st_make_valid(w)\nst_crs(w) = st_crs(4326)\nset.seed(131)\nw$f = factor(sample(1:12, nrow(w), replace = TRUE))\n\n# all points long l, lat p for which cos(c) = 0; l0 = lon0, p0 = lat0\n\n# cos(c) = sin(p0)*sin(p) + cos(p0)*cos(p)*cos(l-l0) = 0\n# sin(p0)*sin(p) = - cos(p0)*cos(p)*cos(l-l0)\n# sin(p)/cos(p) = -cos(p0)*cos(l-l0)/sin(p0)\n# tan(p) = -cos(l-l0)/tan(p0)\n# p = atan(-cos(l-l0)/tan(p0))\n\n# vary l, compute corresponding p;\n# all gc's have all longitudes, except when the poles are part of it;\n# in that case, lat0 == p0 = 0 and p is always pi/2\n\ncirc = function(l = c(-180:180), lon0 = 0, lat0 = 30) {\n\tdeg2rad = pi / 180\n\tlat = atan(-cos((l - lon0) * deg2rad)/tan(lat0 * deg2rad)) / deg2rad\n\txy = if (lat0 == 0) {\n\t\tl1 = lon0 - 90\n\t\tl2 = lon0 + 90\n\t\trbind(c(l1,-90), c(l2,-90), c(l2,0), c(l2,90), c(l1,90), c(l1,0), c(l1,-90))\n\t} else if (lat0 > 0) {\n\t\txy = cbind(lon = l, lat = lat)\n\t\trbind(c(-180,90),xy,c(180,90),c(-180,90))\n\t} else {\n\t\txy = cbind(lon = l, lat = lat)[length(l):1,]\n\t\trbind(c(180,-90), xy, c(-180,-90),c(180,-90))\n\t}\n\tst_sfc(st_polygon(list(xy)), crs = st_crs(4326))\n\t# TODO: break at dateline, guarantee within -180,180\n}\n\nm = st_make_grid()\nm = st_segmentize(m, 4e5)\n#library(animation)\n#saveGIF(\n#for (i in 0:100) {\n#\tpar(mar = rep(0,4))\n#\tlat=30+(i/2)\n#\tlon=-10-(i/2)\n#\tprint(c(i,lon,lat))\n#\tp4s=paste0(\"+proj=ortho +lat_0=\", lat, \" +lon_0=\", lon)\n#\tplot(st_transform(m, st_crs(p4s), check = TRUE), col = 'lightblue', border = 'grey')\n#\tcrc = circ(lat0 = lat, lon0 = lon)\n#\tw0 = suppressWarnings(st_intersection(w, crc))\n#\tw0 = st_cast(w0, \"MULTIPOLYGON\")\n#\tplot(st_transform(w0[\"f\"], st_crs(p4s), check = TRUE), add = TRUE)\n#}\n#, interval = 0.05, clean = FALSE)\n"
  },
  {
    "path": "inst/CITATION",
    "content": "citHeader(\"To cite package sf in publications, please use:\")\n\nbibentry(bibtype = \"Book\",\n  author= \"Edzer Pebesma and Roger Bivand\",\n  title = \"{Spatial Data Science: With applications in R}\",\n  year = 2023,\n  publisher = \"{Chapman and Hall/CRC}\",\n  url = \"https://r-spatial.org/book/\",\n  doi = \"10.1201/9780429459016\",\n  textVersion = \"Pebesma, E., & Bivand, R. (2023). Spatial Data Science: With Applications in R. Chapman and Hall/CRC. https://doi.org/10.1201/9780429459016\"\n)\n\nbibentry(bibtype = \"Article\",\n  author = \"Edzer Pebesma\",\n  title = \"{Simple Features for R: Standardized Support for Spatial Vector Data}\",\n  year = 2018,\n  journal = \"{The R Journal}\",\n  doi = \"10.32614/RJ-2018-009\",\n  url = \"https://doi.org/10.32614/RJ-2018-009\",\n  pages = \"439--446\",\n  volume = 10,\n  number = 1,\n  textVersion = \"Pebesma, E., 2018. Simple Features for R: Standardized Support for Spatial Vector Data. The R Journal 10 (1), 439-446, https://doi.org/10.32614/RJ-2018-009\"\n)\n"
  },
  {
    "path": "inst/csv/pt.csv",
    "content": "Id,Int64,Int32,WKT\n1,0,33,POINT(0 1)\n2,4294967297,44,POINT(44 55)\n3,,,POINT(0 0)\n"
  },
  {
    "path": "inst/docker/README.md",
    "content": "# Build and check sf against r-release and r-devel\n\nSee [here](https://github.com/rocker-org/geospatial) for general docker files building R with a significant number of spatial extension packages and external dependencies, based on [rocker](https://github.com/rocker-org/rocker) and debian.\n\nTo allows building `sf` in alternative environments with all\nexternal system requirements (udunits, proj, gdal, geos, lwgeom),\nthis directory has subdirectories with Docker files:\n\n* [base](base): for installing R-release with all system dependencies required by `sf`, \n* [devel](devel): for building R-devel from source (downloaded from svn, without X11) on top of that. \n* [gdal](gdal): for testing with newer/newst gdal/geos/proj versions\n* [custom](custom): for testing with libraries (gdal, geos, proj.4) installed in custom, non-standard directories\n* [lowest](lowest): for checking sf against the lowest required PROJ, GDAL and GEOS versions\n* [fedora](fedora): for checking sf against the fedora/clang platform\n* [cran](cran): using the debian setup used by several of the CRAN linux servers\n\nExcept for the cran image, all images are built on ubuntu:16.04 (xenial). They use [ubuntugis-unstable](https://launchpad.net/~ubuntugis/+archive/ubuntu/ubuntugis-unstable) for GIS package system dependencies.\n\n## run check under R release\n\nIn directory `base`, type\n\n    docker build . -t sf\n\nthis will build a docker image of approx. 3.8 Gb size, called `sf`. It will also install package `sf` with its dependencies from CRAN, and run a check on the github sources.\n\nRun a container from this image interactively with \n\n\tdocker run -ti sf\n\nIf you want to run it while mounting the current working directory (`pwd`) to `/pkg` inside the container, and want to remove the container after you exit, use:\n\n\tdocker run -v `pwd`:/pkg --rm -ti sf\n\n## build R-devel, check with R-devel\n\n_After_ you built docker image `sf` above, on top of that you can install r-devel; it counts up to 4 Gb. Build it by executing the following command in the `devel` directory: \n\n    docker build . -t sf_devel\n\nRun a container from this image interactively with\n\n\tdocker run -ti sf_devel\n\nto start R-devel in the container, use the `Rdevel` command. Building the image checks sf from github.\n\nIf you want to run R with `gdb` in a container, use e.g.\n\n    docker run --cap-add=SYS_PTRACE --security-opt seccomp=unconfined -ti gdal3\n\n## with custom gdal, geos and proj installs\n"
  },
  {
    "path": "inst/docker/alma/Dockerfile",
    "content": "#\n# Do not edit: NOW CONTINUED IN\n# https://github.com/Open-EO/openeo-udf-python-to-r/tree/main/docker\n#\nARG SPARK_VERSION\nARG PYTHON_PACKAGE\n\nFROM almalinux:8.5\n\nARG SPARK_VERSION\nARG PYTHON_PACKAGE\n\nCOPY vito.repo /etc/yum.repos.d/vito.repo\n\nWORKDIR /opt/spark/work-dir\n\nRUN adduser -u 18585 -d /opt/spark/work-dir spark && \\\n    chown 18585:18585 /opt/spark/work-dir\n\nRUN yum install -y epel-release\nRUN yum install -y dnf --enablerepo=powertools spark-bin-${SPARK_VERSION}\nRUN yum install -y --enablerepo=powertools \\\n    gdal-3.4.0 \\\n    gdal-devel-3.4.0 \\\n    python38-gdal-3.4.0 \\\n    gdal-libs-3.4.0 \\\n    unzip \\\n    java-11-openjdk-headless \\\n    krb5-workstation \\\n    krb5-libs \\\n    sssd-client \\\n    ipa-client \\\n    nss \\\n    orfeo-toolbox-py38 \\\n    procps-ng \\\n    ${PYTHON_PACKAGE} \\\n    python38-pytz  \\\n    python38-Cython \\\n    fftw-libs-double \\\n    fftw-libs-single \\\n    openeo-vito-aux-data \\\n    tinyxml \\\n    compat-libgfortran-48-4.8.5-36.1.el8.x86_64 && \\\n    ln -s /usr/lib64/libgdal.so.30 /usr/lib64/libgdal.so.26 && \\\n    ln -s /usr/lib64/libgdal.so.30 /usr/lib64/libgdal.so.27 && \\\n    pip3 install --upgrade pip setuptools && \\\n    rm -r /root/.cache && \\\n    yum clean all && \\\n    rm -rf /var/cache/yum/*\n\nENV SPARK_HOME /usr/local/spark\nENV JAVA_HOME /usr/lib/jvm/jre\nENV PYSPARK_PYTHON=python3\nENV HADOOP_HOME=/usr/hdp/current/hadoop-client\nENV HADOOP_CONF_DIR=/etc/hadoop/conf\nENV YARN_CONF_DIR=/etc/hadoop/conf\nENV ACCUMULO_CLIENT_CONF_PATH=client.conf\nENV OTB_HOME=/usr\nENV OTB_APPLICATION_PATH=/usr/lib/otb/applications\n\n# EP: install R, system requirements of R-spatial packages, and R package stars\nRUN yum install -y dnf --enablerepo=powertools R-core-devel\nRUN yum install -y dnf --enablerepo=powertools \\\n    udunits2-devel \\\n    openssl-devel \\\n    sqlite-devel \\\n    geos-devel \\\n    proj-devel \\\n    libcurl-devel \\\n    git\nRUN R -e 'install.packages(c(\"stars\", \"jsonlite\", \"curl\", \"lubridate\"), repos = \"https://cloud.r-project.org\")'\nRUN pip3 install rpy2 xarray requests dask\n\n# original:\nUSER 18585\n\n# EP: install UDF test script and run it:\nRUN git clone https://github.com/Open-EO/openeo-udf-python-to-r.git\nRUN (cd openeo-udf-python-to-r; python3 test.py)\n"
  },
  {
    "path": "inst/docker/alma/README.md",
    "content": "VITO openEO backend image; build this docker container with\n```\ndocker build . -t alma --build-arg SPARK_VERSION=3.2.0 --build-arg PYTHON_PACKAGE=python38-devel \n```\n\n"
  },
  {
    "path": "inst/docker/alma/build_command",
    "content": "docker build . -t alma --build-arg SPARK_VERSION=3.2.0 --build-arg PYTHON_PACKAGE=python38-devel \n"
  },
  {
    "path": "inst/docker/alma/vito.repo",
    "content": "[vito-public-alma]\nname=vito-yum-centos-public\nbaseurl=https://artifactory.vgt.vito.be/vito-yum-almalinux8-public/\ngpgcheck=0\n\n[vito-public]\nname=vito-yum-centos-public\nbaseurl=https://artifactory.vgt.vito.be/vito-yum-centos8-public/\ngpgcheck=0\n"
  },
  {
    "path": "inst/docker/arrow/Dockerfile",
    "content": "FROM ubuntu:22.04\n# minimal docker file to get sf running on ubunty 22.04 image,\n# compiling geos/proj/gdal from source, using cmake\n\nMAINTAINER \"edzerpebesma\" edzer.pebesma@uni-muenster.de\n\nRUN apt-get update && apt-get install -y software-properties-common dirmngr\nRUN add-apt-repository ppa:ubuntugis/ubuntugis-unstable\n\nRUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9\n\n# add the R 4.0 repo from CRAN -- adjust 'focal' to 'groovy' or 'bionic' as needed\nRUN add-apt-repository \"deb https://cloud.r-project.org/bin/linux/ubuntu $(lsb_release -cs)-cran40/\"\n\nRUN apt-key  adv --keyserver keyserver.ubuntu.com --recv-keys E084DAB9\n\nRUN apt-get update\nRUN apt-get upgrade -y\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get -y update \\\n  && apt-get install -y \\\n\tgdb \\\n\tgit \\\n\tlibcairo2-dev \\\n\tlibcurl4-openssl-dev \\\n\tlibexpat1-dev \\\n\tlibpq-dev \\\n\tlibsqlite3-dev \\\n\tlibudunits2-dev \\\n\tlibblosc-dev \\\n\tmake \\\n\tpandoc \\\n\tqpdf \\\n\tr-base-dev \\\n  \tsqlite3 \\\n\tsubversion \\\n\tvalgrind \\\n\tvim \\\n\ttk-dev \\\n\twget \\\n\tcmake \\\n\tlibtiff5-dev \\\n\tlibjq-dev \\\n\tlibprotobuf-dev \\\n\tlibxml2-dev \\\n\tlibprotobuf-dev \\\n\tprotobuf-compiler \\\n\tunixodbc-dev \\\n\tlibssh2-1-dev \\\n\tlibgit2-dev \\\n\tlibnetcdf-dev \\\n\tlocales \\\n\tlocales-all \\\n\tlibssl-dev \\\n    libhdf4-alt-dev \\\n\tlibtiff-dev \\\n\tdevscripts\n\nENV LC_ALL en_US.UTF-8\nENV LANG en_US.UTF-8\nENV LANGUAGE en_US.UTF-8\n\n# add arrow/parquet:\n# RUN apt install -y -V ca-certificates lsb-release wget # done\nRUN wget https://apache.jfrog.io/artifactory/arrow/$(lsb_release --id --short | tr 'A-Z' 'a-z')/apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb\nRUN apt install -y -V ./apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb\nRUN apt update\nRUN apt install -y -V libarrow-dev # For C++\nRUN apt install -y -V libarrow-glib-dev # For GLib (C)\nRUN apt install -y -V libarrow-dataset-dev # For Apache Arrow Dataset C++\nRUN apt install -y -V libarrow-dataset-glib-dev # For Apache Arrow Dataset GLib (C)\nRUN apt install -y -V libarrow-flight-dev # For Apache Arrow Flight C++\nRUN apt install -y -V libarrow-flight-glib-dev # For Apache Arrow Flight GLib (C)\n# Notes for Plasma related packages:\n#   * You need to enable \"non-free\" component on Debian GNU/Linux\n#   * You need to enable \"multiverse\" component on Ubuntu\n#   * You can use Plasma related packages only on amd64\nRUN apt install -y -V libplasma-dev # For Plasma C++\nRUN apt install -y -V libplasma-glib-dev # For Plasma GLib (C)\nRUN apt install -y -V libgandiva-dev # For Gandiva C++\nRUN apt install -y -V libgandiva-glib-dev # For Gandiva GLib (C)\nRUN apt install -y -V libparquet-dev # For Apache Parquet C++\nRUN apt install -y -V libparquet-glib-dev # For Apache Parquet GLib (C)\n\nRUN locale-gen en_US.UTF-8\n\nENV LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH\n\n# GEOS:\nENV GEOS_VERSION 3.11.0\n\nRUN wget -q http://download.osgeo.org/geos/geos-${GEOS_VERSION}.tar.bz2 \\\n  && bzip2 -d geos-*bz2 \\\n  && tar xf geos*tar \\\n  && cd geos* \\\n  && mkdir build \\\n  && cd build \\\n  && cmake .. \\\n  && make \\\n  && make install \\\n  && cd ../.. \\\n  && ldconfig\n\n#RUN git clone --depth 1 https://github.com/OSGeo/PROJ.git\n# https://download.osgeo.org/proj/proj-9.0.0RC1.tar.gz\nENV PROJ_VERSION 9.0.1\nRUN wget -q http://download.osgeo.org/proj/proj-${PROJ_VERSION}.tar.gz\nRUN tar zxvf proj-${PROJ_VERSION}.tar.gz\nRUN cd proj* \\\n  && ls -l \\\n  && mkdir build \\\n  && cd build \\\n  && cmake .. \\\n  && make \\\n  && make install \\\n  && cd ../.. \\\n  && ldconfig\n\n# GDAL:\nENV GDAL_VERSION 3.5.1\nENV GDAL_VERSION_NAME 3.5.1\n\nRUN wget -q http://download.osgeo.org/gdal/${GDAL_VERSION}/gdal-${GDAL_VERSION_NAME}.tar.gz \\\n  && tar -xf gdal-${GDAL_VERSION_NAME}.tar.gz \\\n  && cd gdal* \\\n  && mkdir build \\\n  && cd ./build \\\n  && cmake -DCMAKE_BUILD_TYPE=Release .. \\\n  && make \\\n  && make install \\\n  && ldconfig\n\nRUN Rscript -e 'install.packages(c(\"sp\", \"rgeos\", \"rgdal\", \"RPostgreSQL\", \"RSQLite\", \"testthat\", \"knitr\", \"tidyr\", \"geosphere\", \"maptools\", \"maps\", \"microbenchmark\", \"raster\", \"dplyr\", \"tibble\", \"units\", \"DBI\",  \"covr\", \"protolite\", \"tmap\", \"mapview\", \"odbc\", \"pool\", \"rmarkdown\", \"RPostgres\",\"spatstat\", \"stars\", \"XML\", \"tmaptools\", \"tmap\", \"terra\", \"PCICt\", \"RNetCDF\", \"future.apply\", \"ggforce\", \"ggthemes\", \"gstat\", \"ncmeta\", \"pbapply\", \"plm\", \"spacetime\", \"xts\", \"zoo\", \"tidync\", \"ncdfgeom\", \"cubelyr\", \"clue\", \"rmarkdown\", \"classInt\", \"mapview\", \"tmap\", \"exactextractr\"))'\n\nRUN git clone --depth 10 https://github.com/r-spatial/sf.git\nRUN git clone --depth 10 https://github.com/r-spatial/lwgeom.git\nRUN git clone --depth 10 https://github.com/r-spatial/stars.git\n#RUN git config --global user.email \"edzer.pebesma@uni-muenster.de\"\n\nRUN R CMD build --no-build-vignettes --no-manual lwgeom\nRUN R CMD build --no-build-vignettes --no-manual sf\n# RUN pkg-config proj --modversion\nRUN R CMD INSTALL sf\nRUN R CMD INSTALL lwgeom\nRUN R CMD INSTALL stars\n\n#RUN R CMD build --no-build-vignettes --no-manual sf\n#RUN R CMD check --no-build-vignettes --no-manual --as-cran sf_*.tar.gz \n#RUN R CMD check --no-build-vignettes --no-manual --as-cran lwgeom_*.tar.gz \n\n#RUN Rscript -e 'install.packages(\"starsdata\", repos=\"http://gis-bigdata.uni-muenster.de/pebesma/\")'\n#RUN R CMD build --no-manual stars\n#RUN _R_CHECK_FORCE_SUGGESTS_=false R CMD check --no-build-vignettes --no-manual --as-cran stars_*.tar.gz \n"
  },
  {
    "path": "inst/docker/base/Dockerfile",
    "content": "FROM ubuntu:16.04\n# minimal docker file to get sp and sf running on ubunty 16.04 image,\n# using gdal/geos/proj from ppa:ubuntugis/ubuntugis-unstable\n\nMAINTAINER \"edzerpebesma\" edzer.pebesma@uni-muenster.de\n\nRUN apt-get update && apt-get install -y software-properties-common\nRUN add-apt-repository ppa:ubuntugis/ubuntugis-unstable\n\nRUN echo \"deb http://cran.rstudio.com/bin/linux/ubuntu xenial/  \" >> /etc/apt/sources.list\nRUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E084DAB9\n\nRUN apt-get update\nRUN apt-get upgrade -y\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get -y update \\\n && apt-get install -y \\\n\tlibcurl4-openssl-dev \\\n\tqpdf \\\n\tpandoc \\\n\tmake \\\n\twget \\\n\tgit \\\n\tlibgdal-dev \\\n\tlibgeos-dev \\\n\tlibproj-dev \\\n\tliblwgeom-dev \\\n\tlibudunits2-dev \\\n\tpostgis \\\n\tr-base-dev\n\nRUN apt-get install -y texinfo \\\n       texlive-base \\\n       texlive-extra-utils \\\n       texlive-fonts-extra \\\n       texlive-fonts-recommended \\\n       texlive-generic-recommended \\\n       texlive-latex-base \\\n       texlive-latex-extra \\\n       texlive-latex-recommended\n\n# stuff for the tmaptools/rmapshaper/geojsonio etc stack:\nRUN apt-get install -y libv8-3.14-dev libprotobuf-dev protobuf-compiler libcairo2-dev\nRUN add-apt-repository -y ppa:opencpu/jq\nRUN apt-get update\nRUN apt-get install -y libjq-dev\n\nRUN Rscript -e 'install.packages(c(\"sf\", \"lwgeom\", \"covr\", \"raster\"), dependencies = TRUE, repos = \"https://cloud.r-project.org\")'\nRUN git clone   https://github.com/r-spatial/sf.git\nRUN R CMD build --no-build-vignettes sf\nRUN R CMD INSTALL sf_*tar.gz\n\nRUN apt-get install -y pandoc pandoc-citeproc\n\nRUN R CMD check --as-cran sf_*tar.gz\n\nCMD [\"/bin/bash\"]\n"
  },
  {
    "path": "inst/docker/bionic/Dockerfile",
    "content": "FROM ubuntu:18.04\n# minimal docker file to get sp and sf running on ubunty 16.04 image,\n# using gdal/geos/proj from ppa:ubuntugis/ubuntugis-unstable\n\nMAINTAINER \"edzerpebesma\" edzer.pebesma@uni-muenster.de\n\nRUN apt-get update && apt-get install -y software-properties-common\n#RUN add-apt-repository ppa:ubuntugis/ubuntugis-unstable\n\n#RUN echo \"deb http://cran.rstudio.com/bin/linux/ubuntu bionic/  \" >> /etc/apt/sources.list\nRUN echo \"deb http://cran.rstudio.com/bin/linux/ubuntu bionic-cran35/  \" >> /etc/apt/sources.list\n#RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E084DAB9\nRUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9\n\n\nRUN apt-get update\nRUN apt-get upgrade -y\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get -y update \\\n && apt-get install -y \\\n\tlibcurl4-openssl-dev \\\n\tqpdf \\\n\tpandoc \\\n\tmake \\\n\twget \\\n\tgit \\\n\tlibgdal-dev \\\n\tlibgeos-dev \\\n\tlibproj-dev \\\n\tliblwgeom-dev \\\n\tlibudunits2-dev \\\n\tpostgis \\\n\tr-base-dev\n\n# stuff for the tmaptools/rmapshaper/geojsonio etc stack:\nRUN apt-get install -y libv8-3.14-dev libprotobuf-dev protobuf-compiler libcairo2-dev\n#RUN add-apt-repository -y ppa:opencpu/jq\n#RUN apt-get update\nRUN apt-get install -y libjq-dev\n\nRUN Rscript -e 'install.packages(c(\"sf\", \"lwgeom\", \"covr\", \"raster\"), dependencies = TRUE, repos = \"https://cloud.r-project.org\")'\nRUN git clone   https://github.com/r-spatial/sf.git\nRUN R CMD build --no-build-vignettes sf\nRUN R CMD INSTALL sf_*tar.gz\n\nRUN apt-get install -y pandoc pandoc-citeproc\n\n#RUN R CMD check --as-cran sf_*tar.gz\n\nCMD [\"/bin/bash\"]\n"
  },
  {
    "path": "inst/docker/cran/Dockerfile",
    "content": "FROM debian:testing\n# minimal docker file to get sp and sf running on ubunty 16.04 image,\n# using gdal/geos/proj from ppa:ubuntugis/ubuntugis-unstable\n\nMAINTAINER \"edzerpebesma\" edzer.pebesma@uni-muenster.de\n\nRUN apt-get update\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get -y update \\\n  && apt-get install -y \\\n     ca-certificates \\\n\t gnupg2\n\nRUN echo \"deb https://statmath.wu.ac.at/AASC/debian testing main non-free\" >> /etc/apt/sources.list\nRUN echo \"deb http://ftp.de.debian.org/debian unstable main contrib non-free\" >> /etc/apt/sources.list\nRUN echo 'APT::Default-Release \"testing\";' >> /etc/apt/apt.conf\n\nRUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 2302BCB1\n\nRUN apt-get update\nRUN apt-get upgrade -y\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get install -y libv8-dev pdftk\nRUN apt-get -y clean\nRUN apt-get -y autoclean\nRUN apt-get install -y  kdelibs-bin kdelibs5-dev\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get install -y \\\n     rcheckserver\n\n### From here on: spatial R stack\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get install -y git\n\nRUN Rscript -e 'install.packages(c(\"sp\",\"rgeos\",\"rgdal\",\"RPostgreSQL\",\"RSQLite\",\"testthat\",\"knitr\",\"tidyr\",\"geosphere\",\"maptools\",\"maps\",\"microbenchmark\", \"raster\", \"dplyr\", \"tibble\", \"units\", \"DBI\",  \"covr\", \"protolite\", \"tmap\", \"mapview\", \"pool\", \"odbc\"), repos = \"https://cloud.r-project.org\")'\n\nRUN Rscript -e 'install.packages(\"sf\", dependencies = TRUE, repos = \"https://cloud.r-project.org\")'\n\n#RUN svn checkout svn://scm.r-forge.r-project.org/svnroot/rgdal/\n# or:\n# svn checkout svn+ssh://edzer@scm.r-forge.r-project.org/svnroot/rgdal/\n#RUN R CMD build rgdal/pkg --no-build-vignettes\n#RUN R CMD INSTALL rgdal_*.tar.gz \n\nRUN ls\nRUN git clone --depth 1 https://github.com/r-spatial/sf.git\nRUN R CMD build sf\nRUN R CMD INSTALL sf_*gz\n\n#RUN apt-get install -y unixodbc-dev\n\n#RUN Rscript -e 'install.packages(c(\"lwgeom\", \"tmap\", \"pool\", \"odbc\", \"mapview\"), repos = \"https://cloud.r-project.org\")'\n\n#RUN R CMD check --no-build-vignettes --no-manual --as-cran --run-dontrun sf_*tar.gz\nRUN R CMD check --as-cran sf_*tar.gz\n\nCMD [\"/bin/bash\"]\n"
  },
  {
    "path": "inst/docker/custom/Dockerfile",
    "content": "FROM ubuntu:18.04\n# minimal docker file to get sf running on an ubunty 16.04 image,\n# installing gdal, geos and proj.4 from source in a non-standard location\n\nMAINTAINER \"edzerpebesma\" edzer.pebesma@uni-muenster.de\n\nRUN apt-get update && apt-get install -y software-properties-common\nRUN add-apt-repository ppa:ubuntugis/ubuntugis-unstable\n\nRUN echo \"deb http://cran.rstudio.com/bin/linux/ubuntu bionic-cran35/  \" >> /etc/apt/sources.list\nRUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9\n\nRUN apt-get update\nRUN apt-get upgrade -y\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get -y update \\\n && apt-get install -y \\\n\tlibcurl4-openssl-dev \\\n\tlibsqlite3-dev \\\n\tsqlite3 \\\n\tqpdf \\\n\tpandoc \\\n\tmake \\\n\twget \\\n\tgit \\\n\tcmake \\\n\tlibudunits2-dev \\\n\tlibtiff5-dev \\\n\tpkg-config \\\n\tr-base-dev\n\nRUN cd \\\n\t&& mkdir /opt/proj /opt/share \\\n\t&& wget http://download.osgeo.org/proj/proj-7.0.0.tar.gz \\\n\t&& tar zxvf proj-7.0.0.tar.gz  \\\n\t&& cd proj-7.0.0 \\\n\t&& ./configure --prefix=/opt/proj --datadir=/opt/share \\\n\t&& make \\\n\t&& make install install-am\n\nRUN\tcd \\\n\t&& wget http://download.osgeo.org/gdal/3.0.4/gdal-3.0.4.tar.gz \\\n\t&& tar zxvf gdal-3.0.4.tar.gz \\\n\t&& cd gdal-3.0.4 \\\n\t&& mkdir /opt/gdal \\\n\t&& ./configure --prefix=/opt/gdal --with-proj=/opt/proj \\\n\t&& make \\\n\t&& make install\n\nRUN\tmkdir /opt/geos \\\n\t&& cd \\\n\t&& wget http://download.osgeo.org/geos/geos-3.8.1.tar.bz2 \\\n\t&& bunzip2 -c geos-3.8.1.tar.bz2 | tar xvf - \\\n\t&& cd geos-3.8.1 \\\n\t&& mkdir build \\\n\t&& cd build \\\n\t&& cmake -DCMAKE_INSTALL_PREFIX:PATH=/opt/geos .. \\\n\t&& make \\\n\t&& make install\n\t\nRUN R -e 'install.packages(c(\"Rcpp\", \"DBI\", \"units\", \"magrittr\", \"classInt\"), repos = \"https://cran.uni-muenster.de\")'\n\n#RUN\tcd /usr/share \\\n#\t&& mkdir proj \\\n#\t&& cd proj \\\n#\t&& wget https://download.osgeo.org/proj/proj-datumgrid-1.7.zip \\\n#\t&& unzip proj*zip\n\nRUN git clone --depth=1 https://github.com/r-spatial/sf.git\n\nRUN\tcd / \\\n\t&& R CMD build sf --no-build-vignettes\n\n# RUN PKG_CONFIG_PATH=/opt/proj/lib/pkgconfig PROJ_DATA=/opt/proj/share/proj GDAL_DATA=/opt/gdal/share/gdal/ LD_LIBRARY_PATH=/opt/gdal/lib:/opt/geos/lib:/opt/proj/lib R CMD INSTALL --configure-args='--with-gdal-config=/opt/gdal/bin/gdal-config --with-proj-include=/opt/proj/include --with-proj-lib=/opt/proj/lib --with-proj-share=/opt/proj/share/proj --with-proj-api=no --with-geos-config=/opt/geos/bin/geos-config' sf_*.tar.gz  \\\n# LD_LIBRARY_PATH=/opt/gdal/lib:/opt/geos/lib:/opt/proj/lib \n\nRUN export LD_LIBRARY_PATH=/opt/gdal/lib:/opt/geos/lib:/opt/proj/lib\n\nRUN LD_LIBRARY_PATH=/opt/gdal/lib:/opt/geos/lib:/opt/proj/lib \\\n\tPKG_CONFIG_PATH=/opt/proj/lib/pkgconfig \\\n\tPROJ_DATA=/opt/proj/share/proj \\\n\tGDAL_DATA=/opt/gdal/share/gdal/ \\\n\tR CMD INSTALL --configure-args='--with-gdal-config=/opt/gdal/bin/gdal-config \\\n\t\t--with-proj-include=/opt/proj/include --with-proj-lib=/opt/proj/lib \\\n\t\t--with-geos-config=/opt/geos/bin/geos-config' sf_*.tar.gz \n\nRUN LD_LIBRARY_PATH=/opt/gdal/lib:/opt/geos/lib:/opt/proj/lib R -e 'library(sf)'\n\nRUN git clone --depth=1 https://github.com/r-spatial/lwgeom.git\nRUN R CMD build --no-build-vignettes lwgeom\nRUN PKG_CONFIG_PATH=/opt/proj/lib/pkgconfig \\ \n\tLD_LIBRARY_PATH=/opt/gdal/lib:/opt/geos/lib:/opt/proj/lib R CMD INSTALL --configure-args='--with-proj-include=/opt/proj/include --with-proj-lib=/opt/proj/lib --with-geos-config=/opt/geos/bin/geos-config' lwgeom_*.tar.gz\n\nRUN PKG_CONFIG_PATH=/opt/proj/lib/pkgconfig LD_LIBRARY_PATH=/opt/gdal/lib:/opt/geos/lib:/opt/proj/lib PROJ_DATA=/opt/proj/share/proj GDAL_DATA=/opt/gdal/share/gdal/ R CMD INSTALL --configure-args='--with-proj-include=/opt/proj/include --with-proj-lib=/opt/proj/lib --with-geos-config=/opt/geos/bin/geos-config' lwgeom_*.tar.gz \\\n\t\nRUN LD_LIBRARY_PATH=/opt/gdal/lib:/opt/geos/lib:/opt/proj/lib R -e 'library(lwgeom)'\n\nRUN git clone --depth=1 https://github.com/r-spatial/stars.git\nRUN R CMD build --no-build-vignettes stars\nRUN R -e 'install.packages(c(\"abind\", \"rlang\"))'\nRUN LD_LIBRARY_PATH=/opt/gdal/lib:/opt/geos/lib:/opt/proj/lib R CMD INSTALL stars_*.tar.gz\nRUN LD_LIBRARY_PATH=/opt/gdal/lib:/opt/geos/lib:/opt/proj/lib R -e 'library(stars)'\n\nCMD [\"/bin/bash\"]\n"
  },
  {
    "path": "inst/docker/devel/Dockerfile",
    "content": "FROM ubuntu:24.04\n# minimal docker file to get sp and sf running on ubunty 16.04 image,\n# using gdal/geos/proj from ppa:ubuntugis/ubuntugis-unstable\n# \n\nMAINTAINER \"edzerpebesma\" edzer.pebesma@uni-muenster.de\n\n# update indices\nRUN apt-get update -qq\n# install two helper packages we need\nRUN apt-get install -y --no-install-recommends software-properties-common dirmngr\n# add the signing key (by Michael Rutter) for these repos\n# To verify key, run gpg --show-keys /etc/apt/trusted.gpg.d/cran_ubuntu_key.asc\n# Fingerprint: E298A3A825C0D65DFD57CBB651716619E084DAB9\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get install -y wget\nRUN wget -qO- https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc | tee -a /etc/apt/trusted.gpg.d/cran_ubuntu_key.asc\n# add the R 4.0 repo from CRAN -- adjust 'focal' to 'groovy' or 'bionic' as needed\n\nRUN add-apt-repository \"deb https://cloud.r-project.org/bin/linux/ubuntu $(lsb_release -cs)-cran40/\"\n\nRUN apt-get update\nRUN apt-get upgrade -y\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get -y update \\\n && apt-get install -y \\\n\tlibcurl4-openssl-dev \\\n\tqpdf \\\n\tpandoc \\\n\tmake \\\n\twget \\\n\tgit \\\n\tlibgdal-dev \\\n\tlibgeos-dev \\\n\tlibproj-dev \\\n\tlibudunits2-dev\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get install -y \\\n       texinfo \\\n       texlive-base \\\n       texlive-extra-utils \\\n       texlive-fonts-extra \\\n       texlive-fonts-recommended \\\n       texlive-latex-base \\\n       texlive-latex-extra \\\n       texlive-latex-recommended\n\n# texlive-generic-recommended \\\n\n# stuff for the tmaptools/rmapshaper/geojsonio etc stack:\nRUN apt-get install -y libv8-dev libprotobuf-dev protobuf-compiler libcairo2-dev pandoc # pandoc-citeproc \n#RUN add-apt-repository -y ppa:opencpu/jq\n#RUN apt-get update\nRUN apt-get install -y libjq-dev\n\n## Check out & build R-devel:\nRUN apt-get install -y subversion\n\nRUN cd /tmp && svn co https://svn.r-project.org/R/trunk R-devel\n\nRUN apt-get install -y rsync\nRUN /tmp/R-devel/tools/rsync-recommended\n## Build and install according the standard 'recipe' I emailed/posted years ago\n\nRUN apt-get install -y libreadline-dev libbz2-dev\n#RUN apt-get install -y gfortran\nRUN apt-get install -y r-base-dev\n\nRUN cd /tmp/R-devel \\\n\t&& R_PAPERSIZE=letter \\\n\t\tR_BATCHSAVE=\"--no-save --no-restore\" \\\n\t\tR_BROWSER=xdg-open \\\n\t\tPAGER=/usr/bin/pager \\\n\t\tPERL=/usr/bin/perl \\\n\t\tR_UNZIPCMD=/usr/bin/unzip \\\n\t\tR_ZIPCMD=/usr/bin/zip \\\n\t\tR_PRINTCMD=/usr/bin/lpr \\\n\t\tLIBnn=lib \\\n\t\tAWK=/usr/bin/awk \\\n\t\tCFLAGS=$(R CMD config CFLAGS) \\\n\t\tCXXFLAGS=$(R CMD config CXXFLAGS) \\\n\t./configure --enable-R-shlib \\\n               --without-blas \\\n               --without-lapack \\\n               --with-readline \\\n               --with-recommended-packages \\\n               --program-suffix=dev \\\n\t\t\t   --with-x=no \\\n\t&& make \\\n\t&& make install \\\n\t&& rm -rf /tmp/R-devel\n\n## Set default CRAN repo\nRUN echo 'options(repos = c(CRAN = \"https://cran.rstudio.com/\"), download.file.method = \"libcurl\")' >> /usr/local/lib/R/etc/Rprofile.site\n\nRUN Rscript -e 'install.packages(c(\"sf\", \"lwgeom\", \"covr\", \"raster\"), dependencies = TRUE, repos = \"https://cloud.r-project.org\")'\n\nRUN rm -fr sf\n\nRUN git clone https://github.com/r-spatial/sf.git\n\n# RUN R CMD build sf\n\n#ENV PROJ_VERSION 5.0.1\n#ENV LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH\n#RUN wget http://download.osgeo.org/proj/proj-${PROJ_VERSION}.tar.gz \\\n#  && tar zxf proj-*tar.gz \\\n#  && cd proj* \\\n#  && ./configure \\\n#  && make \\\n#  && make install \\\n#  && cd .. \\\n#  && ldconfig\n\nRUN apt-get install -y cmake\nRUN Rscript -e 'install.packages(c(\"s2\"), dependencies = FALSE, repos = \"https://cloud.r-project.org\")'\n#RUN Rscript -e 'install.packages(c(\"RPostgres\"), dependencies = FALSE, repos = \"https://cloud.r-project.org\")'\n\nRUN cd sf && git pull\nRUN R CMD build --no-build-vignettes sf\nRUN R CMD INSTALL sf_*tar.gz\nRUN Rscript -e 'install.packages(c(\"lwgeom\"), dependencies = FALSE, repos = \"https://cloud.r-project.org\")'\n\n# RUN Rscript -e 'install.packages(c(\"RPostgreSQL\"), dependencies = FALSE, repos = \"https://cloud.r-project.org\")'\nRUN _R_CHECK_FORCE_SUGGESTS_=false PROJ_LIB=/usr/share/proj R CMD check --as-cran sf_*tar.gz\n\nRUN wget https://cran.r-project.org/src/contrib/gstat_2.1-6.tar.gz\nRUN Rscript -e 'install.packages(c(\"stars\", \"sftime\"), dependencies = FALSE, repos = \"https://cloud.r-project.org\")'\nRUN Rscript -e 'install.packages(c(\"mapdata\"), repos = \"https://cloud.r-project.org\")'\nRUN _R_CHECK_FORCE_SUGGESTS_=false R CMD check gstat*gz\n\nCMD [\"/bin/bash\"]\n"
  },
  {
    "path": "inst/docker/fedora/Dockerfile",
    "content": "FROM fedora:latest\n\nMAINTAINER \"edzerpebesma\" edzer.pebesma@uni-muenster.de\n\nRUN yum install -y gdal-devel geos-devel udunits2-devel proj-devel\n# RUN yum install -y proj-devel proj-epsg proj-nad \nRUN yum install -y pandoc\nRUN yum install -y readline-devel curl-devel wget clang vim git autoconf sqlite-devel\nRUN yum install -y R-devel\n# needed by R packages:\nRUN yum install -y libxml2-devel openssl-devel cairo-devel postgresql-devel unixODBC-devel libuv-devel\n\n# install R-devel from source, with clang:\nRUN wget https://stat.ethz.ch/R/daily/R-devel.tar.gz\nRUN tar zxvf R-devel.tar.gz \n# Get https://www.stats.ox.ac.uk/pub/bdr/Rconfig/r-devel-linux-x86_64-fedora-clang into ./config.site:\nRUN echo $'CC=clang \\n\\\nOBJC=clang \\n\\\nCXX=clang++ \\n\\\nFC=gfortran \\n\\\nF77=gfortran \\n\\\nCFLAGS=\"-g -O3 -Wall -pedantic -mtune=native\" \\n\\\nFFLAGS=\"-g -O2 -mtune=native -Wall -pedantic\" \\n\\\nFCFLAGS=\"-g -O2 -mtune=native -Wall -pedantic\" \\n\\\nCXXFLAGS=\"-g -O3 -Wall -pedantic -mtune=native -frtti\" \\n\\\nCPPFLAGS=\"-I/usr/local/clang/include -I/usr/local/include\" \\n\\\nJAVA_HOME=/usr/lib/jvm/jre-11 \\n\\\nLDFLAGS=\"-L/usr/local/clang/lib64 -L/usr/local/lib64\"' > R-devel/config.site\n\nRUN (cd R-devel; ./configure --with-x=no --enable-R-shlib --without-lapack; make clean; make; make install)\n\nRUN /usr/local/bin/Rscript -e 'install.packages(c(\"XML\", \"Rcpp\", \"units\", \"DBI\", \"classInt\", \"magrittr\", \"lwgeom\", \"tibble\", \"knitr\", \"sp\", \"maps\", \"markdown\", \"testthat\", \"maptools\", \"dplyr\", \"rgeos\", \"rgdal\", \"tidyr\", \"stars\", \"rmarkdown\", \"covr\", \"ggplot2\", \"mapview\", \"microbenchmark\", \"odbc\", \"pool\", \"raster\", \"rmarkdown\", \"RPostgres\", \"RPostgreSQL\", \"RSQLite\", \"spatstat\", \"tmap\"), repos = \"https://cloud.r-project.org\")'\n\nRUN yum install -y abseil-cpp-devel\nRUN /usr/local/bin/Rscript -e 'install.packages(c(\"s2\", \"sf\"), repos = \"https://cloud.r-project.org\")'\n\n# get CRAN version of sf/lwgeom:\nRUN cd ..\n#RUN wget https://cran.r-project.org/src/contrib/lwgeom_0.2-2.tar.gz\nRUN /usr/local/bin/R -e 'install.packages(\"remotes\", repos = \"https://cloud.r-project.org\"); remotes::install_github(\"r-spatial/lwgeom\")'\nRUN /usr/local/bin/R -e 'install.packages(c(\"stars\", \"tmap\"), repos = \"https://cloud.r-project.org\")'\n#RUN /usr/local/bin/R CMD check --as-cran sf_0.8-1.tar.gz\nRUN rm -fr lwgeom\nRUN git clone --depth 1 https://github.com/r-spatial/lwgeom.git\nRUN R CMD build lwgeom\nRUN /usr/local/bin/Rscript -e 'install.packages(c(\"geosphere\"), repos = \"https://cloud.r-project.org\")'\n#RUN yum install -y xorg-x11-apps\n# RUN yum install -y xorg-x11-server-Xvfb\n# RUN yum /usr/bin/Xvfb :99 -screen 0 1280x1024x24 &\n# RUN /usr/local/bin/Rscript -e 'install.packages(c(\"Cairo\"), repos = \"https://cloud.r-project.org\")'\n\nRUN wget https://cran.r-project.org/src/contrib/gstat_2.1-5.tar.gz\nRUN /usr/local/bin/Rscript -e 'install.packages(c(\"zoo\", \"sftime\", \"spacetime\", \"FNN\"), repos = \"https://cloud.r-project.org\")'\nRUN /usr/local/bin/Rscript -e 'install.packages(c(\"mapdata\"), repos = \"https://cloud.r-project.org\")'\nRUN _R_CHECK_FORCE_SUGGESTS_=false /usr/local/bin/R CMD check --no-build-vignettes --no-build-manuals gstat_2.1-5.tar.gz\n\nCMD [\"/bin/bash\"]\n"
  },
  {
    "path": "inst/docker/gdal/Dockerfile",
    "content": "FROM ubuntu:24.04\n# minimal docker file to get sp and sf running on ubunty 16.04 image,\n# using gdal/geos/proj from ppa:ubuntugis/ubuntugis-unstable\n\nMAINTAINER \"edzerpebesma\" edzer.pebesma@uni-muenster.de\n\nRUN apt-get update && apt-get install -y software-properties-common dirmngr\nRUN add-apt-repository ppa:ubuntugis/ubuntugis-unstable\n\nRUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9\n\n# add the R 4.0 repo from CRAN -- adjust 'focal' to 'groovy' or 'bionic' as needed\nRUN add-apt-repository \"deb https://cloud.r-project.org/bin/linux/ubuntu $(lsb_release -cs)-cran40/\"\n\nRUN apt-key  adv --keyserver keyserver.ubuntu.com --recv-keys E084DAB9\n\nRUN apt-get update\nRUN apt-get upgrade -y\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get -y update \\\n  && apt-get install -y \\\n\tdevscripts \\\n\tgdb \\\n\tgit \\\n\tlibcairo2-dev \\\n\tlibcurl4-openssl-dev \\\n\tlibexpat1-dev \\\n\tlibpq-dev \\\n\tlibblosc-dev \\\n\tlibsqlite3-dev \\\n\tlibudunits2-dev \\\n\tmake \\\n\tpandoc \\\n\tqpdf \\\n\tr-base-dev \\\n  \tsqlite3 \\\n\tsubversion \\\n\tvalgrind \\\n\tvim \\\n\ttk-dev \\\n\twget\n\n#libv8-3.14-dev \\\nRUN apt-get update && apt-get install -y --fix-missing \\\n\tlibjq-dev \\\n\tlibprotobuf-dev \\\n\tlibxml2-dev \\\n\tlibprotobuf-dev \\\n\tprotobuf-compiler \\\n\tunixodbc-dev \\\n\tlibssh2-1-dev \\\n\tlibgit2-dev \\\n\tlibnetcdf-dev \\\n\tlocales \\\n\tlibssl-dev \\\n\tlibtiff-dev \\\n\tcmake \\\n\tlibtiff5-dev \\\n\tlibopenjp2-7-dev \\\n\tlibharfbuzz-dev \\\n\tlibharfbuzz-dev \\\n\tlibfribidi-dev\n\nRUN locale-gen en_US.UTF-8\nENV LANG en_US.UTF-8\nENV LANGUAGE en_US:en\nENV LC_ALL en_US.UTF-8\n\n#ENV PROJ_VERSION=7.1.0\nENV LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH\n\n# GEOS:\nENV GEOS_VERSION 3.14.1\nRUN wget -q http://download.osgeo.org/geos/geos-${GEOS_VERSION}.tar.bz2 \\\n  && bzip2 -d geos-*bz2 \\\n  && tar xf geos*tar \\\n  && cd geos* \\\n  && mkdir build \\\n  && cd build \\\n  && cmake .. \\\n  && make \\\n  && make install \\\n  && cd ../.. \\\n  && ldconfig\n\n# PROJ\nENV PROJ_VERSION 9.7.1\nRUN wget -q http://download.osgeo.org/proj/proj-${PROJ_VERSION}.tar.gz\nRUN tar zxvf proj-${PROJ_VERSION}.tar.gz\nRUN cd proj* \\\n  && ls -l \\\n  && mkdir build \\\n  && cd build \\\n  && cmake .. \\\n  && make \\\n  && make install \\\n  && cd ../.. \\\n  && ldconfig\n\n# GDAL:\nENV GDAL_VERSION 3.13.0\nENV GDAL_VERSION_NAME 3.13.0beta1\nRUN wget -q http://download.osgeo.org/gdal/${GDAL_VERSION}/gdal-${GDAL_VERSION_NAME}.tar.gz \\\n  && tar -xf gdal-${GDAL_VERSION_NAME}.tar.gz \\\n  && cd gdal* \\\n  && mkdir build \\\n  && cd ./build \\\n  && cmake -DCMAKE_BUILD_TYPE=Release .. \\\n  && make \\\n  && make install \\\n  && ldconfig\n\nRUN Rscript -e 'install.packages(c(\"sp\", \"RPostgreSQL\", \"RSQLite\", \"testthat\", \"knitr\", \"tidyr\", \"geosphere\", \"maps\", \"microbenchmark\", \"raster\", \"dplyr\", \"tibble\", \"units\", \"DBI\",  \"covr\", \"protolite\", \"tmap\", \"mapview\", \"odbc\", \"pool\", \"rmarkdown\", \"RPostgres\",\"spatstat\", \"stars\", \"XML\", \"tmaptools\", \"tmap\", \"terra\", \"PCICt\", \"RNetCDF\", \"future.apply\", \"ggforce\", \"ggthemes\", \"gstat\", \"ncmeta\", \"pbapply\", \"plm\", \"spacetime\", \"xts\", \"zoo\", \"tidync\", \"ncdfgeom\", \"cubelyr\", \"clue\", \"classInt\", \"mapdata\", \"ncdfgeom\", \"exactextractr\", \"randomForest\", \"nanoarrow\", \"tmap\", \"spatstat\", \"spatstat.linnet\", \"viridis\", \"CFtime\", \"tinytest\", \"lwgeom\", \"stars\"))'\n\n# sf:\nRUN git clone --depth 10 https://github.com/r-spatial/sf.git\nRUN (cd sf; git pull)\nRUN R CMD build --no-build-vignettes --no-manual sf\nRUN R CMD INSTALL sf_*.tar.gz\nRUN R CMD check --no-build-vignettes --no-manual --as-cran sf_*.tar.gz \n\n# lwgeom:\n#RUN git clone --depth 10 https://github.com/r-spatial/lwgeom.git\n#RUN R CMD build --no-build-vignettes --no-manual lwgeom\n#RUN R CMD INSTALL lwgeom_*.tar.gz\n#RUN R CMD check --no-build-vignettes --no-manual --as-cran lwgeom_*.tar.gz \n\n# stars:\n#RUN git clone --depth 10 https://github.com/r-spatial/stars.git\n#RUN R CMD build --no-manual stars\n#RUN R CMD INSTALL stars_*.tar.gz\n#RUN Rscript -e 'options(timeout=1200); install.packages(\"starsdata\", repos=\"http://cran.uni-muenster.de/pebesma/\")'\n#RUN _R_CHECK_FORCE_SUGGESTS_=false R CMD check --no-build-vignettes --no-manual --as-cran stars_*.tar.gz \n\n#\n#RUN export DEBIAN_FRONTEND=noninteractive; apt-get install -y --fix-missing libmagick++-dev\n#RUN Rscript -e 'install.packages(\"animation\")'\n\n# terra:\n#RUN wget -q https://cran.r-project.org/src/contrib/terra_1.8-80.tar.gz\n#RUN R CMD check --no-manual terra_1.8-80.tar.gz\n\n#RUN wget -q https://cran.r-project.org/src/contrib/vapour_0.12.0.tar.gz\n#RUN R -e 'install.packages(c(\"markdown\", \"spelling\"))'\n#RUN R CMD INSTALL vapour*gz\n#RUN R CMD check --no-manual vapour*gz\n\n#RUN R -e 'install.packages(c(\"gt\"))'\n#RUN wget -q https://cran.r-project.org/src/contrib/gdalraster_2.2.1.tar.gz\n#RUN R -e 'install.packages(c(\"RcppInt64\"))'\n#RUN R CMD INSTALL gdalraster*gz\n#RUN R CMD check --no-manual gdalraster*gz\n"
  },
  {
    "path": "inst/docker/gdal304/Dockerfile",
    "content": "FROM ubuntu:22.04\n# minimal docker file to get sp and sf running on ubunty 16.04 image,\n# using gdal/geos/proj from ppa:ubuntugis/ubuntugis-unstable\n\nMAINTAINER \"edzerpebesma\" edzer.pebesma@uni-muenster.de\n\nRUN apt-get update && apt-get install -y software-properties-common dirmngr\nRUN add-apt-repository ppa:ubuntugis/ubuntugis-unstable\n\nRUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9\n\n# add the R 4.0 repo from CRAN -- adjust 'focal' to 'groovy' or 'bionic' as needed\nRUN add-apt-repository \"deb https://cloud.r-project.org/bin/linux/ubuntu $(lsb_release -cs)-cran40/\"\n\nRUN apt-key  adv --keyserver keyserver.ubuntu.com --recv-keys E084DAB9\n\nRUN apt-get update\nRUN apt-get upgrade -y\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get -y update \\\n  && apt-get install -y \\\n\tgdb \\\n\tgit \\\n\tlibcairo2-dev \\\n\tlibcurl4-openssl-dev \\\n\tlibexpat1-dev \\\n\tlibpq-dev \\\n\tlibsqlite3-dev \\\n\tlibudunits2-dev \\\n\tmake \\\n\tpandoc \\\n\tqpdf \\\n\tr-base-dev \\\n  \tsqlite3 \\\n\tsubversion \\\n\tvalgrind \\\n\tvim \\\n\ttk-dev \\\n\twget\n\n#libv8-3.14-dev \\\nRUN apt-get install -y \\\n\tlibjq-dev \\\n\tlibprotobuf-dev \\\n\tlibxml2-dev \\\n\tlibprotobuf-dev \\\n\tprotobuf-compiler \\\n\tunixodbc-dev \\\n\tlibssh2-1-dev \\\n\tlibgit2-dev \\\n\tlibnetcdf-dev \\\n\tlocales \\\n\tlibssl-dev \\\n\tlibtiff-dev\n\nRUN locale-gen en_US.UTF-8\n\n#ENV PROJ_VERSION=7.1.0\nENV LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get -y update \\\n  && apt-get install -y \\\n\tcmake \\\n\tlibtiff5-dev\n\n# GEOS:\nENV GEOS_VERSION 3.8.0\n\nRUN wget -q http://download.osgeo.org/geos/geos-${GEOS_VERSION}.tar.bz2 \\\n  && bzip2 -d geos-*bz2 \\\n  && tar xf geos*tar \\\n  && cd geos* \\\n  && mkdir build \\\n  && cd build \\\n  && cmake .. \\\n  && make \\\n  && make install \\\n  && cd ../.. \\\n  && ldconfig\n\n#RUN git clone --depth 1 https://github.com/OSGeo/PROJ.git\n# https://download.osgeo.org/proj/proj-9.0.0RC1.tar.gz\nENV PROJ_VERSION 6.3.1\nRUN wget -q http://download.osgeo.org/proj/proj-${PROJ_VERSION}.tar.gz\nRUN tar zxvf proj-${PROJ_VERSION}.tar.gz\nRUN cd proj* \\\n  && ls -l \\\n  && mkdir build \\\n  && cd build \\\n  && cmake .. \\\n  && make \\\n  && make install \\\n  && cd ../.. \\\n  && ldconfig\n\n# install proj-data:\n#RUN cd /usr/local/share/proj \\\n#  && wget http://download.osgeo.org/proj/proj-data-1.1RC1.zip \\\n#  && unzip -o proj-data*zip \\\n#  && rm proj-data*zip \\\n#  && cd -\n\n# GDAL:\n\nENV GDAL_VERSION 3.0.4\nENV GDAL_VERSION_NAME 3.0.4\n\nRUN wget -q http://download.osgeo.org/gdal/${GDAL_VERSION}/gdal-${GDAL_VERSION_NAME}.tar.gz \\\n  && tar -xf gdal-${GDAL_VERSION_NAME}.tar.gz \\\n  && cd gdal* \\\n  && ./configure --disable-driver-cad \\\n  && make \\\n  && make install\n\nRUN R -e 'install.packages(c(\"remotes\", \"Rcpp\", \"s2\", \"e1071\", \"classInt\", \"units\", \"magrittr\", \"DBI\"))'\nRUN echo \"OK223\"\nRUN R -e 'remotes::install_github(\"r-spatial/sf\")'\nRUN R -e 'library(sf)'\n\nRUN Rscript -e 'install.packages(c(\"sp\", \"rgeos\", \"rgdal\", \"RPostgreSQL\", \"RSQLite\", \"testthat\", \"knitr\", \"tidyr\", \"geosphere\", \"maptools\", \"maps\", \"microbenchmark\", \"raster\", \"dplyr\", \"tibble\", \"units\", \"DBI\",  \"covr\", \"protolite\", \"tmap\", \"mapview\", \"odbc\", \"pool\", \"rmarkdown\", \"RPostgres\",\"spatstat\", \"stars\", \"XML\", \"tmaptools\", \"tmap\", \"terra\", \"PCICt\", \"RNetCDF\", \"future.apply\", \"ggforce\", \"ggthemes\", \"gstat\", \"ncmeta\", \"pbapply\", \"plm\", \"spacetime\", \"xts\", \"zoo\", \"tidync\", \"ncdfgeom\", \"cubelyr\", \"clue\", \"classInt\"))'\n\nRUN git clone --depth 10 https://github.com/r-spatial/sf.git\nRUN git clone --depth 10 https://github.com/r-spatial/lwgeom.git\nRUN git clone --depth 10 https://github.com/r-spatial/stars.git\n#RUN git config --global user.email \"edzer.pebesma@uni-muenster.de\"\n\nRUN R CMD build --no-build-vignettes --no-manual lwgeom\nRUN R CMD build --no-build-vignettes --no-manual sf\n# RUN pkg-config proj --modversion\nRUN R CMD INSTALL sf\nRUN R CMD INSTALL lwgeom\nRUN R CMD INSTALL stars\n\nRUN Rscript -e 'install.packages(c(\"mapview\", \"tmap\"))'\nRUN Rscript -e 'install.packages(c(\"spatstat\", \"spatstat.linnet\"))'\n\nRUN R CMD build --no-build-vignettes --no-manual sf\nRUN R CMD check --no-build-vignettes --no-manual --as-cran sf_*.tar.gz \nRUN R CMD check --no-build-vignettes --no-manual --as-cran lwgeom_*.tar.gz \n\n#RUN Rscript -e 'install.packages(\"starsdata\", repos=\"http://gis-bigdata.uni-muenster.de/pebesma/\")'\nRUN R CMD build --no-manual stars\nRUN Rscript -e 'install.packages(c(\"ncdfgeom\"))'\nRUN _R_CHECK_FORCE_SUGGESTS_=false R CMD check --no-build-vignettes --no-manual --as-cran stars_*.tar.gz \n"
  },
  {
    "path": "inst/docker/geos/Dockerfile",
    "content": "FROM ubuntu:18.04\n# minimal docker file to get sp and sf running on ubunty 16.04 image,\n# using gdal/geos/proj from ppa:ubuntugis/ubuntugis-unstable\n\nMAINTAINER \"edzerpebesma\" edzer.pebesma@uni-muenster.de\n\nRUN apt-get update && apt-get install -y software-properties-common\nRUN add-apt-repository ppa:ubuntugis/ubuntugis-unstable\n\nRUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9\nRUN echo \"deb https://cloud.r-project.org/bin/linux/ubuntu bionic-cran40/\" >> /etc/apt/sources.list\n\nRUN apt-key  adv --keyserver keyserver.ubuntu.com --recv-keys E084DAB9\n\nRUN apt-get update\nRUN apt-get upgrade -y\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get -y update \\\n  && apt-get install -y \\\n\tgdb \\\n\tgit \\\n\tlibcairo2-dev \\\n\tlibcurl4-openssl-dev \\\n\tlibexpat1-dev \\\n\tlibpq-dev \\\n\tlibsqlite3-dev \\\n\tlibudunits2-dev \\\n\tmake \\\n\tpandoc \\\n\tqpdf \\\n\tr-base-dev \\\n  \tsqlite3 \\\n\tsubversion \\\n\tvalgrind \\\n\tvim \\\n\ttk-dev \\\n\twget\n\nRUN apt-get install -y \\\n\tlibv8-3.14-dev \\\n\tlibjq-dev \\\n\tlibprotobuf-dev \\\n\tlibxml2-dev \\\n\tlibprotobuf-dev \\\n\tprotobuf-compiler \\\n\tunixodbc-dev \\\n\tlibssh2-1-dev \\\n\tlibgit2-dev \\\n\tlibnetcdf-dev \\\n\tlocales \\\n\tlibssl-dev \\\n\tlibtiff-dev\n\nRUN locale-gen en_US.UTF-8\n\nENV PROJ_VERSION=7.1.0\nENV LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get -y update \\\n  && apt-get install -y \\\n\tcmake \\\n\tlibtiff5-dev\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get -y update \\\n  && apt-get install -y autoconf\n\nRUN git clone --depth 1 https://github.com/libgeos/geos.git\nRUN (cd geos; git pull)\nRUN cd geos \\\n\t&& mkdir build \\\n\t&& cd build \\\n\t&& cmake .. \\\n\t&& make \\\n\t&& make install\n\n#RUN git clone --depth 1 https://github.com/OSGeo/PROJ.git\nRUN wget http://download.osgeo.org/proj/proj-8.0.0.tar.gz\nRUN tar zxvf proj-8.0.0.tar.gz\nRUN cd proj-8.0.0 \\\n  && ls -l \\\n  && mkdir build \\\n  && cd build \\\n  && cmake .. \\\n  && make \\\n  && make install \\\n  && cd ../.. \\\n  && ldconfig\n\n# install proj-data:\n#RUN cd /usr/local/share/proj \\\n#  && wget http://download.osgeo.org/proj/proj-data-1.1RC1.zip \\\n#  && unzip -o proj-data*zip \\\n#  && rm proj-data*zip \\\n#  && cd -\n\n# GDAL:\n\n# https://download.osgeo.org/gdal/3.1.0/gdal-3.1.0rc2.tar.gz\nENV GDAL_VERSION 3.3.0\nENV GDAL_VERSION_NAME 3.3.0rc1\n\nRUN wget http://download.osgeo.org/gdal/${GDAL_VERSION}/gdal-${GDAL_VERSION_NAME}.tar.gz \\\n  && tar -xf gdal-${GDAL_VERSION_NAME}.tar.gz \\\n  && cd gdal* \\\n  && ./configure \\\n  && make \\\n  && make install \\\n  && cd .. \\\n  && ldconfig\n\n# RUN svn  checkout svn://scm.r-forge.r-project.org/svnroot/rgdal/\n# RUN R CMD build rgdal/pkg --no-build-vignettes\n# RUN R CMD INSTALL rgdal_*.tar.gz \n\nRUN Rscript -e 'install.packages(c(\"sp\", \"rgeos\", \"rgdal\", \"RPostgreSQL\", \"RSQLite\", \"testthat\", \"knitr\", \"tidyr\", \"geosphere\", \"maptools\", \"maps\", \"microbenchmark\", \"raster\", \"dplyr\", \"tibble\", \"units\", \"DBI\",  \"covr\", \"protolite\", \"tmap\", \"mapview\", \"odbc\", \"pool\", \"rmarkdown\", \"RPostgres\",\"spatstat\", \"stars\"))'\n\nRUN git clone --depth 10 https://github.com/r-spatial/sf.git\nRUN git clone --depth 10 https://github.com/r-spatial/lwgeom.git\nRUN git clone --depth 10 https://github.com/r-spatial/stars.git\n#RUN git config --global user.email \"edzer.pebesma@uni-muenster.de\"\n\nRUN R CMD build --no-build-vignettes --no-manual lwgeom\nRUN (cd sf; git pull)\nRUN R CMD build --no-build-vignettes --no-manual sf\n# RUN pkg-config proj --modversion\nRUN R CMD INSTALL sf\nRUN R CMD INSTALL lwgeom\nRUN R CMD build --no-build-vignettes --no-manual stars\nRUN R CMD INSTALL stars\n\n\n#RUN svn  checkout svn://scm.r-forge.r-project.org/svnroot/rgdal/\n# or:\n# svn checkout svn+ssh://edzer@scm.r-forge.r-project.org/svnroot/rgdal/\n#RUN R CMD build rgdal/pkg --no-build-vignettes\n#RUN R CMD INSTALL rgdal_*.tar.gz \n#RUN R CMD check --no-vignettes --no-manual rgdal_*.tar.gz \n#RUN Rscript -e 'install.packages(c(\"stars\", \"tmap\"), repos = \"https://cloud.r-project.org\")'\n\nRUN Rscript -e 'install.packages(\"rgdal\", repos=\"http://R-Forge.R-project.org\")'\n# after rgdal:\nRUN Rscript -e 'install.packages(c(\"XML\"))'\nRUN Rscript -e 'install.packages(c(\"tmaptools\", \"tmap\", \"mapview\", \"s2\", \"terra\"))'\nRUN Rscript -e 'install.packages(\"rgeos\", repos=\"http://R-Forge.R-project.org\")'\n\nRUN echo\nRUN (cd sf; git pull)\nRUN R CMD build --no-build-vignettes --no-manual sf\nRUN R CMD check --no-manual --as-cran sf_*.tar.gz \n\n#RUN R CMD check --no-build-vignettes --no-manual --as-cran lwgeom_*.tar.gz \n\n#RUN Rscript -e 'install.packages(\"starsdata\", repos=\"http://gis-bigdata.uni-muenster.de/pebesma/\")'\n#RUN Rscript -e 'install.packages(c(\"PCICt\", \"RNetCDF\", \"future.apply\", \"ggforce\", \"ggthemes\", \"gstat\", \"ncmeta\", \"pbapply\", \"plm\", \"spacetime\", \"xts\", \"zoo\"))'\n#RUN Rscript -e 'install.packages(c(\"tidync\", \"ncdfgeom\", \"cubelyr\"))'\n#RUN echo echo\n#RUN (cd stars; git pull)\n#RUN R CMD build --no-manual stars\n#RUN _R_CHECK_FORCE_SUGGESTS_=false R CMD check --no-build-vignettes --no-manual --as-cran stars_*.tar.gz \n"
  },
  {
    "path": "inst/docker/lowest/Dockerfile",
    "content": "FROM rocker/r-ver\n# minimal docker file to get sf running on an ubunty 16.04 image,\n# installing gdal, geos and proj.4 from source in a non-standard location\n\nMAINTAINER \"edzerpebesma\" edzer.pebesma@uni-muenster.de\n\nRUN apt-get update\n#RUN apt-get -y remove libgdal-dev gdal-bin libgeos-dev libproj-dev \\\n#\tlibgeos-3.8.0 libgdal20 libproj15 proj-data\n\nRUN apt-get update && apt-get install -y software-properties-common wget\n#RUN add-apt-repository ppa:ubuntugis/ubuntugis-unstable\n\n#RUN echo \"deb http://cran.rstudio.com/bin/linux/ubuntu xenial/  \" >> /etc/apt/sources.list\n#RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E084DAB9\n\n#RUN apt-get update\n#RUN apt-get upgrade -y\n\n#RUN export DEBIAN_FRONTEND=noninteractive; apt-get -y update \\\n# && apt-get install -y \\\n#\tlibcurl4-openssl-dev \\\n#\tqpdf \\\n#\tpandoc \\\n#\tpandoc-citeproc \\\n#\tmake \\\n#\twget \\\n#\tgit \\\n#\tsubversion \\\n#\tlibudunits2-dev \\\n#\tlibsqlite3-dev \\\n#\tlibexpat1-dev \\\n#    libprotobuf-dev \\\n#    libv8-3.14-dev \\\n#    libcairo2-dev \\\n#\tprotobuf-compiler \\\n#\tlibxml2-dev \\\n#\tlibpq-dev \\\n#\tlibssh2-1-dev \\\n#    unixodbc-dev \\\n#\tr-base-dev\n#\n#RUN export DEBIAN_FRONTEND=noninteractive; \\\n#    add-apt-repository -y ppa:opencpu/jq; \\\n#    apt-get update; \\\n#    apt-get install -y \\\n#    libjq-dev\n\nRUN cd \\\n\t&& wget http://download.osgeo.org/proj/proj-4.8.0.tar.gz \\\n\t&& tar zxvf proj-4.8.0.tar.gz  \\\n\t&& cd proj-4.8.0/ \\\n\t&& ./configure \\\n\t&& make \\\n\t&& make install\n\n# for now, rgdal needs:\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get -y update \\\n && apt-get install -y \\\n\tlibcurl4-openssl-dev \\\n\tqpdf \\\n\tpandoc \\\n\tpandoc-citeproc \\\n\tmake \\\n\twget \\\n\tgit \\\n\tsubversion \\\n\tlibudunits2-dev \\\n\tlibsqlite3-dev \\\n\tlibexpat1-dev \\\n    libprotobuf-dev \\\n    libcairo2-dev \\\n\tprotobuf-compiler \\\n\tlibxml2-dev \\\n\tlibpq-dev \\\n\tlibssh2-1-dev \\\n    unixodbc-dev \\\n    libjq-dev\n\n#RUN export DEBIAN_FRONTEND=noninteractive; \\\n#    add-apt-repository -y ppa:opencpu/jq; \\\n#    apt-get update; \\\n#    apt-get install -y \\\n#    libjq-dev\n\nRUN\tcd \\\n\t&& wget http://download.osgeo.org/gdal/2.2.3/gdal-2.2.3.tar.gz \\\n\t&& tar zxvf gdal-2.2.3.tar.gz  \\\n\t&& cd gdal-2.2.3 \\\n\t&& ./configure \\\n\t&& make \\\n\t&& make install\n\t\nRUN\tcd \\\n\t&& wget http://download.osgeo.org/geos/geos-3.6.0.tar.bz2 \\\n\t&& bunzip2  geos-3.6.0.tar.bz2  \\\n\t&& tar xvf geos-3.6.0.tar  \\\n\t&& cd geos-3.6.0 \\\n\t&& ./configure \\\n\t&& make \\\n\t&& make install\n\nRUN ldconfig\n\nRUN svn checkout svn://scm.r-forge.r-project.org/svnroot/rgdal/\nRUN R CMD build rgdal/pkg --no-build-vignettes\nRUN R -e 'install.packages(c(\"sp\"))'\nRUN R CMD INSTALL rgdal_*.tar.gz\n\nRUN R -e 'install.packages(\"remotes\")'\n\nRUN echo \"ok\"\n#RUN R -e 'install.packages(\"sf\")'\nRUN R -e 'install.packages(c(\"Rcpp\", \"s2\", \"e1071\", \"classInt\", \"units\", \"magrittr\", \"DBI\"))'\nRUN ls\nRUN echo \"xxyyzz\"\nRUN R -e 'remotes::install_github(\"r-spatial/sf\")'\nRUN R -e 'library(sf)'\n\n# no rgdal:\nRUN R -e 'install.packages(c(\"Rcpp\", \"DBI\", \"units\", \"magrittr\", \"lwgeom\", \"maps\", \"rgeos\", \"sp\", \"raster\", \"spatstat\", \"tmap\", \"maptools\", \"RSQLite\", \"tibble\", \"pillar\", \"rlang\", \"dplyr\", \"tidyr\", \"RPostgres\", \"tidyselect\", \"ggplot2\", \"mapview\", \"testthat\", \"knitr\", \"covr\", \"microbenchmark\", \"rmarkdown\", \"RPostgreSQL\", \"devtools\", \"odbc\", \"pool\"))'\n\nRUN R -e 'library(sf)'\n\nRUN git clone https://github.com/r-spatial/sf.git\n\nRUN\tR CMD build sf\n\nRUN apt-get install -y libssl-dev\nRUN R -e 'install.packages(c(\"covr\", \"stars\"))'\nRUN ls\nRUN (cd sf; git pull)\nRUN R CMD build sf\nRUN\tR CMD check --no-manual sf_*.tar.gz\n\nCMD [\"/bin/bash\"]\n"
  },
  {
    "path": "inst/docker/parquet/Dockerfile",
    "content": "FROM ubuntu:22.04\n# minimal docker file to get sp and sf running on ubunty 16.04 image,\n# using gdal/geos/proj from ppa:ubuntugis/ubuntugis-unstable\n\nMAINTAINER \"edzerpebesma\" edzer.pebesma@uni-muenster.de\n\nRUN apt-get update && apt-get install -y software-properties-common dirmngr\nRUN add-apt-repository ppa:ubuntugis/ubuntugis-unstable\n\nRUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys E298A3A825C0D65DFD57CBB651716619E084DAB9\n\n# add the R 4.0 repo from CRAN -- adjust 'focal' to 'groovy' or 'bionic' as needed\nRUN add-apt-repository \"deb https://cloud.r-project.org/bin/linux/ubuntu $(lsb_release -cs)-cran40/\"\n\nRUN apt-key  adv --keyserver keyserver.ubuntu.com --recv-keys E084DAB9\n\nRUN apt-get update\nRUN apt-get upgrade -y\n\nRUN export DEBIAN_FRONTEND=noninteractive; apt-get -y update \\\n  && apt-get install -y \\\n\tdevscripts \\\n\tgdb \\\n\tgit \\\n\tlibcairo2-dev \\\n\tlibcurl4-openssl-dev \\\n\tlibexpat1-dev \\\n\tlibpq-dev \\\n\tlibsqlite3-dev \\\n\tlibudunits2-dev \\\n\tmake \\\n\tpandoc \\\n\tqpdf \\\n\tr-base-dev \\\n  \tsqlite3 \\\n\tsubversion \\\n\tvalgrind \\\n\tvim \\\n\ttk-dev \\\n\twget\n\n#libv8-3.14-dev \\\nRUN apt-get update && apt-get install -y --fix-missing \\\n\tlibjq-dev \\\n\tlibprotobuf-dev \\\n\tlibxml2-dev \\\n\tlibprotobuf-dev \\\n\tprotobuf-compiler \\\n\tunixodbc-dev \\\n\tlibssh2-1-dev \\\n\tlibgit2-dev \\\n\tlibnetcdf-dev \\\n\tlocales \\\n\tlibssl-dev \\\n\tlibtiff-dev \\\n\tcmake \\\n\tlibtiff5-dev \\\n\tlibopenjp2-7-dev\n\nRUN locale-gen en_US.UTF-8\n\n#ENV PROJ_VERSION=7.1.0\nENV LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH\n\n# GEOS:\nENV GEOS_VERSION 3.14.0\n\nRUN wget -q http://download.osgeo.org/geos/geos-${GEOS_VERSION}.tar.bz2 \\\n  && bzip2 -d geos-*bz2 \\\n  && tar xf geos*tar \\\n  && cd geos* \\\n  && mkdir build \\\n  && cd build \\\n  && cmake .. \\\n  && make \\\n  && make install \\\n  && cd ../.. \\\n  && ldconfig\n\n#RUN git clone --depth 1 https://github.com/OSGeo/PROJ.git\n# https://download.osgeo.org/proj/proj-9.0.0RC1.tar.gz\nENV PROJ_VERSION 9.7.1\nRUN wget -q http://download.osgeo.org/proj/proj-${PROJ_VERSION}.tar.gz\nRUN tar zxvf proj-${PROJ_VERSION}.tar.gz\nRUN cd proj* \\\n  && ls -l \\\n  && mkdir build \\\n  && cd build \\\n  && cmake .. \\\n  && make \\\n  && make install \\\n  && cd ../.. \\\n  && ldconfig\n\n# install proj-data:\n#RUN cd /usr/local/share/proj \\\n#  && wget http://download.osgeo.org/proj/proj-data-1.1RC1.zip \\\n#  && unzip -o proj-data*zip \\\n#  && rm proj-data*zip \\\n#  && cd -\n\n# FROM https://arrow.apache.org/install/ ; probably only a subset is needed:\nRUN apt update\nRUN apt install -y -V ca-certificates lsb-release wget\nRUN wget https://apache.jfrog.io/artifactory/arrow/$(lsb_release --id --short | tr 'A-Z' 'a-z')/apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb\nRUN apt install -y -V ./apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb\nRUN apt update\nRUN apt install -y -V libarrow-dev # For C++\nRUN apt install -y -V libarrow-glib-dev # For GLib (C)\nRUN apt install -y -V libarrow-dataset-dev # For Apache Arrow Dataset C++\nRUN apt install -y -V libarrow-dataset-glib-dev # For Apache Arrow Dataset GLib (C)\nRUN apt install -y -V libparquet-dev # For Apache Parquet C++\nRUN apt install -y -V libparquet-glib-dev # For Apache Parquet GLib (C)\n\n# GDAL:\nENV GDAL_VERSION 3.12.2\nENV GDAL_VERSION_NAME 3.12.2\n\nRUN wget -q http://download.osgeo.org/gdal/${GDAL_VERSION}/gdal-${GDAL_VERSION_NAME}.tar.gz \\\n  && tar -xf gdal-${GDAL_VERSION_NAME}.tar.gz \\\n  && cd gdal* \\\n  && mkdir build \\\n  && cd ./build \\\n  && cmake -DCMAKE_BUILD_TYPE=Release .. \\\n  && make \\\n  && make install \\\n  && ldconfig\n\nRUN gdalinfo --formats\n\nRUN Rscript -e 'install.packages(c(\"sf\"))'\nRUN Rscript -e 'sf::st_drivers(\"vector\", \"Arrow\")'\nRUN Rscript -e 'sf::st_drivers(\"vector\", \"Parquet\")'\n"
  },
  {
    "path": "inst/gml/fmi_test.gml",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<wfs:FeatureCollection\n    timeStamp=\"2017-07-13T13:12:35Z\"\n    numberMatched=\"22\"\n    numberReturned=\"22\"\n           xmlns:wfs=\"http://www.opengis.net/wfs/2.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n        xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:om=\"http://www.opengis.net/om/2.0\"\n        xmlns:ompr=\"http://inspire.ec.europa.eu/schemas/ompr/3.0\"\n        xmlns:omso=\"http://inspire.ec.europa.eu/schemas/omso/3.0\"\n        xmlns:gml=\"http://www.opengis.net/gml/3.2\" xmlns:gmd=\"http://www.isotc211.org/2005/gmd\"\n        xmlns:gco=\"http://www.isotc211.org/2005/gco\" xmlns:swe=\"http://www.opengis.net/swe/2.0\"\n        xmlns:gmlcov=\"http://www.opengis.net/gmlcov/1.0\"\n        xmlns:sam=\"http://www.opengis.net/sampling/2.0\"\n        xmlns:sams=\"http://www.opengis.net/samplingSpatial/2.0\"\n        xmlns:wml2=\"http://www.opengis.net/waterml/2.0\"\n\txmlns:target=\"http://xml.fmi.fi/namespace/om/atmosphericfeatures/1.0\"\n        xsi:schemaLocation=\"http://www.opengis.net/wfs/2.0 http://schemas.opengis.net/wfs/2.0/wfs.xsd\n        http://www.opengis.net/gmlcov/1.0 http://schemas.opengis.net/gmlcov/1.0/gmlcovAll.xsd\n        http://www.opengis.net/sampling/2.0 http://schemas.opengis.net/sampling/2.0/samplingFeature.xsd\n        http://www.opengis.net/samplingSpatial/2.0 http://schemas.opengis.net/samplingSpatial/2.0/spatialSamplingFeature.xsd\n        http://www.opengis.net/swe/2.0 http://schemas.opengis.net/sweCommon/2.0/swe.xsd\n        http://inspire.ec.europa.eu/schemas/ompr/3.0 http://inspire.ec.europa.eu/schemas/ompr/3.0/Processes.xsd\n        http://inspire.ec.europa.eu/schemas/omso/3.0 http://inspire.ec.europa.eu/schemas/omso/3.0/SpecialisedObservations.xsd\n        http://www.opengis.net/waterml/2.0 http://schemas.opengis.net/waterml/2.0/waterml2.xsd\n        http://xml.fmi.fi/namespace/om/atmosphericfeatures/1.0 http://xml.fmi.fi/schema/om/atmosphericfeatures/1.0/atmosphericfeatures.xsd\">\n   \n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-8xxARxbgkA5J421_WXtx16YlC32JTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDBy2aujXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-1\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-1\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-1-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-1-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-100965-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">100965</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Raasepori Jussarö</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000041</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2757</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-100965-1-1-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Raasepori</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-100965-1-1-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Raasepori Jussarö</gml:name>\n                                <gml:pos>59.82076 23.57309 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-1-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.3</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-KcXd5r6N8vkebEjSG.zxUiZWIomJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDBy2bujXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-2\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-2\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-2-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-2-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-100967-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">100967</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Salo Kiikala lentokenttä</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000126</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2777</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-100967-1-2-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Salo</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-100967-1-2-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Salo Kiikala lentokenttä</gml:name>\n                                <gml:pos>60.46415 23.64976 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-2-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>2.6</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-GFmJLMORft8jyl1MC0x7l63vBMSJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDBy2cOjXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-3\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-3\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-3-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-3-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-100968-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">100968</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Vantaa Helsinki-Vantaan lentoasema</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000063</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2974</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-100968-1-3-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Vantaa</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-100968-1-3-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Vantaa Helsinki-Vantaan lentoasema</gml:name>\n                                <gml:pos>60.32670 24.95675 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-3-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.1</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-hBRBA8VDFX9ZLwA.dD9Uq7jkiMKJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDBy2cujXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-4\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-4\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-4-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-4-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-100969-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">100969</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Inkoo Bågaskär</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000158</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2984</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-100969-1-4-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Inkoo</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-100969-1-4-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Inkoo Bågaskär</gml:name>\n                                <gml:pos>59.93114 24.01408 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-4-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.3</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-ToyE7mpc8s9RFRQDZd5swcRdyQOJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDBy3YujXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-5\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-5\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-5-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-5-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-100971-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">100971</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Helsinki Kaisaniemi</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000150</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2978</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-100971-1-5-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Helsinki</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-100971-1-5-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Helsinki Kaisaniemi</gml:name>\n                                <gml:pos>60.17523 24.94459 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-5-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.6</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-kv8O2QAcKlQg24QyjPpI_eQfVpqJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDBy3aOjXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-6\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-6\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-6-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-6-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-100974-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">100974</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Lohja Porla</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000023</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2706</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-100974-1-6-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Lohja</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-100974-1-6-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Lohja Porla</gml:name>\n                                <gml:pos>60.24446 24.04951 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-6-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.4</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-SXVWyrPYfLQt7seuJYmdrANMdTiJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDBy3bOjXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-7\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-7\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-7-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-7-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-100976-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">100976</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Vihti Maasoja</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000165</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2758</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-100976-1-7-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Vihti</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-100976-1-7-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Vihti Maasoja</gml:name>\n                                <gml:pos>60.41875 24.39862 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-7-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.4</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-yCyH2B0Vg1ozCS4FIk0OELORRCqJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDBy5bOjXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-8\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-8\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-8-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-8-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-100996-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">100996</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Helsinki Harmaja</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000153</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2795</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-100996-1-8-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Helsinki</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-100996-1-8-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Helsinki Harmaja</gml:name>\n                                <gml:pos>60.10512 24.97539 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-8-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.3</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-npd6DKIvDvw7gNJOx.MoYei_TSCJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDBy5bujXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-9\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-9\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-9-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-9-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-100997-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">100997</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Kirkkonummi Mäkiluoto</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000119</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2794</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-100997-1-9-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Kirkkonummi</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-100997-1-9-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Kirkkonummi Mäkiluoto</gml:name>\n                                <gml:pos>59.92014 24.34934 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-9-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.4</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-u3Zzp9UpDENLrw9rxGopUvSSYXCJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDFgwZujXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-10\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-10\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-10-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-10-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-101003-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">101003</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Helsinki Helsingin majakka</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000134</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2989</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-101003-1-10-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Helsinki</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-101003-1-10-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Helsinki Helsingin majakka</gml:name>\n                                <gml:pos>59.94898 24.92631 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-10-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.0</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-PRAWCoETeWjy5X6PT3u2sRM7GECJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDFgwaOjXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-11\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-11\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-11-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-11-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-101004-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">101004</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Helsinki Kumpula</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000138</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2998</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-101004-1-11-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Helsinki</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-101004-1-11-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Helsinki Kumpula</gml:name>\n                                <gml:pos>60.20307 24.96131 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-11-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.2</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-pRcTSnY0UVYTu01at.H55JPUzjeJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDFgwaujXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-12\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-12\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-12-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-12-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-101005-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">101005</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Espoo Sepänkylä</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000137</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2703</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-101005-1-12-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Espoo</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-101005-1-12-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Espoo Sepänkylä</gml:name>\n                                <gml:pos>60.20761 24.74152 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-12-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.2</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-1ei1xoSsocqT7SqpKqLxnbLoN4SJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDFgwbujXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-13\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-13\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-13-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-13-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-101007-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">101007</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Helsinki Rautatientori</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16011680</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2934</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-101007-1-13-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Helsinki</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-101007-1-13-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Helsinki Rautatientori</gml:name>\n                                <gml:pos>60.17169 24.94460 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-13-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.7</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-rDUgKMXD92k0OFS0fGv8eE8bpUyJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDFgyZOjXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-14\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-14\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-14-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-14-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-101022-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">101022</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Porvoo Kalbådagrund</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000007</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2987</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-101022-1-14-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Porvoo</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-101022-1-14-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Porvoo Kalbådagrund</gml:name>\n                                <gml:pos>59.98518 25.59855 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-14-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>2.7</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-YeL9vtCGrgM8ICSDWV3Bhr5JhJaJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDFgyZujXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-15\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-15\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-15-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-15-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-101023-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">101023</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Porvoo Emäsalo</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000110</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2991</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-101023-1-15-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Porvoo</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-101023-1-15-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Porvoo Emäsalo</gml:name>\n                                <gml:pos>60.20382 25.62546 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-15-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>2.9</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-NSySNpiz37QW2P4NWkuB3gICDiGJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDFgycOjXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-16\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-16\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-16-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-16-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-101028-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">101028</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Porvoo Harabacka</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000142</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2759</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-101028-1-16-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Porvoo</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-101028-1-16-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Porvoo Harabacka</gml:name>\n                                <gml:pos>60.39172 25.60730 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-16-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.1</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-Nyk8kgdv_0.yj5tVFng1.klAp7CJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDFgzcujXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-17\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-17\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-17-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-17-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-101039-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">101039</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Loviisa Orrengrund</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000050</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2992</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-101039-1-17-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Loviisa</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-101039-1-17-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Loviisa Orrengrund</gml:name>\n                                <gml:pos>60.27488 26.44457 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-17-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.0</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-FMnmiBqWap8.B.iFRTp6tvYD8_6JTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDFiycOjXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-18\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-18\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-18-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-18-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-101128-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">101128</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Somero Salkola</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16011860</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2949</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-101128-1-18-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Somero</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-101128-1-18-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Somero Salkola</gml:name>\n                                <gml:pos>60.64668 23.80559 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-18-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>2.4</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-J07hP0OiyST28p469.wyvGUlT9CJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDFizYOjXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-19\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-19\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-19-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-19-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-101130-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">101130</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Hyvinkää Hyvinkäänkylä</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000152</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2829</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-101130-1-19-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Hyvinkää</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-101130-1-19-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Hyvinkää Hyvinkäänkylä</gml:name>\n                                <gml:pos>60.59589 24.80300 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-19-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.2</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-TEjY0XyoPEgv4MRsOaQWhBalfoCJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWDFi0cujXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-20\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-20\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-20-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-20-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-101149-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">101149</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Nurmijärvi Röykkä</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16000151</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2983</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-101149-1-20-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Nurmijärvi</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-101149-1-20-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Nurmijärvi Röykkä</gml:name>\n                                <gml:pos>60.50878 24.65373 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-20-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>2.8</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-wUI7RdsH3tb4ATEuTqKNMHs0aVOJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mMWrFgycOjXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-21\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-21\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-21-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-21-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-151028-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">151028</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Helsinki Vuosaari satama</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-16011877</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">5720</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-151028-1-21-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Helsinki</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-151028-1-21-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Helsinki Vuosaari satama</gml:name>\n                                <gml:pos>60.20867 25.19590 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-21-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.3</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n\t    <wfs:member>\n                <omso:PointTimeSeriesObservation gml:id=\"WFS-vpdGwON3oHbVqG25kX5BIEMOAlWJTowsIWbbpdOt.Lnl5dsPTTv3c3Trvlw9NGXk6dZMOnZ5dOumnbl7YdnXLww6eULSxZc.ndU07ctr76FChGNj5c61ItCnHdOmjJq4Z2XdkqaduW199ChQjOzbdPPTk51mOG7Rw2ZujXl899_LJf39svLvy09MOLZliZmzD0y8.kTM2b8eHZlrUzab8aSu69MzhrbcPiJp59MO7HlpWroQGltw.IvDfj0c5wSQ.wm9ty9Mu.hh5YduXpl5c6yOmTD5a23Tz56d2epl8dKxp2Gc2t3XbPzU.mHpp37uc4TW49cOzT08yd2bfE1ufTD00791Tzwy1ub.GXdkw9MN_Jh07PLc59N_LLk49cvLzf05K4Qs23S6db8XPLy7Yemnfu5unXfLh6aMvJ06yYdOzy6ddNO3L2w7OuXhh08mh007ctPpl4TNDpp25bW_dlrGq1IY\">\n\n\t\t            <om:phenomenonTime>\n        <gml:TimePeriod  gml:id=\"time1-1-22\">\n          <gml:beginPosition>2014-01-01T00:00:00Z</gml:beginPosition>\n          <gml:endPosition>2014-01-01T00:00:00Z</gml:endPosition>\n        </gml:TimePeriod>\n      </om:phenomenonTime>\n      <om:resultTime>\n        <gml:TimeInstant gml:id=\"time2-1-22\">\n          <gml:timePosition>2014-01-01T00:00:00Z</gml:timePosition>\n        </gml:TimeInstant>\n      </om:resultTime>      \n\n\t\t<om:procedure xlink:href=\"http://xml.fmi.fi/inspire/process/opendata_daily\"/>\n   \t\t            <om:parameter>\n                <om:NamedValue>\n                    <om:name xlink:href=\"http://inspire.ec.europa.eu/codeList/ProcessParameterValue/value/groundObservation/observationIntent\"/>\n                    <om:value>\n\t\t\tatmosphere\n                    </om:value>\n                </om:NamedValue>\n            </om:parameter>\n\n                <om:observedProperty  xlink:href=\"http://data.fmi.fi/fmi-apikey/0253711c-056f-439b-af9d-a5a3a2920faf/meta?observableProperty=observation&amp;param=tday&amp;language=eng\"/>\n\t\t\t\t<om:featureOfInterest>\n                    <sams:SF_SpatialSamplingFeature gml:id=\"fi-1-22-tday\">\n          <sam:sampledFeature>\n\t\t<target:LocationCollection gml:id=\"sampled-target-1-22-tday\">\n\t\t    <target:member>\n\t\t    <target:Location gml:id=\"obsloc-fmisid-874863-pos-tday\">\n\t\t        <gml:identifier codeSpace=\"http://xml.fmi.fi/namespace/stationcode/fmisid\">874863</gml:identifier>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/name\">Espoo Tapiola</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/geoid\">-874863</gml:name>\n\t\t\t<gml:name codeSpace=\"http://xml.fmi.fi/namespace/locationcode/wmo\">2985</gml:name>\n\t\t\t<target:representativePoint xlink:href=\"#point-fmisid-874863-1-22-tday\"/>\n\t\t\t\n\t\t\t\n\t\t\t<target:region codeSpace=\"http://xml.fmi.fi/namespace/location/region\">Espoo</target:region>\n\t\t\t\n\t\t    </target:Location></target:member>\n\t\t</target:LocationCollection>\n \t   </sam:sampledFeature>\n                        <sams:shape>\n                            \n\t\t\t    <gml:Point gml:id=\"point-fmisid-874863-1-22-tday\" srsName=\"http://www.opengis.net/def/crs/EPSG/0/4258\" srsDimension=\"2\">\n                                <gml:name>Espoo Tapiola</gml:name>\n                                <gml:pos>60.17802 24.78732 </gml:pos>\n                            </gml:Point>\n                            \n                        </sams:shape>\n                    </sams:SF_SpatialSamplingFeature>\n                </om:featureOfInterest>\n\t\t  <om:result>\n                    <wml2:MeasurementTimeseries gml:id=\"obs-obs-1-22-tday\">                         \n                        <wml2:point>\n                            <wml2:MeasurementTVP> \n                                      <wml2:time>2014-01-01T00:00:00Z</wml2:time>\n\t\t\t\t      <wml2:value>3.4</wml2:value>\n                            </wml2:MeasurementTVP>\n                        </wml2:point>                         \n                    </wml2:MeasurementTimeseries>\n                </om:result>\n\n        </omso:PointTimeSeriesObservation>\n    </wfs:member>\n</wfs:FeatureCollection>\n"
  },
  {
    "path": "inst/include/sf.h",
    "content": "// Generated by using Rcpp::compileAttributes() -> do not edit by hand\n// Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393\n\n#ifndef RCPP_sf_H_GEN_\n#define RCPP_sf_H_GEN_\n\n#include \"sf_RcppExports.h\"\n\n#endif // RCPP_sf_H_GEN_\n"
  },
  {
    "path": "inst/include/sf_RcppExports.h",
    "content": "// Generated by using Rcpp::compileAttributes() -> do not edit by hand\n// Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393\n\n#ifndef RCPP_sf_RCPPEXPORTS_H_GEN_\n#define RCPP_sf_RCPPEXPORTS_H_GEN_\n\n#include <Rcpp.h>\n\nnamespace sf {\n\n    using namespace Rcpp;\n\n    namespace {\n        void validateSignature(const char* sig) {\n            Rcpp::Function require = Rcpp::Environment::base_env()[\"require\"];\n            require(\"sf\", Rcpp::Named(\"quietly\") = true);\n            typedef int(*Ptr_validate)(const char*);\n            static Ptr_validate p_validate = (Ptr_validate)\n                R_GetCCallable(\"sf\", \"_sf_RcppExport_validate\");\n            if (!p_validate(sig)) {\n                throw Rcpp::function_not_exported(\n                    \"C++ function with signature '\" + std::string(sig) + \"' not found in sf\");\n            }\n        }\n    }\n\n    inline Rcpp::List CPL_read_wkb(Rcpp::List wkb_list, bool EWKB = false, bool spatialite = false) {\n        typedef SEXP(*Ptr_CPL_read_wkb)(SEXP,SEXP,SEXP);\n        static Ptr_CPL_read_wkb p_CPL_read_wkb = NULL;\n        if (p_CPL_read_wkb == NULL) {\n            validateSignature(\"Rcpp::List(*CPL_read_wkb)(Rcpp::List,bool,bool)\");\n            p_CPL_read_wkb = (Ptr_CPL_read_wkb)R_GetCCallable(\"sf\", \"_sf_CPL_read_wkb\");\n        }\n        RObject rcpp_result_gen;\n        {\n            rcpp_result_gen = p_CPL_read_wkb(Shield<SEXP>(Rcpp::wrap(wkb_list)), Shield<SEXP>(Rcpp::wrap(EWKB)), Shield<SEXP>(Rcpp::wrap(spatialite)));\n        }\n        if (rcpp_result_gen.inherits(\"interrupted-error\"))\n            throw Rcpp::internal::InterruptedException();\n        if (Rcpp::internal::isLongjumpSentinel(rcpp_result_gen))\n            throw Rcpp::LongjumpException(rcpp_result_gen);\n        if (rcpp_result_gen.inherits(\"try-error\"))\n            throw Rcpp::exception(Rcpp::as<std::string>(rcpp_result_gen).c_str());\n        return Rcpp::as<Rcpp::List >(rcpp_result_gen);\n    }\n\n    inline Rcpp::List CPL_write_wkb(Rcpp::List sfc, bool EWKB = false) {\n        typedef SEXP(*Ptr_CPL_write_wkb)(SEXP,SEXP);\n        static Ptr_CPL_write_wkb p_CPL_write_wkb = NULL;\n        if (p_CPL_write_wkb == NULL) {\n            validateSignature(\"Rcpp::List(*CPL_write_wkb)(Rcpp::List,bool)\");\n            p_CPL_write_wkb = (Ptr_CPL_write_wkb)R_GetCCallable(\"sf\", \"_sf_CPL_write_wkb\");\n        }\n        RObject rcpp_result_gen;\n        {\n            rcpp_result_gen = p_CPL_write_wkb(Shield<SEXP>(Rcpp::wrap(sfc)), Shield<SEXP>(Rcpp::wrap(EWKB)));\n        }\n        if (rcpp_result_gen.inherits(\"interrupted-error\"))\n            throw Rcpp::internal::InterruptedException();\n        if (Rcpp::internal::isLongjumpSentinel(rcpp_result_gen))\n            throw Rcpp::LongjumpException(rcpp_result_gen);\n        if (rcpp_result_gen.inherits(\"try-error\"))\n            throw Rcpp::exception(Rcpp::as<std::string>(rcpp_result_gen).c_str());\n        return Rcpp::as<Rcpp::List >(rcpp_result_gen);\n    }\n\n}\n\n#endif // RCPP_sf_RCPPEXPORTS_H_GEN_\n"
  },
  {
    "path": "inst/nc/zarr.py",
    "content": "# from https://zarr.readthedocs.io/en/v1.1.0/tutorial.html\nimport zarr\nz = zarr.zeros((100, 100), chunks=(50, 50), dtype='i4')\nz[:] = 1\n#zarr.core.Array((10000, 10000), int32, chunks=(1000, 1000), order=C)\n#  compression: blosc; compression_opts: {'clevel': 5, 'cname': 'lz4', 'shuffle': 1}\n#  nbytes: 381.5M; nbytes_stored: 313; ratio: 1277955.3; initialized: 0/100\n#  store: builtins.dict\n\n# Example: persist in-memory zarr array `z` to disk\n#from zarr import DirectoryStore, open as zopen\nfrom zarr import DirectoryStore, open as zopen\n\nstore = DirectoryStore('ones.zarr')                 # directory on disk\ndst = zopen(store, mode='w',\n             shape=z.shape, chunks=z.chunks,\n             dtype=z.dtype, compressor=getattr(z, \"compressor\", None),\n             order=getattr(z, \"order\", \"C\"))\ndst[:] = z[:]                                           # copy data\ndst.attrs.update(z.attrs)                               # copy metadata (if any)\n\n# reopen later:\nz_on_disk = zopen(store, mode='r')\nz_on_disk\n"
  },
  {
    "path": "inst/osm/overpass.osm",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<osm version=\"0.6\" generator=\"Overpass API\">\n<note>The data included in this document is from www.openstreetmap.org. The data is made available under ODbL.</note>\n<meta osm_base=\"2017-01-12T19:15:02Z\"/>\n\n  <way id=\"6276899\" version=\"2\" timestamp=\"2016-09-02T00:42:29Z\" changeset=\"41859865\" uid=\"2160231\" user=\"rtwbike\">\n    <nd ref=\"52747250\"/>\n    <nd ref=\"52747253\"/>\n    <nd ref=\"52747257\"/>\n    <nd ref=\"52747260\"/>\n    <nd ref=\"52747247\"/>\n    <nd ref=\"52747250\"/>\n    <tag k=\"area\" v=\"yes\"/>\n    <tag k=\"leisure\" v=\"park\"/>\n    <tag k=\"name\" v=\"Parish Church Gardens (Penny Pocket Park)\"/>\n  </way>\n  <way id=\"6276900\" version=\"3\" timestamp=\"2016-09-02T00:42:29Z\" changeset=\"41859865\" uid=\"2160231\" user=\"rtwbike\">\n    <nd ref=\"52747235\"/>\n    <nd ref=\"52747243\"/>\n    <nd ref=\"52747245\"/>\n    <nd ref=\"52747207\"/>\n    <nd ref=\"1674081957\"/>\n    <nd ref=\"52747214\"/>\n    <nd ref=\"52747219\"/>\n    <nd ref=\"52747228\"/>\n    <nd ref=\"52747232\"/>\n    <nd ref=\"52747235\"/>\n    <tag k=\"area\" v=\"yes\"/>\n    <tag k=\"leisure\" v=\"park\"/>\n    <tag k=\"name\" v=\"Parish Church Gardens (Penny Pocket Park)\"/>\n  </way>\n  <way id=\"6278596\" version=\"5\" timestamp=\"2012-10-09T10:24:43Z\" changeset=\"13424748\" uid=\"10829\" user=\"myfanwy\">\n    <nd ref=\"52761021\"/>\n    <nd ref=\"52761025\"/>\n    <nd ref=\"52761028\"/>\n    <nd ref=\"52761032\"/>\n    <nd ref=\"52761021\"/>\n    <tag k=\"leisure\" v=\"park\"/>\n    <tag k=\"name\" v=\"Park Square\"/>\n  </way>\n  <way id=\"6962425\" version=\"3\" timestamp=\"2013-10-14T12:53:29Z\" changeset=\"18349806\" uid=\"1448930\" user=\"valavanisalex\">\n    <nd ref=\"54060356\"/>\n    <nd ref=\"54060340\"/>\n    <nd ref=\"54060343\"/>\n    <nd ref=\"54060348\"/>\n    <nd ref=\"54060488\"/>\n    <nd ref=\"54060352\"/>\n    <nd ref=\"696851549\"/>\n    <nd ref=\"54060421\"/>\n    <nd ref=\"54060376\"/>\n    <nd ref=\"54060356\"/>\n    <tag k=\"historic\" v=\"cemetery\"/>\n    <tag k=\"landuse\" v=\"cemetery\"/>\n    <tag k=\"leisure\" v=\"park\"/>\n    <tag k=\"name\" v=\"St. George's Fields\"/>\n    <tag k=\"note\" v=\"Leeds General Cemetery\"/>\n  </way>\n  <way id=\"15349618\" version=\"5\" timestamp=\"2016-09-02T00:51:49Z\" changeset=\"41859895\" uid=\"2160231\" user=\"rtwbike\">\n    <nd ref=\"152062004\"/>\n    <nd ref=\"152062014\"/>\n    <nd ref=\"152062017\"/>\n    <nd ref=\"152062020\"/>\n    <nd ref=\"152062025\"/>\n    <nd ref=\"1601125094\"/>\n    <nd ref=\"1601125089\"/>\n    <nd ref=\"152062027\"/>\n    <nd ref=\"152062031\"/>\n    <nd ref=\"1601125111\"/>\n    <nd ref=\"152062032\"/>\n    <nd ref=\"247199085\"/>\n    <nd ref=\"247199087\"/>\n    <nd ref=\"247199086\"/>\n    <nd ref=\"1601125097\"/>\n    <nd ref=\"152062004\"/>\n    <tag k=\"leisure\" v=\"park\"/>\n    <tag k=\"name\" v=\"Blackman Lane Rec\"/>\n  </way>\n  <way id=\"15349629\" version=\"1\" timestamp=\"2007-12-06T06:55:22Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <nd ref=\"152063395\"/>\n    <nd ref=\"152063403\"/>\n    <nd ref=\"152063407\"/>\n    <nd ref=\"152063409\"/>\n    <nd ref=\"152063415\"/>\n    <nd ref=\"152063423\"/>\n    <nd ref=\"152063428\"/>\n    <nd ref=\"152063434\"/>\n    <nd ref=\"152063440\"/>\n    <nd ref=\"152063447\"/>\n    <nd ref=\"152063453\"/>\n    <nd ref=\"152063458\"/>\n    <nd ref=\"152063464\"/>\n    <nd ref=\"152063469\"/>\n    <nd ref=\"152063476\"/>\n    <nd ref=\"152063497\"/>\n    <nd ref=\"152063480\"/>\n    <nd ref=\"152063489\"/>\n    <nd ref=\"152063492\"/>\n    <nd ref=\"152063395\"/>\n    <tag k=\"created_by\" v=\"JOSM\"/>\n    <tag k=\"leisure\" v=\"park\"/>\n  </way>\n  <way id=\"22770532\" version=\"3\" timestamp=\"2012-08-11T22:32:39Z\" changeset=\"12696590\" uid=\"2330\" user=\"LeedsTracker\">\n    <nd ref=\"244449800\"/>\n    <nd ref=\"244449801\"/>\n    <nd ref=\"244449802\"/>\n    <nd ref=\"1600382064\"/>\n    <nd ref=\"1600382067\"/>\n    <nd ref=\"333800530\"/>\n    <nd ref=\"244449803\"/>\n    <nd ref=\"1600381982\"/>\n    <nd ref=\"1862252961\"/>\n    <nd ref=\"244449800\"/>\n    <tag k=\"leisure\" v=\"park\"/>\n    <tag k=\"name\" v=\"Mandela Gardens\"/>\n  </way>\n  <way id=\"23203156\" version=\"5\" timestamp=\"2014-08-18T21:29:41Z\" changeset=\"24844489\" uid=\"493595\" user=\"Yorvik Prestigitator\">\n    <nd ref=\"250965488\"/>\n    <nd ref=\"1675168148\"/>\n    <nd ref=\"1675168156\"/>\n    <nd ref=\"1675168168\"/>\n    <nd ref=\"1675168175\"/>\n    <nd ref=\"1675168172\"/>\n    <nd ref=\"52162380\"/>\n    <nd ref=\"250965482\"/>\n    <nd ref=\"250965484\"/>\n    <nd ref=\"250965485\"/>\n    <nd ref=\"250965486\"/>\n    <nd ref=\"250965487\"/>\n    <nd ref=\"250965512\"/>\n    <nd ref=\"1675168162\"/>\n    <nd ref=\"3025778347\"/>\n    <nd ref=\"250965488\"/>\n    <tag k=\"leisure\" v=\"park\"/>\n    <tag k=\"name\" v=\"Lovell Park\"/>\n    <tag k=\"source\" v=\"OS_OpenData_StreetView;Bing\"/>\n  </way>\n  <way id=\"204237007\" version=\"2\" timestamp=\"2016-09-02T00:42:29Z\" changeset=\"41859865\" uid=\"2160231\" user=\"rtwbike\">\n    <nd ref=\"2142487690\"/>\n    <nd ref=\"2142487617\"/>\n    <nd ref=\"2142487652\"/>\n    <nd ref=\"2142487655\"/>\n    <nd ref=\"2142487656\"/>\n    <nd ref=\"2142487663\"/>\n    <nd ref=\"2142487680\"/>\n    <nd ref=\"2142487635\"/>\n    <nd ref=\"2142487638\"/>\n    <nd ref=\"2142487620\"/>\n    <nd ref=\"2142487668\"/>\n    <nd ref=\"2142487649\"/>\n    <nd ref=\"2142487690\"/>\n    <tag k=\"leisure\" v=\"park\"/>\n    <tag k=\"name\" v=\"Parish Church Gardens (Penny Pocket Park)\"/>\n  </way>\n  <way id=\"263958111\" version=\"2\" timestamp=\"2014-03-01T14:40:44Z\" changeset=\"20846249\" uid=\"1960653\" user=\"thomasforth\">\n    <nd ref=\"2696394059\"/>\n    <nd ref=\"2696394060\"/>\n    <nd ref=\"2696405845\"/>\n    <nd ref=\"2696394062\"/>\n    <nd ref=\"2696394063\"/>\n    <nd ref=\"2696394064\"/>\n    <nd ref=\"2696394059\"/>\n    <tag k=\"leisure\" v=\"park\"/>\n  </way>\n  <way id=\"301461256\" version=\"2\" timestamp=\"2015-10-27T09:58:52Z\" changeset=\"34899896\" uid=\"1802093\" user=\"Paul Berry\">\n    <nd ref=\"3055210547\"/>\n    <nd ref=\"3055210548\"/>\n    <nd ref=\"3055210549\"/>\n    <nd ref=\"3055210550\"/>\n    <nd ref=\"3055210551\"/>\n    <nd ref=\"3804710360\"/>\n    <nd ref=\"3055210552\"/>\n    <nd ref=\"3055210547\"/>\n    <tag k=\"leisure\" v=\"park\"/>\n  </way>\n  <way id=\"400895000\" version=\"1\" timestamp=\"2016-02-29T23:37:07Z\" changeset=\"37533403\" uid=\"493595\" user=\"Yorvik Prestigitator\">\n    <nd ref=\"3887608944\"/>\n    <nd ref=\"52635273\"/>\n    <nd ref=\"3887608929\"/>\n    <nd ref=\"3887608930\"/>\n    <nd ref=\"163639564\"/>\n    <nd ref=\"3887608941\"/>\n    <nd ref=\"3887608943\"/>\n    <nd ref=\"163639543\"/>\n    <nd ref=\"163639554\"/>\n    <nd ref=\"3887608944\"/>\n    <tag k=\"leisure\" v=\"park\"/>\n    <tag k=\"name\" v=\"Queen Square\"/>\n  </way>\n  <way id=\"462227487\" version=\"1\" timestamp=\"2016-12-28T01:42:22Z\" changeset=\"44719709\" uid=\"4543415\" user=\"The_JF\">\n    <nd ref=\"4576329772\"/>\n    <nd ref=\"4576329773\"/>\n    <nd ref=\"4576329774\"/>\n    <nd ref=\"4576329775\"/>\n    <nd ref=\"4576329772\"/>\n    <tag k=\"leisure\" v=\"park\"/>\n  </way>\n  <node id=\"2696394060\" lat=\"53.7952273\" lon=\"-1.5507185\" version=\"1\" timestamp=\"2014-03-01T14:27:39Z\" changeset=\"20845992\" uid=\"1960653\" user=\"thomasforth\"/>\n  <node id=\"2696405845\" lat=\"53.7951940\" lon=\"-1.5507158\" version=\"1\" timestamp=\"2014-03-01T14:40:43Z\" changeset=\"20846249\" uid=\"1960653\" user=\"thomasforth\"/>\n  <node id=\"3055210547\" lat=\"53.7966549\" lon=\"-1.5557631\" version=\"1\" timestamp=\"2014-09-02T12:19:56Z\" changeset=\"25180671\" uid=\"1802093\" user=\"Paul Berry\"/>\n  <node id=\"3055210548\" lat=\"53.7962240\" lon=\"-1.5558811\" version=\"1\" timestamp=\"2014-09-02T12:19:56Z\" changeset=\"25180671\" uid=\"1802093\" user=\"Paul Berry\"/>\n  <node id=\"3055210549\" lat=\"53.7962430\" lon=\"-1.5561789\" version=\"1\" timestamp=\"2014-09-02T12:19:56Z\" changeset=\"25180671\" uid=\"1802093\" user=\"Paul Berry\"/>\n  <node id=\"3055210550\" lat=\"53.7960339\" lon=\"-1.5562540\" version=\"1\" timestamp=\"2014-09-02T12:19:56Z\" changeset=\"25180671\" uid=\"1802093\" user=\"Paul Berry\"/>\n  <node id=\"3055210551\" lat=\"53.7961368\" lon=\"-1.5560555\" version=\"1\" timestamp=\"2014-09-02T12:19:56Z\" changeset=\"25180671\" uid=\"1802093\" user=\"Paul Berry\"/>\n  <node id=\"3055210552\" lat=\"53.7965673\" lon=\"-1.5548211\" version=\"2\" timestamp=\"2015-10-27T09:58:51Z\" changeset=\"34899896\" uid=\"1802093\" user=\"Paul Berry\"/>\n  <node id=\"3804710360\" lat=\"53.7964583\" lon=\"-1.5549475\" version=\"1\" timestamp=\"2015-10-27T09:58:51Z\" changeset=\"34899896\" uid=\"1802093\" user=\"Paul Berry\"/>\n  <node id=\"1862252961\" lat=\"53.8008654\" lon=\"-1.5489345\" version=\"1\" timestamp=\"2012-08-11T22:32:34Z\" changeset=\"12696590\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"52761021\" lat=\"53.7992292\" lon=\"-1.5526453\" version=\"3\" timestamp=\"2012-08-11T22:32:54Z\" changeset=\"12696590\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"52761025\" lat=\"53.7990343\" lon=\"-1.5510195\" version=\"3\" timestamp=\"2012-08-11T22:32:54Z\" changeset=\"12696590\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"52761028\" lat=\"53.7984831\" lon=\"-1.5512472\" version=\"3\" timestamp=\"2012-08-11T22:32:54Z\" changeset=\"12696590\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"52761032\" lat=\"53.7987335\" lon=\"-1.5528398\" version=\"4\" timestamp=\"2012-08-11T22:32:54Z\" changeset=\"12696590\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"244449800\" lat=\"53.8009096\" lon=\"-1.5489915\" version=\"4\" timestamp=\"2012-08-11T22:32:48Z\" changeset=\"12696590\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"244449801\" lat=\"53.8012087\" lon=\"-1.5489824\" version=\"4\" timestamp=\"2012-08-11T22:32:48Z\" changeset=\"12696590\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"244449802\" lat=\"53.8011813\" lon=\"-1.5485370\" version=\"3\" timestamp=\"2012-01-21T19:09:17Z\" changeset=\"10458708\" uid=\"21264\" user=\"Pobice\"/>\n  <node id=\"244449803\" lat=\"53.8008528\" lon=\"-1.5483826\" version=\"4\" timestamp=\"2012-01-21T19:09:17Z\" changeset=\"10458708\" uid=\"21264\" user=\"Pobice\"/>\n  <node id=\"333800530\" lat=\"53.8008512\" lon=\"-1.5484408\" version=\"2\" timestamp=\"2012-01-21T19:09:19Z\" changeset=\"10458708\" uid=\"21264\" user=\"Pobice\"/>\n  <node id=\"1600381982\" lat=\"53.8008200\" lon=\"-1.5483775\" version=\"1\" timestamp=\"2012-01-21T19:09:02Z\" changeset=\"10458708\" uid=\"21264\" user=\"Pobice\"/>\n  <node id=\"1600382064\" lat=\"53.8010620\" lon=\"-1.5485343\" version=\"1\" timestamp=\"2012-01-21T19:09:04Z\" changeset=\"10458708\" uid=\"21264\" user=\"Pobice\"/>\n  <node id=\"1600382067\" lat=\"53.8010641\" lon=\"-1.5484570\" version=\"1\" timestamp=\"2012-01-21T19:09:04Z\" changeset=\"10458708\" uid=\"21264\" user=\"Pobice\"/>\n  <node id=\"2696394059\" lat=\"53.7952732\" lon=\"-1.5506192\" version=\"1\" timestamp=\"2014-03-01T14:27:39Z\" changeset=\"20845992\" uid=\"1960653\" user=\"thomasforth\"/>\n  <node id=\"2696394062\" lat=\"53.7952621\" lon=\"-1.5504047\" version=\"1\" timestamp=\"2014-03-01T14:27:39Z\" changeset=\"20845992\" uid=\"1960653\" user=\"thomasforth\"/>\n  <node id=\"2696394063\" lat=\"53.7953620\" lon=\"-1.5503725\" version=\"1\" timestamp=\"2014-03-01T14:27:39Z\" changeset=\"20845992\" uid=\"1960653\" user=\"thomasforth\"/>\n  <node id=\"2696394064\" lat=\"53.7953807\" lon=\"-1.5505980\" version=\"2\" timestamp=\"2014-03-01T14:51:27Z\" changeset=\"20846428\" uid=\"1960653\" user=\"thomasforth\"/>\n  <node id=\"54060340\" lat=\"53.8082414\" lon=\"-1.5584900\" version=\"4\" timestamp=\"2012-02-23T20:23:32Z\" changeset=\"10772177\" uid=\"605122\" user=\"neiljp\"/>\n  <node id=\"54060343\" lat=\"53.8080337\" lon=\"-1.5571431\" version=\"3\" timestamp=\"2012-02-23T20:23:32Z\" changeset=\"10772177\" uid=\"605122\" user=\"neiljp\"/>\n  <node id=\"54060348\" lat=\"53.8077639\" lon=\"-1.5549085\" version=\"4\" timestamp=\"2012-02-23T20:23:32Z\" changeset=\"10772177\" uid=\"605122\" user=\"neiljp\"/>\n  <node id=\"152062004\" lat=\"53.8083215\" lon=\"-1.5468030\" version=\"2\" timestamp=\"2012-01-22T14:04:24Z\" changeset=\"10464976\" uid=\"308\" user=\"MichaelCollinson\"/>\n  <node id=\"152062014\" lat=\"53.8082167\" lon=\"-1.5466570\" version=\"1\" timestamp=\"2007-12-06T06:54:23Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152062017\" lat=\"53.8081481\" lon=\"-1.5466707\" version=\"1\" timestamp=\"2007-12-06T06:54:23Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063428\" lat=\"53.8083291\" lon=\"-1.5476788\" version=\"1\" timestamp=\"2007-12-06T06:55:14Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063434\" lat=\"53.8081653\" lon=\"-1.5475457\" version=\"1\" timestamp=\"2007-12-06T06:55:15Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063440\" lat=\"53.8081198\" lon=\"-1.5475289\" version=\"1\" timestamp=\"2007-12-06T06:55:15Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063447\" lat=\"53.8080941\" lon=\"-1.5475348\" version=\"1\" timestamp=\"2007-12-06T06:55:15Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063453\" lat=\"53.8080417\" lon=\"-1.5476219\" version=\"1\" timestamp=\"2007-12-06T06:55:15Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063458\" lat=\"53.8079942\" lon=\"-1.5477604\" version=\"1\" timestamp=\"2007-12-06T06:55:15Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063464\" lat=\"53.8080090\" lon=\"-1.5478455\" version=\"1\" timestamp=\"2007-12-06T06:55:15Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063469\" lat=\"53.8081391\" lon=\"-1.5482249\" version=\"1\" timestamp=\"2007-12-06T06:55:15Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063476\" lat=\"53.8081876\" lon=\"-1.5483446\" version=\"1\" timestamp=\"2007-12-06T06:55:15Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"4576329772\" lat=\"53.8034124\" lon=\"-1.5515020\" version=\"1\" timestamp=\"2016-12-28T01:42:21Z\" changeset=\"44719709\" uid=\"4543415\" user=\"The_JF\"/>\n  <node id=\"4576329773\" lat=\"53.8034116\" lon=\"-1.5515887\" version=\"1\" timestamp=\"2016-12-28T01:42:21Z\" changeset=\"44719709\" uid=\"4543415\" user=\"The_JF\"/>\n  <node id=\"4576329774\" lat=\"53.8032856\" lon=\"-1.5515851\" version=\"1\" timestamp=\"2016-12-28T01:42:21Z\" changeset=\"44719709\" uid=\"4543415\" user=\"The_JF\"/>\n  <node id=\"4576329775\" lat=\"53.8032865\" lon=\"-1.5514984\" version=\"1\" timestamp=\"2016-12-28T01:42:21Z\" changeset=\"44719709\" uid=\"4543415\" user=\"The_JF\"/>\n  <node id=\"52747207\" lat=\"53.7955132\" lon=\"-1.5357089\" version=\"4\" timestamp=\"2012-03-14T01:26:13Z\" changeset=\"10973816\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"52747214\" lat=\"53.7959245\" lon=\"-1.5357111\" version=\"5\" timestamp=\"2012-03-14T01:26:13Z\" changeset=\"10973816\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"52747219\" lat=\"53.7961411\" lon=\"-1.5342794\" version=\"4\" timestamp=\"2012-03-14T01:26:13Z\" changeset=\"10973816\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"52747228\" lat=\"53.7957210\" lon=\"-1.5343175\" version=\"3\" timestamp=\"2012-03-14T01:26:13Z\" changeset=\"10973816\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"52747232\" lat=\"53.7956015\" lon=\"-1.5343492\" version=\"3\" timestamp=\"2012-03-14T01:26:13Z\" changeset=\"10973816\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"52747235\" lat=\"53.7955654\" lon=\"-1.5344811\" version=\"3\" timestamp=\"2012-03-14T01:26:13Z\" changeset=\"10973816\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"52747243\" lat=\"53.7955068\" lon=\"-1.5345899\" version=\"3\" timestamp=\"2012-03-14T01:26:13Z\" changeset=\"10973816\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"52747245\" lat=\"53.7954477\" lon=\"-1.5346974\" version=\"4\" timestamp=\"2012-03-14T01:26:13Z\" changeset=\"10973816\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"52747247\" lat=\"53.7960329\" lon=\"-1.5356646\" version=\"5\" timestamp=\"2012-03-14T01:26:13Z\" changeset=\"10973816\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"52747250\" lat=\"53.7963833\" lon=\"-1.5356222\" version=\"6\" timestamp=\"2012-03-14T01:26:13Z\" changeset=\"10973816\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"52747253\" lat=\"53.7963696\" lon=\"-1.5344212\" version=\"4\" timestamp=\"2012-03-14T01:26:14Z\" changeset=\"10973816\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"52747257\" lat=\"53.7963203\" lon=\"-1.5343517\" version=\"6\" timestamp=\"2012-03-14T01:26:14Z\" changeset=\"10973816\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"52747260\" lat=\"53.7962001\" lon=\"-1.5343794\" version=\"5\" timestamp=\"2012-03-14T01:26:14Z\" changeset=\"10973816\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"1674081957\" lat=\"53.7956751\" lon=\"-1.5357219\" version=\"1\" timestamp=\"2012-03-14T01:25:43Z\" changeset=\"10973816\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"2142487617\" lat=\"53.7957161\" lon=\"-1.5358544\" version=\"1\" timestamp=\"2013-02-05T11:30:25Z\" changeset=\"14920827\" uid=\"215129\" user=\"inventor\"/>\n  <node id=\"2142487620\" lat=\"53.7956131\" lon=\"-1.5368656\" version=\"1\" timestamp=\"2013-02-05T11:30:25Z\" changeset=\"14920827\" uid=\"215129\" user=\"inventor\"/>\n  <node id=\"2142487635\" lat=\"53.7955545\" lon=\"-1.5365652\" version=\"1\" timestamp=\"2013-02-05T11:30:25Z\" changeset=\"14920827\" uid=\"215129\" user=\"inventor\"/>\n  <node id=\"2142487638\" lat=\"53.7955798\" lon=\"-1.5367073\" version=\"1\" timestamp=\"2013-02-05T11:30:25Z\" changeset=\"14920827\" uid=\"215129\" user=\"inventor\"/>\n  <node id=\"2142487649\" lat=\"53.7956923\" lon=\"-1.5368844\" version=\"1\" timestamp=\"2013-02-05T11:30:25Z\" changeset=\"14920827\" uid=\"215129\" user=\"inventor\"/>\n  <node id=\"2142487652\" lat=\"53.7956907\" lon=\"-1.5359054\" version=\"1\" timestamp=\"2013-02-05T11:30:26Z\" changeset=\"14920827\" uid=\"215129\" user=\"inventor\"/>\n  <node id=\"2142487655\" lat=\"53.7956325\" lon=\"-1.5359133\" version=\"1\" timestamp=\"2013-02-05T11:30:26Z\" changeset=\"14920827\" uid=\"215129\" user=\"inventor\"/>\n  <node id=\"2142487656\" lat=\"53.7955866\" lon=\"-1.5358650\" version=\"1\" timestamp=\"2013-02-05T11:30:26Z\" changeset=\"14920827\" uid=\"215129\" user=\"inventor\"/>\n  <node id=\"2142487663\" lat=\"53.7955260\" lon=\"-1.5358678\" version=\"1\" timestamp=\"2013-02-05T11:30:26Z\" changeset=\"14920827\" uid=\"215129\" user=\"inventor\"/>\n  <node id=\"2142487668\" lat=\"53.7956262\" lon=\"-1.5369191\" version=\"1\" timestamp=\"2013-02-05T11:30:26Z\" changeset=\"14920827\" uid=\"215129\" user=\"inventor\"/>\n  <node id=\"2142487680\" lat=\"53.7955355\" lon=\"-1.5363855\" version=\"1\" timestamp=\"2013-02-05T11:30:26Z\" changeset=\"14920827\" uid=\"215129\" user=\"inventor\"/>\n  <node id=\"2142487690\" lat=\"53.7957731\" lon=\"-1.5358490\" version=\"1\" timestamp=\"2013-02-05T11:30:26Z\" changeset=\"14920827\" uid=\"215129\" user=\"inventor\"/>\n  <node id=\"152062020\" lat=\"53.8078347\" lon=\"-1.5461852\" version=\"1\" timestamp=\"2007-12-06T06:54:24Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152062027\" lat=\"53.8082087\" lon=\"-1.5445742\" version=\"1\" timestamp=\"2007-12-06T06:54:24Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"1601125089\" lat=\"53.8075669\" lon=\"-1.5454836\" version=\"1\" timestamp=\"2012-01-22T14:04:20Z\" changeset=\"10464976\" uid=\"308\" user=\"MichaelCollinson\"/>\n  <node id=\"152062025\" lat=\"53.8076593\" lon=\"-1.5458525\" version=\"3\" timestamp=\"2014-11-14T22:56:29Z\" changeset=\"26788681\" uid=\"493595\" user=\"Yorvik Prestigitator\"/>\n  <node id=\"1601125094\" lat=\"53.8077160\" lon=\"-1.5457296\" version=\"2\" timestamp=\"2014-11-14T22:56:30Z\" changeset=\"26788681\" uid=\"493595\" user=\"Yorvik Prestigitator\"/>\n  <node id=\"52635273\" lat=\"53.8031787\" lon=\"-1.5452663\" version=\"3\" timestamp=\"2015-12-11T13:22:10Z\" changeset=\"35884537\" uid=\"1802093\" user=\"Paul Berry\"/>\n  <node id=\"163639543\" lat=\"53.8038548\" lon=\"-1.5453208\" version=\"3\" timestamp=\"2015-12-11T13:22:10Z\" changeset=\"35884537\" uid=\"1802093\" user=\"Paul Berry\"/>\n  <node id=\"163639554\" lat=\"53.8035169\" lon=\"-1.5458709\" version=\"3\" timestamp=\"2015-12-11T13:22:10Z\" changeset=\"35884537\" uid=\"1802093\" user=\"Paul Berry\"/>\n  <node id=\"163639564\" lat=\"53.8034678\" lon=\"-1.5446373\" version=\"2\" timestamp=\"2015-12-11T13:22:10Z\" changeset=\"35884537\" uid=\"1802093\" user=\"Paul Berry\"/>\n  <node id=\"3887608929\" lat=\"53.8032737\" lon=\"-1.5450397\" version=\"1\" timestamp=\"2015-12-11T13:22:08Z\" changeset=\"35884537\" uid=\"1802093\" user=\"Paul Berry\"/>\n  <node id=\"3887608930\" lat=\"53.8033830\" lon=\"-1.5448278\" version=\"1\" timestamp=\"2015-12-11T13:22:08Z\" changeset=\"35884537\" uid=\"1802093\" user=\"Paul Berry\"/>\n  <node id=\"3887608941\" lat=\"53.8035887\" lon=\"-1.5448509\" version=\"1\" timestamp=\"2015-12-11T13:22:08Z\" changeset=\"35884537\" uid=\"1802093\" user=\"Paul Berry\"/>\n  <node id=\"3887608943\" lat=\"53.8037566\" lon=\"-1.5451525\" version=\"1\" timestamp=\"2015-12-11T13:22:08Z\" changeset=\"35884537\" uid=\"1802093\" user=\"Paul Berry\"/>\n  <node id=\"3887608944\" lat=\"53.8032446\" lon=\"-1.5453842\" version=\"1\" timestamp=\"2015-12-11T13:22:08Z\" changeset=\"35884537\" uid=\"1802093\" user=\"Paul Berry\"/>\n  <node id=\"52162380\" lat=\"53.8025534\" lon=\"-1.5393098\" version=\"1\" timestamp=\"2007-09-15T18:22:26Z\" changeset=\"436551\" uid=\"592\" user=\"JonS\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"250965482\" lat=\"53.8035993\" lon=\"-1.5389931\" version=\"2\" timestamp=\"2012-03-15T00:30:20Z\" changeset=\"10984096\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"250965484\" lat=\"53.8034872\" lon=\"-1.5383624\" version=\"2\" timestamp=\"2012-03-15T00:30:20Z\" changeset=\"10984096\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"250965485\" lat=\"53.8034163\" lon=\"-1.5380279\" version=\"1\" timestamp=\"2008-03-07T10:44:19Z\" changeset=\"282245\" uid=\"25753\" user=\"Dave Fisher\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"250965486\" lat=\"53.8032183\" lon=\"-1.5368183\" version=\"1\" timestamp=\"2008-03-07T10:44:20Z\" changeset=\"282245\" uid=\"25753\" user=\"Dave Fisher\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"250965487\" lat=\"53.8031910\" lon=\"-1.5366867\" version=\"2\" timestamp=\"2012-03-15T00:30:20Z\" changeset=\"10984096\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"250965488\" lat=\"53.8019651\" lon=\"-1.5380095\" version=\"2\" timestamp=\"2012-03-15T00:30:20Z\" changeset=\"10984096\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"250965512\" lat=\"53.8028881\" lon=\"-1.5369206\" version=\"2\" timestamp=\"2012-03-15T00:30:20Z\" changeset=\"10984096\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"1675168148\" lat=\"53.8019663\" lon=\"-1.5381252\" version=\"1\" timestamp=\"2012-03-15T00:29:55Z\" changeset=\"10984096\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"1675168156\" lat=\"53.8022196\" lon=\"-1.5383056\" version=\"1\" timestamp=\"2012-03-15T00:29:56Z\" changeset=\"10984096\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"1675168168\" lat=\"53.8023744\" lon=\"-1.5386256\" version=\"1\" timestamp=\"2012-03-15T00:29:56Z\" changeset=\"10984096\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"1675168172\" lat=\"53.8024006\" lon=\"-1.5393303\" version=\"1\" timestamp=\"2012-03-15T00:29:56Z\" changeset=\"10984096\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"1675168175\" lat=\"53.8024307\" lon=\"-1.5391192\" version=\"1\" timestamp=\"2012-03-15T00:29:56Z\" changeset=\"10984096\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"1675168162\" lat=\"53.8023973\" lon=\"-1.5374202\" version=\"2\" timestamp=\"2014-08-18T21:29:38Z\" changeset=\"24844489\" uid=\"493595\" user=\"Yorvik Prestigitator\"/>\n  <node id=\"3025778347\" lat=\"53.8021243\" lon=\"-1.5377570\" version=\"1\" timestamp=\"2014-08-18T21:29:35Z\" changeset=\"24844489\" uid=\"493595\" user=\"Yorvik Prestigitator\"/>\n  <node id=\"54060352\" lat=\"53.8090773\" lon=\"-1.5546081\" version=\"4\" timestamp=\"2012-02-23T20:23:33Z\" changeset=\"10772177\" uid=\"605122\" user=\"neiljp\"/>\n  <node id=\"54060356\" lat=\"53.8096008\" lon=\"-1.5578287\" version=\"5\" timestamp=\"2012-02-23T20:23:33Z\" changeset=\"10772177\" uid=\"605122\" user=\"neiljp\"/>\n  <node id=\"54060376\" lat=\"53.8095464\" lon=\"-1.5574762\" version=\"3\" timestamp=\"2012-02-23T20:23:33Z\" changeset=\"10772177\" uid=\"605122\" user=\"neiljp\"/>\n  <node id=\"54060421\" lat=\"53.8093942\" lon=\"-1.5564884\" version=\"6\" timestamp=\"2012-04-04T18:14:52Z\" changeset=\"11179979\" uid=\"605122\" user=\"neiljp\">\n    <tag k=\"barrier\" v=\"gate\"/>\n    <tag k=\"foot\" v=\"yes\"/>\n  </node>\n  <node id=\"54060488\" lat=\"53.8086403\" lon=\"-1.5546978\" version=\"2\" timestamp=\"2011-12-27T14:53:26Z\" changeset=\"10216400\" uid=\"2330\" user=\"LeedsTracker\"/>\n  <node id=\"696851549\" lat=\"53.8092123\" lon=\"-1.5554093\" version=\"3\" timestamp=\"2013-10-14T12:53:28Z\" changeset=\"18349806\" uid=\"1448930\" user=\"valavanisalex\"/>\n  <node id=\"152063395\" lat=\"53.8085967\" lon=\"-1.5485440\" version=\"1\" timestamp=\"2007-12-06T06:55:14Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063403\" lat=\"53.8086185\" lon=\"-1.5484312\" version=\"1\" timestamp=\"2007-12-06T06:55:14Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063407\" lat=\"53.8086036\" lon=\"-1.5482289\" version=\"1\" timestamp=\"2007-12-06T06:55:14Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063409\" lat=\"53.8085779\" lon=\"-1.5480844\" version=\"1\" timestamp=\"2007-12-06T06:55:14Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063415\" lat=\"53.8085502\" lon=\"-1.5479603\" version=\"1\" timestamp=\"2007-12-06T06:55:14Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063423\" lat=\"53.8084399\" lon=\"-1.5478015\" version=\"1\" timestamp=\"2007-12-06T06:55:14Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063480\" lat=\"53.8084270\" lon=\"-1.5486469\" version=\"1\" timestamp=\"2007-12-06T06:55:16Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063489\" lat=\"53.8084676\" lon=\"-1.5486479\" version=\"1\" timestamp=\"2007-12-06T06:55:16Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063492\" lat=\"53.8085423\" lon=\"-1.5485974\" version=\"1\" timestamp=\"2007-12-06T06:55:16Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"152063497\" lat=\"53.8083752\" lon=\"-1.5485941\" version=\"1\" timestamp=\"2007-12-06T06:55:16Z\" changeset=\"133500\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"1601125097\" lat=\"53.8083885\" lon=\"-1.5467744\" version=\"1\" timestamp=\"2012-01-22T14:04:20Z\" changeset=\"10464976\" uid=\"308\" user=\"MichaelCollinson\"/>\n  <node id=\"152062031\" lat=\"53.8089100\" lon=\"-1.5457656\" version=\"2\" timestamp=\"2012-01-22T14:04:25Z\" changeset=\"10464976\" uid=\"308\" user=\"MichaelCollinson\"/>\n  <node id=\"152062032\" lat=\"53.8089801\" lon=\"-1.5459390\" version=\"2\" timestamp=\"2012-01-22T14:04:25Z\" changeset=\"10464976\" uid=\"308\" user=\"MichaelCollinson\"/>\n  <node id=\"247199085\" lat=\"53.8089782\" lon=\"-1.5460532\" version=\"2\" timestamp=\"2012-01-22T14:04:26Z\" changeset=\"10464976\" uid=\"308\" user=\"MichaelCollinson\"/>\n  <node id=\"247199086\" lat=\"53.8087121\" lon=\"-1.5463789\" version=\"2\" timestamp=\"2012-01-22T14:04:26Z\" changeset=\"10464976\" uid=\"308\" user=\"MichaelCollinson\"/>\n  <node id=\"247199087\" lat=\"53.8089552\" lon=\"-1.5461456\" version=\"1\" timestamp=\"2008-02-11T15:22:01Z\" changeset=\"99451\" uid=\"16809\" user=\"Geoff Richards\">\n    <tag k=\"created_by\" v=\"JOSM\"/>\n  </node>\n  <node id=\"1601125111\" lat=\"53.8089472\" lon=\"-1.5458357\" version=\"1\" timestamp=\"2012-01-22T14:04:21Z\" changeset=\"10464976\" uid=\"308\" user=\"MichaelCollinson\"/>\n\n</osm>\n"
  },
  {
    "path": "inst/shape/olinda1.prj",
    "content": "GEOGCS[\"GRS 1980(IUGG, 1980)\",DATUM[\"D_unknown\",SPHEROID[\"GRS80\",6378137,298.257222101]],PRIMEM[\"Greenwich\",0],UNIT[\"Degree\",0.017453292519943295]]"
  },
  {
    "path": "man/Ops.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/arith.R\n\\name{Ops}\n\\alias{Ops}\n\\alias{Ops.sfg}\n\\alias{Ops.sfc}\n\\title{Arithmetic operators for simple feature geometries}\n\\usage{\n\\method{Ops}{sfg}(e1, e2)\n\n\\method{Ops}{sfc}(e1, e2)\n}\n\\arguments{\n\\item{e1}{object of class \\code{sfg} or \\code{sfc}}\n\n\\item{e2}{numeric, or object of class \\code{sfg}; in case \\code{e1} is of class \\code{sfc} also an object of class \\code{sfc} is allowed}\n}\n\\value{\nobject of class \\code{sfg}\n}\n\\description{\nArithmetic operators for simple feature geometries\n}\n\\details{\nin case \\code{e2} is numeric, +, -, *, /, \\%\\% and \\%/\\% add, subtract, multiply, divide, modulo, or integer-divide by \\code{e2}. In case \\code{e2} is an n x n matrix, * matrix-multiplies and / multiplies by its inverse. If \\code{e2} is an \\code{sfg} object, |, /, & and \\%/\\% result in the geometric union, difference, intersection and symmetric difference respectively, and \\code{==} and \\code{!=} return geometric (in)equality, using \\link{st_equals}. If \\code{e2} is an \\code{sfg} or \\code{sfc} object, for operations \\code{+} and \\code{-} it has to have \\code{POINT} geometries.\n\nIf \\code{e1} is of class \\code{sfc}, and \\code{e2} is a length 2 numeric, then it is considered a two-dimensional point (and if needed repeated as such) only for operations \\code{+} and \\code{-}, in other cases the individual numbers are repeated; see commented examples.\n\nIt has been reported (https://github.com/r-spatial/sf/issues/2067) that\ncertain ATLAS versions result in invalid polygons, where the final point\nin a ring is no longer equal to the first point. In that case, setting\nthe precisions with \\link{st_set_precision} may help.\n}\n\\examples{\nst_point(c(1,2,3)) + 4\nst_point(c(1,2,3)) * 3 + 4\nm = matrix(0, 2, 2)\ndiag(m) = c(1, 3)\n# affine:\nst_point(c(1,2)) * m + c(2,5)\n# world in 0-360 range:\nif (require(maps, quietly = TRUE)) {\n w = st_as_sf(map('world', plot = FALSE, fill = TRUE))\n w2 = (st_geometry(w) + c(360,90)) \\%\\% c(360) - c(0,90)\n w3 = st_wrap_dateline(st_set_crs(w2 - c(180,0), 4326)) + c(180,0)\n plot(st_set_crs(w3, 4326), axes = TRUE)\n}\n(mp <- st_point(c(1,2)) + st_point(c(3,4))) # MULTIPOINT (1 2, 3 4)\nmp - st_point(c(3,4)) # POINT (1 2)\nopar = par(mfrow = c(2,2), mar = c(0, 0, 1, 0))\na = st_buffer(st_point(c(0,0)), 2)\nb = a + c(2, 0)\np = function(m) { plot(c(a,b)); plot(eval(parse(text=m)), col=grey(.9), add = TRUE); title(m) }\no = lapply(c('a | b', 'a / b', 'a & b', 'a \\%/\\% b'), p)\npar(opar)\nsfc = st_sfc(st_point(0:1), st_point(2:3))\nsfc + c(2,3) # added to EACH geometry\nsfc * c(2,3) # first geometry multiplied by 2, second by 3\nnc = st_transform(st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\")), 32119) # nc state plane, m\nb = st_buffer(st_centroid(st_union(nc)), units::set_units(50, km)) # shoot a hole in nc:\nplot(st_geometry(nc) / b, col = grey(.9))\n}\n"
  },
  {
    "path": "man/aggregate.sf.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/aggregate.R\n\\name{aggregate.sf}\n\\alias{aggregate.sf}\n\\alias{aggregate}\n\\title{aggregate an \\code{sf} object}\n\\usage{\n\\method{aggregate}{sf}(\n  x,\n  by,\n  FUN,\n  ...,\n  do_union = TRUE,\n  simplify = TRUE,\n  join = st_intersects\n)\n}\n\\arguments{\n\\item{x}{object of class \\link{sf}}\n\n\\item{by}{either a list of grouping vectors with length equal to \\code{nrow(x)} (see \\link[stats]{aggregate}), or an object of class \\code{sf} or \\code{sfc} with geometries that are used to generate groupings, using the binary predicate specified by the argument \\code{join}}\n\n\\item{FUN}{function passed on to \\link[stats]{aggregate}, in case \\code{ids} was specified and attributes need to be grouped}\n\n\\item{...}{arguments passed on to \\code{FUN}}\n\n\\item{do_union}{logical; should grouped geometries be unioned using \\link{st_union}? See details.}\n\n\\item{simplify}{logical; see \\link[stats]{aggregate}}\n\n\\item{join}{logical spatial predicate function to use if \\code{by} is a simple features object or geometry; see \\link{st_join}}\n}\n\\value{\nan \\code{sf} object with aggregated attributes and geometries; additional grouping variables having the names of \\code{names(ids)} or are named \\code{Group.i} for \\code{ids[[i]]}; see \\link[stats]{aggregate}.\n}\n\\description{\naggregate an \\code{sf} object, possibly union-ing geometries\n}\n\\details{\nIn case \\code{do_union} is \\code{FALSE}, \\code{aggregate} will simply combine geometries using \\link{c.sfg}. When polygons sharing a boundary are combined, this leads to geometries that are invalid; see \\url{https://github.com/r-spatial/sf/issues/681}.\n}\n\\note{\nDoes not work using the formula notation involving \\code{~} defined in \\link[stats]{aggregate}.\n}\n\\examples{\nm1 = cbind(c(0, 0, 1, 0), c(0, 1, 1, 0))\nm2 = cbind(c(0, 1, 1, 0), c(0, 0, 1, 0))\npol = st_sfc(st_polygon(list(m1)), st_polygon(list(m2)))\nset.seed(1985)\nd = data.frame(matrix(runif(15), ncol = 3))\np = st_as_sf(x = d, coords = 1:2)\nplot(pol)\nplot(p, add = TRUE)\n(p_ag1 = aggregate(p, pol, mean))\nplot(p_ag1) # geometry same as pol\n# works when x overlaps multiple objects in 'by':\np_buff = st_buffer(p, 0.2)\nplot(p_buff, add = TRUE)\n(p_ag2 = aggregate(p_buff, pol, mean)) # increased mean of second\n# with non-matching features\nm3 = cbind(c(0, 0, -0.1, 0), c(0, 0.1, 0.1, 0))\npol = st_sfc(st_polygon(list(m3)), st_polygon(list(m1)), st_polygon(list(m2)))\n(p_ag3 = aggregate(p, pol, mean))\nplot(p_ag3)\n# In case we need to pass an argument to the join function:\n(p_ag4 = aggregate(p, pol, mean, \n     join = function(x, y) st_is_within_distance(x, y, dist = 0.3)))\n}\n"
  },
  {
    "path": "man/bind.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/bind.R\n\\name{bind}\n\\alias{bind}\n\\alias{rbind.sf}\n\\alias{cbind.sf}\n\\alias{st_bind_cols}\n\\title{Bind rows (features) of sf objects}\n\\usage{\n\\method{rbind}{sf}(..., deparse.level = 1)\n\n\\method{cbind}{sf}(..., deparse.level = 1, sf_column_name = NULL)\n\nst_bind_cols(...)\n}\n\\arguments{\n\\item{...}{objects to bind; note that for the rbind and cbind methods, all objects have to be of class \\code{sf}; see \\link{dotsMethods}}\n\n\\item{deparse.level}{integer; see \\link{rbind}}\n\n\\item{sf_column_name}{character; specifies active geometry; passed on to \\link{st_sf}}\n}\n\\value{\n\\code{cbind} called with multiple \\code{sf} objects warns about multiple geometry columns present when the geometry column to use is not specified by using argument \\code{sf_column_name}; see also \\link{st_sf}.\n}\n\\description{\nBind rows (features) of sf objects\n\nBind columns (variables) of sf objects\n}\n\\details{\nboth \\code{rbind} and \\code{cbind} have non-standard method dispatch (see \\link[base]{cbind}): the \\code{rbind} or \\code{cbind} method for \\code{sf} objects is only called when all arguments to be binded are of class \\code{sf}.\n\nIf you need to \\code{cbind} e.g. a \\code{data.frame} to an \\code{sf}, use \\link{data.frame} directly and use \\link{st_sf} on its result, or use \\link[dplyr:bind]{bind_cols}; see examples.\n\n\\code{st_bind_cols} is deprecated; use \\code{cbind} instead.\n}\n\\examples{\ncrs = st_crs(3857)\na = st_sf(a=1, geom = st_sfc(st_point(0:1)), crs = crs)\nb = st_sf(a=1, geom = st_sfc(st_linestring(matrix(1:4,2))), crs = crs)\nc = st_sf(a=4, geom = st_sfc(st_multilinestring(list(matrix(1:4,2)))), crs = crs)\nrbind(a,b,c)\nrbind(a,b)\nrbind(a,b)\nrbind(b,c)\ncbind(a,b,c) # warns\nif (require(dplyr, quietly = TRUE))\n  dplyr::bind_cols(a,b)\nc = st_sf(a=4, geomc = st_sfc(st_multilinestring(list(matrix(1:4,2)))), crs = crs)\ncbind(a,b,c, sf_column_name = \"geomc\")\ndf = data.frame(x=3)\nst_sf(data.frame(c, df))\nif (require(dplyr, quietly = TRUE))\n  dplyr::bind_cols(c, df)\n}\n"
  },
  {
    "path": "man/coerce-methods.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sp.R\n\\name{as}\n\\alias{as}\n\\alias{Spatial}\n\\alias{sf-method}\n\\alias{coerce}\n\\alias{sfc-method}\n\\alias{Spatial-method}\n\\alias{as_Spatial}\n\\alias{crs}\n\\alias{CRS-method}\n\\title{Methods to coerce simple features to \\verb{Spatial*} and \\code{Spatial*DataFrame} objects}\n\\usage{\nas_Spatial(from, cast = TRUE, IDs = paste0(\"ID\", seq_along(from)))\n}\n\\arguments{\n\\item{from}{object of class \\code{sf}, \\code{sfc_POINT}, \\code{sfc_MULTIPOINT}, \\code{sfc_LINESTRING},\n\\code{sfc_MULTILINESTRING}, \\code{sfc_POLYGON}, or \\code{sfc_MULTIPOLYGON}.}\n\n\\item{cast}{logical; if \\code{TRUE}, \\code{\\link[=st_cast]{st_cast()}} \\code{from} before converting, so that e.g.\n\\code{GEOMETRY} objects with a mix of \\code{POLYGON} and \\code{MULTIPOLYGON} are cast to \\code{MULTIPOLYGON}.}\n\n\\item{IDs}{character vector with IDs for the \\verb{Spatial*} geometries}\n}\n\\value{\ngeometry-only object deriving from \\code{Spatial}, of the appropriate class\n}\n\\description{\n\\code{\\link[=as_Spatial]{as_Spatial()}} allows to convert \\code{sf} and \\code{sfc} to \\code{Spatial*DataFrame} and\n\\verb{Spatial*} for \\code{sp} compatibility. You can also use \\code{as(x, \"Spatial\")} To transform\n\\code{sp} objects to \\code{sf} and \\code{sfc} with \\code{as(x, \"sf\")}.\n}\n\\details{\nPackage \\code{sp} supports three dimensions for \\code{POINT} and \\code{MULTIPOINT} (\\verb{SpatialPoint*}).\nOther geometries must be two-dimensional (\\code{XY}). Dimensions can be dropped using\n\\code{\\link[=st_zm]{st_zm()}} with \\code{what = \"M\"} or \\code{what = \"ZM\"}.\n\nFor converting simple features (i.e., \\code{sf} objects) to their \\code{Spatial} counterpart, use \\code{as(obj, \"Spatial\")}\n}\n\\examples{\nnc <- st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\nif (require(sp, quietly = TRUE)) {\n# convert to SpatialPolygonsDataFrame\nspdf <- as_Spatial(nc)\n# identical to\nspdf <- as(nc, \"Spatial\")\n# convert to SpatialPolygons\nas(st_geometry(nc), \"Spatial\")\n# back to sf\nas(spdf, \"sf\")\n}\n}\n"
  },
  {
    "path": "man/dbDataType.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/db.R\n\\name{dbDataType,PostgreSQLConnection,sf-method}\n\\alias{dbDataType,PostgreSQLConnection,sf-method}\n\\alias{dbDataType,DBIObject,sf-method}\n\\title{Determine database type for R vector}\n\\usage{\n\\S4method{dbDataType}{PostgreSQLConnection,sf}(dbObj, obj)\n\n\\S4method{dbDataType}{DBIObject,sf}(dbObj, obj)\n}\n\\arguments{\n\\item{dbObj}{DBIObject driver or connection.}\n\n\\item{obj}{Object to convert}\n}\n\\description{\nDetermine database type for R vector\n\nDetermine database type for R vector\n}\n"
  },
  {
    "path": "man/dbWriteTable.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/db.R\n\\name{dbWriteTable,PostgreSQLConnection,character,sf-method}\n\\alias{dbWriteTable,PostgreSQLConnection,character,sf-method}\n\\alias{dbWriteTable,DBIObject,character,sf-method}\n\\title{Write \\code{sf} object to Database}\n\\usage{\n\\S4method{dbWriteTable}{PostgreSQLConnection,character,sf}(\n  conn,\n  name,\n  value,\n  ...,\n  row.names = FALSE,\n  overwrite = FALSE,\n  append = FALSE,\n  field.types = NULL,\n  binary = TRUE\n)\n\n\\S4method{dbWriteTable}{DBIObject,character,sf}(\n  conn,\n  name,\n  value,\n  ...,\n  row.names = FALSE,\n  overwrite = FALSE,\n  append = FALSE,\n  field.types = NULL,\n  binary = TRUE\n)\n}\n\\arguments{\n\\item{conn}{DBIObject}\n\n\\item{name}{\n   character vector of names (table names, fields, keywords).\n}\n\n\\item{value}{\n   a data.frame.\n}\n\n\\item{...}{\n   placeholder for future use.\n}\n\n\\item{row.names}{Add a \\code{row.name} column, or a vector of length \\code{nrow(obj)}\ncontaining row.names; default \\code{FALSE}.}\n\n\\item{overwrite}{Will try to \\code{drop} table before writing; default \\code{FALSE}.}\n\n\\item{append}{Append rows to existing table; default \\code{FALSE}.}\n\n\\item{field.types}{default \\code{NULL}. Allows to override type conversion from R\nto PostgreSQL. See \\code{dbDataType()} for details.}\n\n\\item{binary}{Send geometries serialized as Well-Known Binary (WKB);\nif \\code{FALSE}, uses Well-Known Text (WKT). Defaults to \\code{TRUE} (WKB).}\n}\n\\description{\nWrite \\code{sf} object to Database\n\nWrite \\code{sf} object to Database\n}\n"
  },
  {
    "path": "man/db_drivers.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/read.R\n\\docType{data}\n\\name{db_drivers}\n\\alias{db_drivers}\n\\title{Drivers for which update should be \\code{TRUE} by default}\n\\usage{\ndb_drivers\n}\n\\description{\nDrivers for which update should be \\code{TRUE} by default\n}\n"
  },
  {
    "path": "man/dot-stop_geos.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/geom-transformers.R\n\\name{.stop_geos}\n\\alias{.stop_geos}\n\\title{Internal functions}\n\\usage{\n.stop_geos(msg)\n}\n\\arguments{\n\\item{msg}{error message}\n}\n\\description{\nInternal functions\n}\n\\keyword{internal}\n"
  },
  {
    "path": "man/extension_map.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/read.R\n\\docType{data}\n\\name{extension_map}\n\\alias{extension_map}\n\\title{Map extension to driver}\n\\usage{\nextension_map\n}\n\\description{\nMap extension to driver\n}\n"
  },
  {
    "path": "man/gdal.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/stars.R\n\\name{gdal}\n\\alias{gdal}\n\\alias{gdal_read}\n\\alias{gdal_write}\n\\alias{gdal_inv_geotransform}\n\\alias{gdal_crs}\n\\alias{gdal_metadata}\n\\alias{gdal_subdatasets}\n\\alias{gdal_polygonize}\n\\alias{gdal_rasterize}\n\\alias{gdal_extract}\n\\alias{gdal_read_mdim}\n\\alias{gdal_write_mdim}\n\\alias{gdal_create}\n\\title{functions to interact with gdal not meant to be called directly by users (but e.g. by stars::read_stars)}\n\\usage{\ngdal_read(\n  x,\n  ...,\n  options = character(0),\n  driver = character(0),\n  read_data = TRUE,\n  NA_value = NA_real_,\n  RasterIO_parameters = list()\n)\n\ngdal_write(\n  x,\n  ...,\n  file,\n  driver = \"GTiff\",\n  options = character(0),\n  type = \"Float32\",\n  NA_value = NA_real_,\n  geotransform,\n  update = FALSE,\n  scale_offset = c(1, 0)\n)\n\ngdal_inv_geotransform(gt)\n\ngdal_crs(file, options = character(0))\n\ngdal_metadata(\n  file,\n  domain_item = character(0),\n  options = character(0),\n  parse = TRUE\n)\n\ngdal_subdatasets(file, options = character(0), name = TRUE)\n\ngdal_polygonize(\n  x,\n  mask = NULL,\n  file = tempfile(),\n  driver = \"GTiff\",\n  use_integer = TRUE,\n  geotransform,\n  breaks = classInt::classIntervals(na.omit(as.vector(x[[1]])))$brks,\n  use_contours = FALSE,\n  contour_lines = FALSE,\n  connect8 = FALSE,\n  ...\n)\n\ngdal_rasterize(sf, x, gt, file, driver = \"GTiff\", options = character())\n\ngdal_extract(\n  f,\n  pts,\n  resampling = c(\"nearest\", \"bilinear\", \"cubic\", \"cubicspline\")\n)\n\ngdal_read_mdim(\n  file,\n  array_name = character(0),\n  options = character(0),\n  offset = integer(0),\n  count = integer(0),\n  step = integer(0),\n  proxy = FALSE,\n  debug = FALSE\n)\n\ngdal_write_mdim(\n  file,\n  driver,\n  dimx,\n  cdl,\n  wkt,\n  xy,\n  ...,\n  root_group_options = character(0),\n  options = character(0),\n  as_float = TRUE\n)\n\ngdal_create(f, nxy, values, crs, xlim, ylim)\n}\n\\arguments{\n\\item{x}{character vector, possibly of length larger than 1 when more than one raster is read}\n\n\\item{...}{ignored}\n\n\\item{options}{character; driver specific options regarding reading or creating the dataset}\n\n\\item{driver}{character; driver short name; when empty vector, driver is auto-detected.}\n\n\\item{read_data}{logical; if \\code{FALSE}, only the imagery metadata is returned}\n\n\\item{NA_value}{(double) non-NA value to use for missing values; if \\code{NA}, when writing missing values are not specially flagged in output dataset, when reading the default (dataset) missing values are used (if present / set).}\n\n\\item{RasterIO_parameters}{list with named parameters to GDAL's RasterIO; see the stars::read_stars documentation.}\n\n\\item{file}{file name}\n\n\\item{type}{gdal write type}\n\n\\item{geotransform}{length 6 numeric vector with GDAL geotransform parameters.}\n\n\\item{update}{logical; \\code{TRUE} if in an existing raster file pixel values shall be updated.}\n\n\\item{scale_offset}{length 2 numeric; contains scale and offset values}\n\n\\item{gt}{double vector of length 6}\n\n\\item{domain_item}{character vector of length 0, 1 (with domain), or 2 (with domain and item); use \\code{\"\"} for the default domain, use \\code{NA_character_} to query the domain names.}\n\n\\item{parse}{logical; should metadata be parsed into a named list (\\code{TRUE}) or returned as character data?}\n\n\\item{name}{logical; retrieve name of subdataset? If \\code{FALSE}, retrieve description}\n\n\\item{mask}{stars object with NA mask (0 where NA), or NULL}\n\n\\item{use_integer}{boolean; if \\code{TRUE}, raster values are read as (and rounded to) unsigned 32-bit integers values; if \\code{FALSE} they are read as 32-bit floating points numbers. The former is supposedly faster.}\n\n\\item{breaks}{numeric vector with break values for contour polygons (or lines)}\n\n\\item{use_contours}{logical;}\n\n\\item{contour_lines}{logical;}\n\n\\item{connect8}{logical; if \\code{TRUE} use 8 connection algorithm, rather than 4}\n\n\\item{sf}{object of class \\code{sf}}\n\n\\item{f}{character; file name}\n\n\\item{pts}{points matrix}\n\n\\item{resampling}{character; resampling method; for method cubic or cubicspline,\n\\code{stars_proxy} objects should be used and GDAL should have version >= 3.10.0}\n\n\\item{array_name}{array name}\n\n\\item{offset}{offset (pixels)}\n\n\\item{count}{number of pixels to read}\n\n\\item{step}{step size (pixels)}\n\n\\item{proxy}{logical; return proxy object?}\n\n\\item{debug}{logical; print debug messages?}\n\n\\item{dimx}{integer named vector with dimensions of object}\n\n\\item{cdl}{list with variables, each having a named dim attribute}\n\n\\item{wkt}{character; WKT of crs}\n\n\\item{xy}{character; names of the spatial x and y dimension}\n\n\\item{root_group_options}{character; driver specific options regarding the creation of the root group}\n\n\\item{as_float}{logical; when \\code{TRUE} write 4-byte floating point numbers, when \\code{FALSE} write 8-byte doubles.}\n\n\\item{nxy}{integer vector of length 2}\n\n\\item{values}{fill value}\n\n\\item{crs}{object of class \\code{crs}}\n\n\\item{xlim}{numeric}\n\n\\item{ylim}{numeric}\n}\n\\value{\nobject of class \\code{crs}, see \\link{st_crs}.\n\nnamed list with metadata items\n\n\\code{gdal_subdatasets} returns a zero-length list if \\code{file} does not have subdatasets, and else a named list with subdatasets.\n}\n\\description{\nfunctions to interact with gdal not meant to be called directly by users (but e.g. by stars::read_stars)\n}\n\\details{\nThese functions are exported for the single purpose of being used by package stars, they are not meant to be used directly and may change or disappear without prior notice or deprecation warnings.\n\ngdal_inv_geotransform returns the inverse geotransform\n\ngdal_crs reads coordinate reference system from GDAL data set\n\nget_metadata gets metadata of a raster layer\n\ngdal_subdatasets returns the subdatasets of a gdal dataset\n}\n\\examples{\n\\dontrun{\n  f = system.file(\"tif/L7_ETMs.tif\", package=\"stars\")\n  f = system.file(\"nc/avhrr-only-v2.19810901.nc\", package = \"stars\")\n  gdal_metadata(f)\n  gdal_metadata(f, NA_character_)\n  try(gdal_metadata(f, \"wrongDomain\"))\n  gdal_metadata(f, c(\"\", \"AREA_OR_POINT\"))\n}\n}\n\\keyword{internal}\n"
  },
  {
    "path": "man/gdal_addo.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/stars.R\n\\name{gdal_addo}\n\\alias{gdal_addo}\n\\title{Add or remove overviews to/from a raster image}\n\\usage{\ngdal_addo(\n  file,\n  overviews = c(2, 4, 8, 16),\n  method = \"NEAREST\",\n  layers = integer(0),\n  options = character(0),\n  config_options = character(0),\n  clean = FALSE,\n  read_only = FALSE\n)\n}\n\\arguments{\n\\item{file}{character; file name}\n\n\\item{overviews}{integer; overview levels}\n\n\\item{method}{character; method to create overview; one of: nearest, average, rms, gauss, cubic, cubicspline, lanczos, average_mp, average_magphase, mode}\n\n\\item{layers}{integer; layers to create overviews for (default: all)}\n\n\\item{options}{character; dataset opening options}\n\n\\item{config_options}{named character vector with GDAL config options, like \\code{c(option1=value1, option2=value2)}}\n\n\\item{clean}{logical; if \\code{TRUE} only remove overviews, do not add}\n\n\\item{read_only}{logical; if \\code{TRUE}, add overviews to another file with extension \\code{.ovr} added to \\code{file}}\n}\n\\value{\n\\code{TRUE}, invisibly, on success\n}\n\\description{\nadd or remove overviews to/from a raster image\n}\n\\seealso{\n\\link{gdal_utils} for access to other gdal utilities that have a C API\n}\n"
  },
  {
    "path": "man/gdal_compressors.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/stars.R\n\\name{gdal_compressors}\n\\alias{gdal_compressors}\n\\title{List GDAL compressors and decompressors}\n\\usage{\ngdal_compressors()\n}\n\\value{\nnamed list with two character vectors, containing compressors and decompressors\n}\n\\description{\nList GDAL compressors and decompressors\n}\n"
  },
  {
    "path": "man/gdal_utils.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/gdal_utils.R\n\\name{gdal_utils}\n\\alias{gdal_utils}\n\\title{Native interface to gdal utils}\n\\usage{\ngdal_utils(\n  util = \"info\",\n  source,\n  destination,\n  options = character(0),\n  quiet = !(util \\%in\\% c(\"info\", \"gdalinfo\", \"ogrinfo\", \"vectorinfo\", \"mdiminfo\")) ||\n    (\"-multi\" \\%in\\% options),\n  processing = character(0),\n  colorfilename = character(0),\n  config_options = character(0),\n  read_only = FALSE\n)\n}\n\\arguments{\n\\item{util}{character; one of \\code{info}, \\code{warp}, \\code{rasterize}, \\code{translate}, \\code{vectortranslate} (for ogr2ogr), \\code{buildvrt}, \\code{demprocessing}, \\code{nearblack}, \\code{grid}, \\code{mdiminfo} and \\code{mdimtranslate} (the last two requiring GDAL 3.1), \\code{ogrinfo} (requiring GDAL 3.7), \\code{footprint} (requiring GDAL 3.8)}\n\n\\item{source}{character; name of input layer(s); for \\code{warp}, \\code{buidvrt} or \\code{mdimtranslate} this can be more than one}\n\n\\item{destination}{character; name of output layer}\n\n\\item{options}{character; options for the utility}\n\n\\item{quiet}{logical; if \\code{TRUE}, suppress printing the output for \\code{info} and \\code{mdiminfo}, and suppress printing progress}\n\n\\item{processing}{character; processing options for \\code{demprocessing}}\n\n\\item{colorfilename}{character; name of color file for \\code{demprocessing} (mandatory if \\code{processing=\"color-relief\"})}\n\n\\item{config_options}{named character vector with GDAL config options, like \\code{c(option1=value1, option2=value2)}}\n\n\\item{read_only}{logical; only for \\code{ogrinfo}: if \\code{TRUE}, source is opened in read-only mode}\n}\n\\value{\n\\code{info} returns a character vector with the raster metadata; all other utils return (invisibly) a logical indicating success (i.e., \\code{TRUE}); in case of failure, an error is raised.\n}\n\\description{\nNative interface to gdal utils\n}\n\\examples{\n\nif (compareVersion(sf_extSoftVersion()[\"GDAL\"], \"2.1.0\") == 1) {\n# info utils can be used to list information about a raster\n# dataset. More info: https://gdal.org/programs/gdalinfo.html\nin_file <- system.file(\"tif/geomatrix.tif\", package = \"sf\")\ngdal_utils(\"info\", in_file, options = c(\"-mm\", \"-proj4\"))\n\n# vectortranslate utils can be used to convert simple features data between\n# file formats. More info: https://gdal.org/programs/ogr2ogr.html\nin_file <- system.file(\"shape/storms_xyz.shp\", package=\"sf\")\nout_file <- paste0(tempfile(), \".gpkg\")\ngdal_utils(\n  util = \"vectortranslate\",\n  source = in_file,\n  destination = out_file, # output format must be specified for GDAL < 2.3\n  options = c(\"-f\", \"GPKG\")\n)\n# The parameters can be specified as c(\"name\") or c(\"name\", \"value\"). The\n# vectortranslate utils can perform also various operations during the\n# conversion process. For example, we can reproject the features during the\n# translation.\ngdal_utils(\n  util = \"vectortranslate\",\n  source = in_file,\n  destination = out_file,\n  options = c(\n  \"-f\", \"GPKG\", # output file format for GDAL < 2.3\n  \"-s_srs\", \"EPSG:4326\", # input file SRS\n  \"-t_srs\", \"EPSG:2264\", # output file SRS\n  \"-overwrite\"\n  )\n)\nst_read(out_file)\n# The parameter s_srs had to be specified because, in this case, the in_file\n# has no associated SRS.\nst_read(in_file)\n}\n}\n\\seealso{\n\\link{gdal_addo} for adding overlays to a raster file; \\link{st_layers} to query geometry type(s) and crs from layers in a (vector) data source\n}\n"
  },
  {
    "path": "man/geos_binary_ops.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/geom-transformers.R\n\\name{geos_binary_ops}\n\\alias{geos_binary_ops}\n\\alias{st_intersection}\n\\alias{st_intersection.sfc}\n\\alias{st_intersection.sf}\n\\alias{st_difference}\n\\alias{st_difference.sfc}\n\\alias{st_sym_difference}\n\\alias{st_snap}\n\\title{Geometric operations on pairs of simple feature geometry sets}\n\\usage{\nst_intersection(x, y, ..., by_element = FALSE)\n\n\\method{st_intersection}{sfc}(x, y, ...)\n\n\\method{st_intersection}{sf}(x, y, ...)\n\nst_difference(x, y, ...)\n\n\\method{st_difference}{sfc}(x, y, ...)\n\nst_sym_difference(x, y, ...)\n\nst_snap(x, y, tolerance)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf}, \\code{sfc} or \\code{sfg}}\n\n\\item{y}{object of class \\code{sf}, \\code{sfc} or \\code{sfg}}\n\n\\item{...}{arguments passed on to \\link[s2]{s2_options}}\n\n\\item{by_element}{logical; if \\code{TRUE}, return pair-wise computed geometries, rather than set-wise; can be used for all binary operations}\n\n\\item{tolerance}{tolerance values used for \\code{st_snap}; numeric value or object of class \\code{units}; may have tolerance values for each feature in \\code{x}}\n}\n\\value{\nThe intersection, difference or symmetric difference between two sets of geometries.\nThe returned object has the same class as that of the first argument (\\code{x}) with the non-empty geometries resulting from applying the operation to all geometry pairs in \\code{x} and \\code{y}. In case \\code{x} is of class \\code{sf}, the matching attributes of the original object(s) are added. The \\code{sfc} geometry list-column returned carries an attribute \\code{idx}, which is an \\code{n}-by-2 matrix with every row the index of the corresponding entries of \\code{x} and \\code{y}, respectively.\n}\n\\description{\nPerform geometric set operations with simple feature geometry collections\n}\n\\details{\nWhen using GEOS and not using s2, a spatial index is built on argument \\code{x}; see \\url{https://r-spatial.org/r/2017/06/22/spatial-index.html}. The reference for the STR tree algorithm is: Leutenegger, Scott T., Mario A. Lopez, and Jeffrey Edgington. \"STR: A simple and efficient algorithm for R-tree packing.\" Data Engineering, 1997. Proceedings. 13th international conference on. IEEE, 1997. For the pdf, search Google Scholar.\n\nWhen called with missing \\code{y}, the \\code{sfc} method for \\code{st_intersection} returns all non-empty intersections of the geometries of \\code{x}; an attribute \\code{idx} contains a list-column with the indexes of contributing geometries.\n\nwhen called with a missing \\code{y}, the \\code{sf} method for \\code{st_intersection} returns an \\code{sf} object with attributes taken from the contributing feature with lowest index; two fields are added: \\code{n.overlaps} with the number of overlapping features in \\code{x}, and a list-column \\code{origins} with indexes of all overlapping features.\n\nWhen \\code{st_difference} is called with a single argument,\noverlapping areas are erased from geometries that are indexed at greater\nnumbers in the argument to \\code{x}; geometries that are empty\nor contained fully inside geometries with higher priority are removed entirely.\nThe \\code{st_difference.sfc} method with a single argument returns an object with\nan \\code{\"idx\"} attribute with the original index for returned geometries.\n\n\\code{st_snap} snaps the vertices and segments of a geometry to another geometry's vertices. If \\code{y} contains more than one geometry, its geometries are merged into a collection before snapping to that collection.\n\n(from the GEOS docs:) \"A snap distance tolerance is used to control where snapping is performed. Snapping one geometry to another can improve robustness for overlay operations by eliminating nearly-coincident edges (which cause problems during noding and intersection calculation). Too much snapping can result in invalid topology being created, so the number and location of snapped vertices is decided using heuristics to determine when it is safe to snap. This can result in some potential snaps being omitted, however.\"\n}\n\\note{\nTo find whether pairs of simple feature geometries intersect, use\nthe function \\code{\\link{st_intersects}} instead of \\code{st_intersection}.\n\nWhen using GEOS and not using s2 polygons contain their boundary. When using s2 this is determined by the \\code{model} defaults of \\link[s2]{s2_options}, which can be overridden via the ... argument, e.g. \\code{model = \"closed\"} to force DE-9IM compliant behaviour of polygons (and reproduce GEOS results).\n}\n\\examples{\nset.seed(131)\nlibrary(sf)\nm = rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0))\np = st_polygon(list(m))\nn = 100\nl = vector(\"list\", n)\nfor (i in 1:n)\n  l[[i]] = p + 10 * runif(2)\ns = st_sfc(l)\nplot(s, col = sf.colors(categorical = TRUE, alpha = .5))\ntitle(\"overlapping squares\")\nd = st_difference(s) # sequential differences: s1, s2-s1, s3-s2-s1, ...\nplot(d, col = sf.colors(categorical = TRUE, alpha = .5))\ntitle(\"non-overlapping differences\")\ni = st_intersection(s) # all intersections\nplot(i, col = sf.colors(categorical = TRUE, alpha = .5))\ntitle(\"non-overlapping intersections\")\nsummary(lengths(st_overlaps(s, s))) # includes self-counts!\nsummary(lengths(st_overlaps(d, d)))\nsummary(lengths(st_overlaps(i, i)))\nsf = st_sf(s)\ni = st_intersection(sf) # all intersections\nplot(i[\"n.overlaps\"])\nsummary(i$n.overlaps - lengths(i$origins))\n# A helper function that erases all of y from x:\nst_erase = function(x, y) st_difference(x, st_union(st_combine(y)))\npoly = st_polygon(list(cbind(c(0, 0, 1, 1, 0), c(0, 1, 1, 0, 0))))\nlines = st_multilinestring(list(\n cbind(c(0, 1), c(1, 1.05)),\n cbind(c(0, 1), c(0, -.05)),\n cbind(c(1, .95, 1), c(1.05, .5, -.05))\n))\nsnapped = st_snap(poly, lines, tolerance=.1)\nplot(snapped, col='red')\nplot(poly, border='green', add=TRUE)\nplot(lines, lwd=2, col='blue', add=TRUE)\n}\n\\seealso{\n\\link{st_union} for the union of simple features collections; \\link{intersect} and \\link{setdiff} for the base R set operations.\n}\n"
  },
  {
    "path": "man/geos_binary_pred.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/geom-predicates.R\n\\name{geos_binary_pred}\n\\alias{geos_binary_pred}\n\\alias{st_intersects}\n\\alias{st_disjoint}\n\\alias{st_touches}\n\\alias{st_crosses}\n\\alias{st_within}\n\\alias{st_contains}\n\\alias{st_contains_properly}\n\\alias{st_overlaps}\n\\alias{st_equals}\n\\alias{st_covers}\n\\alias{st_covered_by}\n\\alias{st_equals_exact}\n\\alias{st_is_within_distance}\n\\title{Geometric binary predicates on pairs of simple feature geometry sets}\n\\usage{\nst_intersects(x, y, sparse = TRUE, ..., by_element = FALSE)\n\nst_disjoint(x, y = x, sparse = TRUE, prepared = TRUE, ...)\n\nst_touches(x, y, sparse = TRUE, prepared = TRUE, ...)\n\nst_crosses(x, y, sparse = TRUE, prepared = TRUE, ...)\n\nst_within(x, y, sparse = TRUE, prepared = TRUE, ...)\n\nst_contains(x, y, sparse = TRUE, prepared = TRUE, ..., model = \"open\")\n\nst_contains_properly(x, y, sparse = TRUE, prepared = TRUE, ...)\n\nst_overlaps(x, y, sparse = TRUE, prepared = TRUE, ...)\n\nst_equals(\n  x,\n  y,\n  sparse = TRUE,\n  prepared = FALSE,\n  ...,\n  retain_unique = FALSE,\n  remove_self = FALSE\n)\n\nst_covers(x, y, sparse = TRUE, prepared = TRUE, ..., model = \"closed\")\n\nst_covered_by(x, y = x, sparse = TRUE, prepared = TRUE, ..., model = \"closed\")\n\nst_equals_exact(x, y, par, sparse = TRUE, prepared = FALSE, ...)\n\nst_is_within_distance(x, y = x, dist, sparse = TRUE, ..., remove_self = FALSE)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf}, \\code{sfc} or \\code{sfg}}\n\n\\item{y}{object of class \\code{sf}, \\code{sfc} or \\code{sfg}; if missing, \\code{x} is used}\n\n\\item{sparse}{logical; should a sparse index list be returned (\\code{TRUE}) or a dense logical matrix? See below.}\n\n\\item{...}{\n  Arguments passed on to \\code{\\link[s2:s2_options]{s2::s2_options}}\n  \\describe{\n    \\item{\\code{snap}}{Use \\code{s2_snap_identity()}, \\code{s2_snap_distance()}, \\code{s2_snap_level()},\nor \\code{s2_snap_precision()} to specify how or if coordinate rounding should\noccur.}\n    \\item{\\code{snap_radius}}{As opposed to the snap function, which specifies\nthe maximum distance a vertex should move, the snap radius (in radians) sets\nthe minimum distance between vertices of the output that don't cause vertices\nto move more than the distance specified by the snap function. This can be used\nto simplify the result of a boolean operation. Use -1 to specify that any\nminimum distance is acceptable.}\n    \\item{\\code{duplicate_edges}}{Use \\code{TRUE} to keep duplicate edges (e.g., duplicate\npoints).}\n    \\item{\\code{edge_type}}{One of 'directed' (default) or 'undirected'.}\n    \\item{\\code{validate}}{Use \\code{TRUE} to validate the result from the builder.}\n    \\item{\\code{polyline_type}}{One of 'path' (default) or 'walk'. If 'walk',\npolylines that backtrack are preserved.}\n    \\item{\\code{polyline_sibling_pairs}}{One of 'discard' (default) or 'keep'.}\n    \\item{\\code{simplify_edge_chains}}{Use \\code{TRUE} to remove vertices that are within\n\\code{snap_radius} of the original vertex.}\n    \\item{\\code{split_crossing_edges}}{Use \\code{TRUE} to split crossing polyline edges\nwhen creating geometries.}\n    \\item{\\code{idempotent}}{Use \\code{FALSE} to apply snap even if snapping is not necessary\nto satisfy vertex constraints.}\n    \\item{\\code{dimensions}}{A combination of 'point', 'polyline', and/or 'polygon'\nthat can used to constrain the output of \\code{\\link[s2:s2_rebuild]{s2_rebuild()}} or a\nboolean operation.}\n    \\item{\\code{level}}{A value from 0 to 30 corresponding to the cell level\nat which snapping should occur.}\n    \\item{\\code{precision}}{A number by which coordinates should be multiplied\nbefore being rounded. Rounded to the nearest exponent of 10.}\n    \\item{\\code{distance}}{A distance (in radians) denoting the maximum\ndistance a vertex should move in the snapping process.}\n  }}\n\n\\item{by_element}{logical; if \\code{TRUE}, return logical vector with x-y pair-wise predicate values}\n\n\\item{prepared}{logical; prepare geometry for \\code{x}, before looping over \\code{y}? See Details.}\n\n\\item{model}{character; polygon/polyline model; one of\n\"open\", \"semi-open\" or \"closed\"; see Details.}\n\n\\item{retain_unique}{logical; if \\code{TRUE} (and \\code{y} is missing) return only indexes of points larger than the current index; this can be used to select unique geometries, see examples. This argument can be used for all geometry predicates; see also \\link{distinct.sf} to find records where geometries AND attributes are distinct.}\n\n\\item{remove_self}{logical; if \\code{TRUE} (and \\code{y} is missing) return only indexes of geometries different from the current index; this can be used to omit self-intersections; see examples. This argument can be used for all geometry predicates}\n\n\\item{par}{numeric; parameter used for \"equals_exact\" (margin);}\n\n\\item{dist}{distance threshold; geometry indexes with distances smaller or equal to this value are returned; numeric value or units value having distance units.}\n}\n\\value{\nIf \\code{sparse=FALSE}, \\code{st_predicate} (with \\code{predicate} e.g. \"intersects\") returns a dense logical matrix with element \\code{i,j} equal to \\code{TRUE} when \\code{predicate(x[i], y[j])} (e.g., when geometry of feature i and j intersect); if \\code{sparse=TRUE}, an object of class \\code{\\link{sgbp}} is returned, which is a sparse list representation of the same matrix, with list element \\code{i} an integer vector with all indices \\code{j} for which \\code{predicate(x[i],y[j])} is \\code{TRUE} (and hence a zero-length integer vector if none of them is \\code{TRUE}). From the dense matrix, one can find out if one or more elements intersect by \\code{apply(mat, 1, any)}, and from the sparse list by \\code{lengths(lst) > 0}, see examples below. If \\code{by_element=TRUE}, return a vector of pair-wise predicate values.\n}\n\\description{\nGeometric binary predicates on pairs of simple feature geometry sets\n}\n\\details{\nIf \\code{prepared} is \\code{TRUE}, and \\code{x} contains POINT geometries and \\code{y} contains polygons, then the polygon geometries are prepared, rather than the points.\n\nFor most predicates, a spatial index is built on argument \\code{x}; see \\url{https://r-spatial.org/r/2017/06/22/spatial-index.html}.\nSpecifically, \\code{st_intersects}, \\code{st_disjoint}, \\code{st_touches} \\code{st_crosses}, \\code{st_within}, \\code{st_contains}, \\code{st_contains_properly}, \\code{st_overlaps}, \\code{st_equals}, \\code{st_covers} and \\code{st_covered_by} all build spatial indexes for more efficient geometry calculations. \\code{st_relate}, \\code{st_equals_exact}, and do not; \\code{st_is_within_distance} uses a spatial index for geographic coordinates when \\code{sf_use_s2()} is true.\n\nIf \\code{y} is missing, \\code{st_predicate(x, x)} is effectively called, and a square matrix is returned with diagonal elements \\code{st_predicate(x[i], x[i])}.\n\nSparse geometry binary predicate (\\code{\\link{sgbp}}) lists have the following attributes: \\code{region.id} with the \\code{row.names} of \\code{x} (if any, else \\code{1:n}), \\code{ncol} with the number of features in \\code{y}, and \\code{predicate} with the name of the predicate used.\n\nfor \\code{model}, see https://github.com/r-spatial/s2/issues/32\n\n\\code{st_contains_properly(A,B)} is true if A intersects B's interior, but not its edges or exterior; A contains A, but A does not properly contain A.\n\nSee also \\link{st_relate} and \\url{https://en.wikipedia.org/wiki/DE-9IM} for a more detailed description of the underlying algorithms.\n\n\\code{st_equals_exact} returns true for two geometries of the same type and their vertices corresponding by index are equal up to a specified tolerance.\n}\n\\note{\nFor intersection on pairs of simple feature geometries, use\nthe function \\code{\\link{st_intersection}} instead of \\code{st_intersects}.\n}\n\\examples{\npts = st_sfc(st_point(c(.5,.5)), st_point(c(1.5, 1.5)), st_point(c(2.5, 2.5)))\npol = st_polygon(list(rbind(c(0,0), c(2,0), c(2,2), c(0,2), c(0,0))))\n(lst = st_intersects(pts, pol))\n(mat = st_intersects(pts, pol, sparse = FALSE))\n# which points fall inside a polygon?\napply(mat, 1, any)\nlengths(lst) > 0\n# which points fall inside the first polygon?\nst_intersects(pol, pts)[[1]]\n# remove duplicate geometries:\np1 = st_point(0:1)\np2 = st_point(2:1)\np = st_sf(a = letters[1:8], geom = st_sfc(p1, p1, p2, p1, p1, p2, p2, p1))\nst_equals(p)\nst_equals(p, remove_self = TRUE)\n(u = st_equals(p, retain_unique = TRUE))\n# retain the records with unique geometries:\np[-unlist(u),]\n}\n"
  },
  {
    "path": "man/geos_combine.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/geom-transformers.R\n\\name{geos_combine}\n\\alias{geos_combine}\n\\alias{st_combine}\n\\alias{st_union}\n\\title{Combine or union feature geometries}\n\\usage{\nst_combine(x)\n\nst_union(x, y, ..., by_feature = FALSE, is_coverage = FALSE)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf}, \\code{sfc} or \\code{sfg}}\n\n\\item{y}{object of class \\code{sf}, \\code{sfc} or \\code{sfg} (optional)}\n\n\\item{...}{ignored}\n\n\\item{by_feature}{logical; if \\code{TRUE}, union each feature if \\code{y} is missing or else each pair of features; if \\code{FALSE} return a single feature that is the geometric union of the set of features in \\code{x} if \\code{y} is missing, or else the unions of each of the elements of the Cartesian product of both sets}\n\n\\item{is_coverage}{logical; if \\code{TRUE}, use an optimized algorithm for features that form a polygonal coverage (have no overlaps)}\n}\n\\value{\n\\code{st_combine} returns a single, combined geometry, with no resolved boundaries; returned geometries may well be invalid.\n\nIf \\code{y} is missing, \\code{st_union(x)} returns a single geometry with resolved boundaries, else the geometries for all unioned pairs of \\code{x[i]} and \\code{y[j]}.\n}\n\\description{\nCombine several feature geometries into one, without unioning or resolving internal boundaries\n}\n\\details{\n\\code{st_combine} combines geometries without resolving borders, using \\link{c.sfg} (analogous to \\link[base]{c} for ordinary vectors).\n\nIf \\code{st_union} is called with a single argument, \\code{x}, (with \\code{y} missing) and \\code{by_feature} is \\code{FALSE} all geometries are unioned together and an \\code{sfg} or single-geometry \\code{sfc} object is returned.\nIf \\code{by_feature} is \\code{TRUE} each feature geometry is unioned individually.\nThis can for instance be used to resolve internal boundaries after polygons were combined using \\code{st_combine}.\nIf \\code{y} is provided, all elements of \\code{x} and \\code{y} are unioned, pairwise if \\code{by_feature} is TRUE, or else as the Cartesian product of both sets.\n\nUnioning a set of overlapping polygons has the effect of merging the areas (i.e. the same effect as iteratively unioning all individual polygons together).\nUnioning a set of LineStrings has the effect of fully noding and dissolving the input linework. In this context \"fully noded\" means that there will be a node or endpoint in the output for every endpoint or line segment crossing in the input.\n\"Dissolved\" means that any duplicate (e.g. coincident) line segments or portions of line segments will be reduced to a single line segment in the output.\tUnioning a set of Points has the effect of merging all identical points (producing a set with no duplicates).\n}\n\\examples{\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\nst_combine(nc)\nplot(st_union(nc))\n}\n\\seealso{\n\\link{st_intersection}, \\link{st_difference}, \\link{st_sym_difference}\n}\n"
  },
  {
    "path": "man/geos_measures.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/geom-measures.R\n\\name{geos_measures}\n\\alias{geos_measures}\n\\alias{st_area}\n\\alias{st_area.sfc}\n\\alias{st_length}\n\\alias{st_perimeter}\n\\alias{st_distance}\n\\title{Compute geometric measurements}\n\\usage{\nst_area(x, ...)\n\n\\method{st_area}{sfc}(x, ...)\n\nst_length(x, ...)\n\nst_perimeter(x, ...)\n\nst_distance(\n  x,\n  y,\n  ...,\n  dist_fun,\n  by_element = FALSE,\n  which = ifelse(isTRUE(st_is_longlat(x)), \"Great Circle\", \"Euclidean\"),\n  par = 0,\n  tolerance = 0\n)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf}, \\code{sfc} or \\code{sfg}}\n\n\\item{...}{passed on to \\link[s2]{s2_distance}, \\link[s2]{s2_distance_matrix}, or \\link[s2]{s2_perimeter}}\n\n\\item{y}{object of class \\code{sf}, \\code{sfc} or \\code{sfg}, defaults to \\code{x}}\n\n\\item{dist_fun}{deprecated}\n\n\\item{by_element}{logical; if \\code{TRUE}, return a vector with distance between the first elements of \\code{x} and \\code{y}, the second, etc; an error is raised if \\code{x} and \\code{y} are not the same length. If \\code{FALSE}, return the dense matrix with all pairwise distances.}\n\n\\item{which}{character; for Cartesian coordinates only: one of \\code{Euclidean}, \\code{Hausdorff} or \\code{Frechet}; for geodetic coordinates, great circle distances are computed; see details}\n\n\\item{par}{for \\code{which} equal to \\code{Hausdorff} or \\code{Frechet}, optionally use a value between 0 and 1 to densify the geometry}\n\n\\item{tolerance}{ignored if \\code{st_is_longlat(x)} is \\code{FALSE}; otherwise, if set to a positive value, the first distance smaller than \\code{tolerance} will be returned, and true distance may be smaller; this may speed up computation. In meters, or a \\code{units} object convertible to meters.}\n}\n\\value{\nIf the coordinate reference system of \\code{x} was set, these functions return values with unit of measurement; see \\link[units]{set_units}.\n\nst_area returns the area of each feature geometry, computed in the coordinate reference system used. In case \\code{x} has geodetic coordinates (unprojected), then if \\code{sf_use_s2()} is \\code{FALSE} \\link[lwgeom:geod]{st_geod_area} is used for area calculation, if it is \\code{TRUE} then \\link[s2:s2_is_collection]{s2_area} is used: the former assumes an ellipsoidal shape, the latter a spherical shape of the Earth. In case of projected data, areas are computed in flat space. The argument \\code{...} can be used to specify \\code{radius} to \\link[s2:s2_is_collection]{s2_area}, to modify the Earth radius.\n\nst_length returns the length of a \\code{LINESTRING} or \\code{MULTILINESTRING} geometry, using the coordinate reference system.  \\code{POINT}, \\code{MULTIPOINT}, \\code{POLYGON} or \\code{MULTIPOLYGON} geometries return zero.\nIf coordinates are geodetic (i.e., long/lat), great circle calculations are carried out on a sphere (if \\code{sf_use_s2()} is \\code{TRUE}), or a geodesic line is computed on an ellipsoid (if \\code{sf_use_s2()} is \\code{FALSE}). For all other non-geodetic, projected coordinate systems, length calculations are planar, Euclidean distance calculations in the units of the coordinate system.\n\nIf \\code{by_element} is \\code{FALSE} \\code{st_distance} returns a dense numeric matrix of dimension length(x) by length(y); otherwise it returns a numeric vector the same length as \\code{x} and \\code{y} with an error raised if the lengths of \\code{x} and \\code{y} are unequal. Distances involving empty geometries are \\code{NA}.\n}\n\\description{\nCompute Euclidean or great circle distance between pairs of geometries; compute, the area or the length of a set of geometries.\n}\n\\details{\ngreat circle distance calculations use by default spherical distances (\\link[s2]{s2_distance} or \\link[s2]{s2_distance_matrix}); if \\code{sf_use_s2()} is \\code{FALSE}, ellipsoidal distances are computed using \\link[lwgeom]{st_geod_distance} which uses function \\code{geod_inverse} from GeographicLib (part of PROJ); see Karney, Charles FF, 2013, Algorithms for geodesics, Journal of Geodesy 87(1), 43--55\n}\n\\examples{\nb0 = st_polygon(list(rbind(c(-1,-1), c(1,-1), c(1,1), c(-1,1), c(-1,-1))))\nb1 = b0 + 2\nb2 = b0 + c(-0.2, 2)\nx = st_sfc(b0, b1, b2)\nst_area(x)\nline = st_sfc(st_linestring(rbind(c(30,30), c(40,40))), crs = 4326)\nst_length(line)\n\nouter = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\nhole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\nhole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\n\npoly = st_polygon(list(outer, hole1, hole2))\nmpoly = st_multipolygon(list(\n\tlist(outer, hole1, hole2),\n\tlist(outer + 12, hole1 + 12)\n))\n\nst_length(st_sfc(poly, mpoly))\nif (requireNamespace(\"lwgeom\", quietly = TRUE)) {\n  st_perimeter(poly)\n  st_perimeter(mpoly)\n}\np = st_sfc(st_point(c(0,0)), st_point(c(0,1)), st_point(c(0,2)))\nst_distance(p, p)\nst_distance(p, p, by_element = TRUE)\n}\n\\seealso{\n\\link{st_dimension}, \\link{st_cast} to convert geometry types\n}\n"
  },
  {
    "path": "man/geos_query.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/geom-measures.R, R/geom-predicates.R\n\\name{geos_query}\n\\alias{geos_query}\n\\alias{st_dimension}\n\\alias{st_is_simple}\n\\alias{st_is_empty}\n\\title{Dimension, simplicity, validity or is_empty queries on simple feature geometries}\n\\usage{\nst_dimension(x, NA_if_empty = TRUE)\n\nst_is_simple(x)\n\nst_is_empty(x)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf}, \\code{sfc} or \\code{sfg}}\n\n\\item{NA_if_empty}{logical; if TRUE, return NA for empty geometries}\n}\n\\value{\nst_dimension returns a numeric vector with 0 for points, 1 for lines, 2 for surfaces, and, if \\code{NA_if_empty} is \\code{TRUE}, \\code{NA} for empty geometries.\n\nst_is_simple returns a logical vector, indicating for each geometry whether it is simple (e.g., not self-intersecting)\n\nst_is_empty returns for each geometry whether it is empty\n}\n\\description{\nDimension, simplicity, validity or is_empty queries on simple feature geometries\n}\n\\examples{\nx = st_sfc(\n\tst_point(0:1),\n\tst_linestring(rbind(c(0,0),c(1,1))),\n\tst_polygon(list(rbind(c(0,0),c(1,0),c(0,1),c(0,0)))),\n\tst_multipoint(),\n\tst_linestring(),\n\tst_geometrycollection())\nst_dimension(x)\nst_dimension(x, FALSE)\nls = st_linestring(rbind(c(0,0), c(1,1), c(1,0), c(0,1)))\nst_is_simple(st_sfc(ls, st_point(c(0,0))))\nls = st_linestring(rbind(c(0,0), c(1,1), c(1,0), c(0,1)))\nst_is_empty(st_sfc(ls, st_point(), st_linestring()))\n}\n"
  },
  {
    "path": "man/geos_unary.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/geom-transformers.R\n\\name{geos_unary}\n\\alias{geos_unary}\n\\alias{st_buffer}\n\\alias{st_boundary}\n\\alias{st_convex_hull}\n\\alias{st_concave_hull}\n\\alias{st_simplify}\n\\alias{st_triangulate}\n\\alias{st_triangulate_constrained}\n\\alias{st_inscribed_circle}\n\\alias{st_minimum_rotated_rectangle}\n\\alias{st_minimum_bounding_circle}\n\\alias{st_voronoi}\n\\alias{st_polygonize}\n\\alias{st_line_merge}\n\\alias{st_centroid}\n\\alias{st_point_on_surface}\n\\alias{st_reverse}\n\\alias{st_node}\n\\alias{st_segmentize}\n\\alias{st_exterior_ring}\n\\title{Geometric unary operations on simple feature geometry sets}\n\\usage{\nst_buffer(\n  x,\n  dist,\n  nQuadSegs = 30,\n  endCapStyle = \"ROUND\",\n  joinStyle = \"ROUND\",\n  mitreLimit = 1,\n  singleSide = FALSE,\n  ...\n)\n\nst_boundary(x)\n\nst_convex_hull(x)\n\nst_concave_hull(x, ratio, ..., allow_holes)\n\nst_simplify(x, preserveTopology, dTolerance = 0)\n\nst_triangulate(x, dTolerance = 0, bOnlyEdges = FALSE)\n\nst_triangulate_constrained(x)\n\nst_inscribed_circle(x, dTolerance, ...)\n\nst_minimum_rotated_rectangle(x, ...)\n\nst_minimum_bounding_circle(x, ...)\n\nst_voronoi(\n  x,\n  envelope,\n  dTolerance = 0,\n  bOnlyEdges = FALSE,\n  point_order = FALSE\n)\n\nst_polygonize(x)\n\nst_line_merge(x, ..., directed = FALSE)\n\nst_centroid(x, ..., of_largest_polygon = FALSE)\n\nst_point_on_surface(x)\n\nst_reverse(x)\n\nst_node(x)\n\nst_segmentize(x, dfMaxLength, ...)\n\nst_exterior_ring(x, ...)\n}\n\\arguments{\n\\item{x}{object of class \\code{sfg}, \\code{sfc} or \\code{sf}}\n\n\\item{dist}{numeric or object of class \\code{units}; buffer distance(s) for all, or for each of the elements in \\code{x}.\nIn case \\code{x} has geodetic coordinates (lon/lat) and \\code{sf_use_s2()} is \\code{TRUE}, a numeric\n\\code{dist} is taken as distance in meters and a \\code{units} object in \\code{dist} is converted to meters.\nIn case \\code{x} has geodetic coordinates (lon/lat) and \\code{sf_use_s2()} is \\code{FALSE}, a numeric\n\\code{dist} is taken as degrees, and a \\code{units} object in \\code{dist} is converted to \\code{arc_degree} (and warnings are issued).\nIn case \\code{x} does not have geodetic coordinates (projected) then\nnumeric \\code{dist} is assumed to have the units of the coordinates, and a \\code{units} \\code{dist} is converted to those if \\code{st_crs(x)} is not \\code{NA}.}\n\n\\item{nQuadSegs}{integer; number of segments per quadrant (fourth of a circle), for all or per-feature; see details}\n\n\\item{endCapStyle}{character; style of line ends, one of 'ROUND', 'FLAT', 'SQUARE'; see details}\n\n\\item{joinStyle}{character; style of line joins, one of 'ROUND', 'MITRE', 'BEVEL'; see details}\n\n\\item{mitreLimit}{numeric; limit of extension for a join if \\code{joinStyle} 'MITRE' is used (default 1.0, minimum 0.0); see details}\n\n\\item{singleSide}{logical; if \\code{TRUE}, single-sided buffers are returned for linear geometries,\nin which case negative \\code{dist} values give buffers on the right-hand side, positive on the left; see details}\n\n\\item{...}{in \\code{st_buffer} passed on to  \\code{\\link[s2:s2_buffer_cells]{s2::s2_buffer_cells()}}, otherwise ignored}\n\n\\item{ratio}{numeric; fraction convex: 1 returns the convex hulls, 0 maximally concave hulls}\n\n\\item{allow_holes}{logical; if \\code{TRUE}, the resulting concave hull may have holes}\n\n\\item{preserveTopology}{logical; carry out topology preserving\nsimplification? May be specified for each, or for all feature geometries.\nNote that topology is preserved only for single feature geometries, not for\nsets of them. If not specified (i.e. the default), then it is internally\nset equal to \\code{FALSE} when the input data is specified with projected\ncoordinates or \\code{sf_use_s2()} returns \\code{FALSE}. Ignored in all the\nother cases (with a warning when set equal to \\code{FALSE}) since the\nfunction implicitly calls \\code{s2::s2_simplify} which always preserve\ntopological relationships (per single feature).}\n\n\\item{dTolerance}{numeric; tolerance parameter, specified for all or for each\nfeature geometry. If you run \\code{st_simplify}, the input data is\nspecified with long-lat coordinates and \\code{sf_use_s2()} returns\n\\code{TRUE}, then the value of \\code{dTolerance} must be specified in\nmeters.}\n\n\\item{bOnlyEdges}{logical; if \\code{TRUE}, return lines, else return polygons}\n\n\\item{envelope}{object of class \\code{sfc} or \\code{sfg} containing a \\code{POLYGON} with the envelope for a voronoi diagram; this only takes effect when it is larger than the default envelope, chosen when \\code{envelope} is an empty polygon}\n\n\\item{point_order}{logical; preserve point order if TRUE and GEOS version >= 3.12; overrides bOnlyEdges}\n\n\\item{directed}{logical; if \\code{TRUE}, lines with opposite directions will not be merged}\n\n\\item{of_largest_polygon}{logical; for \\code{st_centroid}: if \\code{TRUE}, return centroid of the largest (sub)polygon of a \\code{MULTIPOLYGON} rather than of the whole \\code{MULTIPOLYGON}}\n\n\\item{dfMaxLength}{maximum length of a line segment. If \\code{x} has geographical coordinates (long/lat), \\code{dfMaxLength} is either a numeric expressed in meter, or an object of class \\code{units} with length units \\code{rad} or \\code{degree}; segmentation in the long/lat case takes place along the great circle, using \\link[lwgeom:geod]{st_geod_segmentize}.}\n}\n\\value{\nan object of the same class of \\code{x}, with manipulated geometry.\n}\n\\description{\nGeometric unary operations on simple feature geometries. These are all generics, with methods for \\code{sfg}, \\code{sfc} and \\code{sf} objects, returning an object of the same class. All operations work on a per-feature basis, ignoring all other features.\n}\n\\details{\n\\code{st_buffer} computes a buffer around this geometry/each geometry. Depending on the spatial\ncoordinate system, a different engine (GEOS or S2) can be used, which have different function\narguments. The \\code{nQuadSegs}, \\code{endCapsStyle}, \\code{joinStyle}, \\code{mitreLimit} and\n\\code{singleSide} parameters only work if the GEOS engine is used (i.e. projected coordinates or\nwhen \\code{sf_use_s2()} is set to \\code{FALSE}). See \\href{https://postgis.net/docs/ST_Buffer.html}{postgis.net/docs/ST_Buffer.html}\nfor details. The \\code{max_cells} and \\code{min_level} parameters (\\code{\\link[s2:s2_buffer_cells]{s2::s2_buffer_cells()}}) work with the S2\nengine (i.e. geographic coordinates) and can be used to change the buffer shape (e.g. smoothing).\nThe S2 engine returns a polygon \\emph{around} a number of S2 cells that\ncontain the buffer, and hence will always have an area larger than the\ntrue buffer, depending on \\code{max_cells}, and will be non-smooth when sufficiently zoomed in.\nThe GEOS engine will return line segments between points\non the circle, and so will always be \\emph{smaller} than the true\nbuffer, and be smooth, depending on the number of segments \\code{nQuadSegs}.\nA negative \\code{dist} value for geodetic coordinates using S2 does not give a proper (geodetic) buffer.\n\n\\code{st_boundary} returns the boundary of a geometry\n\n\\code{st_convex_hull} creates the convex hull of a set of points\n\n\\code{st_concave_hull} creates the concave hull of a geometry\n\n\\code{st_simplify} simplifies lines by removing vertices.\n\n\\code{st_triangulate} triangulates set of points (not constrained). \\code{st_triangulate} requires GEOS version 3.4 or above\n\n\\code{st_triangulate_constrained} returns the constrained delaunay triangulation of polygons; requires GEOS version 3.10 or above\n\n\\code{st_inscribed_circle} returns the maximum inscribed circle for polygon geometries.\nFor \\code{st_inscribed_circle}, if \\code{nQuadSegs} is 0 a 2-point LINESTRING is returned with the\ncenter point and a boundary point of every circle, otherwise a circle (buffer) is returned where\n\\code{nQuadSegs} controls the number of points per quadrant to approximate the circle.\n\\code{st_inscribed_circle} requires GEOS version 3.9 or above\n\n\\code{st_minimum_rotated_rectangle} returns the minimum\nrotated rectangular POLYGON which encloses the input geometry. The\nrectangle has width equal to the minimum diameter, and a longer\nlength. If the convex hill of the input is degenerate (a line or\npoint) a linestring or point is returned.\n\n\\code{st_minimum_bounding_circle}\nreturns a geometry which represents the \"minimum bounding circle\",\nthe smallest circle that contains the input.\n\n\\code{st_voronoi} creates voronoi tessellation. \\code{st_voronoi} requires GEOS version 3.5 or above\n\n\\code{st_polygonize} creates a polygon from lines that form a closed ring. In case of \\code{st_polygonize}, \\code{x} must be an object of class \\code{LINESTRING} or \\code{MULTILINESTRING}, or an \\code{sfc} geometry list-column object containing these\n\n\\code{st_line_merge} merges lines. In case of \\code{st_line_merge}, \\code{x} must be an object of class \\code{MULTILINESTRING}, or an \\code{sfc} geometry list-column object containing these\n\n\\code{st_centroid} gives the centroid of a geometry\n\n\\code{st_point_on_surface} returns a point guaranteed to be on the (multi)surface.\n\n\\code{st_reverse} reverses the nodes in a line\n\n\\code{st_node} adds nodes to linear geometries at intersections without a node, and only works on individual linear geometries\n\n\\code{st_segmentize} adds points to straight lines\n\n\\code{st_exterior_ring} returns the exterior rings of polygons, removing all holes.\n}\n\\examples{\n\n## st_buffer, style options (taken from rgeos gBuffer)\nl1 = st_as_sfc(\"LINESTRING(0 0,1 5,4 5,5 2,8 2,9 4,4 6.5)\")\nop = par(mfrow=c(2,3))\nplot(st_buffer(l1, dist = 1, endCapStyle=\"ROUND\"), reset = FALSE, main = \"endCapStyle: ROUND\")\nplot(l1,col='blue',add=TRUE)\nplot(st_buffer(l1, dist = 1, endCapStyle=\"FLAT\"), reset = FALSE, main = \"endCapStyle: FLAT\")\nplot(l1,col='blue',add=TRUE)\nplot(st_buffer(l1, dist = 1, endCapStyle=\"SQUARE\"), reset = FALSE, main = \"endCapStyle: SQUARE\")\nplot(l1,col='blue',add=TRUE)\nplot(st_buffer(l1, dist = 1, nQuadSegs=1), reset = FALSE, main = \"nQuadSegs: 1\")\nplot(l1,col='blue',add=TRUE)\nplot(st_buffer(l1, dist = 1, nQuadSegs=2), reset = FALSE, main = \"nQuadSegs: 2\")\nplot(l1,col='blue',add=TRUE)\nplot(st_buffer(l1, dist = 1, nQuadSegs= 5), reset = FALSE, main = \"nQuadSegs: 5\")\nplot(l1,col='blue',add=TRUE)\npar(op)\n\n\nl2 = st_as_sfc(\"LINESTRING(0 0,1 5,3 2)\")\nop = par(mfrow = c(2, 3))\nplot(st_buffer(l2, dist = 1, joinStyle=\"ROUND\"), reset = FALSE, main = \"joinStyle: ROUND\")\nplot(l2, col = 'blue', add = TRUE)\nplot(st_buffer(l2, dist = 1, joinStyle=\"MITRE\"), reset = FALSE, main = \"joinStyle: MITRE\")\nplot(l2, col= 'blue', add = TRUE)\nplot(st_buffer(l2, dist = 1, joinStyle=\"BEVEL\"), reset = FALSE, main = \"joinStyle: BEVEL\")\nplot(l2, col= 'blue', add=TRUE)\nplot(st_buffer(l2, dist = 1, joinStyle=\"MITRE\" , mitreLimit=0.5), reset = FALSE,\n   main = \"mitreLimit: 0.5\")\nplot(l2, col = 'blue', add = TRUE)\nplot(st_buffer(l2, dist = 1, joinStyle=\"MITRE\",mitreLimit=1), reset = FALSE,\n   main = \"mitreLimit: 1\")\nplot(l2, col = 'blue', add = TRUE)\nplot(st_buffer(l2, dist = 1, joinStyle=\"MITRE\",mitreLimit=3), reset = FALSE,\n   main = \"mitreLimit: 3\")\nplot(l2, col = 'blue', add = TRUE)\npar(op)\n\n# compare approximation errors depending on S2 or GEOS backend:\n# geographic coordinates, uses S2:\nx = st_buffer(st_as_sf(data.frame(lon=0,lat=0), coords=c(\"lon\",\"lat\"),crs='OGC:CRS84'), \n      units::as_units(1,\"km\"))\ny = units::set_units(st_area(x), \"km^2\")\n# error: postive, default maxcells = 1000\n(units::drop_units(y)-pi)/pi\nx = st_buffer(st_as_sf(data.frame(lon=0,lat=0), coords=c(\"lon\",\"lat\"),crs='OGC:CRS84'), \n      units::as_units(1,\"km\"), max_cells=1e5)\ny = units::set_units(st_area(x), \"km^2\")\n# error: positive but smaller:\n(units::drop_units(y)-pi)/pi\n\n# no CRS set: assumes Cartesian (projected) coordinates\nx = st_buffer(st_as_sf(data.frame(lon=0,lat=0), coords=c(\"lon\",\"lat\")), 1)\ny = st_area(x)\n# error: negative, nQuadSegs default at 30\n((y)-pi)/pi\nx = st_buffer(st_as_sf(data.frame(lon=0,lat=0), coords=c(\"lon\",\"lat\")), 1, nQuadSegs = 100)\ny = st_area(x)\n# error: negative but smaller:\n((y)-pi)/pi\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\nnc_g = st_geometry(nc)\nplot(st_convex_hull(nc_g))\nplot(nc_g, border = grey(.5), add = TRUE)\npt = st_combine(st_sfc(st_point(c(0,80)), st_point(c(120,80)), st_point(c(240,80))))\nst_convex_hull(pt) # R2\nst_convex_hull(st_set_crs(pt, 'OGC:CRS84')) # S2\nset.seed(131)\nif (compareVersion(sf_extSoftVersion()[[\"GEOS\"]], \"3.11.0\") > -1) {\n pts = cbind(runif(100), runif(100))\n m = st_multipoint(pts)\n co = sf:::st_concave_hull(m, 0.3)\n coh = sf:::st_concave_hull(m, 0.3, allow_holes = TRUE)\n plot(co, col = 'grey')\n plot(coh, add = TRUE, border = 'red')\n plot(m, add = TRUE)\n}\n\n# st_simplify examples:\nop = par(mfrow = c(2, 3), mar = rep(0, 4))\nplot(nc_g[1])\nplot(st_simplify(nc_g[1], dTolerance = 1e3)) # 1000m\nplot(st_simplify(nc_g[1], dTolerance = 5e3)) # 5000m\nnc_g_planar = st_transform(nc_g, 2264) # planar coordinates, US foot\nplot(nc_g_planar[1])\nplot(st_simplify(nc_g_planar[1], dTolerance = 1e3)) # 1000 foot\nplot(st_simplify(nc_g_planar[1], dTolerance = 5e3)) # 5000 foot\npar(op)\n\nif (compareVersion(sf_extSoftVersion()[[\"GEOS\"]], \"3.10.0\") > -1) {\n pts = rbind(c(0,0), c(1,0), c(1,1), c(.5,.5), c(0,1), c(0,0))\n po = st_polygon(list(pts))\n co = st_triangulate_constrained(po)\n tr = st_triangulate(po)\n plot(po, col = NA, border = 'grey', lwd = 15)\n plot(tr, border = 'green', col = NA, lwd = 5, add = TRUE)\n plot(co, border = 'red', col = 'NA', add = TRUE)\n}\nif (compareVersion(sf_extSoftVersion()[[\"GEOS\"]], \"3.9.0\") > -1) {\n  nc_t = st_transform(nc, 'EPSG:2264')\n  x = st_inscribed_circle(st_geometry(nc_t))\n  plot(st_geometry(nc_t), asp = 1, col = grey(.9))\n  plot(x, add = TRUE, col = '#ff9999')\n}\nset.seed(1)\nx = st_multipoint(matrix(runif(10),,2))\nbox = st_polygon(list(rbind(c(0,0),c(1,0),c(1,1),c(0,1),c(0,0))))\nif (compareVersion(sf_extSoftVersion()[[\"GEOS\"]], \"3.5.0\") > -1) {\n v = st_sfc(st_voronoi(x, st_sfc(box)))\n plot(v, col = 0, border = 1, axes = TRUE)\n plot(box, add = TRUE, col = 0, border = 1) # a larger box is returned, as documented\n plot(x, add = TRUE, col = 'red', cex=2, pch=16)\n plot(st_intersection(st_cast(v), box)) # clip to smaller box\n plot(x, add = TRUE, col = 'red', cex=2, pch=16)\n # matching Voronoi polygons to data points:\n # https://github.com/r-spatial/sf/issues/1030\n # generate 50 random unif points:\n n = 100\n pts = st_as_sf(data.frame(matrix(runif(n), , 2), id = 1:(n/2)), coords = c(\"X1\", \"X2\"))\n # compute Voronoi polygons:\n pols = st_collection_extract(st_voronoi(do.call(c, st_geometry(pts))))\n # match them to points:\n pts_pol = st_intersects(pts, pols)\n pts$pols = pols[unlist(pts_pol)] # re-order\n if (isTRUE(try(compareVersion(sf_extSoftVersion()[\"GEOS\"], \"3.12.0\") > -1,\n   silent = TRUE))) {\n   pols_po = st_collection_extract(st_voronoi(do.call(c, st_geometry(pts)),\n     point_order = TRUE)) # GEOS >= 3.12 can preserve order of inputs\n   pts_pol_po = st_intersects(pts, pols_po)\n   print(all(unlist(pts_pol_po) == 1:(n/2)))\n }\n plot(pts[\"id\"], pch = 16) # ID is color\n plot(st_set_geometry(pts, \"pols\")[\"id\"], xlim = c(0,1), ylim = c(0,1), reset = FALSE)\n plot(st_geometry(pts), add = TRUE)\n layout(matrix(1)) # reset plot layout\n}\nmls = st_multilinestring(list(matrix(c(0,0,0,1,1,1,0,0),,2,byrow=TRUE)))\nst_polygonize(st_sfc(mls))\nmls = st_multilinestring(list(rbind(c(0,0), c(1,1)), rbind(c(2,0), c(1,1))))\nst_line_merge(st_sfc(mls))\nplot(nc_g, axes = TRUE)\nplot(st_centroid(nc_g), add = TRUE, pch = 3, col = 'red')\nmp = st_combine(st_buffer(st_sfc(lapply(1:3, function(x) st_point(c(x,x)))), 0.2 * 1:3))\nplot(mp)\nplot(st_centroid(mp), add = TRUE, col = 'red') # centroid of combined geometry\nplot(st_centroid(mp, of_largest_polygon = TRUE), add = TRUE, col = 'blue', pch = 3)\nplot(nc_g, axes = TRUE)\nplot(st_point_on_surface(nc_g), add = TRUE, pch = 3, col = 'red')\nif (compareVersion(sf_extSoftVersion()[[\"GEOS\"]], \"3.7.0\") > -1) {\n  st_reverse(st_linestring(rbind(c(1,1), c(2,2), c(3,3))))\n}\n(l = st_linestring(rbind(c(0,0), c(1,1), c(0,1), c(1,0), c(0,0))))\nst_polygonize(st_node(l))\nst_node(st_multilinestring(list(rbind(c(0,0), c(1,1), c(0,1), c(1,0), c(0,0)))))\nsf = st_sf(a=1, geom=st_sfc(st_linestring(rbind(c(0,0),c(1,1)))), crs = 4326)\nif (require(lwgeom, quietly = TRUE)) {\n seg = st_segmentize(sf, units::set_units(100, km))\n seg = st_segmentize(sf, units::set_units(0.01, rad))\n nrow(seg$geom[[1]])\n}\n}\n\\seealso{\n\\link[grDevices]{chull} for a more efficient algorithm for calculating the convex hull\n}\n"
  },
  {
    "path": "man/interpolate_aw.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/aggregate.R\n\\name{interpolate_aw}\n\\alias{interpolate_aw}\n\\alias{st_interpolate_aw}\n\\alias{st_interpolate_aw.sf}\n\\title{Area-weighted interpolation or dasymetric mapping of polygon data}\n\\usage{\nst_interpolate_aw(x, to, extensive, ...)\n\n\\method{st_interpolate_aw}{sf}(\n  x,\n  to,\n  extensive,\n  ...,\n  keep_NA = FALSE,\n  na.rm = FALSE,\n  include_non_intersected = FALSE,\n  weights = character(0)\n)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf}, for which we want to aggregate attributes}\n\n\\item{to}{object of class \\code{sf} or \\code{sfc}, with the target geometries}\n\n\\item{extensive}{logical; if TRUE, the attribute variables are assumed to be spatially extensive (like population) and the sum is preserved, otherwise, spatially intensive (like population density) and the mean is preserved.}\n\n\\item{...}{ignored}\n\n\\item{keep_NA}{logical; if \\code{TRUE}, return all features in \\code{to}, if \\code{FALSE} return only those with non-NA values (but with \\code{row.names} the index corresponding to the feature in \\code{to})}\n\n\\item{na.rm}{logical; if \\code{TRUE} remove features with \\code{NA} attributes from \\code{x} before interpolating}\n\n\\item{include_non_intersected}{logical; for the case when \\code{extensive=FALSE}, when set to \\code{TRUE} divide by the target areas (including non-intersected areas),\nwhen \\code{FALSE} divide by the sum of the source areas.}\n\n\\item{weights}{character; name of column in \\code{to} that indicates (extensive) weights, to be used instead of areas, for redistributing attributes in \\code{x}; currently only works for \\code{extensive=TRUE}.}\n}\n\\description{\nArea-weighted interpolation or dasymetric mapping of polygon data\n}\n\\details{\nif \\code{extensive} is \\code{TRUE} and \\code{na.rm} is set to \\code{TRUE}, geometries with \\code{NA} are effectively treated as having zero attribute values. Dasymetric mapping is obtained when \\code{weights} are specified.\n}\n\\examples{\n# example Area-weighted interpolation:\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\ng = st_make_grid(nc, n = c(10, 5))\na1 = st_interpolate_aw(nc[\"BIR74\"], g, extensive = FALSE)\nsum(a1$BIR74) / sum(nc$BIR74) # not close to one: property is assumed spatially intensive\na2 = st_interpolate_aw(nc[\"BIR74\"], g, extensive = TRUE)\n# verify mass preservation (pycnophylactic) property:\nsum(a2$BIR74) / sum(nc$BIR74)\na1$intensive = a1$BIR74\na1$extensive = a2$BIR74\n\\donttest{plot(a1[c(\"intensive\", \"extensive\")], key.pos = 4)}\n\n# example Dasymetric mapping:\n# load nr of addresses per 10 km grid cell, to proxy population -> birth density:\ngrd.addr = system.file(\"gpkg/grd_addr.gpkg\", package=\"sf\") |> read_sf()\nxgrd.addr = grd.addr # copy for plotting\nxgrd.addr$ones[grd.addr$ones==0] = 1 # so that logz shows finite values\n\\donttest{plot(xgrd.addr, logz=TRUE, main = \"nr of addresses per cell\") # log scale}\nnc = st_transform(nc, st_crs(grd.addr))\n# avoid \"assumes attributes are constant or uniform over areas\" warnings:\nst_agr(nc) = c(BIR74 = \"constant\", BIR79 = \"constant\")\nst_agr(grd.addr) = c(ones = \"constant\")\n# dasymetric mapping\nbir.grd = st_interpolate_aw(nc[c(\"BIR74\",\"BIR79\")], extensive = TRUE, grd.addr, weights = \"ones\")\nxbir.grd = bir.grd # copy for plotting\nxbir.grd$BIR74[xbir.grd$BIR74 == 0] = 1 # so that logz shows finite values\n\\donttest{plot(xbir.grd[\"BIR74\"], logz = TRUE, main = \"redistributed birth counts, 1974-\")}\n# verify sums:\napply(as.data.frame(bir.grd)[1:2], 2, sum)\napply(as.data.frame(nc)[c(\"BIR74\", \"BIR79\")], 2, sum)\n# compare county-wise:\nst_agr(bir.grd) = c(BIR74 = \"constant\")\naw = st_interpolate_aw(bir.grd[\"BIR74\"], st_geometry(nc), extensive = TRUE)\nplot(nc$BIR74, aw$BIR74, log = 'xy', xlab = 'county-value', ylab = 'area-w interpolated')\nabline(0,1)\n}\n"
  },
  {
    "path": "man/is_driver_available.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/read.R\n\\name{is_driver_available}\n\\alias{is_driver_available}\n\\title{Check if driver is available}\n\\usage{\nis_driver_available(drv, drivers = st_drivers())\n}\n\\arguments{\n\\item{drv}{character. Name of driver}\n\n\\item{drivers}{data.frame. Table containing driver names and support. Default\nis from \\code{\\link{st_drivers}}}\n}\n\\description{\nSearch through the driver table if driver is listed\n}\n"
  },
  {
    "path": "man/is_driver_can.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/read.R\n\\name{is_driver_can}\n\\alias{is_driver_can}\n\\title{Check if a driver can perform an action}\n\\usage{\nis_driver_can(drv, drivers = st_drivers(), operation = \"write\")\n}\n\\arguments{\n\\item{drv}{character. Name of driver}\n\n\\item{drivers}{data.frame. Table containing driver names and support. Default\nis from \\code{\\link{st_drivers}}}\n\n\\item{operation}{character. What action to check}\n}\n\\description{\nSearch through the driver table to match a driver name with\nan action (e.g. \\code{\"write\"}) and check if the action is supported.\n}\n"
  },
  {
    "path": "man/is_geometry_column.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/db.R\n\\name{is_geometry_column}\n\\alias{is_geometry_column}\n\\title{Check if the columns could be of a coercable type for sf}\n\\usage{\nis_geometry_column(con, x, classes = \"\")\n}\n\\arguments{\n\\item{con}{database connection}\n\n\\item{x}{inherits data.frame}\n\n\\item{classes}{classes inherited}\n}\n\\description{\nCheck if the columns could be of a coercable type for sf\n}\n"
  },
  {
    "path": "man/merge.sf.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sf.R\n\\name{merge.sf}\n\\alias{merge.sf}\n\\title{merge method for sf and data.frame object}\n\\usage{\n\\method{merge}{sf}(x, y, ...)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf}}\n\n\\item{y}{object of class \\code{data.frame}}\n\n\\item{...}{arguments passed on to \\code{merge.data.frame}}\n}\n\\description{\nmerge method for sf and data.frame object\n}\n\\examples{\na = data.frame(a = 1:3, b = 5:7)\nst_geometry(a) = st_sfc(st_point(c(0,0)), st_point(c(1,1)), st_point(c(2,2)))\nb = data.frame(x = c(\"a\", \"b\", \"c\"), b = c(2,5,6))\nmerge(a, b)\nmerge(a, b, all = TRUE)\n}\n"
  },
  {
    "path": "man/nc.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/datasets.R\n\\docType{data}\n\\name{nc}\n\\alias{nc}\n\\title{North Carolina SIDS data}\n\\format{\nA \\code{sf} object\n}\n\\description{\nSudden Infant Death Syndrome (SIDS) sample data for North Carolina counties,\ntwo time periods (1974-78 and 1979-84). The details of the columns can be\nfound in a \\href{https://r-spatial.github.io/spdep/articles/sids.html}{spdep package vignette}.\nPlease note that, though this is basically the same as \\code{nc.sids} dataset in spData\npackage, \\code{nc} only contains a subset of variables. The differences are\nalso discussed on the vignette.\n}\n\\examples{\n\\donttest{\nnc <- st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\n}\n}\n\\seealso{\n\\url{https://r-spatial.github.io/spdep/articles/sids.html}\n}\n"
  },
  {
    "path": "man/plot.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/plot.R\n\\name{plot}\n\\alias{plot}\n\\alias{plot.sf}\n\\alias{get_key_pos}\n\\alias{plot.sfc_POINT}\n\\alias{plot.sfc_MULTIPOINT}\n\\alias{plot.sfc_LINESTRING}\n\\alias{plot.sfc_CIRCULARSTRING}\n\\alias{plot.sfc_MULTILINESTRING}\n\\alias{plot.sfc_POLYGON}\n\\alias{plot.sfc_MULTIPOLYGON}\n\\alias{plot.sfc_GEOMETRYCOLLECTION}\n\\alias{plot.sfc_GEOMETRY}\n\\alias{plot.sfg}\n\\alias{plot_sf}\n\\alias{sf.colors}\n\\alias{text.sf}\n\\alias{text.sfc}\n\\alias{points.sf}\n\\alias{points.sfc}\n\\title{plot sf object}\n\\usage{\n\\method{plot}{sf}(\n  x,\n  y,\n  ...,\n  main,\n  pal = NULL,\n  nbreaks = 10,\n  breaks = \"pretty\",\n  max.plot = getOption(\"sf_max.plot\", default = 9),\n  key.pos = get_key_pos(x, ...),\n  key.length = 0.618,\n  key.width = kw_dflt(x, key.pos),\n  reset = TRUE,\n  logz = FALSE,\n  extent = x,\n  xlim = st_bbox(extent)[c(1, 3)],\n  ylim = st_bbox(extent)[c(2, 4)],\n  compact = FALSE\n)\n\nget_key_pos(x, ...)\n\n\\method{plot}{sfc_POINT}(\n  x,\n  y,\n  ...,\n  pch = 1,\n  cex = 1,\n  col = 1,\n  bg = 0,\n  lwd = 1,\n  lty = 1,\n  type = \"p\",\n  add = FALSE\n)\n\n\\method{plot}{sfc_MULTIPOINT}(\n  x,\n  y,\n  ...,\n  pch = 1,\n  cex = 1,\n  col = 1,\n  bg = 0,\n  lwd = 1,\n  lty = 1,\n  type = \"p\",\n  add = FALSE\n)\n\n\\method{plot}{sfc_LINESTRING}(x, y, ..., lty = 1, lwd = 1, col = 1, pch = 1, type = \"l\", add = FALSE)\n\n\\method{plot}{sfc_CIRCULARSTRING}(x, y, ...)\n\n\\method{plot}{sfc_MULTILINESTRING}(x, y, ..., lty = 1, lwd = 1, col = 1, pch = 1, type = \"l\", add = FALSE)\n\n\\method{plot}{sfc_POLYGON}(\n  x,\n  y,\n  ...,\n  lty = 1,\n  lwd = 1,\n  col = NA,\n  cex = 1,\n  pch = NA,\n  border = 1,\n  add = FALSE,\n  rule = \"evenodd\",\n  xpd = par(\"xpd\")\n)\n\n\\method{plot}{sfc_MULTIPOLYGON}(\n  x,\n  y,\n  ...,\n  lty = 1,\n  lwd = 1,\n  col = NA,\n  border = 1,\n  add = FALSE,\n  rule = \"evenodd\",\n  xpd = par(\"xpd\")\n)\n\n\\method{plot}{sfc_GEOMETRYCOLLECTION}(\n  x,\n  y,\n  ...,\n  pch = 1,\n  cex = 1,\n  bg = 0,\n  lty = 1,\n  lwd = 1,\n  col = 1,\n  border = 1,\n  add = FALSE\n)\n\n\\method{plot}{sfc_GEOMETRY}(\n  x,\n  y,\n  ...,\n  pch = 1,\n  cex = 1,\n  bg = 0,\n  lty = 1,\n  lwd = 1,\n  col = ifelse(st_dimension(x) == 2, NA, 1),\n  border = 1,\n  add = FALSE\n)\n\n\\method{plot}{sfg}(x, ...)\n\nplot_sf(\n  x,\n  xlim = NULL,\n  ylim = NULL,\n  asp = NA,\n  axes = FALSE,\n  bgc = par(\"bg\"),\n  ...,\n  xaxs,\n  yaxs,\n  lab,\n  setParUsrBB = FALSE,\n  bgMap = NULL,\n  expandBB = c(0, 0, 0, 0),\n  graticule = NA_crs_,\n  col_graticule = \"grey\",\n  border,\n  extent = x\n)\n\nsf.colors(n = 10, cutoff.tails = c(0.35, 0.2), alpha = 1, categorical = FALSE)\n\n\\method{text}{sf}(x, labels = row.names(x), ...)\n\n\\method{text}{sfc}(x, labels = seq_along(x), ..., of_largest_polygon = FALSE)\n\n\\method{points}{sf}(x, ...)\n\n\\method{points}{sfc}(x, ..., of_largest_polygon = FALSE)\n}\n\\arguments{\n\\item{x}{object of class sf}\n\n\\item{y}{ignored}\n\n\\item{...}{further specifications, see \\link{plot_sf} and \\link{plot} and details.}\n\n\\item{main}{title for plot (\\code{NULL} to remove)}\n\n\\item{pal}{palette function, similar to \\link{rainbow}, or palette values; if omitted, \\code{sf.colors} is used}\n\n\\item{nbreaks}{number of colors breaks (ignored for \\code{factor} or \\code{character} variables)}\n\n\\item{breaks}{either a numeric vector with the actual breaks, or a name of a method accepted by the \\code{style} argument of \\link[classInt]{classIntervals}}\n\n\\item{max.plot}{integer; lower boundary to maximum number of attributes to plot; the default value (9) can be overridden by setting the global option \\code{sf_max.plot}, e.g. \\code{options(sf_max.plot=2)}}\n\n\\item{key.pos}{numeric; side to plot a color key: 1 bottom, 2 left, 3 top, 4 right; set to \\code{NULL} to omit key completely, 0 to only not plot the key, or -1 to select automatically. If multiple columns are plotted in a single function call by default no key is plotted and every submap is stretched individually; if a key is requested (and \\code{col} is missing) all maps are colored according to a single key. Auto select depends on plot size, map aspect, and, if set, parameter \\code{asp}. If it has lenght 2, the second value, ranging from 0 to 1, determines where the key is placed in the available space (default: 0.5, center).}\n\n\\item{key.length}{amount of space reserved for the key along its axis, length of the scale bar}\n\n\\item{key.width}{amount of space reserved for the key (incl. labels), thickness/width of the scale bar}\n\n\\item{reset}{logical; if \\code{FALSE}, keep the plot in a mode that allows adding further map elements; if \\code{TRUE} restore original mode after plotting \\code{sf} objects with attributes; see details.}\n\n\\item{logz}{logical; if \\code{TRUE}, use log10-scale for the attribute variable. In that case, \\code{breaks} and \\code{at} need to be given as log10-values; see examples.}\n\n\\item{extent}{object with an \\code{st_bbox} method to define plot extent; defaults to \\code{x}}\n\n\\item{xlim}{see \\link{plot.window}}\n\n\\item{ylim}{see \\link{plot.window}}\n\n\\item{compact}{logical; compact sub-plots over plotting space?}\n\n\\item{pch}{plotting symbol}\n\n\\item{cex}{symbol size}\n\n\\item{col}{color for plotting features; if \\code{length(col)} does not equal 1 or \\code{nrow(x)}, a warning is emitted that colors will be recycled. Specifying \\code{col} suppresses plotting the legend key.}\n\n\\item{bg}{symbol background color}\n\n\\item{lwd}{line width}\n\n\\item{lty}{line type}\n\n\\item{type}{plot type: 'p' for points, 'l' for lines, 'b' for both}\n\n\\item{add}{logical; add to current plot? Note that when using \\code{add=TRUE}, you may have to set \\code{reset=FALSE} in the first plot command.}\n\n\\item{border}{color of polygon border(s); using \\code{NA} hides them}\n\n\\item{rule}{see \\link[graphics]{polypath}; for \\code{winding}, exterior ring direction should be opposite that of the holes; with \\code{evenodd}, plotting is robust against misspecified ring directions}\n\n\\item{xpd}{see \\link[graphics]{par}; sets polygon clipping strategy; only implemented for POLYGON and MULTIPOLYGON}\n\n\\item{asp}{see below, and see \\link{par}}\n\n\\item{axes}{logical; should axes be plotted? (default FALSE)}\n\n\\item{bgc}{background color}\n\n\\item{xaxs}{see \\link{par}}\n\n\\item{yaxs}{see \\link{par}}\n\n\\item{lab}{see \\link{par}}\n\n\\item{setParUsrBB}{default FALSE; set the \\code{par} \\dQuote{usr} bounding box; see below}\n\n\\item{bgMap}{object of class \\code{ggmap}, or returned by function \\code{RgoogleMaps::GetMap}}\n\n\\item{expandBB}{numeric; fractional values to expand the bounding box with,\nin each direction (bottom, left, top, right)}\n\n\\item{graticule}{logical, or object of class \\code{crs} (e.g., \\code{st_crs('OGC:CRS84')} for a WGS84 graticule), or object created by \\link{st_graticule}}\n\n\\item{col_graticule}{color to used for the graticule (if present)}\n\n\\item{n}{integer; number of colors}\n\n\\item{cutoff.tails}{numeric, in \\verb{[0,0.5]} start and end values}\n\n\\item{alpha}{numeric, in \\verb{[0,1]}, transparency}\n\n\\item{categorical}{logical; do we want colors for a categorical variable? (see details)}\n\n\\item{labels}{character, text to draw (one per row of input)}\n\n\\item{of_largest_polygon}{logical, passed on to \\link{st_centroid}}\n}\n\\description{\nplot one or more attributes of an sf object on a map\nPlot sf object\n}\n\\details{\n\\code{plot.sf} maximally plots \\code{max.plot} maps with colors following from attribute columns,\none map per attribute. It uses \\code{sf.colors} for default colors. For more control over placement of individual maps,\nset parameter \\code{mfrow} with \\link{par} prior to plotting, and plot single maps one by one; note that this only works\nin combination with setting parameters \\code{key.pos=NULL} (no legend) and \\code{reset=FALSE}.\n\n\\code{plot.sfc} plots the geometry, additional parameters can be passed on\nto control color, lines or symbols.\n\nWhen setting \\code{reset} to \\code{FALSE}, the original device parameters are lost, and the device must be reset using \\code{dev.off()} in order to reset it.\n\nparameter \\code{at} can be set to specify where labels are placed along the key; see examples.\n\nparameter \\code{mar} can be set in \\code{...} to override default margins.\n\nThe features are plotted in the order as they apppear in the sf object. See examples for when a different plotting order is wanted.\n\n\\code{plot_sf} sets up the plotting area, axes, graticule, or webmap background; it\nis called by all \\code{plot} methods before anything is drawn.\n\nThe argument \\code{setParUsrBB} may be used to pass the logical value \\code{TRUE} to functions within \\code{plot.Spatial}. When set to \\code{TRUE}, par(\\dQuote{usr}) will be overwritten with \\code{c(xlim, ylim)}, which defaults to the bounding box of the spatial object. This is only needed in the particular context of graphic output to a specified device with given width and height, to be matched to the spatial object, when using par(\\dQuote{xaxs}) and par(\\dQuote{yaxs}) in addition to \\code{par(mar=c(0,0,0,0))}.\n\nThe default aspect for map plots is 1; if however data are not\nprojected (coordinates are long/lat), the aspect is by default set to\n1/cos(My * pi/180) with My the y coordinate of the middle of the map\n(the mean of \\code{ylim}, which defaults to the y range of bounding box). This\nimplies an \\href{https://en.wikipedia.org/wiki/Equirectangular_projection}{Equirectangular projection}.\n\nnon-categorical colors from \\code{sf.colors} were taken from \\link[sp]{bpy.colors}, with modified \\code{cutoff.tails} defaults\nIf categorical is \\code{TRUE}, default colors are from \\url{https://colorbrewer2.org/} (if n < 9, Set2, else Set3).\n\n\\code{text.sf} adds text to an existing base graphic. Text is placed at the centroid of\neach feature in \\code{x}. Provide POINT features for further control of placement.\n\\code{points.sf} adds point symbols to an existing base graphic. If points of text are not shown\ncorrectly, try setting argument \\code{reset} to \\code{FALSE} in the \\code{plot()} call.\n}\n\\examples{\nnc = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), quiet = TRUE)\n# plot single attribute, auto-legend:\nplot(nc[\"SID74\"])\n# plot multiple:\nplot(nc[c(\"SID74\", \"SID79\")]) # better use ggplot2::geom_sf to facet and get a single legend!\n# adding to a plot of an sf object only works when using reset=FALSE in the first plot:\nplot(nc[\"SID74\"], reset = FALSE)\nplot(st_centroid(st_geometry(nc)), add = TRUE)\n# log10 z-scale:\nplot(nc[\"SID74\"], logz = TRUE, breaks = c(0,.5,1,1.5,2), at = c(0,.5,1,1.5,2))\n# and we need to reset the plotting device after that, e.g. by\nlayout(1)\n# when plotting only geometries, the reset=FALSE is not needed:\nplot(st_geometry(nc))\nplot(st_geometry(nc)[1], col = 'red', add = TRUE)\n# add a custom legend to an arbitray plot:\nlayout(matrix(1:2, ncol = 2), widths = c(1, lcm(2)))\nplot(1)\n.image_scale(1:10, col = sf.colors(9), key.length = lcm(8), key.pos = 4, at = 1:10)\n# manipulate plotting order, plot largest polygons first:\np = st_polygon(list(rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0))))\nx = st_sf(a=1:4, st_sfc(p, p * 2, p * 3, p * 4)) # plot(x, col=2:5) only shows the largest polygon!\nplot(x[order(st_area(x), decreasing = TRUE),], col = 2:5) # plot largest polygons first\n\nsf.colors(10)\ntext(nc, labels = substring(nc$NAME,1,1))\n}\n"
  },
  {
    "path": "man/prefix_map.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/read.R\n\\docType{data}\n\\name{prefix_map}\n\\alias{prefix_map}\n\\title{Map prefix to driver}\n\\usage{\nprefix_map\n}\n\\description{\nMap prefix to driver\n}\n"
  },
  {
    "path": "man/proj_tools.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/proj.R\n\\name{proj_tools}\n\\alias{proj_tools}\n\\alias{sf_proj_search_paths}\n\\alias{sf_proj_network}\n\\alias{sf_proj_pipelines}\n\\title{Manage PROJ settings}\n\\usage{\nsf_proj_search_paths(paths = character(0), with_proj = NA)\n\nsf_proj_network(enable = FALSE, url = character(0))\n\nsf_proj_pipelines(\n  source_crs,\n  target_crs,\n  authority = character(0),\n  AOI = numeric(0),\n  Use = \"NONE\",\n  grid_availability = \"USED\",\n  desired_accuracy = -1,\n  strict_containment = FALSE,\n  axis_order_authority_compliant = st_axis_order()\n)\n}\n\\arguments{\n\\item{paths}{the search path to be set; omit if paths need to be queried}\n\n\\item{with_proj}{logical; if \\code{NA} set for both GDAL and PROJ, otherwise set either for PROJ (\\code{TRUE}) or GDAL (\\code{FALSE})}\n\n\\item{enable}{logical; set this to enable (\\code{TRUE}) or disable (\\code{FALSE}) the proj network search facility}\n\n\\item{url}{character; use this to specify and override the default proj network CDN}\n\n\\item{source_crs, target_crs}{object of class \\code{crs} or character}\n\n\\item{authority}{character; constrain output pipelines to those of authority}\n\n\\item{AOI}{length four numeric; desired area of interest for the resulting\ncoordinate transformations (west, south, east, north, in degrees).\nFor an area of interest crossing the anti-meridian, west will be greater than east.}\n\n\\item{Use}{one of \"NONE\", \"BOTH\", \"INTERSECTION\", \"SMALLEST\", indicating how AOI's\nof source_crs and target_crs are being used}\n\n\\item{grid_availability}{character; one of \"USED\" (Grid availability is only used for sorting\nresults. Operations where some grids are missing will be sorted last), \"DISCARD\"\n(Completely discard an operation if a required grid is missing)\n, \"IGNORED\" (Ignore grid availability at all. Results will be presented as if all grids were\navailable.), or \"AVAILABLE\" (Results will be presented as if grids known to PROJ (that is\nregistered in the grid_alternatives table of its database) were available. Used typically when\nnetworking is enabled.)}\n\n\\item{desired_accuracy}{numeric; only return pipelines with at least this accuracy}\n\n\\item{strict_containment}{logical; default \\code{FALSE}; permit partial matching of the area\nof interest; if \\code{TRUE} strictly contain the area of interest.\nThe area of interest is either as given in AOI, or as implied by the\nsource/target coordinate reference systems}\n\n\\item{axis_order_authority_compliant}{logical; if \\code{FALSE} always\nchoose ‘x’ or longitude for the first\naxis; if TRUE, follow the axis orders given by the coordinate reference systems when\nconstructing the for the first axis; if \\code{FALSE}, follow the axis orders given by}\n}\n\\value{\n\\code{sf_proj_search_paths()} returns the search path (possibly after setting it)\n\n\\code{sf_proj_network} when called without arguments returns a logical indicating whether\nnetwork search of datum grids is enabled, when called with arguments it returns a character\nvector with the URL of the CDN used (or specified with \\code{url}).\n\n\\code{sf_proj_pipelines()} returns a table with candidate coordinate transformation\npipelines along with their accuracy; \\code{NA} accuracy indicates ballpark accuracy.\n}\n\\description{\nQuery or manage PROJ search path and network settings\n}\n"
  },
  {
    "path": "man/rawToHex.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/wkb.R\n\\name{rawToHex}\n\\alias{rawToHex}\n\\title{Convert raw vector(s) into hexadecimal character string(s)}\n\\usage{\nrawToHex(x)\n}\n\\arguments{\n\\item{x}{raw vector, or list with raw vectors}\n}\n\\description{\nConvert raw vector(s) into hexadecimal character string(s)\n}\n"
  },
  {
    "path": "man/s2.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/s2.R\n\\name{s2}\n\\alias{s2}\n\\alias{sf_use_s2}\n\\alias{st_as_s2}\n\\alias{st_as_s2.sf}\n\\alias{st_as_s2.sfc}\n\\title{functions for spherical geometry, using s2 package}\n\\usage{\nsf_use_s2(use_s2)\n\nst_as_s2(x, ...)\n\n\\method{st_as_s2}{sf}(x, ...)\n\n\\method{st_as_s2}{sfc}(\n  x,\n  ...,\n  oriented = getOption(\"s2_oriented\", FALSE) || isTRUE(attr(x, \"oriented\")),\n  rebuild = FALSE\n)\n}\n\\arguments{\n\\item{use_s2}{logical; if \\code{TRUE}, use the s2 spherical geometry package\nfor geographical coordinate operations}\n\n\\item{x}{object of class \\code{sf}, \\code{sfc} or \\code{sfg}}\n\n\\item{...}{passed on}\n\n\\item{oriented}{logical; if \\code{FALSE}, polygons that\ncover more than half of the globe are inverted; if \\code{TRUE}, no reversal\ntakes place and it is assumed that the inside of the polygon is to the\nleft of the polygon's path.}\n\n\\item{rebuild}{logical; call \\link[s2]{s2_rebuild} on the geometry (think of this as a \\code{st_make_valid} on the sphere)}\n}\n\\value{\n\\code{sf_use_s2} returns the value of this variable before (re)setting it,\ninvisibly if \\code{use_s2} is not missing.\n}\n\\description{\nfunctions for spherical geometry, using the s2 package based on the google s2geometry.io library\n}\n\\details{\n\\code{st_as_s2} converts an \\code{sf} POLYGON object into a form readable by \\code{s2}.\n}\n\\examples{\nm = rbind(c(-1,-1), c(1,-1), c(1,1), c(-1,1), c(-1,-1))\nm1 = rbind(c(-1,-1), c(1,-1), c(1,1), c(-1,1), c(-1,0), c(-1,-1))\nm0 = m[5:1,]\nmp = st_multipolygon(list(\nlist(m, 0.8 * m0, 0.01 * m1 + 0.9),\nlist(0.7* m, 0.6*m0),\nlist(0.5 * m0),\nlist(m+2),\nlist(m+4,(.9*m0)+4)\n))\nsf = st_sfc(mp, mp, crs = 'EPSG:4326')\ns2 = st_as_s2(sf)\n}\n"
  },
  {
    "path": "man/sf-defunct.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/defunct.R\n\\name{sf-defunct}\n\\alias{sf-defunct}\n\\alias{st_read_db}\n\\alias{st_write_db}\n\\title{Deprecated functions in \\code{sf}}\n\\usage{\nst_read_db(\n  conn = NULL,\n  table = NULL,\n  query = NULL,\n  geom_column = NULL,\n  EWKB = TRUE,\n  ...\n)\n\nst_write_db(\n  conn = NULL,\n  obj,\n  table = deparse(substitute(obj)),\n  ...,\n  drop = FALSE,\n  append = FALSE\n)\n}\n\\arguments{\n\\item{conn}{open database connection}\n\n\\item{table}{table name}\n\n\\item{query}{SQL query to select records; see details}\n\n\\item{geom_column}{deprecated. Geometry column name}\n\n\\item{EWKB}{logical; is the WKB of type EWKB? if missing, defaults to\n\\code{TRUE}}\n\n\\item{...}{parameter(s) passed on to \\link{st_as_sf}}\n}\n\\description{\nThese functions are provided for compatibility with older version of \\code{sf}.\nThey will eventually be completely removed.\n\\itemize{\n\\item Use \\code{\\link[=st_read]{st_read()}} instead of \\code{st_read_db()}.\n\\item Use \\code{\\link[=st_write]{st_write()}} instead_of \\code{st_write_db()}\n}\n}\n\\details{\nThe \\code{geom_column} argument is deprecated. The function will\nautomatically find the \\code{geometry} type columns. For the \\code{RPostgreSQL} drivers\nit will try to cast all the character columns, which can be long for very wide\ntables.\n}\n\\keyword{internal}\n"
  },
  {
    "path": "man/sf-package.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sf-package.R\n\\docType{package}\n\\name{sf-package}\n\\alias{sf-package}\n\\title{sf: Simple Features for R}\n\\description{\n\\if{html}{\\figure{logo.png}{options: style='float: right' alt='logo' width='120'}}\n\nSupport for simple feature access, a standardized way to encode and analyze spatial vector data. Binds to 'GDAL' \\doi{10.5281/zenodo.5884351} for reading and writing data, to 'GEOS' \\doi{10.5281/zenodo.11396894} for geometrical operations, and to 'PROJ' \\doi{10.5281/zenodo.5884394} for projection conversions and datum transformations. Uses by default the 's2' package for geometry operations on geodetic (long/lat degree) coordinates.\n}\n\\references{\nPebesma, E. and Bivand, R. (2023). Spatial Data\nScience: With Applications in R. Chapman and Hall/CRC.\n\\doi{10.1201/9780429459016} which is also found freely\nonline at \\url{https://r-spatial.org/book/}\n\nPebesma, E., 2018. Simple Features for R: Standardized Support\nfor Spatial Vector Data. The R Journal 10 (1), 439-446,\n\\doi{10.32614/RJ-2018-009} (open access)\n}\n\\seealso{\nUseful links:\n\\itemize{\n  \\item \\url{https://r-spatial.github.io/sf/}\n  \\item \\url{https://github.com/r-spatial/sf}\n  \\item Report bugs at \\url{https://github.com/r-spatial/sf/issues}\n}\n\n}\n\\author{\n\\strong{Maintainer}: Edzer Pebesma \\email{edzer.pebesma@uni-muenster.de} (\\href{https://orcid.org/0000-0001-8049-7069}{ORCID})\n\nAuthors:\n\\itemize{\n  \\item Edzer Pebesma \\email{edzer.pebesma@uni-muenster.de} (\\href{https://orcid.org/0000-0001-8049-7069}{ORCID})\n}\n\nOther contributors:\n\\itemize{\n  \\item Roger Bivand (\\href{https://orcid.org/0000-0003-2392-6140}{ORCID}) [contributor]\n  \\item Etienne Racine [contributor]\n  \\item Michael Sumner [contributor]\n  \\item Ian Cook [contributor]\n  \\item Tim Keitt [contributor]\n  \\item Robin Lovelace [contributor]\n  \\item Hadley Wickham [contributor]\n  \\item Jeroen Ooms (\\href{https://orcid.org/0000-0002-4035-0289}{ORCID}) [contributor]\n  \\item Kirill Müller [contributor]\n  \\item Thomas Lin Pedersen [contributor]\n  \\item Dan Baston [contributor]\n  \\item Dewey Dunnington (\\href{https://orcid.org/0000-0002-9415-4582}{ORCID}) [contributor]\n  \\item Alexandre Courtiol (\\href{https://orcid.org/0000-0003-0637-2959}{ORCID}) [contributor]\n}\n\n}\n\\keyword{internal}\n"
  },
  {
    "path": "man/sf.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sf.R\n\\name{sf}\n\\alias{sf}\n\\alias{st_sf}\n\\alias{[.sf}\n\\alias{print.sf}\n\\title{Create sf object}\n\\usage{\nst_sf(\n  ...,\n  agr = NA_agr_,\n  row.names,\n  stringsAsFactors = sf_stringsAsFactors(),\n  crs,\n  precision,\n  sf_column_name = NULL,\n  check_ring_dir = FALSE,\n  sfc_last = TRUE\n)\n\n\\method{[}{sf}(x, i, j, ..., drop = FALSE, op = st_intersects)\n\n\\method{print}{sf}(x, ..., n = getOption(\"sf_max_print\", default = 10))\n}\n\\arguments{\n\\item{...}{column elements to be binded into an \\code{sf} object or a single \\code{list} or \\code{data.frame} with such columns; at least one of these columns shall be a geometry list-column of class \\code{sfc} or be a list-column that can be converted into an \\code{sfc} by \\link{st_as_sfc}.}\n\n\\item{agr}{character vector; see details below.}\n\n\\item{row.names}{row.names for the created \\code{sf} object}\n\n\\item{stringsAsFactors}{logical; see \\link{st_read}}\n\n\\item{crs}{coordinate reference system, something suitable as input to \\link{st_crs}}\n\n\\item{precision}{numeric; see \\link{st_as_binary}}\n\n\\item{sf_column_name}{character; name of the active list-column with simple feature geometries; in case\nthere is more than one and \\code{sf_column_name} is \\code{NULL}, the first one is taken.}\n\n\\item{check_ring_dir}{see \\link{st_read}}\n\n\\item{sfc_last}{logical; if \\code{TRUE}, \\code{sfc} columns are always put last, otherwise column order is left unmodified.}\n\n\\item{x}{object of class \\code{sf}}\n\n\\item{i}{record selection, see \\link{[.data.frame}, or a \\code{sf} object to work with the \\code{op} argument}\n\n\\item{j}{variable selection, see \\link{[.data.frame}}\n\n\\item{drop}{logical, default \\code{FALSE}; if \\code{TRUE} drop the geometry column and return a \\code{data.frame}, else make the geometry sticky and return a \\code{sf} object.}\n\n\\item{op}{function; geometrical binary predicate function to apply when \\code{i} is a simple feature object}\n\n\\item{n}{maximum number of features to print; can be set globally by \\code{options(sf_max_print=...)}}\n}\n\\description{\nCreate sf, which extends data.frame-like objects with a simple feature list column.\nTo convert a data frame object to \\code{sf}, use \\code{\\link[=st_as_sf]{st_as_sf()}}\n}\n\\details{\n\\code{agr}, attribute-geometry-relationship, specifies for each non-geometry attribute column how it relates to the geometry, and can have one of following values: \"constant\", \"aggregate\", \"identity\". \"constant\" is used for attributes that are constant throughout the geometry (e.g. land use), \"aggregate\" where the attribute is an aggregate value over the geometry (e.g. population density or population count), \"identity\" when the attributes uniquely identifies the geometry of particular \"thing\", such as a building ID or a city name. The default value, \\code{NA_agr_}, implies we don't know.\n\nWhen a single value is provided to \\code{agr}, it is cascaded across all input columns; otherwise, a named vector like \\code{c(feature1='constant', ...)} will set \\code{agr} value to \\code{'constant'} for the input column named \\code{feature1}. See \\code{demo(nc)} for a worked example of this.\n\nWhen confronted with a data.frame-like object, \\code{st_sf} will try to find a geometry column of class \\code{sfc}, and otherwise try to convert list-columns when available into a geometry column, using \\link{st_as_sfc}.\n\n\\code{[.sf} will return a \\code{data.frame} or vector if the geometry column (of class \\code{sfc}) is dropped (\\code{drop=TRUE}), an \\code{sfc} object if only the geometry column is selected, and otherwise return an \\code{sf} object; see also \\link{[.data.frame}; for \\code{[.sf} \\code{...} arguments are passed to \\code{op}.\n}\n\\examples{\ng = st_sfc(st_point(1:2))\nst_sf(a=3,g)\nst_sf(g, a=3)\nst_sf(a=3, st_sfc(st_point(1:2))) # better to name it!\n# create empty structure with preallocated empty geometries:\nnrows <- 10\ngeometry = st_sfc(lapply(1:nrows, function(x) st_geometrycollection()))\ndf <- st_sf(id = 1:nrows, geometry = geometry)\ng = st_sfc(st_point(1:2), st_point(3:4))\ns = st_sf(a=3:4, g)\ns[1,]\nclass(s[1,])\ns[,1]\nclass(s[,1])\ns[,2]\nclass(s[,2])\ng = st_sf(a=2:3, g)\npol = st_sfc(st_polygon(list(cbind(c(0,3,3,0,0),c(0,0,3,3,0)))))\nh = st_sf(r = 5, pol)\ng[h,]\nh[g,]\n}\n"
  },
  {
    "path": "man/sf_extSoftVersion.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/init.R\n\\name{sf_extSoftVersion}\n\\alias{sf_extSoftVersion}\n\\title{Provide the external dependencies versions of the libraries linked to sf}\n\\usage{\nsf_extSoftVersion()\n}\n\\description{\nProvide the external dependencies versions of the libraries linked to sf\n}\n"
  },
  {
    "path": "man/sf_project.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/init.R, R/proj.R\n\\name{sf_project}\n\\alias{sf_project}\n\\alias{sf_add_proj_units}\n\\title{directly transform a set of coordinates}\n\\usage{\nsf_add_proj_units()\n\nsf_project(\n  from = character(0),\n  to = character(0),\n  pts,\n  keep = FALSE,\n  warn = TRUE,\n  authority_compliant = st_axis_order()\n)\n}\n\\arguments{\n\\item{from}{character description of source CRS, or object of class \\code{crs},\nor pipeline describing a transformation}\n\n\\item{to}{character description of target CRS, or object of class \\code{crs}}\n\n\\item{pts}{two-, three- or four-column numeric matrix, or object that can be coerced into a matrix; columns 3 and 4 contain z and t values.}\n\n\\item{keep}{logical value controlling the handling of unprojectable points. If\n\\code{keep} is \\code{TRUE}, then such points will yield \\code{Inf} or \\code{-Inf} in the\nreturn value; otherwise an error is reported and nothing is returned.}\n\n\\item{warn}{logical; if \\code{TRUE}, warn when non-finite values are generated}\n\n\\item{authority_compliant}{logical; \\code{TRUE} means handle axis order authority compliant (e.g. EPSG:4326 implying x=lat, y=lon), \\code{FALSE} means use visualisation order (i.e. always x=lon, y=lat)}\n}\n\\value{\ntwo-column numeric matrix with transformed/converted coordinates, returning invalid values as \\code{Inf}\n}\n\\description{\ndirectly transform a set of coordinates\n}\n\\details{\n\\code{sf_add_proj_units} loads the PROJ units \\code{link}, \\code{us_in}, \\code{ind_yd}, \\code{ind_ft}, and \\code{ind_ch} into the udunits database, and returns \\code{TRUE} invisibly on success.\n}\n\\examples{\nsf_add_proj_units()\n}\n"
  },
  {
    "path": "man/sfc.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sfc.R\n\\name{sfc}\n\\alias{sfc}\n\\alias{st_sfc}\n\\alias{sfc_POINT}\n\\alias{sfc_LINESTRING}\n\\alias{sfc_POLYGON}\n\\alias{sfc_MULTIPOINT}\n\\alias{sfc_MULTILINESTRING}\n\\alias{sfc_MULTIPOLYGON}\n\\alias{sfc_GEOMETRYCOLLECTION}\n\\alias{[.sfc}\n\\title{Create simple feature geometry list column}\n\\usage{\nst_sfc(\n  ...,\n  crs = NA_crs_,\n  precision = 0,\n  check_ring_dir = FALSE,\n  dim,\n  recompute_bbox = FALSE,\n  oriented = NA,\n  fall_back_class = c(\"sfc_GEOMETRY\", \"sfc\")\n)\n\n\\method{[}{sfc}(x, i, j, ..., op = st_intersects)\n}\n\\arguments{\n\\item{...}{input: zero or more simple feature geometries (objects of class \\code{sfg}), or a single list of such objects; \\code{NULL} values will get replaced by empty geometries.}\n\n\\item{crs}{coordinate reference system: integer with the EPSG code, or character with proj4string}\n\n\\item{precision}{numeric; see \\link{st_as_binary}}\n\n\\item{check_ring_dir}{see \\link{st_read}}\n\n\\item{dim}{character; if this function is called without valid geometries, this argument may carry the right dimension to set empty geometries}\n\n\\item{recompute_bbox}{logical; use \\code{TRUE} to force recomputation of the bounding box}\n\n\\item{oriented}{logical; if \\code{TRUE}, the ring is oriented such that left of the edges is inside the polygon; this is\nneeded for convering polygons larger than half the globe to s2}\n\n\\item{fall_back_class}{character; class for return object when no geometries are provided as input}\n\n\\item{x}{object of class \\code{sfc}}\n\n\\item{i}{record selection. Might also be an \\code{sfc}/\\code{sf} object to work with the \\code{op} argument}\n\n\\item{j}{ignored if \\code{op} is specified}\n\n\\item{op}{function, geometrical binary predicate function to apply when\n\\code{i} is a \\code{sf}/\\code{sfc} object. Additional arguments can be\nspecified using \\code{...}, see examples.}\n}\n\\value{\nan object of class \\code{sfc}, which is a classed list-column with simple feature geometries.\n}\n\\description{\nCreate simple feature geometry list column, set class, and add coordinate reference system and precision.\nFor data.frame alternatives see \\code{\\link[=st_sf]{st_sf()}}. To convert a foreign object to \\code{sfc}, see \\code{\\link[=st_as_sfc]{st_as_sfc()}}\n}\n\\details{\nA simple feature geometry list-column is a list of class\n\\code{c(\"stc_TYPE\", \"sfc\")} which most often contains objects of identical type;\nin case of a mix of types or an empty set, \\code{TYPE} is set to the\nsuperclass \\code{GEOMETRY}.\n\nif \\code{x} has a \\code{dim} attribute (i.e. is an \\code{array} or \\code{matrix}) then \\code{op} cannot be used.\n}\n\\examples{\npt1 = st_point(c(0,1))\npt2 = st_point(c(1,1))\n(sfc = st_sfc(pt1, pt2))\nsfc[sfc[1], op = st_is_within_distance, dist = 0.5]\nd = st_sf(data.frame(a=1:2, geom=sfc))\n}\n"
  },
  {
    "path": "man/sgbp.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sgbp.R\n\\name{sgbp}\n\\alias{sgbp}\n\\alias{print.sgbp}\n\\alias{t.sgbp}\n\\alias{as.matrix.sgbp}\n\\alias{dim.sgbp}\n\\alias{Ops.sgbp}\n\\alias{as.data.frame.sgbp}\n\\title{Methods for dealing with sparse geometry binary predicate lists}\n\\usage{\n\\method{print}{sgbp}(x, ..., n = 10, max_nb = 10)\n\n\\method{t}{sgbp}(x)\n\n\\method{as.matrix}{sgbp}(x, ...)\n\n\\method{dim}{sgbp}(x)\n\n\\method{Ops}{sgbp}(e1, e2)\n\n\\method{as.data.frame}{sgbp}(x, ...)\n}\n\\arguments{\n\\item{x}{object of class \\code{sgbp}}\n\n\\item{...}{ignored}\n\n\\item{n}{integer; maximum number of items to print}\n\n\\item{max_nb}{integer; maximum number of neighbours to print for each item}\n\n\\item{e1}{object of class \\code{sgbp}}\n\n\\item{e2}{object of class \\code{sgbp}}\n}\n\\description{\nMethods for dealing with sparse geometry binary predicate lists\n}\n\\details{\n\\code{sgbp} are sparse matrices, stored as a list with integer vectors holding the ordered \\code{TRUE} indices of each row. This means that for a dense, \\eqn{m \\times n}{m x n} matrix \\code{Q} and a list \\code{L}, if \\code{Q[i,j]} is \\code{TRUE} then \\eqn{j} is an element of \\code{L[[i]]}. Reversed: when \\eqn{k} is the value of \\code{L[[i]][j]}, then \\code{Q[i,k]} is \\code{TRUE}.\n\n\\code{==} compares only the dimension and index values, not the attributes of two \\code{sgbp} object; use \\code{identical} to check for equality of everything.\n}\n"
  },
  {
    "path": "man/st.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sfg.R\n\\name{st}\n\\alias{st}\n\\alias{st_point}\n\\alias{st_multipoint}\n\\alias{st_linestring}\n\\alias{st_polygon}\n\\alias{st_multilinestring}\n\\alias{st_multipolygon}\n\\alias{st_geometrycollection}\n\\alias{print.sfg}\n\\alias{head.sfg}\n\\alias{format.sfg}\n\\alias{c.sfg}\n\\alias{as.matrix.sfg}\n\\title{Create simple feature from a numeric vector, matrix or list}\n\\usage{\nst_point(x = c(NA_real_, NA_real_), dim = \"XYZ\")\n\nst_multipoint(x = matrix(numeric(0), 0, 2), dim = \"XYZ\")\n\nst_linestring(x = matrix(numeric(0), 0, 2), dim = \"XYZ\")\n\nst_polygon(x = list(), dim = if (length(x)) \"XYZ\" else \"XY\")\n\nst_multilinestring(x = list(), dim = if (length(x)) \"XYZ\" else \"XY\")\n\nst_multipolygon(x = list(), dim = if (length(x)) \"XYZ\" else \"XY\")\n\nst_geometrycollection(x = list(), dims = \"XY\")\n\n\\method{print}{sfg}(x, ..., width = 0)\n\n\\method{head}{sfg}(x, n = 10L, ...)\n\n\\method{format}{sfg}(x, ..., width = 30)\n\n\\method{c}{sfg}(..., recursive = FALSE, flatten = TRUE)\n\n\\method{as.matrix}{sfg}(x, ...)\n}\n\\arguments{\n\\item{x}{for \\code{st_point}, numeric vector (or one-row-matrix) of length 2, 3 or 4; for \\code{st_linestring} and \\code{st_multipoint}, numeric matrix with points in rows; for \\code{st_polygon} and \\code{st_multilinestring}, list with numeric matrices with points in rows; for \\code{st_multipolygon}, list of lists with numeric matrices; for \\code{st_geometrycollection} list with (non-geometrycollection) simple feature geometry (sfg) objects; see examples below}\n\n\\item{dim}{character, indicating dimensions: \"XY\", \"XYZ\", \"XYM\", or \"XYZM\"; only really needed for three-dimensional points (which can be either XYZ or XYM) or empty geometries; see details}\n\n\\item{dims}{character; specify dimensionality in case of an empty (NULL) geometrycollection, in which case \\code{x} is the empty \\code{list()}.}\n\n\\item{...}{objects to be pasted together into a single simple feature}\n\n\\item{width}{integer; number of characters to be printed (max 30; 0 means print everything)}\n\n\\item{n}{integer; number of elements to be selected}\n\n\\item{recursive}{logical; ignored}\n\n\\item{flatten}{logical; if \\code{TRUE}, try to simplify results; if \\code{FALSE}, return geometrycollection containing all objects}\n}\n\\value{\nobject of the same nature as \\code{x}, but with appropriate class attribute set\n\nas.matrix returns the set of points that form a geometry as a single matrix, where each point is a row; use \\code{unlist(x, recursive = FALSE)} to get sets of matrices.\n}\n\\description{\nCreate simple feature from a numeric vector, matrix or list\n}\n\\details{\n\"XYZ\" refers to coordinates where the third dimension represents altitude, \"XYM\" refers to three-dimensional coordinates where the third dimension refers to something else (\"M\" for measure); checking of the sanity of \\code{x} may be only partial.\n\nWhen \\code{flatten=TRUE}, this method may merge points into a multipoint structure, and may not preserve order, and hence cannot be reverted. When given fish, it returns fish soup.\n}\n\\examples{\n(p1 = st_point(c(1,2)))\nclass(p1)\nst_bbox(p1)\n(p2 = st_point(c(1,2,3)))\nclass(p2)\n(p3 = st_point(c(1,2,3), \"XYM\"))\npts = matrix(1:10, , 2)\n(mp1 = st_multipoint(pts))\npts = matrix(1:15, , 3)\n(mp2 = st_multipoint(pts))\n(mp3 = st_multipoint(pts, \"XYM\"))\npts = matrix(1:20, , 4)\n(mp4 = st_multipoint(pts))\npts = matrix(1:10, , 2)\n(ls1 = st_linestring(pts))\npts = matrix(1:15, , 3)\n(ls2 = st_linestring(pts))\n(ls3 = st_linestring(pts, \"XYM\"))\npts = matrix(1:20, , 4)\n(ls4 = st_linestring(pts))\nouter = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\nhole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\nhole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\npts = list(outer, hole1, hole2)\n(ml1 = st_multilinestring(pts))\npts3 = lapply(pts, function(x) cbind(x, 0))\n(ml2 = st_multilinestring(pts3))\n(ml3 = st_multilinestring(pts3, \"XYM\"))\npts4 = lapply(pts3, function(x) cbind(x, 0))\n(ml4 = st_multilinestring(pts4))\nouter = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\nhole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\nhole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\npts = list(outer, hole1, hole2)\n(pl1 = st_polygon(pts))\npts3 = lapply(pts, function(x) cbind(x, 0))\n(pl2 = st_polygon(pts3))\n(pl3 = st_polygon(pts3, \"XYM\"))\npts4 = lapply(pts3, function(x) cbind(x, 0))\n(pl4 = st_polygon(pts4))\npol1 = list(outer, hole1, hole2)\npol2 = list(outer + 12, hole1 + 12)\npol3 = list(outer + 24)\nmp = list(pol1,pol2,pol3)\n(mp1 = st_multipolygon(mp))\npts3 = lapply(mp, function(x) lapply(x, function(y) cbind(y, 0)))\n(mp2 = st_multipolygon(pts3))\n(mp3 = st_multipolygon(pts3, \"XYM\"))\npts4 = lapply(mp2, function(x) lapply(x, function(y) cbind(y, 0)))\n(mp4 = st_multipolygon(pts4))\n(gc = st_geometrycollection(list(p1, ls1, pl1, mp1)))\nst_geometrycollection() # empty geometry\nc(st_point(1:2), st_point(5:6))\nc(st_point(1:2), st_multipoint(matrix(5:8,2)))\nc(st_multipoint(matrix(1:4,2)), st_multipoint(matrix(5:8,2)))\nc(st_linestring(matrix(1:6,3)), st_linestring(matrix(11:16,3)))\nc(st_multilinestring(list(matrix(1:6,3))), st_multilinestring(list(matrix(11:16,3))))\npl = list(rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0)))\nc(st_polygon(pl), st_polygon(pl))\nc(st_polygon(pl), st_multipolygon(list(pl)))\nc(st_linestring(matrix(1:6,3)), st_point(1:2))\nc(st_geometrycollection(list(st_point(1:2), st_linestring(matrix(1:6,3)))),\n  st_geometrycollection(list(st_multilinestring(list(matrix(11:16,3))))))\nc(st_geometrycollection(list(st_point(1:2), st_linestring(matrix(1:6,3)))),\n  st_multilinestring(list(matrix(11:16,3))), st_point(5:6),\n  st_geometrycollection(list(st_point(10:11))))\n}\n"
  },
  {
    "path": "man/st_agr.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/agr.R\n\\name{st_agr}\n\\alias{st_agr}\n\\alias{NA_agr_}\n\\alias{st_agr<-}\n\\alias{st_set_agr}\n\\title{get or set relation_to_geometry attribute of an \\code{sf} object}\n\\usage{\nNA_agr_\n\nst_agr(x, ...)\n\nst_agr(x) <- value\n\nst_set_agr(x, value)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf}}\n\n\\item{...}{ignored}\n\n\\item{value}{character, or factor with appropriate levels; if named, names should correspond to the non-geometry list-column columns of \\code{x}}\n}\n\\description{\nget or set relation_to_geometry attribute of an \\code{sf} object\n}\n\\details{\n\\code{NA_agr_} is the \\code{agr} object with a missing value.\n}\n"
  },
  {
    "path": "man/st_as_binary.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/wkb.R\n\\name{st_as_binary}\n\\alias{st_as_binary}\n\\alias{st_as_binary.sfc}\n\\alias{st_as_binary.sfg}\n\\title{Convert sfc object to an WKB object}\n\\usage{\nst_as_binary(x, ...)\n\n\\method{st_as_binary}{sfc}(\n  x,\n  ...,\n  EWKB = FALSE,\n  endian = .Platform$endian,\n  pureR = FALSE,\n  precision = attr(x, \"precision\"),\n  hex = FALSE\n)\n\n\\method{st_as_binary}{sfg}(\n  x,\n  ...,\n  endian = .Platform$endian,\n  EWKB = FALSE,\n  pureR = FALSE,\n  hex = FALSE,\n  srid = 0\n)\n}\n\\arguments{\n\\item{x}{object to convert}\n\n\\item{...}{ignored}\n\n\\item{EWKB}{logical; use EWKB (PostGIS), or (default) ISO-WKB?}\n\n\\item{endian}{character; either \"big\" or \"little\"; default: use that of platform}\n\n\\item{pureR}{logical; use pure R solution, or C++?}\n\n\\item{precision}{numeric; if zero, do not modify; to reduce precision: negative values convert to float (4-byte real); positive values convert to round(x*precision)/precision. See details.}\n\n\\item{hex}{logical; return as (unclassed) hexadecimal encoded character vector?}\n\n\\item{srid}{integer; override srid (can be used when the srid is unavailable locally).}\n}\n\\description{\nConvert sfc object to an WKB object\n}\n\\details{\n\\code{st_as_binary} is called on sfc objects on their way to the GDAL or GEOS libraries, and hence does rounding (if requested) on the fly before e.g. computing spatial predicates like \\link{st_intersects}. The examples show a round-trip of an \\code{sfc} to and from binary.\n\nFor the precision model used, see also \\url{https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/PrecisionModel.html}. There, it is written that: ``... to specify 3 decimal places of precision, use a scale factor of 1000. To specify -3 decimal places of precision (i.e. rounding to the nearest 1000), use a scale factor of 0.001.''. Note that ALL coordinates, so also Z or M values (if present) are affected.\n}\n\\examples{\n# examples of setting precision:\nst_point(c(1/3, 1/6)) |> st_sfc(precision = 1000) |> st_as_binary() |> st_as_sfc()\nst_point(c(1/3, 1/6)) |> st_sfc(precision =  100) |> st_as_binary() |> st_as_sfc()\nst_point(1e6 * c(1/3, 1/6)) |> st_sfc(precision = 0.01) |> st_as_binary() |> st_as_sfc()\nst_point(1e6 * c(1/3, 1/6)) |> st_sfc(precision = 0.001) |> st_as_binary() |> st_as_sfc()\n}\n"
  },
  {
    "path": "man/st_as_grob.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/grid.R\n\\name{st_as_grob}\n\\alias{st_as_grob}\n\\title{Convert sf* object to a grob}\n\\usage{\nst_as_grob(x, ...)\n}\n\\arguments{\n\\item{x}{object to be converted into an object class \\code{grob}}\n\n\\item{...}{passed on to the xxxGrob function, e.g. \\code{gp = gpar(col = 'red')}}\n}\n\\description{\nConvert sf* object to an grid graphics object (grob)\n}\n"
  },
  {
    "path": "man/st_as_sf.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sf.R, R/sp.R, R/maps.R, R/spatstat.R, R/s2.R\n\\name{st_as_sf}\n\\alias{st_as_sf}\n\\alias{st_as_sf.data.frame}\n\\alias{st_as_sf.sf}\n\\alias{st_as_sf.sfc}\n\\alias{st_as_sf.Spatial}\n\\alias{st_as_sf.map}\n\\alias{st_as_sf.ppp}\n\\alias{st_as_sf.psp}\n\\alias{st_as_sf.lpp}\n\\alias{st_as_sf.s2_geography}\n\\title{Convert foreign object to an sf object}\n\\usage{\nst_as_sf(x, ...)\n\n\\method{st_as_sf}{data.frame}(\n  x,\n  ...,\n  agr = NA_agr_,\n  coords,\n  wkt,\n  dim = \"XYZ\",\n  remove = TRUE,\n  na.fail = TRUE,\n  sf_column_name = NULL\n)\n\n\\method{st_as_sf}{sf}(x, ...)\n\n\\method{st_as_sf}{sfc}(x, ...)\n\n\\method{st_as_sf}{Spatial}(x, ...)\n\n\\method{st_as_sf}{map}(x, ..., fill = TRUE, group = TRUE)\n\n\\method{st_as_sf}{ppp}(x, ...)\n\n\\method{st_as_sf}{psp}(x, ...)\n\n\\method{st_as_sf}{lpp}(x, ...)\n\n\\method{st_as_sf}{s2_geography}(x, ..., crs = st_crs(4326))\n}\n\\arguments{\n\\item{x}{object to be converted into an object class \\code{sf}}\n\n\\item{...}{passed on to \\link{st_sf}, might included named arguments \\code{crs} or \\code{precision}}\n\n\\item{agr}{character vector; see details section of \\link{st_sf}}\n\n\\item{coords}{in case of point data: names or numbers of the numeric columns holding coordinates}\n\n\\item{wkt}{name or number of the character column that holds WKT encoded geometries}\n\n\\item{dim}{specify what 3- or 4-dimensional points reflect: passed on to \\link{st_point} (only when argument coords is given)}\n\n\\item{remove}{logical; when coords or wkt is given, remove these columns from data.frame?}\n\n\\item{na.fail}{logical; if \\code{TRUE}, raise an error if coordinates contain missing values}\n\n\\item{sf_column_name}{character; name of the active list-column with simple feature geometries; in case\nthere is more than one and \\code{sf_column_name} is \\code{NULL}, the first one is taken.}\n\n\\item{fill}{logical; the value for \\code{fill} that was used in the call to \\link[maps]{map}.}\n\n\\item{group}{logical; if \\code{TRUE}, group id labels from \\link[maps]{map} by their prefix before \\code{:}}\n\n\\item{crs}{coordinate reference system to be assigned; object of class \\code{crs}}\n}\n\\description{\nConvert foreign object to an sf object\n}\n\\details{\nsetting argument \\code{wkt} annihilates the use of argument \\code{coords}. If \\code{x} contains a column called \"geometry\", \\code{coords} will result in overwriting of this column by the \\link{sfc} geometry list-column.  Setting \\code{wkt} will replace this column with the geometry list-column, unless \\code{remove} is \\code{FALSE}.\n\nIf \\code{coords} has length 4, and \\code{dim} is not \\code{XYZM}, the four columns are taken as the xmin, ymin, xmax, ymax corner coordinates of a rectangle, and polygons are returned.\n}\n\\examples{\npt1 = st_point(c(0,1))\npt2 = st_point(c(1,1))\nst_sfc(pt1, pt2)\nd = data.frame(a = 1:2)\nd$geom = st_sfc(pt1, pt2)\ndf = st_as_sf(d)\nd$geom = c(\"POINT(0 0)\", \"POINT(0 1)\")\ndf = st_as_sf(d, wkt = \"geom\")\nd$geom2 = st_sfc(pt1, pt2)\nst_as_sf(d) # should warn\nif (require(sp, quietly = TRUE)) {\n data(meuse, package = \"sp\")\n meuse_sf = st_as_sf(meuse, coords = c(\"x\", \"y\"), crs = 28992, agr = \"constant\")\n meuse_sf[1:3,]\n summary(meuse_sf)\n}\nif (require(sp, quietly = TRUE)) {\nx = rbind(c(-1,-1), c(1,-1), c(1,1), c(-1,1), c(-1,-1))\nx1 = 0.1 * x + 0.1\nx2 = 0.1 * x + 0.4\nx3 = 0.1 * x + 0.7\ny = x + 3\ny1 = x1 + 3\ny3 = x3 + 3\nm = matrix(c(3, 0), 5, 2, byrow = TRUE)\nz = x + m\nz1 = x1 + m\nz2 = x2 + m\nz3 = x3 + m\np1 = Polygons(list( Polygon(x[5:1,]), Polygon(x2), Polygon(x3),\n   Polygon(y[5:1,]), Polygon(y1), Polygon(x1), Polygon(y3)), \"ID1\")\np2 = Polygons(list( Polygon(z[5:1,]), Polygon(z2), Polygon(z3), Polygon(z1)),\n  \"ID2\")\nr = SpatialPolygons(list(p1,p2))\na = suppressWarnings(st_as_sf(r))\nsummary(a)\ndemo(meuse, ask = FALSE, echo = FALSE)\nsummary(st_as_sf(meuse))\nsummary(st_as_sf(meuse.grid))\nsummary(st_as_sf(meuse.area))\nsummary(st_as_sf(meuse.riv))\nsummary(st_as_sf(as(meuse.riv, \"SpatialLines\")))\npol.grd = as(meuse.grid, \"SpatialPolygonsDataFrame\")\n# summary(st_as_sf(pol.grd))\n# summary(st_as_sf(as(pol.grd, \"SpatialLinesDataFrame\")))\n}\nif (require(spatstat.geom)) {\n  g = st_as_sf(gorillas)\n  # select only the points:\n  g[st_is(g, \"POINT\"),]\n}\nif (require(spatstat.linnet)) {\n data(chicago)\n plot(st_as_sf(chicago)[\"label\"])\n plot(st_as_sf(chicago)[-1,\"label\"])\n}\n}\n"
  },
  {
    "path": "man/st_as_sfc.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/db.R, R/sfc.R, R/wkb.R, R/wkt.R, R/sp.R,\n%   R/maps.R, R/s2.R\n\\name{st_as_sfc}\n\\alias{st_as_sfc}\n\\alias{st_as_sfc.pq_geometry}\n\\alias{st_as_sfc.list}\n\\alias{st_as_sfc.blob}\n\\alias{st_as_sfc.bbox}\n\\alias{st_as_sfc.WKB}\n\\alias{st_as_sfc.raw}\n\\alias{st_as_sfc.character}\n\\alias{st_as_sfc.factor}\n\\alias{st_as_sfc.SpatialPoints}\n\\alias{st_as_sfc.SpatialPixels}\n\\alias{st_as_sfc.SpatialMultiPoints}\n\\alias{st_as_sfc.SpatialLines}\n\\alias{st_as_sfc.SpatialPolygons}\n\\alias{st_as_sfc.map}\n\\alias{st_as_sfc.s2_geography}\n\\title{Convert foreign geometry object to an sfc object}\n\\usage{\n\\method{st_as_sfc}{pq_geometry}(\n  x,\n  ...,\n  EWKB = TRUE,\n  spatialite = FALSE,\n  pureR = FALSE,\n  crs = NA_crs_\n)\n\n\\method{st_as_sfc}{list}(x, ..., crs = NA_crs_)\n\n\\method{st_as_sfc}{blob}(x, ...)\n\n\\method{st_as_sfc}{bbox}(x, ...)\n\n\\method{st_as_sfc}{WKB}(\n  x,\n  ...,\n  EWKB = FALSE,\n  spatialite = FALSE,\n  pureR = FALSE,\n  crs = NA_crs_\n)\n\n\\method{st_as_sfc}{raw}(x, ...)\n\n\\method{st_as_sfc}{character}(x, crs = NA_integer_, ..., GeoJSON = FALSE)\n\n\\method{st_as_sfc}{factor}(x, ...)\n\nst_as_sfc(x, ...)\n\n\\method{st_as_sfc}{SpatialPoints}(x, ..., precision = 0)\n\n\\method{st_as_sfc}{SpatialPixels}(x, ..., precision = 0)\n\n\\method{st_as_sfc}{SpatialMultiPoints}(x, ..., precision = 0)\n\n\\method{st_as_sfc}{SpatialLines}(x, ..., precision = 0, forceMulti = FALSE)\n\n\\method{st_as_sfc}{SpatialPolygons}(x, ..., precision = 0, forceMulti = FALSE)\n\n\\method{st_as_sfc}{map}(x, ...)\n\n\\method{st_as_sfc}{s2_geography}(\n  x,\n  ...,\n  crs = st_crs(4326),\n  endian = match(.Platform$endian, c(\"big\", \"little\")) - 1L\n)\n}\n\\arguments{\n\\item{x}{object to convert}\n\n\\item{...}{further arguments}\n\n\\item{EWKB}{logical; if \\code{TRUE}, parse as EWKB (extended WKB; PostGIS: ST_AsEWKB), otherwise as ISO WKB (PostGIS: ST_AsBinary)}\n\n\\item{spatialite}{logical; if \\code{TRUE}, WKB is assumed to be in the spatialite dialect, see \\url{https://www.gaia-gis.it/gaia-sins/BLOB-Geometry.html}; this is only supported in native endian-ness (i.e., files written on system with the same endian-ness as that on which it is being read).}\n\n\\item{pureR}{logical; if \\code{TRUE}, use only R code, if \\code{FALSE}, use compiled (C++) code; use \\code{TRUE} when the endian-ness of the binary differs from the host machine (\\code{.Platform$endian}).}\n\n\\item{crs}{coordinate reference system to be assigned; object of class \\code{crs}}\n\n\\item{GeoJSON}{logical; if \\code{TRUE}, try to read geometries from GeoJSON text strings\ngeometry, see \\code{\\link[=st_crs]{st_crs()}}}\n\n\\item{precision}{precision value; see \\link{st_as_binary}}\n\n\\item{forceMulti}{logical; if \\code{TRUE}, force coercion into \\code{MULTIPOLYGON} or \\code{MULTILINE} objects, else autodetect}\n\n\\item{endian}{integer; 0 or 1: defaults to the endian of the native machine}\n}\n\\description{\nConvert foreign geometry object to an sfc object\n}\n\\details{\nWhen converting from WKB, the object \\code{x} is either a character vector such as typically obtained from PostGIS (either with leading \"0x\" or without), or a list with raw vectors representing the features in binary (raw) form.\n\nIf \\code{x} is a character vector, it should be a vector containing\n\\href{https://www.ogc.org/standards/wkt-crs/}{well-known-text}, or\nPostgis EWKT or GeoJSON representations of a single geometry for each vector element.\n\nIf \\code{x} is a \\code{factor}, it is converted to \\code{character}.\n}\n\\examples{\nwkb = structure(list(\"01010000204071000000000000801A064100000000AC5C1441\"), class = \"WKB\")\nst_as_sfc(wkb, EWKB = TRUE)\nwkb = structure(list(\"0x01010000204071000000000000801A064100000000AC5C1441\"), class = \"WKB\")\nst_as_sfc(wkb, EWKB = TRUE)\nst_as_sfc(st_as_binary(st_sfc(st_point(0:1)))[[1]], crs = 4326)\nst_as_sfc(\"SRID=3978;LINESTRING(1663106 -105415,1664320 -104617)\")\n}\n"
  },
  {
    "path": "man/st_as_text.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/crs.R, R/wkt.R\n\\name{st_as_text}\n\\alias{st_as_text}\n\\alias{st_as_text.crs}\n\\alias{st_as_text.sfg}\n\\alias{st_as_text.sfc}\n\\title{Return Well-known Text representation of simple feature geometry or coordinate reference system}\n\\usage{\n\\method{st_as_text}{crs}(x, ..., projjson = FALSE, pretty = FALSE)\n\nst_as_text(x, ...)\n\n\\method{st_as_text}{sfg}(x, ...)\n\n\\method{st_as_text}{sfc}(x, ..., EWKT = FALSE)\n}\n\\arguments{\n\\item{x}{object of class \\code{sfg}, \\code{sfc} or \\code{crs}}\n\n\\item{...}{modifiers; in particular \\code{digits} can be passed to control the number of digits used}\n\n\\item{projjson}{logical; if TRUE, return projjson form (requires GDAL 3.1 and PROJ 6.2), else return well-known-text form}\n\n\\item{pretty}{logical; if TRUE, print human-readable well-known-text representation of a coordinate reference system}\n\n\\item{EWKT}{logical; if TRUE, print SRID=xxx; before the WKT string if \\code{epsg} is available}\n}\n\\description{\nReturn Well-known Text representation of simple feature geometry or coordinate reference system\n}\n\\details{\nThe returned WKT representation of simple feature geometry conforms to the\n\\href{https://en.wikipedia.org/wiki/Simple_Features}{simple features access} specification and extensions\n(known as EWKT, supported by PostGIS and other simple features implementations for addition of\na SRID to a WKT string).\n}\n\\note{\nTo improve conversion performance, the lwgeom package can be used (it must be installed\nbeforehand) and set the \\code{Sys.setenv(\"LWGEOM_WKT\" = \"true\")} environment variable. This\nwill also result in faster printing of complex geometries. Note that the representation as WKT is\ndifferent from the sf package and may cause reproducibility problems. An alternative solution is\nto use the \\code{\\link[lwgeom:st_astext]{lwgeom::st_astext()}} or \\code{\\link[wk:as_wkt]{wk::as_wkt()}} functions.\n}\n\\examples{\nst_as_text(st_point(1:2))\nst_as_text(st_sfc(st_point(c(-90,40)), crs = 4326), EWKT = TRUE)\n}\n"
  },
  {
    "path": "man/st_bbox.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/bbox.R\n\\name{st_bbox}\n\\alias{st_bbox}\n\\alias{is.na.bbox}\n\\alias{st_bbox.POINT}\n\\alias{st_bbox.MULTIPOINT}\n\\alias{st_bbox.LINESTRING}\n\\alias{st_bbox.POLYGON}\n\\alias{st_bbox.MULTILINESTRING}\n\\alias{st_bbox.MULTIPOLYGON}\n\\alias{st_bbox.GEOMETRYCOLLECTION}\n\\alias{st_bbox.MULTISURFACE}\n\\alias{st_bbox.MULTICURVE}\n\\alias{st_bbox.CURVEPOLYGON}\n\\alias{st_bbox.COMPOUNDCURVE}\n\\alias{st_bbox.POLYHEDRALSURFACE}\n\\alias{st_bbox.TIN}\n\\alias{st_bbox.TRIANGLE}\n\\alias{st_bbox.CIRCULARSTRING}\n\\alias{st_bbox.sfc}\n\\alias{st_bbox.sf}\n\\alias{st_bbox.Spatial}\n\\alias{st_bbox.Raster}\n\\alias{st_bbox.Extent}\n\\alias{st_bbox.numeric}\n\\alias{NA_bbox_}\n\\alias{FULL_bbox_}\n\\alias{format.bbox}\n\\title{Return bounding of a simple feature or simple feature set}\n\\usage{\n\\method{is.na}{bbox}(x)\n\nst_bbox(obj, ...)\n\n\\method{st_bbox}{POINT}(obj, ...)\n\n\\method{st_bbox}{MULTIPOINT}(obj, ...)\n\n\\method{st_bbox}{LINESTRING}(obj, ...)\n\n\\method{st_bbox}{POLYGON}(obj, ...)\n\n\\method{st_bbox}{MULTILINESTRING}(obj, ...)\n\n\\method{st_bbox}{MULTIPOLYGON}(obj, ...)\n\n\\method{st_bbox}{GEOMETRYCOLLECTION}(obj, ...)\n\n\\method{st_bbox}{MULTISURFACE}(obj, ...)\n\n\\method{st_bbox}{MULTICURVE}(obj, ...)\n\n\\method{st_bbox}{CURVEPOLYGON}(obj, ...)\n\n\\method{st_bbox}{COMPOUNDCURVE}(obj, ...)\n\n\\method{st_bbox}{POLYHEDRALSURFACE}(obj, ...)\n\n\\method{st_bbox}{TIN}(obj, ...)\n\n\\method{st_bbox}{TRIANGLE}(obj, ...)\n\n\\method{st_bbox}{CIRCULARSTRING}(obj, ...)\n\n\\method{st_bbox}{sfc}(obj, ...)\n\n\\method{st_bbox}{sf}(obj, ...)\n\n\\method{st_bbox}{Spatial}(obj, ...)\n\n\\method{st_bbox}{Raster}(obj, ...)\n\n\\method{st_bbox}{Extent}(obj, ..., crs = NA_crs_)\n\n\\method{st_bbox}{numeric}(obj, ..., crs = NA_crs_)\n\nNA_bbox_\n\nFULL_bbox_\n\n\\method{format}{bbox}(x, ...)\n}\n\\arguments{\n\\item{x}{object of class \\code{bbox}}\n\n\\item{obj}{object to compute the bounding box from}\n\n\\item{...}{for format.bbox, passed on to \\link[base]{format} to format individual numbers}\n\n\\item{crs}{object of class \\code{crs}, or argument to \\link{st_crs}, specifying the CRS of this bounding box.}\n}\n\\value{\na numeric vector of length four, with \\code{xmin}, \\code{ymin}, \\code{xmax}\nand \\code{ymax} values; if \\code{obj} is of class \\code{sf}, \\code{sfc}, \\code{Spatial} or \\code{Raster}, the object\nreturned has a class \\code{bbox}, an attribute \\code{crs} and a method to print the\nbbox and an \\code{st_crs} method to retrieve the coordinate reference system\ncorresponding to \\code{obj} (and hence the bounding box). \\link{st_as_sfc} has a\nmethods for \\code{bbox} objects to generate a polygon around the four bounding box points.\n}\n\\description{\nReturn bounding of a simple feature or simple feature set\n}\n\\details{\n\\code{NA_bbox_} represents the missing value for a \\code{bbox} object\n\n\\code{NA_bbox_} represents the missing value for a \\code{bbox} object\n}\n\\examples{\na = st_sf(a = 1:2, geom = st_sfc(st_point(0:1), st_point(1:2)), crs = 4326)\nst_bbox(a)\nst_as_sfc(st_bbox(a))\nst_bbox(c(xmin = 16.1, xmax = 16.6, ymax = 48.6, ymin = 47.9), crs = st_crs(4326))\n}\n"
  },
  {
    "path": "man/st_break_antimeridian.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/break_antimeridian.R\n\\name{st_break_antimeridian}\n\\alias{st_break_antimeridian}\n\\alias{st_break_antimeridian.sf}\n\\alias{st_break_antimeridian.sfc}\n\\title{Break antimeridian for plotting not centred on Greenwich}\n\\usage{\nst_break_antimeridian(x, lon_0 = 0, tol = 1e-04, ...)\n\n\\method{st_break_antimeridian}{sf}(x, lon_0 = 0, tol = 1e-04, ...)\n\n\\method{st_break_antimeridian}{sfc}(x, lon_0 = 0, tol = 1e-04, ...)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf} or \\code{sfc}}\n\n\\item{lon_0}{target central longitude (degrees)}\n\n\\item{tol}{half of break width (degrees, default 0.0001)}\n\n\\item{...}{ignored here}\n}\n\\description{\nLongitudes can be broken at the antimeridian of a target central longitude\nto permit plotting of (usually world) line or polygon objects centred\non the chosen central longitude. The method may only be used with\nnon-projected, geographical coordinates and linestring or polygon objects.\ns2 is turned off internally to permit the use of a rectangular bounding\nbox. If the input geometries go outside \\verb{[-180, 180]} degrees longitude,\nthe protruding geometries will also be split using the same \\code{tol=}\nvalues; in this case empty geometries will be dropped first.\n}\n\\examples{\n\\donttest{\nif (require(\"maps\", quietly=TRUE)) {\n opar = par(mfrow=c(3, 2))\n wld = st_as_sf(map(fill=FALSE, interior=FALSE, plot=FALSE), fill=FALSE)\n for (lon_0 in c(-170, -90, -10, 10, 90, 170)) {\n   br = st_break_antimeridian(wld, lon_0 = lon_0)\n   tr = st_transform(br, paste0(\"+proj=natearth +lon_0=\", lon_0))\n   plot(st_geometry(tr), main=lon_0)\n }\n par(opar)\n}\n}\n}\n"
  },
  {
    "path": "man/st_cast.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/cast_sfg.R, R/cast_sfc.R\n\\name{st_cast}\n\\alias{st_cast}\n\\alias{st_cast.MULTIPOLYGON}\n\\alias{st_cast.MULTILINESTRING}\n\\alias{st_cast.MULTIPOINT}\n\\alias{st_cast.POLYGON}\n\\alias{st_cast.LINESTRING}\n\\alias{st_cast.POINT}\n\\alias{st_cast.GEOMETRYCOLLECTION}\n\\alias{st_cast.CIRCULARSTRING}\n\\alias{st_cast.MULTISURFACE}\n\\alias{st_cast.COMPOUNDCURVE}\n\\alias{st_cast.MULTICURVE}\n\\alias{st_cast.CURVE}\n\\alias{st_cast.sfc}\n\\alias{st_cast.sf}\n\\alias{st_cast.sfc_CIRCULARSTRING}\n\\title{Cast geometry to another type: either simplify, or cast explicitly}\n\\usage{\n\\method{st_cast}{MULTIPOLYGON}(x, to, ...)\n\n\\method{st_cast}{MULTILINESTRING}(x, to, ...)\n\n\\method{st_cast}{MULTIPOINT}(x, to, ...)\n\n\\method{st_cast}{POLYGON}(x, to, ...)\n\n\\method{st_cast}{LINESTRING}(x, to, ...)\n\n\\method{st_cast}{POINT}(x, to, ...)\n\n\\method{st_cast}{GEOMETRYCOLLECTION}(x, to, ...)\n\n\\method{st_cast}{CIRCULARSTRING}(x, to, ...)\n\n\\method{st_cast}{MULTISURFACE}(x, to, ...)\n\n\\method{st_cast}{COMPOUNDCURVE}(x, to, ...)\n\n\\method{st_cast}{MULTICURVE}(x, to, ...)\n\n\\method{st_cast}{CURVE}(x, to, ...)\n\nst_cast(x, to, ...)\n\n\\method{st_cast}{sfc}(x, to, ..., ids = seq_along(x), group_or_split = TRUE)\n\n\\method{st_cast}{sf}(x, to, ..., warn = TRUE, do_split = TRUE)\n\n\\method{st_cast}{sfc_CIRCULARSTRING}(x, to, ...)\n}\n\\arguments{\n\\item{x}{object of class \\code{sfg}, \\code{sfc} or \\code{sf}}\n\n\\item{to}{character; target type, if missing, simplification is tried; when \\code{x} is of type \\code{sfg} (i.e., a single geometry) then \\code{to} needs to be specified.}\n\n\\item{...}{ignored}\n\n\\item{ids}{integer vector, denoting how geometries should be grouped (default: no grouping)}\n\n\\item{group_or_split}{logical; if TRUE, group or split geometries; if FALSE, carry out a 1-1 per-geometry conversion.}\n\n\\item{warn}{logical; if \\code{TRUE}, warn if attributes are assigned to sub-geometries}\n\n\\item{do_split}{logical; if \\code{TRUE}, allow splitting of geometries in sub-geometries}\n}\n\\value{\nobject of class \\code{to} if successful, or unmodified object if unsuccessful. If information gets lost while type casting, a warning is raised.\n\nIn case \\code{to} is missing, \\code{st_cast.sfc} will coerce combinations of \"POINT\" and \"MULTIPOINT\", \"LINESTRING\" and \"MULTILINESTRING\", \"POLYGON\" and \"MULTIPOLYGON\" into their \"MULTI...\" form, or in case all geometries are \"GEOMETRYCOLLECTION\" will return a list of all the contents of the \"GEOMETRYCOLLECTION\" objects, or else do nothing. In case \\code{to} is specified, if \\code{to} is \"GEOMETRY\", geometries are not converted, else, \\code{st_cast} will try to coerce all elements into \\code{to}; \\code{ids} may be specified to group e.g. \"POINT\" objects into a \"MULTIPOINT\", if not specified no grouping takes place. If e.g. a \"sfc_MULTIPOINT\" is cast to a \"sfc_POINT\", the objects are split, so no information gets lost, unless \\code{group_or_split} is \\code{FALSE}.\n}\n\\description{\nCast geometry to another type: either simplify, or cast explicitly\n}\n\\details{\nWhen converting a GEOMETRYCOLLECTION to COMPOUNDCURVE, MULTISURFACE or CURVEPOLYGON, the user is responsible for the validity of the resulting object: no checks are being carried out by the software.\n\nWhen converting mixed, GEOMETRY sets, it may help to first convert to the MULTI-type, see examples\n\nthe \\code{st_cast} method for \\code{sf} objects can only split geometries, e.g. cast \\code{MULTIPOINT} into multiple \\code{POINT} features.  In case of splitting, attributes are repeated and a warning is issued when non-constant attributes are assigned to sub-geometries. To merge feature geometries and attribute values, use \\link[sf:aggregate.sf]{aggregate} or \\link[sf:tidyverse]{summarise}.\n}\n\\examples{\n# example(st_read)\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\nmpl <- st_geometry(nc)[[4]]\n#st_cast(x) ## error 'argument \"to\" is missing, with no default'\ncast_all <- function(xg) {\n  lapply(c(\"MULTIPOLYGON\", \"MULTILINESTRING\", \"MULTIPOINT\", \"POLYGON\", \"LINESTRING\", \"POINT\"), \n      function(x) st_cast(xg, x))\n}\nst_sfc(cast_all(mpl))\n## no closing coordinates should remain for multipoint\nany(duplicated(unclass(st_cast(mpl, \"MULTIPOINT\"))))  ## should be FALSE\n## number of duplicated coordinates in the linestrings should equal the number of polygon rings \n## (... in this case, won't always be true)\nsum(duplicated(do.call(rbind, unclass(st_cast(mpl, \"MULTILINESTRING\"))))\n     ) == sum(unlist(lapply(mpl, length)))  ## should be TRUE\n\np1 <- structure(c(0, 1, 3, 2, 1, 0, 0, 0, 2, 4, 4, 0), .Dim = c(6L, 2L))\np2 <- structure(c(1, 1, 2, 1, 1, 2, 2, 1), .Dim = c(4L, 2L))\nst_polygon(list(p1, p2))\nmls <- st_cast(st_geometry(nc)[[4]], \"MULTILINESTRING\")\nst_sfc(cast_all(mls))\nmpt <- st_cast(st_geometry(nc)[[4]], \"MULTIPOINT\")\nst_sfc(cast_all(mpt))\npl <- st_cast(st_geometry(nc)[[4]], \"POLYGON\")\nst_sfc(cast_all(pl))\nls <- st_cast(st_geometry(nc)[[4]], \"LINESTRING\")\nst_sfc(cast_all(ls))\npt <- st_cast(st_geometry(nc)[[4]], \"POINT\")\n## st_sfc(cast_all(pt))  ## Error: cannot create MULTIPOLYGON from POINT \nst_sfc(lapply(c(\"POINT\", \"MULTIPOINT\"), function(x) st_cast(pt, x)))\ns = st_multipoint(rbind(c(1,0)))\nst_cast(s, \"POINT\")\n# https://github.com/r-spatial/sf/issues/1930:\npt1 <- st_point(c(0,1))\npt23 <- st_multipoint(matrix(c(1,2,3,4), ncol = 2, byrow = TRUE))\nd <- st_sf(geom = st_sfc(pt1, pt23))\nst_cast(d, \"POINT\") # will not convert the entire MULTIPOINT, and warns\nst_cast(d, \"MULTIPOINT\") |> st_cast(\"POINT\")\n}\n"
  },
  {
    "path": "man/st_cast_sfc_default.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/cast_sfc.R\n\\name{st_cast_sfc_default}\n\\alias{st_cast_sfc_default}\n\\title{Coerce geometry to MULTI* geometry}\n\\usage{\nst_cast_sfc_default(x)\n}\n\\arguments{\n\\item{x}{list of geometries or simple features}\n}\n\\description{\nMixes of POINTS and MULTIPOINTS, LINESTRING and MULTILINESTRING,\nPOLYGON and MULTIPOLYGON are returned as MULTIPOINTS, MULTILINESTRING and MULTIPOLYGONS respectively\n}\n\\details{\nGeometries that are already MULTI* are left unchanged.\nFeatures that can't be cast to a single  MULTI* geometry are return as a\nGEOMETRYCOLLECTION\n}\n"
  },
  {
    "path": "man/st_collection_extract.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/collection_extract.R\n\\name{st_collection_extract}\n\\alias{st_collection_extract}\n\\alias{st_collection_extract.sfg}\n\\alias{st_collection_extract.sfc}\n\\alias{st_collection_extract.sf}\n\\title{Given an object with geometries of type \\code{GEOMETRY} or \\code{GEOMETRYCOLLECTION},\nreturn an object consisting only of elements of the specified type.}\n\\usage{\nst_collection_extract(\n  x,\n  type = c(\"POLYGON\", \"POINT\", \"LINESTRING\"),\n  warn = FALSE\n)\n\n\\method{st_collection_extract}{sfg}(\n  x,\n  type = c(\"POLYGON\", \"POINT\", \"LINESTRING\"),\n  warn = FALSE\n)\n\n\\method{st_collection_extract}{sfc}(\n  x,\n  type = c(\"POLYGON\", \"POINT\", \"LINESTRING\"),\n  warn = FALSE\n)\n\n\\method{st_collection_extract}{sf}(\n  x,\n  type = c(\"POLYGON\", \"POINT\", \"LINESTRING\"),\n  warn = FALSE\n)\n}\n\\arguments{\n\\item{x}{an object of class \\code{sf}, \\code{sfc} or \\code{sfg} that has\nmixed geometry (\\code{GEOMETRY} or \\code{GEOMETRYCOLLECTION}).}\n\n\\item{type}{character; one of \"POLYGON\", \"POINT\", \"LINESTRING\"}\n\n\\item{warn}{logical; if \\code{TRUE}, warn if attributes are assigned to\nsub-geometries when casting (see \\code{\\link{st_cast}})}\n}\n\\value{\nAn object having the same class as \\code{x}, with geometries\nconsisting only of elements of the specified type.\nFor \\code{sfg} objects, an \\code{sfg} object is returned if there is only\none geometry of the specified type, otherwise the geometries are combined\ninto an \\code{sfc} object of the relevant type. If any subgeometries in the\ninput are MULTI, then all of the subgeometries in the output will be MULTI.\n}\n\\description{\nSimilar to ST_CollectionExtract in PostGIS. If there are no sub-geometries\nof the specified type, an empty geometry is returned.\n}\n\\examples{\npt <- st_point(c(1, 0))\nls <- st_linestring(matrix(c(4, 3, 0, 0), ncol = 2))\npoly1 <- st_polygon(list(matrix(c(5.5, 7, 7, 6, 5.5, 0, 0, -0.5, -0.5, 0), ncol = 2)))\npoly2 <- st_polygon(list(matrix(c(6.6, 8, 8, 7, 6.6, 1, 1, 1.5, 1.5, 1), ncol = 2)))\nmultipoly <- st_multipolygon(list(poly1, poly2))\n\ni <- st_geometrycollection(list(pt, ls, poly1, poly2))\nj <- st_geometrycollection(list(pt, ls, poly1, poly2, multipoly))\n\nst_collection_extract(i, \"POLYGON\")\nst_collection_extract(i, \"POINT\")\nst_collection_extract(i, \"LINESTRING\")\n\n## A GEOMETRYCOLLECTION\naa <- rbind(st_sf(a=1, geom = st_sfc(i)),\n\t\t\tst_sf(a=2, geom = st_sfc(j)))\n\n## With sf objects\nst_collection_extract(aa, \"POLYGON\")\nst_collection_extract(aa, \"LINESTRING\")\nst_collection_extract(aa, \"POINT\")\n\n## With sfc objects\nst_collection_extract(st_geometry(aa), \"POLYGON\")\nst_collection_extract(st_geometry(aa), \"LINESTRING\")\nst_collection_extract(st_geometry(aa), \"POINT\")\n\n## A GEOMETRY of single types\nbb <- rbind(\n\tst_sf(a = 1, geom = st_sfc(pt)),\n\tst_sf(a = 2, geom = st_sfc(ls)),\n\tst_sf(a = 3, geom = st_sfc(poly1)),\n\tst_sf(a = 4, geom = st_sfc(multipoly))\n)\n\nst_collection_extract(bb, \"POLYGON\")\n\n## A GEOMETRY of mixed single types and GEOMETRYCOLLECTIONS\ncc <- rbind(aa, bb)\n\nst_collection_extract(cc, \"POLYGON\")\n\n}\n"
  },
  {
    "path": "man/st_coordinates.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sfc.R\n\\name{st_coordinates}\n\\alias{st_coordinates}\n\\title{retrieve coordinates in matrix form}\n\\usage{\nst_coordinates(x, ...)\n}\n\\arguments{\n\\item{x}{object of class sf, sfc or sfg}\n\n\\item{...}{ignored}\n}\n\\value{\nmatrix with coordinates (X, Y, possibly Z and/or M) in rows, possibly followed by integer indicators \\code{L1},...,\\code{L3} that point out to which structure the coordinate belongs; for \\code{POINT} this is absent (each coordinate is a feature), for \\code{LINESTRING} \\code{L1} refers to the feature, for \\code{MULTILINESTRING} \\code{L1} refers to the part and \\code{L2} to the simple feature, for \\code{POLYGON} \\code{L1} refers to the main ring or holes and \\code{L2} to the simple feature, for \\code{MULTIPOLYGON} \\code{L1} refers to the main ring or holes, \\code{L2} to the ring id in the \\code{MULTIPOLYGON}, and \\code{L3} to the simple feature.\n\nFor \\code{POLYGONS}, \\code{L1} can be used to identify exterior rings and inner holes.\nThe exterior ring is when \\code{L1} is equal to 1. Interior rings are identified\nwhen \\code{L1} is greater than 1. \\code{L2} can be used to differentiate between the\nfeature. Whereas for \\code{MULTIPOLYGON}, \\code{L3} refers to the \\code{MULTIPOLYGON}\nfeature and \\code{L2} refers to the component \\code{POLYGON}.\n}\n\\description{\nretrieve coordinates in matrix form\n}\n"
  },
  {
    "path": "man/st_crop.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/crop.R\n\\name{st_crop}\n\\alias{st_crop}\n\\alias{st_crop.sfc}\n\\alias{st_crop.sf}\n\\title{crop an sf object to a specific rectangle}\n\\usage{\nst_crop(x, y, ...)\n\n\\method{st_crop}{sfc}(x, y, ..., xmin, ymin, xmax, ymax)\n\n\\method{st_crop}{sf}(x, y, ...)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf} or \\code{sfc}}\n\n\\item{y}{numeric vector with named elements \\code{xmin}, \\code{ymin}, \\code{xmax} and \\code{ymax}, or object of class \\code{bbox}, or object for which there is an \\link{st_bbox} method to convert it to a \\code{bbox} object}\n\n\\item{...}{ignored}\n\n\\item{xmin}{minimum x extent of cropping area}\n\n\\item{ymin}{minimum y extent of cropping area}\n\n\\item{xmax}{maximum x extent of cropping area}\n\n\\item{ymax}{maximum y extent of cropping area}\n}\n\\description{\ncrop an sf object to a specific rectangle\n}\n\\details{\nsetting arguments \\code{xmin}, \\code{ymin}, \\code{xmax} and \\code{ymax} implies that argument \\code{y} gets ignored.\n}\n\\examples{\nbox = c(xmin = 0, ymin = 0, xmax = 1, ymax = 1)\npol = st_sfc(st_buffer(st_point(c(.5, .5)), .6))\npol_sf = st_sf(a=1, geom=pol)\nplot(st_crop(pol, box))\nplot(st_crop(pol_sf, st_bbox(box)))\n# alternative:\nplot(st_crop(pol, xmin = 0, ymin = 0, xmax = 1, ymax = 1))\n}\n"
  },
  {
    "path": "man/st_crs.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/crs.R\n\\name{st_crs}\n\\alias{st_crs}\n\\alias{st_crs.sf}\n\\alias{st_crs.numeric}\n\\alias{st_crs.character}\n\\alias{st_crs.sfc}\n\\alias{st_crs.bbox}\n\\alias{st_crs.CRS}\n\\alias{st_crs.crs}\n\\alias{st_crs<-}\n\\alias{st_crs<-.sf}\n\\alias{st_crs<-.sfc}\n\\alias{st_set_crs}\n\\alias{NA_crs_}\n\\alias{is.na.crs}\n\\alias{$.crs}\n\\alias{format.crs}\n\\alias{st_axis_order}\n\\title{Retrieve coordinate reference system from object}\n\\usage{\nst_crs(x, ...)\n\n\\method{st_crs}{sf}(x, ...)\n\n\\method{st_crs}{numeric}(x, ...)\n\n\\method{st_crs}{character}(x, ...)\n\n\\method{st_crs}{sfc}(x, ..., parameters = FALSE)\n\n\\method{st_crs}{bbox}(x, ...)\n\n\\method{st_crs}{CRS}(x, ...)\n\n\\method{st_crs}{crs}(x, ...)\n\nst_crs(x) <- value\n\n\\method{st_crs}{sf}(x) <- value\n\n\\method{st_crs}{sfc}(x) <- value\n\nst_set_crs(x, value)\n\nNA_crs_\n\n\\method{is.na}{crs}(x)\n\n\\method{$}{crs}(x, name)\n\n\\method{format}{crs}(x, ...)\n\nst_axis_order(authority_compliant = logical(0))\n}\n\\arguments{\n\\item{x}{numeric, character, or object of class \\link{sf} or \\link{sfc}}\n\n\\item{...}{ignored}\n\n\\item{parameters}{logical; \\code{FALSE} by default; only for the \\code{st_crs.sfc()} method: if \\code{TRUE} return a classed list of coordinate reference system parameters, with named elements \\code{SemiMajor}, \\code{InvFlattening}, \\code{units_gdal}, \\code{IsVertical}, \\code{WktPretty}, \\code{Wkt}, \\code{Name}, \\code{proj4string}, \\code{epsg}, \\code{yx}, \\code{ProjJson}, \\code{WKT1_ESRI}, \\code{srid} (in authority:code form), \\code{axes} (a data.frame with columns \\code{name} and \\code{orientation}), \\code{gcs_crs} with the WKT of the base geographic coordinate system, \\code{ud_unit}. The list has class \\code{crs_parameters}.}\n\n\\item{value}{one of (i) character: a string accepted by GDAL, (ii) integer, a valid EPSG value (numeric), or (iii) an object of class \\code{crs}.}\n\n\\item{name}{element name}\n\n\\item{authority_compliant}{logical; specify whether axis order should be\nhandled compliant to the authority; if omitted, the current value is printed.}\n}\n\\value{\nIf \\code{x} is numeric, return \\code{crs} object for EPSG:\\code{x};\nif \\code{x} is character, return \\code{crs} object for \\code{x};\nif \\code{x} is of class \\code{sf} or \\code{sfc}, return its \\code{crs} object.\n\nObject of class \\code{crs}, which is a list with elements \\code{input} (length-1 character)\nand \\code{wkt} (length-1 character).\nElements may be \\code{NA} valued; if all elements are \\code{NA} the CRS is missing valued, and coordinates are\nassumed to relate to an arbitrary Cartesian coordinate system.\n\n\\code{st_axis_order} returns the (logical) current value if called without\nargument, or (invisibly) the previous value if it is being set.\n}\n\\description{\nRetrieve coordinate reference system from sf or sfc object\n\nSet or replace retrieve coordinate reference system from object\n}\n\\details{\nThe *crs functions create, get, set or replace the \\code{crs} attribute\nof a simple feature geometry list-column. This attribute is of class \\code{crs},\nand is a list consisting of \\code{input} (user input, e.g. \"EPSG:4326\" or \"WGS84\"\nor a proj4string), and \\code{wkt}, an automatically generated wkt2 representation of the crs.\nIf \\code{x} is identical to the wkt2 representation, and the CRS has a name, this name\nis used for the \\code{input} field.\n\nComparison of two objects of class \\code{crs} uses the GDAL function\n\\code{OGRSpatialReference::IsSame}.\n\nIn case a coordinate reference system is replaced, no transformation takes\nplace and a warning is raised to stress this.\n\n\\code{NA_crs_} is the \\code{crs} object with missing values for \\code{input} and \\code{wkt}.\n\nthe \\code{$} method for \\code{crs} objects retrieves named elements\nusing the GDAL interface; named elements include\n\\code{SemiMajor}, \\code{SemiMinor}, \\code{InvFlattening}, \\code{IsGeographic},\n\\code{units_gdal}, \\code{IsVertical}, \\code{WktPretty}, \\code{Wkt},\n\\code{Name}, \\code{proj4string}, \\code{epsg}, \\code{yx},\n\\code{ud_unit}, and \\code{axes} (this may be subject to changes in future GDAL versions).\n\nNote that not all valid CRS have a corresponding \\code{proj4string}.\n\n\\code{ud_unit} returns a valid \\link[units]{units} object or \\code{NULL} if units are missing.\n\nformat.crs returns NA if the crs is missing valued, or else\nthe name of a crs if it is different from \"unknown\", or\nelse the user input if it was set, or else its \"proj4string\" representation;\n\n\\code{st_axis_order} can be used to get and set the axis order: \\code{TRUE}\nindicates axes order according to the authority\n(e.g. EPSG:4326 defining coordinates to be latitude,longitude pairs), \\code{FALSE}\nindicates the usual GIS (display) order (longitude,latitude). This can be useful\nwhen data are read, or have to be written, with coordinates in authority compliant order.\nThe return value is the current state of this (\\code{FALSE}, by default).\n}\n\\examples{\nsfc = st_sfc(st_point(c(0,0)), st_point(c(1,1)))\nsf = st_sf(a = 1:2, geom = sfc)\nst_crs(sf) = 4326\nst_geometry(sf)\nsfc = st_sfc(st_point(c(0,0)), st_point(c(1,1)))\nst_crs(sfc) = 4326\nsfc\nsfc = st_sfc(st_point(c(0,0)), st_point(c(1,1)))\nsfc |> st_set_crs(4326) |> st_transform(3857)\nst_crs(\"EPSG:3857\")$input\nst_crs(3857)$proj4string\npt = st_sfc(st_point(c(0, 60)), crs = 4326)\n# st_axis_order() only has effect in GDAL >= 2.5.0:\nst_axis_order() # query default: FALSE means interpret pt as (longitude latitude)\nst_transform(pt, 3857)[[1]]\nold_value = FALSE\nif (compareVersion(sf_extSoftVersion()[\"GDAL\"], \"2.5.0\") >= 0)\n   (old_value = st_axis_order(TRUE))\n# now interpret pt as (latitude longitude), as EPSG:4326 prescribes:\nst_axis_order() # query current value\nst_transform(pt, 3857)[[1]]\nst_axis_order(old_value) # set back to old value\n}\n"
  },
  {
    "path": "man/st_drivers.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/read.R\n\\name{st_drivers}\n\\alias{st_drivers}\n\\title{Get GDAL drivers}\n\\usage{\nst_drivers(what = \"vector\", regex)\n}\n\\arguments{\n\\item{what}{character: \\code{\"vector\"} or \\code{\"raster\"}, anything else will return all\ndrivers.}\n\n\\item{regex}{character; regular expression to filter the \\code{name} and \\code{long_name}\nfields on}\n}\n\\value{\nA \\code{data.frame} with driver metadata.\n}\n\\description{\nGet a list of the available GDAL drivers\n}\n\\details{\nThe drivers available will depend on the installation of GDAL/OGR,\nand can vary; the \\code{st_drivers()} function shows all the drivers that are\nreadable, and which may be written. The field \\code{vsi} refers to the driver's\ncapability to read/create datasets through the VSI*L API. \\href{https://gdal.org/en/latest/drivers/vector/index.html}{See GDAL website for additional details on driver support}\n}\n\\examples{\n# The following driver lists depend on the GDAL setup and platform used:\nst_drivers()\nst_drivers(\"raster\", \"GeoT\")\n}\n"
  },
  {
    "path": "man/st_geometry.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sfc.R, R/sf.R\n\\name{st_geometry}\n\\alias{st_geometry}\n\\alias{st_geometry.sfc}\n\\alias{st_geometry.sf}\n\\alias{st_geometry.sfg}\n\\alias{st_geometry<-}\n\\alias{st_set_geometry}\n\\alias{st_drop_geometry}\n\\alias{st_drop_geometry.sf}\n\\alias{st_drop_geometry.default}\n\\title{Get, set, replace or rename geometry from an sf object}\n\\usage{\n\\method{st_geometry}{sfc}(obj, ...)\n\nst_geometry(obj, ...)\n\n\\method{st_geometry}{sf}(obj, ...)\n\n\\method{st_geometry}{sfc}(obj, ...)\n\n\\method{st_geometry}{sfg}(obj, ...)\n\nst_geometry(x) <- value\n\nst_set_geometry(x, value)\n\nst_drop_geometry(x, ...)\n\n\\method{st_drop_geometry}{sf}(x, ...)\n\n\\method{st_drop_geometry}{default}(x, ...)\n}\n\\arguments{\n\\item{obj}{object of class \\code{sf} or \\code{sfc}}\n\n\\item{...}{ignored}\n\n\\item{x}{object of class \\code{data.frame} or \\code{sf}}\n\n\\item{value}{object of class \\code{sfc}, or \\code{character} to set, replace, or rename the geometry of \\code{x}}\n}\n\\value{\nst_geometry returns an object of class \\link{sfc}, a list-column with geometries\n\n\\code{st_geometry} returns an object of class \\link{sfc}. Assigning geometry to a \\code{data.frame} creates an \\link{sf} object, assigning it to an \\link{sf} object replaces the geometry list-column.\n}\n\\description{\nGet, set, replace or rename geometry from an sf object\n}\n\\details{\nwhen applied to a \\code{data.frame} and when \\code{value} is an object of class \\code{sfc}, \\code{st_set_geometry} and \\code{st_geometry<-} will first check for the existence of an attribute \\code{sf_column} and overwrite that, or else look for list-columns of class \\code{sfc} and overwrite the first of that, or else write the geometry list-column to a column named \\code{geometry}.  In case \\code{value} is character and \\code{x} is of class \\code{sf}, the \"active\" geometry column is set to \\code{x[[value]]}.\n\nthe replacement function applied to \\code{sf} objects will overwrite the geometry list-column, if \\code{value} is \\code{NULL}, it will remove it and coerce \\code{x} to a \\code{data.frame}.\n\nif \\code{x} is of class \\code{sf}, \\code{st_drop_geometry} drops the geometry of its argument, and reclasses it accordingly; otherwise it returns \\code{x} unmodified.\n}\n\\examples{\ndf = data.frame(a = 1:2)\nsfc = st_sfc(st_point(c(3,4)), st_point(c(10,11)))\nst_geometry(sfc)\nst_geometry(df) <- sfc\nclass(df)\nst_geometry(df)\nst_geometry(df) <- sfc # replaces\nst_geometry(df) <- NULL # remove geometry, coerce to data.frame\nsf <- st_set_geometry(df, sfc) # set geometry, return sf\nst_set_geometry(sf, NULL) # remove geometry, coerce to data.frame\n}\n"
  },
  {
    "path": "man/st_geometry_type.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sfc.R\n\\name{st_geometry_type}\n\\alias{st_geometry_type}\n\\title{Return geometry type of an object}\n\\usage{\nst_geometry_type(x, by_geometry = TRUE)\n}\n\\arguments{\n\\item{x}{object of class \\link{sf} or \\link{sfc}}\n\n\\item{by_geometry}{logical; if \\code{TRUE}, return geometry type of each geometry,\nelse return geometry type of the set}\n}\n\\value{\na factor with the geometry type of each simple feature geometry\nin \\code{x}, or that of the whole set\n}\n\\description{\nReturn geometry type of an object, as a factor\n}\n"
  },
  {
    "path": "man/st_graticule.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/graticule.R\n\\name{st_graticule}\n\\alias{st_graticule}\n\\title{Compute graticules and their parameters}\n\\usage{\nst_graticule(\n  x = c(-180, -90, 180, 90),\n  crs = st_crs(x),\n  datum = st_crs(\"OGC:CRS84\"),\n  ...,\n  lon = NULL,\n  lat = NULL,\n  ndiscr = 100,\n  margin = 0.001\n)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf}, \\code{sfc} or \\code{sfg} or numeric vector with bounding box given as (minx, miny, maxx, maxy).}\n\n\\item{crs}{object of class \\code{crs}, with the display coordinate reference system}\n\n\\item{datum}{either an object of class \\code{crs} with the coordinate reference system for the graticules, or \\code{NULL} in which case a grid in the coordinate system of \\code{x} is drawn, or \\code{NA}, in which case an empty \\code{sf} object is returned. If missing and \\code{x} has a crs with a datum, the geographic coordinate system (datum) of \\code{x} is taken.}\n\n\\item{...}{ignored}\n\n\\item{lon}{numeric; values in degrees East for the meridians, associated with \\code{datum}}\n\n\\item{lat}{numeric; values in degrees North for the parallels, associated with \\code{datum}}\n\n\\item{ndiscr}{integer; number of points to discretize a parallel or meridian}\n\n\\item{margin}{numeric; small number to trim a longlat bounding box that touches or\ncrosses +/-180 long or +/-90 latitude.}\n}\n\\value{\nan object of class \\code{sf} with additional attributes describing the type\n(E: meridian, N: parallel) degree value, label, start and end coordinates and angle;\nsee example.\n}\n\\description{\nCompute graticules and their parameters\n}\n\\section{Use of graticules}{\n\nIn cartographic visualization, the use of graticules is not advised, unless\nthe graphical output will be used for measurement or navigation, or the\ndirection of North is important for the interpretation of the content, or\nthe content is intended to display distortions and artifacts created by\nprojection. Unnecessary use of graticules only adds visual clutter but\nlittle relevant information. Use of coastlines, administrative boundaries\nor place names permits most viewers of the output to orient themselves\nbetter than a graticule.\n}\n\n\\examples{\nlibrary(sf)\nif (require(maps, quietly = TRUE)) {\n\nusa = st_as_sf(map('usa', plot = FALSE, fill = TRUE))\nlaea = st_crs(\"+proj=laea +lat_0=30 +lon_0=-95\") # Lambert equal area\nusa <- st_transform(usa, laea)\n\nbb = st_bbox(usa)\nbbox = st_linestring(rbind(c( bb[1],bb[2]),c( bb[3],bb[2]),\n   c( bb[3],bb[4]),c( bb[1],bb[4]),c( bb[1],bb[2])))\n\ng = st_graticule(usa)\nplot(usa, xlim = 1.2 * c(-2450853.4, 2186391.9), reset = FALSE)\nplot(g[1], add = TRUE, col = 'grey')\nplot(bbox, add = TRUE)\npoints(g$x_start, g$y_start, col = 'red')\npoints(g$x_end, g$y_end, col = 'blue')\n\ninvisible(lapply(seq_len(nrow(g)), function(i) {\nif (g$type[i] == \"N\" && g$x_start[i] - min(g$x_start) < 1000)\n\ttext(g$x_start[i], g$y_start[i], labels = parse(text = g$degree_label[i]), \n\t\tsrt = g$angle_start[i], pos = 2, cex = .7)\nif (g$type[i] == \"E\" && g$y_start[i] - min(g$y_start) < 1000)\n\ttext(g$x_start[i], g$y_start[i], labels = parse(text = g$degree_label[i]), \n\t\tsrt = g$angle_start[i] - 90, pos = 1, cex = .7)\nif (g$type[i] == \"N\" && g$x_end[i] - max(g$x_end) > -1000)\n\ttext(g$x_end[i], g$y_end[i], labels = parse(text = g$degree_label[i]), \n\t\tsrt = g$angle_end[i], pos = 4, cex = .7)\nif (g$type[i] == \"E\" && g$y_end[i] - max(g$y_end) > -1000)\n\ttext(g$x_end[i], g$y_end[i], labels = parse(text = g$degree_label[i]), \n\t\tsrt = g$angle_end[i] - 90, pos = 3, cex = .7)\n}))\nplot(usa, graticule = st_crs(4326), axes = TRUE, lon = seq(-60,-130,by=-10))\n}\n}\n"
  },
  {
    "path": "man/st_is.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/cast_sfc.R\n\\name{st_is}\n\\alias{st_is}\n\\title{test equality between the geometry type and a class or set of classes}\n\\usage{\nst_is(x, type)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf}, \\code{sfc} or \\code{sfg}}\n\n\\item{type}{character; class, or set of classes, to test against}\n}\n\\description{\ntest equality between the geometry type and a class or set of classes\n}\n\\examples{\nst_is(st_point(0:1), \"POINT\")\nsfc = st_sfc(st_point(0:1), st_linestring(matrix(1:6,,2)))\nst_is(sfc, \"POINT\")\nst_is(sfc, \"POLYGON\")\nst_is(sfc, \"LINESTRING\")\nst_is(st_sf(a = 1:2, sfc), \"LINESTRING\")\nst_is(sfc, c(\"POINT\", \"LINESTRING\"))\n}\n"
  },
  {
    "path": "man/st_is_full.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sfc.R\n\\name{st_is_full}\n\\alias{st_is_full}\n\\alias{st_is_full.sfg}\n\\alias{st_is_full.sfc}\n\\alias{st_is_full.sf}\n\\alias{st_is_full.bbox}\n\\title{predicate whether a geometry is equal to a POLYGON FULL}\n\\usage{\nst_is_full(x, ...)\n\n\\method{st_is_full}{sfg}(x, ..., is_longlat = NULL)\n\n\\method{st_is_full}{sfc}(x, ...)\n\n\\method{st_is_full}{sf}(x, ...)\n\n\\method{st_is_full}{bbox}(x, ...)\n}\n\\arguments{\n\\item{x}{object of class \\code{sfg}, \\code{sfc} or \\code{sf}}\n\n\\item{...}{ignored, except when it contains a \\code{crs} argument to inform unspecified \\code{is_longlat}}\n\n\\item{is_longlat}{logical; output of \\link{st_is_longlat} of the parent \\code{sfc} object}\n}\n\\value{\nlogical, indicating whether geometries are POLYGON FULL (a spherical\npolygon covering the entire sphere)\n}\n\\description{\npredicate whether a geometry is equal to a POLYGON FULL\n}\n"
  },
  {
    "path": "man/st_is_longlat.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/crs.R\n\\name{st_is_longlat}\n\\alias{st_is_longlat}\n\\title{Assert whether simple feature coordinates are longlat degrees}\n\\usage{\nst_is_longlat(x)\n}\n\\arguments{\n\\item{x}{object of class \\link{sf} or \\link{sfc}, or otherwise an object of a class that has an \\link{st_crs} method returning a \\code{crs} object}\n}\n\\value{\n\\code{TRUE} if \\code{x} has geographic coordinates, \\code{FALSE} if it has projected coordinates, or \\code{NA} if \\code{is.na(st_crs(x))}.\n}\n\\description{\nAssert whether simple feature coordinates are longlat degrees\n}\n"
  },
  {
    "path": "man/st_jitter.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/jitter.R\n\\name{st_jitter}\n\\alias{st_jitter}\n\\title{jitter geometries}\n\\usage{\nst_jitter(x, amount, factor = 0.002)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf} or \\code{sfc}}\n\n\\item{amount}{numeric; amount of jittering applied; if missing, the amount is set to factor * the bounding box diagonal; units of coordinates.}\n\n\\item{factor}{numeric; fractional amount of jittering to be applied}\n}\n\\description{\njitter geometries\n}\n\\details{\njitters coordinates with an amount such that \\code{runif(1, -amount, amount)} is added to the coordinates. x- and y-coordinates are jittered independently but all coordinates of a single geometry are jittered with the same amount, meaning that the geometry shape does not change. For longlat data, a latitude correction is made such that jittering in East and North directions are identical in distance in the center of the bounding box of \\code{x}.\n}\n\\examples{\nnc = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"))\npts = st_centroid(st_geometry(nc))\nplot(pts)\nplot(st_jitter(pts, .05), add = TRUE, col = 'red')\nplot(st_geometry(nc))\nplot(st_jitter(st_geometry(nc), factor = .01), add = TRUE, col = '#ff8888')\n}\n"
  },
  {
    "path": "man/st_join.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/join.R\n\\name{st_join}\n\\alias{st_join}\n\\alias{st_join.sf}\n\\alias{st_filter}\n\\alias{st_filter.sf}\n\\title{spatial join, spatial filter}\n\\usage{\nst_join(x, y, join, ...)\n\n\\method{st_join}{sf}(\n  x,\n  y,\n  join = st_intersects,\n  ...,\n  suffix = c(\".x\", \".y\"),\n  left = TRUE,\n  largest = FALSE\n)\n\nst_filter(x, y, ...)\n\n\\method{st_filter}{sf}(x, y, ..., .predicate = st_intersects)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf}}\n\n\\item{y}{object of class \\code{sf}}\n\n\\item{join}{geometry predicate function with the same profile as \\link{st_intersects}; see details}\n\n\\item{...}{for \\code{st_join}: arguments passed on to the \\code{join} function or to \\code{st_intersection} when \\code{largest} is \\code{TRUE}; for \\code{st_filter} arguments passed on to the \\code{.predicate} function, e.g. \\code{prepared}, or a pattern for \\link{st_relate}}\n\n\\item{suffix}{length 2 character vector; see \\link[base]{merge}}\n\n\\item{left}{logical; if \\code{TRUE} return the left join, otherwise an inner join; see details.\nsee also \\link[dplyr:mutate-joins]{left_join}}\n\n\\item{largest}{logical; if \\code{TRUE}, return \\code{x} features augmented with the fields of \\code{y} that have the largest overlap with each of the features of \\code{x}; see https://github.com/r-spatial/sf/issues/578}\n\n\\item{.predicate}{geometry predicate function with the same profile as \\link{st_intersects}; see details}\n}\n\\value{\nan object of class \\code{sf}, joined based on geometry\n}\n\\description{\nspatial join, spatial filter\n}\n\\details{\nalternative values for argument \\code{join} are:\n\\itemize{\n\\item \\link{st_contains_properly},\n\\item \\link{st_contains},\n\\item \\link{st_covered_by},\n\\item \\link{st_covers},\n\\item \\link{st_crosses},\n\\item \\link{st_disjoint},\n\\item \\link{st_equals_exact},\n\\item \\link{st_equals},\n\\item \\link{st_is_within_distance},\n\\item \\link{st_nearest_feature},\n\\item \\link{st_overlaps},\n\\item \\link{st_touches},\n\\item \\link{st_within},\n\\item \\link{st_relate} (which will require \\code{pattern} to be set),\n\\item or any user-defined function of the same profile as the above\n}\nA left join returns all records of the \\code{x} object with \\code{y} fields for non-matched records filled with \\code{NA} values; an inner join returns only records that spatially match.\n\nTo replicate the results of \\code{st_within(x, y)} you will need to use \\code{st_join(x, y, join = \"st_within\", left = FALSE)}.\n}\n\\examples{\na = st_sf(a = 1:3,\n geom = st_sfc(st_point(c(1,1)), st_point(c(2,2)), st_point(c(3,3))))\nb = st_sf(a = 11:14,\n geom = st_sfc(st_point(c(10,10)), st_point(c(2,2)), st_point(c(2,2)), st_point(c(3,3))))\nst_join(a, b)\nst_join(a, b, left = FALSE)\n# two ways to aggregate y's attribute values outcome over x's geometries:\nj = st_join(a, b)\naggregate(j, list(j$a.x), mean)\nif (require(dplyr, quietly = TRUE)) {\n st_join(a, b) |> group_by(a.x) |> summarise(mean(a.y))\n}\n# example of largest = TRUE:\nnc <- st_transform(st_read(system.file(\"shape/nc.shp\", package=\"sf\")), 2264)                \ngr = st_sf(\n    label = apply(expand.grid(1:10, LETTERS[10:1])[,2:1], 1, paste0, collapse = \" \"),\n    geom = st_make_grid(st_as_sfc(st_bbox(nc))))\ngr$col = sf.colors(10, categorical = TRUE, alpha = .3)\n# cut, to check, NA's work out:\ngr = gr[-(1:30),]\nnc_j <- st_join(nc, gr, largest = TRUE)\n# the two datasets:\nopar = par(mfrow = c(2,1), mar = rep(0,4))\nplot(st_geometry(nc_j))\nplot(st_geometry(gr), add = TRUE, col = gr$col)\ntext(st_coordinates(st_centroid(gr)), labels = gr$label)\n# the joined dataset:\nplot(st_geometry(nc_j), border = 'black', col = nc_j$col)\ntext(st_coordinates(st_centroid(nc_j)), labels = nc_j$label, cex = .8)\nplot(st_geometry(gr), border = 'green', add = TRUE)\npar(opar)\n# st_filter keeps the geometries in x where .predicate(x,y) returns any match in y for x\nst_filter(a, b)\n# for an anti-join, use the union of y\nst_filter(a, st_union(b), .predicate = st_disjoint)\n}\n"
  },
  {
    "path": "man/st_layers.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/read.R\n\\name{st_layers}\n\\alias{st_layers}\n\\title{Return properties of layers in a datasource}\n\\usage{\nst_layers(dsn, options = character(0), do_count = FALSE)\n}\n\\arguments{\n\\item{dsn}{data source name (interpretation varies by driver - for some drivers, \\code{dsn} is a file name, but may also be a\nfolder, or contain the name and access credentials of a database)}\n\n\\item{options}{character; driver dependent dataset open options, multiple options supported.}\n\n\\item{do_count}{logical; if TRUE, count the features by reading them, even if their count is not reported by the driver}\n}\n\\value{\nlist object of class \\code{sf_layers} with elements\n\\describe{\n\\item{name}{name of the layer}\n\\item{geomtype}{list with for each layer the geometry types}\n\\item{features}{number of features (if reported; see \\code{do_count})}\n\\item{fields}{number of fields}\n\\item{crs}{list with for each layer the \\code{crs} object}\n}\n}\n\\description{\nReturn properties of layers in a datasource\n}\n"
  },
  {
    "path": "man/st_line_project_point.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/geom-measures.R, R/geom-transformers.R\n\\name{st_line_project_point}\n\\alias{st_line_project_point}\n\\alias{st_line_project}\n\\alias{st_line_interpolate}\n\\title{Project point on linestring, interpolate along a linestring}\n\\usage{\nst_line_project(line, point, normalized = FALSE)\n\nst_line_interpolate(line, dist, normalized = FALSE)\n}\n\\arguments{\n\\item{line}{object of class \\code{sfc} with \\code{LINESTRING} geometry}\n\n\\item{point}{object of class \\code{sfc} with \\code{POINT} geometry}\n\n\\item{normalized}{logical; if \\code{TRUE}, use or return distance normalised to 0-1}\n\n\\item{dist}{numeric or units, vector with distance value(s), in units of the coordinates}\n}\n\\value{\n\\code{st_line_project} returns the distance(s) of point(s) along line(s), when projected on the line(s)\n\n\\code{st_line_interpolate} returns the point(s) at dist(s), when measured along (interpolated on) the line(s)\n}\n\\description{\nProject point on linestring, interpolate along a linestring\n}\n\\details{\narguments \\code{line}, \\code{point} and \\code{dist} are recycled to common length when needed\n}\n\\examples{\nst_line_project(st_as_sfc(\"LINESTRING (0 0, 10 10)\"), st_as_sfc(c(\"POINT (0 0)\", \"POINT (5 5)\")))\nst_line_project(st_as_sfc(\"LINESTRING (0 0, 10 10)\"), st_as_sfc(\"POINT (5 5)\"), TRUE)\nst_line_interpolate(st_as_sfc(\"LINESTRING (0 0, 1 1)\"), 1)\nst_line_interpolate(st_as_sfc(\"LINESTRING (0 0, 1 1)\"), 1, TRUE)\n# https://github.com/r-spatial/sf/issues/2542; use for geographic coordinates:\nl1 <- st_as_sfc(\"LINESTRING (10.1 50.1, 10.2 50.2)\", crs = 'OGC:CRS84')\ndists = units::set_units(seq(0, sqrt(2)/10, length.out = 5), degrees)\nst_line_interpolate(l1, dists)\n}\n"
  },
  {
    "path": "man/st_line_sample.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/geom-transformers.R\n\\name{st_line_sample}\n\\alias{st_line_sample}\n\\title{Sample points on a linear geometry}\n\\usage{\nst_line_sample(x, n, density, type = \"regular\", sample = NULL)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf}, \\code{sfc} or \\code{sfg}}\n\n\\item{n}{integer; number of points to choose per geometry; if missing, n will be computed as \\code{round(density * st_length(geom))}.}\n\n\\item{density}{numeric; density (points per distance unit) of the sampling, possibly a vector of length equal to the number of features (otherwise recycled); \\code{density} may be of class \\code{units}.}\n\n\\item{type}{character; indicate the sampling type, either \"regular\" or \"random\"}\n\n\\item{sample}{numeric; a vector of numbers between 0 and 1 indicating the points to sample - if defined sample overrules n, density and type.}\n}\n\\description{\nSample points on a linear geometry\n}\n\\examples{\nls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))),\n\tst_linestring(rbind(c(0,0),c(10,0))))\nst_line_sample(ls, density = 1)\nls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))),\n st_linestring(rbind(c(0,0),c(.1,0))), crs = 4326)\ntry(st_line_sample(ls, density = 1/1000)) # error\nst_line_sample(st_transform(ls, 3857), n = 5) # five points for each line\nst_line_sample(st_transform(ls, 3857), n = c(1, 3)) # one and three points\nst_line_sample(st_transform(ls, 3857), density = 1/1000) # one per km\nst_line_sample(st_transform(ls, 3857), density = c(1/1000, 1/10000)) # one per km, one per 10 km\nst_line_sample(st_transform(ls, 3857), density = units::set_units(1, 1/km)) # one per km\n# five equidistant points including start and end:\nst_line_sample(st_transform(ls, 3857), sample = c(0, 0.25, 0.5, 0.75, 1))\n}\n"
  },
  {
    "path": "man/st_m_range.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/m_range.R\n\\name{st_m_range}\n\\alias{st_m_range}\n\\alias{is.na.m_range}\n\\alias{st_m_range.POINT}\n\\alias{st_m_range.MULTIPOINT}\n\\alias{st_m_range.LINESTRING}\n\\alias{st_m_range.POLYGON}\n\\alias{st_m_range.MULTILINESTRING}\n\\alias{st_m_range.MULTIPOLYGON}\n\\alias{st_m_range.GEOMETRYCOLLECTION}\n\\alias{st_m_range.MULTISURFACE}\n\\alias{st_m_range.MULTICURVE}\n\\alias{st_m_range.CURVEPOLYGON}\n\\alias{st_m_range.COMPOUNDCURVE}\n\\alias{st_m_range.POLYHEDRALSURFACE}\n\\alias{st_m_range.TIN}\n\\alias{st_m_range.TRIANGLE}\n\\alias{st_m_range.CIRCULARSTRING}\n\\alias{st_m_range.sfc}\n\\alias{st_m_range.sf}\n\\alias{st_m_range.numeric}\n\\alias{NA_m_range_}\n\\title{Return 'm' range of a simple feature or simple feature set}\n\\usage{\n\\method{is.na}{m_range}(x)\n\nst_m_range(obj, ...)\n\n\\method{st_m_range}{POINT}(obj, ...)\n\n\\method{st_m_range}{MULTIPOINT}(obj, ...)\n\n\\method{st_m_range}{LINESTRING}(obj, ...)\n\n\\method{st_m_range}{POLYGON}(obj, ...)\n\n\\method{st_m_range}{MULTILINESTRING}(obj, ...)\n\n\\method{st_m_range}{MULTIPOLYGON}(obj, ...)\n\n\\method{st_m_range}{GEOMETRYCOLLECTION}(obj, ...)\n\n\\method{st_m_range}{MULTISURFACE}(obj, ...)\n\n\\method{st_m_range}{MULTICURVE}(obj, ...)\n\n\\method{st_m_range}{CURVEPOLYGON}(obj, ...)\n\n\\method{st_m_range}{COMPOUNDCURVE}(obj, ...)\n\n\\method{st_m_range}{POLYHEDRALSURFACE}(obj, ...)\n\n\\method{st_m_range}{TIN}(obj, ...)\n\n\\method{st_m_range}{TRIANGLE}(obj, ...)\n\n\\method{st_m_range}{CIRCULARSTRING}(obj, ...)\n\n\\method{st_m_range}{sfc}(obj, ...)\n\n\\method{st_m_range}{sf}(obj, ...)\n\n\\method{st_m_range}{numeric}(obj, ..., crs = NA_crs_)\n\nNA_m_range_\n}\n\\arguments{\n\\item{x}{object of class \\code{m_range}}\n\n\\item{obj}{object to compute the m range from}\n\n\\item{...}{ignored}\n\n\\item{crs}{object of class \\code{crs}, or argument to \\link{st_crs}, specifying the CRS of this bounding box.}\n}\n\\value{\na numeric vector of length two, with \\code{mmin} and \\code{mmax} values;\nif \\code{obj} is of class \\code{sf} or \\code{sfc} the object\nif \\code{obj} is of class \\code{sf} or \\code{sfc} the object\nreturned has a class \\code{m_range}\n}\n\\description{\nReturn 'm' range of a simple feature or simple feature set\n}\n\\details{\n\\code{NA_m_range_} represents the missing value for a \\code{m_range} object\n}\n\\examples{\na = st_sf(a = 1:2, geom = st_sfc(st_point(0:3), st_point(1:4)), crs = 4326)\nst_m_range(a)\nst_m_range(c(mmin = 16.1, mmax = 16.6), crs = st_crs(4326))\n}\n"
  },
  {
    "path": "man/st_make_grid.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/make_grid.R\n\\name{st_make_grid}\n\\alias{st_make_grid}\n\\title{Create a regular tesselation over the bounding box of an sf or sfc object}\n\\usage{\nst_make_grid(\n  x,\n  cellsize = c(diff(st_bbox(x)[c(1, 3)]), diff(st_bbox(x)[c(2, 4)]))/n,\n  offset = st_bbox(x)[c(\"xmin\", \"ymin\")],\n  n = c(10, 10),\n  crs = if (missing(x)) NA_crs_ else st_crs(x),\n  what = \"polygons\",\n  square = TRUE,\n  flat_topped = FALSE\n)\n}\n\\arguments{\n\\item{x}{object of class \\link{sf} or \\link{sfc}}\n\n\\item{cellsize}{numeric of length 1 or 2 with target cellsize: for square or rectangular cells the width and height, for hexagonal cells the distance between opposite edges (edge length is cellsize/sqrt(3)). A length units object can be passed, or an area unit object with area size of the square or hexagonal cell.}\n\n\\item{offset}{numeric of length 2; lower left corner coordinates (x, y) of the grid}\n\n\\item{n}{integer of length 1 or 2, number of grid cells in x and y direction (columns, rows)}\n\n\\item{crs}{object of class \\code{crs}; coordinate reference system of the target grid in case argument \\code{x} is missing, if \\code{x} is not missing, its crs is inherited.}\n\n\\item{what}{character; one of: \\code{\"polygons\"}, \\code{\"corners\"}, or \\code{\"centers\"}}\n\n\\item{square}{logical; if \\code{FALSE}, create hexagonal grid}\n\n\\item{flat_topped}{logical; if \\code{TRUE} generate flat topped hexagons, else generate pointy topped}\n}\n\\value{\nObject of class \\code{sfc} (simple feature geometry list column) with, depending on \\code{what} and \\code{square},\nsquare or hexagonal polygons, corner points of these polygons, or center points of these polygons.\n}\n\\description{\nCreate a square or hexagonal grid covering the bounding box of the geometry of an sf or sfc object\n}\n\\examples{\nplot(st_make_grid(what = \"centers\"), axes = TRUE)\nplot(st_make_grid(what = \"corners\"), add = TRUE, col = 'green', pch=3)\nsfc = st_sfc(st_polygon(list(rbind(c(0,0), c(1,0), c(1,1), c(0,0)))))\nplot(st_make_grid(sfc, cellsize = .1, square = FALSE))\nplot(sfc, add = TRUE)\n# non-default offset:\nplot(st_make_grid(sfc, cellsize = .1, square = FALSE, offset = c(0, .05 / (sqrt(3)/2))))\nplot(sfc, add = TRUE)\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\ng = st_make_grid(nc)\nplot(g)\nplot(st_geometry(nc), add = TRUE)\n# g[nc] selects cells that intersect with nc:\nplot(g[nc], col = '#ff000088', add = TRUE)\n}\n"
  },
  {
    "path": "man/st_nearest_feature.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/nearest.R\n\\name{st_nearest_feature}\n\\alias{st_nearest_feature}\n\\title{get index of nearest feature}\n\\usage{\nst_nearest_feature(\n  x,\n  y,\n  ...,\n  check_crs = TRUE,\n  longlat = isTRUE(st_is_longlat(x))\n)\n}\n\\arguments{\n\\item{x}{object of class \\code{sfg}, \\code{sfc} or \\code{sf}}\n\n\\item{y}{object of class \\code{sfg}, \\code{sfc} or \\code{sf}; if missing, features in \\code{x} will be compared to all remaining features in \\code{x}.}\n\n\\item{...}{ignored}\n\n\\item{check_crs}{logical; should \\code{x} and \\code{y} be checked for CRS equality?}\n\n\\item{longlat}{logical; does \\code{x} have ellipsoidal coordinates?}\n}\n\\value{\nfor each feature (geometry) in \\code{x} the index of the nearest feature (geometry) in\nset \\code{y}, or in the remaining set of \\code{x} if \\code{y} is missing;\nempty geometries result in \\code{NA} indexes\n}\n\\description{\nget index of nearest feature\n}\n\\examples{\nls1 = st_linestring(rbind(c(0,0), c(1,0)))\nls2 = st_linestring(rbind(c(0,0.1), c(1,0.1)))\nls3 = st_linestring(rbind(c(0,1), c(1,1)))\n(l = st_sfc(ls1, ls2, ls3))\n\np1 = st_point(c(0.1, -0.1))\np2 = st_point(c(0.1, 0.11))\np3 = st_point(c(0.1, 0.09))\np4 = st_point(c(0.1, 0.9))\n\n(p = st_sfc(p1, p2, p3, p4))\ntry(st_nearest_feature(p, l))\ntry(st_nearest_points(p, l[st_nearest_feature(p,l)], pairwise = TRUE))\n\nr = sqrt(2)/10\nb1 = st_buffer(st_point(c(.1,.1)), r)\nb2 = st_buffer(st_point(c(.9,.9)), r)\nb3 = st_buffer(st_point(c(.9,.1)), r)\ncircles = st_sfc(b1, b2, b3)\nplot(circles, col = NA, border = 2:4)\npts = st_sfc(st_point(c(.3,.1)), st_point(c(.6,.2)), st_point(c(.6,.6)), st_point(c(.4,.8)))\nplot(pts, add = TRUE, col = 1)\n# draw points to nearest circle:\nnearest = try(st_nearest_feature(pts, circles))\nif (inherits(nearest, \"try-error\")) # GEOS 3.6.1 not available\n  nearest = c(1, 3, 2, 2)\nls = st_nearest_points(pts, circles[nearest], pairwise = TRUE)\nplot(ls, col = 5:8, add = TRUE)\n# compute distance between pairs of nearest features:\nst_distance(pts, circles[nearest], by_element = TRUE)\n}\n\\seealso{\n\\link{st_nearest_points} for finding the nearest points for pairs of feature geometries\n}\n"
  },
  {
    "path": "man/st_nearest_points.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/nearest.R\n\\name{st_nearest_points}\n\\alias{st_nearest_points}\n\\alias{st_nearest_points.sfc}\n\\alias{st_nearest_points.sfg}\n\\alias{st_nearest_points.sf}\n\\title{get nearest points between pairs of geometries}\n\\usage{\nst_nearest_points(x, y, ..., by_element = FALSE)\n\n\\method{st_nearest_points}{sfc}(x, y, ..., pairwise = by_element, by_element = FALSE)\n\n\\method{st_nearest_points}{sfg}(x, y, ...)\n\n\\method{st_nearest_points}{sf}(x, y, ...)\n}\n\\arguments{\n\\item{x}{object of class \\code{sfg}, \\code{sfc} or \\code{sf}}\n\n\\item{y}{object of class \\code{sfg}, \\code{sfc} or \\code{sf}; needs to have the same number of geometries of \\code{x} when \\code{by_element=TRUE}}\n\n\\item{...}{ignored}\n\n\\item{by_element}{logical; if \\code{FALSE} (default) return nearest points between all possible pairs, if \\code{TRUE}, return nearest points between row-wise x-y pairs.}\n\n\\item{pairwise}{logical; deprecated in favour of \\code{by_element}}\n}\n\\value{\nan \\link{sfc} object with all two-point \\code{LINESTRING} geometries of point pairs from the first to the second geometry, of length x * y if \\code{by_element=FALSE} (with y cycling fastest), or lf length \\code{length(x)} when \\code{by_element=TRUE}. See examples for ideas how to convert these to \\code{POINT} geometries.\n}\n\\description{\nget nearest points between pairs of geometries\n}\n\\details{\nin case \\code{x} lies inside \\code{y}, when using S2, the end points\nare on polygon boundaries, when using GEOS the end point are identical to \\code{x}.\n}\n\\examples{\nr = sqrt(2)/10\npt1 = st_point(c(.1,.1))\npt2 = st_point(c(.9,.9))\npt3 = st_point(c(.9,.1))\nb1 = st_buffer(pt1, r)\nb2 = st_buffer(pt2, r)\nb3 = st_buffer(pt3, r)\n(ls0 = st_nearest_points(b1, b2)) # sfg\n(ls = st_nearest_points(st_sfc(b1), st_sfc(b2, b3))) # sfc\nplot(b1, xlim = c(-.2,1.2), ylim = c(-.2,1.2), col = NA, border = 'green')\nplot(st_sfc(b2, b3), add = TRUE, col = NA, border = 'blue')\nplot(ls, add = TRUE, col = 'red')\n\nnc = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"))\nplot(st_geometry(nc))\nls = st_nearest_points(nc[1,], nc)\nplot(ls, col = 'red', add = TRUE)\npts = st_cast(ls, \"POINT\") # gives all start & end points\n# starting, \"from\" points, corresponding to x:\nplot(pts[seq(1, 200, 2)], add = TRUE, col = 'blue')\n# ending, \"to\" points, corresponding to y:\nplot(pts[seq(2, 200, 2)], add = TRUE, col = 'green')\n\n}\n\\seealso{\n\\link{st_nearest_feature} for finding the nearest feature\n}\n"
  },
  {
    "path": "man/st_normalize.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/normalize.R\n\\name{st_normalize}\n\\alias{st_normalize}\n\\title{Normalize simple features}\n\\usage{\nst_normalize(x, domain = st_bbox(x), ...)\n}\n\\arguments{\n\\item{x}{object of class sf, sfc or sfg}\n\n\\item{domain}{The domain \\code{x} should be normalized from as a length 4\nvector of the form \\code{c(xmin, ymin, xmax, ymax)}. Defaults to the\nbounding box of \\code{x}}\n\n\\item{...}{ignored}\n}\n\\description{\n\\code{st_normalize} transforms the coordinates in the input feature to fall\nbetween 0 and 1. By default the current domain is set to the bounding box of\nthe input, but other domains can be used as well\n}\n\\examples{\np1 = st_point(c(7,52))\nst_normalize(p1, domain = c(0, 0, 10, 100))\n\np2 = st_point(c(-30,20))\nsfc = st_sfc(p1, p2, crs = 4326)\nsfc\nsfc_norm <- st_normalize(sfc)\nst_bbox(sfc_norm)\n\n}\n"
  },
  {
    "path": "man/st_precision.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sfc.R\n\\name{st_precision}\n\\alias{st_precision}\n\\alias{st_set_precision}\n\\alias{st_precision<-}\n\\title{Get precision}\n\\usage{\nst_precision(x)\n\nst_set_precision(x, precision)\n\nst_precision(x) <- value\n}\n\\arguments{\n\\item{x}{object of class \\code{sfc} or \\code{sf}}\n\n\\item{precision}{numeric, or object of class \\code{units} with distance units (but see details); see \\link{st_as_binary} for how to do this.}\n\n\\item{value}{precision value}\n}\n\\description{\nGet precision\n\nSet precision\n}\n\\details{\nIf \\code{precision} is a \\code{units} object, the object on which we set precision must have a coordinate reference system with compatible distance units.\n\nSetting a \\code{precision} has no direct effect on coordinates of geometries, but merely set an attribute tag to an \\code{sfc} object.\nThe effect takes place in \\link{st_as_binary} or, more precise, in the C++ function \\code{CPL_write_wkb}, where simple feature geometries are being serialized to well-known-binary (WKB).\nThis happens always when routines are called in GEOS library (geometrical operations or predicates), for writing geometries using \\link{st_write} or \\link{write_sf}, \\code{st_make_valid} in package \\code{lwgeom}; also \\link{aggregate} and \\link{summarise} by default union geometries, which calls a GEOS library function.\nRoutines in these libraries receive rounded coordinates, and possibly return results based on them. \\link{st_as_binary} contains an example of a roundtrip of \\code{sfc} geometries through WKB, in order to see the rounding happening to R data.\n\nThe reason to support precision is that geometrical operations in GEOS or liblwgeom may work better at reduced precision. For writing data from R to external resources it is harder to think of a good reason to limiting precision.\n}\n\\examples{\nx <- st_sfc(st_point(c(pi, pi)))\nst_precision(x)\nst_precision(x) <- 0.01\nst_precision(x)\n}\n\\seealso{\n\\link{st_as_binary} for an explanation of what setting precision does, and the examples therein.\n}\n"
  },
  {
    "path": "man/st_read.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/read.R, R/db.R\n\\name{st_read}\n\\alias{st_read}\n\\alias{st_read.character}\n\\alias{read_sf}\n\\alias{st_read.DBIObject}\n\\title{Read simple features or layers from file or database}\n\\usage{\nst_read(dsn, layer, ...)\n\n\\method{st_read}{character}(\n  dsn,\n  layer,\n  ...,\n  query = NA,\n  options = NULL,\n  quiet = FALSE,\n  geometry_column = 1L,\n  type = 0,\n  promote_to_multi = TRUE,\n  stringsAsFactors = sf_stringsAsFactors(),\n  int64_as_string = FALSE,\n  check_ring_dir = FALSE,\n  fid_column_name = character(0),\n  drivers = character(0),\n  wkt_filter = character(0),\n  optional = FALSE,\n  use_stream = default_st_read_use_stream()\n)\n\nread_sf(..., quiet = TRUE, stringsAsFactors = FALSE, as_tibble = TRUE)\n\n\\method{st_read}{DBIObject}(\n  dsn = NULL,\n  layer = NULL,\n  query = NULL,\n  EWKB = TRUE,\n  quiet = TRUE,\n  as_tibble = FALSE,\n  geometry_column = NULL,\n  ...\n)\n}\n\\arguments{\n\\item{dsn}{data source name (interpretation varies by driver - for some\ndrivers, \\code{dsn} is a file name, but may also be a folder, or contain\nthe name and access credentials of a database); in case of GeoJSON,\n\\code{dsn} may be the character string holding the geojson data. It can\nalso be an open database connection.}\n\n\\item{layer}{layer name (varies by driver, may be a file name without\nextension); in case \\code{layer} is missing, \\code{st_read} will read the\nfirst layer of \\code{dsn}, give a warning and (unless \\code{quiet = TRUE})\nprint a message when there are multiple layers, or give an error if there\nare no layers in \\code{dsn}. If \\code{dsn} is a database connection, then\n\\code{layer} can be a table name or a database identifier (see\n\\code{\\link[DBI]{Id}}). It is also possible to omit \\code{layer} and rather\nuse the \\code{query} argument.}\n\n\\item{...}{parameter(s) passed on to \\link{st_as_sf}}\n\n\\item{query}{SQL query to select records; see details}\n\n\\item{options}{character; driver dependent dataset open options, multiple\noptions supported. For possible values, see the \"Open options\" section\nof the GDAL documentation of the corresponding driver, and\n\\url{https://github.com/r-spatial/sf/issues/1157} for an example.}\n\n\\item{quiet}{logical; suppress info on name, driver, size and spatial\nreference, or signaling no or multiple layers}\n\n\\item{geometry_column}{integer or character; in case of multiple geometry\nfields, which one to take?}\n\n\\item{type}{integer; ISO number of desired simple feature type; see details.\nIf left zero, and \\code{promote_to_multi} is \\code{TRUE}, in case of mixed\nfeature geometry types, conversion to the highest numeric type value found\nwill be attempted. A vector with different values for each geometry column\ncan be given.}\n\n\\item{promote_to_multi}{logical; in case of a mix of Point and MultiPoint, or\nof LineString and MultiLineString, or of Polygon and MultiPolygon, convert\nall to the Multi variety; defaults to \\code{TRUE}}\n\n\\item{stringsAsFactors}{logical; should character vectors be\nconverted to factors?  Default for \\code{read_sf} or R version >= 4.1.0 is\n\\code{FALSE}, for \\code{st_read} and R version < 4.1.0 equal to\n\\code{default.stringsAsFactors()}}\n\n\\item{int64_as_string}{logical; if \\code{TRUE}, Int64 attributes are returned as\nstring; if \\code{FALSE}, they are returned as double and a warning is given when\nprecision is lost (i.e., values are larger than 2^53).}\n\n\\item{check_ring_dir}{logical; if \\code{TRUE}, polygon ring directions are checked\nand if necessary corrected (when seen from above: exterior ring counter\nclockwise, holes clockwise)}\n\n\\item{fid_column_name}{character; name of column to write feature IDs to; defaults to not doing this}\n\n\\item{drivers}{character; limited set of driver short names to be tried (default: try all)}\n\n\\item{wkt_filter}{character; WKT representation of a spatial filter (may be used as bounding box, selecting overlapping geometries); see examples}\n\n\\item{optional}{logical; passed to \\link[base]{as.data.frame}; always \\code{TRUE} when \\code{as_tibble} is \\code{TRUE}}\n\n\\item{use_stream}{Use \\code{TRUE} to use the experimental columnar interface introduced in GDAL 3.6.}\n\n\\item{as_tibble}{logical; should the returned table be of class tibble or data.frame?}\n\n\\item{EWKB}{logical; is the WKB of type EWKB? if missing, defaults to\n\\code{TRUE}}\n}\n\\value{\nobject of class \\link{sf} when a layer was successfully read; in case\nargument \\code{layer} is missing and data source \\code{dsn} does not\ncontain a single layer, an object of class \\code{sf_layers} is returned\nwith the layer names, each with their geometry type(s). Note that the\nnumber of layers may also be zero.\n}\n\\description{\nRead simple features from file or database, or retrieve layer names and their\ngeometry type(s)\n\nRead PostGIS table directly through DBI and RPostgreSQL interface, converting\nWell-Know Binary geometries to sfc\n}\n\\details{\nfor \\code{geometry_column}, see also\n\\url{https://gdal.org/en/latest/development/rfc/rfc41_multiple_geometry_fields.html}\n\nfor values for \\code{type} see\n\\url{https://en.wikipedia.org/wiki/Well-known_text_representation_of_geometry#Well-known_binary},\nbut note that not every target value may lead to successful conversion. The\ntypical conversion from POLYGON (3) to MULTIPOLYGON (6) should work; the\nother way around (type=3), secondary rings from MULTIPOLYGONS may be dropped\nwithout warnings. \\code{promote_to_multi} is handled on a per-geometry column\nbasis; \\code{type} may be specified for each geometry column.\n\nNote that stray files in data source directories (such as \\code{*.dbf}) may\nlead to spurious errors that accompanying \\code{*.shp} are missing.\n\nIn case of problems reading shapefiles from USB drives on OSX, please see\n\\url{https://github.com/r-spatial/sf/issues/252}. Reading shapefiles (or other\ndata sources) directly from zip files can be done by prepending the path\nwith \\code{/vsizip/}. This is part of the GDAL Virtual File Systems interface\nthat also supports .gz, curl, and other operations, including chaining; see\n\\url{https://gdal.org/en/latest/user/virtual_file_systems.html} for a complete\ndescription and examples.\n\nFor \\code{query} with a character \\code{dsn} the query text is handed to\n'ExecuteSQL' on the GDAL/OGR data set and will result in the creation of a\nnew layer (and \\code{layer} is ignored). See 'OGRSQL'\n\\url{https://gdal.org/en/latest/user/ogr_sql_dialect.html} for details. Please note that the\n'FID' special field is driver-dependent, and may be either 0-based (e.g. ESRI\nShapefile), 1-based (e.g. MapInfo) or arbitrary (e.g. OSM). Other features of\nOGRSQL are also likely to be driver dependent. The available layer names may\nbe obtained with\n\\link{st_layers}. Care will be required to properly escape the use of some layer names.\n\n\\code{read_sf} and \\code{write_sf} are aliases for \\code{st_read} and \\code{st_write}, respectively, with some\nmodified default arguments.\n\\code{read_sf} and \\code{write_sf} are quiet by default: they do not print information\nabout the data source. \\code{read_sf} returns an sf-tibble rather than an sf-data.frame.\n\\code{write_sf} delete layers by default: it overwrites existing files without asking or warning.\n\nif \\code{table} is not given but \\code{query} is, the spatial\nreference system (crs) of the table queried is only available in case it\nhas been stored into each geometry record (e.g., by PostGIS, when using\nEWKB)\n\nThe function will automatically find the \\code{geometry} type columns for\ndrivers that support it. For the other drivers, it will try to cast all the\ncharacter columns, which can be slow for very wide tables.\n}\n\\note{\nThe use of \\code{system.file} in examples make sure that examples run regardless where R is installed:\ntypical users will not use \\code{system.file} but give the file name directly, either with full path or relative\nto the current working directory (see \\link{getwd}). \"Shapefiles\" consist of several files with the same basename\nthat reside in the same directory, only one of them having extension \\code{.shp}.\n}\n\\examples{\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\nsummary(nc) # note that AREA was computed using Euclidian area on lon/lat degrees\n\n## only three fields by select clause\n## only two features by where clause\nnc_sql = st_read(system.file(\"shape/nc.shp\", package=\"sf\"),\n                     query = \"SELECT NAME, SID74, FIPS FROM \\\"nc\\\" WHERE BIR74 > 20000\")\n\\dontrun{\n  library(sp)\n  example(meuse, ask = FALSE, echo = FALSE)\n  try(st_write(st_as_sf(meuse), \"PG:dbname=postgis\", \"meuse\",\n       layer_options = \"OVERWRITE=true\"))\n  try(st_meuse <- st_read(\"PG:dbname=postgis\", \"meuse\"))\n  if (exists(\"st_meuse\"))\n    summary(st_meuse)\n}\n\n\\dontrun{\n## note that we need special escaping of layer  within single quotes (nc.gpkg)\n## and that geom needs to be included in the select, otherwise we don't detect it\nlayer <- st_layers(system.file(\"gpkg/nc.gpkg\", package = \"sf\"))$name[1]\nnc_gpkg_sql = st_read(system.file(\"gpkg/nc.gpkg\", package = \"sf\"),\n   query = sprintf(\"SELECT NAME, SID74, FIPS, geom  FROM \\\"\\%s\\\" WHERE BIR74 > 20000\", layer))\n}\n# spatial filter, as wkt:\nwkt = st_as_text(st_geometry(nc[1,]))\n# filter by (bbox overlaps of) first feature geometry:\nst_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), wkt_filter = wkt)\n# read geojson from string:\ngeojson_txt <- paste(\"{\\\"type\\\":\\\"MultiPoint\\\",\\\"coordinates\\\":\",\n   \"[[3.2,4],[3,4.6],[3.8,4.4],[3.5,3.8],[3.4,3.6],[3.9,4.5]]}\")\nx = st_read(geojson_txt)\nx\n\\dontrun{\nlibrary(RPostgreSQL)\ntry(conn <- dbConnect(PostgreSQL(), dbname = \"postgis\"))\nif (exists(\"conn\") && !inherits(conn, \"try-error\")) {\n  x = st_read(conn, \"meuse\", query = \"select * from meuse limit 3;\")\n  x = st_read(conn, table = \"public.meuse\")\n  print(st_crs(x)) # SRID resolved by the database, not by GDAL!\n  dbDisconnect(conn)\n }\n}\n}\n\\seealso{\n\\link{st_layers}, \\link{st_drivers}\n}\n"
  },
  {
    "path": "man/st_relate.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/geom-predicates.R\n\\name{st_relate}\n\\alias{st_relate}\n\\title{Compute DE9-IM relation between pairs of geometries, or match it to a given pattern}\n\\usage{\nst_relate(x, y, pattern = NA_character_, sparse = !is.na(pattern), ...)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf}, \\code{sfc} or \\code{sfg}}\n\n\\item{y}{object of class \\code{sf}, \\code{sfc} or \\code{sfg}}\n\n\\item{pattern}{character; define the pattern to match to, see details.}\n\n\\item{sparse}{logical; should a sparse matrix be returned (\\code{TRUE}) or a dense matrix?}\n\n\\item{...}{may be used to specify \\code{by_element=TRUE} to return a vector with element-wise relations or matches}\n}\n\\value{\nIn case \\code{pattern} is not given, \\code{st_relate} returns a dense \\code{character} matrix; element \\verb{[i,j]} has nine characters, referring to the DE9-IM relationship between \\code{x[i]} and \\code{y[j]}, encoded as IxIy,IxBy,IxEy,BxIy,BxBy,BxEy,ExIy,ExBy,ExEy where I refers to interior, B to boundary, and E to exterior, and e.g. BxIy the dimensionality of the intersection of the the boundary of \\code{x[i]} and the interior of \\code{y[j]}, which is one of: 0, 1, 2, or F; digits denoting dimensionality of intersection, F denoting no intersection. When \\code{pattern} is given, a dense logical matrix or sparse index list returned with matches to the given pattern; see \\link{st_intersects} for a description of the returned matrix or list. See also \\url{https://en.wikipedia.org/wiki/DE-9IM} for further explanation.\n}\n\\description{\nCompute DE9-IM relation between pairs of geometries, or match it to a given pattern\n}\n\\examples{\np1 = st_point(c(0,0))\np2 = st_point(c(2,2))\npol1 = st_polygon(list(rbind(c(0,0),c(1,0),c(1,1),c(0,1),c(0,0)))) - 0.5\npol2 = pol1 + 1\npol3 = pol1 + 2\nst_relate(st_sfc(p1, p2), st_sfc(pol1, pol2, pol3))\nsfc = st_sfc(st_point(c(0,0)), st_point(c(3,3)))\ngrd = st_make_grid(sfc, n = c(3,3))\nst_intersects(grd)\nst_relate(grd, pattern = \"****1****\") # sides, not corners, internals\nst_relate(grd, pattern = \"****0****\") # only corners touch\nst_rook = function(a, b = a) st_relate(a, b, pattern = \"F***1****\")\nst_rook(grd)\n# queen neighbours, see \\url{https://github.com/r-spatial/sf/issues/234#issuecomment-300511129}\nst_queen <- function(a, b = a) st_relate(a, b, pattern = \"F***T****\")\n}\n"
  },
  {
    "path": "man/st_sample.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sample.R\n\\name{st_sample}\n\\alias{st_sample}\n\\alias{st_sample.sf}\n\\alias{st_sample.sfc}\n\\alias{st_sample.sfg}\n\\alias{st_sample.bbox}\n\\title{sample points on or in (sets of) spatial features}\n\\usage{\nst_sample(x, size, ...)\n\n\\method{st_sample}{sf}(x, size, ...)\n\n\\method{st_sample}{sfc}(\n  x,\n  size,\n  ...,\n  type = \"random\",\n  exact = TRUE,\n  warn_if_not_integer = TRUE,\n  by_polygon = FALSE,\n  progress = FALSE,\n  force = FALSE\n)\n\n\\method{st_sample}{sfg}(x, size, ...)\n\n\\method{st_sample}{bbox}(\n  x,\n  size,\n  ...,\n  great_circles = FALSE,\n  segments = units::set_units(2, \"degree\", mode = \"standard\")\n)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf} or \\code{sfc}}\n\n\\item{size}{sample size(s) requested; either total size, or a numeric vector with sample sizes for each feature geometry. When sampling polygons, the returned sampling size may differ from the requested size, as the bounding box is sampled, and sampled points intersecting the polygon are returned.}\n\n\\item{...}{passed on to \\link[base]{sample} for \\code{multipoint} sampling, or to \\code{spatstat} functions for spatstat sampling types (see details)}\n\n\\item{type}{character; indicates the spatial sampling type; one of \\code{random}, \\code{hexagonal} (triangular really), \\code{regular}, \\code{Fibonacci},\nor one of the \\code{spatstat} methods such as \\code{Thomas} for calling \\code{spatstat.random::rThomas} (see Details).}\n\n\\item{exact}{logical; should the length of output be exactly}\n\n\\item{warn_if_not_integer}{logical; if \\code{FALSE} then no warning is emitted if \\code{size} is not an integer}\n\n\\item{by_polygon}{logical; for \\code{MULTIPOLYGON} geometries, should the effort be split by \\code{POLYGON}? See https://github.com/r-spatial/sf/issues/1480\nthe same as specified by \\code{size}? \\code{TRUE} by default. Only applies to polygons, and\nwhen \\code{type = \"random\"}.}\n\n\\item{progress}{logical; if \\code{TRUE} show progress bar (only if \\code{size} is a vector).}\n\n\\item{force}{logical; if \\code{TRUE} continue when the sampled bounding box area is more than 1e4 times the area of interest, else (default) stop with an error. If this error is not justified, try setting \\code{oriented=TRUE}, see details.}\n\n\\item{great_circles}{logical; if \\code{TRUE}, great circle arcs are used to connect the bounding box vertices, if \\code{FALSE} parallels (graticules)}\n\n\\item{segments}{units, or numeric (degrees); segment sizes for segmenting a bounding box polygon if \\code{great_circles} is \\code{FALSE}}\n}\n\\value{\nan \\code{sfc} object containing the sampled \\code{POINT} geometries\n}\n\\description{\nSample points on or in (sets of) spatial features.\nBy default, returns a pre-specified number of points that is equal to\n\\code{size} (if \\code{type = \"random\"} and \\code{exact = TRUE}) or an approximation of\n\\code{size} otherwise. \\code{spatstat} methods are\ninterfaced and do not use the \\code{size} argument, see examples.\n}\n\\details{\nThe function is vectorised: it samples \\code{size} points across all geometries in\nthe object if \\code{size} is a single number, or the specified number of points\nin each feature if \\code{size} is a vector of integers equal in length to the geometry\nof \\code{x}.\n\nif \\code{x} has dimension 2 (polygons) and geographical coordinates (long/lat), uniform random sampling on the sphere is applied, see e.g. \\url{https://mathworld.wolfram.com/SpherePointPicking.html}.\n\nFor \\code{regular} or \\code{hexagonal} sampling of polygons, the resulting size is only an approximation.\n\nAs parameter called \\code{offset} can be passed to control (\"fix\") regular or hexagonal sampling: for polygons a length 2 numeric vector (by default: a random point from \\code{st_bbox(x)}); for lines use a number like \\code{runif(1)}.\n\nFibonacci sampling see: Alvaro Gonzalez, 2010. Measurement of Areas on a Sphere Using Fibonacci and Latitude-Longitude Lattices.\nMathematical Geosciences 42(1), p. 49-64\n\nFor regular sampling on the sphere, see also \\code{geosphere::regularCoordinates}.\n\nSampling methods from package \\code{spatstat} are interfaced (see examples), and need their own parameters to be set.\nFor instance, to use \\code{spatstat.random::rThomas()}, set \\code{type = \"Thomas\"}.\n\nFor sampling polygons one can specify \\code{oriented=TRUE} to make sure that polygons larger than half the globe are not reverted, e.g. when specifying a polygon from a bounding box of a global dataset. The \\code{st_sample} method for \\code{bbox} does this by default.\n}\n\\examples{\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\np1 = st_sample(nc[1:3, ], 6)\np2 = st_sample(nc[1:3, ], 1:3)\nplot(st_geometry(nc)[1:3])\nplot(p1, add = TRUE)\nplot(p2, add = TRUE, pch = 2)\nx = st_sfc(st_polygon(list(rbind(c(0,0),c(90,0),c(90,90),c(0,90),c(0,0)))), crs = st_crs(4326))\nplot(x, axes = TRUE, graticule = TRUE)\nif (compareVersion(sf_extSoftVersion()[\"proj.4\"], \"4.9.0\") >= 0)\n  plot(p <- st_sample(x, 1000), add = TRUE)\nif (require(lwgeom, quietly = TRUE)) { # for st_segmentize()\n  x2 = st_transform(st_segmentize(x, 1e4), st_crs(\"+proj=ortho +lat_0=30 +lon_0=45\"))\n  g = st_transform(st_graticule(), st_crs(\"+proj=ortho +lat_0=30 +lon_0=45\"))\n  plot(x2, graticule = g)\n  if (compareVersion(sf_extSoftVersion()[\"proj.4\"], \"4.9.0\") >= 0) {\n    p2 = st_transform(p, st_crs(\"+proj=ortho +lat_0=30 +lon_0=45\"))\n    plot(p2, add = TRUE)\n  }\n}\nx = st_sfc(st_polygon(list(rbind(c(0,0),c(90,0),c(90,10),c(0,90),c(0,0))))) # NOT long/lat:\nplot(x)\np_exact = st_sample(x, 1000, exact = TRUE)\np_not_exact = st_sample(x, 1000, exact = FALSE)\nlength(p_exact); length(p_not_exact)\nplot(st_sample(x, 1000), add = TRUE)\nx = st_sfc(st_polygon(list(rbind(c(-180,-90),c(180,-90),c(180,90),c(-180,90),c(-180,-90)))),\n crs=st_crs(4326))\n# FIXME:\n#if (compareVersion(sf_extSoftVersion()[\"proj.4\"], \"4.9.0\") >= 0) {\n#  p = st_sample(x, 1000)\n#  st_sample(p, 3)\n#}\n# hexagonal:\nsfc = st_sfc(st_polygon(list(rbind(c(0,0), c(1,0), c(1,1), c(0,0)))))\nplot(sfc)\nh = st_sample(sfc, 100, type = \"hexagonal\")\nh1 = st_sample(sfc, 100, type = \"hexagonal\")\nplot(h, add = TRUE)\nplot(h1, col = 'red', add = TRUE)\nc(length(h), length(h1)) # approximate!\npt = st_multipoint(matrix(1:20,,2))\nls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))),\n st_linestring(rbind(c(0,0),c(.1,0))),\n st_linestring(rbind(c(0,1),c(.1,1))),\n st_linestring(rbind(c(2,2),c(2,2.00001))))\nst_sample(ls, 80)\nplot(st_sample(ls, 80))\n# spatstat example:\nif (require(spatstat.random)) {\n  x <- sf::st_sfc(sf::st_polygon(list(rbind(c(0, 0), c(10, 0), c(10, 10), c(0, 0)))))\n  # for spatstat.random::rThomas(), set type = \"Thomas\":\n  pts <- st_sample(x, kappa = 1, mu = 10, scale = 0.1, type = \"Thomas\") \n}\nbbox = st_bbox(\nc(xmin = 0, xmax = 40, ymax = 70, ymin = 60),\n\tcrs = st_crs('OGC:CRS84')\n)\nset.seed(13531)\ns1 = st_sample(bbox, 400)\nst_bbox(s1) # within bbox\ns2 = st_sample(bbox, 400, great_circles = TRUE)\nst_bbox(s2) # outside bbox\n}\n"
  },
  {
    "path": "man/st_shift_longitude.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/shift_longitude.R\n\\name{st_shift_longitude}\n\\alias{st_shift_longitude}\n\\alias{st_shift_longitude.sfc}\n\\alias{st_shift_longitude.sf}\n\\title{Shift or re-center geographical coordinates for a Pacific view}\n\\usage{\nst_shift_longitude(x)\n\n\\method{st_shift_longitude}{sfc}(x, ...)\n\n\\method{st_shift_longitude}{sf}(x, ...)\n}\n\\arguments{\n\\item{x}{object of class \\code{sf} or \\code{sfc}}\n\n\\item{...}{ignored}\n}\n\\description{\nAll longitudes < 0 are added to 360, to avoid for instance parts of Alaska\nbeing represented on the far left and right of a plot because they have\nvalues straddling 180 degrees. In general, using a projected\ncoordinate reference system is to be preferred, but this method permits a\ngeographical coordinate reference system to be used. This is the sf\nequivalent of \\link[sp:recenter]{recenter} in the sp package and\n\\code{ST_ShiftLongitude} in PostGIS.\n}\n\\examples{\n## sfc\npt1 = st_point(c(-170, 50))\npt2 = st_point(c(170, 50))\n(sfc = st_sfc(pt1, pt2))\nsfc = st_set_crs(sfc, 4326)\nst_shift_longitude(sfc)\n\n## sf\nd = st_as_sf(data.frame(id = 1:2, geometry = sfc))\nst_shift_longitude(d)\n}\n"
  },
  {
    "path": "man/st_transform.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/transform.R, R/proj.R\n\\name{st_transform}\n\\alias{st_transform}\n\\alias{st_can_transform}\n\\alias{st_transform.sfc}\n\\alias{st_transform.sf}\n\\alias{st_transform.sfg}\n\\alias{st_transform.bbox}\n\\alias{st_wrap_dateline}\n\\alias{st_wrap_dateline.sfc}\n\\alias{st_wrap_dateline.sf}\n\\alias{st_wrap_dateline.sfg}\n\\alias{sf_proj_info}\n\\title{Transform or convert coordinates of simple feature}\n\\usage{\nst_can_transform(src, dst)\n\nst_transform(x, crs, ...)\n\n\\method{st_transform}{sfc}(\n  x,\n  crs = st_crs(x),\n  ...,\n  aoi = numeric(0),\n  pipeline = character(0),\n  reverse = FALSE,\n  desired_accuracy = -1,\n  allow_ballpark = TRUE,\n  partial = TRUE,\n  check = FALSE\n)\n\n\\method{st_transform}{sf}(x, crs = st_crs(x), ...)\n\n\\method{st_transform}{sfg}(x, crs = st_crs(x), ...)\n\n\\method{st_transform}{bbox}(x, crs, ..., densify = 21)\n\nst_wrap_dateline(x, options, quiet)\n\n\\method{st_wrap_dateline}{sfc}(x, options = \"WRAPDATELINE=YES\", quiet = TRUE)\n\n\\method{st_wrap_dateline}{sf}(x, options = \"WRAPDATELINE=YES\", quiet = TRUE)\n\n\\method{st_wrap_dateline}{sfg}(x, options = \"WRAPDATELINE=YES\", quiet = TRUE)\n\nsf_proj_info(type = \"proj\", path)\n}\n\\arguments{\n\\item{src}{source crs}\n\n\\item{dst}{destination crs}\n\n\\item{x}{object of class sf, sfc or sfg}\n\n\\item{crs}{target coordinate reference system: object of class \\code{crs}, or input string for \\link{st_crs}}\n\n\\item{...}{ignored}\n\n\\item{aoi}{area of interest, in degrees:\nWestLongitude, SouthLatitude, EastLongitude, NorthLatitude}\n\n\\item{pipeline}{character; coordinate operation pipeline, for overriding the default operation}\n\n\\item{reverse}{boolean; has only an effect when \\code{pipeline} is defined:\nif \\code{TRUE}, the inverse operation of the pipeline is applied}\n\n\\item{desired_accuracy}{numeric; Only coordinate operations that offer an accuracy of\nat least the one specified will be considered; a negative value disables this feature\n(requires GDAL >= 3.3)}\n\n\\item{allow_ballpark}{logical; are ballpark (low accuracy) transformations allowed?\n(requires GDAL >= 3.3)}\n\n\\item{partial}{logical; allow for partial projection, if not all points of a geometry can be projected (corresponds to setting environment variable \\code{OGR_ENABLE_PARTIAL_REPROJECTION} to \\code{TRUE})}\n\n\\item{check}{logical; if \\code{TRUE}, perform a sanity check on resulting polygons}\n\n\\item{densify}{integer, number of points for discretizing lines between bounding box corner points; see Details}\n\n\\item{options}{character; should have \"WRAPDATELINE=YES\" to function; another parameter that is used is \"DATELINEOFFSET=10\" (where 10 is the default value)}\n\n\\item{quiet}{logical; print options after they have been parsed?}\n\n\\item{type}{character; one of \\code{have_datum_files}, \\code{proj}, \\code{ellps}, \\code{datum}, \\code{units}, \\code{path}, or \\code{prime_meridians}; see Details.}\n\n\\item{path}{character; PROJ search path to be set}\n}\n\\description{\nTransform or convert coordinates of simple feature\n}\n\\details{\n\\code{st_can_transform} returns a boolean indicating whether\ncoordinates with CRS src can be transformed into CRS dst\n\nTransforms coordinates of object to new projection.\nFeatures that cannot be transformed are returned as empty geometries.\nTransforms using the \\code{pipeline=} argument may fail if there is\nambiguity in the axis order of the specified coordinate reference system;\nif you need the traditional GIS order, use \\code{\"OGC:CRS84\"}, not\n\\code{\"EPSG:4326\"}. Extra care is needed with the ESRI Shapefile format,\nbecause WKT1 does not store axis order unambiguously.\n\nThe \\code{st_transform} method for \\code{sfg} objects assumes that the CRS of the object is available as an attribute of that name.\n\nthe method for \\code{bbox} objects densifies lines for geographic coordinates along Cartesian lines, not great circle arcs\n\nFor a discussion of using \\code{options}, see \\url{https://github.com/r-spatial/sf/issues/280} and \\url{https://github.com/r-spatial/sf/issues/1983}\n\n\\code{sf_proj_info} lists the available projections, ellipses, datums, units, or data search path of the PROJ library when \\code{type} is equal to proj, ellps, datum, units or path; when \\code{type} equals \\code{have_datum_files} a boolean is returned indicating whether datum files are installed and accessible (checking for \\code{conus}). \\code{path} returns the \\code{PROJ_INFO.searchpath} field directly, as a single string with path separaters (\\code{:}  or \\verb{;}).\n\nfor PROJ >= 6, \\code{sf_proj_info} does not provide option \\code{type = \"datums\"}.\nPROJ < 6 does not provide the option \\code{type = \"prime_meridians\"}.\n\nfor PROJ >= 7.1.0, the \"units\" query of \\code{sf_proj_info} returns the \\code{to_meter}\nvariable as numeric, previous versions return a character vector containing a numeric expression.\n}\n\\examples{\np1 = st_point(c(7,52))\np2 = st_point(c(-30,20))\nsfc = st_sfc(p1, p2, crs = 4326)\nsfc\nst_transform(sfc, 3857)\nst_transform(st_sf(a=2:1, geom=sfc), \"EPSG:3857\")\nif (compareVersion(sf_extSoftVersion()[\"GDAL\"], \"3.0.0\") >= 0) {\n  st_transform(sfc, pipeline =\n\t  \"+proj=pipeline +step +proj=axisswap +order=2,1\") # reverse axes\n  st_transform(sfc, pipeline =\n\t  \"+proj=pipeline +step +proj=axisswap +order=2,1\", reverse = TRUE) # also reverse axes\n}\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\nst_area(nc[1,]) # area from long/lat\nst_area(st_transform(nc[1,], 32119)) # NC state plane, m\nst_area(st_transform(nc[1,], 2264)) # NC state plane, US foot\nlibrary(units)\nset_units(st_area(st_transform(nc[1,], 2264)), m^2)\nst_transform(structure(p1, proj4string = \"EPSG:4326\"), \"EPSG:3857\")\nst_wrap_dateline(st_sfc(st_linestring(rbind(c(-179,0),c(179,0))), crs = 4326))\nsf_proj_info(\"datum\")\n}\n\\seealso{\n\\link[lwgeom]{st_transform_proj}, part of package lwgeom.\n\n\\link{sf_project} projects a matrix of coordinates, bypassing GDAL altogether\n\n\\link{st_break_antimeridian}\n}\n"
  },
  {
    "path": "man/st_viewport.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/grid.R\n\\name{st_viewport}\n\\alias{st_viewport}\n\\title{Create viewport from sf, sfc or sfg object}\n\\usage{\nst_viewport(x, ..., bbox = st_bbox(x), asp)\n}\n\\arguments{\n\\item{x}{object of class sf, sfc or sfg object}\n\n\\item{...}{parameters passed on to \\link[grid]{viewport}}\n\n\\item{bbox}{the bounding box used for aspect ratio}\n\n\\item{asp}{numeric; target aspect ratio (y/x), see Details}\n}\n\\value{\nThe output of the call to \\link[grid]{viewport}\n}\n\\description{\nCreate viewport from sf, sfc or sfg object\n}\n\\details{\nparameters \\code{width}, \\code{height}, \\code{xscale} and \\code{yscale} are set such that aspect ratio is honoured and plot size is maximized in the current viewport; others can be passed as \\code{...}\n\nIf \\code{asp} is missing, it is taken as 1, except when \\code{isTRUE(st_is_longlat(x))}, in which case it is set to \\code{1.0 /cos(y)}, with \\code{y} the middle of the latitude bounding box.\n}\n\\examples{\nlibrary(grid)\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\ngrid.newpage()\npushViewport(viewport(width = 0.8, height = 0.8))\npushViewport(st_viewport(nc))\ninvisible(lapply(st_geometry(nc), function(x) grid.draw(st_as_grob(x, gp = gpar(fill = 'red')))))\n}\n"
  },
  {
    "path": "man/st_write.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/read.R\n\\name{st_write}\n\\alias{st_write}\n\\alias{st_write.sfc}\n\\alias{st_write.sf}\n\\alias{st_write.data.frame}\n\\alias{write_sf}\n\\alias{st_delete}\n\\title{Write simple features object to file or database}\n\\usage{\nst_write(obj, dsn, layer, ...)\n\n\\method{st_write}{sfc}(obj, dsn, layer, ...)\n\n\\method{st_write}{sf}(\n  obj,\n  dsn,\n  layer = NULL,\n  ...,\n  driver = guess_driver_can_write(dsn),\n  dataset_options = NULL,\n  layer_options = NULL,\n  quiet = FALSE,\n  factorsAsCharacter = TRUE,\n  append = NA,\n  delete_dsn = FALSE,\n  delete_layer = !is.na(append) && !append,\n  fid_column_name = NULL,\n  config_options = character(0)\n)\n\n\\method{st_write}{data.frame}(obj, dsn, layer = NULL, ...)\n\nwrite_sf(..., quiet = TRUE, append = FALSE, delete_layer = !append)\n\nst_delete(\n  dsn,\n  layer = character(0),\n  driver = guess_driver_can_write(dsn),\n  quiet = FALSE\n)\n}\n\\arguments{\n\\item{obj}{object of class \\code{sf} or \\code{sfc}}\n\n\\item{dsn}{data source name. Interpretation varies by driver: can be\na filename, a folder, a database name, or a Database Connection\n(we officially test support for\n\\code{\\link[RPostgres:Postgres]{RPostgres::Postgres()}} connections).}\n\n\\item{layer}{layer name. Varies by driver, may be a file name without\nextension; for database connection, it is the name of the table. If layer\nis missing, the \\code{basename} of \\code{dsn} is taken.}\n\n\\item{...}{other arguments passed to \\link[DBI]{dbWriteTable} when \\code{dsn} is a\nDatabase Connection}\n\n\\item{driver}{character; name of driver to be used; if missing and \\code{dsn} is not a Database Connection, a driver name is guessed from \\code{dsn};\n\\code{st_drivers()} returns the drivers that are available with their properties; links to full driver documentation\nare found at \\url{https://gdal.org/en/latest/drivers/vector/index.html}}\n\n\\item{dataset_options}{character; driver dependent dataset creation options;\nmultiple options supported.}\n\n\\item{layer_options}{character; driver dependent layer creation options;\nmultiple options supported.}\n\n\\item{quiet}{logical; suppress info on name, driver, size and spatial\nreference}\n\n\\item{factorsAsCharacter}{logical; convert \\code{factor} levels to character\nstrings (\\code{TRUE}, default), otherwise into numbers when\nfactorsAsCharacter is \\code{FALSE}. For database connections,\n\\code{factorsAsCharacter} is always \\code{TRUE}.}\n\n\\item{append}{logical; should we append to an existing layer, or replace it?\nif \\code{TRUE} append, if \\code{FALSE} replace.\nThe default for \\code{st_write} is \\code{NA} which raises an error if the layer exists.\nThe default for \\code{write_sf} is \\code{FALSE}, which overwrites any existing data.\nSee also next two arguments for more control on overwrite behavior.}\n\n\\item{delete_dsn}{logical; delete data source \\code{dsn} before attempting\nto write?}\n\n\\item{delete_layer}{logical; delete layer \\code{layer} before attempting to\nwrite?\nThe default for \\code{st_write} is \\code{FALSE} which raises an error if the layer exists.\nThe default for \\code{write_sf} is \\code{TRUE}.}\n\n\\item{fid_column_name}{character, name of column with feature IDs; if\nspecified, this column is no longer written as feature attribute.}\n\n\\item{config_options}{character, named vector with GDAL config options}\n}\n\\value{\n\\code{obj}, invisibly\n}\n\\description{\nWrite simple features object to file or database\n}\n\\details{\nColumns (variables) of a class not supported are dropped with a warning.\n\nWhen updating an existing layer, records are appended to it if the updating\nobject has the right variable names and types. If names don't match an\nerror is raised. If types don't match, behaviour is undefined: GDAL may\nraise warnings or errors or fail silently.\n\nWhen deleting layers or data sources is not successful, no error is emitted.\n\\code{delete_dsn} and \\code{delete_layer} should be\nhandled with care; the former may erase complete directories or databases.\n\n\\code{st_delete()} deletes layer(s) in a data source, or a data source if layers are\nomitted; it returns \\code{TRUE} on success, \\code{FALSE} on failure, invisibly.\n}\n\\examples{\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\nst_write(nc, paste0(tempdir(), \"/\", \"nc.shp\"))\nst_write(nc, paste0(tempdir(), \"/\", \"nc.shp\"), delete_layer = TRUE) # overwrites\nif (require(sp, quietly = TRUE)) {\n data(meuse, package = \"sp\") # loads data.frame from sp\n meuse_sf = st_as_sf(meuse, coords = c(\"x\", \"y\"), crs = 28992)\n # writes X and Y as columns:\n st_write(meuse_sf, paste0(tempdir(), \"/\", \"meuse.csv\"), layer_options = \"GEOMETRY=AS_XY\")\n st_write(meuse_sf, paste0(tempdir(), \"/\", \"meuse.csv\"), layer_options = \"GEOMETRY=AS_WKT\",\n   delete_dsn=TRUE) # overwrites\n\\dontrun{\n library(sp)\n example(meuse, ask = FALSE, echo = FALSE)\n try(st_write(st_as_sf(meuse), \"PG:dbname=postgis\", \"meuse_sf\",\n     layer_options = c(\"OVERWRITE=yes\", \"LAUNDER=true\")))\n demo(nc, ask = FALSE)\n try(st_write(nc, \"PG:dbname=postgis\", \"sids\", layer_options = \"OVERWRITE=true\"))\n}\n}\n}\n\\seealso{\n\\link{st_drivers}, \\link[DBI]{dbWriteTable}\n}\n"
  },
  {
    "path": "man/st_z_range.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/z_range.R\n\\name{st_z_range}\n\\alias{st_z_range}\n\\alias{is.na.z_range}\n\\alias{st_z_range.POINT}\n\\alias{st_z_range.MULTIPOINT}\n\\alias{st_z_range.LINESTRING}\n\\alias{st_z_range.POLYGON}\n\\alias{st_z_range.MULTILINESTRING}\n\\alias{st_z_range.MULTIPOLYGON}\n\\alias{st_z_range.GEOMETRYCOLLECTION}\n\\alias{st_z_range.MULTISURFACE}\n\\alias{st_z_range.MULTICURVE}\n\\alias{st_z_range.CURVEPOLYGON}\n\\alias{st_z_range.COMPOUNDCURVE}\n\\alias{st_z_range.POLYHEDRALSURFACE}\n\\alias{st_z_range.TIN}\n\\alias{st_z_range.TRIANGLE}\n\\alias{st_z_range.CIRCULARSTRING}\n\\alias{st_z_range.sfc}\n\\alias{st_z_range.sf}\n\\alias{st_z_range.numeric}\n\\alias{NA_z_range_}\n\\title{Return 'z' range of a simple feature or simple feature set}\n\\usage{\n\\method{is.na}{z_range}(x)\n\nst_z_range(obj, ...)\n\n\\method{st_z_range}{POINT}(obj, ...)\n\n\\method{st_z_range}{MULTIPOINT}(obj, ...)\n\n\\method{st_z_range}{LINESTRING}(obj, ...)\n\n\\method{st_z_range}{POLYGON}(obj, ...)\n\n\\method{st_z_range}{MULTILINESTRING}(obj, ...)\n\n\\method{st_z_range}{MULTIPOLYGON}(obj, ...)\n\n\\method{st_z_range}{GEOMETRYCOLLECTION}(obj, ...)\n\n\\method{st_z_range}{MULTISURFACE}(obj, ...)\n\n\\method{st_z_range}{MULTICURVE}(obj, ...)\n\n\\method{st_z_range}{CURVEPOLYGON}(obj, ...)\n\n\\method{st_z_range}{COMPOUNDCURVE}(obj, ...)\n\n\\method{st_z_range}{POLYHEDRALSURFACE}(obj, ...)\n\n\\method{st_z_range}{TIN}(obj, ...)\n\n\\method{st_z_range}{TRIANGLE}(obj, ...)\n\n\\method{st_z_range}{CIRCULARSTRING}(obj, ...)\n\n\\method{st_z_range}{sfc}(obj, ...)\n\n\\method{st_z_range}{sf}(obj, ...)\n\n\\method{st_z_range}{numeric}(obj, ..., crs = NA_crs_)\n\nNA_z_range_\n}\n\\arguments{\n\\item{x}{object of class \\code{z_range}}\n\n\\item{obj}{object to compute the z range from}\n\n\\item{...}{ignored}\n\n\\item{crs}{object of class \\code{crs}, or argument to \\link{st_crs}, specifying the CRS of this bounding box.}\n}\n\\value{\na numeric vector of length two, with \\code{zmin} and \\code{zmax} values;\nif \\code{obj} is of class \\code{sf} or \\code{sfc} the object\nreturned has a class \\code{z_range}\n}\n\\description{\nReturn 'z' range of a simple feature or simple feature set\n}\n\\details{\n\\code{NA_z_range_} represents the missing value for a \\code{z_range} object\n}\n\\examples{\na = st_sf(a = 1:2, geom = st_sfc(st_point(0:2), st_point(1:3)), crs = 4326)\nst_z_range(a)\nst_z_range(c(zmin = 16.1, zmax = 16.6), crs = st_crs(4326))\n}\n"
  },
  {
    "path": "man/st_zm.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sfc.R\n\\name{st_zm}\n\\alias{st_zm}\n\\title{Drop or add Z and/or M dimensions from feature geometries}\n\\usage{\nst_zm(x, ..., drop = TRUE, what = \"ZM\")\n}\n\\arguments{\n\\item{x}{object of class \\code{sfg}, \\code{sfc} or \\code{sf}}\n\n\\item{...}{ignored}\n\n\\item{drop}{logical; drop, or (\\code{FALSE}) add?}\n\n\\item{what}{character which dimensions to drop or add}\n}\n\\description{\nDrop Z and/or M dimensions from feature geometries, resetting classes appropriately\n}\n\\details{\nOnly combinations \\code{drop=TRUE}, \\code{what = \"ZM\"}, and \\code{drop=FALSE}, \\code{what=\"Z\"} are supported so far.\nIn the latter case, \\code{x} should have \\code{XY} geometry, and zero values are added for the \\code{Z} dimension.\n}\n\\examples{\nst_zm(st_linestring(matrix(1:32,8)))\nx = st_sfc(st_linestring(matrix(1:32,8)), st_linestring(matrix(1:8,2)))\nst_zm(x)\na = st_sf(a = 1:2, geom=x)\nst_zm(a)\n}\n"
  },
  {
    "path": "man/stars.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/plot.R\n\\name{stars}\n\\alias{stars}\n\\alias{.get_layout}\n\\alias{.degAxis}\n\\alias{.image_scale}\n\\alias{.image_scale_factor}\n\\title{functions only exported to be used internally by stars}\n\\usage{\n.get_layout(bb, n, total_size, key.pos, key.width, mfrow = NULL, main = NULL)\n\n.degAxis(side, at, labels, ..., lon, lat, ndiscr, reset)\n\n.image_scale(\n  z,\n  col,\n  breaks = NULL,\n  key.pos,\n  add.axis = TRUE,\n  at = NULL,\n  ...,\n  axes = FALSE,\n  key.length,\n  logz = FALSE,\n  lab = \"\",\n  cex.axis = par(\"cex.axis\")\n)\n\n.image_scale_factor(\n  z,\n  col,\n  key.pos,\n  add.axis = TRUE,\n  ...,\n  axes = FALSE,\n  key.width,\n  key.length,\n  cex.axis = par(\"cex.axis\")\n)\n}\n\\arguments{\n\\item{bb}{ignore}\n\n\\item{n}{ignore}\n\n\\item{total_size}{ignore}\n\n\\item{key.pos}{ignore}\n\n\\item{key.width}{ignore}\n\n\\item{mfrow}{length-2 integer vector with number of rows, columns}\n\n\\item{main}{main or sub title}\n\n\\item{side}{ignore}\n\n\\item{at}{ignore}\n\n\\item{labels}{ignore}\n\n\\item{...}{ignore}\n\n\\item{lon}{ignore}\n\n\\item{lat}{ignore}\n\n\\item{ndiscr}{ignore}\n\n\\item{reset}{ignore}\n\n\\item{z}{ignore}\n\n\\item{col}{ignore}\n\n\\item{breaks}{ignore}\n\n\\item{add.axis}{ignore}\n\n\\item{axes}{ignore}\n\n\\item{key.length}{ignore}\n\n\\item{logz}{ignore}\n\n\\item{lab}{ignore}\n\n\\item{cex.axis}{see \\link{par}}\n}\n\\description{\nfunctions only exported to be used internally by stars\n}\n\\keyword{internal}\n"
  },
  {
    "path": "man/summary.sfc.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sfc.R\n\\name{summary.sfc}\n\\alias{summary.sfc}\n\\title{Summarize simple feature column}\n\\usage{\n\\method{summary}{sfc}(object, ..., maxsum = 7L, maxp4s = 10L)\n}\n\\arguments{\n\\item{object}{object of class \\code{sfc}}\n\n\\item{...}{ignored}\n\n\\item{maxsum}{maximum number of classes to summarize the simple feature column to}\n\n\\item{maxp4s}{maximum number of characters to print from the PROJ string}\n}\n\\description{\nSummarize simple feature column\n}\n"
  },
  {
    "path": "man/tibble.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/tidyverse.R\n\\name{tibble}\n\\alias{tibble}\n\\alias{type_sum.sfc}\n\\alias{obj_sum.sfc}\n\\alias{pillar_shaft.sfc}\n\\title{Summarize simple feature type for tibble}\n\\usage{\ntype_sum.sfc(x, ...)\n\nobj_sum.sfc(x)\n\npillar_shaft.sfc(x, ...)\n}\n\\arguments{\n\\item{x}{object of class \\code{sfc}}\n\n\\item{...}{ignored}\n}\n\\description{\nSummarize simple feature type / item for tibble\n}\n\\details{\nsee \\link[pillar]{type_sum}\n}\n"
  },
  {
    "path": "man/tidyverse.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/tidyverse.R, R/join.R\n\\name{tidyverse}\n\\alias{tidyverse}\n\\alias{filter.sf}\n\\alias{arrange.sf}\n\\alias{group_by.sf}\n\\alias{ungroup.sf}\n\\alias{rowwise.sf}\n\\alias{mutate.sf}\n\\alias{transmute.sf}\n\\alias{select.sf}\n\\alias{rename.sf}\n\\alias{rename_with.sf}\n\\alias{slice.sf}\n\\alias{summarise.sf}\n\\alias{summarise}\n\\alias{count.sf}\n\\alias{distinct.sf}\n\\alias{gather.sf}\n\\alias{pivot_longer.sf}\n\\alias{pivot_wider.sf}\n\\alias{spread.sf}\n\\alias{sample_n.sf}\n\\alias{sample_frac.sf}\n\\alias{group_split.sf}\n\\alias{nest.sf}\n\\alias{separate.sf}\n\\alias{separate_rows.sf}\n\\alias{unite.sf}\n\\alias{unnest.sf}\n\\alias{drop_na.sf}\n\\alias{inner_join.sf}\n\\alias{left_join.sf}\n\\alias{right_join.sf}\n\\alias{full_join.sf}\n\\alias{semi_join.sf}\n\\alias{anti_join.sf}\n\\title{Tidyverse methods for sf objects}\n\\usage{\nfilter.sf(.data, ..., .dots)\n\narrange.sf(.data, ..., .dots)\n\ngroup_by.sf(.data, ..., add = FALSE)\n\nungroup.sf(x, ...)\n\nrowwise.sf(x, ...)\n\nmutate.sf(.data, ..., .dots)\n\ntransmute.sf(.data, ..., .dots)\n\nselect.sf(.data, ...)\n\nrename.sf(.data, ...)\n\nrename_with.sf(.data, .fn, .cols, ...)\n\nslice.sf(.data, ..., .dots)\n\nsummarise.sf(.data, ..., .dots, do_union = TRUE, is_coverage = FALSE)\n\ncount.sf(x, ..., wt = NULL, sort = FALSE, name = \"n\", .drop_geometry = FALSE)\n\ndistinct.sf(.data, ..., .keep_all = FALSE, exact = FALSE, par = 0)\n\ngather.sf(\n  data,\n  key,\n  value,\n  ...,\n  na.rm = FALSE,\n  convert = FALSE,\n  factor_key = FALSE\n)\n\npivot_longer.sf(\n  data,\n  cols,\n  names_to = \"name\",\n  names_prefix = NULL,\n  names_sep = NULL,\n  names_pattern = NULL,\n  names_ptypes = NULL,\n  names_transform = NULL,\n  names_repair = \"check_unique\",\n  values_to = \"value\",\n  values_drop_na = FALSE,\n  values_ptypes = NULL,\n  values_transform = NULL,\n  ...\n)\n\npivot_wider.sf(\n  data,\n  ...,\n  id_cols = NULL,\n  id_expand = FALSE,\n  names_from = name,\n  names_prefix = \"\",\n  names_sep = \"_\",\n  names_glue = NULL,\n  names_sort = FALSE,\n  names_vary = \"fastest\",\n  names_expand = FALSE,\n  names_repair = \"check_unique\",\n  values_from = value,\n  values_fill = NULL,\n  values_fn = NULL,\n  unused_fn = NULL\n)\n\nspread.sf(\n  data,\n  key,\n  value,\n  fill = NA,\n  convert = FALSE,\n  drop = TRUE,\n  sep = NULL\n)\n\nsample_n.sf(tbl, size, replace = FALSE, weight = NULL, .env = parent.frame())\n\nsample_frac.sf(\n  tbl,\n  size = 1,\n  replace = FALSE,\n  weight = NULL,\n  .env = parent.frame()\n)\n\ngroup_split.sf(.tbl, ..., .keep = TRUE)\n\nnest.sf(.data, ...)\n\nseparate.sf(\n  data,\n  col,\n  into,\n  sep = \"[^[:alnum:]]+\",\n  remove = TRUE,\n  convert = FALSE,\n  extra = \"warn\",\n  fill = \"warn\",\n  ...\n)\n\nseparate_rows.sf(data, ..., sep = \"[^[:alnum:]]+\", convert = FALSE)\n\nunite.sf(data, col, ..., sep = \"_\", remove = TRUE)\n\nunnest.sf(data, ..., .preserve = NULL)\n\ndrop_na.sf(x, ...)\n\ninner_join.sf(x, y, by = NULL, copy = FALSE, suffix = c(\".x\", \".y\"), ...)\n\nleft_join.sf(x, y, by = NULL, copy = FALSE, suffix = c(\".x\", \".y\"), ...)\n\nright_join.sf(x, y, by = NULL, copy = FALSE, suffix = c(\".x\", \".y\"), ...)\n\nfull_join.sf(x, y, by = NULL, copy = FALSE, suffix = c(\".x\", \".y\"), ...)\n\nsemi_join.sf(x, y, by = NULL, copy = FALSE, suffix = c(\".x\", \".y\"), ...)\n\nanti_join.sf(x, y, by = NULL, copy = FALSE, suffix = c(\".x\", \".y\"), ...)\n}\n\\arguments{\n\\item{.data}{data object of class \\link{sf}}\n\n\\item{...}{other arguments}\n\n\\item{.dots}{see corresponding function in package \\code{dplyr}}\n\n\\item{add}{see corresponding function in dplyr}\n\n\\item{x, y}{A pair of data frames, data frame extensions (e.g. a tibble), or\nlazy data frames (e.g. from dbplyr or dtplyr). See \\emph{Methods}, below, for\nmore details.}\n\n\\item{.fn, .cols}{see original docs}\n\n\\item{do_union}{logical; in case \\code{summary} does not create a geometry column, should geometries be created by unioning using \\link{st_union}, or simply by combining using \\link{st_combine}? Using \\link{st_union} resolves internal boundaries, but in case of unioning points, this will likely change the order of the points; see Details.}\n\n\\item{is_coverage}{logical; if \\code{do_union} is \\code{TRUE}, use an optimized algorithm for features that form a polygonal coverage (have no overlaps)}\n\n\\item{wt}{see original function docs}\n\n\\item{sort}{see original function docs}\n\n\\item{name}{see original function docs}\n\n\\item{.drop_geometry}{logical; if \\code{TRUE}, remove geometry column before computing counts}\n\n\\item{.keep_all}{see corresponding function in dplyr}\n\n\\item{exact}{logical; if \\code{TRUE} use \\link{st_equals_exact} for geometry comparisons}\n\n\\item{par}{numeric; passed on to \\link{st_equals_exact}}\n\n\\item{data}{see original function docs}\n\n\\item{key}{see original function docs}\n\n\\item{value}{see original function docs}\n\n\\item{na.rm}{see original function docs}\n\n\\item{convert}{see \\link[tidyr]{separate_rows}}\n\n\\item{factor_key}{see original function docs}\n\n\\item{cols}{see original function docs}\n\n\\item{names_to, names_pattern, names_ptypes, names_transform}{see \\code{\\link[tidyr:pivot_longer]{tidyr::pivot_longer()}}}\n\n\\item{names_prefix, names_sep, names_repair}{see original function docs.}\n\n\\item{values_to, values_drop_na, values_ptypes, values_transform}{See \\code{\\link[tidyr:pivot_longer]{tidyr::pivot_longer()}}}\n\n\\item{id_cols, id_expand, names_from, names_sort, names_glue, names_vary, names_expand}{see \\code{\\link[tidyr:pivot_wider]{tidyr::pivot_wider()}}}\n\n\\item{values_from, values_fill, values_fn, unused_fn}{see \\code{\\link[tidyr:pivot_wider]{tidyr::pivot_wider()}}}\n\n\\item{fill}{see original function docs}\n\n\\item{drop}{see original function docs}\n\n\\item{sep}{see \\link[tidyr]{separate_rows}}\n\n\\item{tbl}{see original function docs}\n\n\\item{size}{see original function docs}\n\n\\item{replace}{see original function docs}\n\n\\item{weight}{see original function docs}\n\n\\item{.env}{see original function docs}\n\n\\item{.tbl}{see original function docs}\n\n\\item{.keep}{see original function docs}\n\n\\item{col}{see \\link[tidyr]{separate}}\n\n\\item{into}{see \\link[tidyr]{separate}}\n\n\\item{remove}{see \\link[tidyr]{separate}}\n\n\\item{extra}{see \\link[tidyr]{separate}}\n\n\\item{.preserve}{see \\link[tidyr:nest]{unnest}}\n\n\\item{by}{A join specification created with \\code{\\link[dplyr:join_by]{join_by()}}, or a character\nvector of variables to join by.\n\nIf \\code{NULL}, the default, \\verb{*_join()} will perform a natural join, using all\nvariables in common across \\code{x} and \\code{y}. A message lists the variables so\nthat you can check they're correct; suppress the message by supplying \\code{by}\nexplicitly.\n\nTo join on different variables between \\code{x} and \\code{y}, use a \\code{\\link[dplyr:join_by]{join_by()}}\nspecification. For example, \\code{join_by(a == b)} will match \\code{x$a} to \\code{y$b}.\n\nTo join by multiple variables, use a \\code{\\link[dplyr:join_by]{join_by()}} specification with\nmultiple expressions. For example, \\code{join_by(a == b, c == d)} will match\n\\code{x$a} to \\code{y$b} and \\code{x$c} to \\code{y$d}. If the column names are the same between\n\\code{x} and \\code{y}, you can shorten this by listing only the variable names, like\n\\code{join_by(a, c)}.\n\n\\code{\\link[dplyr:join_by]{join_by()}} can also be used to perform inequality, rolling, and overlap\njoins. See the documentation at \\link[dplyr:join_by]{?join_by} for details on\nthese types of joins.\n\nFor simple equality joins, you can alternatively specify a character vector\nof variable names to join by. For example, \\code{by = c(\"a\", \"b\")} joins \\code{x$a}\nto \\code{y$a} and \\code{x$b} to \\code{y$b}. If variable names differ between \\code{x} and \\code{y},\nuse a named character vector like \\code{by = c(\"x_a\" = \"y_a\", \"x_b\" = \"y_b\")}.\n\nTo perform a cross-join, generating all combinations of \\code{x} and \\code{y}, see\n\\code{\\link[dplyr:cross_join]{cross_join()}}.}\n\n\\item{copy}{If \\code{x} and \\code{y} are not from the same data source,\nand \\code{copy} is \\code{TRUE}, then \\code{y} will be copied into the\nsame src as \\code{x}.  This allows you to join tables across srcs, but\nit is a potentially expensive operation so you must opt into it.}\n\n\\item{suffix}{If there are non-joined duplicate variables in \\code{x} and\n\\code{y}, these suffixes will be added to the output to disambiguate them.\nShould be a character vector of length 2.}\n}\n\\value{\nan object of class \\link{sf}\n}\n\\description{\nTidyverse methods for sf objects. Geometries are sticky, use \\link{as.data.frame} to let \\code{dplyr}'s own methods drop them.\nUse these methods after loading the tidyverse package with the generic (or after loading package tidyverse).\n}\n\\details{\n\\code{select} keeps the geometry regardless whether it is selected or not; to deselect it, first pipe through \\code{as.data.frame} to let dplyr's own \\code{select} drop it.\n\nIn case one or more of the arguments (expressions) in the \\code{summarise} call creates a geometry list-column, the first of these will be the (active) geometry of the returned object. If this is not the case, a geometry column is created, depending on the value of \\code{do_union}.\n\nIn case \\code{do_union} is \\code{FALSE}, \\code{summarise} will simply combine geometries using \\link{c.sfg}. When polygons sharing a boundary are combined, this leads to geometries that are invalid; see for instance \\url{https://github.com/r-spatial/sf/issues/681}.\n\nThe functions \\code{count} and \\code{tally} drop all geometries.\nFor counting geometries use \\code{summarise(.data, n = n(), .by = \"geometry\")}.\n\n\\code{distinct} gives distinct records for which all attributes and geometries are distinct; \\link{st_equals} is used to find out which geometries are distinct.\n\n\\code{nest} assumes that a simple feature geometry list-column was among the columns that were nested.\n}\n\\examples{\nif (require(dplyr, quietly = TRUE)) {\n nc = read_sf(system.file(\"shape/nc.shp\", package=\"sf\"))\n nc |> filter(AREA > .1) |> plot()\n # plot 10 smallest counties in grey:\n st_geometry(nc) |> plot()\n nc |> select(AREA) |> arrange(AREA) |> slice(1:10) |> plot(add = TRUE, col = 'grey')\n title(\"the ten counties with smallest area\")\n nc2 <- nc |> mutate(area10 = AREA/10)\n nc |> slice(1:2)\n}\n# plot 10 smallest counties in grey:\nif (require(dplyr, quietly = TRUE)) {\n st_geometry(nc) |> plot()\n nc |> select(AREA) |> arrange(AREA) |> slice(1:10) |> plot(add = TRUE, col = 'grey')\n title(\"the ten counties with smallest area\")\n}\nif (require(dplyr, quietly = TRUE)) {\n nc$area_cl = cut(nc$AREA, c(0, .1, .12, .15, .25))\n nc |> group_by(area_cl) |> class()\n}\nif (require(dplyr, quietly = TRUE)) {\n nc2 <- nc |> mutate(area10 = AREA/10)\n}\nif (require(dplyr, quietly = TRUE)) {\n nc |> transmute(AREA = AREA/10) |> class()\n}\nif (require(dplyr, quietly = TRUE)) {\n nc |> select(SID74, SID79) |> names()\n nc |> select(SID74, SID79) |> class()\n}\nif (require(dplyr, quietly = TRUE)) {\n nc2 <- nc |> rename(area = AREA)\n}\nif (require(dplyr, quietly = TRUE)) {\n nc |> slice(1:2)\n}\nif (require(dplyr, quietly = TRUE)) {\n nc$area_cl = cut(nc$AREA, c(0, .1, .12, .15, .25))\n nc.g <- nc |> group_by(area_cl)\n nc.g |> summarise(mean(AREA))\n nc.g |> summarise(mean(AREA)) |> plot(col = grey(3:6 / 7))\n nc |> as.data.frame() |> summarise(mean(AREA))\n # counting geometries (after duplicating each row):\n nc.dupl <- nc[rep(seq_along(nc), each = 2), ]\n nc.dupl |> summarise(n = n(), .by = \"geometry\")\n}\nif (require(dplyr, quietly = TRUE)) {\n  nc$area_cl <- cut(nc$AREA, c(0, .1, .12, .15, .25))\n  nc |> count(area_cl, .drop_geometry = TRUE)\n}\nif (require(dplyr, quietly = TRUE)) {\n nc[c(1:100, 1:10), ] |> distinct() |> nrow()\n}\nif (require(tidyr, quietly = TRUE) && require(dplyr, quietly = TRUE) && \"geometry\" \\%in\\% names(nc)) {\n nc |> select(SID74, SID79) |> gather(\"VAR\", \"SID\", -geometry) |> summary()\n}\nif (require(tidyr, quietly = TRUE) && require(dplyr, quietly = TRUE) && \"geometry\" \\%in\\% names(nc)) {\n nc$row = 1:100 # needed for spread to work\n nc |> select(SID74, SID79, geometry, row) |>\n\tgather(\"VAR\", \"SID\", -geometry, -row) |>\n\tspread(VAR, SID) |> head()\n}\nif (require(tidyr, quietly = TRUE) && require(dplyr, quietly = TRUE)) {\n storms.sf = st_as_sf(storms, coords = c(\"long\", \"lat\"), crs = 4326)\n x <- storms.sf |> group_by(name, year) |> nest()\n trs = lapply(x$data, function(tr) st_cast(st_combine(tr), \"LINESTRING\")[[1]]) |>\n    st_sfc(crs = 4326)\n trs.sf = st_sf(x[,1:2], trs)\n plot(trs.sf[\"year\"], axes = TRUE)\n}\n}\n"
  },
  {
    "path": "man/transform.sf.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/sf.R\n\\name{transform.sf}\n\\alias{transform.sf}\n\\title{transform method for sf objects}\n\\usage{\n\\method{transform}{sf}(`_data`, ...)\n}\n\\arguments{\n\\item{_data}{object of class \\code{sf}}\n\n\\item{...}{Further arguments of the form \\code{new_variable = expression}}\n}\n\\description{\nCan be used to create or modify attribute variables; for transforming geometries see\n\\link{st_transform}, and all other functions starting with \\code{st_}.\n}\n\\examples{\na = data.frame(x1 = 1:3, x2 = 5:7)\nst_geometry(a) = st_sfc(st_point(c(0,0)), st_point(c(1,1)), st_point(c(2,2)))\ntransform(a, x1_sq = x1^2)\ntransform(a, x1_x2 = x1*x2)\n}\n"
  },
  {
    "path": "man/valid.Rd",
    "content": "% Generated by roxygen2: do not edit by hand\n% Please edit documentation in R/valid.R\n\\name{valid}\n\\alias{valid}\n\\alias{st_is_valid}\n\\alias{st_is_valid.sfc}\n\\alias{st_is_valid.sf}\n\\alias{st_is_valid.sfg}\n\\alias{st_make_valid}\n\\alias{st_make_valid.sfg}\n\\alias{st_make_valid.sfc}\n\\title{Check validity or make an invalid geometry valid}\n\\usage{\nst_is_valid(x, ...)\n\n\\method{st_is_valid}{sfc}(x, ..., NA_on_exception = TRUE, reason = FALSE)\n\n\\method{st_is_valid}{sf}(x, ...)\n\n\\method{st_is_valid}{sfg}(x, ...)\n\nst_make_valid(x, ...)\n\n\\method{st_make_valid}{sfg}(x, ...)\n\n\\method{st_make_valid}{sfc}(\n  x,\n  ...,\n  oriented = FALSE,\n  s2_options = s2::s2_options(snap = s2::s2_snap_precision(1e+07), ...),\n  geos_method = \"valid_structure\",\n  geos_keep_collapsed = TRUE\n)\n}\n\\arguments{\n\\item{x}{object of class \\code{sfg}, \\code{sfc} or \\code{sf}}\n\n\\item{...}{passed on to \\link[s2]{s2_options}}\n\n\\item{NA_on_exception}{logical; if TRUE, for polygons that would otherwise raise a GEOS error (exception, e.g. for a POLYGON having more than zero but less than 4 points, or a LINESTRING having one point) return an \\code{NA} rather than raising an error, and suppress warning messages (e.g. about self-intersection); if FALSE, regular GEOS errors and warnings will be emitted.}\n\n\\item{reason}{logical; if \\code{TRUE}, return a character with, for each geometry, the reason for invalidity, \\code{NA} on exception, or \\code{\"Valid Geometry\"} otherwise.}\n\n\\item{oriented}{logical; only relevant if \\code{st_is_longlat(x)} is \\code{TRUE}; see \\link{s2}}\n\n\\item{s2_options}{only relevant if \\code{st_is_longlat(x)} is \\code{TRUE}; options for \\link[s2]{s2_rebuild}, see \\link[s2]{s2_options} and Details.}\n\n\\item{geos_method}{character; either \"valid_linework\" (Original method, combines all rings into a set of noded lines and then extracts valid polygons from that linework) or \"valid_structure\" (Structured method, first makes all rings valid then merges shells and subtracts holes from shells to generate valid result. Assumes that holes and shells are correctly categorized.) (requires GEOS >= 3.10.1)}\n\n\\item{geos_keep_collapsed}{logical; When this parameter is not set to \\code{FALSE}, the \"valid_structure\" method will keep any component that has collapsed into a lower dimensionality. For example, a ring collapsing to a line, or a line collapsing to a point (requires GEOS >= 3.10.1)}\n}\n\\value{\n\\code{st_is_valid} returns a logical vector indicating for each geometries of \\code{x} whether it is valid. \\code{st_make_valid} returns an object with a topologically valid geometry.\n\nObject of the same class as \\code{x}\n}\n\\description{\nChecks whether a geometry is valid, or makes an invalid geometry valid\n}\n\\details{\nFor projected geometries, \\code{st_make_valid} uses the \\code{lwgeom_makevalid} method also used by the PostGIS command \\code{ST_makevalid} if the GEOS version linked to is smaller than 3.8.0, and otherwise the version shipped in GEOS; for geometries having ellipsoidal coordinates \\code{s2::s2_rebuild} is being used.\n\nif \\code{s2_options} is not specified and \\code{x} has a non-zero precision set, then this precision value will be used as the value in \\code{s2_snap_precision}, passed on to \\code{s2_options}, rather than the 1e7 default.\n}\n\\examples{\np1 = st_as_sfc(\"POLYGON((0 0, 0 10, 10 0, 10 10, 0 0))\")\nst_is_valid(p1)\nst_is_valid(st_sfc(st_point(0:1), p1[[1]]), reason = TRUE)\nlibrary(sf)\nx = st_sfc(st_polygon(list(rbind(c(0,0),c(0.5,0),c(0.5,0.5),c(0.5,0),c(1,0),c(1,1),c(0,1),c(0,0)))))\nsuppressWarnings(st_is_valid(x))\ny = st_make_valid(x)\nst_is_valid(y)\ny |> st_cast()\n}\n"
  },
  {
    "path": "sf.Rproj",
    "content": "Version: 1.0\n\nRestoreWorkspace: No\nSaveWorkspace: No\nAlwaysSaveHistory: Default\n\nEnableCodeIndexing: Yes\nUseSpacesForTab: No\nNumSpacesForTab: 4\nEncoding: UTF-8\n\nRnwWeave: knitr\nLaTeX: XeLaTeX\n\nAutoAppendNewline: Yes\n\nBuildType: Package\nPackageUseDevtools: Yes\nPackageInstallArgs: --no-multiarch --with-keep.source\nPackageRoxygenize: rd,collate,namespace\n\nSpellingDictionary: en_US\n"
  },
  {
    "path": "src/Makevars.in",
    "content": "PKG_CPPFLAGS=@PKG_CPPFLAGS@\nPKG_LIBS=@PKG_LIBS@\n"
  },
  {
    "path": "src/Makevars.ucrt",
    "content": "PKG_CPPFLAGS = \\\n\t-DHAVE_PROJ_H\n\nifeq (,$(shell pkg-config --version 2>/dev/null))\n  LIBSHARPYUV = $(or $(and $(wildcard $(R_TOOLS_SOFT)/lib/libsharpyuv.a),-lsharpyuv),)\n  PKG_LIBS =  \\\n-fopenmp -lgdal -larmadillo -lopenblas -lgfortran -lquadmath -lpq -lpgcommon -lpgport -lodbc32 -lodbccp32 -lblosc -lkea -lhdf5_cpp -lhdf5 -lpoppler -llcms2 -lfreetype -lharfbuzz -lfreetype -llz4 -lpcre2-8 -lxml2 -lopenjp2 -lnetcdf -lmysqlclient -lspatialite -lgeos_c -lgeos -lminizip -lgeos -ljson-c -lgta -lfreexl -lexpat -lssl -lpsapi -lgif -lmfhdf -lhdf5_hl -lcrypto -lportablexdr -ldf -lhdf5 -lsz -lpng16 -lpng -lpoppler -llcms2 -lfreetype -lharfbuzz -lfreetype -llz4 -lpcre2-8 -lpcre -lcurl -lbcrypt -lrtmp -lssl -lssh2 -lidn2 -lunistring -liconv -lgcrypt -lcrypto -lgpg-error -lws2_32 -ltiff -llzma -ljpeg -lz -lcfitsio -lzstd -lwebpdecoder -lwebp $(LIBSHARPYUV) -lsbml-static -lgeotiff -lproj -lsqlite3 -lbz2 -lcrypt32 -lwldap32 -lsecur32\nelse\n  PKG_LIBS = $(shell pkg-config --libs gdal geos proj)\nendif\n\nall: clean winlibs\n\nwinlibs:\n\tcp -r \"$(R_TOOLS_SOFT)/share/gdal\" ../inst/\n\tcp -r \"$(R_TOOLS_SOFT)/share/proj\" ../inst/\n\nclean:\n\trm -f $(SHLIB) $(OBJECTS)\n\n.PHONY: all winlibs clean\n"
  },
  {
    "path": "src/Makevars.win",
    "content": "VERSION = 3.4.1\nRWINLIB = ../windows/gdal3-$(VERSION)\nTARGET = lib$(subst gcc,,$(COMPILED_BY))$(R_ARCH)\n\nPKG_CPPFLAGS =\\\n\t-I$(RWINLIB)/include \\\n\t-DHAVE_PROJ_H\n\nPKG_LIBS = \\\n\t-L$(RWINLIB)/$(TARGET) \\\n\t-L$(RWINLIB)/lib$(R_ARCH) \\\n\t-lgdal -lsqlite3 -lspatialite -lproj -lgeos_c -lgeos  \\\n\t-ljson-c -lnetcdf -lmariadbclient -lpq -lpgport -lpgcommon \\\n\t-lwebp -lcurl -lssh2 -lssl \\\n\t-lhdf5_hl -lhdf5 -lexpat -lfreexl -lcfitsio \\\n\t-lmfhdf -lhdf -lxdr -lpcre \\\n\t-lopenjp2 -ljasper -lpng -ljpeg -ltiff -lgeotiff -lgif -lxml2 -llzma -lz -lzstd \\\n\t-lodbc32 -lodbccp32 -liconv -lpsapi -lwldap32 -lsecur32 -lgdi32 -lnormaliz \\\n\t-lcrypto -lcrypt32 -lws2_32 -lshlwapi -lbcrypt\n\nall: clean winlibs\n\nwinlibs:\n\tmkdir -p ../inst\n\t\"${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe\" --vanilla \"../tools/winlibs.R\" $(VERSION)\n\tcp -r \"$(RWINLIB)/share/gdal\" ../inst/\n\tcp -r \"$(RWINLIB)/share/proj\" ../inst/\n\nclean:\n\trm -f $(SHLIB) $(OBJECTS)\n\n.PHONY: all winlibs clean\n"
  },
  {
    "path": "src/RcppExports.cpp",
    "content": "// Generated by using Rcpp::compileAttributes() -> do not edit by hand\n// Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393\n\n#include \"../inst/include/sf.h\"\n#include <Rcpp.h>\n#include <string>\n#include <set>\n\nusing namespace Rcpp;\n\n#ifdef RCPP_USE_GLOBAL_ROSTREAM\nRcpp::Rostream<true>&  Rcpp::Rcout = Rcpp::Rcpp_cout_get();\nRcpp::Rostream<false>& Rcpp::Rcerr = Rcpp::Rcpp_cerr_get();\n#endif\n\n// CPL_get_bbox\nRcpp::NumericVector CPL_get_bbox(Rcpp::List sf, int depth);\nRcppExport SEXP _sf_CPL_get_bbox(SEXP sfSEXP, SEXP depthSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sf(sfSEXP);\n    Rcpp::traits::input_parameter< int >::type depth(depthSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_get_bbox(sf, depth));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdal_init\nvoid CPL_gdal_init();\nRcppExport SEXP _sf_CPL_gdal_init() {\nBEGIN_RCPP\n    CPL_gdal_init();\n    return R_NilValue;\nEND_RCPP\n}\n// CPL_gdal_cleanup_all\nvoid CPL_gdal_cleanup_all();\nRcppExport SEXP _sf_CPL_gdal_cleanup_all() {\nBEGIN_RCPP\n    CPL_gdal_cleanup_all();\n    return R_NilValue;\nEND_RCPP\n}\n// CPL_gdal_version\nconst char* CPL_gdal_version(const char* what);\nRcppExport SEXP _sf_CPL_gdal_version(SEXP whatSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< const char* >::type what(whatSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdal_version(what));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_crs_parameters\nRcpp::List CPL_crs_parameters(Rcpp::List crs);\nRcppExport SEXP _sf_CPL_crs_parameters(SEXP crsSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type crs(crsSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_crs_parameters(crs));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_crs_equivalent\nRcpp::LogicalVector CPL_crs_equivalent(Rcpp::List crs1, Rcpp::List crs2);\nRcppExport SEXP _sf_CPL_crs_equivalent(SEXP crs1SEXP, SEXP crs2SEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type crs1(crs1SEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type crs2(crs2SEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_crs_equivalent(crs1, crs2));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_crs_from_input\nRcpp::List CPL_crs_from_input(Rcpp::CharacterVector input);\nRcppExport SEXP _sf_CPL_crs_from_input(SEXP inputSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type input(inputSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_crs_from_input(input));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_roundtrip\nRcpp::List CPL_roundtrip(Rcpp::List sfc);\nRcppExport SEXP _sf_CPL_roundtrip(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_roundtrip(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_circularstring_to_linestring\nRcpp::List CPL_circularstring_to_linestring(Rcpp::List sfc);\nRcppExport SEXP _sf_CPL_circularstring_to_linestring(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_circularstring_to_linestring(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_multisurface_to_multipolygon\nRcpp::List CPL_multisurface_to_multipolygon(Rcpp::List sfc);\nRcppExport SEXP _sf_CPL_multisurface_to_multipolygon(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_multisurface_to_multipolygon(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_compoundcurve_to_linear\nRcpp::List CPL_compoundcurve_to_linear(Rcpp::List sfc);\nRcppExport SEXP _sf_CPL_compoundcurve_to_linear(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_compoundcurve_to_linear(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_curve_to_linestring\nRcpp::List CPL_curve_to_linestring(Rcpp::List sfc);\nRcppExport SEXP _sf_CPL_curve_to_linestring(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_curve_to_linestring(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_can_transform\nRcpp::LogicalVector CPL_can_transform(Rcpp::List src, Rcpp::List dst);\nRcppExport SEXP _sf_CPL_can_transform(SEXP srcSEXP, SEXP dstSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type src(srcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type dst(dstSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_can_transform(src, dst));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_transform\nRcpp::List CPL_transform(Rcpp::List sfc, Rcpp::List crs, Rcpp::NumericVector AOI, Rcpp::CharacterVector pipeline, bool reverse, double desired_accuracy, bool allow_ballpark);\nRcppExport SEXP _sf_CPL_transform(SEXP sfcSEXP, SEXP crsSEXP, SEXP AOISEXP, SEXP pipelineSEXP, SEXP reverseSEXP, SEXP desired_accuracySEXP, SEXP allow_ballparkSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type crs(crsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::NumericVector >::type AOI(AOISEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type pipeline(pipelineSEXP);\n    Rcpp::traits::input_parameter< bool >::type reverse(reverseSEXP);\n    Rcpp::traits::input_parameter< double >::type desired_accuracy(desired_accuracySEXP);\n    Rcpp::traits::input_parameter< bool >::type allow_ballpark(allow_ballparkSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_transform(sfc, crs, AOI, pipeline, reverse, desired_accuracy, allow_ballpark));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_transform_bounds\nRcpp::NumericVector CPL_transform_bounds(Rcpp::NumericVector bb, Rcpp::List crs_dst, int densify_pts);\nRcppExport SEXP _sf_CPL_transform_bounds(SEXP bbSEXP, SEXP crs_dstSEXP, SEXP densify_ptsSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::NumericVector >::type bb(bbSEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type crs_dst(crs_dstSEXP);\n    Rcpp::traits::input_parameter< int >::type densify_pts(densify_ptsSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_transform_bounds(bb, crs_dst, densify_pts));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_wrap_dateline\nRcpp::List CPL_wrap_dateline(Rcpp::List sfc, Rcpp::CharacterVector opt, bool quiet);\nRcppExport SEXP _sf_CPL_wrap_dateline(SEXP sfcSEXP, SEXP optSEXP, SEXP quietSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type opt(optSEXP);\n    Rcpp::traits::input_parameter< bool >::type quiet(quietSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_wrap_dateline(sfc, opt, quiet));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_get_gdal_drivers\nRcpp::List CPL_get_gdal_drivers(int dummy);\nRcppExport SEXP _sf_CPL_get_gdal_drivers(SEXP dummySEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< int >::type dummy(dummySEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_get_gdal_drivers(dummy));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_sfc_from_wkt\nRcpp::List CPL_sfc_from_wkt(Rcpp::CharacterVector wkt);\nRcppExport SEXP _sf_CPL_sfc_from_wkt(SEXP wktSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type wkt(wktSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_sfc_from_wkt(wkt));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdal_with_geos\nRcpp::LogicalVector CPL_gdal_with_geos();\nRcppExport SEXP _sf_CPL_gdal_with_geos() {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    rcpp_result_gen = Rcpp::wrap(CPL_gdal_with_geos());\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_axis_order_authority_compliant\nRcpp::LogicalVector CPL_axis_order_authority_compliant(Rcpp::LogicalVector authority_compliant);\nRcppExport SEXP _sf_CPL_axis_order_authority_compliant(SEXP authority_compliantSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::LogicalVector >::type authority_compliant(authority_compliantSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_axis_order_authority_compliant(authority_compliant));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_compressors\nRcpp::List CPL_compressors();\nRcppExport SEXP _sf_CPL_compressors() {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    rcpp_result_gen = Rcpp::wrap(CPL_compressors());\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_area\nRcpp::NumericVector CPL_area(Rcpp::List sfc);\nRcppExport SEXP _sf_CPL_area(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_area(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdal_dimension\nRcpp::IntegerVector CPL_gdal_dimension(Rcpp::List sfc, bool NA_if_empty);\nRcppExport SEXP _sf_CPL_gdal_dimension(SEXP sfcSEXP, SEXP NA_if_emptySEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    Rcpp::traits::input_parameter< bool >::type NA_if_empty(NA_if_emptySEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdal_dimension(sfc, NA_if_empty));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_length\nRcpp::NumericVector CPL_length(Rcpp::List sfc);\nRcppExport SEXP _sf_CPL_length(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_length(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdal_segmentize\nRcpp::List CPL_gdal_segmentize(Rcpp::List sfc, double dfMaxLength);\nRcppExport SEXP _sf_CPL_gdal_segmentize(SEXP sfcSEXP, SEXP dfMaxLengthSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    Rcpp::traits::input_parameter< double >::type dfMaxLength(dfMaxLengthSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdal_segmentize(sfc, dfMaxLength));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdal_linestring_sample\nRcpp::List CPL_gdal_linestring_sample(Rcpp::List sfc, Rcpp::List distLst);\nRcppExport SEXP _sf_CPL_gdal_linestring_sample(SEXP sfcSEXP, SEXP distLstSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type distLst(distLstSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdal_linestring_sample(sfc, distLst));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_get_layers\nRcpp::List CPL_get_layers(Rcpp::CharacterVector datasource, Rcpp::CharacterVector options, bool do_count);\nRcppExport SEXP _sf_CPL_get_layers(SEXP datasourceSEXP, SEXP optionsSEXP, SEXP do_countSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type datasource(datasourceSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< bool >::type do_count(do_countSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_get_layers(datasource, options, do_count));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_read_ogr\nRcpp::List CPL_read_ogr(Rcpp::CharacterVector datasource, Rcpp::CharacterVector layer, Rcpp::CharacterVector query, Rcpp::CharacterVector options, bool quiet, Rcpp::NumericVector toTypeUser, Rcpp::CharacterVector fid_column_name, Rcpp::CharacterVector drivers, Rcpp::CharacterVector wkt_filter, bool promote_to_multi, bool int64_as_string, bool dsn_exists, bool dsn_isdb, int width);\nRcppExport SEXP _sf_CPL_read_ogr(SEXP datasourceSEXP, SEXP layerSEXP, SEXP querySEXP, SEXP optionsSEXP, SEXP quietSEXP, SEXP toTypeUserSEXP, SEXP fid_column_nameSEXP, SEXP driversSEXP, SEXP wkt_filterSEXP, SEXP promote_to_multiSEXP, SEXP int64_as_stringSEXP, SEXP dsn_existsSEXP, SEXP dsn_isdbSEXP, SEXP widthSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type datasource(datasourceSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type layer(layerSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type query(querySEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< bool >::type quiet(quietSEXP);\n    Rcpp::traits::input_parameter< Rcpp::NumericVector >::type toTypeUser(toTypeUserSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type fid_column_name(fid_column_nameSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type drivers(driversSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type wkt_filter(wkt_filterSEXP);\n    Rcpp::traits::input_parameter< bool >::type promote_to_multi(promote_to_multiSEXP);\n    Rcpp::traits::input_parameter< bool >::type int64_as_string(int64_as_stringSEXP);\n    Rcpp::traits::input_parameter< bool >::type dsn_exists(dsn_existsSEXP);\n    Rcpp::traits::input_parameter< bool >::type dsn_isdb(dsn_isdbSEXP);\n    Rcpp::traits::input_parameter< int >::type width(widthSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_read_ogr(datasource, layer, query, options, quiet, toTypeUser, fid_column_name, drivers, wkt_filter, promote_to_multi, int64_as_string, dsn_exists, dsn_isdb, width));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_read_gdal_stream\nRcpp::List CPL_read_gdal_stream(Rcpp::RObject stream_xptr, Rcpp::CharacterVector datasource, Rcpp::CharacterVector layer, Rcpp::CharacterVector query, Rcpp::CharacterVector options, bool quiet, Rcpp::CharacterVector drivers, Rcpp::CharacterVector wkt_filter, bool dsn_exists, bool dsn_isdb, Rcpp::CharacterVector fid_column, int width);\nRcppExport SEXP _sf_CPL_read_gdal_stream(SEXP stream_xptrSEXP, SEXP datasourceSEXP, SEXP layerSEXP, SEXP querySEXP, SEXP optionsSEXP, SEXP quietSEXP, SEXP driversSEXP, SEXP wkt_filterSEXP, SEXP dsn_existsSEXP, SEXP dsn_isdbSEXP, SEXP fid_columnSEXP, SEXP widthSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::RObject >::type stream_xptr(stream_xptrSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type datasource(datasourceSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type layer(layerSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type query(querySEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< bool >::type quiet(quietSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type drivers(driversSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type wkt_filter(wkt_filterSEXP);\n    Rcpp::traits::input_parameter< bool >::type dsn_exists(dsn_existsSEXP);\n    Rcpp::traits::input_parameter< bool >::type dsn_isdb(dsn_isdbSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type fid_column(fid_columnSEXP);\n    Rcpp::traits::input_parameter< int >::type width(widthSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_read_gdal_stream(stream_xptr, datasource, layer, query, options, quiet, drivers, wkt_filter, dsn_exists, dsn_isdb, fid_column, width));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdalinfo\nRcpp::CharacterVector CPL_gdalinfo(Rcpp::CharacterVector obj, Rcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector co);\nRcppExport SEXP _sf_CPL_gdalinfo(SEXP objSEXP, SEXP optionsSEXP, SEXP ooSEXP, SEXP coSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type obj(objSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type oo(ooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type co(coSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdalinfo(obj, options, oo, co));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_ogrinfo\nRcpp::CharacterVector CPL_ogrinfo(Rcpp::CharacterVector obj, Rcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector co, bool read_only);\nRcppExport SEXP _sf_CPL_ogrinfo(SEXP objSEXP, SEXP optionsSEXP, SEXP ooSEXP, SEXP coSEXP, SEXP read_onlySEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type obj(objSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type oo(ooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type co(coSEXP);\n    Rcpp::traits::input_parameter< bool >::type read_only(read_onlySEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_ogrinfo(obj, options, oo, co, read_only));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdaladdo\nRcpp::LogicalVector CPL_gdaladdo(Rcpp::CharacterVector obj, Rcpp::CharacterVector method, Rcpp::IntegerVector overviews, Rcpp::IntegerVector bands, Rcpp::CharacterVector oo, Rcpp::CharacterVector co, bool clean, bool read_only);\nRcppExport SEXP _sf_CPL_gdaladdo(SEXP objSEXP, SEXP methodSEXP, SEXP overviewsSEXP, SEXP bandsSEXP, SEXP ooSEXP, SEXP coSEXP, SEXP cleanSEXP, SEXP read_onlySEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type obj(objSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type method(methodSEXP);\n    Rcpp::traits::input_parameter< Rcpp::IntegerVector >::type overviews(overviewsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::IntegerVector >::type bands(bandsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type oo(ooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type co(coSEXP);\n    Rcpp::traits::input_parameter< bool >::type clean(cleanSEXP);\n    Rcpp::traits::input_parameter< bool >::type read_only(read_onlySEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdaladdo(obj, method, overviews, bands, oo, co, clean, read_only));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdalwarp\nRcpp::LogicalVector CPL_gdalwarp(Rcpp::CharacterVector src, Rcpp::CharacterVector dst, Rcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector doo, Rcpp::CharacterVector co, bool quiet, bool overwrite);\nRcppExport SEXP _sf_CPL_gdalwarp(SEXP srcSEXP, SEXP dstSEXP, SEXP optionsSEXP, SEXP ooSEXP, SEXP dooSEXP, SEXP coSEXP, SEXP quietSEXP, SEXP overwriteSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type src(srcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type dst(dstSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type oo(ooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type doo(dooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type co(coSEXP);\n    Rcpp::traits::input_parameter< bool >::type quiet(quietSEXP);\n    Rcpp::traits::input_parameter< bool >::type overwrite(overwriteSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdalwarp(src, dst, options, oo, doo, co, quiet, overwrite));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdalrasterize\nRcpp::LogicalVector CPL_gdalrasterize(Rcpp::CharacterVector src, Rcpp::CharacterVector dst, Rcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector doo, Rcpp::CharacterVector co, bool overwrite, bool quiet);\nRcppExport SEXP _sf_CPL_gdalrasterize(SEXP srcSEXP, SEXP dstSEXP, SEXP optionsSEXP, SEXP ooSEXP, SEXP dooSEXP, SEXP coSEXP, SEXP overwriteSEXP, SEXP quietSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type src(srcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type dst(dstSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type oo(ooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type doo(dooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type co(coSEXP);\n    Rcpp::traits::input_parameter< bool >::type overwrite(overwriteSEXP);\n    Rcpp::traits::input_parameter< bool >::type quiet(quietSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdalrasterize(src, dst, options, oo, doo, co, overwrite, quiet));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdaltranslate\nRcpp::LogicalVector CPL_gdaltranslate(Rcpp::CharacterVector src, Rcpp::CharacterVector dst, Rcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector co, bool quiet);\nRcppExport SEXP _sf_CPL_gdaltranslate(SEXP srcSEXP, SEXP dstSEXP, SEXP optionsSEXP, SEXP ooSEXP, SEXP coSEXP, SEXP quietSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type src(srcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type dst(dstSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type oo(ooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type co(coSEXP);\n    Rcpp::traits::input_parameter< bool >::type quiet(quietSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdaltranslate(src, dst, options, oo, co, quiet));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdalfootprint\nRcpp::LogicalVector CPL_gdalfootprint(Rcpp::CharacterVector src, Rcpp::CharacterVector dst, Rcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector co, bool quiet);\nRcppExport SEXP _sf_CPL_gdalfootprint(SEXP srcSEXP, SEXP dstSEXP, SEXP optionsSEXP, SEXP ooSEXP, SEXP coSEXP, SEXP quietSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type src(srcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type dst(dstSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type oo(ooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type co(coSEXP);\n    Rcpp::traits::input_parameter< bool >::type quiet(quietSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdalfootprint(src, dst, options, oo, co, quiet));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdalvectortranslate\nRcpp::LogicalVector CPL_gdalvectortranslate(Rcpp::CharacterVector src, Rcpp::CharacterVector dst, Rcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector doo, Rcpp::CharacterVector co, bool quiet);\nRcppExport SEXP _sf_CPL_gdalvectortranslate(SEXP srcSEXP, SEXP dstSEXP, SEXP optionsSEXP, SEXP ooSEXP, SEXP dooSEXP, SEXP coSEXP, SEXP quietSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type src(srcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type dst(dstSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type oo(ooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type doo(dooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type co(coSEXP);\n    Rcpp::traits::input_parameter< bool >::type quiet(quietSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdalvectortranslate(src, dst, options, oo, doo, co, quiet));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdalbuildvrt\nRcpp::LogicalVector CPL_gdalbuildvrt(Rcpp::CharacterVector src, Rcpp::CharacterVector dst, Rcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector co, bool quiet);\nRcppExport SEXP _sf_CPL_gdalbuildvrt(SEXP srcSEXP, SEXP dstSEXP, SEXP optionsSEXP, SEXP ooSEXP, SEXP coSEXP, SEXP quietSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type src(srcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type dst(dstSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type oo(ooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type co(coSEXP);\n    Rcpp::traits::input_parameter< bool >::type quiet(quietSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdalbuildvrt(src, dst, options, oo, co, quiet));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdaldemprocessing\nRcpp::LogicalVector CPL_gdaldemprocessing(Rcpp::CharacterVector src, Rcpp::CharacterVector dst, Rcpp::CharacterVector options, Rcpp::CharacterVector processing, Rcpp::CharacterVector colorfilename, Rcpp::CharacterVector oo, Rcpp::CharacterVector co, bool quiet);\nRcppExport SEXP _sf_CPL_gdaldemprocessing(SEXP srcSEXP, SEXP dstSEXP, SEXP optionsSEXP, SEXP processingSEXP, SEXP colorfilenameSEXP, SEXP ooSEXP, SEXP coSEXP, SEXP quietSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type src(srcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type dst(dstSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type processing(processingSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type colorfilename(colorfilenameSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type oo(ooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type co(coSEXP);\n    Rcpp::traits::input_parameter< bool >::type quiet(quietSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdaldemprocessing(src, dst, options, processing, colorfilename, oo, co, quiet));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdalnearblack\nRcpp::LogicalVector CPL_gdalnearblack(Rcpp::CharacterVector src, Rcpp::CharacterVector dst, Rcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector doo, Rcpp::CharacterVector co, bool quiet);\nRcppExport SEXP _sf_CPL_gdalnearblack(SEXP srcSEXP, SEXP dstSEXP, SEXP optionsSEXP, SEXP ooSEXP, SEXP dooSEXP, SEXP coSEXP, SEXP quietSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type src(srcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type dst(dstSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type oo(ooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type doo(dooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type co(coSEXP);\n    Rcpp::traits::input_parameter< bool >::type quiet(quietSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdalnearblack(src, dst, options, oo, doo, co, quiet));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdalgrid\nRcpp::LogicalVector CPL_gdalgrid(Rcpp::CharacterVector src, Rcpp::CharacterVector dst, Rcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector co, bool quiet);\nRcppExport SEXP _sf_CPL_gdalgrid(SEXP srcSEXP, SEXP dstSEXP, SEXP optionsSEXP, SEXP ooSEXP, SEXP coSEXP, SEXP quietSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type src(srcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type dst(dstSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type oo(ooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type co(coSEXP);\n    Rcpp::traits::input_parameter< bool >::type quiet(quietSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdalgrid(src, dst, options, oo, co, quiet));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdalmdiminfo\nRcpp::CharacterVector CPL_gdalmdiminfo(Rcpp::CharacterVector obj, Rcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector co);\nRcppExport SEXP _sf_CPL_gdalmdiminfo(SEXP objSEXP, SEXP optionsSEXP, SEXP ooSEXP, SEXP coSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type obj(objSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type oo(ooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type co(coSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdalmdiminfo(obj, options, oo, co));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdalmdimtranslate\nRcpp::LogicalVector CPL_gdalmdimtranslate(Rcpp::CharacterVector src, Rcpp::CharacterVector dst, Rcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector co, bool quiet);\nRcppExport SEXP _sf_CPL_gdalmdimtranslate(SEXP srcSEXP, SEXP dstSEXP, SEXP optionsSEXP, SEXP ooSEXP, SEXP coSEXP, SEXP quietSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type src(srcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type dst(dstSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type oo(ooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type co(coSEXP);\n    Rcpp::traits::input_parameter< bool >::type quiet(quietSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdalmdimtranslate(src, dst, options, oo, co, quiet));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_gdal_warper\nRcpp::LogicalVector CPL_gdal_warper(Rcpp::CharacterVector infile, Rcpp::CharacterVector outfile, Rcpp::IntegerVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector doo, Rcpp::CharacterVector co, bool quiet);\nRcppExport SEXP _sf_CPL_gdal_warper(SEXP infileSEXP, SEXP outfileSEXP, SEXP optionsSEXP, SEXP ooSEXP, SEXP dooSEXP, SEXP coSEXP, SEXP quietSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type infile(infileSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type outfile(outfileSEXP);\n    Rcpp::traits::input_parameter< Rcpp::IntegerVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type oo(ooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type doo(dooSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type co(coSEXP);\n    Rcpp::traits::input_parameter< bool >::type quiet(quietSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_gdal_warper(infile, outfile, options, oo, doo, co, quiet));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_write_ogr\nint CPL_write_ogr(Rcpp::List obj, Rcpp::CharacterVector dsn, Rcpp::CharacterVector layer, Rcpp::CharacterVector driver, Rcpp::CharacterVector dco, Rcpp::CharacterVector lco, Rcpp::List geom, Rcpp::CharacterVector dim, Rcpp::CharacterVector fids, Rcpp::CharacterVector ConfigOptions, bool quiet, Rcpp::LogicalVector append, bool delete_dsn, bool delete_layer, bool write_geometries, int width);\nRcppExport SEXP _sf_CPL_write_ogr(SEXP objSEXP, SEXP dsnSEXP, SEXP layerSEXP, SEXP driverSEXP, SEXP dcoSEXP, SEXP lcoSEXP, SEXP geomSEXP, SEXP dimSEXP, SEXP fidsSEXP, SEXP ConfigOptionsSEXP, SEXP quietSEXP, SEXP appendSEXP, SEXP delete_dsnSEXP, SEXP delete_layerSEXP, SEXP write_geometriesSEXP, SEXP widthSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type obj(objSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type dsn(dsnSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type layer(layerSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type driver(driverSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type dco(dcoSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type lco(lcoSEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type geom(geomSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type dim(dimSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type fids(fidsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type ConfigOptions(ConfigOptionsSEXP);\n    Rcpp::traits::input_parameter< bool >::type quiet(quietSEXP);\n    Rcpp::traits::input_parameter< Rcpp::LogicalVector >::type append(appendSEXP);\n    Rcpp::traits::input_parameter< bool >::type delete_dsn(delete_dsnSEXP);\n    Rcpp::traits::input_parameter< bool >::type delete_layer(delete_layerSEXP);\n    Rcpp::traits::input_parameter< bool >::type write_geometries(write_geometriesSEXP);\n    Rcpp::traits::input_parameter< int >::type width(widthSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_write_ogr(obj, dsn, layer, driver, dco, lco, geom, dim, fids, ConfigOptions, quiet, append, delete_dsn, delete_layer, write_geometries, width));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_delete_ogr\nint CPL_delete_ogr(Rcpp::CharacterVector dsn, Rcpp::CharacterVector layer, Rcpp::CharacterVector driver, bool quiet);\nRcppExport SEXP _sf_CPL_delete_ogr(SEXP dsnSEXP, SEXP layerSEXP, SEXP driverSEXP, SEXP quietSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type dsn(dsnSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type layer(layerSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type driver(driverSEXP);\n    Rcpp::traits::input_parameter< bool >::type quiet(quietSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_delete_ogr(dsn, layer, driver, quiet));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_binop\nRcpp::List CPL_geos_binop(Rcpp::List sfc0, Rcpp::List sfc1, std::string op, double par, std::string pattern, bool prepared);\nRcppExport SEXP _sf_CPL_geos_binop(SEXP sfc0SEXP, SEXP sfc1SEXP, SEXP opSEXP, SEXP parSEXP, SEXP patternSEXP, SEXP preparedSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc0(sfc0SEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc1(sfc1SEXP);\n    Rcpp::traits::input_parameter< std::string >::type op(opSEXP);\n    Rcpp::traits::input_parameter< double >::type par(parSEXP);\n    Rcpp::traits::input_parameter< std::string >::type pattern(patternSEXP);\n    Rcpp::traits::input_parameter< bool >::type prepared(preparedSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_binop(sfc0, sfc1, op, par, pattern, prepared));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_binop_by_element\nRcpp::List CPL_geos_binop_by_element(Rcpp::List sfc0, Rcpp::List sfc1, std::string op, double par, std::string pattern, bool prepared);\nRcppExport SEXP _sf_CPL_geos_binop_by_element(SEXP sfc0SEXP, SEXP sfc1SEXP, SEXP opSEXP, SEXP parSEXP, SEXP patternSEXP, SEXP preparedSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc0(sfc0SEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc1(sfc1SEXP);\n    Rcpp::traits::input_parameter< std::string >::type op(opSEXP);\n    Rcpp::traits::input_parameter< double >::type par(parSEXP);\n    Rcpp::traits::input_parameter< std::string >::type pattern(patternSEXP);\n    Rcpp::traits::input_parameter< bool >::type prepared(preparedSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_binop_by_element(sfc0, sfc1, op, par, pattern, prepared));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_is_valid_reason\nRcpp::CharacterVector CPL_geos_is_valid_reason(Rcpp::List sfc);\nRcppExport SEXP _sf_CPL_geos_is_valid_reason(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_is_valid_reason(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_make_valid\nRcpp::List CPL_geos_make_valid(Rcpp::List sfc, std::string method, bool keep_collapsed);\nRcppExport SEXP _sf_CPL_geos_make_valid(SEXP sfcSEXP, SEXP methodSEXP, SEXP keep_collapsedSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    Rcpp::traits::input_parameter< std::string >::type method(methodSEXP);\n    Rcpp::traits::input_parameter< bool >::type keep_collapsed(keep_collapsedSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_make_valid(sfc, method, keep_collapsed));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_is_valid\nRcpp::LogicalVector CPL_geos_is_valid(Rcpp::List sfc, bool NA_on_exception);\nRcppExport SEXP _sf_CPL_geos_is_valid(SEXP sfcSEXP, SEXP NA_on_exceptionSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    Rcpp::traits::input_parameter< bool >::type NA_on_exception(NA_on_exceptionSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_is_valid(sfc, NA_on_exception));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_is_simple\nRcpp::LogicalVector CPL_geos_is_simple(Rcpp::List sfc);\nRcppExport SEXP _sf_CPL_geos_is_simple(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_is_simple(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_is_empty\nRcpp::LogicalVector CPL_geos_is_empty(Rcpp::List sfc);\nRcppExport SEXP _sf_CPL_geos_is_empty(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_is_empty(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_normalize\nRcpp::List CPL_geos_normalize(Rcpp::List sfc);\nRcppExport SEXP _sf_CPL_geos_normalize(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_normalize(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_union\nRcpp::List CPL_geos_union(Rcpp::List sfc, bool by_feature, bool is_coverage);\nRcppExport SEXP _sf_CPL_geos_union(SEXP sfcSEXP, SEXP by_featureSEXP, SEXP is_coverageSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    Rcpp::traits::input_parameter< bool >::type by_feature(by_featureSEXP);\n    Rcpp::traits::input_parameter< bool >::type is_coverage(is_coverageSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_union(sfc, by_feature, is_coverage));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_snap\nRcpp::List CPL_geos_snap(Rcpp::List sfc0, Rcpp::List sfc1, Rcpp::NumericVector tolerance);\nRcppExport SEXP _sf_CPL_geos_snap(SEXP sfc0SEXP, SEXP sfc1SEXP, SEXP toleranceSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc0(sfc0SEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc1(sfc1SEXP);\n    Rcpp::traits::input_parameter< Rcpp::NumericVector >::type tolerance(toleranceSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_snap(sfc0, sfc1, tolerance));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_op\nRcpp::List CPL_geos_op(std::string op, Rcpp::List sfc, Rcpp::NumericVector bufferDist, Rcpp::IntegerVector nQuadSegs, Rcpp::NumericVector dTolerance, Rcpp::LogicalVector preserveTopology, int bOnlyEdges, Rcpp::IntegerVector endCapStyle, Rcpp::IntegerVector joinStyle, Rcpp::NumericVector mitreLimit, Rcpp::LogicalVector singleside);\nRcppExport SEXP _sf_CPL_geos_op(SEXP opSEXP, SEXP sfcSEXP, SEXP bufferDistSEXP, SEXP nQuadSegsSEXP, SEXP dToleranceSEXP, SEXP preserveTopologySEXP, SEXP bOnlyEdgesSEXP, SEXP endCapStyleSEXP, SEXP joinStyleSEXP, SEXP mitreLimitSEXP, SEXP singlesideSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< std::string >::type op(opSEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::NumericVector >::type bufferDist(bufferDistSEXP);\n    Rcpp::traits::input_parameter< Rcpp::IntegerVector >::type nQuadSegs(nQuadSegsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::NumericVector >::type dTolerance(dToleranceSEXP);\n    Rcpp::traits::input_parameter< Rcpp::LogicalVector >::type preserveTopology(preserveTopologySEXP);\n    Rcpp::traits::input_parameter< int >::type bOnlyEdges(bOnlyEdgesSEXP);\n    Rcpp::traits::input_parameter< Rcpp::IntegerVector >::type endCapStyle(endCapStyleSEXP);\n    Rcpp::traits::input_parameter< Rcpp::IntegerVector >::type joinStyle(joinStyleSEXP);\n    Rcpp::traits::input_parameter< Rcpp::NumericVector >::type mitreLimit(mitreLimitSEXP);\n    Rcpp::traits::input_parameter< Rcpp::LogicalVector >::type singleside(singlesideSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_op(op, sfc, bufferDist, nQuadSegs, dTolerance, preserveTopology, bOnlyEdges, endCapStyle, joinStyle, mitreLimit, singleside));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_voronoi\nRcpp::List CPL_geos_voronoi(Rcpp::List sfc, Rcpp::List env, double dTolerance, int bOnlyEdges);\nRcppExport SEXP _sf_CPL_geos_voronoi(SEXP sfcSEXP, SEXP envSEXP, SEXP dToleranceSEXP, SEXP bOnlyEdgesSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type env(envSEXP);\n    Rcpp::traits::input_parameter< double >::type dTolerance(dToleranceSEXP);\n    Rcpp::traits::input_parameter< int >::type bOnlyEdges(bOnlyEdgesSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_voronoi(sfc, env, dTolerance, bOnlyEdges));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_op2\nRcpp::List CPL_geos_op2(std::string op, Rcpp::List sfcx, Rcpp::List sfcy);\nRcppExport SEXP _sf_CPL_geos_op2(SEXP opSEXP, SEXP sfcxSEXP, SEXP sfcySEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< std::string >::type op(opSEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfcx(sfcxSEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfcy(sfcySEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_op2(op, sfcx, sfcy));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_dist_by_element\nRcpp::NumericVector CPL_geos_dist_by_element(Rcpp::List sfc0, Rcpp::List sfc1, std::string which, double par);\nRcppExport SEXP _sf_CPL_geos_dist_by_element(SEXP sfc0SEXP, SEXP sfc1SEXP, SEXP whichSEXP, SEXP parSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc0(sfc0SEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc1(sfc1SEXP);\n    Rcpp::traits::input_parameter< std::string >::type which(whichSEXP);\n    Rcpp::traits::input_parameter< double >::type par(parSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_dist_by_element(sfc0, sfc1, which, par));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_version\nstd::string CPL_geos_version(bool runtime, bool capi);\nRcppExport SEXP _sf_CPL_geos_version(SEXP runtimeSEXP, SEXP capiSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< bool >::type runtime(runtimeSEXP);\n    Rcpp::traits::input_parameter< bool >::type capi(capiSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_version(runtime, capi));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_op2_by_element\nRcpp::List CPL_geos_op2_by_element(std::string op, Rcpp::List sfcx, Rcpp::List sfcy);\nRcppExport SEXP _sf_CPL_geos_op2_by_element(SEXP opSEXP, SEXP sfcxSEXP, SEXP sfcySEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< std::string >::type op(opSEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfcx(sfcxSEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfcy(sfcySEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_op2_by_element(op, sfcx, sfcy));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_dist\nRcpp::NumericMatrix CPL_geos_dist(Rcpp::List sfc0, Rcpp::List sfc1, Rcpp::CharacterVector which, double par);\nRcppExport SEXP _sf_CPL_geos_dist(SEXP sfc0SEXP, SEXP sfc1SEXP, SEXP whichSEXP, SEXP parSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc0(sfc0SEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc1(sfc1SEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type which(whichSEXP);\n    Rcpp::traits::input_parameter< double >::type par(parSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_dist(sfc0, sfc1, which, par));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_nearest_feature\nRcpp::IntegerVector CPL_geos_nearest_feature(Rcpp::List sfc0, Rcpp::List sfc1);\nRcppExport SEXP _sf_CPL_geos_nearest_feature(SEXP sfc0SEXP, SEXP sfc1SEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc0(sfc0SEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc1(sfc1SEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_nearest_feature(sfc0, sfc1));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_geos_nearest_points\nRcpp::List CPL_geos_nearest_points(Rcpp::List sfc0, Rcpp::List sfc1, bool pairwise);\nRcppExport SEXP _sf_CPL_geos_nearest_points(SEXP sfc0SEXP, SEXP sfc1SEXP, SEXP pairwiseSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc0(sfc0SEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc1(sfc1SEXP);\n    Rcpp::traits::input_parameter< bool >::type pairwise(pairwiseSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_geos_nearest_points(sfc0, sfc1, pairwise));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_transpose_sparse_incidence\nRcpp::List CPL_transpose_sparse_incidence(Rcpp::List m, int n);\nRcppExport SEXP _sf_CPL_transpose_sparse_incidence(SEXP mSEXP, SEXP nSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type m(mSEXP);\n    Rcpp::traits::input_parameter< int >::type n(nSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_transpose_sparse_incidence(m, n));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_nary_difference\nRcpp::List CPL_nary_difference(Rcpp::List sfc);\nRcppExport SEXP _sf_CPL_nary_difference(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_nary_difference(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_nary_intersection\nRcpp::List CPL_nary_intersection(Rcpp::List sfc);\nRcppExport SEXP _sf_CPL_nary_intersection(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_nary_intersection(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_line_project\nRcpp::NumericVector CPL_line_project(Rcpp::List lines, Rcpp::List points, bool normalized);\nRcppExport SEXP _sf_CPL_line_project(SEXP linesSEXP, SEXP pointsSEXP, SEXP normalizedSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type lines(linesSEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type points(pointsSEXP);\n    Rcpp::traits::input_parameter< bool >::type normalized(normalizedSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_line_project(lines, points, normalized));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_line_interpolate\nRcpp::List CPL_line_interpolate(Rcpp::List lines, Rcpp::NumericVector dists, bool normalized);\nRcppExport SEXP _sf_CPL_line_interpolate(SEXP linesSEXP, SEXP distsSEXP, SEXP normalizedSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type lines(linesSEXP);\n    Rcpp::traits::input_parameter< Rcpp::NumericVector >::type dists(distsSEXP);\n    Rcpp::traits::input_parameter< bool >::type normalized(normalizedSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_line_interpolate(lines, dists, normalized));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_hex_to_raw\nRcpp::List CPL_hex_to_raw(Rcpp::CharacterVector cx);\nRcppExport SEXP _sf_CPL_hex_to_raw(SEXP cxSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type cx(cxSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_hex_to_raw(cx));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_raw_to_hex\nRcpp::CharacterVector CPL_raw_to_hex(Rcpp::RawVector raw);\nRcppExport SEXP _sf_CPL_raw_to_hex(SEXP rawSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::RawVector >::type raw(rawSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_raw_to_hex(raw));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_read_mdim\nList CPL_read_mdim(CharacterVector file, CharacterVector array_names, CharacterVector oo, IntegerVector offset, IntegerVector count, IntegerVector step, bool proxy, bool debug);\nRcppExport SEXP _sf_CPL_read_mdim(SEXP fileSEXP, SEXP array_namesSEXP, SEXP ooSEXP, SEXP offsetSEXP, SEXP countSEXP, SEXP stepSEXP, SEXP proxySEXP, SEXP debugSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< CharacterVector >::type file(fileSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type array_names(array_namesSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type oo(ooSEXP);\n    Rcpp::traits::input_parameter< IntegerVector >::type offset(offsetSEXP);\n    Rcpp::traits::input_parameter< IntegerVector >::type count(countSEXP);\n    Rcpp::traits::input_parameter< IntegerVector >::type step(stepSEXP);\n    Rcpp::traits::input_parameter< bool >::type proxy(proxySEXP);\n    Rcpp::traits::input_parameter< bool >::type debug(debugSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_read_mdim(file, array_names, oo, offset, count, step, proxy, debug));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_write_mdim\nList CPL_write_mdim(CharacterVector name, CharacterVector driver, IntegerVector dimensions, List variables, CharacterVector wkt, CharacterVector xy, CharacterVector RootGroupOptions, CharacterVector CreationOptions, bool as_float);\nRcppExport SEXP _sf_CPL_write_mdim(SEXP nameSEXP, SEXP driverSEXP, SEXP dimensionsSEXP, SEXP variablesSEXP, SEXP wktSEXP, SEXP xySEXP, SEXP RootGroupOptionsSEXP, SEXP CreationOptionsSEXP, SEXP as_floatSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< CharacterVector >::type name(nameSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type driver(driverSEXP);\n    Rcpp::traits::input_parameter< IntegerVector >::type dimensions(dimensionsSEXP);\n    Rcpp::traits::input_parameter< List >::type variables(variablesSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type wkt(wktSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type xy(xySEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type RootGroupOptions(RootGroupOptionsSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type CreationOptions(CreationOptionsSEXP);\n    Rcpp::traits::input_parameter< bool >::type as_float(as_floatSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_write_mdim(name, driver, dimensions, variables, wkt, xy, RootGroupOptions, CreationOptions, as_float));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// opp_sfc\nSEXP opp_sfc(SEXP geom, SEXP value, SEXP mult, SEXP crs);\nRcppExport SEXP _sf_opp_sfc(SEXP geomSEXP, SEXP valueSEXP, SEXP multSEXP, SEXP crsSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< SEXP >::type geom(geomSEXP);\n    Rcpp::traits::input_parameter< SEXP >::type value(valueSEXP);\n    Rcpp::traits::input_parameter< SEXP >::type mult(multSEXP);\n    Rcpp::traits::input_parameter< SEXP >::type crs(crsSEXP);\n    rcpp_result_gen = Rcpp::wrap(opp_sfc(geom, value, mult, crs));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// normalize_sfc\nSEXP normalize_sfc(SEXP geom, SEXP min, SEXP range, SEXP crs);\nRcppExport SEXP _sf_normalize_sfc(SEXP geomSEXP, SEXP minSEXP, SEXP rangeSEXP, SEXP crsSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< SEXP >::type geom(geomSEXP);\n    Rcpp::traits::input_parameter< SEXP >::type min(minSEXP);\n    Rcpp::traits::input_parameter< SEXP >::type range(rangeSEXP);\n    Rcpp::traits::input_parameter< SEXP >::type crs(crsSEXP);\n    rcpp_result_gen = Rcpp::wrap(normalize_sfc(geom, min, range, crs));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_polygonize\nRcpp::List CPL_polygonize(Rcpp::CharacterVector raster, Rcpp::CharacterVector mask_name, Rcpp::CharacterVector raster_driver, Rcpp::CharacterVector vector_driver, Rcpp::CharacterVector vector_dsn, Rcpp::CharacterVector options, Rcpp::IntegerVector iPixValField, Rcpp::CharacterVector contour_options, bool use_contours, bool use_integer);\nRcppExport SEXP _sf_CPL_polygonize(SEXP rasterSEXP, SEXP mask_nameSEXP, SEXP raster_driverSEXP, SEXP vector_driverSEXP, SEXP vector_dsnSEXP, SEXP optionsSEXP, SEXP iPixValFieldSEXP, SEXP contour_optionsSEXP, SEXP use_contoursSEXP, SEXP use_integerSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type raster(rasterSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type mask_name(mask_nameSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type raster_driver(raster_driverSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type vector_driver(vector_driverSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type vector_dsn(vector_dsnSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::IntegerVector >::type iPixValField(iPixValFieldSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type contour_options(contour_optionsSEXP);\n    Rcpp::traits::input_parameter< bool >::type use_contours(use_contoursSEXP);\n    Rcpp::traits::input_parameter< bool >::type use_integer(use_integerSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_polygonize(raster, mask_name, raster_driver, vector_driver, vector_dsn, options, iPixValField, contour_options, use_contours, use_integer));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_rasterize\nRcpp::List CPL_rasterize(Rcpp::CharacterVector raster, Rcpp::CharacterVector raster_driver, Rcpp::List sfc, Rcpp::NumericVector values, Rcpp::CharacterVector options, Rcpp::NumericVector NA_value);\nRcppExport SEXP _sf_CPL_rasterize(SEXP rasterSEXP, SEXP raster_driverSEXP, SEXP sfcSEXP, SEXP valuesSEXP, SEXP optionsSEXP, SEXP NA_valueSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type raster(rasterSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type raster_driver(raster_driverSEXP);\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    Rcpp::traits::input_parameter< Rcpp::NumericVector >::type values(valuesSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::NumericVector >::type NA_value(NA_valueSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_rasterize(raster, raster_driver, sfc, values, options, NA_value));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_proj_h\nRcpp::LogicalVector CPL_proj_h(bool b);\nRcppExport SEXP _sf_CPL_proj_h(SEXP bSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< bool >::type b(bSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_proj_h(b));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_get_pipelines\nRcpp::DataFrame CPL_get_pipelines(Rcpp::CharacterVector crs, Rcpp::CharacterVector authority, Rcpp::NumericVector AOI, Rcpp::CharacterVector Use, Rcpp::CharacterVector grid_availability, double accuracy, bool strict_containment, bool axis_order_auth_compl);\nRcppExport SEXP _sf_CPL_get_pipelines(SEXP crsSEXP, SEXP authoritySEXP, SEXP AOISEXP, SEXP UseSEXP, SEXP grid_availabilitySEXP, SEXP accuracySEXP, SEXP strict_containmentSEXP, SEXP axis_order_auth_complSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type crs(crsSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type authority(authoritySEXP);\n    Rcpp::traits::input_parameter< Rcpp::NumericVector >::type AOI(AOISEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type Use(UseSEXP);\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type grid_availability(grid_availabilitySEXP);\n    Rcpp::traits::input_parameter< double >::type accuracy(accuracySEXP);\n    Rcpp::traits::input_parameter< bool >::type strict_containment(strict_containmentSEXP);\n    Rcpp::traits::input_parameter< bool >::type axis_order_auth_compl(axis_order_auth_complSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_get_pipelines(crs, authority, AOI, Use, grid_availability, accuracy, strict_containment, axis_order_auth_compl));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_get_data_dir\nRcpp::CharacterVector CPL_get_data_dir(bool from_proj);\nRcppExport SEXP _sf_CPL_get_data_dir(SEXP from_projSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< bool >::type from_proj(from_projSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_get_data_dir(from_proj));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_is_network_enabled\nRcpp::LogicalVector CPL_is_network_enabled(bool b);\nRcppExport SEXP _sf_CPL_is_network_enabled(SEXP bSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< bool >::type b(bSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_is_network_enabled(b));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_enable_network\nRcpp::CharacterVector CPL_enable_network(Rcpp::CharacterVector url, bool enable);\nRcppExport SEXP _sf_CPL_enable_network(SEXP urlSEXP, SEXP enableSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type url(urlSEXP);\n    Rcpp::traits::input_parameter< bool >::type enable(enableSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_enable_network(url, enable));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_set_data_dir\nRcpp::LogicalVector CPL_set_data_dir(Rcpp::CharacterVector data_dir, bool with_proj);\nRcppExport SEXP _sf_CPL_set_data_dir(SEXP data_dirSEXP, SEXP with_projSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type data_dir(data_dirSEXP);\n    Rcpp::traits::input_parameter< bool >::type with_proj(with_projSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_set_data_dir(data_dir, with_proj));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_use_proj4_init_rules\nRcpp::LogicalVector CPL_use_proj4_init_rules(Rcpp::IntegerVector v);\nRcppExport SEXP _sf_CPL_use_proj4_init_rules(SEXP vSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::IntegerVector >::type v(vSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_use_proj4_init_rules(v));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_proj_version\nstd::string CPL_proj_version(bool b);\nRcppExport SEXP _sf_CPL_proj_version(SEXP bSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< bool >::type b(bSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_proj_version(b));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_proj_is_valid\nRcpp::List CPL_proj_is_valid(std::string proj4string);\nRcppExport SEXP _sf_CPL_proj_is_valid(SEXP proj4stringSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< std::string >::type proj4string(proj4stringSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_proj_is_valid(proj4string));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_have_datum_files\nbool CPL_have_datum_files(SEXP foo);\nRcppExport SEXP _sf_CPL_have_datum_files(SEXP fooSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< SEXP >::type foo(fooSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_have_datum_files(foo));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_proj_direct\nRcpp::NumericMatrix CPL_proj_direct(Rcpp::CharacterVector from_to, Rcpp::NumericMatrix pts, bool keep, bool warn, bool authority_compliant);\nRcppExport SEXP _sf_CPL_proj_direct(SEXP from_toSEXP, SEXP ptsSEXP, SEXP keepSEXP, SEXP warnSEXP, SEXP authority_compliantSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::CharacterVector >::type from_to(from_toSEXP);\n    Rcpp::traits::input_parameter< Rcpp::NumericMatrix >::type pts(ptsSEXP);\n    Rcpp::traits::input_parameter< bool >::type keep(keepSEXP);\n    Rcpp::traits::input_parameter< bool >::type warn(warnSEXP);\n    Rcpp::traits::input_parameter< bool >::type authority_compliant(authority_compliantSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_proj_direct(from_to, pts, keep, warn, authority_compliant));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_proj_info\nRcpp::List CPL_proj_info(int type);\nRcppExport SEXP _sf_CPL_proj_info(SEXP typeSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< int >::type type(typeSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_proj_info(type));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_xy2sfc\nList CPL_xy2sfc(NumericMatrix cc, IntegerVector dim, bool to_points, IntegerVector which, bool cc_has_NAs);\nRcppExport SEXP _sf_CPL_xy2sfc(SEXP ccSEXP, SEXP dimSEXP, SEXP to_pointsSEXP, SEXP whichSEXP, SEXP cc_has_NAsSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< NumericMatrix >::type cc(ccSEXP);\n    Rcpp::traits::input_parameter< IntegerVector >::type dim(dimSEXP);\n    Rcpp::traits::input_parameter< bool >::type to_points(to_pointsSEXP);\n    Rcpp::traits::input_parameter< IntegerVector >::type which(whichSEXP);\n    Rcpp::traits::input_parameter< bool >::type cc_has_NAs(cc_has_NAsSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_xy2sfc(cc, dim, to_points, which, cc_has_NAs));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// sfc_is_null\nLogicalVector sfc_is_null(List sfc);\nRcppExport SEXP _sf_sfc_is_null(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(sfc_is_null(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// sfc_unique_sfg_dims_and_types\nList sfc_unique_sfg_dims_and_types(List sfc);\nRcppExport SEXP _sf_sfc_unique_sfg_dims_and_types(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(sfc_unique_sfg_dims_and_types(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// sfc_is_empty\nLogicalVector sfc_is_empty(List sfc);\nRcppExport SEXP _sf_sfc_is_empty(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(sfc_is_empty(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// sfc_is_full\nLogicalVector sfc_is_full(List sfc);\nRcppExport SEXP _sf_sfc_is_full(SEXP sfcSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< List >::type sfc(sfcSEXP);\n    rcpp_result_gen = Rcpp::wrap(sfc_is_full(sfc));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// points_cpp\nList points_cpp(NumericMatrix pts, CharacterVector gdim);\nRcppExport SEXP _sf_points_cpp(SEXP ptsSEXP, SEXP gdimSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< NumericMatrix >::type pts(ptsSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type gdim(gdimSEXP);\n    rcpp_result_gen = Rcpp::wrap(points_cpp(pts, gdim));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_signed_area\ndouble CPL_signed_area(NumericMatrix pts);\nRcppExport SEXP _sf_CPL_signed_area(SEXP ptsSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< NumericMatrix >::type pts(ptsSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_signed_area(pts));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_get_metadata\nCharacterVector CPL_get_metadata(CharacterVector obj, CharacterVector domain_item, CharacterVector options);\nRcppExport SEXP _sf_CPL_get_metadata(SEXP objSEXP, SEXP domain_itemSEXP, SEXP optionsSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< CharacterVector >::type obj(objSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type domain_item(domain_itemSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type options(optionsSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_get_metadata(obj, domain_item, options));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_get_crs\nList CPL_get_crs(CharacterVector obj, CharacterVector options);\nRcppExport SEXP _sf_CPL_get_crs(SEXP objSEXP, SEXP optionsSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< CharacterVector >::type obj(objSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type options(optionsSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_get_crs(obj, options));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_inv_geotransform\nNumericVector CPL_inv_geotransform(NumericVector gt_r);\nRcppExport SEXP _sf_CPL_inv_geotransform(SEXP gt_rSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< NumericVector >::type gt_r(gt_rSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_inv_geotransform(gt_r));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_read_gdal\nList CPL_read_gdal(CharacterVector fname, CharacterVector options, CharacterVector driver, bool read_data, NumericVector NA_value, List RasterIO_parameters, double max_cells);\nRcppExport SEXP _sf_CPL_read_gdal(SEXP fnameSEXP, SEXP optionsSEXP, SEXP driverSEXP, SEXP read_dataSEXP, SEXP NA_valueSEXP, SEXP RasterIO_parametersSEXP, SEXP max_cellsSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< CharacterVector >::type fname(fnameSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type driver(driverSEXP);\n    Rcpp::traits::input_parameter< bool >::type read_data(read_dataSEXP);\n    Rcpp::traits::input_parameter< NumericVector >::type NA_value(NA_valueSEXP);\n    Rcpp::traits::input_parameter< List >::type RasterIO_parameters(RasterIO_parametersSEXP);\n    Rcpp::traits::input_parameter< double >::type max_cells(max_cellsSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_read_gdal(fname, options, driver, read_data, NA_value, RasterIO_parameters, max_cells));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_write_gdal\nvoid CPL_write_gdal(NumericMatrix x, CharacterVector fname, CharacterVector driver, CharacterVector options, CharacterVector Type, IntegerVector dims, IntegerVector from, NumericVector gt, CharacterVector p4s, NumericVector na_val, NumericVector scale_offset, bool create, bool only_create);\nRcppExport SEXP _sf_CPL_write_gdal(SEXP xSEXP, SEXP fnameSEXP, SEXP driverSEXP, SEXP optionsSEXP, SEXP TypeSEXP, SEXP dimsSEXP, SEXP fromSEXP, SEXP gtSEXP, SEXP p4sSEXP, SEXP na_valSEXP, SEXP scale_offsetSEXP, SEXP createSEXP, SEXP only_createSEXP) {\nBEGIN_RCPP\n    Rcpp::traits::input_parameter< NumericMatrix >::type x(xSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type fname(fnameSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type driver(driverSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type options(optionsSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type Type(TypeSEXP);\n    Rcpp::traits::input_parameter< IntegerVector >::type dims(dimsSEXP);\n    Rcpp::traits::input_parameter< IntegerVector >::type from(fromSEXP);\n    Rcpp::traits::input_parameter< NumericVector >::type gt(gtSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type p4s(p4sSEXP);\n    Rcpp::traits::input_parameter< NumericVector >::type na_val(na_valSEXP);\n    Rcpp::traits::input_parameter< NumericVector >::type scale_offset(scale_offsetSEXP);\n    Rcpp::traits::input_parameter< bool >::type create(createSEXP);\n    Rcpp::traits::input_parameter< bool >::type only_create(only_createSEXP);\n    CPL_write_gdal(x, fname, driver, options, Type, dims, from, gt, p4s, na_val, scale_offset, create, only_create);\n    return R_NilValue;\nEND_RCPP\n}\n// CPL_extract\nNumericMatrix CPL_extract(CharacterVector input, NumericMatrix xy, CharacterVector interpolate);\nRcppExport SEXP _sf_CPL_extract(SEXP inputSEXP, SEXP xySEXP, SEXP interpolateSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< CharacterVector >::type input(inputSEXP);\n    Rcpp::traits::input_parameter< NumericMatrix >::type xy(xySEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type interpolate(interpolateSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_extract(input, xy, interpolate));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_create\nvoid CPL_create(CharacterVector file, IntegerVector nxy, NumericVector value, CharacterVector wkt, NumericVector xlim, NumericVector ylim);\nRcppExport SEXP _sf_CPL_create(SEXP fileSEXP, SEXP nxySEXP, SEXP valueSEXP, SEXP wktSEXP, SEXP xlimSEXP, SEXP ylimSEXP) {\nBEGIN_RCPP\n    Rcpp::traits::input_parameter< CharacterVector >::type file(fileSEXP);\n    Rcpp::traits::input_parameter< IntegerVector >::type nxy(nxySEXP);\n    Rcpp::traits::input_parameter< NumericVector >::type value(valueSEXP);\n    Rcpp::traits::input_parameter< CharacterVector >::type wkt(wktSEXP);\n    Rcpp::traits::input_parameter< NumericVector >::type xlim(xlimSEXP);\n    Rcpp::traits::input_parameter< NumericVector >::type ylim(ylimSEXP);\n    CPL_create(file, nxy, value, wkt, xlim, ylim);\n    return R_NilValue;\nEND_RCPP\n}\n// CPL_read_wkb\nRcpp::List CPL_read_wkb(Rcpp::List wkb_list, bool EWKB, bool spatialite);\nstatic SEXP _sf_CPL_read_wkb_try(SEXP wkb_listSEXP, SEXP EWKBSEXP, SEXP spatialiteSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type wkb_list(wkb_listSEXP);\n    Rcpp::traits::input_parameter< bool >::type EWKB(EWKBSEXP);\n    Rcpp::traits::input_parameter< bool >::type spatialite(spatialiteSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_read_wkb(wkb_list, EWKB, spatialite));\n    return rcpp_result_gen;\nEND_RCPP_RETURN_ERROR\n}\nRcppExport SEXP _sf_CPL_read_wkb(SEXP wkb_listSEXP, SEXP EWKBSEXP, SEXP spatialiteSEXP) {\n    SEXP rcpp_result_gen;\n    {\n        rcpp_result_gen = PROTECT(_sf_CPL_read_wkb_try(wkb_listSEXP, EWKBSEXP, spatialiteSEXP));\n    }\n    Rboolean rcpp_isInterrupt_gen = Rf_inherits(rcpp_result_gen, \"interrupted-error\");\n    if (rcpp_isInterrupt_gen) {\n        UNPROTECT(1);\n        Rf_onintr();\n    }\n    bool rcpp_isLongjump_gen = Rcpp::internal::isLongjumpSentinel(rcpp_result_gen);\n    if (rcpp_isLongjump_gen) {\n        Rcpp::internal::resumeJump(rcpp_result_gen);\n    }\n    Rboolean rcpp_isError_gen = Rf_inherits(rcpp_result_gen, \"try-error\");\n    if (rcpp_isError_gen) {\n        SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen);\n        UNPROTECT(1);\n        (Rf_error)(\"%s\", CHAR(rcpp_msgSEXP_gen));\n    }\n    UNPROTECT(1);\n    return rcpp_result_gen;\n}\n// CPL_write_wkb\nRcpp::List CPL_write_wkb(Rcpp::List sfc, bool EWKB);\nstatic SEXP _sf_CPL_write_wkb_try(SEXP sfcSEXP, SEXP EWKBSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sfc(sfcSEXP);\n    Rcpp::traits::input_parameter< bool >::type EWKB(EWKBSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_write_wkb(sfc, EWKB));\n    return rcpp_result_gen;\nEND_RCPP_RETURN_ERROR\n}\nRcppExport SEXP _sf_CPL_write_wkb(SEXP sfcSEXP, SEXP EWKBSEXP) {\n    SEXP rcpp_result_gen;\n    {\n        rcpp_result_gen = PROTECT(_sf_CPL_write_wkb_try(sfcSEXP, EWKBSEXP));\n    }\n    Rboolean rcpp_isInterrupt_gen = Rf_inherits(rcpp_result_gen, \"interrupted-error\");\n    if (rcpp_isInterrupt_gen) {\n        UNPROTECT(1);\n        Rf_onintr();\n    }\n    bool rcpp_isLongjump_gen = Rcpp::internal::isLongjumpSentinel(rcpp_result_gen);\n    if (rcpp_isLongjump_gen) {\n        Rcpp::internal::resumeJump(rcpp_result_gen);\n    }\n    Rboolean rcpp_isError_gen = Rf_inherits(rcpp_result_gen, \"try-error\");\n    if (rcpp_isError_gen) {\n        SEXP rcpp_msgSEXP_gen = Rf_asChar(rcpp_result_gen);\n        UNPROTECT(1);\n        (Rf_error)(\"%s\", CHAR(rcpp_msgSEXP_gen));\n    }\n    UNPROTECT(1);\n    return rcpp_result_gen;\n}\n// CPL_get_z_range\nRcpp::NumericVector CPL_get_z_range(Rcpp::List sf, int depth);\nRcppExport SEXP _sf_CPL_get_z_range(SEXP sfSEXP, SEXP depthSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sf(sfSEXP);\n    Rcpp::traits::input_parameter< int >::type depth(depthSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_get_z_range(sf, depth));\n    return rcpp_result_gen;\nEND_RCPP\n}\n// CPL_get_m_range\nRcpp::NumericVector CPL_get_m_range(Rcpp::List sf, int depth);\nRcppExport SEXP _sf_CPL_get_m_range(SEXP sfSEXP, SEXP depthSEXP) {\nBEGIN_RCPP\n    Rcpp::RObject rcpp_result_gen;\n    Rcpp::traits::input_parameter< Rcpp::List >::type sf(sfSEXP);\n    Rcpp::traits::input_parameter< int >::type depth(depthSEXP);\n    rcpp_result_gen = Rcpp::wrap(CPL_get_m_range(sf, depth));\n    return rcpp_result_gen;\nEND_RCPP\n}\n\n// validate (ensure exported C++ functions exist before calling them)\nstatic int _sf_RcppExport_validate(const char* sig) { \n    static std::set<std::string> signatures;\n    if (signatures.empty()) {\n        signatures.insert(\"Rcpp::List(*CPL_read_wkb)(Rcpp::List,bool,bool)\");\n        signatures.insert(\"Rcpp::List(*CPL_write_wkb)(Rcpp::List,bool)\");\n    }\n    return signatures.find(sig) != signatures.end();\n}\n\n// registerCCallable (register entry points for exported C++ functions)\nRcppExport SEXP _sf_RcppExport_registerCCallable() { \n    R_RegisterCCallable(\"sf\", \"_sf_CPL_read_wkb\", (DL_FUNC)_sf_CPL_read_wkb_try);\n    R_RegisterCCallable(\"sf\", \"_sf_CPL_write_wkb\", (DL_FUNC)_sf_CPL_write_wkb_try);\n    R_RegisterCCallable(\"sf\", \"_sf_RcppExport_validate\", (DL_FUNC)_sf_RcppExport_validate);\n    return R_NilValue;\n}\n\nstatic const R_CallMethodDef CallEntries[] = {\n    {\"_sf_CPL_get_bbox\", (DL_FUNC) &_sf_CPL_get_bbox, 2},\n    {\"_sf_CPL_gdal_init\", (DL_FUNC) &_sf_CPL_gdal_init, 0},\n    {\"_sf_CPL_gdal_cleanup_all\", (DL_FUNC) &_sf_CPL_gdal_cleanup_all, 0},\n    {\"_sf_CPL_gdal_version\", (DL_FUNC) &_sf_CPL_gdal_version, 1},\n    {\"_sf_CPL_crs_parameters\", (DL_FUNC) &_sf_CPL_crs_parameters, 1},\n    {\"_sf_CPL_crs_equivalent\", (DL_FUNC) &_sf_CPL_crs_equivalent, 2},\n    {\"_sf_CPL_crs_from_input\", (DL_FUNC) &_sf_CPL_crs_from_input, 1},\n    {\"_sf_CPL_roundtrip\", (DL_FUNC) &_sf_CPL_roundtrip, 1},\n    {\"_sf_CPL_circularstring_to_linestring\", (DL_FUNC) &_sf_CPL_circularstring_to_linestring, 1},\n    {\"_sf_CPL_multisurface_to_multipolygon\", (DL_FUNC) &_sf_CPL_multisurface_to_multipolygon, 1},\n    {\"_sf_CPL_compoundcurve_to_linear\", (DL_FUNC) &_sf_CPL_compoundcurve_to_linear, 1},\n    {\"_sf_CPL_curve_to_linestring\", (DL_FUNC) &_sf_CPL_curve_to_linestring, 1},\n    {\"_sf_CPL_can_transform\", (DL_FUNC) &_sf_CPL_can_transform, 2},\n    {\"_sf_CPL_transform\", (DL_FUNC) &_sf_CPL_transform, 7},\n    {\"_sf_CPL_transform_bounds\", (DL_FUNC) &_sf_CPL_transform_bounds, 3},\n    {\"_sf_CPL_wrap_dateline\", (DL_FUNC) &_sf_CPL_wrap_dateline, 3},\n    {\"_sf_CPL_get_gdal_drivers\", (DL_FUNC) &_sf_CPL_get_gdal_drivers, 1},\n    {\"_sf_CPL_sfc_from_wkt\", (DL_FUNC) &_sf_CPL_sfc_from_wkt, 1},\n    {\"_sf_CPL_gdal_with_geos\", (DL_FUNC) &_sf_CPL_gdal_with_geos, 0},\n    {\"_sf_CPL_axis_order_authority_compliant\", (DL_FUNC) &_sf_CPL_axis_order_authority_compliant, 1},\n    {\"_sf_CPL_compressors\", (DL_FUNC) &_sf_CPL_compressors, 0},\n    {\"_sf_CPL_area\", (DL_FUNC) &_sf_CPL_area, 1},\n    {\"_sf_CPL_gdal_dimension\", (DL_FUNC) &_sf_CPL_gdal_dimension, 2},\n    {\"_sf_CPL_length\", (DL_FUNC) &_sf_CPL_length, 1},\n    {\"_sf_CPL_gdal_segmentize\", (DL_FUNC) &_sf_CPL_gdal_segmentize, 2},\n    {\"_sf_CPL_gdal_linestring_sample\", (DL_FUNC) &_sf_CPL_gdal_linestring_sample, 2},\n    {\"_sf_CPL_get_layers\", (DL_FUNC) &_sf_CPL_get_layers, 3},\n    {\"_sf_CPL_read_ogr\", (DL_FUNC) &_sf_CPL_read_ogr, 14},\n    {\"_sf_CPL_read_gdal_stream\", (DL_FUNC) &_sf_CPL_read_gdal_stream, 12},\n    {\"_sf_CPL_gdalinfo\", (DL_FUNC) &_sf_CPL_gdalinfo, 4},\n    {\"_sf_CPL_ogrinfo\", (DL_FUNC) &_sf_CPL_ogrinfo, 5},\n    {\"_sf_CPL_gdaladdo\", (DL_FUNC) &_sf_CPL_gdaladdo, 8},\n    {\"_sf_CPL_gdalwarp\", (DL_FUNC) &_sf_CPL_gdalwarp, 8},\n    {\"_sf_CPL_gdalrasterize\", (DL_FUNC) &_sf_CPL_gdalrasterize, 8},\n    {\"_sf_CPL_gdaltranslate\", (DL_FUNC) &_sf_CPL_gdaltranslate, 6},\n    {\"_sf_CPL_gdalfootprint\", (DL_FUNC) &_sf_CPL_gdalfootprint, 6},\n    {\"_sf_CPL_gdalvectortranslate\", (DL_FUNC) &_sf_CPL_gdalvectortranslate, 7},\n    {\"_sf_CPL_gdalbuildvrt\", (DL_FUNC) &_sf_CPL_gdalbuildvrt, 6},\n    {\"_sf_CPL_gdaldemprocessing\", (DL_FUNC) &_sf_CPL_gdaldemprocessing, 8},\n    {\"_sf_CPL_gdalnearblack\", (DL_FUNC) &_sf_CPL_gdalnearblack, 7},\n    {\"_sf_CPL_gdalgrid\", (DL_FUNC) &_sf_CPL_gdalgrid, 6},\n    {\"_sf_CPL_gdalmdiminfo\", (DL_FUNC) &_sf_CPL_gdalmdiminfo, 4},\n    {\"_sf_CPL_gdalmdimtranslate\", (DL_FUNC) &_sf_CPL_gdalmdimtranslate, 6},\n    {\"_sf_CPL_gdal_warper\", (DL_FUNC) &_sf_CPL_gdal_warper, 7},\n    {\"_sf_CPL_write_ogr\", (DL_FUNC) &_sf_CPL_write_ogr, 16},\n    {\"_sf_CPL_delete_ogr\", (DL_FUNC) &_sf_CPL_delete_ogr, 4},\n    {\"_sf_CPL_geos_binop\", (DL_FUNC) &_sf_CPL_geos_binop, 6},\n    {\"_sf_CPL_geos_binop_by_element\", (DL_FUNC) &_sf_CPL_geos_binop_by_element, 6},\n    {\"_sf_CPL_geos_is_valid_reason\", (DL_FUNC) &_sf_CPL_geos_is_valid_reason, 1},\n    {\"_sf_CPL_geos_make_valid\", (DL_FUNC) &_sf_CPL_geos_make_valid, 3},\n    {\"_sf_CPL_geos_is_valid\", (DL_FUNC) &_sf_CPL_geos_is_valid, 2},\n    {\"_sf_CPL_geos_is_simple\", (DL_FUNC) &_sf_CPL_geos_is_simple, 1},\n    {\"_sf_CPL_geos_is_empty\", (DL_FUNC) &_sf_CPL_geos_is_empty, 1},\n    {\"_sf_CPL_geos_normalize\", (DL_FUNC) &_sf_CPL_geos_normalize, 1},\n    {\"_sf_CPL_geos_union\", (DL_FUNC) &_sf_CPL_geos_union, 3},\n    {\"_sf_CPL_geos_snap\", (DL_FUNC) &_sf_CPL_geos_snap, 3},\n    {\"_sf_CPL_geos_op\", (DL_FUNC) &_sf_CPL_geos_op, 11},\n    {\"_sf_CPL_geos_voronoi\", (DL_FUNC) &_sf_CPL_geos_voronoi, 4},\n    {\"_sf_CPL_geos_op2\", (DL_FUNC) &_sf_CPL_geos_op2, 3},\n    {\"_sf_CPL_geos_dist_by_element\", (DL_FUNC) &_sf_CPL_geos_dist_by_element, 4},\n    {\"_sf_CPL_geos_version\", (DL_FUNC) &_sf_CPL_geos_version, 2},\n    {\"_sf_CPL_geos_op2_by_element\", (DL_FUNC) &_sf_CPL_geos_op2_by_element, 3},\n    {\"_sf_CPL_geos_dist\", (DL_FUNC) &_sf_CPL_geos_dist, 4},\n    {\"_sf_CPL_geos_nearest_feature\", (DL_FUNC) &_sf_CPL_geos_nearest_feature, 2},\n    {\"_sf_CPL_geos_nearest_points\", (DL_FUNC) &_sf_CPL_geos_nearest_points, 3},\n    {\"_sf_CPL_transpose_sparse_incidence\", (DL_FUNC) &_sf_CPL_transpose_sparse_incidence, 2},\n    {\"_sf_CPL_nary_difference\", (DL_FUNC) &_sf_CPL_nary_difference, 1},\n    {\"_sf_CPL_nary_intersection\", (DL_FUNC) &_sf_CPL_nary_intersection, 1},\n    {\"_sf_CPL_line_project\", (DL_FUNC) &_sf_CPL_line_project, 3},\n    {\"_sf_CPL_line_interpolate\", (DL_FUNC) &_sf_CPL_line_interpolate, 3},\n    {\"_sf_CPL_hex_to_raw\", (DL_FUNC) &_sf_CPL_hex_to_raw, 1},\n    {\"_sf_CPL_raw_to_hex\", (DL_FUNC) &_sf_CPL_raw_to_hex, 1},\n    {\"_sf_CPL_read_mdim\", (DL_FUNC) &_sf_CPL_read_mdim, 8},\n    {\"_sf_CPL_write_mdim\", (DL_FUNC) &_sf_CPL_write_mdim, 9},\n    {\"_sf_opp_sfc\", (DL_FUNC) &_sf_opp_sfc, 4},\n    {\"_sf_normalize_sfc\", (DL_FUNC) &_sf_normalize_sfc, 4},\n    {\"_sf_CPL_polygonize\", (DL_FUNC) &_sf_CPL_polygonize, 10},\n    {\"_sf_CPL_rasterize\", (DL_FUNC) &_sf_CPL_rasterize, 6},\n    {\"_sf_CPL_proj_h\", (DL_FUNC) &_sf_CPL_proj_h, 1},\n    {\"_sf_CPL_get_pipelines\", (DL_FUNC) &_sf_CPL_get_pipelines, 8},\n    {\"_sf_CPL_get_data_dir\", (DL_FUNC) &_sf_CPL_get_data_dir, 1},\n    {\"_sf_CPL_is_network_enabled\", (DL_FUNC) &_sf_CPL_is_network_enabled, 1},\n    {\"_sf_CPL_enable_network\", (DL_FUNC) &_sf_CPL_enable_network, 2},\n    {\"_sf_CPL_set_data_dir\", (DL_FUNC) &_sf_CPL_set_data_dir, 2},\n    {\"_sf_CPL_use_proj4_init_rules\", (DL_FUNC) &_sf_CPL_use_proj4_init_rules, 1},\n    {\"_sf_CPL_proj_version\", (DL_FUNC) &_sf_CPL_proj_version, 1},\n    {\"_sf_CPL_proj_is_valid\", (DL_FUNC) &_sf_CPL_proj_is_valid, 1},\n    {\"_sf_CPL_have_datum_files\", (DL_FUNC) &_sf_CPL_have_datum_files, 1},\n    {\"_sf_CPL_proj_direct\", (DL_FUNC) &_sf_CPL_proj_direct, 5},\n    {\"_sf_CPL_proj_info\", (DL_FUNC) &_sf_CPL_proj_info, 1},\n    {\"_sf_CPL_xy2sfc\", (DL_FUNC) &_sf_CPL_xy2sfc, 5},\n    {\"_sf_sfc_is_null\", (DL_FUNC) &_sf_sfc_is_null, 1},\n    {\"_sf_sfc_unique_sfg_dims_and_types\", (DL_FUNC) &_sf_sfc_unique_sfg_dims_and_types, 1},\n    {\"_sf_sfc_is_empty\", (DL_FUNC) &_sf_sfc_is_empty, 1},\n    {\"_sf_sfc_is_full\", (DL_FUNC) &_sf_sfc_is_full, 1},\n    {\"_sf_points_cpp\", (DL_FUNC) &_sf_points_cpp, 2},\n    {\"_sf_CPL_signed_area\", (DL_FUNC) &_sf_CPL_signed_area, 1},\n    {\"_sf_CPL_get_metadata\", (DL_FUNC) &_sf_CPL_get_metadata, 3},\n    {\"_sf_CPL_get_crs\", (DL_FUNC) &_sf_CPL_get_crs, 2},\n    {\"_sf_CPL_inv_geotransform\", (DL_FUNC) &_sf_CPL_inv_geotransform, 1},\n    {\"_sf_CPL_read_gdal\", (DL_FUNC) &_sf_CPL_read_gdal, 7},\n    {\"_sf_CPL_write_gdal\", (DL_FUNC) &_sf_CPL_write_gdal, 13},\n    {\"_sf_CPL_extract\", (DL_FUNC) &_sf_CPL_extract, 3},\n    {\"_sf_CPL_create\", (DL_FUNC) &_sf_CPL_create, 6},\n    {\"_sf_CPL_read_wkb\", (DL_FUNC) &_sf_CPL_read_wkb, 3},\n    {\"_sf_CPL_write_wkb\", (DL_FUNC) &_sf_CPL_write_wkb, 2},\n    {\"_sf_CPL_get_z_range\", (DL_FUNC) &_sf_CPL_get_z_range, 2},\n    {\"_sf_CPL_get_m_range\", (DL_FUNC) &_sf_CPL_get_m_range, 2},\n    {\"_sf_RcppExport_registerCCallable\", (DL_FUNC) &_sf_RcppExport_registerCCallable, 0},\n    {NULL, NULL, 0}\n};\n\nRcppExport void R_init_sf(DllInfo *dll) {\n    R_registerRoutines(dll, NULL, CallEntries, NULL, NULL);\n    R_useDynamicSymbols(dll, FALSE);\n}\n"
  },
  {
    "path": "src/bbox.cpp",
    "content": "#include <Rcpp.h>\n\n#include \"bbox.h\"\n\n// [[Rcpp::export(rng=false)]]\nRcpp::NumericVector CPL_get_bbox(Rcpp::List sf, int depth = 0) {\n\tRcpp::NumericVector bb(4);\n\tbb[0] = bb[1] = bb[2] = bb[3] = NA_REAL;\n\tauto n = sf.size();\n\n\tswitch(depth) {\n\t\tcase 0: // points:\n\t\tfor (decltype(n) i = 0; i < n; i++) {\n\t\t\tRcpp::NumericVector pt = sf[i];\n\t\t\tif (i == 0) {\n\t\t\t\tbb[0] = bb[2] = pt[0];\n\t\t\t\tbb[1] = bb[3] = pt[1];\n\t\t\t} else {\n\t\t\t\tbb[0] = std::min(pt[0],bb[0]);\n\t\t\t\tbb[1] = std::min(pt[1],bb[1]);\n\t\t\t\tbb[2] = std::max(pt[0],bb[2]);\n\t\t\t\tbb[3] = std::max(pt[1],bb[3]);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\n\t\tcase 1: { // list of matrices:\n\t\t\tbool initialised = false;\n\t\t\tfor (decltype(n) i = 0; i < n; i++) {\n\t\t\t\tRcpp::NumericMatrix m = sf[i];\n\t\t\t\tauto rows = m.nrow();\n\t\n\t\t\t\tif (rows > 0) { // non-empty:\n\t\t\t\t\tif (! initialised) { // initialize:\n\t\t\t\t\t\tbb[0] = bb[2] = m(0,0);\n\t\t\t\t\t\tbb[1] = bb[3] = m(0,1);\n\t\t\t\t\t\tinitialised = true;\n\t\t\t\t\t}\n\t\t\t\t\tfor (decltype(rows) j = 0; j < rows; j++) {\n\t\t\t\t\t\tbb[0] = std::min(m(j,0),bb[0]);\n\t\t\t\t\t\tbb[1] = std::min(m(j,1),bb[1]);\n\t\t\t\t\t\tbb[2] = std::max(m(j,0),bb[2]);\n\t\t\t\t\t\tbb[3] = std::max(m(j,1),bb[3]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbreak;\n\n\t\tdefault: // recursive list\n\t\tfor (decltype(n) i = 0; i < n; i++) {\n\t\t\tRcpp::NumericVector bbi = CPL_get_bbox(sf[i], depth - 1); // recurse\n\t\t\tif (! Rcpp::NumericVector::is_na(bbi[0])) {\n\t\t\t\tif (i == 0) {\n\t\t\t\t\tbb[0] = bbi[0];\n\t\t\t\t\tbb[1] = bbi[1];\n\t\t\t\t\tbb[2] = bbi[2];\n\t\t\t\t\tbb[3] = bbi[3];\n\t\t\t\t} else {\n\t\t\t\t\tbb[0] = std::min(bbi[0],bb[0]);\n\t\t\t\t\tbb[1] = std::min(bbi[1],bb[1]);\n\t\t\t\t\tbb[2] = std::max(bbi[2],bb[2]);\n\t\t\t\t\tbb[3] = std::max(bbi[3],bb[3]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbreak;\n\t}\n\treturn bb;\n}\n"
  },
  {
    "path": "src/bbox.h",
    "content": "#ifndef SF_BBOX_H_\n#define SF_BBOX_H_\nRcpp::NumericVector CPL_get_bbox(Rcpp::List sf, int depth);\n#endif // SF_BBOX_H_\n"
  },
  {
    "path": "src/gdal.cpp",
    "content": "#include <gdal.h>\n#include <gdal_version.h>\n#include <gdal_alg.h>\n#include <gdal_priv.h> // GDALDriver\n#include <ogr_api.h>\n#include <ogr_geometry.h>\n#include <ogr_srs_api.h>\n#include <ogr_spatialref.h>\n#include <cpl_conv.h>\n#include <cpl_string.h>\n\n#if GDAL_VERSION_NUM >= 3040000\n#include <cpl_compressor.h>\n#endif\n\n#include <stdlib.h> // atoi\n#include <string.h>\n\n#include <Rcpp.h>\n\n#include \"gdal.h\"\n#include \"wkb.h\"\n#include \"gdal_sf_pkg.h\"\n\n// global variable:\nbool axis_order_authority_compliant = false;\n\n//\n// Returns errors to R\n// Note only case 4 actually returns immediately\n// Lower error codes are recoverable\n//\nstatic void __err_handler(CPLErr eErrClass, int err_no, const char *msg)\n{\n\tswitch ( eErrClass )\n\t{\n        case 0:\n            break; // #nocov\n        case 1:\n        case 2:\n            Rf_warning(\"GDAL Message %d: %s\\n\", err_no, msg); // #nocov\n            break; // #nocov\n        case 3:\n            Rf_warning(\"GDAL Error %d: %s\\n\", err_no, msg);\n            break;\n        case 4:\n            Rf_warning(\"GDAL Error %d: %s\\n\", err_no, msg); // #nocov\n            Rcpp::stop(\"Unrecoverable GDAL error\\n\"); // #nocov\n            break;\n        default:\n            Rf_warning(\"Received invalid error class %d (errno %d: %s)\\n\", eErrClass, err_no, msg); // #nocov\n            break; // #nocov\n    }\n    return;\n}\n\n// #nocov start\nstatic void __err_silent(CPLErr eErrClass, int err_no, const char *msg)\n{\n    return;\n}\n// #nocov end\n\nvoid set_error_handler(void)\n{\n    CPLSetErrorHandler((CPLErrorHandler)__err_handler);\n}\n\nvoid unset_error_handler(void)\n{\n    CPLSetErrorHandler((CPLErrorHandler)__err_silent);\n}\n\n// [[Rcpp::export(rng=false)]]\nvoid CPL_gdal_init()\n{\n    CPLSetErrorHandler((CPLErrorHandler)__err_handler);\n    CPLSetConfigOption(\"GDAL_NETCDF_REPORT_EXTRA_DIM_VALUES\", \"YES\");\n    GDALAllRegister();\n    OGRRegisterAll();\n}\n\n// #nocov start\n// [[Rcpp::export(rng=false)]]\nvoid CPL_gdal_cleanup_all()\n{\n    OGRCleanupAll();\n    OSRCleanup();\n}\n// #nocov end\n\n// [[Rcpp::export(rng=false)]]\nconst char* CPL_gdal_version(const char* what = \"RELEASE_NAME\")\n{\n\treturn GDALVersionInfo(what);\n}\n\nvoid handle_error(OGRErr err) {\n\tif (err != OGRERR_NONE) {\n\t\tswitch (err) {\n\t\t\tcase OGRERR_NOT_ENOUGH_DATA:\n\t\t\t\tRcpp::Rcout << \"OGR: Not enough data \" << std::endl; // #nocov\n\t\t\t\tbreak; // #nocov\n\t\t\tcase OGRERR_UNSUPPORTED_GEOMETRY_TYPE:\n\t\t\t\tRcpp::Rcout << \"OGR: Unsupported geometry type\" << std::endl;\n\t\t\t\tbreak;\n\t\t\tcase OGRERR_CORRUPT_DATA:\n\t\t\t\tRcpp::Rcout << \"OGR: Corrupt data\" << std::endl;     // #nocov\n\t\t\t\tbreak; // #nocov\n\t\t\tcase OGRERR_FAILURE:\n\t\t\t\tRcpp::Rcout << \"OGR: index invalid?\" << std::endl;    // #nocov\n\t\t\t\tbreak; // #nocov\n\t\t\tdefault:\n\t\t\t\tRcpp::Rcout << \"Error code: \" << err << std::endl;    // #nocov\n\t\t}\n\t\tRcpp::stop(\"OGR error\");\n\t}\n}\n\nvoid set_config_options(Rcpp::CharacterVector ConfigOptions) {\n\tif (ConfigOptions.size()) {\n\t\tif (ConfigOptions.attr(\"names\") == R_NilValue)\n\t\t\tRcpp::stop(\"config_options should be a character vector with names, as in c(key=\\\"value\\\")\");\n\t\tRcpp::CharacterVector names = ConfigOptions.attr(\"names\");\n\t\tfor (int i = 0; i < ConfigOptions.size(); i++)\n\t\t\tCPLSetConfigOption(names[i], ConfigOptions[i]);\n\t}\n}\n\nvoid unset_config_options(Rcpp::CharacterVector ConfigOptions) {\n\tif (ConfigOptions.size()) {\n\t\tRcpp::CharacterVector names = ConfigOptions.attr(\"names\");\n\t\tfor (int i = 0; i < ConfigOptions.size(); i++)\n\t\t\tCPLSetConfigOption(names[i], NULL);\n\t}\n}\n\nRcpp::CharacterVector wkt_from_spatial_reference(const OGRSpatialReference *srs) { // FIXME: add options?\n\tchar *cp;\n#if GDAL_VERSION_NUM >= 3000000\n\tconst char *options[3] = { \"MULTILINE=YES\", \"FORMAT=WKT2\", NULL };\n\tOGRErr err = srs->exportToWkt(&cp, options);\n#else\n\tOGRErr err = srs->exportToPrettyWkt(&cp);\n#endif\n\tif (err != OGRERR_NONE)\n\t\tRcpp::stop(\"OGR error: cannot export to WKT\"); // #nocov\n\tRcpp::CharacterVector out(cp);\n\tCPLFree(cp);\n\treturn out;\n}\n\nRcpp::List fix_old_style(Rcpp::List crs) {\n\tif (crs.attr(\"names\") == R_NilValue)\n\t\tRcpp::stop(\"invalid crs object: no names\");\n\tRcpp::CharacterVector n = crs.attr(\"names\");\n\tif (n.length() != 2)\n\t\tRcpp::stop(\"invalid crs object: wrong length\");\n\tif (n[0] == \"epsg\") { // create new: // #nocov start\n\t\tRcpp::List ret(2);\n\t\tret[0] = NA_STRING;\n\t\tret[1] = NA_STRING;\n\t\tRcpp::CharacterVector proj4string = crs(1);\n\t\tif (! Rcpp::CharacterVector::is_na(proj4string[0])) {\n\t\t\tret[0] = proj4string[0]; // copy to $input\n\t\t\tOGRSpatialReference *srs = new OGRSpatialReference;\n\t\t\tsrs = handle_axis_order(srs);\n\t\t\thandle_error(srs->SetFromUserInput((const char *) proj4string(0)));\n\t\t\tret[1] = wkt_from_spatial_reference(srs); // copy to $wkt\n\t\t\tdelete srs;\n\t\t}\n\t\tRcpp::CharacterVector names(2);\n\t\tnames(0) = \"input\";\n\t\tnames(1) = \"wkt\";\n\t\tret.attr(\"names\") = names;\n\t\tret.attr(\"class\") = \"crs\";\n\t\tcrs = ret; // #nocov end\n\t}\n\treturn crs;\n}\n\nOGRSpatialReference *OGRSrs_from_crs(Rcpp::List crs) {\n\t// fix old-style crs:\n\tcrs = fix_old_style(crs);\n\tOGRSpatialReference *dest = NULL;\n\tRcpp::CharacterVector wkt = crs[1];\n\tif (! Rcpp::CharacterVector::is_na(wkt[0])) {\n\t\tdest = new OGRSpatialReference;\n\t\tdest = handle_axis_order(dest);\n\t\tchar *cp = wkt[0];\n#if GDAL_VERSION_NUM < 2030000\n\t\thandle_error(dest->importFromWkt(&cp));\n#else\n\t\thandle_error(dest->importFromWkt((const char *) cp));\n#endif\n\t}\n\treturn dest;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_crs_parameters(Rcpp::List crs) {\n\n\tchar *cp = NULL;\n\tunset_error_handler();\n\n\tOGRSpatialReference *srs = OGRSrs_from_crs(crs);\n\tif (srs == NULL)\n\t\tRcpp::stop(\"crs not found\"); // #nocov\n\n\tint n = 18;\n\tRcpp::List out(n);\n\tRcpp::CharacterVector names(n);\n\n\tout(0) = Rcpp::NumericVector::create(srs->GetSemiMajor());\n\tnames(0) = \"SemiMajor\";\n\n\tout(1) = Rcpp::NumericVector::create(srs->GetSemiMinor());\n\tnames(1) = \"SemiMinor\";\n\n\tRcpp::NumericVector InvFlattening(1);\n\tOGRErr Err;\n\tsrs->GetInvFlattening(&Err);\n\tif (Err == OGRERR_FAILURE)\n\t\tInvFlattening(0) = NA_REAL; // #nocov\n\telse\n\t\tInvFlattening(0) = srs->GetInvFlattening(NULL); // for +ellps=sphere, still zero :-(\n\tout(2) = InvFlattening;\n\tnames(2) = \"InvFlattening\";\n\n\tout(3) = Rcpp::LogicalVector::create((bool) srs->IsGeographic());\n\tnames(3) = \"IsGeographic\";\n\n#if GDAL_VERSION_NUM > 2030000\n\tconst char *unit;\n#else\n\tchar *unit;\n#endif\n\tif (srs->IsGeographic())\n\t\tsrs->GetAngularUnits(&unit);\n\telse\n\t\tsrs->GetLinearUnits(&unit);\n\tif (unit == NULL || strncmp(unit, \"unknown\", 8) == 0)\n\t\tout(4) = Rcpp::CharacterVector::create(NA_STRING);\n\telse\n\t\tout(4) = Rcpp::CharacterVector::create(unit);\n\tnames(4) = \"units_gdal\";\n\n\tout(5) = Rcpp::LogicalVector::create(srs->IsVertical());\n\tnames(5) = \"IsVertical\";\n\n\t// wkt pretty:\n\tif (srs->exportToPrettyWkt(&cp) == OGRERR_NONE) {\n\t\tout(6) = Rcpp::CharacterVector::create(cp);\n\t\tCPLFree(cp);\n\t} else\n\t\tout(6) = \"\";\n\tnames(6) = \"WktPretty\";\n\n\t// wkt:\n\tif (srs->exportToWkt(&cp) == OGRERR_NONE) {\n\t\tout(7) = Rcpp::CharacterVector::create(cp);\n\t\tCPLFree(cp);\n\t} else\n\t\tout(7) = \"\";\n\tnames(7) = \"Wkt\";\n\n#if GDAL_VERSION_NUM >= 3000000\n\tout(8) = Rcpp::CharacterVector::create(srs->GetName());\n#else\n\tout(8) = Rcpp::CharacterVector::create(\"unknown\");\n#endif\n\tnames(8) = \"Name\";\n\n\t// proj4string\n\tif (srs->exportToProj4(&cp) == OGRERR_NONE) {\n\t\tout(9) = Rcpp::CharacterVector::create(cp);\n\t\tCPLFree(cp);\n\t} else\n\t\tout(9) = Rcpp::CharacterVector::create(NA_STRING); // #nocov\n\tnames(9) = \"proj4string\";\n\n\t// epsg\n\tif (srs->GetAuthorityCode(NULL) != NULL && strcmp(srs->GetAuthorityName(NULL), \"EPSG\") == 0)\n\t\tout(10) = Rcpp::IntegerVector::create(atoi(srs->GetAuthorityCode(NULL)));\n\telse\n\t\tout(10) = Rcpp::IntegerVector::create(NA_INTEGER);\n\tnames(10) = \"epsg\";\n\n\tbool yx = srs->EPSGTreatsAsLatLong() || srs->EPSGTreatsAsNorthingEasting();\n\tout(11) = Rcpp::LogicalVector(yx);\n\tnames(11) = \"yx\";\n\n\t// ProjJson:\n#if GDAL_VERSION_NUM > 3010000\n\tif (srs->exportToPROJJSON(&cp, NULL) == OGRERR_NONE) {\n\t\tout(12) = Rcpp::CharacterVector::create(cp);\n\t\tCPLFree(cp);\n\t} else\n\t\tout(12) = NA_STRING;\n#else\n\tout(12) = NA_STRING;\n#endif\n\tnames(12) = \"ProjJson\";\n\n\t// WKT1_ESRI\n#if GDAL_VERSION_NUM >= 3000000\n\tconst char *options[3] = { \"MULTILINE=YES\", \"FORMAT=WKT1_ESRI\", NULL };\n\tif (srs->exportToWkt(&cp, options) != OGRERR_NONE)\n\t\tout(13) = Rcpp::CharacterVector::create(NA_STRING); // FIXME: CPLFree() in this case?\n\telse {\n\t\tout(13) = Rcpp::CharacterVector::create(cp);\n\t\tCPLFree(cp);\n\t}\n#else\n\tout(13) = \"\";\n#endif\n\tnames(13) = \"WKT1_ESRI\";\n\n\t// srid\n\tif (srs->GetAuthorityName(NULL) != NULL && srs->GetAuthorityCode(NULL) != NULL) {\n\t\tchar str[101];\n\t\tsnprintf(str, (size_t) 100, \"%s:%s\",\n\t\t\tsrs->GetAuthorityName(NULL), srs->GetAuthorityCode(NULL));\n\t\tRcpp::CharacterVector v = str;\n\t\tout(14) = v;\n\t} else\n\t\tout(14) = Rcpp::CharacterVector::create(NA_STRING);\n\tnames(14) = \"srid\";\n\n\t// axes, 15:\n#if GDAL_VERSION_NUM > 3000000\n\tint ac = srs->GetAxesCount();\n#else\n\tint ac = 0;\n#endif\n\tRcpp::CharacterVector nms(ac);\n\tRcpp::IntegerVector orientation(ac);\n\tfor (int i = 0; i < ac; i++) {\n\t\tOGRAxisOrientation peOrientation;\n\t\tconst char *ret = srs->GetAxis(srs->IsGeographic() ? \"GEOGCS\" : \"PROJCS\", \n\t\t\t\t\t\ti, &peOrientation);\n\t\tif (ret != NULL) {\n\t\t\tnms[i] = ret;\n\t\t\torientation[i] = (int) peOrientation;\n\t\t} else {\n\t\t\tnms[i] = NA_STRING;\n\t\t\torientation[i] = NA_INTEGER;\n\t\t}\n\t}\n\tRcpp::DataFrame axes_df = Rcpp::DataFrame::create(\n\t\tRcpp::_[\"name\"] = nms,\n\t\tRcpp::_[\"orientation\"] = orientation);\n\tout(15) = axes_df;\n\tnames(15) = \"axes\";\n\n\t// base GEOGCRS: https://github.com/r-spatial/sf/issues/2524\n\tOGRSpatialReference *base_srs = new OGRSpatialReference;\n\tif (base_srs->CopyGeogCSFrom(srs) == OGRERR_NONE) {\n\t\tif (base_srs->exportToWkt(&cp) == OGRERR_NONE) {\n\t\t\tout(16) = Rcpp::CharacterVector::create(cp);\n\t\t\tCPLFree(cp);\n\t\t} else\n\t\t\tout(16) = Rcpp::CharacterVector::create(NA_STRING);\n\t} else \n\t\tout(16) = Rcpp::CharacterVector::create(NA_STRING);\n\tnames(16) = \"gcs_crs\";\n\n\tout(17) = Rcpp::LogicalVector::create((bool) base_srs->IsGeocentric());\n\tnames(17) = \"is_geocentric\";\n\n\tdelete base_srs;\n\n\tset_error_handler();\n\n\tdelete srs;\n\tout.attr(\"names\") = names;\n\tout.attr(\"class\") = \"crs_parameters\";\n\treturn out;\n}\n\nint srid_from_crs(Rcpp::List crs) {\n\tconst char *cp;\n\tint ret_val = NA_INTEGER;\n\tunset_error_handler();\n\tOGRSpatialReference *ref = OGRSrs_from_crs(crs);\n\tif (ref && ref->AutoIdentifyEPSG() == OGRERR_NONE &&\n\t\t\t(cp = ref->GetAuthorityCode(NULL)) != NULL) {\n\t\tret_val = atoi(cp);\n\t}\n\tif (ref != NULL)\n\t\tref->Release();\n\tset_error_handler();\n\treturn(ret_val);\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_crs_equivalent(Rcpp::List crs1, Rcpp::List crs2) {\n\n\tOGRSpatialReference *srs1 = OGRSrs_from_crs(crs1);\n\tOGRSpatialReference *srs2 = OGRSrs_from_crs(crs2);\n\tif (srs1 == NULL && srs2 == NULL) // #nocov start\n\t\treturn Rcpp::LogicalVector::create(true);\n\tif (srs1 == NULL) {\n\t\tdelete srs2;\n\t\treturn Rcpp::LogicalVector::create(false);\n\t}\n\tif (srs2 == NULL) {\n\t\tdelete srs1;\n\t\treturn Rcpp::LogicalVector::create(false);\n\t} // #nocov end\n#if GDAL_VERSION_NUM >= 3000000\n\tconst char *options[3] = { NULL, NULL, NULL };\n\tif (axis_order_authority_compliant) {\n\t\toptions[0] = \"IGNORE_DATA_AXIS_TO_SRS_AXIS_MAPPING=NO\";\n\t\toptions[1] = \"CRITERION=STRICT\";\n\t} else\n\t\toptions[0] = \"IGNORE_DATA_AXIS_TO_SRS_AXIS_MAPPING=YES\";\n\tbool b = (bool) srs1->IsSame(srs2, options);\n#else\n\tbool b = (bool) srs1->IsSame(srs2);\n#endif\n\tdelete srs1;\n\tdelete srs2;\n\treturn Rcpp::LogicalVector::create(b);\n}\n\nstd::vector<OGRGeometry *> ogr_from_sfc(Rcpp::List sfc, OGRSpatialReference **sref) {\n\n\tRcpp::List wkblst = CPL_write_wkb(sfc, false);\n\tstd::vector<OGRGeometry *> g(sfc.length());\n\tOGRSpatialReference *local_srs = OGRSrs_from_crs(sfc.attr(\"crs\"));\n\n\tfor (int i = 0; i < wkblst.length(); i++) {\n\t\tRcpp::RawVector r = wkblst[i];\n\t\tOGRErr err = OGRGeometryFactory::createFromWkb(&(r[0]), local_srs, &(g[i]),\n\t\t\tr.length(), wkbVariantIso);\n\t\tif (err != OGRERR_NONE) {\n\t\t\tif (g[i] != NULL) // release: #nocov\n\t\t\t\tOGRGeometryFactory::destroyGeometry(g[i]); // #nocov\n\t\t\tif (local_srs != NULL)      // #nocov start\n\t\t\t\tlocal_srs->Release();\n\t\t\thandle_error(err);          // #nocov end\n\t\t}\n\t}\n\tif (sref != NULL)\n\t\t*sref = local_srs; // return and release later, or\n\telse if (local_srs != NULL)\n\t\tlocal_srs->Release(); // release now\n\treturn g;\n}\n\nstd::vector<char *> create_options(Rcpp::CharacterVector lco, bool quiet) {\n\tif (lco.size() == 0)\n\t\tquiet = true; // nothing to report\n\tif (! quiet)\n\t\tRcpp::Rcout <<  \"options:        \"; // #nocov\n\tstd::vector<char *> ret(lco.size() + 1);\n\tfor (int i = 0; i < lco.size(); i++) {\n\t\tret[i] = (char *) (lco[i]);\n\t\tif (! quiet)\n\t\t\tRcpp::Rcout << ret[i] << \" \"; // #nocov\n\t}\n\tret[lco.size()] = NULL;\n\tif (! quiet)\n\t\tRcpp::Rcout << std::endl;         // #nocov\n\treturn ret;\n}\n\n// convert NULL-terminated array of strings to Rcpp::CharacterVector\nRcpp::CharacterVector charpp2CV(CSLConstList cp) {\n\tint n = 0;\n\twhile (cp && cp[n] != NULL)\n\t\tn++; // count\n\tRcpp::CharacterVector ret(n);\n\tfor (int i = 0; i < n; i++)\n\t\tret(i) = cp[i];\n\treturn ret;\n}\n\nRcpp::List create_crs(const OGRSpatialReference *ref, bool set_input) {\n\tRcpp::List crs(2);\n\tif (ref == NULL) {\n\t\tcrs(0) = Rcpp::CharacterVector::create(NA_STRING);\n\t\tcrs(1) = Rcpp::CharacterVector::create(NA_STRING);\n\t} else {\n\t\tif (set_input) {\n#if GDAL_VERSION_NUM >= 3000000\n\t\t\tcrs(0) = Rcpp::CharacterVector::create(ref->GetName());\n#else\n\t\t\tconst char *cp;\n\t\t\tOGRSpatialReference ref_cp = *ref;\n\t\t\tif (ref_cp.AutoIdentifyEPSG() == OGRERR_NONE && // ->AutoIdentifyEPSG() breaks if \"this\" is const\n\t\t\t\t\t(cp = ref_cp.GetAuthorityCode(NULL)) != NULL)\n\t\t\t\tcrs(0) = cp;\n\t\t\telse\n\t\t\t\tcrs(0) = Rcpp::CharacterVector::create(NA_STRING);\n#endif\n\t\t}\n\t\tcrs(1) = wkt_from_spatial_reference(ref);\n\t}\n\tRcpp::CharacterVector nms(2);\n\tnms(0) = \"input\";\n\tnms(1) = \"wkt\";\n\tcrs.attr(\"names\") = nms;\n\tcrs.attr(\"class\") = \"crs\";\n\treturn crs;\n}\n\nRcpp::List sfc_from_ogr(std::vector<OGRGeometry *> g, bool destroy = false) {\n\tOGRwkbGeometryType type = wkbGeometryCollection;\n\tRcpp::List lst(g.size());\n\tRcpp::List crs = create_crs(g.size() && g[0] != NULL ? g[0]->getSpatialReference() : NULL);\n\tfor (size_t i = 0; i < g.size(); i++) {\n\t\tif (g[i] == NULL)\n\t\t\tg[i] = OGRGeometryFactory::createGeometry(type); // #nocov\n\t\telse\n\t\t\ttype = g[i]->getGeometryType();\n\t\tRcpp::RawVector raw(g[i]->WkbSize());\n\t\thandle_error(g[i]->exportToWkb(wkbNDR, &(raw[0]), wkbVariantIso));\n\t\tlst[i] = raw;\n\t\tif (destroy)\n\t\t\tOGRGeometryFactory::destroyGeometry(g[i]);\n\t}\n\tRcpp::List ret = CPL_read_wkb(lst, false, false);\n\tret.attr(\"crs\") = crs;\n\tret.attr(\"class\") = \"sfc\";\n\treturn ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_crs_from_input(Rcpp::CharacterVector input) {\n\tOGRSpatialReference *ref = new OGRSpatialReference;\n\thandle_axis_order(ref);\n\tRcpp::List crs;\n\t// const char *options[3] = {\"ALLOW_NETWORK_ACCESS=YES\", \"ALLOW_FILE_ACCESS=YES\", NULL}; -> defaults\n\tif (ref->SetFromUserInput(input[0]) == OGRERR_NONE) {\n\t\tcrs = create_crs(ref, false);\n\t\tcrs(0) = input;\n\t} else\n\t\tcrs = create_crs(NULL);\n\tdelete ref;\n\treturn crs;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_roundtrip(Rcpp::List sfc) { // for debug purposes\n\tstd::vector<OGRGeometry *> g = ogr_from_sfc(sfc, NULL);\n\tfor (size_t i = 0; i < g.size(); i++) {\n\t\tchar *out;\n\t\tg[i]->exportToWkt(&out);\n\t\tRcpp::Rcout << out << std::endl;\n\t\tCPLFree(out);\n\t}\n\treturn sfc_from_ogr(g, true); // destroys g;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_circularstring_to_linestring(Rcpp::List sfc) { // need to pass more parameters?\n\tstd::vector<OGRGeometry *> g = ogr_from_sfc(sfc, NULL);\n\tstd::vector<OGRGeometry *> out(g.size());\n\tfor (size_t i = 0; i < g.size(); i++) {\n\t\tOGRCircularString *cs = (OGRCircularString *) g[i];\n\t\tout[i] = cs->CurveToLine();\n\t\tOGRGeometryFactory::destroyGeometry(g[i]);\n\t}\n\treturn sfc_from_ogr(out, true); // destroys out;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_multisurface_to_multipolygon(Rcpp::List sfc) { // need to pass more parameters?\n\tstd::vector<OGRGeometry *> g = ogr_from_sfc(sfc, NULL);\n\tstd::vector<OGRGeometry *> out(g.size());\n\tfor (size_t i = 0; i < g.size(); i++) {\n\t\tOGRMultiSurface *cs = (OGRMultiSurface *) g[i];\n\t\tif (cs->hasCurveGeometry(true)) {\n\t\t\tout[i] = cs->getLinearGeometry();\n\t\t\tOGRGeometryFactory::destroyGeometry(g[i]);\n\t\t} else\n\t\t\tout[i] = cs->CastToMultiPolygon(cs); // consumes cs #nocov\n\t\tif (out[i] == NULL)\n\t\t\tRcpp::stop(\"CPL_multisurface_to_multipolygon: NULL returned - non-polygonal surface?\"); // #nocov\n\t}\n\treturn sfc_from_ogr(out, true); // destroys out;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_compoundcurve_to_linear(Rcpp::List sfc) { // need to pass more parameters?\n\tstd::vector<OGRGeometry *> g = ogr_from_sfc(sfc, NULL);\n\tstd::vector<OGRGeometry *> out(g.size());\n\tfor (size_t i = 0; i < g.size(); i++) {\n\t\tOGRCompoundCurve *cs = (OGRCompoundCurve *) g[i];\n\t\tout[i] = cs->getLinearGeometry();\n\t\tOGRGeometryFactory::destroyGeometry(g[i]);\n\t}\n\treturn sfc_from_ogr(out, true); // destroys out;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_curve_to_linestring(Rcpp::List sfc) { // need to pass more parameters? #nocov start\n\tstd::vector<OGRGeometry *> g = ogr_from_sfc(sfc, NULL);\n\tstd::vector<OGRGeometry *> out(g.size());\n\tfor (size_t i = 0; i < g.size(); i++) {\n\t\tOGRCurve *cs = (OGRCurve *) g[i];\n\t\tout[i] = cs->CastToLineString(cs);\n\t}\n\treturn sfc_from_ogr(out, true); // destroys out;\n} // #nocov end\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_can_transform(Rcpp::List src, Rcpp::List dst) {\n\tif (src.size() != 2 || dst.size() != 2)\n\t\treturn false;\n\tRcpp::CharacterVector src_cv = src[0];\n\tRcpp::CharacterVector dst_cv = dst[0];\n\tif (Rcpp::CharacterVector::is_na(src_cv[0]) || Rcpp::CharacterVector::is_na(dst_cv[0]))\n\t\treturn false;\n\tOGRSpatialReference *srs_src = OGRSrs_from_crs(src);\n\tOGRSpatialReference *srs_dst = OGRSrs_from_crs(dst);\n\tunset_error_handler();\n\tOGRCoordinateTransformation *ct = OGRCreateCoordinateTransformation(srs_src, srs_dst);\n\tset_error_handler();\n\tdelete srs_src;\n\tdelete srs_dst;\n\tif (ct) {\n\t\tct->DestroyCT(ct);\n\t\treturn true;\n\t} else\n\t\treturn false;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_transform(Rcpp::List sfc, Rcpp::List crs,\n\t\tRcpp::NumericVector AOI, Rcpp::CharacterVector pipeline, bool reverse = false,\n\t\tdouble desired_accuracy = -1.0, bool allow_ballpark = true) {\n\n\t// transform geometries:\n\tstd::vector<OGRGeometry *> g = ogr_from_sfc(sfc, NULL);\n\tif (g.empty())\n\t\treturn sfc_from_ogr(g, true); // destroys g\n\n\tOGRSpatialReference *dest = NULL;\n\t// if pipeline was not set, import crs to dest:\n\tif (pipeline.size() == 0 && !(dest = OGRSrs_from_crs(crs)))\n\t\tRcpp::stop(\"crs not found: is it missing?\"); // #nocov\n\n#if GDAL_VERSION_NUM >= 3000000\n\t// OGRCoordinateTransformationOptions *options = new OGRCoordinateTransformationOptions;\n\tOGRCoordinateTransformationOptions options;\n\tif (pipeline.size() && !options.SetCoordinateOperation(pipeline[0], reverse))\n\t\tRcpp::stop(\"pipeline value not accepted\");\n\tif (AOI.size() == 4 && !options.SetAreaOfInterest(AOI[0], AOI[1], AOI[2], AOI[3]))\n\t\tRcpp::stop(\"values for area of interest not accepted\");\n#if GDAL_VERSION_NUM >= 3030000\n\toptions.SetDesiredAccuracy(desired_accuracy);\n\toptions.SetBallparkAllowed(allow_ballpark);\n#endif\n\t// unset_error_handler(); // FIXME: is this always a good idea?\n\tOGRCoordinateTransformation *ct =\n\t\tOGRCreateCoordinateTransformation(g[0]->getSpatialReference(), dest, options);\n\t// set_error_handler();\n#else\n\tif (pipeline.size() || AOI.size())\n\t\tRcpp::stop(\"pipeline or area of interest require GDAL >= 3\"); // #nocov\n\tOGRCoordinateTransformation *ct =\n\t\tOGRCreateCoordinateTransformation(g[0]->getSpatialReference(), dest);\n#endif\n\tif (ct == NULL) {\n\t\tif (dest)\n\t\t\tdest->Release(); // #nocov start\n\t\tsfc_from_ogr(g, true); // to destroy g\n\t\tRcpp::stop(\"OGRCreateCoordinateTransformation(): transformation not available\"); // #nocov end\n\t}\n\tfor (size_t i = 0; i < g.size(); i++) {\n\t\tCPLPushErrorHandler(CPLQuietErrorHandler);\n\t\tOGRErr err = 0;\n\t\tif (! g[i]->IsEmpty())\n\t\t\terr = g[i]->transform(ct);\n\t\tCPLPopErrorHandler();\n\t\tif (err == 1 || err == 6) {\n\t\t\tOGRwkbGeometryType geomType = g[i]->getGeometryType();\n\t\t\tOGRGeometryFactory::destroyGeometry(g[i]);\n\t\t\tg[i] = OGRGeometryFactory::createGeometry(geomType); // return empty geometry of this type\n\t\t} else\n\t\t\thandle_error(err);\n\t}\n\n\tRcpp::List ret = sfc_from_ogr(g, true); // destroys g;\n\t// how to return the target CRS when only a transformation pipeline is provided? Not by:\n\t// ret.attr(\"crs\") = create_crs(ct->GetTargetCS(), true);\n\t// \n\t// According to the discussion at https://github.com/r-spatial/sf/issues/2439, this is \n\t// not a solvable issue in general. See the same link for a possible workaround and \n\t// a more general solution that uses PROJ. \n\tct->DestroyCT(ct);\n\tif (dest)\n\t\tdest->Release();\n\treturn ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::NumericVector CPL_transform_bounds(Rcpp::NumericVector bb, Rcpp::List crs_dst,\n\t\tint densify_pts = 21) {\n\n\tRcpp::NumericVector ret(4);\n\tret[0] = 0.0;\n\tret[1] = 0.0;\n\tret[2] = 0.0;\n\tret[3] = 0.0;\n\tRcpp::CharacterVector names(4);\n\tnames(0) = \"xmin\";\n\tnames(1) = \"ymin\";\n\tnames(2) = \"xmax\";\n\tnames(3) = \"ymax\";\n\tret.attr(\"names\") = names;\n#if GDAL_VERSION_NUM >= 3040000\n\tif (bb.size() != 4)\n\t\tRcpp::stop(\"bb should have length 4\");\n\tRcpp::List crs_src = bb.attr(\"crs\");\n\tOGRSpatialReference *src = OGRSrs_from_crs(crs_src);\n\tOGRSpatialReference *dst = OGRSrs_from_crs(crs_dst);\n\tif (src == NULL)\n\t\tRcpp::stop(\"crs_src not found: is it missing?\"); // #nocov\n\tif (dst == NULL)\n\t\tRcpp::stop(\"crs_dst not found: is it missing?\"); // #nocov\n\tOGRCoordinateTransformation *ct = OGRCreateCoordinateTransformation(src, dst);\n\tif (ct == NULL) {\n\t\tdst->Release(); // #nocov start\n\t\tsrc->Release();\n\t\tRcpp::stop(\"transform_bounds(): transformation not available\"); // #nocov end\n\t}\n\tdouble xmin, ymin, xmax, ymax;\n\tint success = ct->TransformBounds(bb[0], bb[1], bb[2], bb[3], &xmin, &ymin, &xmax, &ymax, densify_pts);\n\tif (!success)\n\t\tRcpp::stop(\"transform_bounds(): failures encountered\"); // #nocov\n\tret[0] = xmin;\n\tret[1] = ymin;\n\tret[2] = xmax;\n\tret[3] = ymax;\n\tct->DestroyCT(ct);\n\tdst->Release();\n\tsrc->Release();\n#else\n\tRcpp::stop(\"transform_bounds() requires GDAL >= 3.4\");\n#endif\n\treturn ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_wrap_dateline(Rcpp::List sfc, Rcpp::CharacterVector opt, bool quiet = true) {\n\n\tstd::vector <char *> options = create_options(opt, quiet);\n\tstd::vector<OGRGeometry *> g = ogr_from_sfc(sfc, NULL);\n\tstd::vector<OGRGeometry *> ret(g.size());\n\tfor (size_t i = 0; i < g.size(); i++) {\n\t\tret[i] = OGRGeometryFactory::transformWithOptions(g[i], NULL, options.data());\n\t\tOGRGeometryFactory::destroyGeometry(g[i]);\n\t}\n\treturn sfc_from_ogr(ret, true); // destroys ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_get_gdal_drivers(int dummy) {\n\n\tint ndr = GetGDALDriverManager()->GetDriverCount();\n\tRcpp::CharacterVector name(ndr);\n\tRcpp::CharacterVector long_name(ndr);\n\tRcpp::LogicalVector create(ndr);\n\tRcpp::LogicalVector copy(ndr);\n\tRcpp::LogicalVector vattr(ndr);\n\tRcpp::LogicalVector rattr(ndr);\n\tRcpp::LogicalVector vsi_attr(ndr);\n\tfor (int i = 0; i < ndr; i++) {\n\t\tGDALDriver *pDriver = GetGDALDriverManager()->GetDriver(i);\n\t\tname(i) = GDALGetDriverShortName( pDriver );\n\t\tlong_name(i) = GDALGetDriverLongName( pDriver );\n\t\tcreate(i) = (pDriver->GetMetadataItem(GDAL_DCAP_CREATE) != NULL);\n\t\tcopy(i) =   (pDriver->GetMetadataItem(GDAL_DCAP_CREATECOPY) != NULL);\n\t\tvattr(i) =  (pDriver->GetMetadataItem(GDAL_DCAP_VECTOR) != NULL);\n\t\trattr(i) =  (pDriver->GetMetadataItem(GDAL_DCAP_RASTER) != NULL);\n\t\tvsi_attr(i) =  (pDriver->GetMetadataItem(GDAL_DCAP_VIRTUALIO) != NULL);\n\t}\n\treturn Rcpp::DataFrame::create(\n\t\tRcpp::Named(\"name\") = name,\n\t\tRcpp::Named(\"long_name\") = long_name,\n\t\tRcpp::Named(\"write\") = create,\n\t\tRcpp::Named(\"copy\") = copy,\n\t\tRcpp::Named(\"is_raster\") = rattr,\n\t\tRcpp::Named(\"is_vector\") = vattr,\n\t\tRcpp::Named(\"vsi\") = vsi_attr);\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_sfc_from_wkt(Rcpp::CharacterVector wkt) {\n\tstd::vector<OGRGeometry *> g(wkt.size());\n\tOGRGeometryFactory f;\n\tfor (int i = 0; i < wkt.size(); i++) {\n\t\tchar *wkt_str = wkt(i);\n#if GDAL_VERSION_NUM < 2030000\n\t\thandle_error(f.createFromWkt(&wkt_str, NULL, &(g[i])));\n#else\n\t\thandle_error(f.createFromWkt( (const char*) wkt_str, NULL, &(g[i])));\n#endif\n\t}\n\treturn sfc_from_ogr(g, true);\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_gdal_with_geos() {\n\tbool withGEOS = OGRGeometryFactory::haveGEOS();\n\treturn Rcpp::LogicalVector::create(withGEOS);\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_axis_order_authority_compliant(Rcpp::LogicalVector authority_compliant) {\n\tif (authority_compliant.size() > 1)\n\t\tRcpp::stop(\"argument authority_compliant should have length 0 or 1\"); // #nocov\n#if GDAL_VERSION_NUM < 2050000\n\tif (authority_compliant.size() == 1 && authority_compliant[0])\n\t\tRcpp::stop(\"For setting axis order compliancy, GDAL >= 2.5.0 is required\"); // #nocov\n#endif\n\tbool old_value = axis_order_authority_compliant;\n\tif (authority_compliant.size() == 1)\n\t\taxis_order_authority_compliant = authority_compliant[0];\n\treturn Rcpp::LogicalVector::create(old_value);\n}\n\nOGRSpatialReference *handle_axis_order(OGRSpatialReference *sr) {\n#if GDAL_VERSION_NUM >= 2050000\n\tif (sr != NULL) {\n\t\tif (!axis_order_authority_compliant)\n\t\t\tsr->SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);\n\t\telse\n\t\t\tsr->SetAxisMappingStrategy(OAMS_AUTHORITY_COMPLIANT);\n\t}\n#endif\n\treturn sr;\n}\n\nRcpp::CharacterVector to_cv(char **cpp) {\n\tRcpp::CharacterVector cv;\n\tfor (int i = 0; cpp[i] != NULL; i++)\n\t\tcv.push_back(cpp[i]);\n\tCSLDestroy(cpp);\n\treturn cv;\n}\n\n#if GDAL_VERSION_NUM >= 3040000\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_compressors() {\n\tRcpp::CharacterVector compressors =   to_cv(CPLGetCompressors());\n\tRcpp::CharacterVector decompressors = to_cv(CPLGetDecompressors());\n\treturn Rcpp::List::create(\n\t\t\tRcpp::_[\"compressors\"] = compressors,\n\t\t\tRcpp::_[\"decompressors\"] = decompressors\n\t\t);\n}\n#else\nRcpp::List CPL_compressors() {\n\tRcpp::stop(\"CPL_compressors() requires GDAL >= 3.4\\n\");\n\treturn Rcpp::List::create();\n}\n#endif\n"
  },
  {
    "path": "src/gdal.h",
    "content": "#ifndef SF_GDAL_H_\n#define SF_GDAL_H_\nvoid set_error_handler(void);\nvoid unset_error_handler(void);\nOGRSpatialReference *handle_axis_order(OGRSpatialReference *sr);\nRcpp::List create_crs(const OGRSpatialReference *ref, bool set_input);\nRcpp::CharacterVector wkt_from_spatial_reference(const OGRSpatialReference *srs);\nint srid_from_crs(Rcpp::List crs);\nvoid   set_config_options(Rcpp::CharacterVector ConfigOptions);\nvoid unset_config_options(Rcpp::CharacterVector ConfigOptions);\n#endif // SF_GDAL_H_\n"
  },
  {
    "path": "src/gdal_geom.cpp",
    "content": "#include <ogr_api.h>\n#include <ogr_geometry.h>\n\n#include <Rcpp.h>\n\n#include \"gdal_sf_pkg.h\"\n\n// [[Rcpp::export(rng=false)]]\nRcpp::NumericVector CPL_area(Rcpp::List sfc) { \n\tstd::vector<OGRGeometry *> g = ogr_from_sfc(sfc, NULL);\n\tRcpp::NumericVector out(sfc.length());\n\tfor (size_t i = 0; i < g.size(); i++) {\n\t\tif (g[i]->getDimension() == 2) {\n\t\t\tOGRwkbGeometryType gt = OGR_GT_Flatten(g[i]->getGeometryType());\n\t\t\tif (OGR_GT_IsSubClassOf(gt, wkbGeometryCollection)) {\n\t\t\t\t// will match OGRMultiPolygon, OGRMultiSurface and OGRGeometryCollection\n\t\t\t\tOGRGeometryCollection *gc = (OGRGeometryCollection *) g[i];\n\t\t\t\tout[i] = gc->get_Area();\n\t\t\t} else if (OGR_GT_IsSurface(gt)) {\n\t\t\t\tOGRSurface *surf = (OGRSurface *) g[i];\n\t\t\t\tout[i] = surf->get_Area();\n\t\t\t} else {\n\t\t\t\tout[i] = 0.0; // not supposed to happen, but who knows...\n\t\t\t}\n\t\t} else\n\t\t\tout[i] = 0.0;\n\t\tOGRGeometryFactory::destroyGeometry(g[i]);\n\t}\n\treturn out;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::IntegerVector CPL_gdal_dimension(Rcpp::List sfc, bool NA_if_empty = true) {\n\tstd::vector<OGRGeometry *> g = ogr_from_sfc(sfc, NULL);\n\tRcpp::IntegerVector out(sfc.length());\n\tfor (size_t i = 0; i < g.size(); i++) {\n\t\tif (NA_if_empty && g[i]->IsEmpty())\n\t\t\tout[i] = NA_INTEGER;\n\t\telse\n\t\t\tout[i] = g[i]->getDimension();\n\t\tOGRGeometryFactory f;\n\t\tf.destroyGeometry(g[i]);\n\t}\n\treturn out;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::NumericVector CPL_length(Rcpp::List sfc) { \n\tstd::vector<OGRGeometry *> g = ogr_from_sfc(sfc, NULL);\n\tRcpp::NumericVector out(sfc.length());\n\tfor (size_t i = 0; i < g.size(); i++) {\n\t\tOGRwkbGeometryType gt = OGR_GT_Flatten(g[i]->getGeometryType());\n\t\tswitch (gt) {\n\t\t\tcase wkbPoint: \n\t\t\tcase wkbMultiPoint:\n\t\t\tcase wkbPolygon:\n\t\t\tcase wkbMultiPolygon:\n\t\t\t\tout[i] = 0.0;\n\t\t\t\tbreak;\n\t\t\tcase wkbLineString:\n\t\t\tcase wkbCircularString:\n\t\t\tcase wkbCompoundCurve:\n\t\t\tcase wkbCurve: {\n\t\t\t\t\tOGRCurve *a = (OGRCurve *) g[i];\n\t\t\t\t\tout[i] = a->get_Length();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault: {\n\t\t\t\t\tif (OGR_GT_IsSubClassOf(gt, wkbGeometryCollection)) {\n\t\t\t\t\t\tOGRGeometryCollection *a = (OGRGeometryCollection *) g[i];\n\t\t\t\t\t\tout[i] = a->get_Length();\n\t\t\t\t\t} else {\n\t\t\t\t\t\tout[i] = 0.0;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t}\n\t\tOGRGeometryFactory f;\n\t\tf.destroyGeometry(g[i]);\n\t}\n\treturn out;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_gdal_segmentize(Rcpp::List sfc, double dfMaxLength = 0.0) {\n\n\tif (dfMaxLength <= 0.0)\n\t\tRcpp::stop(\"argument dfMaxLength should be positive\\n\");\n\n\tstd::vector<OGRGeometry *> g = ogr_from_sfc(sfc, NULL);\n\tfor (size_t i = 0; i < g.size(); i++)\n\t\tg[i]->segmentize(dfMaxLength);\n\tRcpp::List ret = sfc_from_ogr(g, true);\n\tret.attr(\"crs\") = sfc.attr(\"crs\");\n\treturn ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_gdal_linestring_sample(Rcpp::List sfc, Rcpp::List distLst) {\n\tif (sfc.size() != distLst.size())\n\t\tRcpp::stop(\"sfc and dist should have equal length\"); // #nocov\n\tstd::vector<OGRGeometry *> g = ogr_from_sfc(sfc, NULL);\n\tstd::vector<OGRGeometry *> out(g.size());\n\tfor (size_t i = 0; i < g.size(); i++) {\n\t\tif (wkbFlatten(g[i]->getGeometryType()) != wkbLineString)\n\t\t\tRcpp::stop(\"CPL_gdal_linestring_sample only available for LINESTRING\"); // #nocov\n\t\tOGRGeometryCollection *gc = new OGRGeometryCollection;\n\t\tRcpp::NumericVector dists = distLst[i];\n\t\tfor (int j = 0; j < dists.size(); j++) {\n\t\t\tOGRPoint *poPoint  = new OGRPoint;\n\t\t\t((OGRLineString *) g[i])->Value(dists[j], poPoint);\n\t\t\tgc->addGeometryDirectly(poPoint);\n\t\t}\n\t\tout[i] = OGRGeometryFactory::forceToMultiPoint(gc);\n\t}\n\tRcpp::List ret = sfc_from_ogr(g, true); // releases g\n\tret = sfc_from_ogr(out, true); // releases out\n\tret.attr(\"crs\") = sfc.attr(\"crs\");\n\treturn ret;\n}\n"
  },
  {
    "path": "src/gdal_read.cpp",
    "content": "#include <string>\n#include <sstream>\n\n#include <ogrsf_frmts.h>\n\n#define RCPP_DEFAULT_INCLUDE_CALL false\n#include \"Rcpp.h\"\n\n#include \"gdal_sf_pkg.h\"\n#include \"gdal_read.h\"\n\nRcpp::List allocate_out_list(OGRFeatureDefn *poFDefn, int n_features, bool int64_as_string,\n\t\tRcpp::CharacterVector fid_column) {\n\n\tif (fid_column.size() > 1)\n\t\tRcpp::stop(\"FID column name should be a length 1 character vector\"); // #nocov\n\n\tint n = poFDefn->GetFieldCount() + poFDefn->GetGeomFieldCount() + fid_column.size();\n\tRcpp::List out(n);\n\tRcpp::CharacterVector names(n);\n\tfor (int i = 0; i < poFDefn->GetFieldCount(); i++) {\n\t\tOGRFieldDefn *poFieldDefn = poFDefn->GetFieldDefn(i);\n\t\tswitch (poFieldDefn->GetType()) {\n\t\t\tcase OFTInteger: {\n\t\t\t\t\tif (poFieldDefn->GetSubType() == OFSTBoolean)\n\t\t\t\t\t\tout[i] = Rcpp::LogicalVector(n_features);\n\t\t\t\t\telse\n\t\t\t\t\t\tout[i] = Rcpp::IntegerVector(n_features);\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase OFTDate: {\n\t\t\t\tRcpp::NumericVector ret(n_features);\n\t\t\t\tret.attr(\"class\") = \"Date\";\n\t\t\t\tout[i] = ret;\n\t\t\t\t} break;\n\t\t\tcase OFTDateTime: {\n\t\t\t\tRcpp::NumericVector ret(n_features);\n\t\t\t\tRcpp::CharacterVector cls(2);\n\t\t\t\tcls(0) = \"POSIXct\";\n\t\t\t\tcls(1) = \"POSIXt\";\n\t\t\t\tret.attr(\"class\") = cls;\n\t\t\t\tout[i] = ret;\n\t\t\t\t} break;\n\t\t\tcase OFTInteger64: // fall through: converts Int64 -> double\n\t\t\t\tif (int64_as_string)\n\t\t\t\t\tout[i] = Rcpp::CharacterVector(n_features);\n\t\t\t\telse\n\t\t\t\t\tout[i] = Rcpp::NumericVector(n_features);\n\t\t\t\tbreak;\n\t\t\tcase OFTReal:\n\t\t\t\tout[i] = Rcpp::NumericVector(n_features);\n\t\t\t\tbreak;\n\t\t\tcase OFTStringList:\n\t\t\tcase OFTRealList:\n\t\t\tcase OFTIntegerList:\n\t\t\tcase OFTInteger64List:\n\t\t\tcase OFTBinary:\n\t\t\t\tout[i] = Rcpp::List(n_features);\n\t\t\t\tbreak;\n\t\t\tcase OFTString:\n\t\t\tdefault:\n\t\t\t\tout[i] = Rcpp::CharacterVector(n_features);\n\t\t\t\tbreak;\n\t\t}\n\t\tnames[i] = poFieldDefn->GetNameRef();\n\t}\n\n\tif (fid_column.size())\n\t\tnames[ poFDefn->GetFieldCount() ] = fid_column[0];\n\n\tfor (int i = 0; i < poFDefn->GetGeomFieldCount(); i++) {\n\t\t// get the geometry fields:\n\t\tOGRGeomFieldDefn *poGFDefn = poFDefn->GetGeomFieldDefn(i);\n\t\tif (poGFDefn == NULL)\n\t\t\tRcpp::stop(\"GeomFieldDefn error\"); // #nocov\n\t\tstd::string geom = \"geometry\";\n\t\tconst char *geom_name = poGFDefn->GetNameRef();\n\t\tif (*geom_name == '\\0') {\n\t\t\tif (i > 0)\n\t\t\t\tnames[i + poFDefn->GetFieldCount() + fid_column.size()] = geom + std::to_string(i); // c++11; #nocov\n\t\t\telse\n\t\t\t\tnames[i + poFDefn->GetFieldCount() + fid_column.size()] = geom;\n\t\t} else\n\t\t\tnames[i + poFDefn->GetFieldCount() + fid_column.size()] = geom_name;\n\t\tout[i + poFDefn->GetFieldCount() + fid_column.size()] = Rcpp::List(n_features); // ?\n\t}\n\n\tout.attr(\"names\") = names;\n\treturn out;\n}\n\nOGRwkbGeometryType to_multi_what(std::vector<OGRGeometry *> gv) {\n\tbool points = false, multipoints = false,\n\t\tlines = false, multilines = false,\n\t\tpolygons = false, multipolygons = false;\n\n\tfor (unsigned int i = 0; i < gv.size(); i++) {\n\t\t// drop Z and M:\n\t\tif (gv[i] == NULL)\n\t\t\tbreak;\n\t\tOGRwkbGeometryType gt = OGR_GT_SetModifier(gv[i]->getGeometryType(), 0, 0);\n\t\tswitch(gt) {\n\t\t\tcase wkbPoint: points = true; break;\n\t\t\tcase wkbMultiPoint: multipoints = true; break;\n\t\t\tcase wkbLineString: lines = true; break;\n\t\t\tcase wkbMultiLineString: multilines = true; break;\n\t\t\tcase wkbPolygon: polygons = true; break;\n\t\t\tcase wkbMultiPolygon: multipolygons = true; break;\n\t\t\tdefault: return wkbUnknown; // #nocov\n\t\t}\n\t}\n\tint sum = points + multipoints + lines + multilines + polygons + multipolygons;\n\tif (sum == 2) {\n\t\tif (points && multipoints)\n\t\t\treturn wkbMultiPoint;\n\t\tif (lines && multilines)\n\t\t\treturn wkbMultiLineString;\n\t\tif (polygons && multipolygons)\n\t\t\treturn wkbMultiPolygon;\n\t}\n\t// another mix or single type:\n\treturn wkbUnknown;\n}\n\nsize_t count_features(OGRLayer *poLayer) {\n\tsize_t n = 0;\n\tOGRFeature *poFeature;\n\twhile((poFeature = poLayer->GetNextFeature()) != NULL) {\n\t\tn++;\n\t\tdelete poFeature;\n\t\tif (n == INT_MAX)\n\t\t\tRcpp::stop(\"Cannot read layer with more than MAX_INT features\"); // #nocov\n\t}\n\tpoLayer->ResetReading ();\n\treturn n;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_get_layers(Rcpp::CharacterVector datasource, Rcpp::CharacterVector options, bool do_count = false) {\n\n\tif (datasource.size() != 1)\n\t\tRcpp::stop(\"argument datasource should have length 1.\\n\"); // #nocov\n\tstd::vector <char *> open_options = create_options(options, false);\n\tGDALDataset *poDS;\n\tpoDS = (GDALDataset *) GDALOpenEx(datasource[0], GDAL_OF_VECTOR | GDAL_OF_READONLY, NULL,\n\t\topen_options.data(), NULL);\n\tif (poDS == NULL) {\n\t\tRcpp::Rcout << \"Cannot open data source \" << datasource[0] << std::endl;\n\t\tRcpp::stop(\"Open failed.\\n\");\n\t}\n\t// template from ogrinfo.cpp:\n\tRcpp::CharacterVector names(poDS->GetLayerCount());\n\tRcpp::List geomtype(poDS->GetLayerCount());\n\tRcpp::NumericVector field_count(poDS->GetLayerCount());\n\tRcpp::NumericVector feature_count(poDS->GetLayerCount());\n\tRcpp::List layer_crs(poDS->GetLayerCount());\n\n\tfor(int iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++) {\n\t\tOGRLayer *poLayer = poDS->GetLayer(iLayer);\n\t\tlayer_crs[iLayer] = create_crs(poLayer->GetSpatialRef());\n\t\tnames(iLayer) = poLayer->GetName();\n\t\tint nGeomFieldCount = poLayer->GetLayerDefn()->GetGeomFieldCount();\n\t\tif (nGeomFieldCount == 0) {\n\t\t\tRcpp::CharacterVector fieldtp(1); // #nocov start ; though tested in #334\n\t\t\tfieldtp(0) = NA_STRING;\n\t\t\tgeomtype(iLayer) = fieldtp;       // #nocov end\n\t\t} else {\n\t\t\tRcpp::CharacterVector fieldtp(nGeomFieldCount);\n\t\t\tif( nGeomFieldCount > 1 ) {\n\t\t\t\tfor(int iGeom = 0; iGeom < nGeomFieldCount; iGeom ++ ) {\n\t\t\t\t\tOGRGeomFieldDefn* poGFldDefn = poLayer->GetLayerDefn()->GetGeomFieldDefn(iGeom);\n\t\t\t\t\tfieldtp(iGeom) = OGRGeometryTypeToName(poGFldDefn->GetType());\n\t\t\t\t}\n\t\t\t} else if (poLayer->GetGeomType() != wkbUnknown)\n\t\t\t\tfieldtp(0) = OGRGeometryTypeToName(poLayer->GetGeomType());\n\t\t\tgeomtype(iLayer) = fieldtp;\n\t\t}\n\t\tOGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();\n\t\tfield_count(iLayer) = poFDefn->GetFieldCount();\n\t\tfeature_count(iLayer) = poLayer->GetFeatureCount();\n\t\tif (feature_count(iLayer) < 0 && do_count)\n\t\t\tfeature_count(iLayer) = count_features(poLayer);\n\t}\n\n\tRcpp::List ret = Rcpp::List::create(\n\t\tRcpp::_[\"name\"] = names,\n\t\tRcpp::_[\"geomtype\"] = geomtype,\n\t\tRcpp::_[\"driver\"] = poDS->GetDriverName(),\n\t\tRcpp::_[\"features\"] = feature_count,\n\t\tRcpp::_[\"fields\"] = field_count,\n\t\tRcpp::_[\"crs\"] = layer_crs);\n\tGDALClose(poDS); // close & destroys data source\n\treturn ret;\n}\n\nRcpp::List sf_from_ogrlayer(OGRLayer *poLayer, bool quiet, bool int64_as_string,\n\t\tRcpp::NumericVector toTypeUser, Rcpp::CharacterVector fid_column, \n\t\tbool promote_to_multi = true, int nfeatures = -1) {\n\n\tOGRFeatureDefn *poFDefn = poLayer->GetLayerDefn();\n\n\tsize_t n = 0;\n\tif (nfeatures == -1) {\n\t\tdouble n_d = (double) poLayer->GetFeatureCount();\n\t\tif (n_d > INT_MAX)\n\t\t\tRcpp::stop(\"Cannot read layer with more than MAX_INT features\"); // #nocov\n\t\tif (n_d < 0)\n\t\t\tn_d = (double) count_features(poLayer);\n\t\tn = (size_t) n_d; // what is List's max length?\n\t } else\n\t\tn = nfeatures;\n\n\tstd::vector<OGRFeature *> poFeatureV(n); // full archive\n\tRcpp::CharacterVector fids(n);\n\n\tstd::vector<OGRGeometry *> poGeometryV(n * poFDefn->GetGeomFieldCount());\n\t// cycles column wise: 2nd el is 1st geometry, 2nd feature\n\n\tRcpp::List out = allocate_out_list(poFDefn, n, int64_as_string, fid_column);\n\n\t// read all features:\n\tpoLayer->ResetReading();\n\tsize_t i = 0; // feature counter\n\tdouble dbl_max_int64 = pow(2.0, 53);\n\tbool warn_int64 = false, has_null_geometries = false;\n\tOGRFeature *poFeature;\n\twhile ((poFeature = poLayer->GetNextFeature()) != NULL) {\n\t\tif (i > (n - 1)) {\n\t\t\tRcpp::warning(\"more features available than GetFeatureCount() reported: some records may be failing\");\n\t\t\tbreak;\n\t\t}\n\t\t// getFID:\n\t\tfids[i] = std::to_string(poFeature->GetFID());\n\n\t\t// feature attribute fields:\n\t\tfor (int iField = 0; iField < poFDefn->GetFieldCount(); iField++ ) {\n\t\t\tOGRFieldDefn *poFieldDefn = poFDefn->GetFieldDefn( iField );\n#if GDAL_VERSION_NUM >= 2020000\n\t\t\tint not_NA = poFeature->IsFieldSetAndNotNull(iField);\n#else\n\t\t\tint not_NA = poFeature->IsFieldSet(iField);\n#endif\n\t\t\tswitch(poFieldDefn->GetType()) {\n\t\t\t\tcase OFTInteger: {\n\t\t\t\t\tif (poFieldDefn->GetSubType() == OFSTBoolean) {\n\t\t\t\t\t\tRcpp::LogicalVector lv;\n\t\t\t\t\t\tlv = out[iField];\n\t\t\t\t\t\tif (not_NA) {\n\t\t\t\t\t\t\tif (poFeature->GetFieldAsInteger(iField))\n\t\t\t\t\t\t\t\tlv[i] = true;\n\t\t\t\t\t\t\telse\n\t\t\t\t\t\t\t\tlv[i] = false;\n\t\t\t\t\t\t} else\n\t\t\t\t\t\t\tlv[i] = NA_LOGICAL;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tRcpp::IntegerVector iv;\n\t\t\t\t\t\tiv = out[iField];\n\t\t\t\t\t\tif (not_NA)\n\t\t\t\t\t\t\tiv[i] = poFeature->GetFieldAsInteger(iField);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tiv[i] = NA_INTEGER;\n\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase OFTInteger64: {\n\t\t\t\t\tif (int64_as_string) {\n\t\t\t\t\t\tRcpp::CharacterVector cv;\n\t\t\t\t\t\tcv = out[iField];\n\t\t\t\t\t\tif (not_NA)\n\t\t\t\t\t\t\tcv[i] = poFeature->GetFieldAsString(iField);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tcv[i] = NA_STRING;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tRcpp::NumericVector nv;\n\t\t\t\t\t\tnv = out[iField];\n\t\t\t\t\t\tif (not_NA)\n\t\t\t\t\t\t\tnv[i] = (double) poFeature->GetFieldAsInteger64(iField);\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tnv[i] = NA_REAL;\n\t\t\t\t\t\t// OR: poFeature->GetFieldAsString(iField);\n\t\t\t\t\t\tif (nv[i] > dbl_max_int64)\n\t\t\t\t\t\t\twarn_int64 = true;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase OFTDateTime:\n\t\t\t\tcase OFTDate: {\n\t\t\t\t\tint Year, Month, Day, Hour, Minute, TZFlag;\n\t\t\t\t\tfloat Second;\n\t\t\t\t\tconst char *tzone = \"\";\n\t\t\t\t\tpoFeature->GetFieldAsDateTime(iField, &Year, &Month, &Day, &Hour, &Minute,\n\t\t\t\t\t\t&Second, &TZFlag);\n\t\t\t\t\tif (TZFlag == 100)\n\t\t\t\t\t\ttzone = \"UTC\";\n\t\t\t\t\t//  POSIXlt: sec   min  hour  mday   mon  year  wday  yday isdst ...\n\t\t\t\t\tRcpp::List dtlst =\n\t\t\t\t\t\tRcpp::List::create(\n\t\t\t\t\t\t\tRcpp::_[\"sec\"] = (double) Second,\n\t\t\t\t\t\t\tRcpp::_[\"min\"] = (int) Minute,\n\t\t\t\t\t\t\tRcpp::_[\"hour\"] = (int) Hour,\n\t\t\t\t\t\t\tRcpp::_[\"mday\"] = (int) Day,\n\t\t\t\t\t\t\tRcpp::_[\"mon\"] = (int) Month - 1,\n\t\t\t\t\t\t\tRcpp::_[\"year\"] = (int) Year - 1900,\n\t\t\t\t\t\t\tRcpp::_[\"wday\"] = NA_INTEGER,\n\t\t\t\t\t\t\tRcpp::_[\"yday\"] = NA_INTEGER,\n\t\t\t\t\t\t\tRcpp::_[\"isdst\"] = NA_INTEGER,\n\t\t\t\t\t\t\tRcpp::_[\"zone\"] = tzone,\n\t\t\t\t\t\t\tRcpp::_[\"gmtoff\"] = NA_INTEGER);\n\t\t\t\t\tif (TZFlag == 100)\n\t\t\t\t\t\tdtlst.attr(\"tzone\") = \"UTC\";\n\t\t\t\t\tdtlst.attr(\"class\") = \"POSIXlt\";\n\t\t\t\t\tRcpp::NumericVector nv;\n\t\t\t\t\tnv = out[iField];\n\t\t\t\t\tif (! not_NA) {\n\t\t\t\t\t\tnv[i] = NA_REAL;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tif (poFieldDefn->GetType() == OFTDateTime) {\n\t\t\t\t\t\tRcpp::Function as_POSIXct_POSIXlt(\"as.POSIXct.POSIXlt\");\n\t\t\t\t\t\tRcpp::NumericVector ret = as_POSIXct_POSIXlt(dtlst); // R help me!\n\t\t\t\t\t\tnv[i] = ret[0];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tRcpp::Function as_Date_POSIXlt(\"as.Date.POSIXlt\");\n\t\t\t\t\t\tRcpp::NumericVector ret = as_Date_POSIXlt(dtlst); // R help me!\n\t\t\t\t\t\tnv[i] = ret[0];\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase OFTReal: {\n\t\t\t\t\tRcpp::NumericVector nv;\n\t\t\t\t\tnv = out[iField];\n\t\t\t\t\tif (not_NA)\n\t\t\t\t\t\tnv[i] = (double) poFeature->GetFieldAsDouble(iField);\n\t\t\t\t\telse\n\t\t\t\t\t\tnv[i] = NA_REAL;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase OFTStringList: {\n\t\t\t\t\tRcpp::List lv;\n\t\t\t\t\tlv = out[iField];\n\t\t\t\t\tchar **sl = poFeature->GetFieldAsStringList(iField);\n\t\t\t\t\tRcpp::CharacterVector cv(CSLCount(sl));\n\t\t\t\t\tfor (int j = 0; j < cv.size(); j++)\n\t\t\t\t\t\tcv[j] = sl[j];\n\t\t\t\t\tlv[i] = cv;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase OFTRealList: {\n\t\t\t\t\t// for all *List types, NA is handled by zero-length lists\n\t\t\t\t\tRcpp::List lv; // #nocov start\n\t\t\t\t\tlv = out[iField];\n\t\t\t\t\tint n;\n\t\t\t\t\tconst double *dl = poFeature->GetFieldAsDoubleList(iField, &n);\n\t\t\t\t\tRcpp::NumericVector nv(n);\n\t\t\t\t\tfor (int j = 0; j < nv.size(); j++)\n\t\t\t\t\t\tnv[j] = dl[j];\n\t\t\t\t\tlv[i] = nv;\n\t\t\t\t\t}\n\t\t\t\t\tbreak; // #nocov end\n\t\t\t\tcase OFTIntegerList: {\n\t\t\t\t\tRcpp::List lv;\n\t\t\t\t\tlv = out[iField];\n\t\t\t\t\tint n;\n\t\t\t\t\tconst int *il = poFeature->GetFieldAsIntegerList(iField, &n);\n\t\t\t\t\tRcpp::IntegerVector iv(n);\n\t\t\t\t\tfor (int j = 0; j < iv.size(); j++)\n\t\t\t\t\t\tiv[j] = il[j];\n\t\t\t\t\tlv[i] = iv;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase OFTInteger64List: {\n\t\t\t\t\tRcpp::List lv;\n\t\t\t\t\tlv = out[iField];\n\t\t\t\t\tint n;\n\t\t\t\t\tconst GIntBig *int64list = poFeature->GetFieldAsInteger64List(iField, &n);\n\t\t\t\t\tif (int64_as_string) {\n\t\t\t\t\t\tRcpp::CharacterVector cv(n);\n\t\t\t\t\t\tfor (int j = 0; j < cv.size(); j++) {\n\t\t\t\t\t\t\tstd::stringstream stream;\n\t\t\t\t\t\t\tstream << int64list[j];\n\t\t\t\t\t\t\tcv[j] = stream.str();\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlv[i] = cv;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tRcpp::NumericVector nv(n);\n\t\t\t\t\t\tfor (int j = 0; j < nv.size(); j++) {\n\t\t\t\t\t\t\tnv[j] = (double) int64list[j];\n\t\t\t\t\t\t\tif (nv[j] > dbl_max_int64)\n\t\t\t\t\t\t\t\t\twarn_int64 = true; // #nocov\n\t\t\t\t\t\t}\n\t\t\t\t\t\tlv[i] = nv;\n\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tcase OFTBinary: {\n\t\t\t\t\tRcpp::List lv;\n\t\t\t\t\tlv = out[iField];\n\t\t\t\t\tint n;\n\t\t\t\t\tconst GByte *bl = poFeature->GetFieldAsBinary(iField, &n);\n\t\t\t\t\tRcpp::RawVector rv(n);\n\t\t\t\t\tfor (int j = 0; j < rv.size(); j++)\n\t\t\t\t\t\trv[j] = bl[j];\n\t\t\t\t\tlv[i] = rv;\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t\tdefault: // break through: anything else to be converted to string?\n\t\t\t\tcase OFTString: {\n\t\t\t\t\tRcpp::CharacterVector cv;\n\t\t\t\t\tcv = out[iField];\n\t\t\t\t\tif (not_NA)\n\t\t\t\t\t\tcv[i] = poFeature->GetFieldAsString(iField);\n\t\t\t\t\telse\n\t\t\t\t\t\tcv[i] = NA_STRING;\n\t\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// feature geometry:\n\t\tfor (int iGeom = 0; iGeom < poFDefn->GetGeomFieldCount(); iGeom++ ) {\n\t\t\tpoGeometryV[i + n * iGeom] = poFeature->GetGeomFieldRef(iGeom);\n\t\t\tif (poGeometryV[i + n * iGeom] == NULL)\n\t\t\t\thas_null_geometries = true;\n\t\t}\n\n\t\tpoFeatureV[i] = poFeature;\n\t\ti++;\n\t} // all read...\n\tif (i < n) { // re-read with preset n: see https://github.com/r-spatial/sf/issues/2248\n\t\tRcpp::Rcout << \"Re-reading with feature count reset from \" << n << \" to \" << i << std::endl;\n\t\treturn sf_from_ogrlayer(poLayer, quiet, int64_as_string, toTypeUser, fid_column, promote_to_multi, i);\n\t} else { \n\n\t\t// add feature IDs if needed:\n\t\tif (fid_column.size())\n\t\t\tout[ poFDefn->GetFieldCount() ] = fids;\n\n\t\tstd::vector<OGRGeometry *> to_be_freed;\n\t\tfor (int iGeom = 0; iGeom < poFDefn->GetGeomFieldCount(); iGeom++ ) {\n\n\t\t\tstd::vector<OGRGeometry *> poGeom(n);\n\t\t\tfor (i = 0; i < n; i++)\n\t\t\t\tpoGeom[i] = poGeometryV[i + n * iGeom];\n\n\t\t\tOGRwkbGeometryType toType = wkbUnknown, toTypeU = wkbUnknown;\n\t\t\tif (toTypeUser.size() == poFDefn->GetGeomFieldCount())\n\t\t\t\ttoTypeU = (OGRwkbGeometryType) toTypeUser[iGeom];\n\t\t\telse\n\t\t\t\ttoTypeU = (OGRwkbGeometryType) toTypeUser[0];\n\t\t\tif (promote_to_multi && toTypeU == wkbUnknown)\n\t\t\t\ttoType = to_multi_what(poGeom);\n\t\t\telse\n\t\t\t\ttoType = toTypeU;\n\n\t\t\tif (toType != 0) { // coerce to toType:\n\t\t\t\t// OGRGeomFieldDefn *poGFDefn = poFDefn->GetGeomFieldDefn(i);\n\t\t\t\tfor (i = 0; i < poFeatureV.size(); i++) {\n\t\t\t\t\tOGRGeometry *geom = poFeatureV[i]->StealGeometry(iGeom); // transfer ownership\n\t\t\t\t\tif (geom == NULL)\n\t\t\t\t\t\tgeom = OGRGeometryFactory::createGeometry((OGRwkbGeometryType) toType); // #nocov\n\t\t\t\t\telse if ((geom =\n#if GDAL_VERSION_NUM >= 3130000\n\t\t\t\t\t\t\tOGRGeometryFactory::forceTo(std::unique_ptr<OGRGeometry>(geom), (OGRwkbGeometryType) toType, NULL).release()\n#else\n\t\t\t\t\t\t\tOGRGeometryFactory::forceTo(geom, (OGRwkbGeometryType) toType, NULL)\n#endif\n\t\t\t\t\t\t\t) == NULL)\n\t\t\t\t\t\tRcpp::stop(\"OGRGeometryFactory::forceTo returned NULL\"); // #nocov\n\t\t\t\t\thandle_error(poFeatureV[i]->SetGeomFieldDirectly(iGeom, geom));\n\t\t\t\t\tpoGeom[i] = poFeatureV[i]->GetGeomFieldRef(iGeom);\n\t\t\t\t\tif (poGeom[i] == NULL)\n\t\t\t\t\t\tRcpp::stop(\"GetGeomFieldRef returned NULL\"); // #nocov\n\t\t\t\t}\n\t\t\t} else if (has_null_geometries) {\n\t\t\t\tif (! quiet)\n\t\t\t\t\tRcpp::Rcout << \"replacing null geometries with empty geometries\" << std::endl; // #nocov\n\n\t\t\t\t// replace null's with empty:\n\t\t\t\tOGRwkbGeometryType gt = wkbGeometryCollection;\n\t\t\t\tfor (i = 0; i < poGeom.size(); i++) {\n\t\t\t\t\tif (poGeom[i] != NULL) {\n\t\t\t\t\t\tgt = poGeom[i]->getGeometryType(); // first non-NULL\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tfor (i = 0; i < poGeom.size(); i++) {\n\t\t\t\t\tif (poGeom[i] == NULL) {\n\t\t\t\t\t\tpoGeom[i] = OGRGeometryFactory::createGeometry(gt);\n\t\t\t\t\t\tif (poGeom[i] == NULL)\n\t\t\t\t\t\t\tRcpp::stop(\"createGeometry returned NULL\"); // #nocov\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tto_be_freed.push_back(poGeom[i]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (! quiet && toTypeU != 0 && n > 0)\n\t\t\t\tRcpp::Rcout << \"converted into: \" << poGeom[0]->getGeometryName() << std::endl; // #nocov\n\t\t\t// convert to R:\n\t\t\tRcpp::List sfc = sfc_from_ogr(poGeom, false); // don't destroy\n\t\t\tOGRGeomFieldDefn *fdfn = poFDefn->GetGeomFieldDefn(iGeom);\n\t\t\tsfc.attr(\"crs\") = create_crs(fdfn->GetSpatialRef()); // overwrite: see #449 for the reason why\n\t\t\tout[iGeom + poFDefn->GetFieldCount() + fid_column.size()] = sfc;\n\t\t}\n\n\t\tif (warn_int64)\n\t\t\tRcpp::Rcout << \"Integer64 values larger than \" << dbl_max_int64 <<\n\t\t\t\t\" lost significance after conversion to double;\" << std::endl <<\n\t\t\t\t\"use argument int64_as_string = TRUE to import them lossless, as character\" << std::endl;\n\n\t\t// clean up:\n\t\tfor (i = 0; i < n; i++)\n\t\t\tOGRFeature::DestroyFeature(poFeatureV[i]);\n\t\tfor (i = 0; i < to_be_freed.size(); i++)\n\t\t\tOGRGeometryFactory::destroyGeometry(to_be_freed[i]);\n\n\t\treturn out;\n\t}\n}\n\nstatic void finalize_dataset_xptr(SEXP dataset_xptr) {\n\tGDALDataset *poDS = (GDALDataset*)R_ExternalPtrAddr(dataset_xptr);\n\tif (poDS != nullptr) {\n\t\tGDALClose(poDS);\n\t}\n}\n\nRcpp::List CPL_ogr_layer_setup(Rcpp::CharacterVector datasource, Rcpp::CharacterVector layer,\n\t\tRcpp::CharacterVector query,\n\t\tRcpp::CharacterVector options, bool quiet, Rcpp::CharacterVector drivers,\n\t\tRcpp::CharacterVector wkt_filter,\n\t\tbool dsn_exists,\n\t\tbool dsn_isdb,\n\t\tint width) {\n    // adapted from the OGR tutorial @ www.gdal.org\n\tstd::vector <char *> open_options = create_options(options, quiet);\n\tstd::vector <char *> drivers_v = create_options(drivers, quiet);\n\tGDALDataset *poDS;\n\tpoDS = (GDALDataset *) GDALOpenEx( datasource[0], GDAL_OF_VECTOR | GDAL_OF_READONLY,\n\t\tdrivers.size() ? drivers_v.data() : NULL, open_options.data(), NULL );\n\tif( poDS == NULL ) {\n\t\t// could not open dsn\n\t\tif( dsn_isdb ) {\n\t\t\tRcpp::stop(\"Cannot open %s; Check connection parameters.\", datasource);\n\t\t}\n\t\tif( dsn_exists ) {\n\t\t\tRcpp::stop(\"Cannot open %s; %s %s\",\n              datasource,\n              \"The source could be corrupt or not supported.\",\n              \"See `st_drivers()` for a list of supported formats.\");\n\t\t}\n\t\tRcpp::stop(\"Cannot open %s; The file doesn't seem to exist.\", datasource);\n\t}\n\n\t// Will close the dataset if some early return/exception prevents GDALClose() from being\n\t// called/allows the result to be accessed by the caller.\n\tRcpp::RObject dataset_xptr = R_MakeExternalPtr(poDS, R_NilValue, R_NilValue);\n\tR_RegisterCFinalizer(dataset_xptr, &finalize_dataset_xptr);\n\n\tif (layer.size() == 0 && Rcpp::CharacterVector::is_na(query[0])) { // no layer specified\n\t\tswitch (poDS->GetLayerCount()) {\n\t\t\tcase 0: { // error:\n\t\t\t\tRcpp::stop(\"No layers in datasource.\");\n\t\t\t}\n\t\t\tcase 1: { // silent:\n\t\t\t\tOGRLayer *poLayer = poDS->GetLayer(0);\n\t\t\t\tlayer = Rcpp::CharacterVector::create(poLayer->GetName());\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: { // select first layer: message + warning:\n\t\t\t\tOGRLayer *poLayer = poDS->GetLayer(0);\n\t\t\t\tlayer = Rcpp::CharacterVector::create(poLayer->GetName());\n\t\t\t\tif (! quiet) { // #nocov start\n\t\t\t\t\tRcpp::Rcout << \"Multiple layers are present in data source \" << datasource[0] << \", \";\n\t\t\t\t\tRcpp::Rcout << \"reading layer `\" << layer[0] << \"'.\" << std::endl;\n\t\t\t\t\tRcpp::Rcout << \"Use `st_layers' to list all layer names and their type in a data source.\" << std::endl;\n\t\t\t\t\tRcpp::Rcout << \"Set the `layer' argument in `st_read' to read a particular layer.\" << std::endl;\n\t\t\t\t} // #nocov end\n\t\t\t\tRcpp::Function warning(\"warning\");\n\t\t\t\twarning(\"automatically selected the first layer in a data source containing more than one.\");\n\t\t\t}\n\t\t}\n\t}\n\n\tOGRLayer *poLayer;\n\tif (! Rcpp::CharacterVector::is_na(query[0])) {\n\t\tpoLayer = poDS->ExecuteSQL(query[0], NULL, NULL);\n\t\tif (poLayer == NULL)\n\t\t\tRcpp::stop(\"Query execution failed, cannot open layer.\\n\"); // #nocov\n\t\tif (layer.size())\n\t\t\tRcpp::warning(\"argument layer is ignored when query is specified\\n\"); // #nocov\n\t} else\n\t\tpoLayer = \tpoDS->GetLayerByName(layer[0]);\n\tif (poLayer == NULL) {\n\t\tRcpp::Rcout << \"Cannot open layer \" << layer[0] << std::endl;\n\t\tRcpp::stop(\"Opening layer failed.\\n\");\n\t}\n\n\t// set spatial filter?\n\tif (wkt_filter.size()) {\n\t\tchar *wkt = wkt_filter[0];\n\t\tOGRGeometry *new_geom;\n#if GDAL_VERSION_NUM < 2030000\n\t\tOGRErr err = OGRGeometryFactory::createFromWkt(&wkt, poLayer->GetSpatialRef(), &new_geom);\n#else\n\t\tOGRErr err = OGRGeometryFactory::createFromWkt((const char *) wkt, poLayer->GetSpatialRef(), &new_geom);\n#endif\n\t\tif (err != OGRERR_NONE) {\n\t\t\tRcpp::Rcout << \"Cannot create geometry from: \" << wkt_filter[0] << std::endl;\n\t\t\tRcpp::stop(\"wkt parse error.\\n\");\n\t\t}\n\t\tpoLayer->SetSpatialFilter(new_geom);\n\t\tOGRGeometryFactory::destroyGeometry(new_geom);\n\t}\n\n\tif (! quiet) {\n\t\tif (! Rcpp::CharacterVector::is_na(query[0]))\n\t\t\tRcpp::Rcout << \"Reading query `\" << query[0] << \"'\" << std::endl << \"from data source \";\n\t\telse\n\t\t\tRcpp::Rcout << \"Reading layer `\" << layer[0] << \"' from data source \";\n\t\t// if (LENGTH(datasource[0]) > (width - (34 + LENGTH(layer[0]))))\n\t\tRcpp::String ds(datasource(0));\n\t\tif (layer.size()) {\n\t\t\tRcpp::String la(layer(0));\n\t\t\tif (strlen(ds.get_cstring()) > (width - (34 + strlen(la.get_cstring()))))\n\t\t\t\tRcpp::Rcout << std::endl << \"  \";\n\t\t}\n\t\tRcpp::Rcout << \"`\" << datasource[0] << \"' \";\n\t\tif (((int) strlen(ds.get_cstring())) > (width - 25))\n\t\t\tRcpp::Rcout << std::endl << \"  \";\n\t\tRcpp::Rcout << \"using driver `\" << poDS->GetDriverName() << \"'\" << std::endl;                       // #nocov\n\t}\n\n\t// Keeps the dataset external pointer alive as long as the layer external pointer is alive\n\tRcpp::RObject layer_xptr = R_MakeExternalPtr(poLayer, R_NilValue, dataset_xptr);\n\n\treturn Rcpp::List::create(dataset_xptr, layer_xptr);\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_read_ogr(Rcpp::CharacterVector datasource, Rcpp::CharacterVector layer,\n\t\tRcpp::CharacterVector query,\n\t\tRcpp::CharacterVector options, bool quiet, Rcpp::NumericVector toTypeUser,\n\t\tRcpp::CharacterVector fid_column_name, Rcpp::CharacterVector drivers,\n\t\tRcpp::CharacterVector wkt_filter,\n\t\tbool promote_to_multi = true, bool int64_as_string = false,\n\t\tbool dsn_exists = true,\n\t\tbool dsn_isdb = false,\n\t\tint width = 80) {\n    Rcpp::List prep = CPL_ogr_layer_setup(datasource, layer, query, options,\n\t\t\t\t\t\t\tquiet,  drivers,\n\t\t\t\t\t\t\twkt_filter,\n\t\t\t\t\t\t\tdsn_exists, dsn_isdb, width);\n\tOGRDataSource* poDS = (OGRDataSource*)(R_ExternalPtrAddr(prep[0]));\n\tOGRLayer* poLayer = (OGRLayer*)R_ExternalPtrAddr(prep[1]);\n\n\tRcpp::List out = sf_from_ogrlayer(poLayer, quiet, int64_as_string, toTypeUser, fid_column_name,\n\t\tpromote_to_multi, -1);\n\n\t// clean up if SQL was used https://www.gdal.org/classGDALDataset.html#ab2c2b105b8f76a279e6a53b9b4a182e0\n\tif (! Rcpp::CharacterVector::is_na(query[0]))\n\t\tpoDS->ReleaseResultSet(poLayer);\n\n\tGDALClose(poDS);\n\tR_SetExternalPtrAddr(prep[0], nullptr);\n\treturn out;\n}\n"
  },
  {
    "path": "src/gdal_read.h",
    "content": "#ifndef SF_GDAL_READ_H_\n#define SF_GDAL_READ_H_\nRcpp::List sf_from_ogrlayer(OGRLayer *poLayer, bool quiet, bool int64_as_string,\n\t\tRcpp::NumericVector toTypeUser, Rcpp::CharacterVector fid_column, bool promote_to_multi,\n\t\tint nfeatures);\n\nRcpp::List CPL_ogr_layer_setup(Rcpp::CharacterVector datasource, Rcpp::CharacterVector layer,\n\t\tRcpp::CharacterVector query,\n\t\tRcpp::CharacterVector options, bool quiet, Rcpp::CharacterVector drivers,\n\t\tRcpp::CharacterVector wkt_filter,\n\t\tbool dsn_exists,\n\t\tbool dsn_isdb,\n\t\tint width);\n\nRcpp::List CPL_read_gdal(Rcpp::CharacterVector fname, Rcpp::CharacterVector options, Rcpp::CharacterVector driver,\n\t\tbool read_data, Rcpp::NumericVector NA_value, Rcpp::List RasterIO_parameters);\n#endif //  SF_GDAL_READ_H_\n"
  },
  {
    "path": "src/gdal_read_stream.cpp",
    "content": "\n#include <ogrsf_frmts.h>\n\n#define RCPP_DEFAULT_INCLUDE_CALL false\n#include \"Rcpp.h\"\n\n#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)\n\n#include <ogr_recordbatch.h>\n#include \"gdal_read.h\"\n\nclass GDALStreamWrapper {\npublic:\n    static void Make(struct ArrowArrayStream* stream, Rcpp::List shelter,\n                     struct ArrowArrayStream* stream_out) {\n        stream_out->get_schema = &get_schema_wrap;\n        stream_out->get_next = &get_next_wrap;\n        stream_out->get_last_error = &get_last_error_wrap;\n        stream_out->release = &release_wrap;\n        stream_out->private_data = new GDALStreamWrapper(stream, shelter);\n    }\n\n    ~GDALStreamWrapper() {\n        stream_.release(&stream_);\n        GDALDataset* poDS = (GDALDataset*)R_ExternalPtrAddr(shelter_[0]);\n        GDALClose(poDS);\n        R_SetExternalPtrAddr(shelter_[0], nullptr);\n    }\n\nprivate:\n    // The parent stream as returned from GDAL\n    struct ArrowArrayStream stream_;\n    Rcpp::List shelter_;\n\n    GDALStreamWrapper(struct ArrowArrayStream* stream, Rcpp::List shelter):\n        shelter_(shelter) {\n        memcpy(&stream_, stream, sizeof(struct ArrowArrayStream));\n        stream->release = nullptr;\n    }\n\n    int get_schema(struct ArrowSchema* out) {\n        return stream_.get_schema(&stream_, out);\n    }\n\n    int get_next(struct ArrowArray* out) {\n        return stream_.get_next(&stream_, out);\n    }\n\n    const char* get_last_error() {\n        return stream_.get_last_error(&stream_);\n    }\n\n    static int get_schema_wrap(struct ArrowArrayStream* stream, struct ArrowSchema* out) {\n        return reinterpret_cast<GDALStreamWrapper*>(stream->private_data)->get_schema(out);\n    }\n\n    static int get_next_wrap(struct ArrowArrayStream* stream, struct ArrowArray* out) {\n        return reinterpret_cast<GDALStreamWrapper*>(stream->private_data)->get_next(out);\n    }\n\n    static const char* get_last_error_wrap(struct ArrowArrayStream* stream) {\n        return reinterpret_cast<GDALStreamWrapper*>(stream->private_data)->get_last_error();\n    }\n\n    static void release_wrap(struct ArrowArrayStream* stream) {\n        delete reinterpret_cast<GDALStreamWrapper*>(stream->private_data);\n        stream->release = nullptr;\n    }\n};\n\n#endif\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_read_gdal_stream(\n        Rcpp::RObject stream_xptr,\n        Rcpp::CharacterVector datasource, Rcpp::CharacterVector layer,\n\t\tRcpp::CharacterVector query,\n\t\tRcpp::CharacterVector options, bool quiet, Rcpp::CharacterVector drivers,\n\t\tRcpp::CharacterVector wkt_filter,\n\t\tbool dsn_exists,\n\t\tbool dsn_isdb,\n        Rcpp::CharacterVector fid_column,\n\t\tint width) {\n\n#if GDAL_VERSION_NUM >= GDAL_COMPUTE_VERSION(3,6,0)\n\n    const char* array_stream_options[] = {\"INCLUDE_FID=NO\", nullptr};\n    if (fid_column.size() == 1) {\n        array_stream_options[0] = \"INCLUDE_FID=YES\";\n    }\n\n    Rcpp::List prep = CPL_ogr_layer_setup(datasource, layer, query, options,\n\t\t\t\t\t\t\tquiet,  drivers,\n\t\t\t\t\t\t\twkt_filter,\n\t\t\t\t\t\t\tdsn_exists, dsn_isdb, width);\n\tOGRLayer* poLayer = (OGRLayer*)R_ExternalPtrAddr(prep[1]);\n    auto stream_out = reinterpret_cast<struct ArrowArrayStream*>(\n        R_ExternalPtrAddr(stream_xptr));\n\n    OGRFeatureDefn* poFDefn = poLayer->GetLayerDefn();\n    Rcpp::CharacterVector geom_field_name(poFDefn->GetGeomFieldCount());\n    Rcpp::CharacterVector geom_field_crs(poFDefn->GetGeomFieldCount());\n\n    for (int i = 0; i < poFDefn->GetGeomFieldCount(); i++) {\n        OGRGeomFieldDefn* poGFDefn = poFDefn->GetGeomFieldDefn(i);\n\t\tif (poGFDefn == nullptr) {\n\t\t\tRcpp::stop(\"GeomFieldDefn error\"); // #nocov\n        }\n\n        const char* name = poGFDefn->GetNameRef();\n        if (strlen(name) == 0) {\n            name = \"geometry\";\n        }\n\n        const OGRSpatialReference* crs = poGFDefn->GetSpatialRef();\n        Rcpp::String wkt_str = NA_STRING;\n        if (crs != nullptr) {\n            char* wkt_out;\n            crs->exportToWkt(&wkt_out);\n            wkt_str = wkt_out;\n            CPLFree(wkt_out);\n        }\n\n        geom_field_name[i] = name;\n        geom_field_crs[i] = wkt_str;\n    }\n\n    struct ArrowArrayStream stream_temp;\n    if (!poLayer->GetArrowStream(&stream_temp, array_stream_options)) {\n        Rcpp::stop(\"Failed to open ArrayStream from Layer\");\n    }\n\n    GDALStreamWrapper::Make(&stream_temp, prep, stream_out);\n\n    // The reported feature count is incorrect if there is a query\n    double num_features;\n    if (query.size() == 0) {\n        num_features = (double) poLayer->GetFeatureCount(false);\n    } else {\n        num_features = -1;\n    }\n\n    return Rcpp::List::create(\n        geom_field_name,\n        geom_field_crs,\n        Rcpp::NumericVector::create(num_features));\n\n#else\n\n    Rcpp::stop(\"read_stream() requires GDAL >= 3.6\");\n\n#endif\n\n}\n"
  },
  {
    "path": "src/gdal_sf_pkg.h",
    "content": "#ifndef SF_GDAL_SF_PKG_H_\n#define SF_GDAL_SF_PKG_H_\n\n#ifndef NO_GDAL_CPP_HEADERS\nRcpp::CharacterVector p4s_from_spatial_reference(OGRSpatialReference *ref);\nRcpp::List sfc_from_ogr(std::vector<OGRGeometry *>, bool destroy);\nstd::vector<OGRGeometry *> ogr_from_sfc(Rcpp::List sfc, OGRSpatialReference **sref);\nRcpp::List create_crs(const OGRSpatialReference *ref, bool set_input = true);\n#endif\n\nvoid handle_error(OGRErr err);\nstd::vector<char *> create_options(Rcpp::CharacterVector lco, bool quiet = true);\nRcpp::CharacterVector charpp2CV(CSLConstList cp);\n#endif // SF_GDAL_SF_PKG_H_"
  },
  {
    "path": "src/gdal_utils.cpp",
    "content": "#include \"cpl_port.h\"\n#include \"cpl_conv.h\" // CPLFree()\n#include \"gdal_version.h\"\n#include \"gdalwarper.h\"\n\n#include <ogr_srs_api.h>\n#include <ogr_spatialref.h>\n\n#include \"Rcpp.h\"\n#include \"gdal.h\" // local\n\n#define NO_GDAL_CPP_HEADERS\n#include \"gdal_sf_pkg.h\"\n\n/* modified from GDALTermProgress: */\nint CPL_STDCALL GDALRProgress( double dfComplete,\n                                  CPL_UNUSED const char * pszMessage,\n                                  CPL_UNUSED void * pProgressArg )\n{\n    const int nThisTick = std::min(40, std::max(0,\n        static_cast<int>(dfComplete * 40.0) ));\n\n    // Have we started a new progress run?\n    static int nLastTick = -1;\n    if( nThisTick < nLastTick && nLastTick >= 39 )\n        nLastTick = -1;\n\n    if( nThisTick <= nLastTick )\n        return TRUE;\n\n    while( nThisTick > nLastTick )\n    {\n        ++nLastTick;\n        if( nLastTick % 4 == 0 )\n            Rprintf(\"%d\", (nLastTick / 4) * 10 );\n        else\n            Rprintf(\".\" );\n    }\n\n    if( nThisTick == 40 )\n        Rprintf(\" - done.\\n\" );\n\n    return TRUE;\n}\n\n#if GDAL_VERSION_NUM >= 2010000\n# include \"gdal_utils.h\" // requires >= 2.1\n\n// [[Rcpp::export(rng=false)]]\nRcpp::CharacterVector CPL_gdalinfo(Rcpp::CharacterVector obj, Rcpp::CharacterVector options, \n\t\tRcpp::CharacterVector oo, Rcpp::CharacterVector co) {\n\tset_config_options(co);\n\tstd::vector <char *> options_char = create_options(options, true);\n\tstd::vector <char *> oo_char = create_options(oo, true); // open options\n\tGDALInfoOptions* opt = GDALInfoOptionsNew(options_char.data(), NULL);\n\tGDALDatasetH ds = NULL;\n\tif (obj.size())\n\t\tds = GDALOpenEx((const char *) obj[0], GA_ReadOnly, NULL, oo_char.data(), NULL);\n\tchar *ret_val = GDALInfo(ds, opt);\n\tif (ret_val == NULL)\n\t\treturn Rcpp::CharacterVector::create();\n\tRcpp::CharacterVector ret = ret_val; // copies\n\tCPLFree(ret_val);\n\tGDALInfoOptionsFree(opt);\n\tif (ds)\n\t\tGDALClose(ds);\n\tunset_config_options(co);\n\treturn ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::CharacterVector CPL_ogrinfo(Rcpp::CharacterVector obj, Rcpp::CharacterVector options, \n\t\tRcpp::CharacterVector oo, Rcpp::CharacterVector co, bool read_only = false) {\n\tset_config_options(co);\n\tstd::vector <char *> options_char = create_options(options, true);\n\tstd::vector <char *> oo_char = create_options(oo, true); // open options\n\tGDALDatasetH ds = NULL;\n#if GDAL_VERSION_NUM >= 3070000\n\tif (obj.size())\n\t\tds = GDALOpenEx((const char *) obj[0], read_only ? GA_ReadOnly : GA_Update, NULL, oo_char.data(), NULL);\n\tGDALVectorInfoOptions* opt = GDALVectorInfoOptionsNew(options_char.data(), NULL);\n\tchar *ret_val = GDALVectorInfo(ds, opt);\n\tif (ret_val == NULL)\n\t\treturn Rcpp::CharacterVector::create();\n\tRcpp::CharacterVector ret = ret_val; // copies\n\tCPLFree(ret_val);\n\tGDALVectorInfoOptionsFree(opt);\n#else\n\tRcpp::CharacterVector ret;\n\tRcpp::stop(\"ogrinfo util requires GDAL >= 3.7.0\");\n#endif\n\tif (ds)\n\t\tGDALClose(ds);\n\tunset_config_options(co);\n\treturn ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_gdaladdo(Rcpp::CharacterVector obj, Rcpp::CharacterVector method, \n\t\tRcpp::IntegerVector overviews, Rcpp::IntegerVector bands, Rcpp::CharacterVector oo,\n\t\tRcpp::CharacterVector co, bool clean = false, bool read_only = false) {\n\n\tset_config_options(co);\n\t/*\n\tstd::vector <char *> options_char = create_options(options, true);\n\tGDALInfoOptions* opt = GDALInfoOptionsNew(options_char.data(), NULL);\n\t*/\n\tstd::vector <char *> oo_char = create_options(oo, true); // open options\n\n\tGDALDatasetH ds;\n\tif ((ds = GDALOpenEx((const char *) obj[0], \n\t\t\t\t\t\tGDAL_OF_RASTER | (read_only ? GA_ReadOnly : GA_Update),\n\t\t\t\t\t\tNULL, oo_char.data(), NULL)) == NULL)\n\t\tRcpp::stop(read_only ? \"cannot open file for reading\" : \"cannot open file for writing\");\n\n\tif (clean) { // remove overviews:\n\t\tif (GDALBuildOverviews(ds, method[0], 0, nullptr,\n                               0, nullptr, GDALRProgress, nullptr) != CE_None) {\n\t\t\tGDALClose(ds);\n\t\t\tRcpp::stop(\"error while cleaning overviews\");\n\t\t}\n\t} else { // build overviews:\n\t\tif (GDALBuildOverviews(ds, method[0], \n\t\t\t\t\toverviews.size(), overviews.size() ? &(overviews[0]) : NULL,\n\t\t\t\t\tbands.size(), bands.size() ? &(bands[0]) : NULL, \n\t\t\t\t\tGDALRProgress, NULL) != CE_None) {\n\t\t\tGDALClose(ds);\n\t\t\tRcpp::stop(\"error while building overviews\");\n\t\t}\n\t}\n\tGDALClose(ds);\n\tunset_config_options(co);\n\treturn true;\n}\n\n// #nocov start\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_gdalwarp(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector doo,\n\t\tRcpp::CharacterVector co, bool quiet = true, bool overwrite = false) {\n\n\tint err = 0;\n\n\tset_config_options(co);\n\tstd::vector <char *> oo_char = create_options(oo, true); // open options\n\tstd::vector<GDALDatasetH> src_pt(src.size());\n\tfor (int i = 0; i < src.size(); i++)\n\t\tsrc_pt[i] = GDALOpenEx((const char *) src[i], GA_ReadOnly, NULL, oo_char.data(), NULL);\n\n\tstd::vector <char *> doo_char = create_options(doo, true); // open options\n\tGDALDatasetH dst_ds = GDALOpenEx((const char *) dst[0], GDAL_OF_RASTER | GA_Update, NULL, doo_char.data(), NULL);\n\n\tstd::vector <char *> options_char = create_options(options, true);\n\tGDALWarpAppOptions* opt = GDALWarpAppOptionsNew(options_char.data(), NULL);\n\tif (opt == NULL)\n\t\tRcpp::stop(\"warp: options error\");\n\n\tif (! quiet) {\n\t\tGDALWarpAppOptionsSetProgress(opt, GDALRProgress, NULL);\n#if GDAL_VERSION_NUM >= 2030000\n\t\tGDALWarpAppOptionsSetQuiet(opt, 0);\n#endif\n\t}\n\tif (overwrite && dst_ds != NULL) {\n\t\tGDALClose(dst_ds);\n\t\tdst_ds = NULL;\n\t}\n\tGDALDatasetH result = GDALWarp(dst_ds == NULL ? (const char *) dst[0] : NULL, dst_ds, \n\t\tsrc.size(), src_pt.data(), opt, &err);\n\tGDALWarpAppOptionsFree(opt);\n\tfor (int i = 0; i < src.size(); i++)\n\t\tif (src_pt[i] != NULL)\n\t\t\tGDALClose(src_pt[i]);\n\tif (result != NULL)\n\t\tGDALClose(result);\n\tunset_config_options(co);\n\treturn result == NULL || err;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_gdalrasterize(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector doo,\n\t\tRcpp::CharacterVector co, bool overwrite = false, bool quiet = true) {\n\n\tset_config_options(co);\n\tint err = 0;\n\tstd::vector <char *> options_char = create_options(options, true);\n\tstd::vector <char *> oo_char = create_options(oo, true); // open options\n\tGDALRasterizeOptions* opt =  GDALRasterizeOptionsNew(options_char.data(), NULL);\n\tif (opt == NULL)\n\t\tRcpp::stop(\"rasterize: options error\");\n\n\tif (! quiet)\n\t\tGDALRasterizeOptionsSetProgress(opt, GDALRProgress, NULL);\n\tGDALDatasetH src_pt = GDALOpenEx((const char *) src[0], GDAL_OF_VECTOR | GA_ReadOnly, \n\t\tNULL, oo_char.data(), NULL);\n\tif (src_pt == NULL)\n\t\tRcpp::stop(\"source dataset not found\");\n\tunset_error_handler();\n\tGDALDatasetH dst_pt = NULL;\n\tif (! overwrite) {\n\t\tstd::vector <char *> doo_char = create_options(doo, true); // open options\n\t\tdst_pt = GDALOpenEx((const char *) dst[0], GDAL_OF_RASTER | GA_Update, NULL, doo_char.data(), NULL);\n\t}\n\tset_error_handler();\n\tGDALDatasetH result = \n\t\tGDALRasterize(dst_pt == NULL ? (const char *) dst[0] : NULL, dst_pt, src_pt, opt, &err);\n\tGDALRasterizeOptionsFree(opt);\n\tif (src_pt != NULL)\n\t\tGDALClose(src_pt);\n\tif (result != NULL)\n\t\tGDALClose(result);\n\tunset_config_options(co);\n\treturn result == NULL || err;\n}\n// #nocov end\n\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_gdaltranslate(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector co,\n\t\tbool quiet = true) {\n\n\tset_config_options(co);\n\tint err = 0;\n\tstd::vector <char *> options_char = create_options(options, true);\n\tstd::vector <char *> oo_char = create_options(oo, true);\n\tGDALTranslateOptions* opt =  GDALTranslateOptionsNew(options_char.data(), NULL);\n\tif (opt == NULL)\n\t\tRcpp::stop(\"translate: options error\");\n\n\tif (! quiet)\n\t\tGDALTranslateOptionsSetProgress(opt, GDALRProgress, NULL);\n\tGDALDatasetH src_pt = GDALOpenEx((const char *) src[0], GDAL_OF_RASTER | GA_ReadOnly, \n\t\tNULL, oo_char.data(), NULL);\n\tif (src_pt == NULL)\n\t\treturn 1; // #nocov\n\tGDALDatasetH result = GDALTranslate((const char *) dst[0], src_pt, opt, &err);\n\tGDALTranslateOptionsFree(opt);\n\t// see https://github.com/r-spatial/sf/issues/1352:\n\tif (result != NULL)\n\t\tGDALClose(result);\n\tif (src_pt != NULL)\n\t\tGDALClose(src_pt);\n\tunset_config_options(co);\n\treturn result == NULL || err;\n}\n\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_gdalfootprint(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n        Rcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector co,\n        bool quiet = true) {\n\t\n#if GDAL_VERSION_NUM < 3080000\n\tRcpp::stop(\"footprint util requires GDAL >= 3.8.0\");\n#else\n\tint err = 0;\n\tset_config_options(co);\n\tstd::vector <char *> options_char = create_options(options, true);\n\tstd::vector <char *> oo_char = create_options(oo, true);\n\tGDALFootprintOptions* opt =  GDALFootprintOptionsNew(options_char.data(), NULL);\n\t\n\tif (opt == NULL)\n\t\tRcpp::stop(\"footprint: options error\");\n\t\n\tif (! quiet)\n\t\tGDALFootprintOptionsSetProgress(opt, GDALRProgress, NULL);\n\tGDALDatasetH src_pt = GDALOpenEx((const char *) src[0], GDAL_OF_RASTER | GA_ReadOnly,\n                                  NULL, oo_char.data(), NULL);\n\tif (src_pt == NULL)\n\t\treturn 1; // #nocov\n\tGDALDatasetH result = GDALFootprint((const char *) dst[0], NULL,src_pt, opt, &err);\n\tGDALFootprintOptionsFree(opt);\n\t// see https://github.com/r-spatial/sf/issues/1352:\n\tif (result != NULL)\n\t\tGDALClose(result);\n\tif (src_pt != NULL)\n\t\tGDALClose(src_pt);\n\tunset_config_options(co);\n\treturn result == NULL || err;\n#endif\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_gdalvectortranslate(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector doo,\n\t\tRcpp::CharacterVector co, bool quiet = true) {\n\n\tset_config_options(co);\n\tint err = 0;\n\tstd::vector <char *> options_char = create_options(options, true);\n\tGDALVectorTranslateOptions* opt =  GDALVectorTranslateOptionsNew(options_char.data(), NULL);\n\tif (opt == NULL)\n\t\tRcpp::stop(\"vectortranslate: options error\");\n\n\tif (! quiet)\n\t\tGDALVectorTranslateOptionsSetProgress(opt, GDALRProgress, NULL);\n\tstd::vector <char *> oo_char = create_options(oo, true); // open options\n\tGDALDatasetH src_pt = GDALOpenEx((const char *) src[0], GDAL_OF_VECTOR | GA_ReadOnly, NULL, \n\t\too_char.data(), NULL);\n\tif (src_pt == NULL)\n\t\treturn 1; // #nocov\n\tstd::vector <char *> doo_char = create_options(doo, true); // open options\n\tunset_error_handler();\n\tGDALDatasetH dst_pt = GDALOpenEx((const char *) dst[0], GDAL_OF_VECTOR | GA_Update, NULL, doo_char.data(), NULL);\n\tset_error_handler();\n\tGDALDatasetH result = \n\t\tGDALVectorTranslate(dst_pt == NULL ? (const char *) dst[0] : NULL, dst_pt, 1, &src_pt, opt, &err);\n\tGDALVectorTranslateOptionsFree(opt);\n\tGDALClose(src_pt);\n\tif (result != NULL)\n\t\tGDALClose(result);\n\tunset_config_options(co);\n\treturn result == NULL || err;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_gdalbuildvrt(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo, \n\t\tRcpp::CharacterVector co, bool quiet = true) {\n\n\tset_config_options(co);\n\tint err = 0;\n\tstd::vector <char *> options_char = create_options(options, true);\n\tGDALBuildVRTOptions* opt = GDALBuildVRTOptionsNew(options_char.data(), NULL);\n\tif (opt == NULL)\n\t\tRcpp::stop(\"buildvrt: options error\");\n\n\tif (! quiet)\n\t\tGDALBuildVRTOptionsSetProgress(opt, GDALRProgress, NULL);\n\tGDALDatasetH result = NULL;\n\tif (oo.size()) { \n\t\t// to understand why we don't always take this path, read: \n\t\t// https://github.com/r-spatial/sf/issues/1336\n\t\tstd::vector <char *> oo_char = create_options(oo, true); // open options\n\t\tstd::vector<GDALDatasetH> srcpt(src.size());\n\t\tfor (int i = 0; i < src.size(); i++) {\n\t\t\tsrcpt[i] = GDALOpenEx((const char *) src[i], GDAL_OF_RASTER | GA_ReadOnly, NULL, \n\t\t\t\too_char.data(), NULL);\n\t\t\tif (srcpt[i] == NULL)\n\t\t\t\tRcpp::stop(\"cannot open source dataset\");\n\t\t}\n\t\tresult = GDALBuildVRT((const char *) dst[0], src.size(), srcpt.data(), NULL, opt, &err);\n\t\tfor (int i = 0; i < src.size(); i++)\n\t\t\tGDALClose(srcpt[i]);\n\t} else {\n\t\tstd::vector<const char *> srcpt(src.size());\n\t\tfor (int i = 0; i < src.size(); i++)\n\t\t\tsrcpt[i] = (const char *) src[i];\n\t\tresult = GDALBuildVRT((const char *) dst[0], src.size(), NULL, srcpt.data(), opt, &err);\n\t}\n\tGDALBuildVRTOptionsFree(opt);\n\tif (result != NULL)\n\t\tGDALClose(result);\n\tunset_config_options(co);\n\treturn result == NULL || err;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_gdaldemprocessing(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector processing, \n\t\tRcpp::CharacterVector colorfilename, Rcpp::CharacterVector oo, \n\t\tRcpp::CharacterVector co, bool quiet = true) {\n\n\tint err = 0;\n\tset_config_options(co);\n\tstd::vector <char *> options_char = create_options(options, true);\n\tstd::vector <char *> oo_char = create_options(oo, true); // open options\n\tGDALDEMProcessingOptions* opt =  GDALDEMProcessingOptionsNew(options_char.data(), NULL);\n\tif (opt == NULL)\n\t\tRcpp::stop(\"demprocessing: options error\");\n\n\tif (! quiet)\n\t\tGDALDEMProcessingOptionsSetProgress(opt, GDALRProgress, NULL);\n\tGDALDatasetH src_pt = GDALOpenEx((const char *) src[0], GDAL_OF_RASTER | GA_ReadOnly, \n\t\tNULL, oo_char.data(), NULL);\n\tif (src_pt == NULL)\n\t\tRcpp::stop(\"cannot open source dataset\"); // #nocov\n\tGDALDatasetH result = GDALDEMProcessing((const char *) dst[0], src_pt, \n\t\tprocessing.size() == 0 ? NULL : (const char *) processing[0], \n\t\tcolorfilename.size() == 0 ? NULL : (const char *) colorfilename[0], \n\t\topt, &err);\n\tGDALDEMProcessingOptionsFree(opt);\n\tif (result != NULL)\n\t\tGDALClose(result);\n\tif (src_pt != NULL)\n\t\tGDALClose(src_pt);\n\tunset_config_options(co);\n\treturn result == NULL || err;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_gdalnearblack(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector doo, \n\t\tRcpp::CharacterVector co, bool quiet = true) {\n\n\tset_config_options(co);\n\tint err = 0;\n\tstd::vector <char *> options_char = create_options(options, true);\n\tstd::vector <char *> oo_char = create_options(oo, true); // open options\n\tstd::vector <char *> doo_char = create_options(doo, true); // open options\n\tGDALNearblackOptions* opt =  GDALNearblackOptionsNew(options_char.data(), NULL);\n\tif (opt == NULL)\n\t\tRcpp::stop(\"nearblack: options error\");\n\n\tif (! quiet)\n\t\tGDALNearblackOptionsSetProgress(opt, GDALRProgress, NULL);\n\t// GDALDatasetH src_pt = GDALOpen((const char *) src[0], GA_ReadOnly);\n\tGDALDatasetH src_pt = GDALOpenEx((const char *) src[0], GDAL_OF_RASTER | GA_ReadOnly, NULL, oo_char.data(), NULL);\n\tGDALDatasetH dst_pt = GDALOpenEx((const char *) dst[0], GDAL_OF_RASTER | GA_Update, NULL, doo_char.data(), NULL);\n\tGDALDatasetH result = GDALNearblack(dst_pt == NULL ? (const char *) dst[0] : NULL, dst_pt, src_pt, opt, &err);\n\tGDALNearblackOptionsFree(opt);\n\tif (src_pt != NULL) \n\t\tGDALClose(src_pt);\n\tif (result != NULL)\n\t\tGDALClose(result);\n\tunset_config_options(co);\n\treturn result == NULL || err;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_gdalgrid(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo,\n\t\tRcpp::CharacterVector co, bool quiet = true) {\n\n\tset_config_options(co);\n\tint err = 0;\n\tstd::vector <char *> options_char = create_options(options, true);\n\tstd::vector <char *> oo_char = create_options(oo, true); // open options\n\tGDALGridOptions* opt =  GDALGridOptionsNew(options_char.data(), NULL);\n\tif (opt == NULL)\n\t\tRcpp::stop(\"grid: options error\");\n\n\tif (! quiet)\n\t\tGDALGridOptionsSetProgress(opt, GDALRProgress, NULL);\n\tGDALDatasetH src_pt = GDALOpenEx((const char *) src[0], GDAL_OF_ALL | GA_ReadOnly, \n\t\tNULL, oo_char.data(), NULL);\n\tGDALDatasetH result = GDALGrid((const char *) dst[0], src_pt, opt, &err);\n\tGDALGridOptionsFree(opt);\n\tif (src_pt != NULL)\n\t\tGDALClose(src_pt);\n\tif (result != NULL)\n\t\tGDALClose(result);\n\tunset_config_options(co);\n\treturn result == NULL || err;\n}\n\n// gdal >= 3.1: mdim utils:\n#if GDAL_VERSION_NUM >= 3010000\n// [[Rcpp::export(rng=false)]]\nRcpp::CharacterVector CPL_gdalmdiminfo(Rcpp::CharacterVector obj, Rcpp::CharacterVector options,\n\t\tRcpp::CharacterVector oo, Rcpp::CharacterVector co) { \n\tset_config_options(co);\n\tstd::vector <char *> oo_char = create_options(oo, true);\n\tGDALDatasetH ds = GDALOpenEx((const char *) obj[0], GDAL_OF_MULTIDIM_RASTER | GDAL_OF_VERBOSE_ERROR , NULL, oo_char.data(), NULL);\n\tif (ds == NULL) {\n\t\tRcpp::Rcout << \"failed to open \" << obj[0] << std::endl;\n\t\tRcpp::stop(\"cannot open data source\");\n\t}\n\tstd::vector <char *> options_char = create_options(options, true);\n\tGDALMultiDimInfoOptions* opt = GDALMultiDimInfoOptionsNew(options_char.data(), NULL);\n\tchar *ret_val = GDALMultiDimInfo(ds, opt);\n\tGDALMultiDimInfoOptionsFree(opt);\n\tGDALClose(ds);\n\tif (ret_val == NULL)\n\t\tRcpp::stop(\"GDALMultiDimInfo returned NULL\");\n\tRcpp::CharacterVector ret(1);\n\tret[0] = ret_val;\n\tCPLFree(ret_val);\n\tunset_config_options(co);\n\treturn ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_gdalmdimtranslate(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector co,\n\t\tbool quiet = true) {\n\n\tset_config_options(co);\n\tint err = 0;\n\tstd::vector <char *> options_char = create_options(options, true);\n\tstd::vector <char *> oo_char = create_options(oo, true);\n\tGDALMultiDimTranslateOptions* opt = GDALMultiDimTranslateOptionsNew(options_char.data(), NULL);\n\tif (opt == NULL)\n\t\tRcpp::stop(\"mdimtranslate: options error\");\n\n\tif (! quiet)\n\t\tGDALMultiDimTranslateOptionsSetProgress(opt, GDALRProgress, NULL);\n\tstd::vector<GDALDatasetH> srcpt(src.size());\n\tfor (int i = 0; i < src.size(); i++) {\n\t\tsrcpt[i] = GDALOpenEx((const char *) src[i], GDAL_OF_RASTER | GDAL_OF_MULTIDIM_RASTER | GDAL_OF_VERBOSE_ERROR, NULL, \n\t\t\too_char.data(), NULL);\n\t\tif (srcpt[i] == NULL) {\n\t\t\tRcpp::Rcout << \"dataset: \" << src[i] << \": \" << std::endl;\n\t\t\tRcpp::stop(\"Cannot open source dataset\");\n\t\t}\n\t}\n\tGDALDatasetH result = GDALMultiDimTranslate((const char *) dst[0], NULL, srcpt.size(), srcpt.data(), opt, &err);\n\tGDALMultiDimTranslateOptionsFree(opt);\n\tif (result != NULL)\n\t\tGDALClose(result);\n\telse \n\t\tRcpp::stop(\"failed to open destination data set\");\n\tfor (int i = 0; i < src.size(); i++)\n\t\tGDALClose(srcpt[i]);\n\tunset_config_options(co);\n\treturn result == NULL || err;\n}\n#else\nRcpp::CharacterVector CPL_gdalmdiminfo(Rcpp::CharacterVector obj, Rcpp::CharacterVector options,\n\t\tRcpp::CharacterVector oo, Rcpp::CharacterVector co) { \n\tRcpp::stop(\"GDAL version >= 3.1 required for mdiminfo\");\n}\nRcpp::LogicalVector CPL_gdalmdimtranslate(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector co,\n\t\tbool quiet = true) {\n\tRcpp::stop(\"GDAL version >= 3.1 required for mdimtranslate\");\n}\n#endif\n\n#else\n#include \"Rcpp.h\"\n\nRcpp::CharacterVector CPL_gdalinfo(Rcpp::CharacterVector obj, Rcpp::CharacterVector options, \n\t\tRcpp::CharacterVector oo, Rcpp::CharacterVector co) {\n\tRcpp::stop(\"GDAL version >= 2.1 required for gdal_utils\");\n}\n\nRcpp::LogicalVector CPL_gdalwarp(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector doo, Rcpp::CharacterVector co) {\n\tRcpp::stop(\"GDAL version >= 2.1 required for gdal_utils\");\n}\n\nRcpp::LogicalVector CPL_gdalrasterize(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector doo, Rcpp::CharacterVector co,\n\t\tbool overwrite = false) {\n\tRcpp::stop(\"GDAL version >= 2.1 required for gdal_utils\");\n}\n\nRcpp::LogicalVector CPL_gdaltranslate(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector co) {\n\tRcpp::stop(\"GDAL version >= 2.1 required for gdal_utils\");\n}\n\nRcpp::LogicalVector CPL_gdalvectortranslate(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector doo, Rcpp::CharacterVector co) {\n\tRcpp::stop(\"GDAL version >= 2.1 required for gdal_utils\");\n}\n\nRcpp::LogicalVector CPL_gdalbuildvrt(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector co) {\n\tRcpp::stop(\"GDAL version >= 2.1 required for gdal_utils\");\n}\n\nRcpp::LogicalVector CPL_gdaldemprocessing(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector processing, Rcpp::CharacterVector colorfilename,\n\t\tRcpp::CharacterVector oo, Rcpp::CharacterVector co) {\n\tRcpp::stop(\"GDAL version >= 2.1 required for gdal_utils\");\n}\n\nRcpp::LogicalVector CPL_gdalnearblack(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector doo, Rcpp::CharacterVector co) {\n\tRcpp::stop(\"GDAL version >= 2.1 required for gdal_utils\");\n}\n\nRcpp::LogicalVector CPL_gdalgrid(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector co) {\n\tRcpp::stop(\"GDAL version >= 2.1 required for gdal_utils\");\n}\n\nRcpp::CharacterVector CPL_gdalmdiminfo(Rcpp::CharacterVector obj, Rcpp::CharacterVector options, \n\t\tRcpp::CharacterVector oo, Rcpp::CharacterVector co) {\n\tRcpp::stop(\"GDAL version >= 3.1 required for mdiminfo\");\n}\n\nRcpp::LogicalVector CPL_gdalmdimtranslate(Rcpp::CharacterVector src, Rcpp::CharacterVector dst,\n\t\tRcpp::CharacterVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector co) {\n\tRcpp::stop(\"GDAL version >= 3.1 required for mdimtranslate\");\n}\n#endif\n\n// #nocov start\n// https://gdal.org/tutorials/warp_tut.html\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_gdal_warper(Rcpp::CharacterVector infile, Rcpp::CharacterVector outfile,\n\t\tRcpp::IntegerVector options, Rcpp::CharacterVector oo, Rcpp::CharacterVector doo,\n\t\tRcpp::CharacterVector co, bool quiet = true) {\n\n\tset_config_options(co);\n\tstd::vector <char *> oo_char = create_options(oo, true); // open options\n\tGDALDatasetH  hSrcDS, hDstDS;\n\t// Open input and output files.\n\tGDALAllRegister();\n\thSrcDS = GDALOpenEx( infile[0], GA_ReadOnly, NULL, oo_char.data(), NULL );\n\tif (hSrcDS == NULL)\n\t\tRcpp::stop(\"input file not found\");\n\tstd::vector <char *> doo_char = create_options(doo, true); // open options\n\thDstDS = GDALOpenEx(outfile[0], GA_Update, NULL, doo_char.data(), NULL);\n\tif (hDstDS == NULL)\n\t\tRcpp::stop(\"could not open output file for writing\");\n\t// Setup warp options.\n\tGDALWarpOptions *psWarpOptions = GDALCreateWarpOptions();\n\tpsWarpOptions->hSrcDS = hSrcDS;\n\tpsWarpOptions->hDstDS = hDstDS;\n\n\tif (GDALGetRasterCount(hSrcDS) != GDALGetRasterCount(hDstDS))\n\t\tRcpp::stop(\"warper: source and destination must have the same number of bands\");\n\n\tpsWarpOptions->nBandCount = GDALGetRasterCount(hSrcDS);\n\tpsWarpOptions->panSrcBands =\n\t\t(int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount );\n\tpsWarpOptions->panDstBands =\n\t\t(int *) CPLMalloc(sizeof(int) * psWarpOptions->nBandCount );\n\tfor (int i = 0; i < psWarpOptions->nBandCount; i++) {\n\t\tpsWarpOptions->panSrcBands[i] = i + 1;\n\t\tpsWarpOptions->panDstBands[i] = i + 1;\n\t}\n\n\tpsWarpOptions->padfSrcNoDataReal = (double *) CPLMalloc(sizeof(double) * GDALGetRasterCount(hSrcDS));\n\tpsWarpOptions->padfDstNoDataReal = (double *) CPLMalloc(sizeof(double) * GDALGetRasterCount(hSrcDS));\n\n\tGDALRasterBandH poBand;\n\tint success;\n\tdouble d = 0xffffffff;\n\tfor (int i = 0; i < GDALGetRasterCount(hSrcDS); i++) {\n\t\tpoBand = GDALGetRasterBand(hSrcDS, i + 1);\n\t\tGDALGetRasterNoDataValue(poBand, &success);\n\t\tif (success) {\n\t\t\tpsWarpOptions->padfSrcNoDataReal[i] = GDALGetRasterNoDataValue(poBand, &success);\n\t\t\t// Rcpp::Rcout << \"1: \" << GDALGetRasterNoDataValue(poBand, &success) << std::endl;\n\t\t } else\n\t\t\tmemcpy(&(psWarpOptions->padfSrcNoDataReal[i]), &d, sizeof(double));\n\t\tpoBand = GDALGetRasterBand(hDstDS, i + 1);\n\t\tGDALGetRasterNoDataValue(poBand, &success);\n\t\tif (success) {\n\t\t\tpsWarpOptions->padfDstNoDataReal[i] = GDALGetRasterNoDataValue(poBand, &success);\n\t\t\t// Rcpp::Rcout << \"2: \" << GDALGetRasterNoDataValue(poBand, &success) << std::endl;\n\t\t} else // NaN:\n\t\t\tmemcpy(&(psWarpOptions->padfDstNoDataReal[i]), &d, sizeof(double));\n\t}\n\n\tif (quiet)\n\t\tpsWarpOptions->pfnProgress = GDALDummyProgress;\n\telse\n\t\tpsWarpOptions->pfnProgress = GDALRProgress; // 0...10...20...30...40...50...60...70...80...90...100 - done.\n\t// Establish reprojection transformer.\n\tif (options.size() == 1)\n\t\tpsWarpOptions->eResampleAlg = (GDALResampleAlg) options[0];\n\tpsWarpOptions->pTransformerArg =\n\t\tGDALCreateGenImgProjTransformer( hSrcDS,\n\t\t\t\t\t\t\t\t\t\t GDALGetProjectionRef(hSrcDS),\n\t\t\t\t\t\t\t\t\t\t hDstDS,\n\t\t\t\t\t\t\t\t\t\t GDALGetProjectionRef(hDstDS),\n\t\t\t\t\t\t\t\t\t\t FALSE, 0.0, 1 );\n\tpsWarpOptions->pfnTransformer = GDALGenImgProjTransform;\n\t// Initialize and execute the warp operation.\n\tGDALWarpOperation oOperation;\n\toOperation.Initialize( psWarpOptions );\n\toOperation.ChunkAndWarpImage( 0, 0,\n\t\t\t\t\t\t\t\t  GDALGetRasterXSize( hDstDS ),\n\t\t\t\t\t\t\t\t  GDALGetRasterYSize( hDstDS ) );\n\tGDALDestroyGenImgProjTransformer( psWarpOptions->pTransformerArg );\n\tGDALDestroyWarpOptions( psWarpOptions );\n\tif (hDstDS)\n\t\tGDALClose( hDstDS );\n\tif (hSrcDS)\n\t\tGDALClose( hSrcDS );\n\tunset_config_options(co);\n\treturn false;\n}\n// #nocov end\n"
  },
  {
    "path": "src/gdal_write.cpp",
    "content": "#include <string.h>\n\n#include \"Rcpp.h\"\n\n#include \"ogrsf_frmts.h\"\n#include \"wkb.h\"\n#include \"gdal.h\"\n#include \"gdal_sf_pkg.h\"\n\nstd::vector<OGRFieldType> SetupFields(OGRLayer *poLayer, Rcpp::List obj, bool update_layer) {\n\tstd::vector<OGRFieldType> ret(obj.size());\n\tRcpp::CharacterVector cls = obj.attr(\"colclasses\");\n\tRcpp::CharacterVector nm  = obj.attr(\"names\");\n\tfor (int i = 0; i < obj.size(); i++) {\n\t\tif (strcmp(cls[i], \"character\") == 0)\n\t\t\tret[i] = OFTString;\n\t\telse if (strcmp(cls[i], \"integer\") == 0 || strcmp(cls[i], \"logical\") == 0)\n\t\t\tret[i] = OFTInteger;\n\t\telse if (strcmp(cls[i], \"numeric\") == 0)\n\t\t\tret[i] = OFTReal;\n\t\telse if (strcmp(cls[i], \"Date\") == 0)\n\t\t\tret[i] = OFTDate;\n\t\telse if (strcmp(cls[i], \"POSIXct\") == 0)\n\t\t\tret[i] = OFTDateTime;\n\t\telse if (strcmp(cls[i], \"list\") == 0) // list with raw vectors; #1721\n\t\t\tret[i] = OFTBinary;\n\t\telse { // #nocov start\n\t\t\tRcpp::Rcout << \"Field \" << nm[i] << \" of type \" << cls[i] << \" not supported.\" << std::endl;\n\t\t\tRcpp::stop(\"Layer creation failed.\\n\");\n\t\t}      // #nocov end\n\t\tif (poLayer->FindFieldIndex(nm[i], TRUE) == -1) { // not already present:\n\t\t\tOGRFieldDefn oField(nm[i], ret[i]);\n\t\t\tif (strcmp(cls[i], \"logical\") == 0)\n\t\t\t\toField.SetSubType(OFSTBoolean);\n\t\t\tif (!update_layer && poLayer->CreateField(&oField) != OGRERR_NONE) { // #nocov start\n\t\t\t\tRcpp::Rcout << \"Creating field \" << nm[i] << \" failed.\" << std::endl;\n\t\t\t\tRcpp::stop(\"Layer creation failed.\\n\");\n\t\t\t} // #nocov end\n\t\t} else {\n\t\t\t// otherwise, one could check the type?\n\t\t\t// some type conversion, e.g. int -> char seems to be done by GDAL, see #2202\n\t\t}\n\t}\n\treturn ret;\n}\n\n// this is like an unlist -> dbl, but only does the first 6; if we'd do unlist on the POSIXlt\n// object, we'd get a character vector...\nRcpp::NumericVector get_dbl6(Rcpp::List in) { \n\tRcpp::NumericVector ret(6);\n\tfor (int i = 0; i < 6; i++) {\n\t\tRcpp::NumericVector x = in(i);\n\t\tret(i) = x(0);\n\t}\n\treturn ret;\n}\n\nvoid SetNull(OGRFeature *poFeature, size_t field) {\n#if GDAL_VERSION_NUM >= 2020000\n\tpoFeature->SetFieldNull(field);\n#else\n\tpoFeature->UnsetField(field);\n#endif\n}\n\nstd::vector<int> GetFieldIndex(OGRLayer *poLayer, Rcpp::List obj) {\n\tstd::vector<int> ret(obj.size());\n\tRcpp::CharacterVector nm  = obj.attr(\"names\");\n\tfor (int i = 0; i < obj.size(); i++) {\n\t\tret[i] = poLayer->FindFieldIndex(nm[i], TRUE);\n\t\tif (ret[i] == -1) {\n\t\t\tRcpp::Rcout << \"Unknown field name `\" << nm[i] << \n\t\t\t\t\"': updating a layer with improper field name(s)?\" << std::endl;\n\t\t\tRcpp::stop(\"Write error\\n\");\n\t\t}\n\t}\n\treturn ret;\n}\n\nvoid SetFields(OGRFeature *poFeature, std::vector<OGRFieldType> tp, Rcpp::List obj, size_t i, std::vector<int> fld) {\n\tfor (size_t j = 0; j < tp.size(); j++) {\n\t\tif (j >= (size_t) poFeature->GetFieldCount())\n\t\t\tRcpp::stop(\"Field count reached: duplicate names present?\\n\"); // #nocov\n\t\tswitch (tp[j]) {\n\t\t\tcase OFTString: {\n\t\t\t\tRcpp::CharacterVector cv;\n\t\t\t\tcv = obj[j];\n\t\t\t\tif (! Rcpp::CharacterVector::is_na(cv[i]))\n\t\t\t\t\tpoFeature->SetField(fld[j], (const char *) cv[i]);\n\t\t\t\telse\n\t\t\t\t\tSetNull(poFeature, fld[j]);\n\t\t\t\t} break;\n\t\t\tcase OFTInteger: {\n\t\t\t\tconst OGRFieldDefn *def = poFeature->GetFieldDefnRef(j);\n\t\t\t\tif (def->GetSubType() == OFSTBoolean) {\n\t\t\t\t\tRcpp::LogicalVector lv;\n\t\t\t\t\tlv = obj[j];\n\t\t\t\t\tif (! Rcpp::LogicalVector::is_na(lv[i]))\n\t\t\t\t\t\tpoFeature->SetField(fld[j], (int) lv[i]);\n\t\t\t\t\telse\n\t\t\t\t\t\tSetNull(poFeature, fld[j]); // #nocov\n\t\t\t\t} else { // integer:\n\t\t\t\t\tRcpp::IntegerVector iv;\n\t\t\t\t\tiv = obj[j];\n\t\t\t\t\tif (! Rcpp::IntegerVector::is_na(iv[i]))\n\t\t\t\t\t\tpoFeature->SetField(fld[j], (int) iv[i]);\n\t\t\t\t\telse\n\t\t\t\t\t\tSetNull(poFeature, fld[j]); // #nocov\n\t\t\t\t}\n\t\t\t\t} break;\n\t\t\tcase OFTReal: {\n\t\t\t\tRcpp::NumericVector nv;\n\t\t\t\tnv = obj[j];\n\t\t\t\tif (! Rcpp::NumericVector::is_na(nv[i]))\n\t\t\t\t\tpoFeature->SetField(fld[j], (double) nv[i]);\n\t\t\t\telse\n\t\t\t\t\tSetNull(poFeature, fld[j]);\n\t\t\t\t} break;\n\t\t\tcase OFTDate: {\n\t\t\t\tRcpp::NumericVector nv;\n\t\t\t\tnv = obj[j];\n\t\t\t\tif (Rcpp::NumericVector::is_na(nv[i])) {\n\t\t\t\t\tSetNull(poFeature, fld[j]);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tRcpp::NumericVector nv0(1);\n\t\t\t\tnv0[0] = nv[i];\n\t\t\t\tnv0.attr(\"class\") = \"Date\";\n\t\t\t\tRcpp::Function as_POSIXlt_Date(\"as.POSIXlt.Date\");\n\t\t\t\tRcpp::NumericVector ret = get_dbl6(as_POSIXlt_Date(nv0));\n\t\t\t\tpoFeature->SetField(fld[j], 1900 + (int) ret[5], (int) ret[4] + 1, (int) ret[3]);\n\t\t\t\t} break;\n\t\t\tcase OFTDateTime: {\n\t\t\t\tRcpp::NumericVector nv;\n\t\t\t\tnv = obj[j];\n\t\t\t\tif (Rcpp::NumericVector::is_na(nv[i])) {\n\t\t\t\t\tSetNull(poFeature, fld[j]);\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\tRcpp::NumericVector nv0(1);\n\t\t\t\tnv0[0] = nv[i];\n\t\t\t\tnv0.attr(\"tzone\") = \"UTC\";\n\t\t\t\tRcpp::Function as_POSIXlt_POSIXct(\"as.POSIXlt.POSIXct\");\n\t\t\t\tRcpp::NumericVector rd = get_dbl6(as_POSIXlt_POSIXct(nv0)); // use R\n\t\t\t\tpoFeature->SetField(fld[j], 1900 + (int) rd[5], (int) rd[4] + 1, // #nocov start\n\t\t\t\t\t\t(int) rd[3], (int) rd[2], (int) rd[1],\n\t\t\t\t\t\t(float) rd[0], 100); // nTZFlag: 0=unkown, 1=local, 100=GMT; #nocov end\n\t\t\t\t} break;\n\t\t\tcase OFTBinary: \n#if GDAL_VERSION_NUM > 3000000\n\t\t\t\t{\n\t\t\t\tRcpp::List lv;\n\t\t\t\tlv = obj[j];\n\t\t\t\tRcpp::RawVector rv;\n\t\t\t\trv = lv(0);\n\t\t\t\tif (rv.size() == 0)\n\t\t\t\t\tSetNull(poFeature, fld[j]); // #nocov\n\t\t\t\telse {\n\t\t\t\t\tconst void *ptr = &(rv[0]);\n\t\t\t\t\tint size = rv.size();\n\t\t\t\t\tpoFeature->SetField(fld[j], size, ptr);\n\t\t\t\t}\n\t\t\t\t} break;\n#endif\n\t\t\tdefault:\n\t\t\t\t// we should never get here! // #nocov start\n\t\t\t\tRcpp::Rcout << \"field with unsupported type ignored\" << std::endl; \n\t\t\t\tRcpp::stop(\"Layer creation failed.\\n\");\n\t\t\t\tbreak; // #nocov end\n\t\t}\n\t}\n}\n\n// [[Rcpp::export(rng=false)]]\nint CPL_write_ogr(Rcpp::List obj, Rcpp::CharacterVector dsn, Rcpp::CharacterVector layer,\n\tRcpp::CharacterVector driver, Rcpp::CharacterVector dco, Rcpp::CharacterVector lco,\n\tRcpp::List geom, Rcpp::CharacterVector dim, Rcpp::CharacterVector fids,\n\tRcpp::CharacterVector ConfigOptions,\n\tbool quiet, Rcpp::LogicalVector append, bool delete_dsn = false, bool delete_layer = false,\n\tbool write_geometries = true, int width = 80) {\n\n\t// init:\n\tset_config_options(ConfigOptions);\n\tif (driver.size() != 1 || dsn.size() != 1 || layer.size() != 1)\n\t\tRcpp::stop(\"argument dsn, layer or driver not of length 1.\\n\");\n\n\t/* GDALAllRegister(); -- has been done during .onLoad() */\n\t// get driver:\n\tGDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName(driver[0]);\n\tif (poDriver == NULL) {\n\t\tRcpp::Rcout << \"driver `\" << driver[0] << \"' not available.\" << std::endl;\n\t\tRcpp::stop(\"Driver not available.\\n\");\n\t}\n\n\t// delete data source:\n\tif (delete_dsn) {\n\t\tif (poDriver->Delete(dsn[0]) != CE_None) {\n\t\t\tif (! quiet)\n\t\t\t\tRcpp::Rcout << \"Deleting source `\" << dsn[0] << \"' failed\" << std::endl;\n\t\t} else if (! quiet)\n\t\t\tRcpp::Rcout << \"Deleting source `\" << dsn[0] << \"' using driver `\" << driver[0] << \"'\" << std::endl;\n\t}\n\n\tstd::vector <char *> options = create_options(dco, quiet);\n\tstd::vector <char *> drivers = create_options(driver, true);\n\n\t// data set:\n\tGDALDataset *poDS; \n\n\t// delete layer:\n\tif (delete_layer && (poDS = (GDALDataset *) GDALOpenEx(dsn[0], GDAL_OF_VECTOR | GDAL_OF_UPDATE, \n\t\t\t\tdrivers.data(), options.data(), NULL)) != NULL) { // don't complain if the layer is not present\n\t\t// find & delete layer:\n\t\tbool deleted = false;\n\t\tfor (int iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++) {\n\t\t\tOGRLayer *poLayer = poDS->GetLayer(iLayer);\n\t\t\tif (poLayer != NULL && EQUAL(poLayer->GetName(), layer[0])) {\n\t\t\t\tOGRErr err = poDS->DeleteLayer(iLayer);\n\t\t\t\tif (! quiet) {\n\t\t\t\t\tif (err == OGRERR_UNSUPPORTED_OPERATION)\n\t\t\t\t\t\tRcpp::Rcout << \"Deleting layer not supported by driver `\" << driver[0] << \"'\"  // #nocov\n\t\t\t\t\t\t\t<< std::endl; // #nocov\n\t\t\t\t\telse  {\n\t\t\t\t\t\tRcpp::Rcout << \"Deleting layer `\" << layer[0] << \"' using driver `\" << \n\t\t\t\t\t\t\tdriver[0] << \"'\" << std::endl;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tdeleted = (err == OGRERR_NONE);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t\tif (! deleted && ! quiet)\n\t\t\tRcpp::Rcout << \"Deleting layer `\" << layer[0] << \"' failed\" << std::endl;\n\t\tGDALClose(poDS);\n\t}\n\t\n\t// append to ds:\n\tif (append[0] == TRUE) { // and not NA_LOGICAL:\n\t\tpoDS = (GDALDataset *) GDALOpenEx(dsn[0], GDAL_OF_VECTOR | GDAL_OF_UPDATE, \n\t\t\t\tdrivers.data(), options.data(), NULL);\n\t\tif (poDS == NULL) {\n\t\t\tif ((poDS = (GDALDataset *) GDALOpenEx(dsn[0], GDAL_OF_VECTOR | GDAL_OF_READONLY, NULL, \n\t\t\t\t\t\toptions.data(), NULL)) != NULL) { // exists read-only:\n\t\t\t\tGDALClose(poDS);\n\t\t\t\tRcpp::Rcout << \"Cannot append to \" <<  dsn[0] << \n\t\t\t\t\t\": do you have write permission?\" << std::endl;\n\t\t\t\tRcpp::stop(\"Cannot append to existing dataset.\\n\");\n\t\t\t} else { // doesn't exist: create\n\t\t\t\tif ((poDS = poDriver->Create(dsn[0], 0, 0, 0, GDT_Unknown, options.data())) == NULL) {\n\t\t\t\t\tRcpp::Rcout << \"Creating dataset \" <<  dsn[0] << \" failed.\" << std::endl;\n\t\t\t\t\tRcpp::stop(\"Creation failed.\\n\");\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif (! quiet)\n\t\t\tRcpp::Rcout << \"Updating layer `\" << layer[0] << \"' to data source `\" << dsn[0] <<\n\t\t\t\"' using driver `\" << driver[0] << \"'\" << std::endl;\n\t} else { // add to existing ds or create new ds: \n\t\t// when append == NA, raise error when it already exists:\n\t\tif (!delete_dsn && !delete_layer && append[0] == NA_LOGICAL && \n\t\t\t\t(poDS = (GDALDataset *) GDALOpenEx(dsn[0], \n\t\t\t\t\tGDAL_OF_VECTOR | GDAL_OF_READONLY, NULL, options.data(), NULL)) != NULL &&\n\t\t\t\tpoDS->GetLayerByName(layer[0]) != NULL) {\n\t\t\tGDALClose(poDS);\n\t\t\tRcpp::Rcout << \"Layer \" << layer[0] << \" in dataset \" <<  dsn[0] << \" already exists:\\n\" <<\n\t\t\t\t\"use either append=TRUE to append to layer or append=FALSE to overwrite layer\" << std::endl;\n\t\t\tRcpp::stop(\"Dataset already exists.\\n\");\n\t\t}\n\n\t\tif (delete_dsn || (poDS = (GDALDataset *) GDALOpenEx(dsn[0], GDAL_OF_VECTOR | GDAL_OF_UPDATE, \n\t\t\t\tdrivers.data(), options.data(), NULL)) == NULL) {\n\t\t\t// if dsn does not exist, then create:\n\t\t\tif ((poDS = poDriver->Create(dsn[0], 0, 0, 0, GDT_Unknown, options.data())) == NULL) {\n\t\t\t\tRcpp::Rcout << \"Creating dataset \" <<  dsn[0] << \" failed.\" << std::endl;\n\t\t\t\tRcpp::stop(\"Creation failed.\\n\");\n\t\t\t}\n\t\t}\n\t\tif (! quiet) {\n\t\t\tRcpp::Rcout << \"Writing layer `\" << layer[0] << \"' to data source \";\n\t\t\tif (LENGTH(dsn[0]) > width - (44 + LENGTH(layer[0]) + LENGTH(driver[0])))\n\t\t\t\tRcpp::Rcout << std::endl << \"  \";\n\t\t\tRcpp::Rcout << \"`\" << dsn[0] << \"' using driver `\" << driver[0] << \"'\" << std::endl;\n\t\t}\n\t}\n\n\t// can & do transaction?\n\tbool can_do_transaction = (poDS->TestCapability(ODsCTransactions) == TRUE); // can?\n\tbool transaction = false;\n\tif (can_do_transaction) { // try to start transaction:\n\t\tunset_error_handler();\n\t\ttransaction = (poDS->StartTransaction() == OGRERR_NONE); // do?\n\t\tset_error_handler();\n\t\tif (! transaction) { // failed: #nocov start\n\t\t\tGDALClose(poDS);\n\t\t\treturn 1; // transaction failed!\n\t\t} // #nocov end\n\t}\n\n\t// read geometries:\n\tOGRSpatialReference *sref = NULL;\n\tstd::vector<OGRGeometry *> geomv; \n\tOGRwkbGeometryType wkbType;\n\tif (! write_geometries) { // write an aspatial table, see #1345\n\t\twkbType = wkbNone;\n\t\tfor (int i = 0; i < geom.size(); i++)\n\t\t\tgeomv.push_back(NULL);\n\t} else {\n\t\tRcpp::CharacterVector clsv = geom.attr(\"class\");\n\t\twkbType = (OGRwkbGeometryType) make_type(clsv[0], dim[0], false, NULL, 0);\n\t\tgeomv = ogr_from_sfc(geom, &sref);\n\t\tsref = handle_axis_order(sref);\n\t}\n\n\t// create layer:\n\toptions = create_options(lco, quiet);\n\tOGRLayer *poLayer = NULL;\n\tbool update_layer = false;\n\tif ((poLayer = poDS->GetLayerByName(layer[0])) != NULL) {\n\t\tif (!quiet)\n\t\t\tRcpp::Rcout << \"Updating existing layer \" << layer[0] << std::endl;\n\t\tupdate_layer = true;\n\t} else\n\t\tpoLayer = poDS->CreateLayer(layer[0], sref, wkbType, options.data());\n\tif (sref != NULL)\n\t\tsref->Release();\n\tif (poLayer == NULL)  {\n\t\tRcpp::Rcout << \"Creating or updating layer \" << layer[0] << \" failed.\" << std::endl;\n\t\tGDALClose(poDS);\n\t\tRcpp::stop(\"Write error.\\n\");\n\t}\n\n\t// write feature attribute fields & geometries:\n\tstd::vector<OGRFieldType> fieldTypes = SetupFields(poLayer, obj, update_layer);\n\tif (! quiet) {\n\t\tRcpp::Rcout << \"Writing \" << geomv.size() << \" features with \" << \n\t\t\tfieldTypes.size() << \" fields\";\n\t\tif (write_geometries)\n\t\t\tRcpp::Rcout << \" and geometry type \" << OGRGeometryTypeToName(wkbType);\n\t\telse\n\t\t\tRcpp::Rcout << \" without geometries\";\n\t\tRcpp::Rcout << \".\" << std::endl;\n\t}\n\n\tstd::vector<int> fieldIndex = GetFieldIndex(poLayer, obj);\n\n\tfor (size_t i = 0; i < geomv.size(); i++) { // create all features & add to layer:\n\t\tOGRFeature *poFeature = OGRFeature::CreateFeature(poLayer->GetLayerDefn());\n\t\tSetFields(poFeature, fieldTypes, obj, i, fieldIndex);\n\t\tif (write_geometries)\n\t\t\tpoFeature->SetGeometryDirectly(geomv[i]);\n\t\tif (fids.size() > (int) i)\n\t\t\tpoFeature->SetFID(std::stoll(Rcpp::as<std::string>(fids[i]), NULL, 10));\n\t\tif (poLayer->CreateFeature(poFeature) != OGRERR_NONE) {\n\t\t\tRcpp::Rcout << \"Failed to create feature \" << i << \" in \" << layer[0] << std::endl;\n\t\t    // delete layer when  failing to  create feature\n\t\t\tOGRErr err = poDS->DeleteLayer(0);\n\t\t\tGDALClose(poDS);\n\t\t\tif (err != OGRERR_NONE) { // #nocov start\n\t\t\t    if (err == OGRERR_UNSUPPORTED_OPERATION)\n\t\t\t        Rcpp::Rcout << \"Deleting layer not supported by driver `\" << driver[0] << \"'\" << std::endl;\n\t\t\t    else if (! transaction)\n\t\t\t        Rcpp::Rcout << \"Deleting layer `\" << layer[0] << \"' failed\" << std::endl;\n\t\t\t} // #nocov end\n\t\t\tOGRFeature::DestroyFeature(poFeature);\n\t\t\tif (transaction) {\n\t\t\t\tunset_config_options(ConfigOptions);\n\t\t\t\treturn 1; // try once more, writing to tmp file and copy #nocov\n\t\t\t} else\n\t\t\t\tRcpp::stop(\"Feature creation failed.\\n\");\n\t\t}\n\t\tOGRFeature::DestroyFeature(poFeature); // deletes geom[i] as well\n\t}\n\tif (transaction && poDS->CommitTransaction() != OGRERR_NONE) { // #nocov start\n\t\tpoDS->RollbackTransaction();\n\t\tGDALClose(poDS);\n\t\tRcpp::stop(\"CommitTransaction() failed.\\n\"); \n\t} // #nocov end\n\tGDALClose(poDS);\n\tunset_config_options(ConfigOptions);\n\treturn 0; // all O.K.\n}\n\n// delete a data source, or one or more layers within a data source\n// [[Rcpp::export(rng=false)]]\nint CPL_delete_ogr(Rcpp::CharacterVector dsn, Rcpp::CharacterVector layer,\n\tRcpp::CharacterVector driver, bool quiet = true) {\n\n\t// init:\n\tif (driver.size() != 1 || dsn.size() != 1)\n\t\tRcpp::stop(\"argument dsn or driver not of length 1.\\n\");\n\n\t/* GDALAllRegister(); -- has been done during .onLoad() */\n\t// get driver:\n\tGDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName(driver[0]);\n\tif (poDriver == NULL) {\n\t\tRcpp::Rcout << \"driver `\" << driver[0] << \"' not available.\" << std::endl;\n\t\tRcpp::stop(\"Driver not available.\\n\");\n\t}\n\n\t// delete data source:\n\tif (layer.size() == 0) {\n\t\tif (poDriver->Delete(dsn[0]) != CE_None)\n\t\t\tRcpp::Rcout << \"Deleting source `\" << dsn[0] << \"' failed\" << std::endl;\n\t\telse if (! quiet)\n\t\t\tRcpp::Rcout << \"Deleting source `\" << dsn[0] << \"' using driver `\" << driver[0] << \"'\" << std::endl;\n\t\treturn 0;\n\t} \n\n\t// delete layer(s):\n\n\t// data set:\n\tGDALDataset *poDS = (GDALDataset *) GDALOpenEx(dsn[0], GDAL_OF_VECTOR | GDAL_OF_UPDATE, NULL, NULL, NULL); \n\tif (poDS == NULL) {\n\t\tRcpp::Rcout << \"Data source `\" << dsn[0] << \"' not found\" << std::endl;\n\t\treturn 1;\n\t}\n\n\tbool can_do_transaction = (poDS->TestCapability(ODsCTransactions) == TRUE); // can?\n\tbool transaction = false;\n\tif (can_do_transaction) { // try to start transaction:\n\t\tunset_error_handler();\n\t\ttransaction = (poDS->StartTransaction() == OGRERR_NONE); // do?\n\t\tset_error_handler();\n\t\tif (! transaction) { // failed: #nocov start\n\t\t\tGDALClose(poDS);\n\t\t\tRcpp::Rcout << \"On data source `\" << dsn[0] << \"' cannot start transaction\" << std::endl;\n\t\t\treturn 1; // transaction failed!\n\t\t} // #nocov end\n\t}\n\n\tfor (int i = 0; i < layer.size(); i++) { // reverse loop order if inefficient?\n\t\t// find & delete layer:\n\t\tfor (int iLayer = 0; iLayer < poDS->GetLayerCount(); iLayer++) {\n\t\t\tOGRLayer *poLayer = poDS->GetLayer(iLayer);\n\t\t\tif (poLayer != NULL && EQUAL(poLayer->GetName(), layer[i])) {\n\t\t\t\tOGRErr err = poDS->DeleteLayer(iLayer);\n\t\t\t\tif (! quiet) {\n\t\t\t\t\tif (err == OGRERR_UNSUPPORTED_OPERATION)\n\t\t\t\t\t\tRcpp::Rcout << \"Deleting layer not supported by driver `\" << driver[0] << \"'\"  // #nocov\n\t\t\t\t\t\t\t<< std::endl; // #nocov\n\t\t\t\t\telse  {\n\t\t\t\t\t\tRcpp::Rcout << \"Deleting layer `\" << layer[0] << \"' using driver `\" << \n\t\t\t\t\t\t\tdriver[0] << \"'\" << std::endl;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif (err != OGRERR_NONE)\n\t\t\t\t\tRcpp::Rcout << \"Deleting layer `\" << layer[i] << \"' failed\" << std::endl;\n\t\t\t}\n\t\t}\n\t}\n\tif (transaction && poDS->CommitTransaction() != OGRERR_NONE) { // #nocov start\n\t\tpoDS->RollbackTransaction();\n\t\tRcpp::Rcout << \"CommitTransaction() failed.\" << std::endl; \n\t\treturn 1;\n\t} // #nocov end\n\tGDALClose(poDS);\n\treturn 0;\n}\n"
  },
  {
    "path": "src/geos.cpp",
    "content": "#define GEOS_USE_ONLY_R_API // prevents using non-thread-safe GEOSxx functions without _r extension.\n#include <geos_c.h>\n\n#if GEOS_VERSION_MAJOR == 3\n# if GEOS_VERSION_MINOR >= 4\n#  define HAVE340\n# endif\n# if GEOS_VERSION_MINOR >= 5\n#  define HAVE350\n# endif\n# if GEOS_VERSION_MINOR == 6\n#  if GEOS_VERSION_PATCH >= 1\n#   define HAVE361\n#  endif\n# endif\n# if GEOS_VERSION_MINOR >= 7\n#  define HAVE361\n#  define HAVE370\n# endif\n# if GEOS_VERSION_MINOR >= 8\n#  define HAVE380\n# endif\n# if GEOS_VERSION_MINOR >= 9\n#  define HAVE390\n# endif\n# if GEOS_VERSION_MINOR == 10\n#  if GEOS_VERSION_PATCH >= 1\n#   define HAVE3101\n#  endif\n# endif\n# if GEOS_VERSION_MINOR >= 10\n#  define HAVE310\n#  define HAVE3101\n# endif\n# if GEOS_VERSION_MINOR >= 11\n#  define HAVE311\n# endif\n# if GEOS_VERSION_MINOR >= 12\n#  define HAVE312\n# endif\n#else\n# if GEOS_VERSION_MAJOR > 3\n#  define HAVE340\n#  define HAVE350\n#  define HAVE370\n#  define HAVE361\n#  define HAVE380\n#  define HAVE390\n#  define HAVE310\n#  define HAVE3101\n#  define HAVE311\n# endif\n#endif\n\n#include <Rcpp.h>\n#include <memory>\n#include <vector>\n\n#include \"wkb.h\"\n#include \"hex.h\"\n\ntypedef int (* dist_fn)(GEOSContextHandle_t, const GEOSGeometry *, const GEOSGeometry *, double *);\ntypedef int (* dist_parfn)(GEOSContextHandle_t, const GEOSGeometry *, const GEOSGeometry *, double, double *);\ntypedef char (* log_fn)(GEOSContextHandle_t, const GEOSGeometry *, const GEOSGeometry *);\ntypedef char (* log_prfn)(GEOSContextHandle_t, const GEOSPreparedGeometry *,\n\tconst GEOSGeometry *);\ntypedef GEOSGeom (* geom_fn)(GEOSContextHandle_t, const GEOSGeom, const GEOSGeom);\ntypedef GEOSGeom (* geom_fnp)(GEOSContextHandle_t, const GEOSGeom, const GEOSGeom, double grid_size);\n\nstatic void __errorHandler(const char *fmt, ...) { // #nocov start\n\n\tchar buf[BUFSIZ], *p;\n\tva_list ap;\n\tva_start(ap, fmt);\n\tvsnprintf(buf, (size_t) BUFSIZ, fmt, ap);\n\tva_end(ap);\n\tp = buf + strlen(buf) - 1;\n\tif(strlen(buf) > 0 && *p == '\\n') *p = '\\0';\n\n\tRcpp::Function error(\".stop_geos\", Rcpp::Environment::namespace_env(\"sf\"));\n\terror(buf);\n\n\treturn; // #nocov end\n}\n\nstatic void __warningHandler(const char *fmt, ...) {\n\n\tchar buf[BUFSIZ], *p;\n\tva_list ap;\n\tva_start(ap, fmt);\n\tvsnprintf(buf, (size_t) BUFSIZ, fmt, ap);\n\tva_end(ap);\n\tp = buf + strlen(buf) - 1;\n\tif(strlen(buf) > 0 && *p == '\\n') *p = '\\0';\n\n\tRcpp::Function warning(\"warning\");\n\twarning(buf);\n\n\treturn;\n}\n\n// #nocov start\nstatic void __countErrorHandler(const char *fmt, void *userdata) {\n\tint *i = (int *) userdata;\n\t*i = *i + 1;\n}\n\nstatic void __emptyNoticeHandler(const char *fmt, void *userdata) { }\n\n#ifdef GEOS350\nstatic void __checkInterruptFn(void*) {\n\tR_CheckUserInterrupt();\n}\n\nstatic void __checkInterrupt() {\n\t// Adapted from Rcpp/Interrupt.h\n\tif (!R_ToplevelExec(__checkInterruptFn, nullptr)) {\n\t\tGEOS_interruptRequest();\n\t}\n}\n// #nocov end\n#endif\n\n// from terra:\nstatic void __warningIgnore(const char *fmt, ...) {\n\treturn;\n}\n\ninline GEOSContextHandle_t geos_init(void) {\n#ifdef GEOS350\n\tGEOSContextHandle_t ctxt = GEOS_init_r();\n\tGEOSContext_setNoticeHandler_r(ctxt, __warningHandler);\n\tGEOSContext_setErrorHandler_r(ctxt, __errorHandler);\n\tGEOS_interruptRegisterCallback(__checkInterrupt);\n\treturn ctxt;\n#else\n\treturn initGEOS_r((GEOSMessageHandler) __warningHandler, (GEOSMessageHandler) __errorHandler);\n#endif\n}\n\ninline void geos_finish(GEOSContextHandle_t ctxt) {\n#ifdef GEOS350\n\tGEOS_finish_r(ctxt);\n#else\n\tfinishGEOS_r(ctxt);\n#endif\n}\n\ninline GEOSContextHandle_t geos_init2(void) {\n\n#ifdef GEOS350\n\tGEOSContextHandle_t ctxt = GEOS_init_r();\n\tGEOSContext_setNoticeHandler_r(ctxt, __warningIgnore);\n\tGEOSContext_setErrorHandler_r(ctxt, __errorHandler);\n\treturn ctxt;\n#else\n\treturn initGEOS_r((GEOSMessageHandler) __warningIgnore, (GEOSMessageHandler) __errorHandler);\n#endif\n}\n\n// RAII wrapper: declares the context handle before geometry vectors so that,\n// on scope exit, geometry vectors (which call GEOSGeom_destroy_r) are destroyed\n// first, and geos_finish is called last. Implicit conversion to\n// GEOSContextHandle_t means existing code works without changes.\nstruct GEOSContextScope {\n    GEOSContextHandle_t hctx;\n    GEOSContextScope() : hctx(geos_init()) {}\n    explicit GEOSContextScope(bool quiet) : hctx(quiet ? geos_init2() : geos_init()) {}\n    ~GEOSContextScope() { geos_finish(hctx); }\n    operator GEOSContextHandle_t() const { return hctx; }\n    GEOSContextScope(const GEOSContextScope&) = delete;\n    GEOSContextScope& operator=(const GEOSContextScope&) = delete;\n};\n\nstatic int notice = 0; // global var to silently catch notice of illegal geoms, e.g. non-closed rings\n\nvoid cb(void *item, void *userdata) { // callback function for tree selection\n\tstd::vector<size_t> *ret = (std::vector<size_t> *) userdata;\n\tret->push_back(*((size_t *) item));\n}\n\nusing PrepGeomPtr= std::unique_ptr<const GEOSPreparedGeometry, std::function<void(const GEOSPreparedGeometry*)> >;\nusing GeomPtr= std::unique_ptr<GEOSGeometry, std::function<void(GEOSGeometry*)> >;\nusing TreePtr= std::unique_ptr<GEOSSTRtree, std::function<void(GEOSSTRtree*)> >;\n\nstatic GeomPtr geos_ptr(GEOSGeometry* g, GEOSContextHandle_t hGEOSctxt) {\n\tauto deleter = std::bind(GEOSGeom_destroy_r, hGEOSctxt, std::placeholders::_1);\n\treturn GeomPtr(g, deleter);\n}\n\nstatic PrepGeomPtr geos_ptr(const GEOSPreparedGeometry* pg, GEOSContextHandle_t hGEOSctxt) {\n\tauto deleter = std::bind(GEOSPreparedGeom_destroy_r, hGEOSctxt, std::placeholders::_1);\n\treturn PrepGeomPtr(pg, deleter);\n}\n\nstatic TreePtr geos_ptr(GEOSSTRtree* t, GEOSContextHandle_t hGEOSctxt) {\n\tauto deleter = std::bind(GEOSSTRtree_destroy_r, hGEOSctxt, std::placeholders::_1);\n\treturn TreePtr(t, deleter);\n}\n\nstatic std::vector<GEOSGeometry*> to_raw(std::vector<GeomPtr> & g) {\n\tstd::vector<GEOSGeometry*> raw(g.size());\n\tstd::transform(g.begin(), g.end(), raw.begin(), [](GeomPtr & g) { return g.release(); });\n\treturn raw;\n}\n\ndouble geos_grid_size(Rcpp::List x) {\n\tdouble precision = x.attr(\"precision\");\n\tif (precision != 0.0)\n\t\tprecision = 1. / precision;\n\treturn precision;\n}\n\ndouble geos_grid_size_xy(Rcpp::List x, Rcpp::List y) {\n\treturn std::max(geos_grid_size(x), geos_grid_size(y));\n}\n\nstd::vector<GeomPtr> geometries_from_sfc(GEOSContextHandle_t hGEOSCtxt, Rcpp::List sfc, int *dim = NULL, bool stop_on_NULL = true) {\n\n\tRcpp::List sfc_cls = get_dim_sfc(sfc);\n\tRcpp::CharacterVector cls = sfc_cls[\"_cls\"];\n\tif (dim != NULL) {\n\t\tRcpp::IntegerVector sfc_dim = sfc_cls[\"_dim\"];\n\t\tif (sfc_dim.size() == 0)\n\t\t\tRcpp::stop(\"sfc_dim size 0: should not happen\"); // #nocov\n\t\t*dim = sfc_dim[0];\n\t}\n\n\tif (cls[0] == \"XYM\" || cls[0] == \"XYZM\")\n\t\tRcpp::stop(\"GEOS does not support XYM or XYZM geometries; use st_zm() to drop M\\n\"); // #nocov\n\n#ifdef HAVE_390\n\tdouble grid_size = geos_grid_size(sfc);\n\tbool set_precision = grid_size != 0.0;\n\tsfc.attr(\"precision\") = 0.0; // so that CPL_write_wkb doesn't do the rounding;\n#endif\n\tRcpp::List wkblst = CPL_write_wkb(sfc, true);\n\tstd::vector<GeomPtr> g(sfc.size());\n\tGEOSWKBReader *wkb_reader = GEOSWKBReader_create_r(hGEOSCtxt);\n\tfor (int i = 0; i < sfc.size(); i++) {\n\t\tRcpp::RawVector r = wkblst[i];\n\t\tg[i] = geos_ptr(GEOSWKBReader_read_r(hGEOSCtxt, wkb_reader, &(r[0]), r.size()), hGEOSCtxt);\n\t\tif (g[i].get() == NULL) {\n\t\t\tif (stop_on_NULL) {\n\t\t\t\tRcpp::Rcout << \"While converting geometry of record: \" << i << \" to GEOS:\" << std::endl;\n\t\t\t\tRcpp::stop(\"Illegal geometry found: fix manually, or filter out using st_is_valid() and is.na()\\n\");\n\t\t\t}\n\t\t}\n#ifdef HAVE_390\n\t\telse if (set_precision)\n\t\t\tg[i] = geos_ptr(GEOSGeom_setPrecision_r(hGEOSCtxt, g[i].get(), grid_size, GEOS_PREC_VALID_OUTPUT), hGEOSCtxt);\n#endif\n\t}\n\tGEOSWKBReader_destroy_r(hGEOSCtxt, wkb_reader);\n\treturn g;\n}\n\nRcpp::List sfc_from_geometry(GEOSContextHandle_t hGEOSCtxt, std::vector<GeomPtr> & geom, int dim = 2, bool free = true) {\n\n\tRcpp::List out(geom.size());\n\tGEOSWKBWriter *wkb_writer = GEOSWKBWriter_create_r(hGEOSCtxt);\n\tGEOSWKBWriter_setOutputDimension_r(hGEOSCtxt, wkb_writer, dim);\n\t// empty point, binary, with R NA's (not NaN's); GEOS can't WKB empty points,\n\t// so we need to work around; see also https://trac.osgeo.org/postgis/ticket/3031\n\t// > sf:::CPL_raw_to_hex(st_as_binary(st_point()))\n\t// [1] \"0101000000a20700000000f07fa20700000000f07f\"\n\tRcpp::RawVector empty_point(CPL_hex_to_raw(\"0101000000a20700000000f07fa20700000000f07f\")[0]);\n\tfor (size_t i = 0; i < geom.size(); i++) {\n\t\tbool is_empty_point = false;\n\t\tbool is_empty = GEOSisEmpty_r(hGEOSCtxt, geom[i].get()) == 1;\n\t\tif (is_empty) {\n\t\t\tchar *geom_type = GEOSGeomType_r(hGEOSCtxt, geom[i].get());\n\t\t\tis_empty_point = strcmp(\"Point\", geom_type) == 0;\n\t\t\tGEOSFree_r(hGEOSCtxt, geom_type);\n\t\t}\n\t\tif (is_empty_point)\n\t\t\tout[i] = empty_point;\n\t\telse {\n\t\t\tsize_t size;\n\t\t\tunsigned char *buf = GEOSWKBWriter_write_r(hGEOSCtxt, wkb_writer, geom[i].get(), &size);\n\t\t\tRcpp::RawVector raw(size);\n\t\t\tmemcpy(&(raw[0]), buf, size);\n\t\t\tGEOSFree_r(hGEOSCtxt, buf);\n\t\t\tout[i] = raw;\n\t\t}\n\t}\n\tGEOSWKBWriter_destroy_r(hGEOSCtxt, wkb_writer);\n\treturn CPL_read_wkb(out, true, false);\n}\n\nRcpp::NumericVector get_dim(double dim0, double dim1) {\n\tRcpp::NumericVector dim(2);\n\tdim(0) = dim0;\n\tdim(1) = dim1;\n\treturn dim;\n}\n\nRcpp::IntegerVector get_which(Rcpp::LogicalVector row) {\n\tstd::vector<int32_t> v;\n\tfor (int i = 0; i < row.length(); i++)\n\t\tif (row(i))\n\t\t\tv.push_back(i + 1);\n\treturn Rcpp::wrap(v);\n}\n\nbool chk_(char value) {\n\tif (value == 2)\n\t\tRcpp::stop(\"GEOS exception\"); // #nocov\n\treturn value; // 1: true, 0: false\n}\n\nlog_fn which_geom_fn(const std::string op) {\n\tif (op == \"intersects\")\n\t\treturn GEOSIntersects_r;\n//\telse if (op == \"disjoint\")\n//\t\treturn GEOSDisjoint_r;\n\telse if (op == \"touches\")\n\t\treturn GEOSTouches_r;\n\telse if (op == \"crosses\")\n\t\treturn GEOSCrosses_r;\n\telse if (op == \"within\")\n\t\treturn GEOSWithin_r;\n\telse if (op == \"contains\")\n\t\treturn GEOSContains_r;\n\telse if (op == \"overlaps\")\n\t\treturn GEOSOverlaps_r;\n\telse if (op == \"equals\")\n\t\treturn GEOSEquals_r;\n\telse if (op == \"covers\")\n\t\treturn GEOSCovers_r;\n\telse if (op == \"covered_by\")\n\t\treturn GEOSCoveredBy_r;\n\tRcpp::stop(\"wrong value for op: please report as issue\"); // unlikely to happen unless user wants to #nocov\n\treturn GEOSCoveredBy_r; // never reached; satisfy -Wreturn-type #nocov\n}\n\nlog_prfn which_prep_geom_fn(const std::string op) {\n\tif (op == \"intersects\")\n\t\treturn GEOSPreparedIntersects_r;\n//\telse if (op == \"disjoint\")\n//\t\treturn GEOSPreparedDisjoint_r;\n\telse if (op == \"touches\")\n\t\treturn GEOSPreparedTouches_r;\n\telse if (op == \"crosses\")\n\t\treturn GEOSPreparedCrosses_r;\n\telse if (op == \"within\")\n\t\treturn GEOSPreparedWithin_r;\n\telse if (op == \"contains\")\n\t\treturn GEOSPreparedContains_r;\n\telse if (op == \"contains_properly\")\n\t\treturn GEOSPreparedContainsProperly_r;\n\telse if (op == \"overlaps\")\n\t\treturn GEOSPreparedOverlaps_r;\n\t//else if (op == \"equals\")\n\t//\treturn GEOSPreparedEquals_r;\n\telse if (op == \"covers\")\n\t\treturn GEOSPreparedCovers_r;\n\telse if (op == \"covered_by\")\n\t\treturn GEOSPreparedCoveredBy_r;\n\tRcpp::stop(\"wrong value for op\"); // unlikely to happen unless user wants to #nocov\n\treturn GEOSPreparedCoveredBy_r; // never reached; satisfy -Wreturn-type #nocov\n}\n\n/*\nRcpp::LogicalVector get_dense(std::vector<size_t> items, int length) {\n\tRcpp::LogicalVector rowi(length);\n\tfor (int j = 0; j < length; j++)\n\t\trowi(j) = false;\n\tfor (size_t j = 0; j < items.size(); j++)\n\t\trowi(items[j] - 1) = true; // items is 1-based\n\treturn rowi;\n}\n*/\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_geos_binop(Rcpp::List sfc0, Rcpp::List sfc1, std::string op, double par = 0.0,\n\t\tstd::string pattern = \"\", bool prepared = false) {\n\n\tGEOSContextScope hGEOSCtxt;\n\n\tstd::vector<GeomPtr> gmv0 = geometries_from_sfc(hGEOSCtxt, sfc0, NULL);\n\tstd::vector<GeomPtr> gmv1 = geometries_from_sfc(hGEOSCtxt, sfc1, NULL);\n\n\tRcpp::List ret_list;\n\n\tusing namespace Rcpp; // so that later on the (i,_) works\n\tif (op == \"relate\") { // return character matrix:\n\t\tRcpp::CharacterVector out(sfc0.length() * sfc1.length());\n\t\tfor (int i = 0; i < sfc0.length(); i++) {\n\t\t\tfor (int j = 0; j < sfc1.length(); j++) {\n\t\t\t\tchar *cp = GEOSRelate_r(hGEOSCtxt, gmv0[i].get(), gmv1[j].get());\n\t\t\t\tif (cp == NULL) {\n\t\t\t\t\tGEOSFree_r(hGEOSCtxt, cp); // #nocov\n\t\t\t\t\tRcpp::stop(\"GEOS error in GEOSRelate_r\"); // #nocov\n\t\t\t\t}\n\t\t\t\tout[j * sfc0.length() + i] = cp;\n\t\t\t\tGEOSFree_r(hGEOSCtxt, cp);\n\t\t\t}\n\t\t\tRcpp::checkUserInterrupt();\n\t\t}\n\t\tout.attr(\"dim\") = get_dim(sfc0.length(), sfc1.length());\n\t\tret_list = Rcpp::List::create(out);\n\t} else if (op == \"Euclidean\" || op == \"distance\" || op == \"Hausdorff\" || op == \"Frechet\") { // return double matrix:\n\t\t// dist_fn, dist_parfn\n\t\tRcpp::NumericMatrix out(sfc0.length(), sfc1.length());\n\t\tif (par <= 0.0) {\n\t\t\tdist_fn dist_function;\n\t\t\tif (op == \"Euclidean\" || op == \"distance\")\n\t\t\t\tdist_function = GEOSDistance_r;\n\t\t\telse if (op == \"Hausdorff\")\n\t\t\t\tdist_function = GEOSHausdorffDistance_r;\n#ifdef HAVE370\n\t\t\telse if (op == \"Frechet\")\n\t\t\t\tdist_function = GEOSFrechetDistance_r;\n#endif\n\t\t\telse\n\t\t\t\tRcpp::stop(\"distance function not supported\"); // #nocov\n\n\t\t\tfor (size_t i = 0; i < gmv0.size(); i++) {\n\t\t\t\tif (GEOSisEmpty_r(hGEOSCtxt, gmv0[i].get())) {\n\t\t\t\t\tfor (size_t j = 0; j < gmv1.size(); j++) // #nocov\n\t\t\t\t\t\tout(i, j) = NA_REAL;                 // #nocov\n\t\t\t\t} else for (size_t j = 0; j < gmv1.size(); j++) {\n\t\t\t\t\tif (GEOSisEmpty_r(hGEOSCtxt, gmv1[j].get()))\n\t\t\t\t\t\tout(i, j) = NA_REAL;\n\t\t\t\t\telse {\n\t\t\t\t\t\tdouble dist = -1.0;\n\t\t\t\t\t\tif (dist_function(hGEOSCtxt, gmv0[i].get(), gmv1[j].get(), &dist) == 0)\n\t\t\t\t\t\t\tRcpp::stop(\"GEOS error in GEOS_xx_Distance_r\"); // #nocov\n\t\t\t\t\t\tout(i, j) = dist;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tRcpp::checkUserInterrupt();\n\t\t\t}\n\t\t} else {\n\t\t\tdist_parfn dist_function = NULL;\n\t\t\tif (op == \"Hausdorff\")\n\t\t\t\tdist_function = GEOSHausdorffDistanceDensify_r;\n#ifdef HAVE370\n\t\t\telse if (op == \"Frechet\")\n\t\t\t\tdist_function = GEOSFrechetDistanceDensify_r;\n#endif\n\t\t\telse\n\t\t\t\tRcpp::stop(\"distance function not supported\"); // #nocov\n\n\t\t\tfor (size_t i = 0; i < gmv0.size(); i++) {\n\t\t\t\tif (GEOSisEmpty_r(hGEOSCtxt, gmv0[i].get())) {\n\t\t\t\t\tfor (size_t j = 0; j < gmv1.size(); j++)\n\t\t\t\t\t\tout(i, j) = NA_REAL;\n\t\t\t\t} else for (size_t j = 0; j < gmv1.size(); j++) {\n\t\t\t\t\tif (GEOSisEmpty_r(hGEOSCtxt, gmv1[j].get()))\n\t\t\t\t\t\tout(i, j) = NA_REAL;\n\t\t\t\t\telse {\n\t\t\t\t\t\tdouble dist = -1.0;\n\t\t\t\t\t\tif (dist_function(hGEOSCtxt, gmv0[i].get(), gmv1[j].get(), par, &dist) == 0)\n\t\t\t\t\t\t\tRcpp::stop(\"GEOS error in GEOS_xx_Distance_r\"); // #nocov\n\t\t\t\t\t\tout(i, j) = dist;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tRcpp::checkUserInterrupt();\n\t\t\t}\n\t\t}\n\t\tret_list = Rcpp::List::create(out);\n\t} else if (op == \"is_within_distance\") {\n\t\tRcpp::List sparsemat(sfc0.length());\n\t\tfor (size_t i = 0; i < gmv0.size(); i++) {\n\t\t\tstd::vector<size_t> sel;\n\t\t\tfor (size_t j = 0; j < gmv1.size(); j++) {\n\t\t\t\tdouble dist = -1.0;\n\t\t\t\tif (GEOSDistance_r(hGEOSCtxt, gmv0[i].get(), gmv1[j].get(), &dist) == 0)\n\t\t\t\t\tRcpp::stop(\"GEOS error in GEOSDistance_r\"); // #nocov\n\t\t\t\tif (dist <= par)\n\t\t\t\t\tsel.push_back(j + 1); // 1-based\n\t\t\t}\n\t\t\tsparsemat[i] = Rcpp::IntegerVector(sel.begin(), sel.end());\n\t\t\tRcpp::checkUserInterrupt();\n\t\t}\n\t\tret_list = sparsemat;\n\t} else if (gmv1.size()) {\n\t\t// other cases: sparse matrix\n\t\tRcpp::List sparsemat(sfc0.length());\n\n\t\tstd::vector<size_t> items(gmv1.size());\n\t\tTreePtr tree1 = geos_ptr(GEOSSTRtree_create_r(hGEOSCtxt, 10), hGEOSCtxt);\n\t\tfor (size_t i = 0; i < gmv1.size(); i++) {\n\t\t\titems[i] = i;\n\t\t\tif (! GEOSisEmpty_r(hGEOSCtxt, gmv1[i].get()))\n\t\t\t\tGEOSSTRtree_insert_r(hGEOSCtxt, tree1.get(), gmv1[i].get(), &(items[i]));\n\t\t}\n\n\t\tif (op == \"equals_exact\") { // has it's own signature, needing `par':\n\t\t\tfor (int i = 0; i < sfc0.length(); i++) { // row\n\t\t\t\tRcpp::LogicalVector rowi(sfc1.length());\n\t\t\t\tfor (int j = 0; j < sfc1.length(); j++)\n\t\t\t\t\trowi(j) = chk_(GEOSEqualsExact_r(hGEOSCtxt, gmv0[i].get(), gmv1[j].get(), par));\n\t\t\t\tsparsemat[i] = get_which(rowi);\n\t\t\t\tRcpp::checkUserInterrupt();\n\t\t\t}\n\t\t} else if (op == \"relate_pattern\") { // needing pattern\n\t\t\tif (GEOSRelatePatternMatch_r(hGEOSCtxt, pattern.c_str(), \"FF*FF****\"))\n\t\t\t\tRcpp::stop(\"use st_disjoint for this pattern\");\n\t\t\t// all remaining can use tree:\n\t\t\tfor (int i = 0; i < sfc0.length(); i++) { // row\n\t\t\t\t// pre-select sfc1's using tree:\n\t\t\t\tstd::vector<size_t> tree_sel, sel;\n\t\t\t\tif (! GEOSisEmpty_r(hGEOSCtxt, gmv0[i].get()))\n\t\t\t\t\tGEOSSTRtree_query_r(hGEOSCtxt, tree1.get(), gmv0[i].get(), cb, &tree_sel);\n\t\t\t\tfor (size_t j = 0; j < tree_sel.size(); j++)\n\t\t\t\t\tif (chk_(GEOSRelatePattern_r(hGEOSCtxt, gmv0[i].get(), gmv1[tree_sel[j]].get(), pattern.c_str())))\n\t\t\t\t\t\tsel.push_back(tree_sel[j] + 1); // 1-based\n\t\t\t\tstd::sort(sel.begin(), sel.end());\n\t\t\t\tsparsemat[i] = Rcpp::IntegerVector(sel.begin(), sel.end());\n\t\t\t\tRcpp::checkUserInterrupt();\n\t\t\t}\n\t\t} else if (op == \"disjoint\")\n\t\t\tRcpp::stop(\"disjoint should have been handled in R\"); // #nocov\n\t\telse { // anything else:\n\t\t\tif (prepared) {\n\t\t\t\tlog_prfn logical_fn = which_prep_geom_fn(op);\n\t\t\t\tfor (int i = 0; i < sfc0.length(); i++) { // row\n\t\t\t\t\t// pre-select sfc1's using tree:\n\t\t\t\t\tstd::vector<size_t> tree_sel, sel;\n\t\t\t\t\tif (! GEOSisEmpty_r(hGEOSCtxt, gmv0[i].get()))\n\t\t\t\t\t\tGEOSSTRtree_query_r(hGEOSCtxt, tree1.get(), gmv0[i].get(), cb, &tree_sel);\n\n\t\t\t\t\tif (! tree_sel.empty()) {\n\t\t\t\t\t\tPrepGeomPtr pr = geos_ptr(GEOSPrepare_r(hGEOSCtxt, gmv0[i].get()), hGEOSCtxt);\n\t\t\t\t\t\tfor (size_t j = 0; j < tree_sel.size(); j++)\n\t\t\t\t\t\t\tif (chk_(logical_fn(hGEOSCtxt, pr.get(), gmv1[tree_sel[j]].get())))\n\t\t\t\t\t\t\t\tsel.push_back(tree_sel[j] + 1); // 1-based\n\t\t\t\t\t\tstd::sort(sel.begin(), sel.end());\n\t\t\t\t\t}\n\n\t\t\t\t\tsparsemat[i] = Rcpp::IntegerVector(sel.begin(), sel.end());\n\t\t\t\t\tRcpp::checkUserInterrupt();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tlog_fn logical_fn = which_geom_fn(op);\n\t\t\t\tfor (int i = 0; i < sfc0.length(); i++) { // row\n\t\t\t\t\t// pre-select sfc1's using tree:\n\t\t\t\t\tstd::vector<size_t> tree_sel, sel;\n\t\t\t\t\tif (! GEOSisEmpty_r(hGEOSCtxt, gmv0[i].get()))\n\t\t\t\t\t\tGEOSSTRtree_query_r(hGEOSCtxt, tree1.get(), gmv0[i].get(), cb, &tree_sel);\n\t\t\t\t\tfor (size_t j = 0; j < tree_sel.size(); j++)\n\t\t\t\t\t\tif (chk_(logical_fn(hGEOSCtxt, gmv0[i].get(), gmv1[tree_sel[j]].get())))\n\t\t\t\t\t\t\tsel.push_back(tree_sel[j] + 1); // 1-based\n\t\t\t\t\tstd::sort(sel.begin(), sel.end());\n\t\t\t\t\tsparsemat[i] = Rcpp::IntegerVector(sel.begin(), sel.end());\n\t\t\t\t\tRcpp::checkUserInterrupt();\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tret_list = sparsemat;\n\t} else { // gmv1.size() == 0:\n\t\tRcpp::List sparsemat(sfc0.length());\n\t\tfor (size_t i = 0; i < gmv0.size(); i++)\n\t\t\tsparsemat[i] = Rcpp::IntegerVector();\n\t\tret_list = sparsemat;\n\t}\n\treturn ret_list;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_geos_binop_by_element(Rcpp::List sfc0, Rcpp::List sfc1,\n                                     std::string op, double par, std::string pattern, bool prepared) {\n  \n  GEOSContextScope hGEOSCtxt;\n\n  std::vector<GeomPtr> gmv0 = geometries_from_sfc(hGEOSCtxt, sfc0, NULL);\n  std::vector<GeomPtr> gmv1 = geometries_from_sfc(hGEOSCtxt, sfc1, NULL);\n\n  if (gmv0.size() != gmv1.size())\n    Rcpp::stop(\"for element-wise predicates, x and y must have equal length\");\n\n  size_t n = gmv0.size();\n  Rcpp::List ret_list;\n  \n  if (op == \"relate\") {\n    Rcpp::CharacterVector out(n);\n    for (size_t i = 0; i < n; i++) {\n      char *cp = GEOSRelate_r(hGEOSCtxt, gmv0[i].get(), gmv1[i].get());\n      if (cp == NULL)\n        Rcpp::stop(\"GEOS error in GEOSRelate_r\"); // #nocov\n      out[i] = cp;\n      GEOSFree_r(hGEOSCtxt, cp);\n      Rcpp::checkUserInterrupt();\n    }\n    ret_list = Rcpp::List::create(out);\n  } else if (op == \"relate_pattern\") {\n    Rcpp::LogicalVector out(n);\n    for (size_t i = 0; i < n; i++) {\n      out[i] = chk_(GEOSRelatePattern_r(hGEOSCtxt,\n                                        gmv0[i].get(), gmv1[i].get(), pattern.c_str()));\n      Rcpp::checkUserInterrupt();\n    }\n    ret_list = Rcpp::List::create(out);\n  } else if (op == \"equals_exact\") {\n    Rcpp::LogicalVector out(n);\n    for (size_t i = 0; i < n; i++) {\n      out[i] = chk_(GEOSEqualsExact_r(hGEOSCtxt,\n                                      gmv0[i].get(), gmv1[i].get(), par));\n      Rcpp::checkUserInterrupt();\n    }\n    ret_list = Rcpp::List::create(out);\n  } else if (op == \"is_within_distance\") {\n    Rcpp::LogicalVector out(n);\n    for (size_t i = 0; i < n; i++) {\n      double dist = -1.0;\n\n      if (GEOSDistance_r(hGEOSCtxt, gmv0[i].get(), gmv1[i].get(), &dist) == 0)\n        Rcpp::stop(\"GEOS error in GEOSDistance_r\"); // #nocov\n\t\t\t\t\t\t\t\t\t\t\t\t\t//\n      out[i] = dist <= par;\n      Rcpp::checkUserInterrupt();\n    }\n    ret_list = Rcpp::List::create(out);\n  } else {\n    log_fn logical_fn = which_geom_fn(op);\n    Rcpp::LogicalVector out(n);\n    for (size_t i = 0; i < n; i++) {\n      out[i] = chk_(logical_fn(hGEOSCtxt, gmv0[i].get(), gmv1[i].get()));\n      Rcpp::checkUserInterrupt();\n    }\n    ret_list = Rcpp::List::create(out);\n  }\n  return ret_list;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::CharacterVector CPL_geos_is_valid_reason(Rcpp::List sfc) {\n\tGEOSContextScope hGEOSCtxt;\n\n\tstd::vector<GeomPtr> gmv = geometries_from_sfc(hGEOSCtxt, sfc, NULL, false);\n\tRcpp::CharacterVector out(gmv.size());\n\tfor (int i = 0; i < out.length(); i++) {\n\t\tif (gmv[i].get() == NULL)\n\t\t\tout[i] = NA_STRING;\n\t\telse {\n\t\t\tchar *buf = GEOSisValidReason_r(hGEOSCtxt, gmv[i].get());\n\t\t\tif (buf == NULL)\n\t\t\t\tout[i] = NA_STRING; // #nocov\n\t\t\telse {\n\t\t\t\tout[i] = buf;\n\t\t\t\tGEOSFree_r(hGEOSCtxt, buf);\n\t\t\t}\n\t\t}\n\t}\n\treturn out;\n}\n\n// #nocov start - no GEOS 3.8.0 on travis yet\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_geos_make_valid(Rcpp::List sfc, std::string method, bool keep_collapsed) {\n\tGEOSContextScope hGEOSCtxt;\n\n\tstd::vector<GeomPtr> gmv = geometries_from_sfc(hGEOSCtxt, sfc, NULL);\n\tstd::vector<GeomPtr> out(gmv.size());\n#ifdef HAVE380\n# ifdef HAVE3101\n\tGEOSMakeValidParams *makeValidParams = GEOSMakeValidParams_create_r(hGEOSCtxt);\n\tif (method == \"valid_linework\")\n\t\tGEOSMakeValidParams_setMethod_r(hGEOSCtxt, makeValidParams, GEOS_MAKE_VALID_LINEWORK);\n\telse if (method == \"valid_structure\")\n\t\tGEOSMakeValidParams_setMethod_r(hGEOSCtxt, makeValidParams, GEOS_MAKE_VALID_STRUCTURE);\n\telse\n\t\tRcpp::stop(\"geos_method not recognized\");\n\tGEOSMakeValidParams_setKeepCollapsed_r(hGEOSCtxt, makeValidParams, (int) keep_collapsed);\n\tfor (size_t i = 0; i < gmv.size(); i++)\n\t\tgmv[i] = geos_ptr(GEOSMakeValidWithParams_r(hGEOSCtxt, gmv[i].get(), makeValidParams), hGEOSCtxt);\n\tGEOSMakeValidParams_destroy_r(hGEOSCtxt, makeValidParams);\n# else\n\tfor (size_t i = 0; i < gmv.size(); i++)\n\t\tgmv[i] = geos_ptr(GEOSMakeValid_r(hGEOSCtxt, gmv[i].get()), hGEOSCtxt);\n# endif\n#else\n\tRcpp::stop(\"this shouldn't happen: st_make_valid should use lwgeom\");\n#endif\n\tRcpp::List ret = sfc_from_geometry(hGEOSCtxt, gmv);\n\treturn ret;\n}\n// #nocov end\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_geos_is_valid(Rcpp::List sfc, bool NA_on_exception = true) {\n\tGEOSContextScope hGEOSCtxt;\n\n\tnotice = 0;\n\tif (NA_on_exception) {\n/*\n\t\tif (sfc.size() > 1)\n\t\t\tRcpp::stop(\"NA_on_exception will only work reliably with length 1 sfc objects\"); // #nocov\n*/\n#ifdef HAVE350\n\t\tGEOSContext_setNoticeMessageHandler_r(hGEOSCtxt,\n\t\t\t(GEOSMessageHandler_r) __emptyNoticeHandler, (void *) &notice);\n\t\tGEOSContext_setErrorMessageHandler_r(hGEOSCtxt,\n\t\t\t(GEOSMessageHandler_r) __countErrorHandler, (void *) &notice);\n#endif\n\t}\n\tRcpp::LogicalVector out(sfc.size());\n\tfor (int i = 0; i < out.length(); i++) {\n\t\t// get geometry i:\n\t\tRcpp::List geom_i = Rcpp::List::create(sfc[i]);\n\t\tgeom_i.attr(\"precision\") = sfc.attr(\"precision\");\n\t\tgeom_i.attr(\"class\") = sfc.attr(\"class\");\n\t\tgeom_i.attr(\"crs\") = sfc.attr(\"crs\");\n\t\tSEXP classes = sfc.attr(\"classes\");\n\t\tif (classes != R_NilValue) {\n\t\t\tRcpp::CharacterVector cl = sfc.attr(\"classes\");\n\t\t\tgeom_i.attr(\"classes\") = cl[i];\n\t\t}\n\t\tstd::vector<GeomPtr> gmv = geometries_from_sfc(hGEOSCtxt, geom_i, NULL, false); // where notice might be set!\n\t\tint ret;\n\t\tif (gmv[0].get() == NULL)\n\t\t\tret = 2;\n\t\telse\n\t\t\tret = GEOSisValid_r(hGEOSCtxt, gmv[0].get());\n\t\tif (NA_on_exception && (ret == 2 || notice != 0))\n\t\t\tout[i] = NA_LOGICAL; // no need to set notice back here, as we only consider 1 geometry #nocov\n\t\telse\n\t\t\tout[i] = chk_(ret);\n\t\tnotice = 0; // reset notice.\n\t}\n#ifdef HAVE350\n\tGEOSContext_setNoticeHandler_r(hGEOSCtxt, __warningHandler);\n\tGEOSContext_setErrorHandler_r(hGEOSCtxt, __errorHandler);\n#endif\n\treturn out;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_geos_is_simple(Rcpp::List sfc) {\n\tGEOSContextScope hGEOSCtxt;\n\tRcpp::LogicalVector out(sfc.length());\n\tstd::vector<GeomPtr> g = geometries_from_sfc(hGEOSCtxt, sfc, NULL);\n\tfor (size_t i = 0; i < g.size(); i++)\n\t\tout[i] = chk_(GEOSisSimple_r(hGEOSCtxt, g[i].get()));\n\treturn out;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_geos_is_empty(Rcpp::List sfc) {\n\tGEOSContextScope hGEOSCtxt;\n\tRcpp::LogicalVector out(sfc.length());\n\tstd::vector<GeomPtr> g = geometries_from_sfc(hGEOSCtxt, sfc, NULL);\n\tfor (size_t i = 0; i < g.size(); i++)\n\t\tout[i] = chk_(GEOSisEmpty_r(hGEOSCtxt, g[i].get()));\n\treturn out;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_geos_normalize(Rcpp::List sfc) { // #nocov start\n\tint dim = 2;\n\tGEOSContextScope hGEOSCtxt;\n\tstd::vector<GeomPtr> gmv = geometries_from_sfc(hGEOSCtxt, sfc, &dim);\n\tfor (int i = 0; i < sfc.size(); i++) {\n\t\tif (GEOSNormalize_r(hGEOSCtxt, gmv[i].get()) == -1)\n\t\t\tRcpp::stop(\"normalize: GEOS exception\");\n\t}\n\tRcpp::List out(sfc_from_geometry(hGEOSCtxt, gmv, dim));\n\tout.attr(\"precision\") = sfc.attr(\"precision\");\n\tout.attr(\"crs\") = sfc.attr(\"crs\");\n\treturn out;\n} // #nocov end\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_geos_union(Rcpp::List sfc, bool by_feature = false, bool is_coverage = false) {\n\n\tGEOSContextScope hGEOSCtxt;\n#ifndef HAVE380\n\tif (is_coverage) {\n\t\tRcpp::warning(\"ignoring 'is_coverage = TRUE' which requires GEOS version 3.8 or greater\");\n\t\tis_coverage = false;\n\t}\n#endif\n\n\tif (sfc.size() == 0)\n\t\treturn sfc; // #nocov\n\n\tint dim = 2;\n\tstd::vector<GeomPtr> gmv = geometries_from_sfc(hGEOSCtxt, sfc, &dim);\n\tstd::vector<GeomPtr> gmv_out(by_feature ? sfc.size() : 1);\n\n\tif (by_feature) {\n\t\tfor (int i = 0; i < sfc.size(); i++) {\n\t\t\tgmv_out[i] = geos_ptr(GEOSUnaryUnion_r(hGEOSCtxt, gmv[i].get()), hGEOSCtxt);\n\t\t}\n\t} else {\n\t\tbool all_inputs_same = true;\n\n\t\t// check to see if all geometries are identical, as in a call to summarize(..., do_union=TRUE)\n\t\tfor (size_t i = 1; i < gmv.size(); i++) {\n\t\t\tif (!GEOSEqualsExact_r(hGEOSCtxt, gmv[0].get(), gmv[i].get(), 0.0)) {\n\t\t\t\tall_inputs_same = false;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (all_inputs_same) {\n\t\t\tgmv_out[0] = std::move(gmv[0]);\n\t\t} else {\n\t\t\tGeomPtr gc = geos_ptr(GEOSGeom_createCollection_r(hGEOSCtxt, GEOS_GEOMETRYCOLLECTION, to_raw(gmv).data(), gmv.size()), hGEOSCtxt);\n\n#ifdef HAVE380\n\t\t\tif (is_coverage)\n\t\t\t\tgmv_out[0] = geos_ptr(GEOSCoverageUnion_r(hGEOSCtxt, gc.get()), hGEOSCtxt);\n\t\t\telse\n#endif\n\t\t\tgmv_out[0] = geos_ptr(GEOSUnaryUnion_r(hGEOSCtxt, gc.get()), hGEOSCtxt);\n\t\t}\n\t}\n\n\tRcpp::List out(sfc_from_geometry(hGEOSCtxt, gmv_out, dim));\n\tout.attr(\"precision\") = sfc.attr(\"precision\");\n\tout.attr(\"crs\") = sfc.attr(\"crs\");\n\treturn out;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_geos_snap(Rcpp::List sfc0, Rcpp::List sfc1, Rcpp::NumericVector tolerance) {\n\tint dim = 2;\n\tGEOSContextScope hGEOSCtxt;\n\tstd::vector<GeomPtr> gmv0 = geometries_from_sfc(hGEOSCtxt, sfc0, &dim);\n\tstd::vector<GeomPtr> gmv1 = geometries_from_sfc(hGEOSCtxt, sfc1, &dim);\n\tGeomPtr gc;\n\tif (gmv1.size() > 1)\n\t\tgc = geos_ptr(GEOSGeom_createCollection_r(hGEOSCtxt, GEOS_GEOMETRYCOLLECTION,\n\t\t\tto_raw(gmv1).data(), gmv1.size()), hGEOSCtxt);\n\telse\n\t\tgc = std::move(gmv1[0]);\n\n\tstd::vector<GeomPtr> gmv_out(sfc0.size());\n\tfor (int i = 0; i < sfc0.size(); i++) {\n\t\tgmv_out[i] = geos_ptr(GEOSSnap_r(hGEOSCtxt, gmv0[i].get(), gc.get(), tolerance[i]), hGEOSCtxt);\n\t\tif (gmv_out[i] == NULL)\n\t\t\tRcpp::stop(\"snap: GEOS exception\"); // #nocov\n\t}\n\tRcpp::List out(sfc_from_geometry(hGEOSCtxt, gmv_out, dim));\n\tout.attr(\"precision\") = sfc0.attr(\"precision\");\n\tout.attr(\"crs\") = sfc0.attr(\"crs\");\n\treturn out;\n}\n\nGEOSGeometry *chkNULL(GEOSGeometry *value) {\n\tif (value == NULL)\n\t\tRcpp::stop(\"GEOS exception\"); // #nocov\n\tRcpp::checkUserInterrupt();\n\treturn value;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_geos_op(std::string op, Rcpp::List sfc,\n                       Rcpp::NumericVector bufferDist, Rcpp::IntegerVector nQuadSegs,\n                       Rcpp::NumericVector dTolerance, Rcpp::LogicalVector preserveTopology,\n                       int bOnlyEdges = 1,\n                       Rcpp::IntegerVector endCapStyle = 0, Rcpp::IntegerVector joinStyle = 0,\n\t\t\t\t\t   Rcpp::NumericVector mitreLimit = 1, Rcpp::LogicalVector singleside = 0)\n{\n\tGEOSContextScope hGEOSCtxt;\n\tint dim = 2;\n\n\tstd::vector<GeomPtr> g = geometries_from_sfc(hGEOSCtxt, sfc, &dim);\n\tstd::vector<GeomPtr> out(sfc.length());\n\n\tif (op == \"buffer\") {\n\t\tif (bufferDist.size() != (int) g.size())\n\t\t\tRcpp::stop(\"invalid dist argument\"); // #nocov\n\t\tfor (size_t i = 0; i < g.size(); i++)\n\t\t\tout[i] = geos_ptr(chkNULL(GEOSBuffer_r(hGEOSCtxt, g[i].get(), bufferDist[i], nQuadSegs[i])), hGEOSCtxt);\n\t} else if (op == \"buffer_with_style\") {\n\t\tGEOSBufferParams *bufferparams = GEOSBufferParams_create_r(hGEOSCtxt);\n\t\tfor (size_t i = 0; i < g.size(); i++) {\n\t\t\tif (GEOSBufferParams_setEndCapStyle_r(hGEOSCtxt, bufferparams, endCapStyle[i]) &&\n\t\t\t\t\tGEOSBufferParams_setJoinStyle_r(hGEOSCtxt, bufferparams, joinStyle[i]) &&\n\t\t\t\t\tGEOSBufferParams_setMitreLimit_r(hGEOSCtxt, bufferparams, mitreLimit[i]) &&\n\t\t\t\t\tGEOSBufferParams_setQuadrantSegments_r(hGEOSCtxt, bufferparams, nQuadSegs[i]) &&\n\t\t\t\t\tGEOSBufferParams_setSingleSided_r(hGEOSCtxt, bufferparams, singleside[i]))\n\t\t\t\t// out[i] = geos_ptr(chkNULL(GEOSBufferWithStyle_r(hGEOSCtxt, g[i].get(), bufferDist[i], nQuadSegs[i], endCapStyle[i], joinStyle[i], mitreLimit[i])), hGEOSCtxt);\n\t\t\t\tout[i] = geos_ptr(chkNULL(GEOSBufferWithParams_r(hGEOSCtxt, g[i].get(),\n\t\t\t\t\tbufferparams, bufferDist[i])), hGEOSCtxt);\n\t\t\telse\n\t\t\t\tRcpp::stop(\"invalid buffer parameters\"); // #nocov\n\t\t}\n\t\tGEOSBufferParams_destroy_r(hGEOSCtxt, bufferparams);\n\t} else if (op == \"boundary\") {\n\t\tfor (size_t i = 0; i < g.size(); i++)\n\t\t\tout[i] = geos_ptr(chkNULL(GEOSBoundary_r(hGEOSCtxt, g[i].get())), hGEOSCtxt);\n\t} else if (op == \"concave_hull\") {\n#ifdef HAVE311\n\t\tdouble ratio = bufferDist[0];\n\t\tunsigned int allowHoles = preserveTopology[0];\n\t\tfor (size_t i = 0; i < g.size(); i++)\n\t\t\tout[i] = geos_ptr(chkNULL(GEOSConcaveHull_r(hGEOSCtxt, g[i].get(), ratio, allowHoles)), hGEOSCtxt);\n#else\n\t\tRcpp::stop(\"st_concave_hull requires GEOS >= 3.11\");\n#endif\n\t} else if (op == \"convex_hull\") {\n\t\tfor (size_t i = 0; i < g.size(); i++)\n\t\t\tout[i] = geos_ptr(chkNULL(GEOSConvexHull_r(hGEOSCtxt, g[i].get())), hGEOSCtxt);\n\t} else if (op == \"simplify\") {\n\t\tfor (size_t i = 0; i < g.size(); i++)\n\t\t\tout[i] = geos_ptr(\n\t\t\t\t\tpreserveTopology[i] ?\n\t\t\t\t\t\tchkNULL(GEOSTopologyPreserveSimplify_r(hGEOSCtxt, g[i].get(),\n\t\t\t\t\t\t\tdTolerance[i])) :\n\t\t\t\t\t\tchkNULL(GEOSSimplify_r(hGEOSCtxt, g[i].get(), dTolerance[i])), hGEOSCtxt);\n\t} else if (op == \"linemerge\") {\n\t\tfor (size_t i = 0; i < g.size(); i++)\n\t\t\tout[i] = geos_ptr(chkNULL(GEOSLineMerge_r(hGEOSCtxt, g[i].get())), hGEOSCtxt);\n\t} else if (op == \"linemergedirected\") {\n#ifdef HAVE311\n\t\tfor (size_t i = 0; i < g.size(); i++)\n\t\t\tout[i] = geos_ptr(chkNULL(GEOSLineMergeDirected_r(hGEOSCtxt, g[i].get())), hGEOSCtxt);\n#else\n\t\tRcpp::stop(\"directed line merge requires GEOS >= 3.11\");\n#endif\n\t} else if (op == \"polygonize\") {\n\t\tfor (size_t i = 0; i < g.size(); i++) {\n\t\t\tconst GEOSGeometry* gi = g[i].get();\n\t\t\tout[i] = geos_ptr(chkNULL(GEOSPolygonize_r(hGEOSCtxt, &gi, 1)), hGEOSCtxt);\n\t\t}\n\t} else if (op == \"centroid\") {\n\t\tfor (size_t i = 0; i < g.size(); i++) {\n\t\t\tout[i] = geos_ptr(chkNULL(GEOSGetCentroid_r(hGEOSCtxt, g[i].get())), hGEOSCtxt);\n\t\t}\n\t} else\n\tif (op == \"node\") {\n\t\tfor (size_t i = 0; i < g.size(); i++) {\n\t\t\tout[i] = geos_ptr(chkNULL(GEOSNode_r(hGEOSCtxt, g[i].get())), hGEOSCtxt);\n\t\t}\n\t} else if (op == \"point_on_surface\") {\n\t\tfor (size_t i = 0; i < g.size(); i++) {\n\t\t\tout[i] = geos_ptr(chkNULL(GEOSPointOnSurface_r(hGEOSCtxt, g[i].get())), hGEOSCtxt);\n\t\t}\n\t} else\n#ifdef HAVE340\n\tif (op == \"triangulate\") {\n\t\tfor (size_t i = 0; i < g.size(); i++)\n\t\t\tout[i] = geos_ptr(chkNULL(GEOSDelaunayTriangulation_r(hGEOSCtxt, g[i].get(),\n\t\t\t\tdTolerance[i], bOnlyEdges)), hGEOSCtxt);\n\t} else\n#endif\n#ifdef HAVE310\n\tif (op == \"triangulate_constrained\") {\n\t\tfor (size_t i = 0; i < g.size(); i++)\n\t\t\tout[i] = geos_ptr(chkNULL(GEOSConstrainedDelaunayTriangulation_r(hGEOSCtxt, g[i].get())), \n\t\t\t\t\t\t\thGEOSCtxt);\n\t} else\n#endif\n#ifdef HAVE370\n\tif (op == \"reverse\") {\n\t\tfor (size_t i = 0; i < g.size(); i++) {\n\t\t\tout[i] = geos_ptr(chkNULL(GEOSReverse_r(hGEOSCtxt, g[i].get())), hGEOSCtxt);\n\t\t}\n\t} else\n#endif\n#ifdef HAVE380\n\tif (op == \"bounding_circle\") {\n\t\tdouble r;\n\t\tfor (size_t i = 0; i < g.size(); i++)\n\t\t\tout[i] = geos_ptr(chkNULL(GEOSMinimumBoundingCircle_r(hGEOSCtxt, g[i].get(), &r, NULL)), hGEOSCtxt);\n\t} else\n#endif\n#ifdef HAVE390\n\tif (op == \"inscribed_circle\") {\n\t\tfor (size_t i = 0; i < g.size(); i++) {\n\t\t\tout[i] = geos_ptr(chkNULL(GEOSMaximumInscribedCircle_r(hGEOSCtxt, g[i].get(),\n\t\t\t\tdTolerance[i])), hGEOSCtxt);\n\t\t}\n\t} else if (op == \"minimum_rotated_rectangle\") {\n\t\tfor (size_t i = 0; i < g.size(); i++) {\n\t\t\tout[i] = geos_ptr(chkNULL(GEOSMinimumRotatedRectangle_r(hGEOSCtxt, g[i].get())), hGEOSCtxt);\n\t\t}\n\t} else\n#endif\n\t\tRcpp::stop(\"invalid operation\"); // #nocov\n\n\tRcpp::List ret(sfc_from_geometry(hGEOSCtxt, out, dim));\n\tret.attr(\"precision\") = sfc.attr(\"precision\");\n\tret.attr(\"crs\") = sfc.attr(\"crs\");\n\treturn ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_geos_voronoi(Rcpp::List sfc, Rcpp::List env, double dTolerance = 0.0, int bOnlyEdges = 1) {\n\n\tGEOSContextScope hGEOSCtxt;\n\tint dim = 2;\n\n\tstd::vector<GeomPtr> g = geometries_from_sfc(hGEOSCtxt, sfc, &dim);\n\tstd::vector<GeomPtr> out(sfc.length());\n\n#ifdef HAVE350\n\tswitch (env.size()) {\n\t\tcase 0: ;\n\t\tcase 1: {\n\t\t\tstd::vector<GeomPtr> g_env = geometries_from_sfc(hGEOSCtxt, env);\n\t\t\tfor (size_t i = 0; i < g.size(); i++) {\n\t\t\t\tout[i] = geos_ptr(chkNULL(GEOSVoronoiDiagram_r(hGEOSCtxt, g[i].get(),\n\t\t\t\t\tg_env.size() ? g_env[0].get() : NULL, dTolerance, bOnlyEdges)), hGEOSCtxt);\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\t\tdefault:\n\t\t\tRcpp::stop(\"env should have length 0 or 1\"); // #nocov\n\t}\n#else\n\tRcpp::stop(\"voronoi diagrams require a GEOS version >= 3.5.0\"); // #nocov\n#endif\n\n\tRcpp::List ret(sfc_from_geometry(hGEOSCtxt, out, dim));\n\tret.attr(\"precision\") = sfc.attr(\"precision\");\n\tret.attr(\"crs\") = sfc.attr(\"crs\");\n\treturn ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_geos_op2(std::string op, Rcpp::List sfcx, Rcpp::List sfcy) {\n\n\tusing namespace Rcpp; // so that later on the (_,1) works\n\n\tint dim = 2;\n\tGEOSContextScope hGEOSCtxt;\n\tstd::vector<GeomPtr> x = geometries_from_sfc(hGEOSCtxt, sfcx, &dim);\n\tstd::vector<GeomPtr> y = geometries_from_sfc(hGEOSCtxt, sfcy, &dim);\n\tstd::vector<GeomPtr> out;\n\tstd::vector<double> index_x, index_y;\n\tstd::vector<size_t> items(x.size());\n#ifdef HAVE_390\n\tdouble grid_size = geos_grid_size_xy(sfcx, sfcy);\n#endif\n\n\tif (op == \"intersection\") {\n\n\t\tbool tree_empty = true;\n\t\tTreePtr tree = geos_ptr(GEOSSTRtree_create_r(hGEOSCtxt, 10), hGEOSCtxt);\n\t\tfor (size_t i = 0; i < x.size(); i++) {\n\t\t\titems[i] = i;\n\t\t\tif (! GEOSisEmpty_r(hGEOSCtxt, x[i].get())) {\n\t\t\t\tGEOSSTRtree_insert_r(hGEOSCtxt, tree.get(), x[i].get(), &(items[i]));\n\t\t\t\ttree_empty = false;\n\t\t\t}\n\t\t}\n\n\t\tfor (size_t i = 0; i < y.size(); i++) {\n\t\t\t// select x's using tree:\n\t\t\tstd::vector<size_t> sel;\n\t\t\tsel.reserve(x.size());\n\t\t\tif (! GEOSisEmpty_r(hGEOSCtxt, y[i].get()) && ! tree_empty)\n\t\t\t\tGEOSSTRtree_query_r(hGEOSCtxt, tree.get(), y[i].get(), cb, &sel);\n\t\t\tstd::sort(sel.begin(), sel.end());\n\t\t\tfor (size_t item = 0; item < sel.size(); item++) {\n\t\t\t\tsize_t j = sel[item];\n#ifndef HAVE_390\n\t\t\t\tGeomPtr geom = geos_ptr(GEOSIntersection_r(hGEOSCtxt, x[j].get(), y[i].get()), hGEOSCtxt);\n#else\n\t\t\t\tGeomPtr geom = geos_ptr(GEOSIntersectionPrec_r(hGEOSCtxt, x[j].get(), y[i].get(), grid_size), hGEOSCtxt);\n#endif\n\t\t\t\tif (geom == nullptr)\n\t\t\t\t\tRcpp::stop(\"GEOS exception\"); // #nocov\n\t\t\t\tif (! chk_(GEOSisEmpty_r(hGEOSCtxt, geom.get()))) {\n\t\t\t\t\tindex_x.push_back(j + 1);\n\t\t\t\t\tindex_y.push_back(i + 1);\n\t\t\t\t\tout.push_back(std::move(geom)); // keep\n\t\t\t\t}\n\t\t\t\tRcpp::checkUserInterrupt();\n\t\t\t}\n\t\t}\n\n\t} else {\n#ifndef HAVE_390\n\t\tgeom_fn geom_function;\n\t\tif (op == \"union\")\n\t\t\tgeom_function = (geom_fn) GEOSUnion_r;\n\t\telse if (op == \"difference\")\n\t\t\tgeom_function = (geom_fn) GEOSDifference_r;\n\t\telse if (op == \"sym_difference\")\n\t\t\tgeom_function = (geom_fn) GEOSSymDifference_r;\n#else\n\t\tgeom_fnp geom_function;\n\t\tif (op == \"union\")\n\t\t\tgeom_function = (geom_fn) GEOSUnionPrec_r;\n\t\telse if (op == \"difference\")\n\t\t\tgeom_function = (geom_fn) GEOSDifferencePrec_r;\n\t\telse if (op == \"sym_difference\")\n\t\t\tgeom_function = (geom_fn) GEOSSymDifferencePrec_r;\n#endif\n\t\telse\n\t\t\tRcpp::stop(\"invalid operation\"); // #nocov\n\n\t\tfor (size_t i = 0; i < y.size(); i++) {\n\t\t\tfor (size_t j = 0; j < x.size(); j++) {\n#ifndef HAVE_390\n\t\t\t\tGeomPtr geom = geos_ptr(geom_function(hGEOSCtxt, x[j].get(), y[i].get()), hGEOSCtxt);\n#else\n\t\t\t\tGeomPtr geom = geos_ptr(geom_function(hGEOSCtxt, x[j].get(), y[i].get(), grid_size), hGEOSCtxt);\n#endif\n\t\t\t\tif (geom == nullptr)\n\t\t\t\t\tRcpp::stop(\"GEOS exception\"); // #nocov\n\t\t\t\tif (! chk_(GEOSisEmpty_r(hGEOSCtxt, geom.get()))) {\n\t\t\t\t\tindex_x.push_back(j + 1);\n\t\t\t\t\tindex_y.push_back(i + 1);\n\t\t\t\t\tout.push_back(std::move(geom)); // keep\n\t\t\t\t}\n\t\t\t\tRcpp::checkUserInterrupt();\n\t\t\t}\n\t\t}\n\t}\n\n\tRcpp::NumericMatrix m(index_x.size(), 2); // and a set of 1-based indices to x and y\n\tm(_, 0) = Rcpp::NumericVector(index_x.begin(), index_x.end());\n\tm(_, 1) = Rcpp::NumericVector(index_y.begin(), index_y.end());\n\n\tRcpp::List ret;\n\tif ((x.size() == 0 || y.size() == 0) && op != \"intersection\") {\n\t\tif (op == \"union\" || op == \"sym_difference\") { // return \"the other\"\n\t\t\tif (y.size() == 0)\n\t\t\t\tret = sfcx;\n\t\t\telse\n\t\t\t\tret = sfcy;\n\t\t} else // \"difference\" is asymmetric: x - 0 -> return x\n\t\t\tret = sfcx;\n\t} else {\n\t\tret = sfc_from_geometry(hGEOSCtxt, out, dim);\n\t\tret.attr(\"crs\") = sfcx.attr(\"crs\");\n\t\tret.attr(\"idx\") = m;\n\t}\n\treturn ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::NumericVector CPL_geos_dist_by_element(Rcpp::List sfc0, Rcpp::List sfc1,\n                                             std::string which, double par) {\n  \n  GEOSContextScope hGEOSCtxt;\n\n  int dim = 2;\n  std::vector<GeomPtr> gmv0 = geometries_from_sfc(hGEOSCtxt, sfc0, &dim);\n  std::vector<GeomPtr> gmv1 = geometries_from_sfc(hGEOSCtxt, sfc1, &dim);\n\n  if (gmv0.size() != gmv1.size())\n    Rcpp::stop(\"for element-wise distance, x and y must have equal length\");\n\n  size_t n = gmv0.size();\n  Rcpp::NumericVector out(n);\n  \n  if (par <= 0.0) {\n    dist_fn dist_function;\n    if (which == \"Euclidean\")       dist_function = GEOSDistance_r;\n    else if (which == \"Hausdorff\")  dist_function = GEOSHausdorffDistance_r;\n#ifdef HAVE370\n    else if (which == \"Frechet\")    dist_function = GEOSFrechetDistance_r;\n#endif\n    else\n      Rcpp::stop(\"distance function not supported\"); // #nocov\n\n    for (size_t i = 0; i < n; i++) {\n      if (GEOSisEmpty_r(hGEOSCtxt, gmv0[i].get()) ||\n          GEOSisEmpty_r(hGEOSCtxt, gmv1[i].get()))\n        out[i] = NA_REAL;\n      else {\n        double dist = -1.0;\n        if (dist_function(hGEOSCtxt, gmv0[i].get(), gmv1[i].get(), &dist) == 0)\n          Rcpp::stop(\"GEOS error in GEOS_xx_Distance_r\"); // #nocov\n        out[i] = dist;\n      }\n      Rcpp::checkUserInterrupt();\n    }\n  } else {\n    dist_parfn dist_function = NULL;\n    if (which == \"Hausdorff\")       dist_function = GEOSHausdorffDistanceDensify_r;\n#ifdef HAVE370\n    else if (which == \"Frechet\")    dist_function = GEOSFrechetDistanceDensify_r;\n#endif\n    else\n      Rcpp::stop(\"distance function not supported\"); // #nocov\n\n    for (size_t i = 0; i < n; i++) {\n      if (GEOSisEmpty_r(hGEOSCtxt, gmv0[i].get()) ||\n          GEOSisEmpty_r(hGEOSCtxt, gmv1[i].get()))\n        out[i] = NA_REAL;\n      else {\n        double dist = -1.0;\n        if (dist_function(hGEOSCtxt, gmv0[i].get(), gmv1[i].get(), par, &dist) == 0)\n          Rcpp::stop(\"GEOS error in GEOS_xx_Distance_r\"); // #nocov\n \n        out[i] = dist;\n      }\n      Rcpp::checkUserInterrupt();\n    }\n  }\n  return out;\n}\n\n// [[Rcpp::export(rng=false)]]\nstd::string CPL_geos_version(bool runtime = false, bool capi = false) {\n\tif (runtime)\n\t\treturn GEOSversion();\n\telse {\n\t\tif (capi)\n\t\t\treturn GEOS_CAPI_VERSION;\n\t\telse\n\t\t\treturn GEOS_VERSION;\n\t}\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_geos_op2_by_element(std::string op, Rcpp::List sfcx, Rcpp::List sfcy) {\n  \n  using namespace Rcpp;\n  \n  GEOSContextScope hGEOSCtxt;\n\n  int dim = 2;\n\n  std::vector<GeomPtr> x = geometries_from_sfc(hGEOSCtxt, sfcx, &dim);\n  std::vector<GeomPtr> y = geometries_from_sfc(hGEOSCtxt, sfcy, &dim);\n\n  if (x.size() != y.size())\n    Rcpp::stop(\"for element-wise operations, x and y must have equal length\");\n\n  size_t n = x.size();\n  std::vector<GeomPtr> out(n);\n#ifdef HAVE390\n  double grid_size = geos_grid_size_xy(sfcx, sfcy);\n#endif\n  \n#ifndef HAVE390\n  geom_fn geom_function;\n  if (op == \"intersection\")        geom_function = (geom_fn) GEOSIntersection_r;\n  else if (op == \"union\")          geom_function = (geom_fn) GEOSUnion_r;\n  else if (op == \"difference\")     geom_function = (geom_fn) GEOSDifference_r;\n  else if (op == \"sym_difference\") geom_function = (geom_fn) GEOSSymDifference_r;\n#else\n  geom_fnp geom_function;\n  if (op == \"intersection\")        geom_function = (geom_fnp) GEOSIntersectionPrec_r;\n  else if (op == \"union\")          geom_function = (geom_fnp) GEOSUnionPrec_r;\n  else if (op == \"difference\")     geom_function = (geom_fnp) GEOSDifferencePrec_r;\n  else if (op == \"sym_difference\") geom_function = (geom_fnp) GEOSSymDifferencePrec_r;\n#endif\n  else\n    Rcpp::stop(\"invalid operation\"); // #nocov\n  \n  for (size_t i = 0; i < n; i++) {\n    if (GEOSisEmpty_r(hGEOSCtxt, x[i].get()) || GEOSisEmpty_r(hGEOSCtxt, y[i].get())) {\n      out[i] = geos_ptr(GEOSGeom_createEmptyCollection_r(hGEOSCtxt,\n                                                         GEOS_GEOMETRYCOLLECTION), hGEOSCtxt);\n    } else {\n#ifndef HAVE390\n      GeomPtr geom = geos_ptr(geom_function(hGEOSCtxt, x[i].get(), y[i].get()), hGEOSCtxt);\n#else\n      GeomPtr geom = geos_ptr(geom_function(hGEOSCtxt, x[i].get(), y[i].get(), grid_size), hGEOSCtxt);\n#endif\n      if (geom == nullptr)\n        out[i] = geos_ptr(GEOSGeom_createEmptyCollection_r(hGEOSCtxt,\n                                                           GEOS_GEOMETRYCOLLECTION), hGEOSCtxt);\n      else\n        out[i] = std::move(geom);\n    }\n    Rcpp::checkUserInterrupt();\n  }\n  \n  Rcpp::NumericMatrix m(n, 2);\n  for (size_t i = 0; i < n; i++) {\n    m(i, 0) = i + 1;\n    m(i, 1) = i + 1;\n  }\n  \n  Rcpp::List ret = sfc_from_geometry(hGEOSCtxt, out, dim);\n  ret.attr(\"crs\") = sfcx.attr(\"crs\");\n  ret.attr(\"idx\") = m;\n  return ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::NumericMatrix CPL_geos_dist(Rcpp::List sfc0, Rcpp::List sfc1,\n\t\tRcpp::CharacterVector which, double par) {\n\tRcpp::NumericMatrix out = CPL_geos_binop(sfc0, sfc1, Rcpp::as<std::string>(which), par, \"\", false)[0];\n\treturn out;\n}\n\n// requires 3.6.1: https://trac.osgeo.org/geos/browser/git/NEWS?rev=3.6.2\n#ifdef HAVE361\n// helper struct & distance function for STRtree:\ntypedef struct { GEOSGeom g; size_t id; } item_g;\n\nint distance_fn(const void *item1, const void *item2, double *distance, void *userdata) {\n\treturn GEOSDistance_r( (GEOSContextHandle_t) userdata, ((const item_g *)item1)->g, ((const item_g *)item2)->g, distance);\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::IntegerVector CPL_geos_nearest_feature(Rcpp::List sfc0, Rcpp::List sfc1) {\n\t// for every feature in sf0, find the index (1-based) of the nearest feature in sfc1\n\tGEOSContextScope hGEOSCtxt;\n\n\tint dim = 2;\n\tstd::vector<GeomPtr> gmv0 = geometries_from_sfc(hGEOSCtxt, sfc0, &dim);\n\tstd::vector<GeomPtr> gmv1 = geometries_from_sfc(hGEOSCtxt, sfc1, &dim);\n\tTreePtr tree = geos_ptr(GEOSSTRtree_create_r(hGEOSCtxt, 10), hGEOSCtxt);\n\tstd::vector<item_g> items(gmv1.size());\n\tbool tree_is_empty = true;\n\tfor (size_t i = 0; i < gmv1.size(); i++) {\n\t\titems[i].id = i + 1; // 1-based\n\t\titems[i].g = gmv1[i].get();\n\t\tif (!GEOSisEmpty_r(hGEOSCtxt, gmv1[i].get())) {\n\t\t\tGEOSSTRtree_insert_r(hGEOSCtxt, tree.get(), gmv1[i].get(), &(items[i]));\n\t\t\ttree_is_empty = false;\n\t\t}\n\t}\n\tRcpp::IntegerVector out(gmv0.size());\n\tfor (size_t i = 0; i < gmv0.size(); i++) {\n\t\tif (!GEOSisEmpty_r(hGEOSCtxt, gmv0[i].get()) && !tree_is_empty) {\n\t\t\titem_g item;\n\t\t\titem.id = 0; // is irrelevant\n\t\t\titem.g = gmv0[i].get();\n\t\t\tconst item_g *ret_item;\n\t\t\t// now query tree for nearest GEOM at item:\n\t\t\tret_item = (const item_g *) GEOSSTRtree_nearest_generic_r(hGEOSCtxt, tree.get(), &item,\n\t\t\t\t\tgmv0[i].get(), distance_fn, hGEOSCtxt);\n\t\t\tif (ret_item != NULL)\n\t\t\t\tout[i] = ret_item->id; // the index (1-based) of nearest GEOM\n\t\t\telse\n\t\t\t\tRcpp::stop(\"st_nearest_feature: GEOS exception\");\n\t\t} else\n\t\t\tout[i] = NA_INTEGER;\n\t}\n\treturn out;\n}\n#else\nRcpp::IntegerVector CPL_geos_nearest_feature(Rcpp::List sfc0, Rcpp::List sfc1) {\n\tRcpp::stop(\"GEOS version 3.6.1 required for selecting nearest features\");\n}\n#endif // HAVE_361\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_geos_nearest_points(Rcpp::List sfc0, Rcpp::List sfc1, bool pairwise) {\n\tint dim = 2;\n\tGEOSContextScope hGEOSCtxt;\n\tstd::vector<GeomPtr> gmv0 = geometries_from_sfc(hGEOSCtxt, sfc0, &dim);\n\tstd::vector<GeomPtr> gmv1 = geometries_from_sfc(hGEOSCtxt, sfc1, &dim);\n\tRcpp::List out;\n\tif (pairwise) {\n\t\tif (gmv0.size() != gmv1.size())\n\t\t\tRcpp::stop(\"for pairwise nearest points, both arguments need to have the same number of geometries\"); // #nocov\n\t\tstd::vector<GeomPtr> ls(sfc0.size());\n\t\tfor (size_t i = 0; i < gmv0.size(); i++)\n\t\t\tls[i] = geos_ptr(GEOSGeom_createLineString_r(hGEOSCtxt, GEOSNearestPoints_r(hGEOSCtxt, gmv0[i].get(), gmv1[i].get())), hGEOSCtxt); // converts as LINESTRING\n\t\tout = sfc_from_geometry(hGEOSCtxt, ls, dim);\n\t} else {\n\t\tstd::vector<GeomPtr> ls(sfc0.size() * sfc1.size());\n\t\tfor (size_t i = 0; i < gmv0.size(); i++) {\n\t\t\tfor (size_t j = 0; j < gmv1.size(); j++)\n\t\t\t\tls[(i * gmv1.size()) + j] =\n\t\t\t\t\tgeos_ptr(GEOSGeom_createLineString_r(hGEOSCtxt, GEOSNearestPoints_r(hGEOSCtxt, gmv0[i].get(), gmv1[j].get())), hGEOSCtxt); // converts as LINESTRING\n\t\t\tR_CheckUserInterrupt();\n\t\t}\n\t\tout = sfc_from_geometry(hGEOSCtxt, ls, dim);\n\t}\n\n\tout.attr(\"precision\") = sfc0.attr(\"precision\");\n\tout.attr(\"crs\") = sfc0.attr(\"crs\");\n\treturn out;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_transpose_sparse_incidence(Rcpp::List m, int n) {\n// transpose a sparse incidence matrix list m that has n columns\n\tstd::vector<size_t> sizes(n);\n\tfor (int i = 0; i < n; i++)\n\t\tsizes[i] = 0; // init\n\tfor (int i = 0; i < m.size(); i++) {\n\t\tRcpp::IntegerVector v = m[i];\n\t\tfor (int j = 0; j < v.size(); j++) {\n\t\t\tif (v[j] > n || v[j] < 0)\n\t\t\t\tRcpp::stop(\"CPL_transpose_sparse_incidence: index out of bounds\"); // #nocov\n\t\t\tsizes[v[j] - 1] += 1; // count\n\t\t}\n\t}\n\tRcpp::List out(n);\n\tfor (int i = 0; i < n; i++)\n\t\tout[i] = Rcpp::IntegerVector(sizes[i]);\n\tfor (int i = 0; i < m.size(); i++) {\n\t\tRcpp::IntegerVector v = m[i];\n\t\tfor (int j = 0; j < v.size(); j++) {\n\t\t\tsize_t new_i = v[j] - 1;\n\t\t\tRcpp::IntegerVector w = out[new_i];\n\t\t\tw[w.size() - sizes[new_i]] = i + 1; // 1-based\n\t\t\tsizes[new_i] -= 1;\n\t\t}\n\t}\n\treturn out;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_nary_difference(Rcpp::List sfc) {\n\t// initialize objects\n\tint dim = 2;\n\tstd::vector<size_t> index;\n\tGEOSContextScope hGEOSCtxt;\n\tstd::vector<GeomPtr> x = geometries_from_sfc(hGEOSCtxt, sfc, &dim);\n\tstd::vector<GeomPtr> out;\n#ifdef HAVE_390\n\tdouble grid_size = geos_grid_size(sfc);\n#endif\n\t// initialize trees to find overlapping areas quickly\n\tfor (size_t i = 0; i < x.size(); i++) {\n\t\t// if i'th geometry in x is empty then skip it\n\t\tif (! GEOSisEmpty_r(hGEOSCtxt, x[i].get())) {\n\t\t\tbool contained = false;\n\t\t\tTreePtr tree = geos_ptr(GEOSSTRtree_create_r(hGEOSCtxt, 10), hGEOSCtxt);\n\t\t\tGeomPtr geom = std::move(x[i]);\n\t\t\t// if out contains geometries than remove overlaps from geom\n\t\t\tif (out.size() > 0) {\n\t\t\t\t// generate tree for all items in out\n\t\t\t\tstd::vector<size_t> items(out.size());\n\t\t\t\tfor (size_t j = 0; j < out.size(); j++) {\n\t\t\t\t\titems[j] = j;\n\t\t\t\t\tif (! GEOSisEmpty_r(hGEOSCtxt, out[j].get())) {\n\t\t\t\t\t\tGEOSSTRtree_insert_r(hGEOSCtxt, tree.get(), out[j].get(), &(items[j]));\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t// query which geometries in out overlap with geom\n\t\t\t\tstd::vector<size_t> tree_sel;\n\t\t\t\tGEOSSTRtree_query_r(hGEOSCtxt, tree.get(), geom.get(), cb, &tree_sel);\n\t\t\t\t// iterate over items in query and erase overlapping areas in geom\n\t\t\t\tfor (size_t j = 0; j < tree_sel.size(); j++) {\n\t\t\t\t\t// test if the items are fully contained\n\t\t\t\t\tcontained = chk_(GEOSContains_r(hGEOSCtxt, out[tree_sel[j]].get(), geom.get()));\n\t\t\t\t\tif (contained)\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t// test if the items intersect with geom\n\t\t\t\t\tif (chk_(GEOSIntersects_r(hGEOSCtxt, geom.get(), out[tree_sel[j]].get()))) {\n\t\t\t\t\t\t// if they do then erase overlapping parts from geom\n#ifndef HAVE_390\n\t\t\t\t\t\tgeom = geos_ptr(GEOSDifference_r(hGEOSCtxt, geom.get(), out[tree_sel[j]].get()), hGEOSCtxt);\n#else\n\t\t\t\t\t\tgeom = geos_ptr(GEOSDifferencePrec_r(hGEOSCtxt, geom.get(), out[tree_sel[j]].get(), grid_size), hGEOSCtxt);\n#endif\n\t\t\t\t\t\tif (geom == nullptr)\n\t\t\t\t\t\t\tRcpp::stop(\"GEOS exception\"); // #nocov\n\t\t\t\t\t\t// ensure that geom is valid\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\t// add geom to out if not empty\n\t\t\tif (!contained) {\n\t\t\t\tindex.push_back(i + 1);\n\t\t\t\tout.push_back(std::move(geom)); // keep\n\t\t\t}\n\t\t\t// check for user interrupt\n\t\t\tRcpp::checkUserInterrupt();\n\t\t}\n\t}\n\t// prepare output\n\tRcpp::List ret(sfc_from_geometry(hGEOSCtxt, out, dim)); // destroys out\n\tret.attr(\"crs\") = sfc.attr(\"crs\");\n\tRcpp::IntegerVector out_index = Rcpp::IntegerVector(index.begin(), index.end());\n\tret.attr(\"idx\") = out_index;\n\treturn ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_nary_intersection(Rcpp::List sfc) {\n\tGEOSContextScope hGEOSCtxt;\n\t// initialize objects\n\tint dim = 2;\n\tstd::vector< std::vector<size_t> > index;\n\tstd::vector<GeomPtr> x = geometries_from_sfc(hGEOSCtxt, sfc, &dim);\n\tstd::vector<GeomPtr> out;\n\tint errors = 0;\n#ifdef HAVE_390\n\tdouble grid_size = geos_grid_size(sfc);\n#endif\n#ifdef HAVE350\n\tnotice = 0;\n\tGEOSContext_setNoticeMessageHandler_r(hGEOSCtxt,\n\t\t(GEOSMessageHandler_r) __emptyNoticeHandler, (void *) &notice);\n\tGEOSContext_setErrorMessageHandler_r(hGEOSCtxt,\n\t\t(GEOSMessageHandler_r) __countErrorHandler, (void *) &notice);\n#endif\n\t// initialize trees to find overlapping areas quickly\n\tfor (size_t i = 0; i < x.size(); i++) {\n\t\t// if i'th geometry in x is empty then skip it\n\t\tif (! GEOSisEmpty_r(hGEOSCtxt, x[i].get())) {\n\t\t\tTreePtr tree = geos_ptr(GEOSSTRtree_create_r(hGEOSCtxt, 10), hGEOSCtxt);\n\t\t\tGeomPtr geom = std::move(x[i]);\n\t\t\t// if out contains geometries than remove overlaps from geom\n\t\t\tif (out.size() > 0) {\n\t\t\t\t// generate tree for all items in out\n\t\t\t\tstd::vector<size_t> items(out.size());\n\t\t\t\tfor (size_t j = 0; j < out.size(); j++) {\n\t\t\t\t\titems[j] = j;\n\t\t\t\t\tif (! GEOSisEmpty_r(hGEOSCtxt, out[j].get()))\n\t\t\t\t\t\tGEOSSTRtree_insert_r(hGEOSCtxt, tree.get(), out[j].get(), &(items[j]));\n\t\t\t\t}\n\t\t\t\t// query which geometries in out overlap with geom\n\t\t\t\tstd::vector<size_t> tree_sel;\n\t\t\t\tGEOSSTRtree_query_r(hGEOSCtxt, tree.get(), geom.get(), cb, &tree_sel);\n\t\t\t\t// iterate over items in query and erase overlapping areas in geom\n\t\t\t\tfor (size_t j = 0; j < tree_sel.size(); j++) {\n\t\t\t\t\tsize_t k = tree_sel[j];\n#ifndef HAVE_390\n\t\t\t\t\tGeomPtr inters = geos_ptr(GEOSIntersection_r(hGEOSCtxt, out[k].get(), geom.get()), hGEOSCtxt);\n#else\n\t\t\t\t\tGeomPtr inters = geos_ptr(GEOSIntersectionPrec_r(hGEOSCtxt, out[k].get(), geom.get(), grid_size), hGEOSCtxt);\n#endif\n\t\t\t\t\tif (geom.get() != nullptr) {\n\t\t\t\t\t\tif (inters == nullptr)\n\t\t\t\t\t\t\terrors++;\n\t\t\t\t\t\telse if (!chk_(GEOSisEmpty_r(hGEOSCtxt, inters.get()))) { // i and k intersection\n\t\t\t\t\t\t\t// cut out inters from geom:\n\t\t\t\t\t\t\tgeom = geos_ptr(GEOSDifference_r(hGEOSCtxt, geom.get(), inters.get()), hGEOSCtxt); \n\t\t\t\t\t\t\tif (geom == nullptr)\n\t\t\t\t\t\t\t\tRcpp::stop(\"GEOS exception\"); // #nocov\n\t\t\t\t\t\t\t// cut out inters from out[k]:\n#ifndef HAVE_390\n\t\t\t\t\t\t\tGeomPtr g = geos_ptr(GEOSDifference_r(hGEOSCtxt, out[k].get(), inters.get()), hGEOSCtxt); \n#else\n\t\t\t\t\t\t\tGeomPtr g = geos_ptr(GEOSDifferencePrec_r(hGEOSCtxt, out[k].get(), inters.get(), grid_size), hGEOSCtxt); \n#endif\n\t\t\t\t\t\t\tif (g == nullptr)\n\t\t\t\t\t\t\t\tRcpp::warning(\"GEOS difference returns NULL\"); // #nocov\n\t\t\t\t\t\t\telse {\n\t\t\t\t\t\t\t\tout[k] = std::move(g);\n\t\t\t\t\t\t\t\tout.push_back(std::move(inters)); // keep\n\t\t\t\t\t\t\t\tstd::vector<size_t> idx = index[k]; // k < i, and k might already be an intersection\n\t\t\t\t\t\t\t\tidx.push_back(i + 1);\n\t\t\t\t\t\t\t\tindex.push_back(idx);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else\n\t\t\t\t\t\terrors++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (geom != nullptr && ! chk_(GEOSisEmpty_r(hGEOSCtxt, geom.get()))) {\n\t\t\t\tout.push_back(std::move(geom));\n\t\t\t\tstd::vector<size_t> idx;\n\t\t\t\tidx.push_back(i + 1);\n\t\t\t\tindex.push_back(idx);\n\t\t\t}\n\t\t\t// check for user interrupt\n\t\t\tRcpp::checkUserInterrupt();\n\t\t}\n\t} // for i\n\tif (errors > 0)\n\t\tRcpp::Rcout << \"geometry errors: \" << errors << std::endl;\n#ifdef HAVE350\n\tif (notice > 0)\n\t\tRcpp::warning(\"one or more notices ignored\");\n\tnotice = 0;\n\tGEOSContext_setNoticeHandler_r(hGEOSCtxt, __warningHandler);\n\tGEOSContext_setErrorHandler_r(hGEOSCtxt, __errorHandler);\n#endif\n\tsize_t j = 0;\n\tfor (size_t i = 0; i < out.size(); i++) {\n\t\tif (! GEOSisEmpty_r(hGEOSCtxt, out[i].get())) {\n\t\t\tif (i != j) {\n\t\t\t\tout[j] = std::move(out[i]);\n\t\t\t\tindex[j] = index[i];\n\t\t\t}\n\t\t\tstd::sort(index[j].begin(), index[j].end());\n\t\t\tj++;\n\t\t}\n\t}\n\tout.resize(j);\n\tindex.resize(j);\n\t// prepare output\n\tRcpp::List ret(sfc_from_geometry(hGEOSCtxt, out, dim));\n\tret.attr(\"crs\") = sfc.attr(\"crs\");\n\tRcpp::List index_list(index.size());\n\tfor (size_t i = 0; i < index.size(); i++) {\n\t\tRcpp::IntegerVector out_index = Rcpp::IntegerVector(index[i].begin(), index[i].end());\n\t\tindex_list[i] = out_index;\n\t}\n\tret.attr(\"idx\") = index_list;\n\treturn ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::NumericVector CPL_line_project(Rcpp::List lines, Rcpp::List points, bool normalized) {\n\tGEOSContextScope hGEOSCtxt;\n\tint dim = 2;\n\tstd::vector<GeomPtr> l = geometries_from_sfc(hGEOSCtxt, lines, &dim);\n\tstd::vector<GeomPtr> p = geometries_from_sfc(hGEOSCtxt, points, &dim);\n\tRcpp::NumericVector ret(p.size());\n\tif (normalized) {\n\t\tfor (size_t i = 0; i < l.size() && i < p.size(); i++)\n\t\t\tret[i] = GEOSProjectNormalized_r(hGEOSCtxt, l[i].get(), p[i].get());\n\t} else {\n\t\tfor (size_t i = 0; i < l.size() && i < p.size(); i++)\n\t\t\tret[i] = GEOSProject_r(hGEOSCtxt, l[i].get(), p[i].get());\n\t}\n\treturn ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_line_interpolate(Rcpp::List lines, Rcpp::NumericVector dists, bool normalized) {\n\tGEOSContextScope hGEOSCtxt;\n\tint dim = 2;\n\tstd::vector<GeomPtr> l = geometries_from_sfc(hGEOSCtxt, lines, &dim);\n\tstd::vector<GeomPtr> p(l.size());\n\tif (normalized) {\n\t\tfor (int i = 0; i < (int) l.size() && i < dists.size(); i++)\n\t\t\tp[i] = geos_ptr(GEOSInterpolateNormalized_r(hGEOSCtxt, l[i].get(), dists[i]), hGEOSCtxt);\n\t} else {\n\t\tfor (int i = 0; i < (int) l.size() && i < dists.size(); i++)\n\t\t\tp[i] = geos_ptr(GEOSInterpolate_r(hGEOSCtxt, l[i].get(), dists[i]), hGEOSCtxt);\n\t}\n\tRcpp::List ret(sfc_from_geometry(hGEOSCtxt, p, dim));\n\treturn ret;\n}\n"
  },
  {
    "path": "src/hex.cpp",
    "content": "#include <Rcpp.h>\n\ninline unsigned char char2int(char c) {\n\tif (c >= '0' && c <= '9')\n\t\treturn c - '0';\n\tif (c >= 'a' && c <= 'f')\n\t\treturn c - 'a' + 10;\n\tif (c >= 'A' && c <= 'F')\n\t\treturn c - 'A' + 10;\n\tRcpp::stop(\"char2int: unrecognized character in hex string\");\n\treturn '0'; // never reached, satisfy -Wreturn-type #nocov\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_hex_to_raw(Rcpp::CharacterVector cx) {\n// convert hexadecimal string into a raw vector:\n\tRcpp::List output(cx.size());\n\tfor (int j = 0; j < cx.size(); j++) {\n\t\tRcpp::RawVector raw(cx[j].size() / 2);\n\t\tconst char *cp = cx[j];\n\t\tfor (int i = 0; i < raw.size(); i++) {\n\t\t\traw[i] = (char2int(cp[0]) << 4) + char2int(cp[1]);\n\t\t\tcp += 2;\n\t\t\tif (i % 131072 == 0) // 2^17, see https://www.jottr.org/2015/06/05/checkuserinterrupt/\n\t\t\t\tRcpp::checkUserInterrupt();\n\t\t}\n\t\toutput[j] = raw;\n\t\tif (j % 1024 == 0)\n\t\t\tRcpp::checkUserInterrupt();\n\t}\n\treturn output;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::CharacterVector CPL_raw_to_hex(Rcpp::RawVector raw) {\n// convert a raw vector into hexadecimal string:\n\tstd::vector<char> str(raw.size() * 2 + 1);\n\tchar hex[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',\n\t\t'a', 'b', 'c', 'd', 'e', 'f' };\n\tunsigned char *cp = &(raw[0]);\n\tint j = 0;\n\tfor (int i = 0; i < raw.size(); i++) {\n\t\tstr[j] = hex[(((int) cp[i]) / 16)];\n\t\tj++;\n\t\tstr[j] = hex[(((int) cp[i]) % 16)];\n\t\tj++;\n\t}\n\tstr[j] = '\\0';\n\treturn Rcpp::CharacterVector::create(str.data());\n}\n"
  },
  {
    "path": "src/hex.h",
    "content": "#ifndef SF_HEX_H_\n#define SF_HEX_H_\nRcpp::List CPL_hex_to_raw(Rcpp::CharacterVector cx);\nRcpp::CharacterVector CPL_raw_to_hex(Rcpp::RawVector raw);\n#endif // SF_HEX_H_\n"
  },
  {
    "path": "src/mdim.cpp",
    "content": "// https://github.com/rouault/gdal/blob/rfc75/gdal/doc/source/tutorials/multidimensional_api_tut.rst\n#include \"gdal_priv.h\"\n\n#include <Rcpp.h>\n\n#define NO_GDAL_CPP_HEADERS\n#include \"gdal.h\"\n#include \"gdal_sf_pkg.h\"\n\nusing namespace Rcpp;\n\n#if defined(__MINGW32__) && !defined(__MINGW64__)\n#define WIN32BIT\n#endif\n\n#if GDAL_VERSION_NUM >= 3040000 && !(defined(WIN32BIT))\nCharacterVector get_attributes(std::vector<std::shared_ptr<GDALAttribute>> a) {\n\tCharacterVector l(a.size());\n\tCharacterVector na(a.size());\n\tfor (size_t i = 0; i < a.size(); i++) {\n\t\tl[i] = a[i]->ReadAsString();\n\t\tna[i] = a[i]->GetName();\n\t}\n\tif (a.size())\n\t\tl.attr(\"names\") = na;\n\treturn l;\n}\n#endif\n\n#if GDAL_VERSION_NUM >= 3010000 && !(defined(WIN32BIT))\nList get_dimension_values(std::shared_ptr<GDALMDArray> array) {\n\tList ret(1);\n\tif (array == nullptr) {\n\t\twarning(\"array is NULL\");\n\t\treturn ret; // FIXME but this is an error essentially.\n\t}\n\tsize_t nValues = 1;\n\tstd::vector<size_t> anCount;\n\tIntegerVector dims;\n\tstd::vector<GUInt64> offset;\n\tCharacterVector d_names;\n\tfor (const auto &poDim: array->GetDimensions()) {\n\t\tanCount.push_back(static_cast<size_t>(poDim->GetSize()));\n\t\tdims.push_back(static_cast<size_t>(poDim->GetSize()));\n\t\td_names.push_back(poDim->GetName());\n\t\toffset.push_back(0);\n\t\tnValues *= anCount.back();\n\t}\n#if GDAL_VERSION_NUM >= 3040000 && !(defined(WIN32BIT))\n\tCharacterVector att = get_attributes(array->GetAttributes());\n#else\n\tCharacterVector att;\n#endif\n\tif (array->GetDataType().GetClass() == GEDTC_NUMERIC) {\n\t\tNumericVector vec( nValues );\n\t\tbool ok = array->Read(offset.data(),\n\t\t\t\t\tanCount.data(),\n\t\t\t\t\tnullptr, /* step: defaults to 1,1,1 */\n\t\t\t\t\tnullptr, /* stride: default to row-major convention */\n\t\t\t\t\tGDALExtendedDataType::Create(GDT_Float64),\n\t\t\t\t\tvec.begin());\n\t\tif (!ok)\n\t\t\tRcout << \"cannot convert values for array \" << array->GetName() << std::endl;\n\t\tvec.attr(\"dim\") = dims;\n\t\tvec.attr(\"units\") = array->GetUnit();\n\t\tvec.attr(\"d_names\") = d_names;\n\t\tif (att.size())\n\t\t\tvec.attr(\"attributes\") = att;\n\t\tret[0] = vec;\n\t} else {\n\t\t// CharacterVector vec(nValues);\n\t\tstd::vector<char *> vec(nValues);\n\t\tbool ok = array->Read(offset.data(),\n\t\t\t\t\tanCount.data(),\n\t\t\t\t\tnullptr, /* step: defaults to 1,1,1 */\n\t\t\t\t\tnullptr, /* stride: default to row-major convention */\n\t\t\t\t\tGDALExtendedDataType::CreateString(100),\n\t\t\t\t\tvec.data());\n\t\tif (!ok)\n\t\t\tRcout << \"cannot convert values for array \" << array->GetName() << std::endl;\n\t\tCharacterVector cv(nValues);\n\t\tfor (size_t i = 0; i < nValues; i++)\n\t\t\tcv[i] = vec[i];\n\t\tif (att.size())\n\t\t\tcv.attr(\"attributes\") = att;\n\t\tret[0] = cv;\n\t}\n\treturn ret;\n}\n\nList get_dimension(const std::shared_ptr<GDALDimension> dim) {\n\tif (dim == nullptr)\n\t\tstop(\"dim is NULL\");\n\tList dv;\n\tif (dim->GetIndexingVariable() == nullptr) {\n\t\tNumericVector nv(dim->GetSize());\n\t\tfor (size_t i = 0; i < dim->GetSize(); i++)\n\t\t\tnv[i] = i + 1.0;\n\t\tdv = List::create(nv);\n\t} else\n\t\tdv = get_dimension_values(dim->GetIndexingVariable());\n\tList dimension = List::create(\n\t\t_[\"from\"] = IntegerVector::create(1),\n\t\t_[\"to\"] = IntegerVector::create(dim->GetSize()),\n\t\t_[\"values\"] = dv,\n\t\t_[\"type\"] = CharacterVector::create(dim->GetType()),\n\t\t_[\"direction\"] = CharacterVector::create(dim->GetDirection())\n\t\t);\n\treturn dimension;\n}\n\n// if present, return geometry elements (coordinates, indexes), else return empty list\nList get_geometry(std::shared_ptr<GDALGroup> curGroup) {\n\tList lst;\n\tfor (const auto &an: curGroup->GetMDArrayNames()) {\n\t\tauto a(curGroup->OpenMDArray(an));\n\t\tif (a == nullptr) {\n\t\t\tRcout << \"could not open geometry array \" << an << std::endl;\n\t\t\tstop(\"get_geometry(): cannot OpenMDArray()\");\n\t\t}\n\t\tauto geom = a->GetAttribute(\"geometry\");\n\t\tif (geom) {\n\t\t\ta = curGroup->OpenMDArray(geom->ReadAsString());\n\t\t\tif (a == nullptr) {\n\t\t\t\tRcout << \"could not open geometry array \" << geom->ReadAsString() << std::endl;\n\t\t\t\tstop(\"geometry array missing\");\n\t\t\t}\n\t\t\tauto nc = a->GetAttribute(\"node_coordinates\");\n\t\t\tif (nc && nc->GetDataType().GetClass() == GEDTC_STRING && nc->GetDimensionCount() == 0) {\n\t\t\t\tconst char *ncs = nc->ReadAsString();\n\t\t\t\tif (ncs) {\n\t\t\t\t\tconst CPLStringList nc_names(CSLTokenizeString2(ncs, \" \", 0)); // x and y coordinate array\n\t\t\t\t\tauto gt = a->GetAttribute(\"geometry_type\");\n\t\t\t\t\tif (gt == nullptr || gt->GetDataType().GetClass() != GEDTC_STRING)\n\t\t\t\t\t\tstop(\"cannot get geometry_type attribute\");\n\t\t\t\t\tauto nco = a->GetAttribute(\"node_count\");\n\t\t\t\t\tauto pnco = a->GetAttribute(\"part_node_count\");\n\t\t\t\t\tauto ir = a->GetAttribute(\"interior_ring\");\n\t\t\t\t\tlst = List::create(\n\t\t\t\t\t\t_[\"geometry_type\"] = CharacterVector::create(gt->ReadAsString()),\n\t\t\t\t\t\t_[\"x\"] = get_dimension_values(curGroup->OpenMDArray(nc_names[0])),\n\t\t\t\t\t\t_[\"y\"] = get_dimension_values(curGroup->OpenMDArray(nc_names[1])),\n\t\t\t\t\t\t_[\"node_count\"] = nco ? get_dimension_values(curGroup->OpenMDArray(nco->ReadAsString())) : List::create(),\n\t\t\t\t\t\t_[\"part_node_count\"] = pnco ? get_dimension_values(curGroup->OpenMDArray(pnco->ReadAsString())) : List::create(),\n\t\t\t\t\t\t_[\"interior_ring\"] = ir ?  get_dimension_values(curGroup->OpenMDArray(ir->ReadAsString())): List::create() \n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} \n\t\t}\n\t}\n\treturn(lst);\n}\n\nList get_all_arrays(std::shared_ptr<GDALGroup> curGroup, List ret, std::string name) {\n\tauto array_names(curGroup->GetMDArrayNames());\n\t// for (size_t i = 0 i < array_names\n\tCharacterVector a(array_names.size());\n\t// ret needs to be a _named_ list, so that na is never null\n\tCharacterVector na = ret.attr(\"names\");\n\tif (a.size() > 0) { // group with array(s):\n\t\tfor (int i = 0; i < a.size(); i++)\n\t\t\ta[i] = array_names[i];\n\t\tret.push_back(a);\n\t\tCharacterVector gn;\n\t\t// gn.push_back(\"\");\n\t\tstd::string group_name;\n\t\tif (name == \"/\")\n\t\t\tgroup_name = name;\n\t\telse\n\t\t\tgroup_name = name + \"/\";\n\t\tna.push_back(group_name);\n\t}\n\tret.attr(\"names\") = na;\n\tauto gn(curGroup->GetGroupNames());\n\tfor (const auto &gn: curGroup->GetGroupNames()) { // iterate over groups:\n\t\tstd::string slash;\n\t\tif (name == \"/\")\n\t\t\tslash = \"\";\n\t\telse\n\t\t\tslash = \"/\";\n\t\tret = get_all_arrays(curGroup->OpenGroup(gn), ret, name + slash + gn);\n\t}\n\treturn ret;\n}\n\nstd::shared_ptr<GDALMDArray> get_array(std::shared_ptr<GDALGroup> grp, const std::string &osName) {\n\tCPLStringList aosTokens(CSLTokenizeString2(osName.c_str(), \"/\", 0));\n\tfor (int i = 0; i < aosTokens.size() - 1; i++) {\n\t\tauto curGroupNew = grp->OpenGroup(aosTokens[i]);\n\t\tif (!curGroupNew) {\n\t\t\tRcout << \"Cannot find group \" << aosTokens[i] << std::endl;\n\t\t\tstop(\"group not found\");\n\t\t}\n\t\tgrp = curGroupNew;\n\t}\n\tconst char *pszArrayName = aosTokens[aosTokens.size() - 1];\n\tauto array(grp->OpenMDArray(pszArrayName));\n\tif (!array) {\n\t\tRcout << \"Cannot open array \" << pszArrayName << std::endl;\n\t\tstop(\"array not found\");\n\t}\n\treturn array;\n}\n\n// [[Rcpp::export(rng=false)]]\nList CPL_read_mdim(CharacterVector file, CharacterVector array_names, CharacterVector oo, \n\t\t\t\tIntegerVector offset, IntegerVector count, IntegerVector step, \n\t\t\t\tbool proxy = false, bool debug = false) {\n\n\tstd::vector <char *> oo_char = create_options(oo, true); // open options\n\tauto poDataset = std::unique_ptr<GDALDataset>(\n\t\tGDALDataset::Open((const char *) file[0], GDAL_OF_MULTIDIM_RASTER | GDAL_OF_VERBOSE_ERROR,\n\t\t\tnullptr, oo_char.data(), nullptr));\n\tif( !poDataset )\n\t\tstop(\"file not found\");\n\n\tauto poRootGroup = poDataset->GetRootGroup();\n\tif( !poRootGroup )\n\t\tstop(\"cannot open root group\");\n\n\tif (array_names.size() == 1 && array_names[0] == \"?\") {\n\t\tList l;\n\t\tl.attr(\"names\") = CharacterVector::create();\n\t\treturn get_all_arrays(poRootGroup, l, poRootGroup->GetName());\n\t}\n\n\tauto curGroup = poRootGroup;\n\t// find possible vector geometry array, and construct\n\tList geometry = get_geometry(curGroup);\n\n\t// Rcout << \"name: \" << curGroup->GetName() << \" full_name: \" << curGroup->GetFullName() << std::endl;\n\tif (array_names.size() == 0) { // find the one(s) with the most dimensions:\n\t\tint ndim = 0;\n\t\tint largest_size = 0;\n\t\tfor (const auto &an: curGroup->GetMDArrayNames()) { // find largest size:\n\t\t\tauto a(curGroup->OpenMDArray(an));\n\t\t\tndim = a->GetDimensions().size();\n\t\t\tif (ndim > largest_size)\n\t\t\t\tlargest_size = ndim;\n\t\t}\n\t\tfor (const auto &an: curGroup->GetMDArrayNames()) { // identify target arrays:\n\t\t\tauto a(curGroup->OpenMDArray(an));\n\t\t\tndim = a->GetDimensions().size();\n\t\t\tif (ndim == largest_size)\n\t\t\t\tarray_names.push_back(an);\n\t\t}\n\t\tif (array_names.size() == 0)\n\t\t\tstop(\"no array names found\");\n\t}\n\tint n = array_names.size();\n\n\tconst char *name = array_names[0];\n\tstd::shared_ptr<GDALMDArray> array;\n\tarray = get_array(curGroup, name);\n\tif (!array)\n\t\tstop(\"Cannot find array\");\n\tif (offset.size() != 0 && (size_t) offset.size() != array->GetDimensionCount())\n\t\tstop(\"offset has wrong size\");\n\tif (count.size() != 0 && (size_t) count.size() != array->GetDimensionCount())\n\t\tstop(\"count has wrong size\");\n\tif (step.size() != 0 && (size_t) step.size() != array->GetDimensionCount())\n\t\tstop(\"step has wrong size\");\n\tif (proxy && (offset.size() != 0 || count.size() != 0 || step.size() != 0))\n\t\tstop(\"if proxy=TRUE, do not set offset, count or step, use these when reading data (downsample)\");\n\n\tsize_t nValues = 1;\n\tstd::vector<size_t> anCount;\n\tstd::vector<GInt64> stp;\n\tIntegerVector dims;\n\tCharacterVector dim_names;\n\tstd::vector<GUInt64> offst;\n\tList dimensions;\n\tint i = 0;\n\tfor (const auto &poDim: array->GetDimensions()) {\n\t\tdim_names.push_back(poDim->GetName());\n\t\tif (offset.size() == 0)\n\t\t\toffst.push_back(0);\n\t\telse\n\t\t\toffst.push_back(offset[i]);\n\t\tif (step.size() == 0)\n\t\t\tstp.push_back(1);\n\t\telse\n\t\t\tstp.push_back(step[i]);\n\t\tif (count.size() == 0 || count[i] == NA_INTEGER || count[i] <= 0)\n\t\t\tanCount.push_back((poDim->GetSize() - offst.back())/stp.back());\n\t\telse\n\t\t\tanCount.push_back(count[i]);\n\t\tdims.push_back(anCount.back());\n\t\tnValues *= anCount.back();\n\t\tif (debug) {\n\t\t\tRcout << \"Dimension name: \" << poDim->GetName() << \"\\n\";\n\t\t\tif (count.size() > i)\n\t\t\t\tRcout << \"count[i]: \" << count[i] << \"\\n\";\n\t\t\tRcout << \"nValues: \" << nValues << \"\\n\";\n\t\t\tRcout << \"stp[i]: \" << stp[i] << \"\\n\";\n\t\t\tRcout << \"anCount[i]: \" << anCount[i] << \"\\n\";\n\t\t\tRcout << \"offst[i]: \" << offst[i] << \"\\n\";\n\t\t\tRcout << \"dims[i]: \" << dims[i] << \"\\n\";\n\t\t}\n\t\tList dimension(get_dimension(poDim));\n\t\tdimensions.push_back(dimension); // mind the \"s\"\n\t\ti++;\n\t}\n\tList vec_lst(n);\n\tCharacterVector a_names(n);\n\tfor (int i = 0; i < n; i++) {\n\t\tname = array_names[i];\n\t\ta_names[i] = array_names[i];\n\t\tauto arr(get_array(curGroup, name));\n\t\tdims.attr(\"names\") = dim_names;\n\t\tdimensions.attr(\"names\") = dim_names;\n\t\tif (! proxy) { // read the arrays:\n\t\t\tauto data_type(arr->GetDataType());\n\t\t\tsize_t sz = data_type.GetSize();\n\t\t\tif (data_type.GetClass() == GEDTC_NUMERIC) {\n\t\t\t\tNumericVector vec(nValues);\n\t\t\t\tif (debug)\n\t\t\t\t\tRcout << \"size of vec: \" << vec.size() << \"\\n\";\n\t\t\t\tbool ok = arr->Read(offst.data(),\n\t\t\t\t\t\t\tanCount.data(),\n\t\t\t\t\t\t\tstp.data(), /* step: defaults to 1,1,1 */\n\t\t\t\t\t\t\tnullptr, /* stride: default to row-major convention */\n\t\t\t\t\t\t\tGDALExtendedDataType::Create(GDT_Float64),\n\t\t\t\t\t\t\tvec.begin());\n\t\t\t\tif (!ok)\n\t\t\t\t\tstop(\"Cannot read array into a Float64 buffer\");\n\t\t\t\tbool has_offset = false;\n\t\t\t\tdouble offst = arr->GetOffset(&has_offset);\n\t\t\t\tif (!has_offset)\n\t\t\t\t\toffst = 0.0;\n\t\t\t\tbool has_scale = false;\n\t\t\t\tdouble scale = arr->GetScale(&has_scale);\n\t\t\t\tif (!has_scale)\n\t\t\t\t\tscale = 1.0;\n\t\t\t\tbool has_nodata = false;\n\t\t\t\tdouble nodata_value = arr->GetNoDataValueAsDouble(&has_nodata);\n\t\t\t\tif (has_offset || has_scale || has_nodata) {\n\t\t\t\t\tfor (size_t j = 0; j < nValues; j++) {\n\t\t\t\t\t\tif (ISNAN(vec[j]) || (has_nodata && vec[j] == nodata_value))\n\t\t\t\t\t\t\tvec[j] = NA_REAL;\n\t\t\t\t\t\telse\n\t\t\t\t\t\t\tvec[j] = vec[j] * scale + offst;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tvec.attr(\"dim\") = dims;\n\t\t\t\tvec.attr(\"units\") = arr->GetUnit();\n\t\t\t\tvec_lst[i] = vec;\n\t\t\t} else if (data_type.GetClass() == GEDTC_COMPOUND) {\n\t\t\t\tconst auto &components = data_type.GetComponents();\n\t\t\t\tstd::vector<GByte> buf(sz * nValues);\n\t\t\t\tbool ok = arr->Read(offst.data(),\n\t\t\t\t\t\t\tanCount.data(),\n\t\t\t\t\t\t\tstp.data(), /* step: defaults to 1,1,1 */\n\t\t\t\t\t\t\tnullptr, /* stride: default to row-major convention */\n\t\t\t\t\t\t\tdata_type,\n\t\t\t\t\t\t\t&buf[0]);\n\t\t\t\tif (!ok)\n\t\t\t\t\tstop(\"Cannot read array into Compound buffer\");\n\t\t\t\tDataFrame tbl;\n\t\t\t\tGByte *v = buf.data();\n\t\t\t\tfor (const auto &co: components) { \n\t\t\t\t\tauto t(co->GetType());\n\t\t\t\t\tif (t.GetClass() == GEDTC_NUMERIC) {\n\t\t\t\t\t\tif (t.GetNumericDataType() != GDT_Float64)\n\t\t\t\t\t\t\tstop(\"only Float64 data supported in numeric compounds\");\n\t\t\t\t\t\tNumericVector vec(nValues);\n\t\t\t\t\t\tfor (size_t j = 0; j < nValues; j++)\n\t\t\t\t\t\t\tmemcpy(&(vec[j]), v + j * sz + co->GetOffset(), sizeof(double));\n\t\t\t\t\t\ttbl.push_back(vec, co->GetName());\n\t\t\t\t\t} else if (t.GetClass() == GEDTC_STRING) {\n\t\t\t\t\t\tCharacterVector vec(nValues);\n\t\t\t\t\t\tconst char *str;\n\t\t\t\t\t\tfor (size_t j = 0; j < nValues; j++) {\n\t\t\t\t\t\t\tmemcpy(&str, v + j * sz + co->GetOffset(), sizeof(const char *));\n\t\t\t\t\t\t\tvec[j] = str; // deep copy\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttbl.push_back(vec, co->GetName());\n\t\t\t\t\t} else \n\t\t\t\t\t\tstop(\"unsupported type\");\n\t\t\t\t}\n\t\t\t\tvec_lst[i] = tbl;\n\t\t\t} else { // GEDTC_STRING:\n\t\t\t\tstd::vector<GByte> buf(sz * nValues);\n\t\t\t\tbool ok = arr->Read(offst.data(),\n\t\t\t\t\t\t\tanCount.data(),\n\t\t\t\t\t\t\tstp.data(), /* step: defaults to 1,1,1 */\n\t\t\t\t\t\t\tnullptr, /* stride: default to row-major convention */\n\t\t\t\t\t\t\tdata_type,\n\t\t\t\t\t\t\t&buf[0]);\n\t\t\t\tif (!ok)\n\t\t\t\t\tstop(\"Cannot read array into string buffer\");\n\t\t\t\tGByte *v = buf.data();\n\t\t\t\tCharacterVector vec(nValues);\n\t\t\t\tconst char *str;\n\t\t\t\tfor (size_t j = 0; j < nValues; j++) {\n\t\t\t\t\tmemcpy(&str, v + j * sz, sizeof(const char *));\n\t\t\t\t\tvec[j] = str; // deep copy\n\t\t\t\t}\n\t\t\t\tvec.attr(\"dim\") = dims;\n\t\t\t\tvec.attr(\"units\") = arr->GetUnit();\n\t\t\t\tvec_lst[i] = vec;\n\t\t\t}\n\t\t}\n\t}\n\tvec_lst.attr(\"names\") = a_names;\n\tstd::shared_ptr<OGRSpatialReference> srs = array->GetSpatialRef();\n\tList ret = List::create(\n\t\t_[\"array_list\"] = vec_lst,\n\t\t_[\"dimensions\"] = dimensions,\n\t\t_[\"srs\"] = srs == nullptr ? CharacterVector::create(NA_STRING) : wkt_from_spatial_reference(srs.get()),\n\t\t_[\"geometry\"] = geometry\n\t);\n\treturn ret;\n}\n\n/// WRITE:\nvoid write_attributes(std::shared_ptr<GDALMDArray> md, CharacterVector attrs) {\n\tif (attrs.size() > 0) {\n\t\tCharacterVector names = attrs.attr(\"names\");\n\t\tstd::vector<GUInt64> empty;\n\t\tfor (int i = 0; i < attrs.size(); i++) {\n\t\t\tconst char *name = names[i];\n\t\t\tstd::shared_ptr<GDALAttribute> at = \n\t\t\t\t\tmd->CreateAttribute(name, empty,  GDALExtendedDataType::CreateString(0), nullptr);\n\t\t\tif (at == nullptr) {\n\t\t\t\tRcout << names[i] << \":\" << std::endl;\n\t\t\t\twarning(\"could not create attribute: does it already exist? (skipping)\");\n\t\t\t} else\n\t\t\t\tat->Write(attrs[i]);\n\t\t}\n\t}\n}\n\n// [[Rcpp::export(rng=false)]]\nList CPL_write_mdim(CharacterVector name, CharacterVector driver, IntegerVector dimensions,\n\t\t\t\tList variables, CharacterVector wkt, CharacterVector xy, CharacterVector RootGroupOptions,\n\t\t\t\tCharacterVector CreationOptions, bool as_float = true) {\n\t\n\tif (name.size() != 1)\n\t\tstop(\"name should have length 1\");\n\tif (driver.size() != 1)\n\t\tstop(\"driver should have length 1\");\n\tGDALDriver *nc = GetGDALDriverManager()->GetDriverByName(driver[0]);\n\tif (nc == NULL)\n\t\tstop(\"cannot open driver\");\n\tOGRSpatialReference *dest = NULL;\n\tif (wkt.size()) {\n\t\tchar *cp = wkt[0];\n\t\tdest = new OGRSpatialReference;\n\t\tdest->importFromWkt((const char *) cp);\n\t}\n\n\t// create n-D array\n\tstd::vector <char *> rgo = create_options(RootGroupOptions, true);\n\tstd::vector <char *> co = create_options(CreationOptions, true); // open options\n\tGDALDataset *md = nc->CreateMultiDimensional(name[0], \n\t\t\t\t\tRootGroupOptions.size() ? rgo.data() : nullptr, \n\t\t\t\t\tCreationOptions.size()  ? co.data() : nullptr);\n\tif (md == NULL)\n\t\tstop(\"Cannot create MD array on this driver\");\n\tstd::shared_ptr<GDALGroup> g = md->GetRootGroup();\n\tif (g == NULL)\n\t\tstop(\"Cannot get RootGroup\");\n\n\t// create dimensions on g:\n\tCharacterVector dimnames; \n\tif (dimensions.attr(\"names\") != R_NilValue)\n\t\tdimnames = dimensions.attr(\"names\");\n\telse\n\t\tstop(\"dimensions should have names\");\n\tstd::vector<std::shared_ptr<GDALDimension>> all_dims;\n\tfor (int i = dimensions.size() - 1; i >= 0; i--) { // backwards, for whatever reason\n\t\tstd::string type;\n\t\tstd::string direction = \"\";\n\t\tif (dimnames[i] == xy[0]) // \"x\"\n\t\t\ttype = \"HORIZONTAL_X\";\n\t\telse if (dimnames[i] == xy[1]) // \"y\"\n\t\t\ttype = \"HORIZONTAL_Y\";\n\t\telse if (dimnames[i] == \"depth\") {\n\t\t\ttype = \"VERTICAL\";\n\t\t\tdirection = \"DOWN\";\n\t\t} else if (dimnames[i] == \"height\") {\n\t\t\ttype = \"VERTICAL\";\n\t\t\tdirection = \"UP\";\n\t\t} else if (dimnames[i] == \"time\")\n\t\t\ttype = \"TEMPORAL\";\n\t\telse\n\t\t\ttype = \"\";\n\t\tconst char *name = dimnames[i];\n\t\tstd::shared_ptr<GDALDimension> d = g->CreateDimension(name, type, direction, dimensions[i], nullptr);\n\t\tif (d == nullptr)\n\t\t\tstop(\"creation of dimension failed\");\n\t\tall_dims.push_back(d);\n\t}\n\tstd::reverse(all_dims.begin(), all_dims.end()); // because I can't think backwards\n\n\t// create & write variables to g; write attributes\n\tGDALExtendedDataType edt = GDALExtendedDataType::Create(GDT_Float64);\n\tCharacterVector names; \n\tif (variables.attr(\"names\") != R_NilValue)\n\t\tnames = variables.attr(\"names\");\n\telse\n\t\tstop(\"variables should have names\");\n\tLogicalVector which_crs;\n\tif (variables.attr(\"which_crs\") != R_NilValue)\n\t\twhich_crs = variables.attr(\"which_crs\");\n\telse\n\t\tstop(\"which_crs attribute missing\");\n\tLogicalVector is_numeric;\n\tif (variables.attr(\"is_numeric\") != R_NilValue)\n\t\tis_numeric = variables.attr(\"is_numeric\");\n\telse\n\t\tstop(\"is_numeric attribute missing\");\n\n\tfor (int i = 0; i < variables.size(); i++) {\n\t\tNumericVector a;\n\t\tCharacterVector c;\n\t\tIntegerVector which_dims;\n\t\tstd::vector<std::shared_ptr<GDALDimension>> dims;\n\t\tif (is_numeric[i]) {\n\t\t\tif (as_float)\n\t\t\t\tedt = GDALExtendedDataType::Create(GDT_Float32);\n\t\t\telse\n\t\t\t\tedt = GDALExtendedDataType::Create(GDT_Float64);\n\t\t\ta = variables[i];\n\t\t\tif (a.attr(\"which_dims\") == R_NilValue)\n\t\t\t\tstop(\"variable has no attribute which_dims\");\n\t\t\telse\n\t\t\t\twhich_dims = a.attr(\"which_dims\");\n\t\t} else {\n\t\t\tedt = GDALExtendedDataType::CreateString(0);\n\t\t\tc = variables[i];\n\t\t\tif (c.attr(\"which_dims\") == R_NilValue)\n\t\t\t\tstop(\"variable has no attribute which_dims\");\n\t\t\telse\n\t\t\t\twhich_dims = c.attr(\"which_dims\");\n\t\t}\n\t\tfor (int i = which_dims.size() - 1; i >= 0; i--) {\n\t\t\tif (which_dims[i] == NA_INTEGER)\n\t\t\t\tstop(\"NA value in which_dims: logic error\");\n\t\t\tdims.push_back(all_dims[which_dims[i]]);\n\t\t}\n\t\tconst char *name = names[i];\n\t\tstd::shared_ptr<GDALMDArray> mda = g->CreateMDArray(name, dims, edt, nullptr);\n\t\tif (dims.size() == 1 && names[i] == dimnames[which_dims[0]])\n\t\t\tdims[0]->SetIndexingVariable(mda); // FIXME: NetCDF doesn't have?\n\t\tif (dest != NULL && which_crs[i] && !mda->SetSpatialRef(dest))\n\t\t\twarning(\"failed to assign CRS to array\");\n\n\t\t// set start & count of writing area:\n\t\tstd::vector<GUInt64> start;\n\t\tstd::vector<size_t> count;\n\t\tfor (int i = dims.size() - 1; i >= 0; i--) {\n\t\t\tstart.push_back(0); // FIXME: modify if updating sub-array\n\t\t\tcount.push_back(dimensions[which_dims[i]]);\n\t\t}\n\t\tbool success = true;\n\t\tif (is_numeric[i]) { // write numeric array:\n\t\t\tif (a.attr(\"attrs\") != R_NilValue)\n\t\t\t\twrite_attributes(mda, a.attr(\"attrs\"));\n\t\t\tif (a.size() != 0) {\n\t\t\t\t// Rcout << \"Variable: \" << name << \", ndims: \" << dims.size() << \", crs: \" << which_crs[i] << std::endl;\n\t\t\t\tif (as_float) {\n\t\t\t\t\tstd::vector<float> flt(a.size());\n\t\t\t\t\tfor (int j = 0; j < a.size(); j++)\n\t\t\t\t\t\tflt[j] = a[j];\n\t\t\t\t\tsuccess = mda->Write(start.data(), count.data(), nullptr, nullptr, edt, flt.data(), nullptr, 0);\n\t\t\t\t} else\n\t\t\t\t\tsuccess = mda->Write(start.data(), count.data(), nullptr, nullptr, edt, &(a[0]), nullptr, 0);\n\t\t\t}\n\t\t} else { // write character array:\n\t\t\tif (c.attr(\"attrs\") != R_NilValue)\n\t\t\t\twrite_attributes(mda, c.attr(\"attrs\"));\n\t\t\tif (c.size() != 0) {\n\t\t\t\tif (dims.size() != 1)\n\t\t\t\t\tstop(\"can only write one-dimensional character variables\");\n\t\t\t\tstd::vector<const char *> v;\n\t\t\t\tfor (int i = 0; i < c.size(); i++) {\n\t\t\t\t\tconst char *cp = c[i];\n\t\t\t\t\tv.push_back(cp);\n\t\t\t\t}\n\t\t\t\tsuccess = mda->Write(start.data(), count.data(), nullptr, nullptr, edt, v.data(), nullptr, 0);\n\t\t\t}\n\t\t}\n\t\tif (! success)\n\t\t\tRcout << \"Error writing array \" << name << std::endl;\n\t}\n\n\t// close, free & return:\n\tGDALClose(md);\n\tif (dest != NULL)\n\t\tdelete dest;\n\treturn variables;\n}\n\n#else\nList CPL_read_mdim(CharacterVector file, CharacterVector array_names, CharacterVector oo,\n\t\t\t\tIntegerVector offset, IntegerVector count, IntegerVector step, \n\t\t\t\tbool proxy = false, bool debug = false) {\n\tstop(\"requires GDAL >= 3.1.0 and 64-bit\");\n}\n\nList CPL_write_mdim(CharacterVector name, CharacterVector driver, IntegerVector dimensions,\n\t\t\t\tList variables, CharacterVector wkt, CharacterVector xy, CharacterVector RootGroupOptions,\n\t\t\t\tCharacterVector CreationOptions, bool as_float = true) {\n\tstop(\"requires GDAL >= 3.1.0 and 64-bit\");\n}\n#endif\n"
  },
  {
    "path": "src/ops.cpp",
    "content": "#include <Rcpp.h>\n\nvoid add_feature(SEXP &feature, SEXP &value) {\n\tdouble* p_feature = REAL(feature);\n\tdouble* p_value = REAL(value);\n\tint nval = LENGTH(value);\n\tif (Rf_isMatrix(feature)) {\n\t\tint nrow = Rf_nrows(feature);\n\t\tint ncol = Rf_ncols(feature);\n\t\tncol = ncol > 2 ? 2 : ncol;\n\t\tfor (int i = 0; i < nrow * ncol; i ++) {\n\t\t\tp_feature[i] = p_feature[i] + p_value[(i / nrow) % nval];\n\t\t}\n\t} else {\n\t\tint nfeat = LENGTH(feature);\n\t\tnfeat = nfeat > 2 ? 2 : nfeat;\n\t\tfor (int i = 0; i < nfeat; i ++) {\n\t\t\tp_feature[i] = p_feature[i] + p_value[i % nval];\n\t\t}\n\t}\n}\nvoid mult_feature(SEXP &feature, SEXP &value) {\n\tdouble* p_feature = REAL(feature);\n\tdouble* p_value = REAL(value);\n\tint nval = LENGTH(value);\n\tif (Rf_isMatrix(feature)) {\n\t\tint nrow = Rf_nrows(feature);\n\t\tint ncol = Rf_ncols(feature);\n\t\tncol = ncol > 2 ? 2 : ncol;\n\t\tfor (int i = 0; i < nrow * ncol; i ++) {\n\t\t\tp_feature[i] = p_feature[i] * p_value[(i / nrow) % nval];\n\t\t}\n\t} else {\n\t\tint nfeat = LENGTH(feature); // # nocov start\n\t\tnfeat = nfeat > 2 ? 2 : nfeat;\n\t\tfor (int i = 0; i < nfeat; i ++) {\n\t\t\tp_feature[i] = p_feature[i] * p_value[i % nval];\n\t\t} // # nocov end\n\t}\n}\n\nvoid recursive_opp(SEXP &feature, SEXP &value, int mult) {\n\tif (Rf_isVectorList(feature)) {\n\t\tfor (int i = 0; i < LENGTH(feature); i++) {\n\t\t\tSEXP next_feature = VECTOR_ELT(feature, i);\n\t\t\tif (Rf_isInteger(next_feature)) {\n\t\t\t\tSEXP num_feature = PROTECT(Rf_coerceVector(next_feature, REALSXP));\n\t\t\t\tDUPLICATE_ATTRIB(num_feature, next_feature);\n\t\t\t\tnext_feature = SET_VECTOR_ELT(feature, i, num_feature);\n\t\t\t\tUNPROTECT(1);\n\t\t\t}\n\t\t\trecursive_opp(next_feature, value, mult);\n\t\t}\n\t} else {\n\t\tif (mult) {\n\t\t\tmult_feature(feature, value);\n\t\t} else {\n\t\t\tadd_feature(feature, value);\n\t\t}\n\t}\n}\n\nvoid transform_bbox(SEXP &feature, SEXP &value, int mult) {\n\tdouble* p_bbox = REAL(Rf_getAttrib(feature, Rf_install(\"bbox\")));\n\tdouble* p_value = REAL(value);\n\tif (mult) {\n\t\tp_bbox[0] = p_bbox[0] * p_value[0];\n\t\tp_bbox[2] = p_bbox[2] * p_value[0];\n\t\tp_bbox[1] = p_bbox[1] * p_value[1 % LENGTH(value)];\n\t\tp_bbox[3] = p_bbox[3] * p_value[1 % LENGTH(value)];\n\t} else {\n\t\tp_bbox[0] = p_bbox[0] + p_value[0];\n\t\tp_bbox[2] = p_bbox[2] + p_value[0];\n\t\tp_bbox[1] = p_bbox[1] + p_value[1 % LENGTH(value)];\n\t\tp_bbox[3] = p_bbox[3] + p_value[1 % LENGTH(value)];\n\t}\n}\n\n//[[Rcpp::export(rng=false)]]\nSEXP opp_sfc(SEXP geom, SEXP value, SEXP mult, SEXP crs) {\n\tSEXP new_geom = PROTECT(Rf_duplicate(geom));\n\n\tint multiply = INTEGER(mult)[0] == 1;\n\n\trecursive_opp(new_geom, value, multiply);\n\ttransform_bbox(new_geom, value, multiply);\n\tRf_setAttrib(new_geom, Rf_install(\"crs\"), crs);\n\n\tUNPROTECT(1);\n\treturn new_geom;\n}\n\n//[[Rcpp::export(rng=false)]]\nSEXP normalize_sfc(SEXP geom, SEXP min, SEXP range, SEXP crs) {\n\tSEXP new_geom = PROTECT(Rf_duplicate(geom));\n\n\trecursive_opp(new_geom, min, 0);\n\trecursive_opp(new_geom, range, 1);\n\ttransform_bbox(new_geom, min, 0);\n\ttransform_bbox(new_geom, range, 1);\n\tRf_setAttrib(new_geom, Rf_install(\"crs\"), crs);\n\n\tUNPROTECT(1);\n\treturn new_geom;\n}\n"
  },
  {
    "path": "src/polygonize.cpp",
    "content": "#include <gdal.h>\n#include <gdal_alg.h>\n#include <gdal_priv.h> // GDALDriver\n#include <ogr_api.h>\n#include <ogr_geometry.h>\n#include <ogr_srs_api.h>\n#include <ogr_spatialref.h>\n#include <cpl_conv.h>\n#include <cpl_string.h>\n\n#include <stdlib.h> // atoi\n#include <string.h>\n\n#include <ogrsf_frmts.h>\n\n#include <Rcpp.h>\n\n#include \"gdal.h\"\n#include \"gdal_read.h\"\n#include \"gdal_sf_pkg.h\"\n\n// # nocov start\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_polygonize(Rcpp::CharacterVector raster, Rcpp::CharacterVector mask_name,\n\t\tRcpp::CharacterVector raster_driver, \n\t\tRcpp::CharacterVector vector_driver, Rcpp::CharacterVector vector_dsn,\n\t\tRcpp::CharacterVector options, Rcpp::IntegerVector iPixValField,\n\t\tRcpp::CharacterVector contour_options, bool use_contours = false,\n\t\tbool use_integer = true) {\n\n    GDALDataset  *poDataset = (GDALDataset *) GDALOpenEx(raster[0], GA_ReadOnly,\n\t\traster_driver.size() ? create_options(raster_driver).data() : NULL,\n\t\t// options.size() ? create_options(options).data() : NULL,\n\t\tNULL, NULL);\n    if (poDataset == NULL) {\n\t\tRcpp::Rcout << \"trying to read file: \" << raster[0] << std::endl; // #nocov\n        Rcpp::stop(\"file not found\"); // #nocov\n\t}\n\n\tconst char *wkt = poDataset->GetProjectionRef();\n\n\tGDALRasterBand *poBand = NULL;\n\tif (poDataset->GetRasterCount() > 0)\n\t\tpoBand = poDataset->GetRasterBand( 1 );\n\telse\n\t\tRcpp::Rcout << \"No bands in raster file.\" << std::endl; // #nocov\n\n\t// mask:\n    GDALDataset  *maskDataset = NULL;\n\tGDALRasterBand *maskBand = NULL;\n\tif (mask_name.size()) {\n\t\tmaskDataset = (GDALDataset *) GDALOpenEx(mask_name[0], GA_ReadOnly,\n\t\t\traster_driver.size() ? create_options(raster_driver).data() : NULL,\n\t\t\t// options.size() ? create_options(options).data() : NULL,\n\t\t\tNULL, NULL);\n    \tif (maskDataset == NULL) {\n\t\t\tRcpp::Rcout << \"trying to read file: \" << mask_name[0] << std::endl; // #nocov\n        \tRcpp::stop(\"file not found\"); // #nocov\n\t\t}\n\t\n\t\tif (maskDataset->GetRasterCount() > 0)\n\t\t\tmaskBand = maskDataset->GetRasterBand( 1 );\n\t\telse\n\t\t\tRcpp::Rcout << \"No bands in mask file.\" << std::endl; // #nocov\n\t}\n\n\n\t// output: vector layer\n\tGDALDriver *poDriver = GetGDALDriverManager()->GetDriverByName(vector_driver[0]);\n\tif (poDriver == NULL) {\n\t\tRcpp::Rcout << \"driver `\" << vector_driver[0] << \"' not available.\" << std::endl; // #nocov\n\t\tRcpp::stop(\"Driver not available.\\n\"); // #nocov\n\t}\n\tGDALDataset *poDS; \n\tif ((poDS = poDriver->Create(vector_dsn[0], 0, 0, 0, GDT_Unknown, NULL)) == NULL) {\n\t\tRcpp::Rcout << \"Creating dataset \" <<  vector_dsn[0] << \" failed.\" << std::endl; // #nocov\n\t\tRcpp::stop(\"Creation failed.\\n\"); // #nocov\n\t}\n\tOGRSpatialReference *sr = NULL;\n\tif (wkt != NULL && *wkt != '\\0') {\n\t\tsr = new OGRSpatialReference;\n\t\tsr = handle_axis_order(sr);\n#if GDAL_VERSION_NUM < 2030000\n\t\tchar **ppt = (char **) &wkt;\n#else\n\t\tconst char **ppt = (const char **) &wkt;\n#endif\n\t\tsr->importFromWkt(ppt);\n\t}\n\tOGRLayer *poLayer = poDS->CreateLayer(\"raster\", sr, wkbMultiPolygon, NULL);\n\tdelete sr;\n\n\tif (use_integer) {\n\t\t// create field:\n\t\tOGRFieldDefn oField(\"Value\", OFTInteger);\n\t\tif (poLayer->CreateField(&oField) != OGRERR_NONE)\n    \t\tRcpp::stop(\"Creating attribute field failed.\\n\"); // #nocov\n\t\tif (GDALPolygonize((GDALRasterBandH) poBand, maskBand,\n\t\t\t(OGRLayerH) poLayer,\n\t\t\tiPixValField[0],\n\t\t\tNULL, // create_options(options, true),\n\t\t\tNULL, NULL) != OGRERR_NONE)\n\t\t\t\tRcpp::Rcout << \"GDALPolygonize returned an error\" << std::endl; // #nocov\n\t} else {\n\t\tOGRFieldDefn oField(\"Value\", OFTReal);\n\t\tif (poLayer->CreateField(&oField) != OGRERR_NONE)\n    \t\tRcpp::stop(\"Creating attribute field failed.\\n\"); // #nocov\n\t\tOGRFieldDefn minField(\"Min\", OFTReal);\n\t\tif (poLayer->CreateField(&minField) != OGRERR_NONE)\n    \t\tRcpp::stop(\"Creating attribute field failed.\\n\"); // #nocov\n\t\tOGRFieldDefn maxField(\"Max\", OFTReal);\n\t\tif (poLayer->CreateField(&maxField) != OGRERR_NONE)\n    \t\tRcpp::stop(\"Creating attribute field failed.\\n\"); // #nocov\n\n\t\tif (!use_contours) {\n\t\t\tif (GDALFPolygonize((GDALRasterBandH) poBand, maskBand,\n\t\t\t\t(OGRLayerH) poLayer,\n\t\t\t\tiPixValField[0],\n\t\t\t\tcreate_options(options, true).data(),\n\t\t\t\tNULL, NULL) != OGRERR_NONE)\n\t\t\t\t\tRcpp::Rcout << \"GDALFPolygonize returned an error\" << std::endl; // #nocov\n\t\t} else {\n#if GDAL_VERSION_NUM >= 2040000\n\t\t\tif (GDALContourGenerateEx((GDALRasterBandH) poBand, (void *) poLayer,\n                       \tcreate_options(contour_options).data(), NULL, NULL) != OGRERR_NONE)\n\t\t\t\tRcpp::stop(\"GDALContourGenerateEx returned an error\");\n#else\n\t\t\tRcpp::stop(\"contour requires GDAL >= 2.4.0\");\n#endif\n\t\t}\n\t}\n\n\tRcpp::NumericVector type(1);\n\ttype[0] = 0;\n\tRcpp::CharacterVector fid_column; // empty\n\tRcpp::List lst = sf_from_ogrlayer(poLayer, false, true, type, fid_column, true, -1);\n\tGDALClose(poDataset); // raster\n\tGDALClose(poDS); // vector\n\tif (maskDataset != NULL)\n\t\tGDALClose(maskDataset); // mask\n\treturn lst; \n} \n// # nocov end\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_rasterize(Rcpp::CharacterVector raster, Rcpp::CharacterVector raster_driver,\n\t\tRcpp::List sfc, Rcpp::NumericVector values,\n\t\tRcpp::CharacterVector options,\n\t\tRcpp::NumericVector NA_value) {\n\n    GDALDataset  *poDataset = (GDALDataset *) GDALOpenEx(raster[0], GDAL_OF_UPDATE,\n\t\traster_driver.size() ? create_options(raster_driver).data() : NULL,\n\t\t// options.size() ? create_options(options).data() : NULL,\n\t\tNULL, NULL);\n    if (poDataset == NULL) {\n\t\tRcpp::Rcout << \"trying to read file: \" << raster[0] << std::endl; // #nocov\n        Rcpp::stop(\"file not found\"); // #nocov\n\t}\n\t\n\tstd::vector<OGRGeometry *> geoms = ogr_from_sfc(sfc, NULL);\n\n\t// int bandlist = 1;\n\tstd::vector<int> bandlist(poDataset->GetRasterCount());\n\tfor (size_t i = 0; i < bandlist.size(); i++)\n\t\tbandlist[i] = (int) i+1; // 1-based\n\n\tCPLErr err = GDALRasterizeGeometries((GDALDatasetH) poDataset, // hDS,\n\t\tpoDataset->GetRasterCount(), // int \tnBandCount,\n\t\tbandlist.data(), // int * \tpanBandList,\n\t\tgeoms.size(), // int \tnGeomCount,\n\t\t(OGRGeometryH *) geoms.data(), // OGRGeometryH * \tpahGeometries,\n\t\tNULL, // GDALTransformerFunc \tpfnTransformer,\n\t\tNULL, // void * \tpTransformArg,\n\t\t(double *) &(values[0]), // double * \tpadfGeomBurnValue,\n\t\toptions.size() ? create_options(options).data() : NULL, // char ** \tpapszOptions,\n\t\tNULL, // GDALProgressFunc \tpfnProgress,\n\t\tNULL  //void * \tpProgressArg \n\t);\n\n\tfor (size_t i = 0; i < geoms.size(); i++)\n\t\tOGRGeometryFactory::destroyGeometry(geoms[i]);\n\n\tif (err != OGRERR_NONE)\n\t\tRcpp::Rcout << \"GDALRasterizeGeometries returned an error\" << std::endl; // #nocov\n\tGDALClose(poDataset); // raster\n\treturn Rcpp::List::create();\n}\n"
  },
  {
    "path": "src/proj.cpp",
    "content": "#include <iostream>\n\n#include <ogr_srs_api.h>\n#include <cpl_string.h>\n\n#include \"Rcpp.h\"\n\n#define NO_GDAL_CPP_HEADERS\n#include \"gdal_sf_pkg.h\"\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_proj_h(bool b = false) {\n#if defined(HAVE_PROJ_H) && !defined(ACCEPT_USE_OF_DEPRECATED_PROJ_API_H)\n\treturn true;\n#else\n\treturn false;\n#endif\n}\n\n#if defined(HAVE_PROJ_H) && !defined(ACCEPT_USE_OF_DEPRECATED_PROJ_API_H) // new api\n# include <proj.h>\n\n#if PROJ_VERSION_MAJOR > 7\n# define HAVE_71\n#else\n# if PROJ_VERSION_MAJOR == 7\n#  if PROJ_VERSION_MINOR >= 1\n#   define HAVE_71\n#  endif\n# endif\n#endif\n\n// [[Rcpp::export(rng=false)]]\nRcpp::DataFrame CPL_get_pipelines(Rcpp::CharacterVector crs, Rcpp::CharacterVector authority, \n\t\tRcpp::NumericVector AOI, Rcpp::CharacterVector Use, \n\t\tRcpp::CharacterVector grid_availability,\n\t\tdouble accuracy = -1.0,\n\t\tbool strict_containment = false,\n\t\tbool axis_order_auth_compl = false) {\n#ifdef HAVE_71\n\tif (crs.size() != 2)\n\t\tRcpp::stop(\"length 2 character vector expected\");\n\tconst char *auth = NULL;\n\tif (authority.size())\n\t\tauth = authority[0];\n\tPJ_OPERATION_FACTORY_CONTEXT *factory_ctx = \n\t\tproj_create_operation_factory_context(PJ_DEFAULT_CTX, auth);\n\tif (accuracy >= 0.0)\n\t\tproj_operation_factory_context_set_desired_accuracy(PJ_DEFAULT_CTX, factory_ctx, accuracy);\n\tif (AOI.size() == 4)\n\t\tproj_operation_factory_context_set_area_of_interest(PJ_DEFAULT_CTX, factory_ctx, \n\t\t\tAOI[0], AOI[1], AOI[2], AOI[3]);\n\telse if (Use.size() == 1) {\n\t\tif (Use[0] == \"NONE\")\n\t\t\tproj_operation_factory_context_set_crs_extent_use(PJ_DEFAULT_CTX, factory_ctx, \n\t\t\t\tPJ_CRS_EXTENT_NONE);\n\t\telse if (Use[0] == \"BOTH\")\n\t\t\tproj_operation_factory_context_set_crs_extent_use(PJ_DEFAULT_CTX, factory_ctx, \n\t\t\t\tPJ_CRS_EXTENT_BOTH);\n\t\telse if (Use[0] == \"INTERSECTION\")\n\t\t\tproj_operation_factory_context_set_crs_extent_use(PJ_DEFAULT_CTX, factory_ctx,\n\t\t\t\tPJ_CRS_EXTENT_INTERSECTION);\n\t\telse if (Use[0] == \"SMALLEST\")\n\t\t\tproj_operation_factory_context_set_crs_extent_use(PJ_DEFAULT_CTX, factory_ctx, \n\t\t\t\tPJ_CRS_EXTENT_SMALLEST);\n\t\telse\n\t\t\tRcpp::stop(\"unknown value for Use\");\n\t}\n\t// FIXME:\n\t// handle many more constraining options\n\tif (strict_containment)\n\t\tproj_operation_factory_context_set_spatial_criterion(PJ_DEFAULT_CTX, factory_ctx,\n\t\t\tPROJ_SPATIAL_CRITERION_STRICT_CONTAINMENT);\n\telse\n\t\tproj_operation_factory_context_set_spatial_criterion(PJ_DEFAULT_CTX, factory_ctx,\n\t\t\tPROJ_SPATIAL_CRITERION_PARTIAL_INTERSECTION);\n\n\t// PROJ_GRID_AVAILABILITY_USE\n\tif (grid_availability.size() == 1) {\n\t\tif (grid_availability[0] == \"USED\")\n\t\t\tproj_operation_factory_context_set_grid_availability_use(PJ_DEFAULT_CTX, factory_ctx, \n\t\t\t\tPROJ_GRID_AVAILABILITY_USED_FOR_SORTING); // Grid availability is only used for sorting results. \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t  // Operations where some grids are missing will be sorted last.\n\t\telse if (grid_availability[0] == \"DISCARD\")\n\t\t\tproj_operation_factory_context_set_grid_availability_use(PJ_DEFAULT_CTX, factory_ctx, \n\t\t\t\t\t\t\tPROJ_GRID_AVAILABILITY_DISCARD_OPERATION_IF_MISSING_GRID); // Completely discard an operation if a required grid is missing.\n\t\telse if (grid_availability[0] == \"IGNORED\")\n\t\t\tproj_operation_factory_context_set_grid_availability_use(PJ_DEFAULT_CTX, factory_ctx, \n\t\t\t\t\t\t\tPROJ_GRID_AVAILABILITY_IGNORED); // Ignore grid availability at all. Results will be presented as if all grids were available.\n\t\telse if (grid_availability[0] == \"AVAILABLE\")\n\t\t\tproj_operation_factory_context_set_grid_availability_use(PJ_DEFAULT_CTX, factory_ctx, \n\t\t\t\t\t\t\tPROJ_GRID_AVAILABILITY_KNOWN_AVAILABLE); // Results will be presented as if grids known to PROJ \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t // (that is registered in the grid_alternatives table of its database) \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t // were available. Used typically when networking is enabled.\n\t\telse\n\t\t\tRcpp::stop(\"Unknown value for grid_availability\");\n\t}\n\n\tPJ *source_crs = proj_create(PJ_DEFAULT_CTX, crs[0]);\n\tif (source_crs == NULL)\n\t\tRcpp::stop(proj_errno_string(proj_context_errno(PJ_DEFAULT_CTX)));\n\tPJ *target_crs = proj_create(PJ_DEFAULT_CTX, crs[1]);\n\tif (target_crs == NULL)\n\t\tRcpp::stop(proj_errno_string(proj_context_errno(PJ_DEFAULT_CTX)));\n\n\tPJ_OBJ_LIST *obj_list = proj_create_operations(PJ_DEFAULT_CTX, source_crs, target_crs, \n\t\tfactory_ctx);\n\tif (obj_list == NULL)\n\t\tRcpp::stop(\"proj_create_operations() returned NULL\"); // and clean up?\n\tint n = proj_list_get_count(obj_list);\n\tRcpp::CharacterVector id(n);\n\tRcpp::CharacterVector description(n);\n\tRcpp::CharacterVector definition(n);\n\tRcpp::LogicalVector   has_inverse(n);\n\tRcpp::LogicalVector   axis_order(n);\n\tRcpp::NumericVector   acc(n);\n\tRcpp::IntegerVector   grid_count(n);\n\tRcpp::LogicalVector   instantiable(n);\n\tRcpp::List            grids(n);\n\tfor (int i = 0; i < n; i++) {\n\t\tPJ *pj = proj_list_get(PJ_DEFAULT_CTX, obj_list, i);\n\t\tif (! axis_order_auth_compl) {\n\t\t\tPJ* orig = pj;\n\t\t\tpj = proj_normalize_for_visualization(PJ_DEFAULT_CTX, orig);\n\t\t\tproj_destroy(orig);\n\t\t}\n\t\taxis_order(i) = axis_order_auth_compl;\n\t\tgrid_count(i) = proj_coordoperation_get_grid_used_count(PJ_DEFAULT_CTX, pj);\n\t\tinstantiable(i) = (bool) proj_coordoperation_is_instantiable(PJ_DEFAULT_CTX, pj);\n\t\tPJ_PROJ_INFO info = proj_pj_info(pj);\n\t\tdescription(i) = info.description;\n\t\tdefinition(i) = info.definition;\n\t\tif (info.id != NULL)\n\t\t\tid(i) = info.id;\n\t\thas_inverse(i) = info.has_inverse != 0;\n\t\tif (info.accuracy == -1.0)\n\t\t\tacc(i) = NA_REAL;\n\t\telse\n\t\t\tacc(i) = info.accuracy;\n\t\tif (grid_count(i) > 0) {\n\t\t\tRcpp::List g(grid_count(i));\n\t\t\tfor (int j = 0; j < grid_count(i); j++) {\n\t\t\t\tconst char *out_short_name, *out_full_name, *out_package_name, *out_url;\n\t\t\t\tint grid_OK, out_direct_download, out_open_license, out_available;\n\t\t\t\tgrid_OK = proj_coordoperation_get_grid_used(PJ_DEFAULT_CTX, pj,\n\t\t\t\t\tj, &out_short_name, &out_full_name, &out_package_name,\n\t\t\t\t\t&out_url, &out_direct_download, &out_open_license,\n\t\t\t\t\t&out_available);\n\t\t\t\tif (grid_OK) {\n\t\t\t\t\tg(j) = Rcpp::List::create(\n\t\t\t\t\t\tRcpp::Named(\"out_short_name\") = out_short_name,\n\t\t\t\t\t\tRcpp::Named(\"out_full_name\") = out_full_name,\n\t\t\t\t\t\tRcpp::Named(\"out_package_name\") = out_package_name,\n\t\t\t\t\t\tRcpp::Named(\"out_url\") = out_url,\n\t\t\t\t\t\tRcpp::Named(\"out_direct_download\") = out_direct_download,\n\t\t\t\t\t\tRcpp::Named(\"out_open_license\") = out_open_license,\n\t\t\t\t\t\tRcpp::Named(\"out_available\") = out_available\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t\tgrids(i) = g;\n\t\t}\n\t\tproj_destroy(pj);\n\t}\n\t// int sug = proj_get_suggested_operation(PJ_DEFAULT_CTX, *obj_list, PJ_DIRECTION direction, PJ_COORD coord)\n\tproj_list_destroy(obj_list);\n\n\tRcpp::DataFrame df = Rcpp::DataFrame::create( \n\t\tRcpp::Named(\"id\") = id,\n\t\tRcpp::Named(\"description\") = description,\n\t\tRcpp::Named(\"definition\") = definition,\n\t\tRcpp::Named(\"has_inverse\") = has_inverse,\n\t\tRcpp::Named(\"accuracy\") = acc,\n\t\tRcpp::Named(\"axis_order\") = axis_order,\n\t\tRcpp::Named(\"grid_count\") = grid_count,\n\t\tRcpp::Named(\"instantiable\") = instantiable\n\t);\n\tdf.attr(\"grids\") = grids;\n\n\tproj_destroy(source_crs);\n\tproj_destroy(target_crs);\n\tproj_operation_factory_context_destroy(factory_ctx);\n\treturn df;\n#else\n\tRcpp::warning(\"PROJ >= 7.1 required\");\n\treturn Rcpp::DataFrame::create();\n#endif\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::CharacterVector CPL_get_data_dir(bool from_proj = false) {\n\tif (from_proj) {\n\t\tRcpp::CharacterVector ret(proj_info().searchpath);\n\t\treturn ret;\n\t} else {\n#if GDAL_VERSION_NUM >= 3000300\n\t\tchar **ogr_sp = OSRGetPROJSearchPaths();\n\t\tRcpp::CharacterVector ogr_sp_sf = charpp2CV(ogr_sp);\n\t\tCSLDestroy(ogr_sp);\n\t\treturn ogr_sp_sf;\n#else\n\t\tRcpp::stop(\"requires GDAL >= 3.0.3\");\n#endif\n\t}\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_is_network_enabled(bool b = false) {\n#if PROJ_VERSION_MAJOR >= 7\n#if GDAL_VERSION_NUM >= 3040000\n\tif (OSRGetPROJEnableNetwork() != proj_context_is_network_enabled(PJ_DEFAULT_CTX))\n\t\tRcpp::warning(\"GDAL and PROJ have different settings for network enablement; use sf_use_network() to sync them\");\n#endif\n\treturn Rcpp::LogicalVector::create(proj_context_is_network_enabled(PJ_DEFAULT_CTX));\n#else\n\treturn Rcpp::LogicalVector::create(false);\n#endif\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::CharacterVector CPL_enable_network(Rcpp::CharacterVector url, bool enable = true) {\n#ifdef HAVE_71\n\tif (enable) {\n\t\tproj_context_set_enable_network(PJ_DEFAULT_CTX, 1);\n#if GDAL_VERSION_NUM >= 3040000\n\t\tOSRSetPROJEnableNetwork(1);\n#endif\n\t\tif (url.size())\n\t\t\tproj_context_set_url_endpoint(PJ_DEFAULT_CTX, url[0]);\n\t\treturn Rcpp::CharacterVector::create(proj_context_get_url_endpoint(PJ_DEFAULT_CTX));\n\t} else { // disable:\n\t\tproj_context_set_enable_network(PJ_DEFAULT_CTX, 0);\n#if GDAL_VERSION_NUM >= 3040000\n\t\tOSRSetPROJEnableNetwork(0);\n#endif\n\t\treturn Rcpp::CharacterVector::create();\n\t}\n#else\n\treturn Rcpp::CharacterVector::create();\n#endif\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_set_data_dir(Rcpp::CharacterVector data_dir, bool with_proj) {\n\tif (with_proj) {\n\t\tif (data_dir.size() != 1)\n\t\t\tRcpp::stop(\"data_dir should be size 1 character vector\"); // #nocov\n\t\tstd::string dd = Rcpp::as<std::string>(data_dir);\n\t\tconst char *cp = dd.c_str();\n\t\tproj_context_set_search_paths(PJ_DEFAULT_CTX, 1, &cp);\n\t} else {\n#if GDAL_VERSION_NUM >= 3000000\n\t\tstd::vector <char *> dirs = create_options(data_dir, true);\n\t\tOSRSetPROJSearchPaths(dirs.data());\n#else\n\t\tRcpp::stop(\"setting proj search path for GDAL requires GDAL >= 3.0.0\");\n#endif\n\t}\n\treturn true;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::LogicalVector CPL_use_proj4_init_rules(Rcpp::IntegerVector v) {\n\tproj_context_use_proj4_init_rules(PJ_DEFAULT_CTX, v[0]);\n\treturn true;\n}\n\n// [[Rcpp::export(rng=false)]]\nstd::string CPL_proj_version(bool b = false) {\n\n\tstd::stringstream buffer;\n\tbuffer << PROJ_VERSION_MAJOR << \".\" << PROJ_VERSION_MINOR << \".\" << PROJ_VERSION_PATCH;\n\treturn buffer.str();\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_proj_is_valid(std::string proj4string) {\n\tRcpp::List out(2);\n\n\tproj_context_use_proj4_init_rules(PJ_DEFAULT_CTX, 1);\n\tPJ *P = proj_create(PJ_DEFAULT_CTX, proj4string.c_str());\n\tif (P == NULL) {\n\t\tout(0) = Rcpp::LogicalVector::create(false);\n\t\tout(1) = Rcpp::CharacterVector::create( proj_errno_string(proj_context_errno(PJ_DEFAULT_CTX)));\n\t} else {\n\t\tout(0) = Rcpp::LogicalVector::create(true);\n\t\tPJ_PROJ_INFO pi;\n\t\tpi = proj_pj_info(P);\n\t\tout(1) = Rcpp::CharacterVector::create(pi.description);\n\t\tproj_destroy(P);\n\t}\n\treturn out;\n}\n\n// [[Rcpp::export(rng=false)]]\nbool CPL_have_datum_files(SEXP foo) {\n\n\t// TODO:\n\t// create a PJ with e.g. conus, check success, if yes destroy, return success\n\tRcpp::warning(\"CPL_have_datum not yet implemented for PROJ6 proj.h interface\");\n\treturn true;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::NumericMatrix CPL_proj_direct(Rcpp::CharacterVector from_to, Rcpp::NumericMatrix pts, \n\t\tbool keep, bool warn = true, bool authority_compliant = false) {\n\n\tusing namespace Rcpp;\n\n\tif (from_to.size() != 1 && from_to.size() != 2)\n\t\tstop(\"from_to should be size 1 or 2 character vector\"); // #nocov\n\tif (pts.ncol() < 2 || pts.ncol() > 4)\n\t\tstop(\"pts should be 2-, 3- or 4-column numeric vector\"); // #nocov\n\tbool have_z = pts.ncol() > 2; // column 3\n\tbool have_t = pts.ncol() > 3; // column 4\n\n\tproj_context_use_proj4_init_rules(PJ_DEFAULT_CTX, 1); // FIXME: needed?\n\tPJ *P = NULL;\n\tif (from_to.size() == 2) // source + target:\n\t\tP = proj_create_crs_to_crs(PJ_DEFAULT_CTX, from_to[0], from_to[1], NULL); \n\t\t// PJ_AREA *area);\n\telse // source to target pipeline:\n\t\tP = proj_create(PJ_DEFAULT_CTX, from_to[0]);\n\tif (P == NULL)\n\t\tstop(proj_errno_string(proj_context_errno(PJ_DEFAULT_CTX)));\n\tif (!authority_compliant && from_to.size() == 2) { // keep lat/lon as lon/lat\n\t\tPJ *NewP = proj_normalize_for_visualization(PJ_DEFAULT_CTX, P);\n\t\tproj_destroy(P);\n\t\tif (NewP == NULL)\n\t\t\tstop(proj_errno_string(proj_context_errno(PJ_DEFAULT_CTX)));\n\t\telse\n\t\t\tP = NewP;\n\t}\n\t// copy over:\n\tstd::vector<PJ_COORD> x(pts.nrow());\n\tfor (int i = 0; i < pts.nrow(); i++) {\n\t\tx.data()[i].lpzt.lam = pts(i, 0);\n\t\tx.data()[i].lpzt.phi = pts(i, 1);\n\t\t// for default z and t values, see https://proj.org/development/migration.html\n\t\tx.data()[i].lpzt.z = have_z ? pts(i, 2) : 0.0;\n\t\tx.data()[i].lpzt.t = have_t ? pts(i, 3) : HUGE_VAL; \n\t}\n\n\t// deg2rad?\n\tif (proj_angular_output(P, PJ_INV)) {\n\t\tfor (int i = 0; i < pts.nrow(); i++) {\n\t\t\tx.data()[i].lpzt.lam = proj_torad(x.data()[i].lpzt.lam);\n\t\t\tx.data()[i].lpzt.phi = proj_torad(x.data()[i].lpzt.phi);\n\t\t}\n\t}\n\n\t// transform:\n\tif (keep) {\n\t\t// use proj_trans() on individual points, making unprojectable points be NA\n\t\tPJ_COORD row = {{ 0.0, 0.0, 0.0, 0.0 }}, projected;\n\t\tfor (int i = 0; i < pts.nrow(); i++) {\n\t\t\t/*\n\t\t\trow.lpzt.lam = x.data()[i].lpzt.lam;\n\t\t\trow.lpzt.phi = x.data()[i].lpzt.phi;\n\t\t\trow.lpzt.z = x.data()[i].lpzt.z;\n\t\t\trow.lpzt.t = x.data()[i].lpzt.t;\n\t\t\t*/\n\t\t\trow.lpzt = x.data()[i].lpzt;\n\t\t\tprojected = proj_trans(P, PJ_FWD, row);\n\t\t\t/*\n\t\t\tx.data()[i].lpzt.lam = projected.lpzt.lam;\n\t\t\tx.data()[i].lpzt.phi = projected.lpzt.phi;\n\t\t\tx.data()[i].lpzt.z = projected.lpzt.z;\n\t\t\tx.data()[i].lpzt.t = projected.lpzt.t;\n\t\t\t*/\n\t\t\tx.data()[i].lpzt = projected.lpzt;\n\t\t}\n\t} else {\n\t\t// DEFAULT: use proj_trans_array() on array, returning zero-length if any point is unprojectable\n\t\tif (proj_trans_array(P, PJ_FWD, x.size(), x.data())) {\n\t\t\tproj_destroy(P);\n\t\t\tstop(proj_errno_string(proj_context_errno(PJ_DEFAULT_CTX)));\n\t\t}\n\t}\n\n\t// rad2deg?\n\tif (proj_angular_output(P, PJ_FWD)) {\n\t\tfor (int i = 0; i < pts.nrow(); i++) {\n\t\t\tx.data()[i].lpzt.lam = proj_todeg(x.data()[i].lpzt.lam);\n\t\t\tx.data()[i].lpzt.phi = proj_todeg(x.data()[i].lpzt.phi);\n\t\t}\n\t}\n\tproj_destroy(P);\n\n\t// copy to out matrix:\n\tNumericMatrix out(pts.nrow(), pts.ncol());\n\tfor (int i = 0; i < out.nrow(); i++) {\n\t\tout(i, 0) = x.data()[i].lpzt.lam;\n\t\tout(i, 1) = x.data()[i].lpzt.phi;\n\t\tif (have_z)\n\t\t\tout(i, 2) = x.data()[i].lpzt.z;\n\t\tif (have_t)\n\t\t\tout(i, 3) = x.data()[i].lpzt.t;\n\t}\n\n\tint nwarn = 0;\n\tfor (int i = 0; i < out.nrow(); i++) {\n\t\tif (out(i, 0) == HUGE_VAL || out(i, 1) == HUGE_VAL) {\n\t\t\tout(i, 0) = NA_REAL;\n\t\t\tout(i, 1) = NA_REAL;\n\t\t\tif (have_z)\n\t\t\t\tout(i, 2) = NA_REAL;\n\t\t\tif (have_t)\n\t\t\t\tout(i, 3) = NA_REAL;\n\t\t\tnwarn++; // #nocov\n\t\t}\n\t}\n\tif (warn && nwarn > 0)\n\t\twarning(\"one or more projected point(s) not finite\"); // #nocov\n\treturn out;\n}\n\n\n#else // if defined(HAVE_PROJ_H) && !defined(ACCEPT_USE_OF_DEPRECATED_PROJ_API_H) i.e., old proj_api:\n# include <proj_api.h>\n\n#if PJ_VERSION >= 600\n# define PROJ6 1\n#endif\n\nRcpp::DataFrame CPL_get_pipelines(Rcpp::CharacterVector crs, Rcpp::CharacterVector authority, \n\t\tRcpp::NumericVector AOI, Rcpp::CharacterVector Use, \n\t\tRcpp::CharacterVector grid_availability,\n\t\tdouble accuracy = -1.0,\n\t\tbool strict_containment = false,\n\t\tbool axis_order_auth_compl = false) {\n\n\tRcpp::stop(\"PROJ 7 required\");\n\treturn Rcpp::DataFrame::create();\n}\n\nRcpp::LogicalVector CPL_is_network_enabled(bool b = false) {\n#if PROJ_VERSION_MAJOR >= 7\n\treturn Rcpp::LogicalVector::create(proj_context_is_network_enabled(PJ_DEFAULT_CTX));\n#else\n\treturn Rcpp::LogicalVector::create(false);\n#endif\n}\n\nRcpp::CharacterVector CPL_enable_network(Rcpp::CharacterVector url, bool enable = true) {\n#if PROJ_VERSION_MAJOR >= 7\n\tif (enable) {\n\t\tproj_context_set_enable_network(PJ_DEFAULT_CTX, 1);\n\t\tif (url.size())\n\t\t\tproj_context_set_url_endpoint(PJ_DEFAULT_CTX, url[0]);\n\t\treturn Rcpp::CharacterVector::create(proj_context_get_url_endpoint(PJ_DEFAULT_CTX));\n\t} else { // disable:\n\t\tproj_context_set_enable_network(PJ_DEFAULT_CTX, 0);\n\t\treturn Rcpp::CharacterVector::create();\n\t}\n#else\n\treturn Rcpp::CharacterVector::create();\n#endif\n}\n\nRcpp::CharacterVector CPL_get_data_dir(bool from_proj = false) {\n#if PROJ_VERSION_MAJOR >= 7\n\treturn Rcpp::CharacterVector(proj_info().searchpath);\n#else\n\treturn Rcpp::CharacterVector(NA_STRING);\n#endif\n}\n\nRcpp::LogicalVector CPL_set_data_dir(Rcpp::CharacterVector data_dir, bool with_proj) { // #nocov start\n\treturn false;\n}\n\nRcpp::LogicalVector CPL_use_proj4_init_rules(Rcpp::IntegerVector v) {\n\treturn false;\n}  // #nocov end\n\n#if PJ_VERSION == 480\nextern \"C\" {\nFILE *pj_open_lib(projCtx, const char *, const char *);\n}\n#endif\n\n#include \"Rcpp.h\"\n\nstd::string CPL_proj_version(bool b = false) {\n\tint v = PJ_VERSION;\n\tstd::stringstream buffer;\n\tbuffer << v / 100 << \".\" << (v / 10) % 10 << \".\" << v % 10;\n\treturn buffer.str();\n}\n\nRcpp::List CPL_proj_is_valid(std::string proj4string) {\n\tRcpp::List out(2);\n\tprojPJ pj = pj_init_plus(proj4string.c_str());\n\tif (pj == NULL) {\n\t\tout(0) = Rcpp::LogicalVector::create(false);\n\t\tout(1) = Rcpp::CharacterVector::create(pj_strerrno(*pj_get_errno_ref()));\n\t} else {\n\t\tout(0) = Rcpp::LogicalVector::create(true);\n\t\tchar *def = pj_get_def(pj, 0);\n\t\tout(1) = Rcpp::CharacterVector::create(def);\n\t\tpj_free(pj);\n\t\tfree(def);\n\t}\n\treturn out;\n}\n\nbool CPL_have_datum_files(SEXP foo) {\n\n#if PJ_VERSION <= 480\n\tFILE *fp;\n#else\n\tPAFile fp;\n#endif\n\tprojCtx ctx;\n\tctx = pj_get_default_ctx();\n\tfp = pj_open_lib(ctx, \"conus\", \"rb\");\n\tif (fp != NULL) {\n#if PJ_VERSION <= 480\n\t\tfclose(fp);\n#else\n\t\tpj_ctx_fclose(ctx, fp);\n#endif\n\t\treturn true;\n\t} else\n\t\treturn false; // #nocov\n}\n\nRcpp::NumericMatrix CPL_proj_direct(Rcpp::CharacterVector from_to, Rcpp::NumericMatrix pts, \n\t\tbool keep, bool warn = true, bool authority_compliant = false) {\n\n\tusing namespace Rcpp;\n\n\tif (authority_compliant)\n\t\tstop(\"authority_compliant = TRUE requires the new PROJ (proj.h) interface\");\n\tif (from_to.size() != 2)\n\t\tstop(\"from_to should be size 2 character vector\"); // #nocov\n\tif (pts.ncol() != 2)\n\t\tstop(\"pts should be 2-column numeric vector\"); // #nocov\n\n\tprojPJ fromPJ, toPJ;\n\n\tif (!(fromPJ = pj_init_plus(from_to[0])))\n\t\tstop(pj_strerrno(*pj_get_errno_ref()));\n\n\tif (!(toPJ = pj_init_plus(from_to[1])))\n\t\tstop(pj_strerrno(*pj_get_errno_ref()));\n\n\t// copy over:\n\tstd::vector<double> xx(pts.nrow()), yy(pts.nrow());\n\tfor (int i = 0; i < pts.nrow(); i++) {\n   \t\t xx[i] = pts(i, 0);\n   \t\t yy[i] = pts(i, 1);\n\t}\n\tif (pj_is_latlong(fromPJ)) {\n\t\tfor (int i = 0; i < pts.nrow(); i++) {\n\t   \t\t xx[i] *= DEG_TO_RAD;\n\t   \t\t yy[i] *= DEG_TO_RAD;\n\t\t}\n\t}\n\n//\tfor (int i = 0; i < pts.nrow(); i++)\n//  \t\t Rcout << xx[i] << \" \" << yy[i] << std::endl;\n\tif (keep) {\n\t\t// use proj_trans() on individual points, making unprojectable points be NA\n\t\t// FIXME: not tested, since author has no access to the old proj API.\n\t\tdouble thisx, thisy;\n\t\tfor (int i = 0; i < pts.nrow(); i++) {\n\t\t\tthisx = xx[i];\n\t\t\tthisy = yy[i];\n\t\t\tif (pj_transform(fromPJ, toPJ, 1, 0, &thisx, &thisy, NULL) != 0) {\n\t\t\t\txx[i] = R_PosInf;\n\t\t\t\tyy[i] = R_PosInf;\n\t\t\t} else {\n\t\t\t\txx[i] = thisx;\n\t\t\t\tyy[i] = thisy;\n\t\t\t}\n\t\t}\n\t} else {\n   \t\t// DEFAULT: use proj_trans_array() on array, returning zero-length if any point is unprojectable\n\t\tif (pj_transform(fromPJ, toPJ, pts.nrow(), 0, xx.data(), yy.data(), NULL) != 0) {\n\t\t\tpj_free(fromPJ); pj_free(toPJ); // #nocov start\n\t\t\tRcout << \"error in pj_transform: \" << pj_strerrno(*pj_get_errno_ref()) << std::endl;\n\t\t\tstop(\"error\"); // #nocov end\n\t\t}\n\t}\n\tpj_free(fromPJ);\n\tif (pj_is_latlong(toPJ)) {\n\t\tfor (int i = 0; i < pts.nrow(); i++) {\n\t   \t\t\t xx[i] *= RAD_TO_DEG;\n\t   \t\t\t yy[i] *= RAD_TO_DEG;\n\t\t}\n\t}\n\t// copy to out matrix:\n\tNumericMatrix out(pts.nrow(), pts.ncol());\n\tfor (int i = 0; i < out.nrow(); i++) {\n   \t\t out(i, 0) = xx[i];\n   \t\t out(i, 1) = yy[i];\n\t}\n\tpj_free(toPJ);\n\tint nwarn = 0;\n\tfor (int i = 0; i < out.nrow(); i++) {\n\t\tif (out(i, 0) == HUGE_VAL || out(i, 1) == HUGE_VAL) {\n\t\t\tout(i, 0) = NA_REAL;\n\t\t\tout(i, 1) = NA_REAL;\n\t\t\tnwarn++; // #nocov\n\t\t}\n\t}\n\tif (warn && nwarn > 0) \n\t\twarning(\"one or more projected point(s) not finite\"); // #nocov\n\treturn out;\n}\n#endif\n"
  },
  {
    "path": "src/proj_info.cpp",
    "content": "#include \"Rcpp.h\"\n\n#ifdef HAVE_PROJ_H\n#include <proj.h>\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_proj_info(int type) {\n\n\tRcpp::List ret;\n\tswitch (type) {\n\t\tcase 0: {\n\t\t\tRcpp::List ans(2);\n\t\t\tans.attr(\"names\") = Rcpp::CharacterVector::create(\"name\", \"description\");\n\t\t\tint n = 0;\n\t\t\tconst struct PJ_LIST *lp;\n\t\t\tfor (lp = proj_list_operations() ; lp->id ; ++lp) {\n\t\t\t\tif( strcmp(lp->id,\"latlong\") == 0\n\t\t\t\t\t\t|| strcmp(lp->id,\"longlat\") == 0\n\t\t\t\t\t\t|| strcmp(lp->id,\"geocent\") == 0 )\n\t\t\t\t\tcontinue;\n\t\t\t\tn++;\n\t\t\t}\n\t\t\tRcpp::CharacterVector cv0(n);\n\t\t\tRcpp::CharacterVector cv1(n);\n\t\t\tn = 0;\n\t\t\tfor (lp = proj_list_operations() ; lp->id ; ++lp) {\n\t\t\t\tif (strcmp(lp->id,\"latlong\") == 0\n\t\t\t\t\t\t|| strcmp(lp->id,\"longlat\") == 0\n\t\t\t\t\t\t|| strcmp(lp->id,\"geocent\") == 0 )\n\t\t\t\t\tcontinue;\n\t\t\t\tcv0(n) = lp->id;\n\t\t\t\tcv1(n) = *lp->descr;\n\t\t\t\tn++;\n\t\t\t}\n\t\t\tans(0) = cv0;\n\t\t\tans(1) = cv1;\n\t\t\tret = ans;\n\t\t} break;\n\t\tcase 1: {\n\t\t\tRcpp::List ans(4);\n\t\t\tans.attr(\"names\") = Rcpp::CharacterVector::create(\"name\", \n\t\t\t\t\"major\", \"ell\", \"description\");\n\t\t\tint n = 0;\n\t\t\tconst struct PJ_ELLPS *le;\n\t\t\tfor (le = proj_list_ellps(); le->id ; ++le) \n\t\t\t\tn++;\n\t\t\tRcpp::CharacterVector ans0(n);\n\t\t\tRcpp::CharacterVector ans1(n);\n\t\t\tRcpp::CharacterVector ans2(n);\n\t\t\tRcpp::CharacterVector ans3(n);\n\t\t\tn = 0;\n\t\t\tfor (le = proj_list_ellps(); le->id ; ++le) {\n\t\t\t\tans0(n) = le->id;\n\t\t\t\tans1(n) = le->major;\n\t\t\t\tans2(n) = le->ell;\n\t\t\t\tans3(n) = le->name;\n\t\t\t\tn++;\n\t\t\t}\n\t\t\tans(0) = ans0;\n\t\t\tans(1) = ans1;\n\t\t\tans(2) = ans2;\n\t\t\tans(3) = ans3;\n\t\t\tret = ans;\n\t\t} break;\n\t\tcase 2: {\n\t\t\tret = R_NilValue;\n\t\t} break;\n\t\tcase 3: {\n\t\t\tRcpp::List ans(3);\n\t\t\tans.attr(\"names\") = Rcpp::CharacterVector::create(\"id\", \"to_meter\",\n\t\t\t\t\"name\");\n\t\t\tint n = 0;\n#if ((PROJ_VERSION_MAJOR == 7 && PROJ_VERSION_MINOR >= 1) || PROJ_VERSION_MAJOR > 7)\n\t\t\tPROJ_UNIT_INFO** units;\n\t\t\tunits = proj_get_units_from_database(nullptr, nullptr, \"linear\", false, nullptr);\n\t\t\tfor (int i = 0; units && units[i]; i++) {\n\t\t\t\tif (units[i]->proj_short_name) \n\t\t\t\t\tn++;\n\t\t\t}\n\t\t\tRcpp::CharacterVector ans0(n);\n\t\t\tRcpp::NumericVector ans1(n);\n\t\t\tRcpp::CharacterVector ans2(n);\n\t\t\tint item = 0;\n\t\t\tfor (int i = 0; units && units[i]; i++) {\n\t\t\t\tif (units[i]->proj_short_name) {\n\t\t\t\t\tans0[item] = units[i]->proj_short_name;\n\t\t\t\t\tans1[item] = units[i]->conv_factor;\n\t\t\t\t\tans2[item] = units[i]->name;\n\t\t\t\t\titem++;\n\t\t\t\t}\n\t\t\t\tif (item >= n)\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tproj_unit_list_destroy(units);\n\t\t\tans(0) = ans0;\n\t\t\tans(1) = ans1;\n\t\t\tans(2) = ans2;\n#else\n\t\t\tconst struct PJ_UNITS *lu;\n\t\t\tfor (lu = proj_list_units(); lu->id ; ++lu) \n\t\t\t\tn++;\n\t\t\tRcpp::CharacterVector ans0(n);\n\t\t\tRcpp::CharacterVector ans1(n);\n\t\t\tRcpp::CharacterVector ans2(n);\n\t\t\tn = 0;\n\t\t\tfor (lu = proj_list_units(); lu->id ; ++lu) {\n\t\t\t\tans0(n) = lu->id;\n\t\t\t\tans1(n) = lu->to_meter;\n\t\t\t\tans2(n) = lu->name;\n\t\t\t\tn++;\n\t\t\t}\n\t\t\tans(0) = ans0;\n\t\t\tans(1) = ans1;\n\t\t\tans(2) = ans2;\n#endif\n\t\t\tret = ans;\n\t\t} break;\n\t\tcase 4: {\n\t\t\tRcpp::List ans(2);\n\t\t\tans.attr(\"names\") = Rcpp::CharacterVector::create(\"id\", \"definition\");\n\t\t\tint n = 0;\n\t\t\tconst struct PJ_PRIME_MERIDIANS *lpm;\n\t\t\tfor (lpm = proj_list_prime_meridians(); lpm->id ; ++lpm) \n\t\t\t\tn++;\n\t\t\tRcpp::CharacterVector ans0(n);\n\t\t\tRcpp::CharacterVector ans1(n);\n\t\t\tn = 0;\n\t\t\tfor (lpm = proj_list_prime_meridians(); lpm->id ; ++lpm) {\n\t\t\t\tans0(n) = lpm->id;\n\t\t\t\tans1(n) = lpm->defn;\n\t\t\t\tn++;\n\t\t\t}\n\t\t\tans(0) = ans0;\n\t\t\tans(1) = ans1;\n\t\t\tret = ans;\n\t\t} break;\n\t\tdefault:\n\t\t\tRcpp::stop(\"unknown type\"); // #nocov\n\t\tbreak;\n\t}\n\treturn ret;\n}\n\n#else\n#include <proj_api.h>\n\nextern \"C\" {\n// modified from: rgdal/pkg/src/projectit.cpp\n\n// copied necessary parts from projects.h; full header conflicts with R headers;\n// should these things ever change in the proj API, then we're in trouble.\nstruct PJconsts;\nstruct PJ_LIST {\n\tchar\t*id;\t\t/* projection keyword */\n\tstruct PJconsts\t*(*proj)(struct PJconsts*);/* projection entry point */\n\tchar \t* const *descr;\t/* description text */\n};\nstruct PJ_LIST *pj_get_list_ref( void );\nstruct PJ_ELLPS {\n\tchar\t*id;\t/* ellipse keyword name */\n\tchar\t*major;\t/* a= value */\n\tchar\t*ell;\t/* elliptical parameter */\n\tchar\t*name;\t/* comments */\n};\nstruct PJ_ELLPS *pj_get_ellps_ref( void );\nstruct PJ_DATUMS {\n\tchar\t*id;\t /* datum keyword */\n\tchar\t*defn;\t /* ie. \"to_wgs84=...\" */\n\tchar\t*ellipse_id; /* ie from ellipse table */\n\tchar\t*comments; /* EPSG code, etc */\n};\nstruct PJ_DATUMS *pj_get_datums_ref( void ); \nstruct PJ_UNITS {\n\tchar\t*id;\t\t/* units keyword */\n\tchar\t*to_meter;\t/* multiply by value to get meters */\n\tchar\t*name;\t\t/* comments */\n#if PJ_VERSION >= 500\n\tdouble   factor;       /* to_meter factor in actual numbers */\n#endif\n};\nstruct PJ_UNITS *pj_get_units_ref( void );\n\n} // extern \"C\"\n\nRcpp::List CPL_proj_info(int type) {\n\n\tRcpp::List ret;\n\tswitch (type) {\n\t\tcase 0: {\n\t\t\tRcpp::List ans(2);\n\t\t\tans.attr(\"names\") = Rcpp::CharacterVector::create(\"name\", \"description\");\n\t\t\tint n = 0;\n\t\t\tstruct PJ_LIST *lp;\n\t\t\tfor (lp = pj_get_list_ref() ; lp->id ; ++lp)\n\t\t\t\tn++;\n\t\t\tRcpp::CharacterVector cv0(n);\n\t\t\tRcpp::CharacterVector cv1(n);\n\t\t\tn = 0;\n\t\t\tfor (lp = pj_get_list_ref() ; lp->id ; ++lp) {\n\t\t\t\tcv0(n) = lp->id;\n\t\t\t\tcv1(n) = *lp->descr;\n\t\t\t\tn++;\n\t\t\t}\n\t\t\tans(0) = cv0;\n\t\t\tans(1) = cv1;\n\t\t\tret = ans;\n\t\t} break;\n\t\tcase 1: {\n\t\t\tRcpp::List ans(4);\n\t\t\tans.attr(\"names\") = Rcpp::CharacterVector::create(\"name\", \n\t\t\t\t\"major\", \"ell\", \"description\");\n\t\t\tint n = 0;\n\t\t\tstruct PJ_ELLPS *le;\n\t\t\tfor (le = pj_get_ellps_ref(); le->id ; ++le) \n\t\t\t\tn++;\n\t\t\tRcpp::CharacterVector ans0(n);\n\t\t\tRcpp::CharacterVector ans1(n);\n\t\t\tRcpp::CharacterVector ans2(n);\n\t\t\tRcpp::CharacterVector ans3(n);\n\t\t\tn = 0;\n\t\t\tfor (le = pj_get_ellps_ref(); le->id ; ++le) {\n\t\t\t\tans0(n) = le->id;\n\t\t\t\tans1(n) = le->major;\n\t\t\t\tans2(n) = le->ell;\n\t\t\t\tans3(n) = le->name;\n\t\t\t\tn++;\n\t\t\t}\n\t\t\tans(0) = ans0;\n\t\t\tans(1) = ans1;\n\t\t\tans(2) = ans2;\n\t\t\tans(3) = ans3;\n\t\t\tret = ans;\n\t\t} break;\n\t\tcase 2: {\n\t\t\tRcpp::List ans(4);\n\t\t\tans.attr(\"names\") = Rcpp::CharacterVector::create(\"name\", \"ellipse\",\n\t\t\t\t\"definition\", \"description\");\n\t\t\tint n = 0;\n\t\t\tstruct PJ_DATUMS *ld;\n\t\t\tfor (ld = pj_get_datums_ref(); ld->id ; ++ld) \n\t\t\t\tn++;\n\t\t\tRcpp::CharacterVector ans0(n);\n\t\t\tRcpp::CharacterVector ans1(n);\n\t\t\tRcpp::CharacterVector ans2(n);\n\t\t\tRcpp::CharacterVector ans3(n);\n\t\t\tn = 0;\n\t\t\tfor (ld = pj_get_datums_ref(); ld->id ; ++ld) {\n\t\t\t\tans0(n) = ld->id;\n\t\t\t\tans1(n) = ld->ellipse_id;\n\t\t\t\tans2(n) = ld->defn;\n\t\t\t\tans3(n) = ld->comments;\n\t\t\t\tn++;\n\t\t\t}\n\t\t\tans(0) = ans0;\n\t\t\tans(1) = ans1;\n\t\t\tans(2) = ans2;\n\t\t\tans(3) = ans3;\n\t\t\tret = ans;\n\t\t} break;\n\t\tcase 3: {\n#if PJ_VERSION >= 500\n\t\t\tRcpp::List ans(4);\n\t\t\tans.attr(\"names\") = Rcpp::CharacterVector::create(\"id\", \"to_meter\",\n\t\t\t\t\"name\", \"factor\");\n\t\t\tint n = 0;\n\t\t\tstruct PJ_UNITS *ld;\n\t\t\tfor (ld = pj_get_units_ref(); ld->id ; ++ld) \n\t\t\t\tn++;\n\t\t\tRcpp::CharacterVector ans0(n);\n\t\t\tRcpp::CharacterVector ans1(n);\n\t\t\tRcpp::CharacterVector ans2(n);\n\t\t\tRcpp::NumericVector ans3(n);\n\t\t\tn = 0;\n\t\t\tfor (ld = pj_get_units_ref(); ld->id ; ++ld) {\n\t\t\t\tans0(n) = ld->id;\n\t\t\t\tans1(n) = ld->to_meter;\n\t\t\t\tans2(n) = ld->name;\n\t\t\t\tans3(n) = ld->factor;\n\t\t\t\tn++;\n\t\t\t}\n\t\t\tans(0) = ans0;\n\t\t\tans(1) = ans1;\n\t\t\tans(2) = ans2;\n\t\t\tans(3) = ans3;\n\t\t\tret = ans;\n#else\n\t\t\tRcpp::List ans(3);\n\t\t\tans.attr(\"names\") = Rcpp::CharacterVector::create(\"id\", \"to_meter\",\n\t\t\t\t\"name\");\n\t\t\tint n = 0;\n\t\t\tstruct PJ_UNITS *ld;\n\t\t\tfor (ld = pj_get_units_ref(); ld->id ; ++ld) \n\t\t\t\tn++;\n\t\t\tRcpp::CharacterVector ans0(n);\n\t\t\tRcpp::CharacterVector ans1(n);\n\t\t\tRcpp::CharacterVector ans2(n);\n\t\t\tn = 0;\n\t\t\tfor (ld = pj_get_units_ref(); ld->id ; ++ld) {\n\t\t\t\tans0(n) = ld->id;\n\t\t\t\tans1(n) = ld->to_meter;\n\t\t\t\tans2(n) = ld->name;\n\t\t\t\tn++;\n\t\t\t}\n\t\t\tans(0) = ans0;\n\t\t\tans(1) = ans1;\n\t\t\tans(2) = ans2;\n\t\t\tret = ans;\n#endif\n\t\t} break;\n\t\tdefault:\n\t\t\tRcpp::stop(\"unknown type\"); // #nocov\n\t\tbreak;\n\t}\n\treturn ret;\n}\n\n#endif // HAVE_PROJ_H\n"
  },
  {
    "path": "src/raster2sf.cpp",
    "content": "#include \"Rcpp.h\"\n\nusing namespace Rcpp;\n\n// [[Rcpp::export(rng=false)]]\nList CPL_xy2sfc(NumericMatrix cc, IntegerVector dim, bool to_points, IntegerVector which, bool cc_has_NAs) {\n\tif (cc.nrow() != dim[0] * dim[1])\n\t\tstop(\"xy2sfc: wrong dimensions\"); // #nocov\n\tList sfc(which.length());\n\tif (to_points) {\n\t\tNumericVector point(2);\n\t\tpoint.attr(\"class\") = CharacterVector::create(\"XY\", \"POINT\", \"sfg\");\n\t\tfor (int i = 0; i < which.length(); i++) {\n\t\t\tint ix = which[i] - 1;\n\t\t\tpoint(0) = cc(ix, 0);\n\t\t\tpoint(1) = cc(ix, 1);\n\t\t\tsfc(i) = clone(point);\n\t\t}\n\t\tsfc.attr(\"class\") = CharacterVector::create(\"sfc_POINT\", \"sfc\");\n\t} else {\n\t\tfor (int i = 0; i < which.length(); i++) {\n\t\t\tint ix = which[i] - 1; // from R, 1-based\n\t\t\tsize_t y = ix / (dim[0] - 1); // row index\n\t\t\tsize_t x = ix % (dim[0] - 1); // col index\n\t\t\t// Rcpp::Rcout << \"x is:\" << x << \" y is:\" << y << std::endl;\n\t\t\tNumericMatrix points(5, 2); // the four corners\n\t\t\tpoints(0,0) = cc(y * (dim[0]) + x    ,   0); // top left\n\t\t\tpoints(0,1) = cc(y * (dim[0]) + x    ,   1); // top left\n\t\t\tpoints(1,0) = cc(y * (dim[0]) + x + 1,   0); // top right\n\t\t\tpoints(1,1) = cc(y * (dim[0]) + x + 1,   1); // top right\n\t\t\tpoints(2,0) = cc((y + 1) * (dim[0]) + x + 1, 0); // bottom right\n\t\t\tpoints(2,1) = cc((y + 1) * (dim[0]) + x + 1, 1); // bottom right\n\t\t\tpoints(3,0) = cc((y + 1) * (dim[0]) + x    , 0); // bottom left\n\t\t\tpoints(3,1) = cc((y + 1) * (dim[0]) + x    , 1); // bottom left\n\t\t\tpoints(4,0) = cc(y * (dim[0]) + x    ,       0); // top left\n\t\t\tpoints(4,1) = cc(y * (dim[0]) + x    ,       1); // top left\n\t\t\tbool empty = false;\n\t\t\tif (cc_has_NAs) {\n\t\t\t\tNumericVector xy(8);\n\t\t\t\txy(0) = points(0,0);\n\t\t\t\txy(1) = points(0,1);\n\t\t\t\txy(2) = points(1,0);\n\t\t\t\txy(3) = points(1,1);\n\t\t\t\txy(4) = points(2,0);\n\t\t\t\txy(5) = points(2,1);\n\t\t\t\txy(6) = points(3,0);\n\t\t\t\txy(7) = points(3,1);\n\t\t\t\tLogicalVector b = any(is_na(xy));\n\t\t\t\tif (b[0]) {\n\t\t\t\t\tList polygon;\n\t\t\t\t\tpolygon.attr(\"class\") = CharacterVector::create(\"XY\", \"POLYGON\", \"sfg\");\n\t\t\t\t\tsfc(i) = polygon; // empty polygon\n\t\t\t\t\tempty = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!empty) {\n\t\t\t\tList polygon(1);\n\t\t\t\tpolygon.attr(\"class\") = CharacterVector::create(\"XY\", \"POLYGON\", \"sfg\");\n\t\t\t\tpolygon(0) = points;\n\t\t\t\tsfc(i) = polygon; \n\t\t\t}\n\t\t}\n\t\tsfc.attr(\"class\") = CharacterVector::create(\"sfc_POLYGON\", \"sfc\");\n\t}\n\tsfc.attr(\"precision\") = NumericVector::create(0.0);\n\treturn(sfc);\n}\n"
  },
  {
    "path": "src/sfc-sfg.cpp",
    "content": "#include <Rcpp.h>\nusing namespace Rcpp;\n\n#include <unordered_set>\n\n// [[Rcpp::export(rng=false)]]\nLogicalVector sfc_is_null(List sfc) {\n\tLogicalVector out(sfc.size());\n\t\n\t// An element identical to NA_logical_ or NULL is considered NULL\n\t// for the purposes of the sfc constructor\n\tSEXP item;\n\t\n\tfor (R_xlen_t i = 0; i < sfc.size(); i++) {\n\t\titem = sfc[i];\n\t\tout[i] = item == R_NilValue ||\n\t\t\t(TYPEOF(item) == LGLSXP && \n\t\t\t Rf_length(item) == 1 && \n\t\t\t LOGICAL(item)[0] == NA_LOGICAL);\n\t}\n\t\n\treturn out;\n}\n\n// [[Rcpp::export(rng=false)]]\nList sfc_unique_sfg_dims_and_types(List sfc) {\n\tif (sfc.size() == 0) {\n\t\treturn List::create(\n\t\t\t_[\"class_dim\"] = CharacterVector::create(),\n\t\t\t_[\"class_type\"] = CharacterVector::create());\n\t}\n\t\n\tstd::unordered_set<std::string> class_dim;\n\tstd::unordered_set<std::string> class_type;\n\tSEXP item;\n\t\n\tfor (R_xlen_t i = 0; i < sfc.size(); i++) {\n\t\titem = sfc[i];\n\t\t\n\t\t// Because Rf_inherits() is faster than using Rf_getAttrib\n\t\t// or RObject::attr()\n\t\tif (Rf_inherits(item, \"XY\")) {\n\t\t\tclass_dim.insert(\"XY\");\n\t\t} else if (Rf_inherits(item, \"XYZ\")) {\n\t\t\tclass_dim.insert(\"XYZ\");\n\t\t} else if (Rf_inherits(item, \"XYM\")) {\n\t\t\tclass_dim.insert(\"XYM\");\n\t\t} else if (Rf_inherits(item, \"XYZM\")) {\n\t\t\tclass_dim.insert(\"XYZM\");\n\t\t}\n\t\t\n\t\tif (!Rf_inherits(item, \"sfg\"))\n\t\t\tstop(\"object(s) should be of class 'sfg'\");\n\n\t\tif (Rf_inherits(item, \"POINT\")) {\n\t\t\tclass_type.insert(\"POINT\");\n\t\t\tcontinue;\n\t\t} else if (Rf_inherits(item, \"LINESTRING\")) {\n\t\t\tclass_type.insert(\"LINESTRING\");\n\t\t\tcontinue;\n\t\t} else if (Rf_inherits(item, \"POLYGON\")) {\n\t\t\tclass_type.insert(\"POLYGON\");\n\t\t\tcontinue;\n\t\t} else if (Rf_inherits(item, \"MULTIPOINT\")) {\n\t\t\tclass_type.insert(\"MULTIPOINT\");\n\t\t\tcontinue;\n\t\t} else if (Rf_inherits(item, \"MULTILINESTRING\")) {\n\t\t\tclass_type.insert(\"MULTILINESTRING\");\n\t\t\tcontinue;\n\t\t} else if (Rf_inherits(item, \"MULTIPOLYGON\")) {\n\t\t\tclass_type.insert(\"MULTIPOLYGON\");\n\t\t\tcontinue;\n\t\t}\n\t\t\n\t\t// Other types exist, too, but are more rare are not optimized yet\n\t\tRObject itemSlow(sfc[i]);\n\t\tRObject classes = itemSlow.attr(\"class\");\n\t\tif (classes == R_NilValue) {\n\t\t\tcontinue;\n\t\t}\n\t\t\n\t\tCharacterVector classes_chr(classes);\n\t\tif (classes_chr.size() == 3) {\n\t\t\tclass_type.insert(static_cast<std::string>(classes_chr[1]));\n\t\t}\n\t}\n\t\n\tCharacterVector class_dim_chr(class_dim.begin(), class_dim.end());\n\tCharacterVector class_type_chr(class_type.begin(), class_type.end());\n\t\n\treturn List::create(\n\t\t_[\"class_dim\"] = class_dim_chr,\n\t\t_[\"class_type\"] = class_type_chr);\n}\n\n// [[Rcpp::export(rng=false)]]\nLogicalVector sfc_is_empty(List sfc) {\n\tLogicalVector out(sfc.size());\n\t\n\tSEXP item;\n\t\n\tfor (R_xlen_t i = 0; i < sfc.size(); i++) {\n\t\titem = sfc[i];\n\t\tint item_len = Rf_length(item);\n\t\tbool is_empty = true;\n\t\t\n\t\tif (Rf_inherits(item, \"POINT\")) {\n\t\t\tif (TYPEOF(item) == REALSXP) {\n\t\t\t\tfor (int j = 0; j < item_len; j++) {\n\t\t\t\t\tdouble val = REAL(item)[j];\n\t\t\t\t\tif (!ISNA(val) && !ISNAN(val)) {\n\t\t\t\t\t\tis_empty = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if (TYPEOF(item) == INTSXP) {\n\t\t\t\tfor (int j = 0; j < item_len; j++) {\n\t\t\t\t\tint val = INTEGER(item)[j];\n\t\t\t\t\tif (val != NA_INTEGER) {\n\t\t\t\t\t\tis_empty = false;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif (item_len == 0) \n\t\t\t\tis_empty = true;\n\t\t\telse if (TYPEOF(item) == VECSXP) { // #2463\n\t\t\t\titem = VECTOR_ELT(item, 0); \n\t\t\t\tis_empty = Rf_length(item) == 0 || // e.g. POLYGON with 1 ring without coordinates\n\t\t\t\t\t\t(TYPEOF(item) == VECSXP && Rf_length(VECTOR_ELT(item, 0)) == 0); // same for one level deeper, e.g. MULTIPOLYGON:\n\t\t\t} else\n\t\t\t\tis_empty = false;\n\t\t}\n\t\tout[i] = is_empty;\n\t}\n\t\n\treturn out;\n}\n\n// [[Rcpp::export(rng=false)]]\nLogicalVector sfc_is_full(List sfc) {\n\tLogicalVector out(sfc.size());\n\t\n\tSEXP item;\n\t\n\tfor (R_xlen_t i = 0; i < sfc.size(); i++) {\n\t\titem = sfc[i];\n\t\tint item_len = Rf_length(item);\n\t\tbool is_full = false;\n\t\tif (item_len == 1 && Rf_inherits(item, \"POLYGON\")) {\n\t\t\tSEXP m = VECTOR_ELT(item, 0);\n\t\t\tif (Rf_isMatrix(m) && Rf_nrows(m) == 2) /* we can go on and check the values, but... */\n\t\t\t\tis_full = true;\n\t\t}\n\t\tout[i] = is_full;\n\t}\n\treturn out;\n}\n\n// [[Rcpp::export(rng=false)]]\nList points_cpp(NumericMatrix pts, CharacterVector gdim = \"XY\") {\n\tint n = pts.nrow();\n\tList out(n);\n\tCharacterVector cls = CharacterVector::create(gdim[0], \"POINT\", \"sfg\");\n\tfor (int i = 0; i < n; i++) {\n\n\t\tNumericVector lp = pts(i, _);\n\t\tlp.attr(\"class\") = cls;\n\t\tout[i] = lp;\n\t}\n\treturn out;\n}\n"
  },
  {
    "path": "src/signed_area.cpp",
    "content": "#include <Rcpp.h>\nusing namespace Rcpp;\n\n// return signed area of a ring;\n// positive area indicates a counter clock-wise ring direction\n// https://en.wikipedia.org/wiki/Shoelace_formula\n\n// [[Rcpp::export(rng=false)]]\ndouble CPL_signed_area(NumericMatrix pts) {\n\tdouble sum = 0.0;\n\tdouble x0, x, y1, y2;\n\n\tif (pts.ncol() < 2)\n\t\tstop(\"need at least two columns in matrix\\n\"); // #nocov\n\n\tif (pts.nrow() <= 3)\n\t\treturn 0.0;\n\t\n\tx0 = pts(0, 0);\n\tfor (int i = 2; i < pts.nrow(); i++) {\n\t\tx =  pts(i-1, 0) - x0; \n\t\ty1 = pts(i,   1);\n\t\ty2 = pts(i-2, 1);\n\t\tsum += x * (y1 - y2);\n\t}\n    return sum / 2.0; \n}\n"
  },
  {
    "path": "src/stars.cpp",
    "content": "#include <cpl_port.h>\n#include <gdal.h>\n#include <gdal_priv.h>\n#include <gdal_rat.h>\n#include <ogr_api.h>\n#include <ogr_geometry.h>\n#include <ogr_srs_api.h>\n#include <cpl_string.h>\n\n#include <Rcpp.h>\n\n#include \"gdal.h\"\n#include \"gdal_read.h\"\n#include \"gdal_sf_pkg.h\"\n\nusing namespace Rcpp;\n\nCharacterVector get_meta_data(GDALDatasetH ds, CharacterVector domain_item) {\n\n\tCharacterVector ret;\n\tif (ds == NULL)\n\t\treturn NA_STRING;\n\tif (domain_item.size() == 0)\n\t\tret = charpp2CV(GDALGetMetadata(ds, NULL)); // #nocov\n\telse if (domain_item.size() == 1) {\n\t\tif (CharacterVector::is_na(domain_item[0])) {\n\t\t\t char **dl = GDALGetMetadataDomainList(ds);\n\t\t\t ret = charpp2CV(dl);\n\t\t\t CSLDestroy(dl);\n\t\t} else\n\t\t\t ret = charpp2CV(GDALGetMetadata(ds, domain_item[0]));\n\t} else if (domain_item.size() == 2) // domain and item // #nocov start\n\t\tret = CharacterVector::create(GDALGetMetadataItem(ds, domain_item[1], domain_item[0]));\n\telse\n\t\tret = NA_STRING; // #nocov end\n\treturn(ret);\n}\n\nList get_band_meta_data(GDALDataset *poDataset) {\n\tint n_bands = poDataset->GetRasterCount();\n\tList ret(n_bands);\n\tfor (int band = 1; band <= n_bands; band++) { // unlike x & y, band is 1-based\n\t\tGDALRasterBand *poBand = poDataset->GetRasterBand( band );\n\t\tret[band - 1] = charpp2CV(poBand->GetMetadata(NULL));\n\t}\n\treturn ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nCharacterVector CPL_get_metadata(CharacterVector obj, CharacterVector domain_item,\n\t\tCharacterVector options) {\n\n\tGDALDatasetH ds = GDALOpenEx(obj[0], GDAL_OF_RASTER | GDAL_OF_READONLY, NULL, NULL,\n\t\tcreate_options(options).data());\n\tCharacterVector ret = get_meta_data(ds, domain_item);\n\tif (ds != NULL)\n\t\tGDALClose(ds);\n\treturn ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nList CPL_get_crs(CharacterVector obj, CharacterVector options) {\n\tList ret(4);\n\tGDALDatasetH ds = GDALOpenEx(obj[0], GDAL_OF_RASTER | GDAL_OF_READONLY, NULL, NULL,\n\t\tcreate_options(options).data());\n\tif (ds == NULL)\n\t\treturn ret; // #nocov\n\n\tret(0) = GDALGetRasterCount(ds);\n\n\tret(1) = GDALGetProjectionRef(ds); // wkt\n\n\tdouble gt[6];\n\tGDALGetGeoTransform(ds, gt);\n\tNumericVector gt_r(6);\n\tfor (int i = 0; i < 6; i++)\n\t\tgt_r(i) = gt[i];\n\tret(2) = gt_r;\n\n\tdouble gt_inv[6];\n\tint retval = GDALInvGeoTransform(gt, gt_inv);\n\tNumericVector gt_r_inv(6);\n\tfor (int i = 0; i < 6; i++)\n\t\tgt_r_inv(i) = retval ? gt_inv[i] : NA_REAL;\n\tret(3) = gt_r_inv;\n\n\tret.attr(\"names\") = CharacterVector::create(\"nbands\", \"crs\", \"gt\", \"gt_inv\");\n\n\treturn ret;\n}\n// [[Rcpp::export(rng=false)]]\nNumericVector CPL_inv_geotransform(NumericVector gt_r) {\n\tif (gt_r.size() != 6)\n\t\tstop(\"wrong length geotransform\"); // #nocov\n\tdouble gt_inv[6], gt[6];\n\tfor (int i = 0; i < 6; i++)\n\t\tgt[i] = gt_r[i];\n\tint retval = GDALInvGeoTransform(gt, gt_inv);\n\tNumericVector gt_r_inv(6);\n\tfor (int i = 0; i < 6; i++)\n\t\tgt_r_inv(i) = retval ? gt_inv[i] : NA_REAL;\n\treturn gt_r_inv;\n}\n\nbool equals_na(double value, double na, GDALDataType dt) {\n\tif (ISNAN(value))\n\t\treturn true;\n\tif (dt == GDT_Float32)\n\t\treturn (float) value == (float) na;\n\telse\n\t\treturn value == na;\n}\n\n// formerly: stars/src/gdal.cpp\nNumericVector read_gdal_data(GDALDataset *poDataset,\n\t\t\tNumericVector nodatavalue,\n\t\t\tint nXOff,\n\t\t\tint nYOff,\n\t\t\tint nXSize,\n\t\t\tint nYSize,\n\t\t\tint nBufXSize,\n\t\t\tint nBufYSize,\n\t\t\tIntegerVector bands,\n\t\t\tGDALRasterIOExtraArg *resample\n\t\t) {\n\n\t// collapse x & y into rows, redim later:\n\tNumericVector vec( 1.0 * nBufXSize * nBufYSize * bands.size() );\n\t// floor returns double -> no integer overflow\n\n\t// read bands:\n\tif (poDataset->RasterIO( GF_Read,\n\t\t\tnXOff,\n\t\t\tnYOff,\n\t\t\tnXSize,\n\t\t\tnYSize,\n\t\t\tvec.begin(),\n\t\t\tnBufXSize,\n\t\t\tnBufYSize,\n\t\t\tGDT_Float64,\n\t\t\tbands.size(),\n\t\t\tbands.begin(),\n\t\t\t0,\n\t\t\t0,\n\t\t\t0,\n\t\t\tresample) == CE_Failure)\n\t\tstop(\"read failure\"); // #nocov\n\n\tCharacterVector units(bands.size());\n\t// scale && set NA:\n\tfor (int i = 0; i < bands.size(); i++) {\n\t\tint band = bands(i);\n\t\tGDALRasterBand *poBand = poDataset->GetRasterBand( band );\n\t\t// NumericVector nodatavalue = NumericVector::create(NA_REAL);\n\t\t// int success = 0,\n\t\tint has_scale = 0, has_offset = 0;\n\t\tdouble offset = 0.0, scale = 1.0;\n\t\t// poBand->GetNoDataValue(&success);\n\t\t// if (success)\n\t\t// \tnodatavalue = poBand->GetNoDataValue(NULL); // #nocov\n\t\tpoBand->GetScale(&has_scale);\n\t\tif (has_scale)\n\t\t\tscale = poBand->GetScale(NULL);\n\t\tpoBand->GetOffset(&has_offset);\n\t\tif (has_offset)\n\t\t\toffset = poBand->GetOffset(NULL);\n\t\tunits[i] = poBand->GetUnitType();\n\t\t// if (! NumericVector::is_na(nodatavalue[0]) || has_offset || has_scale) {\n\t\t// outcommented because of NaN handling, https://github.com/r-spatial/stars/issues/333\n\t\tfor (R_xlen_t j = i * (((R_xlen_t) nBufXSize) * nBufYSize); // start of band i\n\t\t\t\tj < (i + 1) * (((R_xlen_t) nBufXSize) * nBufYSize); // end of band i\n\t\t\t\tj++) {\n\t\t\tif (equals_na(vec[j], nodatavalue[0], poBand->GetRasterDataType()))\n\t\t\t\tvec[j] = NA_REAL; // #nocov\n\t\t\telse\n\t\t\t\tvec[j] = (vec[j] * scale) + offset;\n\t\t}\n\t\t// }\n\t\tcheckUserInterrupt();\n\t}\n\tvec.attr(\"units\") = units;\n\n\t// set dim attr:\n\tIntegerVector dims;\n\tif (bands.size() == 1) { // single band:\n\t\tdims = IntegerVector::create(nBufXSize, nBufYSize);\n\t\tdims.attr(\"names\") = CharacterVector::create(\"x\", \"y\");\n\t} else { // multiple bands:\n\t\tdims = IntegerVector::create(nBufXSize, nBufYSize, bands.size()); // #nocov\n\t\tdims.attr(\"names\") = CharacterVector::create(\"x\", \"y\", \"band\"); // #nocov\n\t}\n\tvec.attr(\"dim\") = dims;\n\treturn vec;\n}\n\nint get_from_list(List lst, const char *name, int otherwise) {\n\tif (lst.containsElementNamed(name) && lst[name] != R_NilValue) {\n\t\tIntegerVector ret = lst[name]; // #nocov\n\t\treturn(ret[0]);                // #nocov\n\t} else\n\t\treturn(otherwise);\n}\n\nNumericMatrix get_color_table(GDALColorTable *tbl) {\n\tint n = tbl->GetColorEntryCount();\n\tNumericMatrix t(n, 4);\n\tfor (int i = 0; i < n; i++) {\n\t\tconst GDALColorEntry *ce = tbl->GetColorEntry(i);\n\t\tt(i, 0) = ce->c1;\n\t\tt(i, 1) = ce->c2;\n\t\tt(i, 2) = ce->c3;\n\t\tt(i, 3) = ce->c4;\n\t}\n\tint i = (int) tbl->GetPaletteInterpretation();\n\tt.attr(\"interpretation\") = IntegerVector::create(i);\n\treturn t;\n}\n\nList get_cat(char **cat) {\n\tif (cat == NULL)\n\t\treturn(List::create());\n\n\tint n = 0;\n\tfor (n = 0; cat[n] != NULL; n++)\n\t\t; // n is number of categories\n\n\tList t(1);\n\tCharacterVector col(n);\n\tIntegerVector row_names(n);\n\tfor (int i = 0; i < n; i++) {\n\t\tcol(i) = cat[i];\n\t\trow_names(i) = i+1;\n\t}\n\tt(0) = col;\n\tt.attr(\"names\") = CharacterVector::create(\"category\");\n\tt.attr(\"row.names\") = row_names;\n\tt.attr(\"class\") = CharacterVector::create(\"data.frame\");\n\treturn t;\n}\n\nList get_rat(GDALRasterAttributeTable *tbl) {\n\n\tif (tbl == NULL)\n\t\treturn(List::create());\n\n\tList t(tbl->GetColumnCount());\n\tList names(tbl->GetColumnCount());\n\tfor (int i = 0; i < tbl->GetColumnCount(); i++) {\n\t\tswitch (tbl->GetTypeOfCol(i)) {\n\t\t\tcase GFT_Integer: {\n\t\t\t\t\tIntegerVector col(tbl->GetRowCount());\n\t\t\t\t\tfor (int j = 0; j < tbl->GetRowCount(); j++)\n\t\t\t\t\t\tcol(j) = tbl->GetValueAsInt(j, i);\n\t\t\t\t\tt(i) = col;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase GFT_Real: {\n\t\t\t\t\tNumericVector col(tbl->GetRowCount());\n\t\t\t\t\tfor (int j = 0; j < tbl->GetRowCount(); j++)\n\t\t\t\t\t\tcol(j) = tbl->GetValueAsDouble(j, i);\n\t\t\t\t\tt(i) = col;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase GFT_String: {\n\t\t\t\t\tCharacterVector col(tbl->GetRowCount());\n\t\t\t\t\tfor (int j = 0; j < tbl->GetRowCount(); j++)\n\t\t\t\t\t\tcol(j) = tbl->GetValueAsString(j, i);\n\t\t\t\t\tt(i) = col;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tstop(\"unknown column type in raster attribute table\");\n\t\t}\n\t\tnames(i) = tbl->GetNameOfCol(i);\n\t}\n\tIntegerVector row_names(tbl->GetRowCount());\n\tfor (int i = 0; i < tbl->GetRowCount(); i++)\n\t\trow_names(i) = i+1;\n\tt.attr(\"names\") = names;\n\tt.attr(\"row.names\") = row_names;\n\tt.attr(\"class\") = CharacterVector::create(\"data.frame\");\n\treturn t;\n}\n\n// [[Rcpp::export(rng=false)]]\nList CPL_read_gdal(CharacterVector fname, CharacterVector options, CharacterVector driver,\n\t\tbool read_data, NumericVector NA_value, List RasterIO_parameters, double max_cells) {\n// reads and returns data set metadata, and adds data array if read_data is true, or less \n// than max_cells are to be read\n\tGDALDataset *poDataset = (GDALDataset *) GDALOpenEx(fname[0], GA_ReadOnly,\n\t\tdriver.size() ? create_options(driver).data() : NULL,\n\t\toptions.size() ? create_options(options).data() : NULL,\n\t\tNULL);\n\tif (poDataset == NULL) {\n\t\tRcout << \"trying to read file: \" << fname[0] << std::endl; // #nocov\n\t\tstop(\"file not found\"); // #nocov\n\t}\n\n\tCharacterVector Driver = CharacterVector::create(\n\t\tpoDataset->GetDriver()->GetDescription(),\n\t\tpoDataset->GetDriver()->GetMetadataItem( GDAL_DMD_LONGNAME ));\n\n\t/*\n\tif (poDataset->GetRasterCount() == 0)\n\t\tstop(\"zero bands\"); -->> this indicates there are (only) subdatasets\n\t*/\n\n\t// geotransform:\n\tdouble adfGeoTransform[6];\n\tCPLErr err = poDataset->GetGeoTransform( adfGeoTransform );\n\t// return the default geotransform as per the\n\t// GetGeoTransform() doc in classGDALDataset\n\tNumericVector geotransform = NumericVector::create(\n\t\terr == CE_None ? adfGeoTransform[0] : 0,\n\t\terr == CE_None ? adfGeoTransform[1] : 1,\n\t\terr == CE_None ? adfGeoTransform[2] : 0,\n\t\terr == CE_None ? adfGeoTransform[3] : 0,\n\t\terr == CE_None ? adfGeoTransform[4] : 0,\n\t\terr == CE_None ? adfGeoTransform[5] : 1); // see https://github.com/r-spatial/sf/pull/1307\n\tint default_geotransform = 0;\n\tif (err != CE_None) {\n\t\tdefault_geotransform = 1;\n\t}\n\tbool geo_transform_set = (err == CE_None);\n\n\t// CRS, projection:\n#if GDAL_VERSION_NUM >= 3000000\n\tconst OGRSpatialReference *sr = poDataset->GetSpatialRef();\n\t// sr = handle_axis_order(sr); -- should be done by GDAL; xy\n\tRcpp::List crs = create_crs(sr, true);\n#else\n\tconst char *wkt_gdal = poDataset->GetProjectionRef();\n\tCharacterVector wkt = NA_STRING;\n\tif (*wkt_gdal != '\\0')\n\t\twkt = CharacterVector::create(wkt_gdal);\n#endif\n\n\tGDALRasterBand *poBand = NULL;\n\tNumericVector nodatavalue = NumericVector::create(NA_REAL);\n\n\tif (poDataset->GetRasterCount()) {\n\t\tpoBand = poDataset->GetRasterBand( 1 );\n\t\tint set = 0;\n\t\tpoBand->GetNoDataValue(&set);\n\t\tif (NA_value.size() > 0 && !NumericVector::is_na(NA_value[0])) {\n\t\t\tif (set)\n\t\t\t\twarning(\"NoDataValue of band is ignored\"); // #nocov\n\t\t\tnodatavalue[0] = NA_value[0];\n\t\t} else if (set)\n\t\t\tnodatavalue[0] = poBand->GetNoDataValue(NULL); // #nocov\n\t}\n\n\t// bands:\n\tIntegerVector bands;\n\tif (RasterIO_parameters.containsElementNamed(\"bands\"))\n\t\tbands = RasterIO_parameters[\"bands\"]; // #nocov\n\telse {\n\t\tbands = IntegerVector(poDataset->GetRasterCount());\n\t\tfor (int j = 0; j < bands.size(); j++)\n\t\t\tbands(j) = j + 1; // bands is 1-based\n\t}\n\n\t// get color table, attribute table, and min/max values:\n\tList colorTables(bands.size());\n\tList attributeTables(bands.size());\n\tCharacterVector descriptions(bands.size());\n\tNumericMatrix ranges(bands.size(), 4);\n\tIntegerMatrix blocksizes(bands.size(), 2);\n\tIntegerVector colorInterp(bands.size());\n\tfor (int i = 0; i < bands.size(); i++) {\n\t\tif ((poBand = poDataset->GetRasterBand(bands(i))) == NULL)\n\t\t\tstop(\"trying to read a band that is not present\");\n\t\tconst char *md = poBand->GetMetadataItem(\"BANDNAME\", NULL);\n\t\tif (md == NULL)\n\t\t\tdescriptions(i) = poBand->GetDescription();\n\t\telse\n\t\t\tdescriptions(i) = md;\n\n\t\tif (poBand->GetColorTable() != NULL)\n\t\t\tcolorTables(i) = get_color_table(poBand->GetColorTable());\n\t\tif (poBand->GetCategoryNames() != NULL)\n\t\t\tattributeTables(i) = get_cat(poBand->GetCategoryNames());\n\t\telse\n\t\t\tattributeTables(i) = get_rat(poBand->GetDefaultRAT());\n\t\tint set = 1;\n\t\tranges(i, 0) = poBand->GetMinimum(&set);\n\t\tranges(i, 1) = (double) set;\n\t\tranges(i, 2) = poBand->GetMaximum(&set);\n\t\tranges(i, 3) = (double) set;\n\t\tint nBlockXSize = 0;\n\t\tint nBlockYSize = 0;\n\t\tpoBand->GetBlockSize(&nBlockXSize, &nBlockYSize);\n\t\tblocksizes(i, 0) = nBlockXSize;\n\t\tblocksizes(i, 1) = nBlockYSize;\n\t\tcolorInterp(i) = (int) poBand->GetColorInterpretation();\n\t}\n\n\t// get metadata items:\n\tCharacterVector items = get_meta_data((GDALDatasetH) poDataset, NA_STRING);\n\tCharacterVector sub = NA_STRING;\n\tfor (int i = 0; i < items.size(); i++) {\n\t\t// Rcpp::Rcout << items[i] << std::endl;\n\t\tif (items[i] == \"SUBDATASETS\")\n\t\t\tsub = get_meta_data(poDataset, \"SUBDATASETS\"); // #nocov\n\t}\n\n\t// image dimension:\n\tint nXOff = get_from_list(RasterIO_parameters, \"nXOff\", 1) - 1;\n\tint nYOff = get_from_list(RasterIO_parameters, \"nYOff\", 1) - 1;\n\tint nXSize = get_from_list(RasterIO_parameters, \"nXSize\", poDataset->GetRasterXSize() - nXOff);\n\tint nYSize = get_from_list(RasterIO_parameters, \"nYSize\", poDataset->GetRasterYSize() - nYOff);\n\tint nBufXSize = get_from_list(RasterIO_parameters, \"nBufXSize\", nXSize);\n\tint nBufYSize = get_from_list(RasterIO_parameters, \"nBufYSize\", nYSize);\n\n\tif (max_cells > 0) \n\t\tread_data = (bands.size() * nBufXSize * nBufYSize) < max_cells;\n\n\t// resampling method:\n\tGDALRasterIOExtraArg resample;\n\tINIT_RASTERIO_EXTRA_ARG(resample);\n\n\tif (RasterIO_parameters.containsElementNamed(\"resample\")) { // #nocov start\n\t\tCharacterVector res = RasterIO_parameters[\"resample\"];\n\t\tif (res[0] == \"bilinear\")\n\t\t\tresample.eResampleAlg = GRIORA_Bilinear;\n\t\telse if (res[0] == \"cubic\")\n\t\t\tresample.eResampleAlg = GRIORA_Cubic;\n\t\telse if (res[0] == \"cubic_spline\")\n\t\t\tresample.eResampleAlg = GRIORA_CubicSpline;\n\t\telse if (res[0] == \"lanczos\")\n\t\t\tresample.eResampleAlg = GRIORA_Lanczos;\n\t\telse if (res[0] == \"average\")\n\t\t\tresample.eResampleAlg = GRIORA_Average;\n\t\telse if (res[0] == \"mode\")\n\t\t\tresample.eResampleAlg = GRIORA_Mode;\n\t\telse if (res[0] == \"Gauss\")\n\t\t\tresample.eResampleAlg = GRIORA_Gauss;\n\t\telse if (res[0] == \"nearest_neighbour\")\n\t\t\tresample.eResampleAlg = GRIORA_NearestNeighbour;\n\t\telse stop(\"unknown method for resample\"); // #nocov end\n\t}\n\n\tList ReturnList = List::create(\n\t\t_[\"filename\"] = fname,\n\t\t_[\"driver\"] = Driver,\n\t\t_[\"cols\"] = NumericVector::create(nXOff + 1, nXOff + nBufXSize),\n\t\t_[\"rows\"] = NumericVector::create(nYOff + 1, nYOff + nBufYSize),\n\t\t_[\"bands\"] = bands,\n#if GDAL_VERSION_NUM >= 3000000\n\t\t_[\"crs\"] = crs,\n#else\n\t\t_[\"proj_wkt\"] = wkt,\n#endif\n\t\t_[\"geotransform\"] = geotransform,\n\t\t_[\"datatype\"] =\tpoBand != NULL ?\n\t\t\tGDALGetDataTypeName(poBand->GetRasterDataType()) :\n\t\t\tCharacterVector::create(NA_STRING),\n\t\t_[\"sub\"] = sub,\n\t\t_[\"meta\"] = get_meta_data(poDataset, CharacterVector::create()),\n\t\t_[\"band_meta\"] = get_band_meta_data(poDataset),\n\t\t_[\"attribute_tables\"] = attributeTables,\n\t\t_[\"color_tables\"] = colorTables,\n\t\t_[\"ranges\"] = ranges,\n\t\t_[\"blocksizes\"] = blocksizes,\n\t\t_[\"descriptions\"] = descriptions,\n\t\t_[\"default_geotransform\"] = default_geotransform,\n\t\t_[\"proxy\"] = LogicalVector::create(!read_data),\n\t\t_[\"colorInterp\"] = colorInterp\n\t);\n\tif (read_data) {\n\t\tReturnList.attr(\"data\") = read_gdal_data(poDataset, nodatavalue, nXOff, nYOff,\n\t\t\tnXSize, nYSize, nBufXSize, nBufYSize, bands, &resample);\n\t}\n\tGDALClose(poDataset);\n\n\t// adjust geotransform & offset if Buf?Size was set:\n\tif ((nXSize != nBufXSize || nYSize != nBufYSize) && geo_transform_set) { // #nocov start\n\t\tif (geotransform[2] != 0.0 || geotransform[4] != 0.0)\n\t\t\tstop(\"reading affine grids with resampling would result in a wrong geotransform; please file an issue\"); // #nocov\n\t\tdouble ratio_x = (1.0 * nXSize) / nBufXSize;\n\t\tdouble ratio_y = (1.0 * nYSize) / nBufYSize;\n\t\tgeotransform[1] = geotransform[1] * ratio_x;\n\t\tgeotransform[5] = geotransform[5] * ratio_y;\n\t\tReturnList[\"geotransform\"] = geotransform;\n\t\tnXOff = (int) (nXOff / ratio_x);\n\t\tnYOff = (int) (nYOff / ratio_y);\n\t\tReturnList[\"cols\"] = NumericVector::create(nXOff + 1, nXOff + nBufXSize);\n\t\tReturnList[\"rows\"] = NumericVector::create(nYOff + 1, nYOff + nBufYSize);\n\t} // #nocov end\n\n\treturn ReturnList;\n}\n\n// [[Rcpp::export(rng=false)]]\nvoid CPL_write_gdal(NumericMatrix x, CharacterVector fname, CharacterVector driver,\n\t\tCharacterVector options, CharacterVector Type, IntegerVector dims, IntegerVector from,\n\t\tNumericVector gt, CharacterVector p4s, NumericVector na_val, NumericVector scale_offset,\n\t\tbool create = true, bool only_create = false) {\n\n\t// figure out driver:\n\tif (driver.length() != 1)\n\t\tstop(\"driver should have length one\"); // #nocov\n\tGDALDriver *poDriver;\n\tif ((poDriver = GetGDALDriverManager()->GetDriverByName(driver[0])) == NULL)\n\t\tstop(\"driver not recognized.\"); // #nocov\n\n\t// can this driver Create()?\n\tCSLConstList papszMetadata = poDriver->GetMetadata();\n\tif (!CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATE, FALSE ) && !CSLFetchBoolean( papszMetadata, GDAL_DCAP_CREATECOPY, FALSE ) )\n\t\tstop(\"driver does not support Create() or CreateCopy() method.\"); // #nocov\n\n\t// figure out eType:\n\tGDALDataType eType = GDT_Unknown;\n\tif (Type.length() != 1)\n\t\tstop(\"Type should have length 1\"); // #nocov\n\tif (Type[0] == \"Byte\")\n\t\teType = GDT_Byte; // #nocov\n#if GDAL_VERSION_NUM >= 3070000\n\telse if (Type[0] == \"Int8\")\n\t\teType = GDT_Int8; // #nocov\n#endif\n\telse if (Type[0] == \"UInt16\")\n\t\teType = GDT_UInt16; // #nocov\n\telse if (Type[0] == \"Int16\")\n\t\teType = GDT_Int16; // #nocov\n\telse if (Type[0] == \"UInt32\")\n\t\teType = GDT_UInt32; // #nocov\n\telse if (Type[0] == \"Int16\")\n\t\teType = GDT_Int32; // #nocov\n#if GDAL_VERSION_NUM >= 3110000\n\telse if (Type[0] == \"Float16\")\n\t\teType = GDT_Float16; // #nocov\n#endif\n\telse if (Type[0] == \"Float32\")\n\t\teType = GDT_Float32;\n\telse if (Type[0] == \"Float64\") // #nocov\n\t\teType = GDT_Float64; // #nocov\n\telse\n\t\tstop(\"unknown data type\"); // #nocov\n\n\t// sanity checks:\n\tif (fname.length() != 1)\n\t\tstop(\"fname should have length one\"); // #nocov\n\tif (dims.length() != 3)\n\t\tstop(\"dims should have length three\"); // #nocov\n\tif (from.length() != 2)\n\t\tstop(\"from should have length two\"); // #nocov\n\tif (na_val.length() != 1)\n\t\tstop(\"na_val should have length 1\"); // #nocov\n\tif (scale_offset.size() != 2)\n\t\tstop(\"scale_offset should have length 2\");\n\tbool set_scale_offset = (scale_offset[0] != 1.0 || scale_offset[1] != 0.0);\n\n\t// create dataset:\n\tGDALDataset *poDstDS;\n\tbool createCopy = false;\n\tif (create) {\n\t\tif (from[0] != 0 || from[1] != 0)\n\t\t\tstop(\"from values should be zero when creating a dataset\"); // #nocov\n\n\t\tif (poDriver->GetMetadataItem(GDAL_DCAP_CREATE) == NULL && \n\t\t\t\t\t\tpoDriver->GetMetadataItem(GDAL_DCAP_CREATECOPY) != NULL) {\n\t\t\tcreateCopy = true;\n\t\t\tGDALDriver *memDriver = GetGDALDriverManager()->GetDriverByName(\"MEM\");\n\t\t\tif ((poDstDS = memDriver->Create(fname[0], dims[0], dims[1], dims[2], eType, NULL)) == NULL)\n\t\t\t\tstop(\"cannot create copy in memory\"); // #nocov\n\t\t} else if ((poDstDS = poDriver->Create( fname[0], dims[0], dims[1], dims[2], eType,\n\t\t\t\tcreate_options(options).data())) == NULL)\n\t\t\tstop(\"creating dataset failed\"); // #nocov\n\n\t\t// set geotransform:\n\t\tdouble adfGeoTransform[6];\n\t\tif (gt.length() != 6)\n\t\t\tstop(\"gt should have length 6\"); // #nocov\n\t\tfor (int i = 0; i < gt.length(); i++)\n\t\t\tadfGeoTransform[i] = gt[i];\n\t\tif (poDstDS->SetGeoTransform( adfGeoTransform ) != CE_None)\n\t\t\twarning(\"SetGeoTransform() returned an error: not available?\"); // #nocov\n\n\t\t// CRS:\n\t\tif (p4s.length() != 1)\n\t\t\tstop(\"p4s should have length one\"); // #nocov\n\t\tif (p4s[0] != NA_STRING) {\n\t\t\tOGRSpatialReference oSRS;\n\t\t\toSRS.SetFromUserInput((const char *) p4s[0]); // handles wkt too\n#if GDAL_VERSION_NUM >= 3000000\n\t\t\tpoDstDS->SetSpatialRef(&oSRS);\n#else\n\t\t\tchar *pszSRS_WKT = NULL;\n\t\t\toSRS.exportToWkt( &pszSRS_WKT );\n\t\t\tif (poDstDS->SetProjection( pszSRS_WKT ) != CE_None)\n\t\t\t\tstop(\"SetProjection: error\"); // #nocov\n\t\t\tCPLFree( pszSRS_WKT );\n#endif\n\t\t}\n\n\t\t// set band NA's\n\t\tif (! NumericVector::is_na(na_val[0])) {\n\t\t\tfor (int band = 1; band <= dims(2); band++) { // unlike x & y, band is 1-based\n\t\t\t\tGDALRasterBand *poBand = poDstDS->GetRasterBand( band );\n\t\t\t\tif (poBand->SetNoDataValue(na_val[0]) != CE_None) {\n\t\t\t\t\twarning(\"SetNoDataValue not supported by driver\"); // #nocov\n\t\t\t\t\tbreak; // #nocov\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\t// set scale_offset\n\t\tif (set_scale_offset) {\n\t\t\tfor (int band = 1; band <= dims(2); band++) { // unlike x & y, band is 1-based\n\t\t\t\tGDALRasterBand *poBand = poDstDS->GetRasterBand( band );\n\t\t\t\tif (poBand->SetScale(scale_offset[0]) != CE_None ||\n\t\t\t\t\t\tpoBand->SetOffset(scale_offset[1]) != CE_None)\n\t\t\t\t\twarning(\"writing scale and/or offset failed (not supported by driver)\"); // #nocov\n\t\t\t}\n\t\t}\n\t\t// set descriptions:\n\t\tif (x.attr(\"descriptions\") != R_NilValue) {\n\t\t\tRcpp::CharacterVector descriptions = x.attr(\"descriptions\");\n\t\t\tfor (int band = 1; band <= dims(2); band++) {\n\t\t\t\tGDALRasterBand *poBand = poDstDS->GetRasterBand( band );\n\t\t\t\tpoBand->SetDescription(descriptions(band-1));\n\t\t\t}\n\t\t}\n\n\t\t// write factor levels to CategoryNames:\n\t\tif (x.attr(\"levels\") != R_NilValue) {\n\t\t\tRcpp::CharacterVector levels = x.attr(\"levels\");\n\t\t\tfor (int band = 1; band <= dims(2); band++) {\n\t\t\t\tGDALRasterBand *poBand = poDstDS->GetRasterBand( band );\n\t\t\t\tif (poBand->SetCategoryNames(create_options(levels).data()) != CE_None)\n\t\t\t\t\twarning(\"error writing factor levels to raster band\");\n\t\t\t}\n\t\t}\n\t\t// write color table:\n\t\tif (x.attr(\"rgba\") != R_NilValue) {\n\t\t\tRcpp::NumericMatrix co = x.attr(\"rgba\"); // r g b alpha in columns; levels in rows\n\t\t\tGDALColorTable ct = GDALColorTable(GPI_RGB);\n\t\t\tGDALColorEntry ce;\n\t\t\tfor (int i = 0; i < co.nrow(); i++) {\n\t\t\t\tce.c1 = co(i, 0);\n\t\t\t\tce.c2 = co(i, 1);\n\t\t\t\tce.c3 = co(i, 2);\n\t\t\t\tce.c4 = co(i, 3);\n\t\t\t\tct.SetColorEntry(i, &ce);\n\t\t\t}\n\t\t\tGDALRasterBand *poBand = poDstDS->GetRasterBand( 1 ); // can only set CT for band 1\n\t\t\tif (poBand->SetColorTable(&ct) != CE_None)\n\t\t\t\twarning(\"error writing color table to raster band\");\n\t\t}\n\n\t} else { // no create, update:\n\t\tif ((poDstDS = (GDALDataset *) GDALOpen(fname[0], GA_Update)) == NULL) // #nocov\n\t\t\tstop(\"updating dataset failed\"); // #nocov\n\t}\n\n\tif (! only_create) {\n\t\tif (! NumericVector::is_na(na_val[0])) { // replace R's NA's with GDAL write NA value\n\t\t\tfor (int i = 0; i < x.ncol(); i++) {\n\t\t\t\tNumericVector nv = x(_, i);\n\t\t\t\tfor (int j = 0; j < x.nrow(); j++) {\n\t\t\t\t\tif (NumericVector::is_na(nv[j]))\n\t\t\t\t\t\tnv[j] = na_val[0];\n\t\t\t\t}\n\t\t\t\tx(_, i) = nv;\n\t\t\t}\n\t\t\tcheckUserInterrupt();\n\t\t}\n\t\tif (set_scale_offset) {\n\t\t\tfor (int i = 0; i < x.ncol(); i++) {\n\t\t\t\tNumericVector nv = x(_, i);\n\t\t\t\tfor (int j = 0; j < x.nrow(); j++)\n\t\t\t\t\tnv[j] = (nv[j] - scale_offset[1]) / scale_offset[0]; // raw = (units - offset) / scale\n\t\t\t\tx(_, i) = nv;\n\t\t\t}\n\t\t}\n\t\t// write values:\n\t\t// write the whole lot:\n\t\tif (poDstDS->RasterIO(GF_Write, from[0], from[1], dims[0] - from[0], dims[1] - from[1],\n\t\t\t\tx.begin(), dims[0] - from[0], dims[1] - from[1], GDT_Float64,\n\t\t\t\tdims[2], NULL, 0, 0, 0, NULL) == CE_Failure)\n\t\t\tstop(\"write failure\"); // #nocov\n\n\t\tif (createCopy) { // so far in memory, still need to write to disk:\n\t\t\toptions.push_back(\"APPEND_SUBDATASET=YES\");\n\t\t\tGDALDataset *poCopyDS;\n\t\t\tif ((poCopyDS = poDriver->CreateCopy(fname[0], poDstDS, FALSE, \n\t\t\t\t\t\t\t\t\t\tcreate_options(options).data(), NULL, NULL)) == NULL)\n\t\t\t\tstop(\"cannot CreateCopy from memory dataset\");\n\t\t\tGDALClose(poCopyDS);\n\t\t}\n\t}\n\n\t/* close: */\n\tGDALClose( (GDALDatasetH) poDstDS );\n\treturn;\n}\n\ndouble get_bilinear(GDALRasterBand *poBand, double Pixel, double Line,\n\t\t\t\t\t\tint iPixel, int iLine, double RasterXSize, double RasterYSize,\n\t\t\t\t\t\tint na_set, double na_value) {\n\n\tdouble pixels[4];\n\tdouble dY  = Line - iLine; // [0, 1) over a raster cell\n\tdouble dX  = Pixel - iPixel; // [0, 1) over a raster cell\n\tdouble eps = 1.0e-13;\n\tif ((dY < 0.5 && iLine > 0) || (iLine == RasterYSize - 1)) { // where to start reading\n\t\tiLine -= 1;\n\t\tdY += 1.0;\n\t}\n\tif ((dX < 0.5 && iPixel > 0) || (iPixel == RasterXSize - 1)) {\n\t\tiPixel -= 1;\n\t\tdX += 1.0;\n\t}\n\n\t// x:\n\tif (Pixel < (0.5 - eps)) // border:\n\t\tdX = 0.0;\n\telse if (Pixel > (RasterXSize - 0.5 + eps))\n\t\tdX = 1.0;\n\telse if (dX < (0.5 - eps)) // shift to pixel center:\n\t\tdX += 0.5;\n\telse\n\t\tdX -= 0.5;\n\n\t// y:\n\tif (Line < (0.5 - eps))\n\t\tdY = 0.0;\n\telse if (Line > (RasterYSize - 0.5 + eps))\n\t\tdY = 1.0;\n\telse if (dY < (0.5 - eps))\n\t\tdY += 0.5;\n\telse\n\t\tdY -= 0.5;\n\n\t// read:\n\tif (poBand->RasterIO(GF_Read, iPixel, iLine, 2, 2,\n\t\t\t(void *) pixels, 2, 2, GDT_CFloat64, sizeof(double), 0, NULL) != CE_None)\n\t\tstop(\"Error reading!\");\n\t// Rprintf(\"px[%g (%g) %g (%g) %g (%g) %g (%g)] dY: %g dX: %g iLine: %d iPixel: %d Line: %g Pixel :%g\\n\", pixels[0], (1-dX)*(1-dY), pixels[1], dX * (1-dY), pixels[2], (1-dX) * dY, pixels[3], dX * dY, dY, dX, iLine, iPixel, Line, Pixel);\n\t//\n\t// f(0,0): pixels[0], f(1,0): pixels[1], f(0,1): pixels[2], f(1,1): pixels[3]\n\tif (na_set && (pixels[0] == na_value || pixels[1] == na_value ||\n\t\t\tpixels[2] == na_value || pixels[3] == na_value))\n\t\treturn na_value;\n\telse // https://en.wikipedia.org/wiki/Bilinear_interpolation#Unit_square\n\t\treturn\tpixels[0] * (1-dX) * (1-dY) +\n\t\t\t\tpixels[1] * dX     * (1-dY) +\n\t\t\t\tpixels[2] * (1-dX) * dY +\n\t\t\t\tpixels[3] * dX     * dY;\n}\n\n// [[Rcpp::export(rng=false)]]\nNumericMatrix CPL_extract(CharacterVector input, NumericMatrix xy, CharacterVector interpolate) {\n\t// mostly taken from gdal/apps/gdallocationinfo.cpp\n\n\tGDALDataset *poDataset = (GDALDataset *) GDALOpenEx(input[0], GA_ReadOnly,\n\t\tNULL, NULL, NULL);\n\tif (poDataset == NULL) {\n\t\tRcout << \"trying to read file: \" << input[0] << std::endl; // #nocov\n\t\tstop(\"file not found\"); // #nocov\n\t}\n\n\tNumericMatrix ret(xy.nrow(), poDataset->GetRasterCount());\n\tint xsize = poDataset->GetRasterXSize();\n\tint ysize = poDataset->GetRasterYSize();\n\tGDALRIOResampleAlg RA;\n\tif (interpolate[0] == \"nearest\")\n\t\tRA = GRIORA_NearestNeighbour;\n\telse if (interpolate[0] == \"bilinear\")\n\t\tRA = GRIORA_Bilinear;\n\telse if (interpolate[0] == \"cubic\")\n\t\tRA = GRIORA_Cubic;\n\telse if (interpolate[0] == \"cubicspline\")\n\t\tRA = GRIORA_CubicSpline;\n\telse\n\t\tstop(\"interpolation method not supported\"); // #nocov\n\n\tdouble gt[6];\n\tint n_err = 0;\n\tpoDataset->GetGeoTransform(gt);\n\tdouble gt_inv[6];\n\t// int retval = GDALInvGeoTransform(gt, gt_inv);\n\tif (! GDALInvGeoTransform(gt, gt_inv))\n\t\tstop(\"geotransform not invertible\");\n\n\tfor (int j = 0; j < poDataset->GetRasterCount(); j++) {\n\t\tGDALRasterBand *poBand = poDataset->GetRasterBand(j+1);\n\t\tint bSuccess;\n\t\tdouble dfOffset = poBand->GetOffset(&bSuccess);\n\t\tdouble dfScale  = poBand->GetScale(&bSuccess);\n\t\tdouble nodata = NA_REAL;\n\t\tint nodata_set = 0;\n\t\tpoBand->GetNoDataValue(&nodata_set);\n\t\tif (nodata_set)\n\t\t\tnodata = poBand->GetNoDataValue(NULL);\n\t\tfor (int i = 0; i < xy.nrow(); i++) {\n\t\t\tdouble dfGeoX = xy(i, 0);\n\t\t\tdouble dfGeoY = xy(i, 1);\n\t\t\tdouble Pixel = gt_inv[0] + gt_inv[1] * dfGeoX + gt_inv[2] * dfGeoY;\n\t\t\tdouble Line  = gt_inv[3] + gt_inv[4] * dfGeoX + gt_inv[5] * dfGeoY;\n\t\t\tint iPixel = static_cast<int>(floor( Pixel ));\n\t\t\tint iLine  = static_cast<int>(floor( Line ));\n\t\t\tdouble pixel;\n\t\t\tif (iPixel < 0 || iLine < 0 || iPixel >= xsize || iLine >= ysize) // outside bbox:\n\t\t\t\tpixel = NA_REAL;\n\t\t\telse { // read pixel:\n#if GDAL_VERSION_NUM >= 3100000\n\t\t\t\tif (poBand->InterpolateAtPoint(Pixel, Line, RA, &pixel, nullptr) != CE_None)\n\t\t\t\t\t\t// tbd: handle GRIORA_Cubic, GRIORA_CubicSpline\n\t\t\t\t\tn_err += 1;\n#else\n\t\t\t\tif (RA == GRIORA_Cubic || RA == GRIORA_CubicSpline)\n\t\t\t\t\tstop(\"cubic or cubicspline requires GDAL >= 3.10.0\");\n\t\t\t\tif (RA == GRIORA_Bilinear)\n\t\t\t\t\tpixel = get_bilinear(poBand, Pixel, Line, iPixel, iLine,\n\t\t\t\t\t\txsize, ysize, nodata_set, nodata);\n\t\t\t\telse if (poBand->RasterIO(GF_Read, iPixel, iLine, 1, 1,\n\t\t\t\t\t\t&pixel, 1, 1, GDT_CFloat64, 0, 0, NULL) != CE_None)\n\t\t\t\t\tstop(\"Error reading!\");\n#endif\n\t\t\t\tif (nodata_set && pixel == nodata)\n\t\t\t\t\tpixel = NA_REAL;\n\t\t\t\telse if (dfOffset != 0.0 || dfScale != 1.0)\n\t\t\t\t\tpixel = pixel * dfScale + dfOffset;\n\t\t\t}\n\t\t\tret(i, j) = pixel;\n\t\t}\n\t}\n\tif (n_err > 0)\n\t\tRcout << n_err << \" error(s) in InterpolateAtPoint()\" << std::endl; // #nocov\n\tGDALClose(poDataset);\n\treturn ret;\n}\n\n// [[Rcpp::export(rng=false)]]\nvoid CPL_create(CharacterVector file, IntegerVector nxy, NumericVector value, CharacterVector wkt,\n\t\t\t\tNumericVector xlim, NumericVector ylim) {\n//\n// modified from gdal/apps/gdal_create.cpp:\n//\n\tint nPixels = nxy[0], nLines = nxy[1];\n\tGDALDatasetH hDS = GDALCreate(GDALGetDriverByName(\"GTiff\"),\n                                   file[0], nPixels, nLines,\n                                   1, GDT_Byte, NULL);\n\tOGRSpatialReference oSRS;\n#if GDAL_VERSION_NUM >= 2050000\n\toSRS.SetAxisMappingStrategy(OAMS_TRADITIONAL_GIS_ORDER);\n#endif\n\tif (oSRS.SetFromUserInput( wkt[0] ) != OGRERR_NONE) {\n\t\tCPLError(CE_Failure, CPLE_AppDefined, \"Failed to process SRS definition\");\n\t\tstop(\"CPL_create failed\");\n\t}\n\tchar* pszSRS = nullptr;\n\toSRS.exportToWkt( &pszSRS );\n\tif( GDALSetProjection(hDS, pszSRS) != CE_None ) {\n\t\tCPLFree(pszSRS);\n\t\tGDALClose(hDS);\n\t\tstop(\"CPL_create failed\");\n\t}\n\tdouble adfGeoTransform[6];\n\tadfGeoTransform[0] = xlim[0];\n\tadfGeoTransform[1] = (xlim[1] - xlim[0]) / nPixels;\n\tadfGeoTransform[2] = 0;\n\tadfGeoTransform[3] = ylim[1];\n\tadfGeoTransform[4] = 0;\n\tadfGeoTransform[5] = (ylim[0] - ylim[1]) / nLines;\n\tGDALSetGeoTransform(hDS, adfGeoTransform);\n\tGDALFillRaster(GDALGetRasterBand(hDS, 1), value[0], 0);\n\tCPLFree(pszSRS);\n\tGDALClose(hDS);\n}\n"
  },
  {
    "path": "src/wkb.cpp",
    "content": "/*\n everything with \"write\" is meant as \"write from R into foreign (wkb)\",\n \"read\" as \"read from foreign (wkb) into R\".\n*/\n\n#include <iostream>\n#include <iomanip>\n#include <sstream>\n#include <string>\n\n#include <math.h> // round()\n#include <string.h> // memcpy()\n\n#include <Rcpp.h>\n\n#include \"wkb.h\"\n\n#define EWKB_Z_BIT    0x80000000\n#define EWKB_M_BIT    0x40000000\n#define EWKB_SRID_BIT 0x20000000\n\n// [[Rcpp::interfaces(r, cpp)]]\n\ntypedef struct {\n\tconst unsigned char *pt;\n\tsize_t size;\n} wkb_buf;\n\nRcpp::List read_data(wkb_buf *wkb, bool EWKB, bool spatialite, int endian,\n\tbool addclass, int *type, uint32_t *srid);\nvoid write_data(std::ostringstream& os, Rcpp::List sfc, int i, bool EWKB,\n\t\tint endian, const char *cls, const char *dim, double prec, int srid);\n\nstatic inline void wkb_read(wkb_buf *wkb, void *dst, size_t n) {\n\tif (n > wkb->size)\n\t\tRcpp::stop(\"range check error: WKB buffer too small. Input file corrupt?\"); // #nocov\n\tif (dst != NULL)\n\t\tmemcpy(dst, wkb->pt, n);\n\twkb->pt += n;\n\twkb->size -= n;\n}\n\ntemplate<typename T>\ninline T wkb_read(wkb_buf *wkb) {\n\tif (sizeof(T) > wkb->size)\n\t\tRcpp::stop(\"range check error: WKB buffer too small. Input file corrupt?\");\n\n\tT dst;\n\tmemcpy(&dst, wkb->pt, sizeof(T));\n\twkb->pt += sizeof(T);\n\twkb->size -= sizeof(T);\n\treturn dst;\n}\n\n// https://stackoverflow.com/questions/105252/how-do-i-convert-between-big-endian-and-little-endian-values-in-c\ntemplate <typename T>\nT swap_endian(T u) {\n    union {\n        T u;\n        unsigned char u8[sizeof(T)];\n    } source, dest;\n    source.u = u;\n    for (size_t k = 0; k < sizeof(T); k++)\n        dest.u8[k] = source.u8[sizeof(T) - k - 1];\n    return dest.u;\n}\n\n\nvoid read_spatialite_header(wkb_buf *wkb, uint32_t *srid, bool swap) {\n\t// we're at byte 3 now:\n\t*srid = wkb_read<uint32_t>(wkb);\n\n\tif (swap)\n\t\t*srid = swap_endian<uint32_t>(*srid); // #nocov\n\n\twkb_read(wkb, NULL, 32); // skip header\n\t// verify special marker; if not there, raise error:\n\tunsigned char marker;\n\twkb_read(wkb, &marker, 1); // skip header\n\tif (marker != 0x7c) {\n\t\tRcpp::Rcout << \"byte 39 should be 0x7c, but is \" << marker << std::endl; // #nocov\n\t\tRcpp::stop(\"invalid spatialite header\"); // #nocov\n\t}\n}\n\nvoid read_gpkg_header(wkb_buf *wkb, uint32_t *srid, int endian) {\n\t// http://www.geopackage.org/spec/#gpb_format\n\twkb_read(wkb, NULL, 3); // 'G', 'P', version\n\n\t// read flag:\n\tunsigned char flag;\n\twkb_read(wkb, &flag, 1);\n\tbool swap = ((flag & 0x01) != (int) endian); // endian check\n\n\t// read srid, if needed, swap:\n\t*srid = wkb_read<uint32_t>(wkb);\n\tif (swap)\n\t\t*srid = swap_endian<uint32_t>(*srid); // #nocov\n\n\t// how much header is there to skip? bbox: 4, 6, 6, or 8 doubles:\n\tflag = (flag >> 1) & 0x07; // get bytes 3,2,1\n\tint n = 0;\n\tif (flag == 1) // [minx, maxx, miny, maxy]\n\t\tn = 32;\n\telse if (flag == 2 || flag == 3) // #nocov start\n\t\t\t// [minx, maxx, miny, maxy, minz, maxz] or [minx, maxx, miny, maxy, minm, maxm]\n\t\tn = 48;\n\telse if (flag == 4) // [minx, maxx, miny, maxy, minz, maxz, minm, maxm]\n\t\tn = 64; // #nocov end\n\twkb_read(wkb, NULL, n);\n}\n\nRcpp::NumericMatrix read_multipoint(wkb_buf *wkb, int n_dims, bool swap,\n\t\tbool EWKB = 0, bool spatialite = false, int endian = 0, Rcpp::CharacterVector cls = \"\",\n\t\tbool *empty = NULL) {\n\n\tuint32_t npts = wkb_read<uint32_t>(wkb);\n\n\tif (swap)\n\t\tnpts = swap_endian<uint32_t>(npts); // #nocov\n\n\tRcpp::NumericMatrix ret(npts, n_dims);\n\tfor (size_t i = 0; i < npts; i++) {\n\t\tif (spatialite) {\n\t\t\t// verify special marker; if not there, raise error:\n\t\t\tunsigned char marker;\n\t\t\twkb_read(wkb, &marker, 1); // absorb the 0x69 #nocov start\n\t\t\tif (marker != 0x69) {\n\t\t\t\tRcpp::Rcout << \"0x69 marker missing before ring \" << i+1 << std::endl;\n\t\t\t\tRcpp::stop(\"invalid spatialite header\");\n\t\t\t} // #nocov end\n\t\t}\n\t\tRcpp::List lst = read_data(wkb, EWKB, spatialite, endian, false, NULL, NULL);\n\t\tRcpp::NumericVector vec = lst[0];\n\t\tfor (int j = 0; j < n_dims; j++)\n\t\t\tret(i,j) = vec(j);\n\t}\n\tif (cls.size() == 3)\n\t\tret.attr(\"class\") = cls;\n\tif (empty != NULL)\n\t\t*empty = npts == 0;\n\treturn ret;\n}\n\nRcpp::List read_geometrycollection(wkb_buf *wkb, int n_dims, bool swap, bool EWKB = 0,\n\t\tbool spatialite = false, int endian = 0, Rcpp::CharacterVector cls = \"\", bool isGC = true,\n\t\tbool *empty = NULL) {\n\n\tuint32_t nlst = wkb_read<uint32_t>(wkb);\n\n\tif (swap)\n\t\tnlst = swap_endian<uint32_t>(nlst); // #nocov\n\n\tRcpp::List ret(nlst);\n\n\tfor (size_t i = 0; i < nlst; i++) {\n\t\tif (spatialite) {\n\t\t\t// verify special marker; if not there, raise error\n\t\t\tunsigned char marker;\n\t\t\twkb_read(wkb, &marker, 1); // absorb the 0x69\n\t\t\tif (marker != 0x69) { // #nocov start\n\t\t\t\tRcpp::Rcout << \"0x69 marker missing before ring \" << i+1 << std::endl;\n\t\t\t\tRcpp::stop(\"invalid spatialite header\");\n\t\t\t} // #nocov end\n\t\t}\n\t\tret[i] = read_data(wkb, EWKB, spatialite, endian, isGC, NULL, NULL)[0];\n\t}\n\tif (cls.size() == 3)\n\t\tret.attr(\"class\") = cls;\n\tif (empty != NULL)\n\t\t*empty = nlst == 0;\n\treturn ret;\n}\n\nRcpp::NumericVector read_numeric_vector(wkb_buf *wkb, int n, bool swap,\n\t\tRcpp::CharacterVector cls = \"\", bool *empty = NULL) {\n\tRcpp::NumericVector ret(n);\n\tfor (int i = 0; i < n; i++) {\n\t\tdouble d = wkb_read<double>(wkb);\n\t\tif (swap)\n\t\t\tret(i) = swap_endian<double>(d); // #nocov\n\t\telse\n\t\t\tret(i) = d;\n\t\tif (i == 0 && empty != NULL && std::isnan(d))\n\t\t\t*empty = true;\n\t}\n\tif (cls.size() == 3)\n\t\tret.attr(\"class\") = cls;\n\treturn ret;\n}\n\nRcpp::NumericMatrix read_numeric_matrix(wkb_buf *wkb, int n_dims, bool swap,\n\t\tRcpp::CharacterVector cls = \"\", bool *empty = NULL) {\n\n\tuint32_t npts = wkb_read<uint32_t>(wkb);\n\n\tif (swap)\n\t\tnpts = swap_endian<uint32_t>(npts); // #nocov\n\n\tRcpp::NumericMatrix ret = Rcpp::no_init(npts, n_dims);\n\tfor (size_t i = 0; i < npts; i++)\n\t\tfor (int j = 0; j< n_dims; j++) {\n\t\t\tdouble d = wkb_read<double>(wkb);\n\t\t\tif (swap)\n\t\t\t\tret(i, j) = swap_endian<double>(d); // #nocov\n\t\t\telse\n\t\t\t\tret(i, j) = d;\n\t\t}\n\tif (cls.size() == 3)\n\t\tret.attr(\"class\") = cls;\n\tif (empty != NULL)\n\t\t*empty = npts == 0;\n\treturn ret;\n}\n\nRcpp::List read_matrix_list(wkb_buf *wkb, int n_dims, bool swap,\n\t\tRcpp::CharacterVector cls = \"\", bool *empty = NULL) {\n\n\tuint32_t nlst = wkb_read<uint32_t>(wkb);\n\n\tif (swap)\n\t\tnlst = swap_endian<uint32_t>(nlst); // #nocov\n\n\tRcpp::List ret(nlst);\n\tfor (size_t i = 0; i < nlst; i++)\n\t\tret[i] = read_numeric_matrix(wkb, n_dims, swap, \"\");\n\n\tif (cls.size() == 3)\n\t\tret.attr(\"class\") = cls;\n\tif (empty != NULL)\n\t\t*empty = nlst == 0;\n\treturn ret;\n}\n\nRcpp::List read_data(wkb_buf *wkb, bool EWKB = false, bool spatialite = false,\n\t\tint endian = 0, bool addclass = true, int *type = NULL, uint32_t *srid = NULL) {\n/*\n pt: handle to the memory buffer\n EWKB: should we read EWKB, as opposed to ISO WKB?\n endian: 0 or 1, indicating big (0) or little (1) endian of the buffer\n addclass: write class information to object?\n type: IF NOT NULL: output the geometry type of object read\n srid: IF NOT NULL: output the srid read; NULL indicates a nested call\n*/\n\n\tRcpp::List output(1); // to deal with varying result type\n\n\tif (srid != NULL && wkb->size > 2 && wkb->pt[0] == 'G' && wkb->pt[1] == 'P') // GPKG header? skip:\n\t\tread_gpkg_header(wkb, srid, endian);\n\n\tif (spatialite && srid != NULL)\n\t\twkb_read(wkb, NULL, 1); // starting 0x00 contains no information\n\n\tunsigned char swap_char;\n\tbool swap;\n\n\tif (spatialite && srid == NULL) // nested call: don't read swap:\n\t\tswap = false;\n\telse {\n\t\twkb_read(wkb, &swap_char, 1);\n\t\tswap = ((int) swap_char != (int) endian); // endian check\n\t}\n\tif (spatialite) {\n\t\tif (swap)\n\t\t\tRcpp::stop(\"reading non-native endian spatialite geometries not supported\"); // #nocov\n\t\tif (srid != NULL) // not nested:\n\t\t\tread_spatialite_header(wkb, srid, swap);\n\t}\n\n\t// read type:\n\tuint32_t wkbType = wkb_read<uint32_t>(wkb);\n\n\tif (swap)\n\t\twkbType = swap_endian<uint32_t>(wkbType); // #nocov\n\n\tint sf_type = 0, n_dims = 0;\n\tstd::string dim_str = \"\";\n\tif (EWKB) { // EWKB: PostGIS default\n\t\tsf_type =     wkbType & 0x000000ff; // mask the other bits\n\t\tint wkbZ =    wkbType & EWKB_Z_BIT;\n\t\tint wkbM =    wkbType & EWKB_M_BIT;\n\t\tint wkbSRID = wkbType & EWKB_SRID_BIT;\n\t\tn_dims = 2 + (int) (wkbZ != 0) + (int) (wkbM != 0);\n\t\tif (wkbZ == 0 && wkbM == 0)\n\t\t\tdim_str = \"XY\";\n\t\telse if (wkbZ != 0 && wkbM == 0)\n\t\t\tdim_str = \"XYZ\";\n\t\telse if (wkbZ == 0 && wkbM != 1)\n\t\t\tdim_str = \"XYM\";\n\t\telse\n\t\t\tdim_str = \"XYZM\";\n\t\tif (wkbSRID != 0) {\n\t\t\tif (srid != NULL) {\n\t\t\t\twkb_read(wkb, srid, 4);\n\t\t\t\tif (swap)\n\t\t\t\t\t*srid = swap_endian<uint32_t>(*srid); // #nocov\n\t\t\t}\n\t\t}\n\t} else { // ISO\n\t\tsf_type = wkbType % 1000;\n\t\tswitch (wkbType / 1000) { // 0: XY, 1: XYZ, 2: XYM, 3: XYZM\n\t\t\tcase 0: n_dims = 2; dim_str = \"XY\"; break;\n\t\t\tcase 1: n_dims = 3; dim_str = \"XYZ\"; break;\n\t\t\tcase 2: n_dims = 3; dim_str = \"XYM\"; break;\n\t\t\tcase 3: n_dims = 4; dim_str = \"XYZM\"; break;\n\t\t\tdefault:\n\t\t\t\tRcpp::Rcout << \"wkbType: \" << wkbType << std::endl; // #nocov\n\t\t\t\tRcpp::stop(\"unsupported wkbType dim in switch\"); // #nocov\n\t\t}\n\t}\n\tbool empty = false;\n\tswitch(sf_type) {\n\t\tcase SF_Point:\n\t\t\toutput[0] = read_numeric_vector(wkb, n_dims, swap, addclass ?\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"POINT\", \"sfg\") : \"\", &empty);\n\t\t\tbreak;\n\t\tcase SF_LineString:\n\t\t\toutput[0] = read_numeric_matrix(wkb, n_dims, swap, addclass ?\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"LINESTRING\", \"sfg\") : \"\", &empty);\n\t\t\tbreak;\n\t\tcase SF_Polygon:\n\t\t\toutput[0] = read_matrix_list(wkb, n_dims, swap, addclass ?\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"POLYGON\", \"sfg\") : \"\", &empty);\n\t\t\tbreak;\n\t\tcase SF_MultiPoint:\n\t\t\toutput[0] = read_multipoint(wkb, n_dims, swap, EWKB, spatialite, endian, addclass ?\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"MULTIPOINT\", \"sfg\") : \"\", &empty);\n\t\t\tbreak;\n\t\tcase SF_MultiLineString:\n\t\t\toutput[0] = read_geometrycollection(wkb, n_dims, swap, EWKB, spatialite, endian,\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"MULTILINESTRING\", \"sfg\"), false, &empty);\n\t\t\tbreak;\n\t\tcase SF_MultiPolygon:\n\t\t\toutput[0] = read_geometrycollection(wkb, n_dims, swap, EWKB, spatialite, endian,\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"MULTIPOLYGON\", \"sfg\"), false, &empty);\n\t\t\tbreak;\n\t\tcase SF_GeometryCollection:\n\t\t\toutput[0] = read_geometrycollection(wkb, n_dims, swap, EWKB, spatialite, endian,\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"GEOMETRYCOLLECTION\", \"sfg\"), true,\n\t\t\t\t&empty);\n\t\t\tbreak;\n\t\tcase SF_CircularString:\n\t\t\toutput[0] = read_numeric_matrix(wkb, n_dims, swap, addclass ?\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"CIRCULARSTRING\", \"sfg\") : \"\", &empty);\n\t\t\tbreak;\n\t\tcase SF_CompoundCurve:\n\t\t\toutput[0] = read_geometrycollection(wkb, n_dims, swap, EWKB, spatialite, endian,\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"COMPOUNDCURVE\", \"sfg\"), true, &empty);\n\t\t\tbreak;\n\t\tcase SF_CurvePolygon:\n\t\t\toutput[0] = read_geometrycollection(wkb, n_dims, swap, EWKB, spatialite, endian,\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"CURVEPOLYGON\", \"sfg\"), true, &empty);\n\t\t\tbreak;\n\t\tcase SF_MultiCurve:\n\t\t\toutput[0] = read_geometrycollection(wkb, n_dims, swap, EWKB, spatialite, endian,\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"MULTICURVE\", \"sfg\"), true, &empty);\n\t\t\tbreak;\n\t\tcase SF_MultiSurface:\n\t\t\toutput[0] = read_geometrycollection(wkb, n_dims, swap, EWKB, spatialite, endian,\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"MULTISURFACE\", \"sfg\"), true, &empty);\n\t\t\tbreak;\n\t\tcase SF_Curve: // #nocov start\n\t\t\toutput[0] = read_numeric_matrix(wkb, n_dims, swap, addclass ?\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"CURVE\", \"sfg\") : \"\", &empty);\n\t\t\tbreak;\n\t\tcase SF_Surface:\n\t\t\toutput[0] = read_matrix_list(wkb, n_dims, swap, addclass ?\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"SURFACE\", \"sfg\") : \"\", &empty);\n\t\t\tbreak; // #nocov end\n\t\tcase SF_PolyhedralSurface:\n\t\t\toutput[0] = read_geometrycollection(wkb, n_dims, swap, EWKB, spatialite, endian,\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"POLYHEDRALSURFACE\", \"sfg\"), false, &empty);\n\t\t\tbreak;\n\t\tcase SF_TIN:\n\t\t\toutput[0] = read_geometrycollection(wkb, n_dims, swap, EWKB, spatialite, endian,\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"TIN\", \"sfg\"), false, &empty);\n\t\t\tbreak;\n\t\tcase SF_Triangle:\n\t\t\toutput[0] = read_matrix_list(wkb, n_dims, swap,\n\t\t\t\tRcpp::CharacterVector::create(dim_str, \"TRIANGLE\", \"sfg\"), &empty);\n\t\t\tbreak;\n\t\tdefault: {\n\t\t\tchar cp[100];\n\t\t\tsnprintf(cp, 100, \"reading wkb type %d is not supported\\n\", sf_type);\n\t\t\tRcpp::stop(cp);\n\t\t}\n\t}\n\tif (type != NULL) {\n\t\tif (empty)\n\t\t\t*type = -sf_type;\n\t\telse\n\t\t\t*type = sf_type;\n\t}\n\treturn output;\n}\n\nint native_endian(void) {\n\tconst int one = 1;\n\tconst unsigned char *cp = (const unsigned char *) &one;\n\treturn (int) *cp;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_read_wkb(Rcpp::List wkb_list, bool EWKB = false, bool spatialite = false) {\n\tRcpp::List output(wkb_list.size());\n\n\tint type = 0, last_type = 0, n_types = 0, n_empty = 0;\n\tint endian = native_endian();\n\n\tuint32_t srid = 0;\n\tfor (int i = 0; i < wkb_list.size(); i++) {\n\t\tRcpp::checkUserInterrupt();\n\t\tRcpp::RawVector raw = wkb_list[i];\n\t\twkb_buf wkb;\n\t\twkb.pt = &(raw[0]);\n\t\twkb.size = raw.size();\n\t\t// const unsigned char *pt = &(raw[0]);\n\t\toutput[i] = read_data(&wkb, EWKB, spatialite, endian, true, &type, &srid)[0];\n\t\tif (type <= 0) {\n\t\t\ttype = -type;\n\t\t\tn_empty++;\n\t\t}\n\t\t// Rcpp::Rcout << \"type is \" << type << \"\\n\";\n\t\tif (n_types <= 1 && type != last_type) {\n\t\t\tlast_type = type;\n\t\t\tn_types++; // check if there's more than 1 type:\n\t\t}\n\t}\n\toutput.attr(\"single_type\") = n_types <= 1; // if 0, we have only empty geometrycollections\n\toutput.attr(\"n_empty\") = (int) n_empty;\n\tif ((EWKB || spatialite) && srid != 0)\n\t\toutput.attr(\"srid\") = (int) srid;\n\treturn output;\n}\n\n//\n// write wkb:\n//\n\nunsigned int make_type(const char *cls, const char *dim, bool EWKB = false, int *tp = NULL,\n\t\tint srid = 0) {\n\tint type = 0;\n\tif (strstr(cls, \"sfc_\") == cls)\n\t\tcls += 4;\n\tif (strcmp(cls, \"POINT\") == 0)\n\t\ttype = SF_Point;\n\telse if (strcmp(cls, \"LINESTRING\") == 0)\n\t\ttype = SF_LineString;\n\telse if (strcmp(cls, \"POLYGON\") == 0)\n\t\ttype = SF_Polygon;\n\telse if (strcmp(cls, \"MULTIPOINT\") == 0)\n\t\ttype = SF_MultiPoint;\n\telse if (strcmp(cls, \"MULTILINESTRING\") == 0)\n\t\ttype = SF_MultiLineString;\n\telse if (strcmp(cls, \"MULTIPOLYGON\") == 0)\n\t\ttype = SF_MultiPolygon;\n\telse if (strcmp(cls, \"GEOMETRYCOLLECTION\") == 0)\n\t\ttype = SF_GeometryCollection;\n\telse if (strcmp(cls, \"CIRCULARSTRING\") == 0)\n\t\ttype = SF_CircularString;\n\telse if (strcmp(cls, \"COMPOUNDCURVE\") == 0)\n\t\ttype = SF_CompoundCurve;\n\telse if (strcmp(cls, \"CURVEPOLYGON\") == 0)\n\t\ttype = SF_CurvePolygon;\n\telse if (strcmp(cls, \"MULTICURVE\") == 0)\n\t\ttype = SF_MultiCurve;\n\telse if (strcmp(cls, \"MULTISURFACE\") == 0)\n\t\ttype = SF_MultiSurface;\n\telse if (strcmp(cls, \"CURVE\") == 0)\n\t\ttype = SF_Curve; // #nocov\n\telse if (strcmp(cls, \"SURFACE\") == 0)\n\t\ttype = SF_Surface; // #nocov\n\telse if (strcmp(cls, \"POLYHEDRALSURFACE\") == 0)\n\t\ttype = SF_PolyhedralSurface;\n\telse if (strcmp(cls, \"TIN\") == 0)\n\t\ttype = SF_TIN;\n\telse if (strcmp(cls, \"TRIANGLE\") == 0)\n\t\ttype = SF_Triangle;\n\telse\n\t\ttype = SF_Unknown; // a mix: GEOMETRY\n\tif (tp != NULL)\n\t\t*tp = type;\n\tif (EWKB) {\n\t\tif (strcmp(dim, \"XYZ\") == 0)\n\t\t\ttype = type | EWKB_Z_BIT;\n\t\telse if (strcmp(dim, \"XYM\") == 0)\n\t\t\ttype = type | EWKB_M_BIT;\n\t\telse if (strcmp(dim, \"XYZM\") == 0)\n\t\t\ttype = type | EWKB_M_BIT | EWKB_Z_BIT;\n\t\tif (srid != 0)\n\t\t\ttype = type | EWKB_SRID_BIT;\n\t} else {\n\t\tif (strcmp(dim, \"XYZ\") == 0)\n\t\t\ttype += 1000;\n\t\telse if (strcmp(dim, \"XYM\") == 0)\n\t\t\ttype += 2000;\n\t\telse if (strcmp(dim, \"XYZM\") == 0)\n\t\t\ttype += 3000;\n\t}\n\treturn type;\n}\n\nvoid add_byte(std::ostringstream& os, char c) {\n  os.write((char*) &c, sizeof(char));\n}\n\nvoid add_int(std::ostringstream& os, unsigned int i) {\n  char *cp = (char *)&i;\n  os.write((char*) cp, sizeof(int));\n}\n\ndouble make_precise(double d, double precision) {\n\tif (precision == 0.0)\n\t\treturn d;\n\tif (precision < 0.0) { // round to float, 4-byte precision\n\t\tfloat f = d;\n\t\treturn (double) f;\n\t}\n\treturn round(d * precision) / precision;\n}\n\nvoid add_double(std::ostringstream& os, double d, double prec = 0.0) {\n  d = make_precise(d, prec); // doubles are ALWAYS coordinates\n  char *cp = (char *)&d;\n  os.write((char*) cp, sizeof(double));\n}\n\nvoid write_vector(std::ostringstream& os, Rcpp::NumericVector vec, double prec) {\n\tfor (int i = 0; i < vec.length(); i++)\n\t\tadd_double(os, vec(i), prec);\n}\n\nvoid write_matrix(std::ostringstream& os, Rcpp::NumericMatrix mat, double prec) {\n\tauto nrow = mat.nrow();\n\tauto ncol = mat.ncol();\n\n\tadd_int(os, mat.nrow());\n\tfor (decltype(nrow) i = 0; i < nrow; i++)\n\t\tfor (decltype(ncol) j = 0; j < ncol; j++)\n\t\t\tadd_double(os, mat(i,j), prec);\n}\n\nvoid write_matrix_list(std::ostringstream& os, Rcpp::List lst, double prec) {\n\tsize_t len = lst.length();\n\tadd_int(os, len);\n\tfor (size_t i = 0; i < len; i++)\n\t\twrite_matrix(os, lst[i], prec);\n}\n\nvoid write_multilinestring(std::ostringstream& os, Rcpp::List lst, bool EWKB = false,\n\t\tint endian = 0, double prec = 0.0) {\n\tRcpp::CharacterVector cl_attr = lst.attr(\"class\");\n\tconst char *dim = cl_attr[0];\n\tadd_int(os, lst.length());\n\tfor (int i = 0; i < lst.length(); i++)\n\t\twrite_data(os, lst, i, EWKB, endian, \"LINESTRING\", dim, prec, 0);\n}\n\nvoid write_multipolygon(std::ostringstream& os, Rcpp::List lst, bool EWKB = false,\n\t\tint endian = 0, double prec = 0.0) {\n\tRcpp::CharacterVector cl_attr = lst.attr(\"class\");\n\tconst char *dim = cl_attr[0];\n\tadd_int(os, lst.length());\n\tfor (int i = 0; i < lst.length(); i++)\n\t\twrite_data(os, lst, i, EWKB, endian, \"POLYGON\", dim, prec, 0);\n}\n\nvoid write_triangles(std::ostringstream& os, Rcpp::List lst, bool EWKB = false,\n\t\tint endian = 0, double prec = 0.0) {\n\tRcpp::CharacterVector cl_attr = lst.attr(\"class\");\n\tconst char *dim = cl_attr[0];\n\tadd_int(os, lst.length());\n\tfor (int i = 0; i < lst.length(); i++)\n\t\twrite_data(os, lst, i, EWKB, endian, \"TRIANGLE\", dim, prec, 0);\n}\n\nvoid write_geometrycollection(std::ostringstream& os, Rcpp::List lst, bool EWKB = false,\n\t\tint endian = 0, double prec = 0.0) {\n\tadd_int(os, lst.length());\n\tRcpp::Function Rclass(\"class\");\n\tfor (int i = 0; i < lst.length(); i++) {\n\t\tRcpp::CharacterVector cl_attr = Rclass(lst[i]);\n\t\tconst char *cls = cl_attr[1], *dim = cl_attr[0];\n\t\twrite_data(os, lst, i, EWKB, endian, cls, dim, prec, 0);\n\t}\n}\n\nvoid write_multipoint(std::ostringstream& os, Rcpp::NumericMatrix mat,\n\t\tbool EWKB = false, int endian = 0, double prec = 0.0) {\n\tadd_int(os, mat.nrow());\n\tRcpp::CharacterVector cl_attr = mat.attr(\"class\");\n\tconst char *dim = cl_attr[0];\n\tRcpp::NumericVector v(mat.ncol()); // copy row i\n\tfor (int i = 0; i < mat.nrow(); i++) {\n\t\tfor (int j = 0; j < mat.ncol(); j++)\n\t\t\tv(j) = mat(i,j);\n\t\twrite_data(os, Rcpp::List::create(v), 0, EWKB, endian, \"POINT\", dim, prec, 0);\n\t}\n}\n\n// write single simple feature object as (E)WKB to stream os\nvoid write_data(std::ostringstream& os, Rcpp::List sfc, int i = 0, bool EWKB = false,\n\t\tint endian = 0, const char *cls = NULL, const char *dim = NULL, double prec = 0.0,\n\t\tint srid = 0) {\n\n\tadd_byte(os, (char) endian);\n\tint tp;\n\tunsigned int sf_type = make_type(cls, dim, EWKB, &tp, srid);\n\tadd_int(os, sf_type);\n\tif (EWKB && srid != 0)\n\t\tadd_int(os, srid);\n\tswitch(tp) {\n\t\tcase SF_Point: write_vector(os, sfc[i], prec);\n\t\t\tbreak;\n\t\tcase SF_LineString: write_matrix(os, sfc[i], prec);\n\t\t\tbreak;\n\t\tcase SF_Polygon: write_matrix_list(os, sfc[i], prec);\n\t\t\tbreak;\n\t\tcase SF_MultiPoint: write_multipoint(os, sfc[i], EWKB, endian, prec);\n\t\t\tbreak;\n\t\tcase SF_MultiLineString: write_multilinestring(os, sfc[i], EWKB, endian, prec);\n\t\t\tbreak;\n\t\tcase SF_MultiPolygon: write_multipolygon(os, sfc[i], EWKB, endian, prec);\n\t\t\tbreak;\n\t\tcase SF_GeometryCollection: write_geometrycollection(os, sfc[i], EWKB, endian, prec);\n\t\t\tbreak;\n\t\tcase SF_CircularString: write_matrix(os, sfc[i], prec);\n\t\t\tbreak;\n\t\tcase SF_CompoundCurve: write_geometrycollection(os, sfc[i], EWKB, endian, prec);\n\t\t\tbreak;\n\t\tcase SF_CurvePolygon: write_geometrycollection(os, sfc[i], EWKB, endian, prec);\n\t\t\tbreak;\n\t\tcase SF_MultiCurve: write_geometrycollection(os, sfc[i], EWKB, endian, prec);\n\t\t\tbreak;\n\t\tcase SF_MultiSurface: write_geometrycollection(os, sfc[i], EWKB, endian, prec);\n\t\t\tbreak;\n\t\tcase SF_Curve: write_matrix(os, sfc[i], prec); // #nocov start\n\t\t\tbreak;\n\t\tcase SF_Surface: write_matrix_list(os, sfc[i], prec);\n\t\t\tbreak; // #nocov end\n\t\tcase SF_PolyhedralSurface: write_multipolygon(os, sfc[i], EWKB, endian, prec);\n\t\t\tbreak;\n\t\tcase SF_TIN: write_triangles(os, sfc[i], EWKB, endian, prec);\n\t\t\tbreak;\n\t\tcase SF_Triangle: write_matrix_list(os, sfc[i], prec);\n\t\t\tbreak;\n\t\tdefault: {\n\t\t\tRcpp::Rcout << \"type is \" << sf_type << \"\\n\"; // #nocov\n\t\t\tRcpp::stop(\"writing this sf type is not supported, please file an issue\"); // #nocov\n\t\t}\n\t}\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::List CPL_write_wkb(Rcpp::List sfc, bool EWKB = false) {\n\n\tdouble precision = sfc.attr(\"precision\");\n\tRcpp::CharacterVector cls_attr = sfc.attr(\"class\");\n\tRcpp::List sfc_dim = get_dim_sfc(sfc);\n\tRcpp::CharacterVector dim = sfc_dim[\"_cls\"];\n\tconst char *cls = cls_attr[0], *dm = dim[0];\n\n\tRcpp::List output(sfc.size()); // with raw vectors\n\n\tint endian = native_endian();\n\n\t// got the following from:\n\t// http://stackoverflow.com/questions/24744802/rcpp-how-to-check-if-any-attribute-is-null\n\tRcpp::CharacterVector classes;\n\tbool have_classes = false;\n\tif (sfc.size() > 0 && strcmp(cls, \"sfc_GEOMETRY\") == 0) {\n\t\tif (sfc.hasAttribute(\"classes\")) { // only sfc_GEOMETRY, the mixed bag, sets the classes attr\n\t\t\tclasses = sfc.attr(\"classes\");\n\t\t\tif (classes.size() != sfc.size())\n\t\t\t\tRcpp::stop(\"attr classes has wrong size: please file an issue\"); // #nocov\n\t\t\thave_classes = true;\n\t\t} else\n\t\t\tRcpp::stop(\"sfc_GEOMETRY has no classes attribute; please file an issue\"); // #nocov\n\t}\n\n\tint srid = 0;\n\tif (EWKB) { \n\t\t// get SRID from crs[[\"input\"]], either of the form \"4326\" \n\t\t// or \"XXXX:4326\" with arbitrary XXXX string,\n\t\t// or else from the wkt field of the crs using srid_from_crs()\n\t\tRcpp::List crs = sfc.attr(\"crs\");\n\t\tRcpp::CharacterVector input = crs(0);\n\t\tchar *inp = input[0];\n\t\tchar *remainder = NULL;\n\t\t// check for \":\", and move one beyond:\n\t\tif ((remainder = strstr(inp, \":\")) != NULL)\n\t\t\tinp = remainder + 1;\n\t\tlong value = strtol(inp, &remainder, 10);\n\t\tif (*remainder == '\\0') // strtol() succeeded:\n\t\t\tsrid = (int) value;\n\t\telse {\n\t\t\tint i = srid_from_crs(crs);\n\t\t\tif (i != NA_INTEGER)\n\t\t\t\tsrid = i; // else leave 0\n\t\t}\n\t}\n\n\tfor (int i = 0; i < sfc.size(); i++) {\n\t\tRcpp::checkUserInterrupt();\n\t\tstd::ostringstream os;\n\t\tif (have_classes)\n\t\t\tcls = classes[i];\n\t\twrite_data(os, sfc, i, EWKB, endian, cls, dm, precision, srid);\n\t\tRcpp::RawVector raw(os.str().size()); // os -> raw:\n\t\tstd::string str = os.str();\n\t\tconst char *cp = str.c_str();\n\t\tfor (size_t j = 0; j < str.size(); j++)\n\t\t\traw[j] = cp[j];\n\t\toutput[i] = raw; // raw vector to list\n\t}\n\treturn output;\n}\n\n// get dim, \"XY\", \"XYZ\", \"XYZM\" or \"XYM\" from an sfc object\n\nRcpp::List get_dim_sfc(Rcpp::List sfc) {\n\n\tif (sfc.length() == 0)\n\t\treturn Rcpp::List::create(\n\t\t\tRcpp::Named(\"_cls\") = Rcpp::CharacterVector::create(\"XY\"),\n\t\t\tRcpp::Named(\"_dim\") = Rcpp::IntegerVector::create(2)\n\t\t);\n\n\t// we have data:\n\tRcpp::CharacterVector cls = sfc.attr(\"class\");\n\tunsigned int tp = make_type(cls[0], \"\", false, NULL, 0);\n\tif (tp == SF_Unknown) {\n\t\tcls = sfc.attr(\"classes\");\n\t\ttp = make_type(cls[0], \"\", false, NULL, 0);\n\t}\n\tswitch (tp) {\n\t\tcase SF_Unknown: { // further check:\n\t\t\tRcpp::stop(\"impossible classs in get_dim_sfc()\"); // #nocov\n\t\t} break;\n\t\tcase SF_Point: { // numeric:\n\t\t\tRcpp::NumericVector v = sfc[0];\n\t\t\tcls = v.attr(\"class\");\n\t\t} break;\n\t\tcase SF_LineString:  // matrix:\n\t\tcase SF_MultiPoint:\n\t\tcase SF_CircularString:\n\t\tcase SF_Curve: {\n\t\t\tRcpp::NumericMatrix m = sfc[0];\n\t\t\tcls = m.attr(\"class\");\n\t\t} break;\n\t\tcase SF_Polygon: // list:\n\t\tcase SF_MultiLineString:\n\t\tcase SF_MultiPolygon:\n\t\tcase SF_GeometryCollection:\n\t\tcase SF_CompoundCurve:\n\t\tcase SF_CurvePolygon:\n\t\tcase SF_MultiCurve:\n\t\tcase SF_MultiSurface:\n\t\tcase SF_Surface:\n\t\tcase SF_PolyhedralSurface:\n\t\tcase SF_TIN:\n\t\tcase SF_Triangle: {\n\t\t\tRcpp::List l = sfc[0];\n\t\t\tcls = l.attr(\"class\");\n\t\t} break;\n\t}\n\n\treturn Rcpp::List::create(\n\t\tRcpp::Named(\"_cls\") = cls,\n\t\tRcpp::Named(\"_dim\") = strstr(cls[0], \"Z\") != NULL ?\n\t\t\tRcpp::IntegerVector::create(3) :\n\t\t\tRcpp::IntegerVector::create(2));\n}\n\n"
  },
  {
    "path": "src/wkb.h",
    "content": "#ifndef SF_WKB_H_\n#define SF_WKB_H_\n/*      NULL/EMPTY             0 */\n#define SF_Unknown             0 /* sfc_GEOMETRY */\n#define SF_Point               1\n#define SF_LineString          2\n#define SF_Polygon             3\n#define SF_MultiPoint          4\n#define SF_MultiLineString     5\n#define SF_MultiPolygon        6\n#define SF_GeometryCollection  7\n#define SF_CircularString      8\n#define SF_CompoundCurve       9\n#define SF_CurvePolygon       10\n#define SF_MultiCurve         11\n#define SF_MultiSurface       12\n#define SF_Curve              13\n#define SF_Surface            14\n#define SF_PolyhedralSurface  15\n#define SF_TIN                16\n#define SF_Triangle           17\n\nRcpp::List CPL_read_wkb(Rcpp::List wkb_list, bool EWKB, bool spatialite);\nRcpp::List CPL_write_wkb(Rcpp::List sfc, bool EWKB);\nunsigned int make_type(const char *cls, const char *dim, bool EWKB, int *tp, int srid);\nRcpp::List get_dim_sfc(Rcpp::List sfc);\nint srid_from_crs(Rcpp::List crs);\n#endif // SF_WKB_H_\n"
  },
  {
    "path": "src/zm_range.cpp",
    "content": "#include <Rcpp.h>\n\n#include \"zm_range.h\"\n\nint get_m_position(Rcpp::NumericVector& pt) {\n\tif( pt.size() < 3 ) {\n\t\treturn -1;\n\t}\n\tint pos = pt.size() == 3 ? 2 : 3;\n\treturn pos;\n}\n\nint get_m_position(Rcpp::NumericMatrix& nm) {\n\tif( nm.ncol() < 3 ) {\n\t\treturn -1;\n\t}\n\tint pos = nm.ncol() == 3 ? 2 : 3;\n\treturn pos;\n}\n\nint get_z_position(Rcpp::NumericVector& pt) {\n\tif( pt.size() < 3 ) {\n\t\treturn -1;\n\t}\n\treturn 2;\n}\n\nint get_z_position(Rcpp::NumericMatrix& nm) {\n\tif( nm.ncol() < 3 ) {\n\t\treturn -1;\n\t}\n\treturn 2;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::NumericVector CPL_get_z_range(Rcpp::List sf, int depth) {\n\n\tRcpp::NumericVector bb_na(2);\n\tbb_na[0] = bb_na[1] = NA_REAL;\n\tRcpp::NumericVector bb(2);\n\tbb[0] = bb[1] = NA_REAL;\n\tauto n = sf.size();\n\n\tswitch(depth) {\n\tcase 0: // points:\n\t\tfor (decltype(n) i = 0; i < n; i++) {\n\t\t\tRcpp::NumericVector pt = sf[i];\n\t\t\tint pos = get_z_position(pt);\n\t\t\tif (i == -1)\n\t\t\t\treturn bb_na;\n\t\t\telse if (i == 0) {\n\t\t\t\tbb[0] = pt[pos];\n\t\t\t\tbb[1] = pt[pos];\n\t\t\t} else {\n\t\t\t\tbb[0] = std::min(pt[pos],bb[0]);\n\t\t\t\tbb[1] = std::max(pt[pos],bb[1]);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\n\tcase 1: { // list of matrices:\n\t\t\tbool initialised = false;\n\t\t\tfor (decltype(n) i = 0; i < n; i++) {\n\t\t\t\tRcpp::NumericMatrix m = sf[i];\n\t\t\t\tint pos = get_z_position(m);\n\t\t\t\tif (pos == -1)\n\t\t\t\t\treturn bb_na;\n\t\t\t\tauto rows = m.nrow();\n\t\n\t\t\t\tif (rows > 0) {\n\t\t\t\t\tif (! initialised) { // initialize:\n\t\t\t\t\t\tbb[0] = m(0,pos);\n\t\t\t\t\t\tbb[1] = m(0,pos);\n\t\t\t\t\t\tinitialised = true;\n\t\t\t\t\t}\n\t\t\t\t\tfor (decltype(rows) j = 0; j < rows; j++) {\n\t\t\t\t\t\tbb[0] = std::min(m(j,pos),bb[0]);\n\t\t\t\t\t\tbb[1] = std::max(m(j,pos),bb[1]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbreak;\n\n\tdefault: // recursive list\n\t\tfor (decltype(n) i = 0; i < n; i++) {\n\t\t\tRcpp::NumericVector bbi = CPL_get_z_range(sf[i], depth - 1); // recurse\n\t\t\tif (! Rcpp::NumericVector::is_na(bbi[0])) {\n\t\t\t\tif (i == 0) {\n\t\t\t\t\tbb[0] = bbi[0];\n\t\t\t\t\tbb[1] = bbi[1];\n\t\t\t\t} else {\n\t\t\t\t\tbb[0] = std::min(bbi[0],bb[0]);\n\t\t\t\t\tbb[1] = std::max(bbi[1],bb[1]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbreak;\n\t}\n\treturn bb;\n}\n\n// [[Rcpp::export(rng=false)]]\nRcpp::NumericVector CPL_get_m_range(Rcpp::List sf, int depth) {\n\n\tRcpp::NumericVector bb_na(2);\n\tbb_na[0] = bb_na[1] = NA_REAL;\n\tRcpp::NumericVector bb(2);\n\tbb[0] = bb[1] = NA_REAL;\n\tauto n = sf.size();\n\n\tswitch(depth) {\n\tcase 0: // points:\n\t\tfor (decltype(n) i = 0; i < n; i++) {\n\t\t\tRcpp::NumericVector pt = sf[i];\n\t\t\tint pos = get_m_position(pt);\n\t\t\tif (i == -1)\n\t\t\t\treturn bb_na;\n\t\t\telse if (i == 0) {\n\t\t\t\tbb[0] = pt[pos];\n\t\t\t\tbb[1] = pt[pos];\n\t\t\t} else {\n\t\t\t\tbb[0] = std::min(pt[pos],bb[0]);\n\t\t\t\tbb[1] = std::max(pt[pos],bb[1]);\n\t\t\t}\n\t\t}\n\t\tbreak;\n\n\tcase 1: { // list of matrices:\n\t\t\tbool initialised = false;\n\t\t\tfor (decltype(n) i = 0; i < n; i++) {\n\t\t\t\tRcpp::NumericMatrix m = sf[i];\n\t\t\t\tint pos = get_m_position(m);\n\t\t\t\tif (pos == -1)\n\t\t\t\t\treturn bb_na;\n\t\t\t\tauto rows = m.nrow();\n\t\n\t\t\t\tif (rows > 0) {\n\t\t\t\t\tif (! initialised) { // initialize:\n\t\t\t\t\t\tbb[0] = m(0,pos);\n\t\t\t\t\t\tbb[1] = m(0,pos);\n\t\t\t\t\t\tinitialised = true;\n\t\t\t\t\t}\n\t\t\t\t\tfor (decltype(rows) j = 0; j < rows; j++) {\n\t\t\t\t\t\tbb[0] = std::min(m(j,pos),bb[0]);\n\t\t\t\t\t\tbb[1] = std::max(m(j,pos),bb[1]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbreak;\n\n\tdefault: // recursive list\n\t\tfor (decltype(n) i = 0; i < n; i++) {\n\t\t\tRcpp::NumericVector bbi = CPL_get_m_range(sf[i], depth - 1); // recurse\n\t\t\tif (! Rcpp::NumericVector::is_na(bbi[0])) {\n\t\t\t\tif (i == 0) {\n\t\t\t\t\tbb[0] = bbi[0];\n\t\t\t\t\tbb[1] = bbi[1];\n\t\t\t\t} else {\n\t\t\t\t\tbb[0] = std::min(bbi[0],bb[0]);\n\t\t\t\t\tbb[1] = std::max(bbi[1],bb[1]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tbreak;\n\t}\n\treturn bb;\n}\n"
  },
  {
    "path": "src/zm_range.h",
    "content": "#ifndef SF_ZM_RANGE_H_\n#define SF_ZM_RANGE_H_\n//Rcpp::NumericVector CPL_get_zm_range(Rcpp::List sf, int depth);\n\nint get_m_position(Rcpp::NumericVector& pt);\n\nint get_m_position(Rcpp::NumericMatrix& nm);\n\nint get_z_position(Rcpp::NumericVector& pt);\n\nint get_z_position(Rcpp::NumericMatrix& nm);\n\nRcpp::NumericVector CPL_get_z_range(Rcpp::List sf, int depth);\n\nRcpp::NumericVector CPL_get_m_range(Rcpp::List sf, int depth);\n#endif // SF_ZM_RANGE_H_\n"
  },
  {
    "path": "tests/aggregate.R",
    "content": "## IGNORE_RDIFF_BEGIN\nlibrary(sf)\n## IGNORE_RDIFF_END\n# aggregate\npl1 = st_polygon(list(rbind(c(0,0),c(1,0),c(1,1),c(0,0))))\npl2 = st_polygon(list(rbind(c(0,0),c(1,1),c(0,1),c(0,0))))\ns = st_sf(a = 1:2, geom = st_sfc(pl1, pl2))\n(a = aggregate(s, list(c(1,1)), mean, do_union = FALSE))\n(a = aggregate(s, list(c(1,1)), mean, do_union = TRUE))\n# expect_warning(st_cast(a, \"POINT\"))\nif (suppressPackageStartupMessages(require(sp, quietly = TRUE))) {\n demo(meuse_sf, echo = FALSE, ask = FALSE)\n a = aggregate(meuse_sf, list(meuse_sf$soil), mean)\n print(attributes(a)$agr)\n a = aggregate(meuse_sf, list(soil = meuse_sf$soil), mean)\n print(attributes(a)$agr)\n a = aggregate(meuse_sf, list(meuse_sf$soil, meuse_sf$ffreq), mean)\n print(attributes(a)$agr)\n a = aggregate(meuse_sf, list(soil = meuse_sf$soil, ff = meuse_sf$ffreq), mean)\n print(attributes(a)$agr)\n}\n\n# aggregate by sf/sfc\na = st_polygon(list(rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0)))) * 2\nb = a + 1\np = st_sfc(st_point(c(0.1,0.1)), st_point(c(1.5,1.5)), st_point(c(2.9,2.9)))\nx = st_sf(count = 1:3, geom = p)\naggregate(x, st_sfc(a,b), mean)\naggregate(x, st_sf(st_sfc(a,b)), mean)\naggregate(x, st_sf(st_sfc(a,b,b+10)), mean)\n"
  },
  {
    "path": "tests/aggregate.Rout.save",
    "content": "\nR Under development (unstable) (2025-11-05 r88988 ucrt) -- \"Unsuffered Consequences\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-w64-mingw32/x64\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> ## IGNORE_RDIFF_BEGIN\n> library(sf)\nLinking to GEOS 3.13.1, GDAL 3.11.4, PROJ 9.7.0; sf_use_s2() is TRUE\n> ## IGNORE_RDIFF_END\n> # aggregate\n> pl1 = st_polygon(list(rbind(c(0,0),c(1,0),c(1,1),c(0,0))))\n> pl2 = st_polygon(list(rbind(c(0,0),c(1,1),c(0,1),c(0,0))))\n> s = st_sf(a = 1:2, geom = st_sfc(pl1, pl2))\n> (a = aggregate(s, list(c(1,1)), mean, do_union = FALSE))\nSimple feature collection with 1 feature and 2 fields\nAttribute-geometry relationships: aggregate (1), identity (1)\nGeometry type: MULTIPOLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\n  Group.1   a                       geometry\n1       1 1.5 MULTIPOLYGON (((0 0, 1 0, 1...\n> (a = aggregate(s, list(c(1,1)), mean, do_union = TRUE))\nSimple feature collection with 1 feature and 2 fields\nAttribute-geometry relationships: aggregate (1), identity (1)\nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\n  Group.1   a                       geometry\n1       1 1.5 POLYGON ((1 0, 0 0, 0 1, 1 ...\n> # expect_warning(st_cast(a, \"POINT\"))\n> if (suppressPackageStartupMessages(require(sp, quietly = TRUE))) {\n+  demo(meuse_sf, echo = FALSE, ask = FALSE)\n+  a = aggregate(meuse_sf, list(meuse_sf$soil), mean)\n+  print(attributes(a)$agr)\n+  a = aggregate(meuse_sf, list(soil = meuse_sf$soil), mean)\n+  print(attributes(a)$agr)\n+  a = aggregate(meuse_sf, list(meuse_sf$soil, meuse_sf$ffreq), mean)\n+  print(attributes(a)$agr)\n+  a = aggregate(meuse_sf, list(soil = meuse_sf$soil, ff = meuse_sf$ffreq), mean)\n+  print(attributes(a)$agr)\n+ }\n  Group.1   cadmium    copper      lead      zinc      elev      dist        om \n identity aggregate aggregate aggregate aggregate aggregate aggregate aggregate \n    ffreq      soil      lime   landuse    dist.m \naggregate aggregate aggregate aggregate aggregate \nLevels: constant aggregate identity\n     soil   cadmium    copper      lead      zinc      elev      dist        om \n identity aggregate aggregate aggregate aggregate aggregate aggregate aggregate \n    ffreq    soil.1      lime   landuse    dist.m \naggregate aggregate aggregate aggregate aggregate \nLevels: constant aggregate identity\n  Group.1   Group.2   cadmium    copper      lead      zinc      elev      dist \n identity  identity aggregate aggregate aggregate aggregate aggregate aggregate \n       om     ffreq      soil      lime   landuse    dist.m \naggregate aggregate aggregate aggregate aggregate aggregate \nLevels: constant aggregate identity\n     soil        ff   cadmium    copper      lead      zinc      elev      dist \n identity  identity aggregate aggregate aggregate aggregate aggregate aggregate \n       om     ffreq    soil.1      lime   landuse    dist.m \naggregate aggregate aggregate aggregate aggregate aggregate \nLevels: constant aggregate identity\nThere were 50 or more warnings (use warnings() to see the first 50)\n> \n> # aggregate by sf/sfc\n> a = st_polygon(list(rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0)))) * 2\n> b = a + 1\n> p = st_sfc(st_point(c(0.1,0.1)), st_point(c(1.5,1.5)), st_point(c(2.9,2.9)))\n> x = st_sf(count = 1:3, geom = p)\n> aggregate(x, st_sfc(a,b), mean)\nSimple feature collection with 2 features and 1 field\nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 3 ymax: 3\nCRS:           NA\n  count                       geometry\n1   1.5 POLYGON ((0 0, 2 0, 2 2, 0 ...\n2   2.5 POLYGON ((1 1, 3 1, 3 3, 1 ...\n> aggregate(x, st_sf(st_sfc(a,b)), mean)\nSimple feature collection with 2 features and 1 field\nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 3 ymax: 3\nCRS:           NA\n  count                       geometry\n1   1.5 POLYGON ((0 0, 2 0, 2 2, 0 ...\n2   2.5 POLYGON ((1 1, 3 1, 3 3, 1 ...\n> aggregate(x, st_sf(st_sfc(a,b,b+10)), mean)\nSimple feature collection with 3 features and 1 field\nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 13 ymax: 13\nCRS:           NA\n  count                       geometry\n1   1.5 POLYGON ((0 0, 2 0, 2 2, 0 ...\n2   2.5 POLYGON ((1 1, 3 1, 3 3, 1 ...\n3    NA POLYGON ((11 11, 13 11, 13 ...\n> \n> proc.time()\n   user  system elapsed \n   0.62    0.12    0.73 \n"
  },
  {
    "path": "tests/cast.R",
    "content": "suppressPackageStartupMessages(library(sf))\nlibrary(testthat)\n# \"vertical\" conversions:\n# column 1:\nmp = st_sfc(st_multipoint(matrix(0:3,,2)), st_multipoint(matrix(10:15,,2)))\n(ls = st_cast(mp, \"LINESTRING\"))\nst_cast(ls, \"MULTIPOINT\")\n\n# column 2:\nmls = st_sfc(st_multilinestring(list(rbind(c(0,0), c(10,0), c(10,10), c(0,10)), \n\trbind(c(5,5),c(5,6), c(6,6), c(6,5)))), \n\tst_multilinestring(list(rbind(c(0,0), c(1,0), c(1,1), c(0,1)))))\n(pol = st_cast(mls, \"POLYGON\"))\nst_cast(pol, \"MULTILINESTRING\")\n\n# \"horizontal\" conversions:\n\n(pt = st_cast(mp, \"POINT\"))\n(i = attr(pt, \"ids\"))\n(xx = st_cast(pt, \"MULTIPOINT\", rep(seq_along(i), i)))\ntry(yy <- st_cast(pt, \"LINESTRING\", rep(seq_along(i), i)))\n\n#(zz = st_cast(yy, \"MULTILINESTRING\"))\n#(zz = st_cast(yy, \"POLYGON\"))\n\nst_cast(mls, \"LINESTRING\")\n\n(g = st_sfc(c(mls, ls)))\nst_cast(g, \"MULTILINESTRING\")\nexpect_warning(st_cast(g, \"LINESTRING\"))\nst_cast(st_cast(g, \"MULTILINESTRING\"), \"LINESTRING\") # will not loose\n\ngc = st_sfc(st_geometrycollection(\n  list(\n    st_multilinestring(list(rbind(c(0,0), c(10,0), c(10,10), c(0,10)), \n\trbind(c(5,5),c(5,6), c(6,6), c(6,5)))), \n\tst_multilinestring(list(rbind(c(0,0), c(1,0), c(1,1), c(0,1)))),\n\tst_point(0:1)\n  )))\ntry(st_cast(mls, \"POINT\"))\ntry(st_cast(mls, \"MULTIPOINT\"))\n\nouter = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\nhole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\nhole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\npol1 = list(outer, hole1, hole2)\npol2 = list(outer + 12, hole1 + 12)\npol3 = list(outer + 24)\nmp = list(pol1,pol2,pol3)\nmp1 = st_multipolygon(mp)\ns = st_sfc(mp1)\nx = st_cast(s, \"MULTIPOINT\")\nx = st_cast(s, \"POINT\")\nexpect_warning(st_cast(mp1, \"LINESTRING\"))\nexpect_warning(st_cast(mp1, \"POINT\"))\nmls = mls[[1]]\nclass(mls)\n#expect_error(st_cast(mls, \"POLYGON\"))\nst_cast(mls, \"POLYGON\")\n\nexpect_warning(st_cast(mls, \"POINT\"))\np1 = st_polygon(pol1)\nexpect_warning(st_cast(p1, \"POINT\"))\nls = ls[[1]]\nclass(ls)\nexpect_warning(st_cast(ls, \"POINT\"))\n\nmls = st_cast(p1, \"MULTILINESTRING\")\np2 = st_cast(mls, \"POLYGON\")\n\n# st_is:\nst_is(st_point(0:1), \"POINT\")\nsfc = st_sfc(st_point(0:1), st_linestring(matrix(1:6,,2)))\nst_is(sfc, \"POINT\")\nst_is(sfc, \"POLYGON\")\nst_is(sfc, \"LINESTRING\")\nst_is(st_sf(a = 1:2, sfc), \"LINESTRING\")\nst_is(sfc, c(\"POINT\", \"LINESTRING\"))\n\n#1194:\nwkt <- \"MULTICURVE (COMPOUNDCURVE (LINESTRING (-83.62333 35.55244, -83.62328 35.55232, -83.62323 35.55223, -83.62319 35.55216, -83.62312 35.55209, -83.6231 35.55207), CIRCULARSTRING (-83.6231 35.55207, -83.62307 35.55205, -83.62302 35.55204), LINESTRING (-83.62302 35.55204, -83.62299 35.55203, -83.62289 35.55198, -83.62281 35.55189, -83.62271 35.55182)))\"\ng <- st_as_sfc(wkt)\ng <- st_sf(demo = \"test\", geom = g, crs = 4326)\nm = st_cast(g, \"MULTILINESTRING\")\nidentical(m$geom[[1]], st_cast(g$geom[[1]], \"MULTILINESTRING\"))\n\nst_cast(st_sfc(st_geometrycollection(), st_multipolygon()), 'MULTIPOLYGON') #1961\nst_cast(st_sfc(st_geometrycollection(), st_multipolygon(), st_point(0:1)), 'POINT') #1961\n"
  },
  {
    "path": "tests/cast.Rout.save",
    "content": "\nR Under development (unstable) (2025-11-05 r88988 ucrt) -- \"Unsuffered Consequences\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-w64-mingw32/x64\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> library(testthat)\n> # \"vertical\" conversions:\n> # column 1:\n> mp = st_sfc(st_multipoint(matrix(0:3,,2)), st_multipoint(matrix(10:15,,2)))\n> (ls = st_cast(mp, \"LINESTRING\"))\nGeometry set for 2 features \nGeometry type: LINESTRING\nDimension:     XY\nBounding box:  xmin: 0 ymin: 2 xmax: 12 ymax: 15\nCRS:           NA\nLINESTRING (0 2, 1 3)\nLINESTRING (10 13, 11 14, 12 15)\n> st_cast(ls, \"MULTIPOINT\")\nGeometry set for 2 features \nGeometry type: MULTIPOINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 2 xmax: 12 ymax: 15\nCRS:           NA\nMULTIPOINT ((0 2), (1 3))\nMULTIPOINT ((10 13), (11 14), (12 15))\n> \n> # column 2:\n> mls = st_sfc(st_multilinestring(list(rbind(c(0,0), c(10,0), c(10,10), c(0,10)), \n+ \trbind(c(5,5),c(5,6), c(6,6), c(6,5)))), \n+ \tst_multilinestring(list(rbind(c(0,0), c(1,0), c(1,1), c(0,1)))))\n> (pol = st_cast(mls, \"POLYGON\"))\nGeometry set for 2 features \nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 10 ymax: 10\nCRS:           NA\nPOLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (5 5, 5...\nPOLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))\n> st_cast(pol, \"MULTILINESTRING\")\nGeometry set for 2 features \nGeometry type: MULTILINESTRING\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 10 ymax: 10\nCRS:           NA\nMULTILINESTRING ((0 0, 10 0, 10 10, 0 10, 0 0),...\nMULTILINESTRING ((0 0, 1 0, 1 1, 0 1, 0 0))\n> \n> # \"horizontal\" conversions:\n> \n> (pt = st_cast(mp, \"POINT\"))\nGeometry set for 5 features \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 2 xmax: 12 ymax: 15\nCRS:           NA\nPOINT (0 2)\nPOINT (1 3)\nPOINT (10 13)\nPOINT (11 14)\nPOINT (12 15)\n> (i = attr(pt, \"ids\"))\n[1] 2 3\n> (xx = st_cast(pt, \"MULTIPOINT\", rep(seq_along(i), i)))\nGeometry set for 5 features \nGeometry type: MULTIPOINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 2 xmax: 12 ymax: 15\nCRS:           NA\nMULTIPOINT ((0 2))\nMULTIPOINT ((1 3))\nMULTIPOINT ((10 13))\nMULTIPOINT ((11 14))\nMULTIPOINT ((12 15))\n> try(yy <- st_cast(pt, \"LINESTRING\", rep(seq_along(i), i)))\n> \n> #(zz = st_cast(yy, \"MULTILINESTRING\"))\n> #(zz = st_cast(yy, \"POLYGON\"))\n> \n> st_cast(mls, \"LINESTRING\")\nGeometry set for 3 features \nGeometry type: LINESTRING\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 10 ymax: 10\nCRS:           NA\nLINESTRING (0 0, 10 0, 10 10, 0 10)\nLINESTRING (5 5, 5 6, 6 6, 6 5)\nLINESTRING (0 0, 1 0, 1 1, 0 1)\n> \n> (g = st_sfc(c(mls, ls)))\nGeometry set for 4 features \nGeometry type: GEOMETRY\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 12 ymax: 15\nCRS:           NA\nMULTILINESTRING ((0 0, 10 0, 10 10, 0 10), (5 5...\nMULTILINESTRING ((0 0, 1 0, 1 1, 0 1))\nLINESTRING (0 2, 1 3)\nLINESTRING (10 13, 11 14, 12 15)\n> st_cast(g, \"MULTILINESTRING\")\nGeometry set for 4 features \nGeometry type: MULTILINESTRING\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 12 ymax: 15\nCRS:           NA\nMULTILINESTRING ((0 0, 10 0, 10 10, 0 10), (5 5...\nMULTILINESTRING ((0 0, 1 0, 1 1, 0 1))\nMULTILINESTRING ((0 2, 1 3))\nMULTILINESTRING ((10 13, 11 14, 12 15))\n> expect_warning(st_cast(g, \"LINESTRING\"))\n> st_cast(st_cast(g, \"MULTILINESTRING\"), \"LINESTRING\") # will not loose\nGeometry set for 5 features \nGeometry type: LINESTRING\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 12 ymax: 15\nCRS:           NA\nLINESTRING (0 0, 10 0, 10 10, 0 10)\nLINESTRING (5 5, 5 6, 6 6, 6 5)\nLINESTRING (0 0, 1 0, 1 1, 0 1)\nLINESTRING (0 2, 1 3)\nLINESTRING (10 13, 11 14, 12 15)\n> \n> gc = st_sfc(st_geometrycollection(\n+   list(\n+     st_multilinestring(list(rbind(c(0,0), c(10,0), c(10,10), c(0,10)), \n+ \trbind(c(5,5),c(5,6), c(6,6), c(6,5)))), \n+ \tst_multilinestring(list(rbind(c(0,0), c(1,0), c(1,1), c(0,1)))),\n+ \tst_point(0:1)\n+   )))\n> try(st_cast(mls, \"POINT\"))\nGeometry set for 12 features \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 10 ymax: 10\nCRS:           NA\nFirst 5 geometries:\nPOINT (0 0)\nPOINT (10 0)\nPOINT (10 10)\nPOINT (0 10)\nPOINT (5 5)\n> try(st_cast(mls, \"MULTIPOINT\"))\nGeometry set for 3 features \nGeometry type: MULTIPOINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 10 ymax: 10\nCRS:           NA\nMULTIPOINT ((0 0), (10 0), (10 10), (0 10))\nMULTIPOINT ((5 5), (5 6), (6 6), (6 5))\nMULTIPOINT ((0 0), (1 0), (1 1), (0 1))\n> \n> outer = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\n> hole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\n> hole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\n> pol1 = list(outer, hole1, hole2)\n> pol2 = list(outer + 12, hole1 + 12)\n> pol3 = list(outer + 24)\n> mp = list(pol1,pol2,pol3)\n> mp1 = st_multipolygon(mp)\n> s = st_sfc(mp1)\n> x = st_cast(s, \"MULTIPOINT\")\n> x = st_cast(s, \"POINT\")\n> expect_warning(st_cast(mp1, \"LINESTRING\"))\n> expect_warning(st_cast(mp1, \"POINT\"))\n> mls = mls[[1]]\n> class(mls)\n[1] \"XY\"              \"MULTILINESTRING\" \"sfg\"            \n> #expect_error(st_cast(mls, \"POLYGON\"))\n> st_cast(mls, \"POLYGON\")\nPOLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (5 5, 5 6, 6 6, 6 5, 5 5))\n> \n> expect_warning(st_cast(mls, \"POINT\"))\n> p1 = st_polygon(pol1)\n> expect_warning(st_cast(p1, \"POINT\"))\n> ls = ls[[1]]\n> class(ls)\n[1] \"XY\"         \"LINESTRING\" \"sfg\"       \n> expect_warning(st_cast(ls, \"POINT\"))\n> \n> mls = st_cast(p1, \"MULTILINESTRING\")\n> p2 = st_cast(mls, \"POLYGON\")\n> \n> # st_is:\n> st_is(st_point(0:1), \"POINT\")\n[1] TRUE\n> sfc = st_sfc(st_point(0:1), st_linestring(matrix(1:6,,2)))\n> st_is(sfc, \"POINT\")\n[1]  TRUE FALSE\n> st_is(sfc, \"POLYGON\")\n[1] FALSE FALSE\n> st_is(sfc, \"LINESTRING\")\n[1] FALSE  TRUE\n> st_is(st_sf(a = 1:2, sfc), \"LINESTRING\")\n[1] FALSE  TRUE\n> st_is(sfc, c(\"POINT\", \"LINESTRING\"))\n[1] TRUE TRUE\n> \n> #1194:\n> wkt <- \"MULTICURVE (COMPOUNDCURVE (LINESTRING (-83.62333 35.55244, -83.62328 35.55232, -83.62323 35.55223, -83.62319 35.55216, -83.62312 35.55209, -83.6231 35.55207), CIRCULARSTRING (-83.6231 35.55207, -83.62307 35.55205, -83.62302 35.55204), LINESTRING (-83.62302 35.55204, -83.62299 35.55203, -83.62289 35.55198, -83.62281 35.55189, -83.62271 35.55182)))\"\n> g <- st_as_sfc(wkt)\n> g <- st_sf(demo = \"test\", geom = g, crs = 4326)\n> m = st_cast(g, \"MULTILINESTRING\")\n> identical(m$geom[[1]], st_cast(g$geom[[1]], \"MULTILINESTRING\"))\n[1] TRUE\n> \n> st_cast(st_sfc(st_geometrycollection(), st_multipolygon()), 'MULTIPOLYGON') #1961\nGeometry set for 2 features  (with 2 geometries empty)\nGeometry type: MULTIPOLYGON\nDimension:     XY\nBounding box:  xmin: NA ymin: NA xmax: NA ymax: NA\nCRS:           NA\nMULTIPOLYGON EMPTY\nMULTIPOLYGON EMPTY\n> st_cast(st_sfc(st_geometrycollection(), st_multipolygon(), st_point(0:1)), 'POINT') #1961\nGeometry set for 3 features  (with 2 geometries empty)\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1\nCRS:           NA\nPOINT EMPTY\nPOINT EMPTY\nPOINT (0 1)\n> \n> proc.time()\n   user  system elapsed \n   1.00    0.23    1.17 \n"
  },
  {
    "path": "tests/crs.R",
    "content": "suppressPackageStartupMessages(library(sf))\noptions(rgdal_show_exportToProj4_warnings = \"none\")\nsuppressWarnings(st_crs(-1))\nsuppressWarnings(st_crs(999999))\ninherits(try(st_crs(\"error\"), silent = TRUE), \"try-error\")\nstr = \"+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +towgs84=565.4171,50.3319,465.5524,-0.398957388243134,0.343987817378283,-1.87740163998045,4.0725 +units=m +no_defs\"\nx <- st_crs(str)\nx<- st_crs(3857)\nstr = st_crs(3857)$proj4string\nst_crs(3857)$units\nx = st_crs(\"+proj=longlat +datum=WGS84\")\nx = st_crs(4326)\nx = st_crs(\"+proj=laea\") # no EPSG\n\nx = st_sfc(st_point(0:1))\ny = st_crs(x, parameters = TRUE)\nst_crs(x) = 4326\ny = st_crs(x, parameters = TRUE)\n\nfrom = st_crs(4326)$proj4string\nto = st_crs(3857)$proj4string\nret = sf_project(from, to, rbind(c(0,0), c(1,1)))\nround(ret, 7)\n# create Inf points: #1227/#1228\nsuppressWarnings(\n  sf_project(\"+proj=longlat\", \"+proj=lcc +lat_1=30 +lat_2=60\", cbind(c(0,0),c(-80,-90)), keep = TRUE)\n)\nsf_project(to, from, ret)\nsuppressWarnings(\n  sf_project(\"+proj=longlat\", \"+proj=lcc +lat_1=30 +lat_2=60\", cbind(c(0,0),c(-80,-90)), keep = TRUE)\n)\nst_transform(st_sfc(st_point(c(0,0)), st_point(c(1,1)), crs = 4326), 3857)\nif (sf_extSoftVersion()[\"USE_PROJ_H\"] == \"true\" || sf_proj_info(\"have_datum_files\")) {\n  \"datum files installed\"\n} else {\n  \"datum files not installed\"\n}\n\n# https://github.com/r-spatial/sf/issues/1170\ng = st_as_sfc(\"POLYGON ((-61.66957 10.69214, -61.565 10.75728, -61.37453 10.77654, -61.40721 10.60681, -61.66957 10.69214))\")\nd = st_as_sf(data.frame(id=1, geometry=g), crs=4326)\nst_area(d)\nst_area(st_transform(d, 2314))\n\nst_axis_order()\nif (compareVersion(sf_extSoftVersion()[\"GDAL\"], \"2.5.0\") > -1)\n  st_axis_order(TRUE)\nst_axis_order(FALSE)\n"
  },
  {
    "path": "tests/crs.Rout.save",
    "content": "\nR Under development (unstable) (2025-11-05 r88988 ucrt) -- \"Unsuffered Consequences\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-w64-mingw32/x64\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> options(rgdal_show_exportToProj4_warnings = \"none\")\n> suppressWarnings(st_crs(-1))\nCoordinate Reference System: NA\n> suppressWarnings(st_crs(999999))\nCoordinate Reference System: NA\n> inherits(try(st_crs(\"error\"), silent = TRUE), \"try-error\")\n[1] TRUE\n> str = \"+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +towgs84=565.4171,50.3319,465.5524,-0.398957388243134,0.343987817378283,-1.87740163998045,4.0725 +units=m +no_defs\"\n> x <- st_crs(str)\n> x<- st_crs(3857)\n> str = st_crs(3857)$proj4string\n> st_crs(3857)$units\n[1] \"m\"\n> x = st_crs(\"+proj=longlat +datum=WGS84\")\n> x = st_crs(4326)\n> x = st_crs(\"+proj=laea\") # no EPSG\n> \n> x = st_sfc(st_point(0:1))\n> y = st_crs(x, parameters = TRUE)\n> st_crs(x) = 4326\n> y = st_crs(x, parameters = TRUE)\n> \n> from = st_crs(4326)$proj4string\n> to = st_crs(3857)$proj4string\n> ret = sf_project(from, to, rbind(c(0,0), c(1,1)))\n> round(ret, 7)\n         [,1]     [,2]\n[1,]      0.0      0.0\n[2,] 111319.5 111325.1\n> # create Inf points: #1227/#1228\n> suppressWarnings(\n+   sf_project(\"+proj=longlat\", \"+proj=lcc +lat_1=30 +lat_2=60\", cbind(c(0,0),c(-80,-90)), keep = TRUE)\n+ )\n     [,1]      [,2]\n[1,]    0 -53554590\n[2,]   NA        NA\n> sf_project(to, from, ret)\n     [,1] [,2]\n[1,]    0    0\n[2,]    1    1\n> suppressWarnings(\n+   sf_project(\"+proj=longlat\", \"+proj=lcc +lat_1=30 +lat_2=60\", cbind(c(0,0),c(-80,-90)), keep = TRUE)\n+ )\n     [,1]      [,2]\n[1,]    0 -53554590\n[2,]   NA        NA\n> st_transform(st_sfc(st_point(c(0,0)), st_point(c(1,1)), crs = 4326), 3857)\nGeometry set for 2 features \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 111319.5 ymax: 111325.1\nProjected CRS: WGS 84 / Pseudo-Mercator\nPOINT (0 0)\nPOINT (111319.5 111325.1)\n> if (sf_extSoftVersion()[\"USE_PROJ_H\"] == \"true\" || sf_proj_info(\"have_datum_files\")) {\n+   \"datum files installed\"\n+ } else {\n+   \"datum files not installed\"\n+ }\n[1] \"datum files installed\"\n> \n> # https://github.com/r-spatial/sf/issues/1170\n> g = st_as_sfc(\"POLYGON ((-61.66957 10.69214, -61.565 10.75728, -61.37453 10.77654, -61.40721 10.60681, -61.66957 10.69214))\")\n> d = st_as_sf(data.frame(id=1, geometry=g), crs=4326)\n> st_area(d)\n350534486 [m^2]\n> st_area(st_transform(d, 2314))\n349124497 [m^2]\n> \n> st_axis_order()\n[1] FALSE\n> if (compareVersion(sf_extSoftVersion()[\"GDAL\"], \"2.5.0\") > -1)\n+   st_axis_order(TRUE)\n> st_axis_order(FALSE)\n> \n> proc.time()\n   user  system elapsed \n   0.51    0.20    0.70 \n"
  },
  {
    "path": "tests/dist.R",
    "content": "suppressPackageStartupMessages(library(sf))\nsuppressPackageStartupMessages(library(units))\n\nx = st_sfc(\nst_point(c(0,0)),\nst_point(c(1,0)),\nst_point(c(2,0)),\nst_point(c(3,0)),\ncrs = 4326\n)\n\ny = st_sfc(\nst_point(c(0,10)),\nst_point(c(1,0)),\nst_point(c(2,0)),\nst_point(c(3,0)),\nst_point(c(4,0)),\ncrs = 4326\n)\n\nif (suppressPackageStartupMessages(require(sp, quietly = TRUE))) {\n d.sf = st_distance(x, y)\n d.sp = spDists(as(x, \"Spatial\"), as(y, \"Spatial\"))\n units(d.sp) = as_units(\"km\")\n print(round(d.sf - d.sp, 7))\n\n#summary(unclass(d.sf) - d.sp)\n\n st_crs(x) = st_crs(y) = NA\n d.sf = st_distance(x, y)\n d.sp = spDists(as(x, \"Spatial\"), as(y, \"Spatial\"))\n print(round(d.sf - d.sp, 7))\n}\n\n# st_length:\nst_crs(y) = 4326\n(z = st_sfc(st_linestring(rbind(c(0,10), c(1,0), c(2,0), c(3,0), c(4,0))), crs = 4326))\nd = st_distance(y, y)\nround(d, 7)\nst_length(z)\nround(st_length(z) - sum(d[1,2], d[2,3], d[3,4], d[4,5]), 7)\n\n# st_line_sample:\nls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))),\n\tst_linestring(rbind(c(0,0),c(10,0))))\n# set.seed(135)\nst_line_sample(ls, density = 1)\n\nls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))),\n\tst_linestring(rbind(c(0,0),c(.1,0))), crs = 4326)\n\nst_length(ls)\ntry(st_line_sample(ls, density = 1/1000))\nx = st_line_sample(st_transform(ls, 3857), density = 1/1000) # one per km\n"
  },
  {
    "path": "tests/dist.Rout.save",
    "content": "\nR Under development (unstable) (2025-11-05 r88988 ucrt) -- \"Unsuffered Consequences\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-w64-mingw32/x64\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> suppressPackageStartupMessages(library(units))\n> \n> x = st_sfc(\n+ st_point(c(0,0)),\n+ st_point(c(1,0)),\n+ st_point(c(2,0)),\n+ st_point(c(3,0)),\n+ crs = 4326\n+ )\n> \n> y = st_sfc(\n+ st_point(c(0,10)),\n+ st_point(c(1,0)),\n+ st_point(c(2,0)),\n+ st_point(c(3,0)),\n+ st_point(c(4,0)),\n+ crs = 4326\n+ )\n> \n> if (suppressPackageStartupMessages(require(sp, quietly = TRUE))) {\n+  d.sf = st_distance(x, y)\n+  d.sp = spDists(as(x, \"Spatial\"), as(y, \"Spatial\"))\n+  units(d.sp) = as_units(\"km\")\n+  print(round(d.sf - d.sp, 7))\n+ \n+ #summary(unclass(d.sf) - d.sp)\n+ \n+  st_crs(x) = st_crs(y) = NA\n+  d.sf = st_distance(x, y)\n+  d.sp = spDists(as(x, \"Spatial\"), as(y, \"Spatial\"))\n+  print(round(d.sf - d.sp, 7))\n+ }\nUnits: [m]\n         [,1]      [,2]      [,3]      [,4]      [,5]\n[1,] 6107.765 -124.3896 -248.7792 -373.1688 -497.5585\n[2,] 6065.138    0.0000 -124.3896 -248.7792 -373.1688\n[3,] 5940.569 -124.3896    0.0000 -124.3896 -248.7792\n[4,] 5743.252 -248.7792 -124.3896    0.0000 -124.3896\n     [,1] [,2] [,3] [,4] [,5]\n[1,]    0    0    0    0    0\n[2,]    0    0    0    0    0\n[3,]    0    0    0    0    0\n[4,]    0    0    0    0    0\n> \n> # st_length:\n> st_crs(y) = 4326\n> (z = st_sfc(st_linestring(rbind(c(0,10), c(1,0), c(2,0), c(3,0), c(4,0))), crs = 4326))\nGeometry set for 1 feature \nGeometry type: LINESTRING\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 4 ymax: 10\nGeodetic CRS:  WGS 84\nLINESTRING (0 10, 1 0, 2 0, 3 0, 4 0)\n> d = st_distance(y, y)\n> round(d, 7)\nUnits: [m]\n        [,1]      [,2]      [,3]      [,4]      [,5]\n[1,]       0 1117440.6 1133750.1 1160423.1 1196767.0\n[2,] 1117441       0.0  111195.1  222390.2  333585.3\n[3,] 1133750  111195.1       0.0  111195.1  222390.2\n[4,] 1160423  222390.2  111195.1       0.0  111195.1\n[5,] 1196767  333585.3  222390.2  111195.1       0.0\n> st_length(z)\n1451026 [m]\n> round(st_length(z) - sum(d[1,2], d[2,3], d[3,4], d[4,5]), 7)\n0 [m]\n> \n> # st_line_sample:\n> ls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))),\n+ \tst_linestring(rbind(c(0,0),c(10,0))))\n> # set.seed(135)\n> st_line_sample(ls, density = 1)\nGeometry set for 2 features \nGeometry type: MULTIPOINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 9.5 ymax: 0.5\nCRS:           NA\nMULTIPOINT ((0 0.5))\nMULTIPOINT ((0.5 0), (1.5 0), (2.5 0), (3.5 0),...\n> \n> ls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))),\n+ \tst_linestring(rbind(c(0,0),c(.1,0))), crs = 4326)\n> \n> st_length(ls)\nUnits: [m]\n[1] 111195.10  11119.51\n> try(st_line_sample(ls, density = 1/1000))\nError in st_line_sample(ls, density = 1/1000) : \n  st_line_sample for longitude/latitude not supported; use st_segmentize?\n> x = st_line_sample(st_transform(ls, 3857), density = 1/1000) # one per km\n> \n> proc.time()\n   user  system elapsed \n   0.65    0.20    0.79 \n"
  },
  {
    "path": "tests/dplyr.R",
    "content": "suppressPackageStartupMessages(library(sf))\n\nif (require(dplyr, quietly = TRUE) && require(tidyr, quietly = TRUE)) {\n options(dplyr.summarise.inform=FALSE)\n read_sf(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE) |>\n\tst_transform(3857) -> nc\n nc |> filter(AREA > .1) |> plot()\n\n# plot 10 smallest counties in grey:\n nc |> \n   select(BIR74, geometry) |> \n   plot()\n\n nc |> \n  select(AREA, geometry) |> \n  arrange(AREA) |> \n  slice(1:10) |> \n  plot(add = TRUE, col = 'grey', main =\"\")\n\n# select: check both when geometry is part of the selection, and when not:\n nc |> select(SID74, SID79) |> names()\n nc |> select(SID74, SID79, geometry) |> names()\n nc |> select(SID74, SID79) |> class()\n nc |> select(SID74, SID79, geometry) |> class()\n\n# group_by:\n nc$area_cl = cut(nc$AREA, c(0, .1, .12, .15, .25))\n nc |> group_by(area_cl) |> class()\n\n# mutate:\n nc2 <- nc |> mutate(area10 = AREA/10)\n\n# transmute:\n nc |> transmute(AREA = AREA/10, geometry = geometry) |> class()\n nc |> transmute(AREA = AREA/10) |> class()\n\n# rename:\n nc2 <- nc |> rename(area = AREA)\n\n# distinct:\n nc[c(1:100,1:10),] |> distinct() |> nrow()\n\n# summarize:\n nc$area_cl = cut(nc$AREA, c(0, .1, .12, .15, .25))\n nc.g <- nc |> group_by(area_cl)\n nc.g |> summarise(mean(AREA))\n nc.g |> summarize(mean(AREA)) |> plot(col = 3:6/7)\n\n library(tidyr)\n\n# time-wide to long table, using tidyr::gather\n# stack the two SID columns for the July 1, 1974 - June 30, 1978 and July 1, 1979 - June 30, 1984 periods\n# (see https://cran.r-project.org/web/packages/spdep/vignettes/sids.pdf)\n nc |> select(SID74, SID79, geometry) |> gather(\"VAR\", \"SID\", -geometry) |> summary()\n\n# spread:\n nc$row = 1:100\n nc.g <- nc |> select(SID74, SID79, row) |> gather(\"VAR\", \"SID\", -row, -geometry)\n nc.g |> tail()\n nc.g |> spread(VAR, SID) |> head()\n nc |> select(SID74, SID79, geometry, row) |> gather(\"VAR\", \"SID\", -geometry, -row) |> spread(VAR, SID) |> head()\n\n# test st_set_crs in pipe:\n sfc = st_sfc(st_point(c(0,0)), st_point(c(1,1)))\n x <- sfc |> st_set_crs(4326) |> st_transform(3857)\n x\n\nread_sf(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE) |>\n\tst_transform(3857) -> nc\n nc.merc <- st_transform(nc, 32119) # NC State Plane\n suppressPackageStartupMessages(library(units))\n install_unit(\"person\")\n person = as_units(\"person\")\n nc.merc <- nc.merc |> mutate(area = st_area(nc.merc), dens = BIR74 * person / area)\n\n# summary(nc.merc$dens) # requires units 0.4-2\n nc.merc$area_cl <- cut(nc$AREA, c(0, .1, .12, .15, .25))\n nc.grp <- nc.merc |> group_by(area_cl)\n\n out <- nc.grp |> summarise(A = sum(area), pop = sum(dens * area), \n\tnew_dens = sum(dens * area)/sum(area)) \n\n# mean densities depend on grouping:\n nc.merc |> summarize(mean(dens))\n out |> summarise(mean(new_dens))\n\n# total densities don't:\n nc.merc |> summarise(sum(area * dens))\n out |> summarise(sum(A * new_dens))\n\n conn = system.file(\"gpkg/nc.gpkg\", package = \"sf\")\n\nif (require(DBI, quietly = TRUE) && require(RSQLite, quietly = TRUE)) {\n con = dbConnect(SQLite(), dbname = system.file(\"gpkg/nc.gpkg\", package = \"sf\"))\n dbReadTable(con, \"nc.gpkg\") |> filter(AREA > 0.2) |> collect() |> st_sf()\n\n# nest:\n storms.sf = st_as_sf(storms, coords = c(\"long\", \"lat\"), crs = 4326)\n x <- storms.sf |> group_by(name, year) |> nest()\n\n nrow(distinct(nc[c(1,1,1,2,2,3:100),]))\n\n# set.seed(1331)\n nc$gp <- sample(10, 100, replace=TRUE)\n# Get centroid of each group of polygons; https://github.com/r-spatial/sf/issues/969\n nc_gp_cent <- nc |>\n                group_by(gp) |>\n                group_map(st_area)\n\n nc |> st_filter(nc[1,]) |> nrow()\n} # DBI & SQLITE\n} # dplyr & tidyr\n"
  },
  {
    "path": "tests/dplyr.Rout.save",
    "content": "\nR version 4.6.0 (2026-04-24) -- \"Because it was There\"\nCopyright (C) 2026 The R Foundation for Statistical Computing\nPlatform: x86_64-pc-linux-gnu\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> \n> if (require(dplyr, quietly = TRUE) && require(tidyr, quietly = TRUE)) {\n+  options(dplyr.summarise.inform=FALSE)\n+  read_sf(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE) |>\n+ \tst_transform(3857) -> nc\n+  nc |> filter(AREA > .1) |> plot()\n+ \n+ # plot 10 smallest counties in grey:\n+  nc |> \n+    select(BIR74, geometry) |> \n+    plot()\n+ \n+  nc |> \n+   select(AREA, geometry) |> \n+   arrange(AREA) |> \n+   slice(1:10) |> \n+   plot(add = TRUE, col = 'grey', main =\"\")\n+ \n+ # select: check both when geometry is part of the selection, and when not:\n+  nc |> select(SID74, SID79) |> names()\n+  nc |> select(SID74, SID79, geometry) |> names()\n+  nc |> select(SID74, SID79) |> class()\n+  nc |> select(SID74, SID79, geometry) |> class()\n+ \n+ # group_by:\n+  nc$area_cl = cut(nc$AREA, c(0, .1, .12, .15, .25))\n+  nc |> group_by(area_cl) |> class()\n+ \n+ # mutate:\n+  nc2 <- nc |> mutate(area10 = AREA/10)\n+ \n+ # transmute:\n+  nc |> transmute(AREA = AREA/10, geometry = geometry) |> class()\n+  nc |> transmute(AREA = AREA/10) |> class()\n+ \n+ # rename:\n+  nc2 <- nc |> rename(area = AREA)\n+ \n+ # distinct:\n+  nc[c(1:100,1:10),] |> distinct() |> nrow()\n+ \n+ # summarize:\n+  nc$area_cl = cut(nc$AREA, c(0, .1, .12, .15, .25))\n+  nc.g <- nc |> group_by(area_cl)\n+  nc.g |> summarise(mean(AREA))\n+  nc.g |> summarize(mean(AREA)) |> plot(col = 3:6/7)\n+ \n+  library(tidyr)\n+ \n+ # time-wide to long table, using tidyr::gather\n+ # stack the two SID columns for the July 1, 1974 - June 30, 1978 and July 1, 1979 - June 30, 1984 periods\n+ # (see https://cran.r-project.org/web/packages/spdep/vignettes/sids.pdf)\n+  nc |> select(SID74, SID79, geometry) |> gather(\"VAR\", \"SID\", -geometry) |> summary()\n+ \n+ # spread:\n+  nc$row = 1:100\n+  nc.g <- nc |> select(SID74, SID79, row) |> gather(\"VAR\", \"SID\", -row, -geometry)\n+  nc.g |> tail()\n+  nc.g |> spread(VAR, SID) |> head()\n+  nc |> select(SID74, SID79, geometry, row) |> gather(\"VAR\", \"SID\", -geometry, -row) |> spread(VAR, SID) |> head()\n+ \n+ # test st_set_crs in pipe:\n+  sfc = st_sfc(st_point(c(0,0)), st_point(c(1,1)))\n+  x <- sfc |> st_set_crs(4326) |> st_transform(3857)\n+  x\n+ \n+ read_sf(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE) |>\n+ \tst_transform(3857) -> nc\n+  nc.merc <- st_transform(nc, 32119) # NC State Plane\n+  suppressPackageStartupMessages(library(units))\n+  install_unit(\"person\")\n+  person = as_units(\"person\")\n+  nc.merc <- nc.merc |> mutate(area = st_area(nc.merc), dens = BIR74 * person / area)\n+ \n+ # summary(nc.merc$dens) # requires units 0.4-2\n+  nc.merc$area_cl <- cut(nc$AREA, c(0, .1, .12, .15, .25))\n+  nc.grp <- nc.merc |> group_by(area_cl)\n+ \n+  out <- nc.grp |> summarise(A = sum(area), pop = sum(dens * area), \n+ \tnew_dens = sum(dens * area)/sum(area)) \n+ \n+ # mean densities depend on grouping:\n+  nc.merc |> summarize(mean(dens))\n+  out |> summarise(mean(new_dens))\n+ \n+ # total densities don't:\n+  nc.merc |> summarise(sum(area * dens))\n+  out |> summarise(sum(A * new_dens))\n+ \n+  conn = system.file(\"gpkg/nc.gpkg\", package = \"sf\")\n+ \n+ if (require(DBI, quietly = TRUE) && require(RSQLite, quietly = TRUE)) {\n+  con = dbConnect(SQLite(), dbname = system.file(\"gpkg/nc.gpkg\", package = \"sf\"))\n+  dbReadTable(con, \"nc.gpkg\") |> filter(AREA > 0.2) |> collect() |> st_sf()\n+ \n+ # nest:\n+  storms.sf = st_as_sf(storms, coords = c(\"long\", \"lat\"), crs = 4326)\n+  x <- storms.sf |> group_by(name, year) |> nest()\n+ \n+  nrow(distinct(nc[c(1,1,1,2,2,3:100),]))\n+ \n+ # set.seed(1331)\n+  nc$gp <- sample(10, 100, replace=TRUE)\n+ # Get centroid of each group of polygons; https://github.com/r-spatial/sf/issues/969\n+  nc_gp_cent <- nc |>\n+                 group_by(gp) |>\n+                 group_map(st_area)\n+ \n+  nc |> st_filter(nc[1,]) |> nrow()\n+ } # DBI & SQLITE\n+ } # dplyr & tidyr\n\nAttaching package: 'dplyr'\n\nThe following objects are masked from 'package:stats':\n\n    filter, lag\n\nThe following objects are masked from 'package:base':\n\n    intersect, setdiff, setequal, union\n\n[1] 4\nWarning message:\nplotting the first 10 out of 14 attributes; use max.plot = 14 to plot all \n> \n> proc.time()\n   user  system elapsed \n  1.692   1.299   1.596 \n"
  },
  {
    "path": "tests/empty.R",
    "content": "suppressPackageStartupMessages(library(sf))\n\n# create empty geometries:\nst_point(rep(NA_real_,2))\nst_point(rep(NA_real_,3), dim = \"XYZ\")\nst_point(rep(NA_real_,3), dim = \"XYM\")\nst_point(rep(NA_real_,4), dim = \"XYZM\")\n\nst_multipoint()\nst_multipoint(matrix(numeric(0), 0, 3), dim = \"XYZ\")\nst_multipoint(matrix(numeric(0), 0, 3), dim = \"XYM\")\nst_multipoint(matrix(numeric(0), 0, 4), dim = \"XYZM\")\n\nst_linestring(matrix(numeric(0), 0, 2), \"XY\")\nst_linestring(matrix(numeric(0), 0, 3), \"XYZ\")\nst_linestring(matrix(numeric(0), 0, 3), \"XYM\")\nst_linestring(matrix(numeric(0), 0, 4), \"XYZM\")\n\nst_multilinestring(list(), \"XY\")\nst_multilinestring(list(), \"XYZ\")\nst_multilinestring(list(), \"XYM\")\nst_multilinestring(list(), \"XYZM\")\n\nst_polygon(list(), \"XY\")\nst_polygon(list(), \"XYZ\")\nst_polygon(list(), \"XYM\")\nst_polygon(list(), \"XYZM\")\n\nst_multipolygon(list(), \"XY\")\nst_multipolygon(list(), \"XYZ\")\nst_multipolygon(list(), \"XYM\")\nst_multipolygon(list(), \"XYZM\")\n\nst_geometrycollection()\nst_geometrycollection(dim = \"XYZ\")\nst_geometrycollection(dim = \"XYM\")\nst_geometrycollection(dim = \"XYZM\")\n\nst_point(rep(NA_real_,2))\nst_multipoint()\nst_linestring(matrix(numeric(0), 0, 2))\nst_multilinestring(list(), \"XY\")\nst_polygon(list(), \"XY\")\nst_multipolygon(list(), \"XY\")\nst_geometrycollection(, \"XY\")\n\n(e1 = st_sfc(\nst_point(rep(NA_real_,2)),\nst_multipoint(),\nst_linestring(matrix(numeric(0), 0, 2)),\nst_multilinestring(list(), \"XY\"),\nst_polygon(list(), \"XY\"),\nst_multipolygon(list(), \"XY\"),\nst_geometrycollection(, \"XY\")))\n\n(e2 = st_sfc(st_point(rep(NA_real_,3), \"XYZ\"),\nst_multipoint(matrix(numeric(0),0,3), dim = \"XYZ\"),\nst_linestring(matrix(numeric(0), 0, 3)),\nst_multilinestring(list(), \"XYZ\"),\nst_polygon(list(), \"XYZ\"),\nst_multipolygon(list(), \"XYZ\"),\nst_geometrycollection(dim = \"XYZ\")))\n\n(e3 = st_sfc(st_point(rep(NA_real_,3), \"XYM\"),\nst_multipoint(matrix(numeric(0),0,3), dim = \"XYM\"),\nst_linestring(matrix(numeric(0), 0, 3), \"XYM\"),\nst_multilinestring(list(), \"XYM\"),\nst_polygon(list(), \"XYM\"),\nst_multipolygon(list(), \"XYM\"),\nst_geometrycollection(dim = \"XYM\")))\n\n(e4 = st_sfc(st_point(rep(NA_real_,4)),\nst_multipoint(matrix(numeric(0),0,4), dim = \"XYZM\"),\nst_linestring(matrix(numeric(0), 0, 4)),\nst_multilinestring(list(), \"XYZM\"),\nst_polygon(list(), \"XYZM\"),\nst_multipolygon(list(), \"XYZM\"),\nst_geometrycollection(dim = \"XYZM\")))\n\nst_as_sfc(st_as_binary(e1, pureR = TRUE))\nst_as_sfc(st_as_binary(e1, pureR = FALSE))\nst_as_sfc(st_as_binary(e2, pureR = FALSE))\nst_as_sfc(st_as_binary(e3, pureR = FALSE))\nst_as_sfc(st_as_binary(e4, pureR = FALSE))\nst_as_sfc(st_as_binary(e1, pureR = FALSE))\n\n# sfc_GEOMETRY:\nx = st_sfc(st_point(0:1), st_linestring(matrix(1:4,2,2)))\nst_intersects(x, x, sparse = FALSE)\n\n# two empty geoms:\nx = st_sfc(st_multipoint(), st_linestring())\nst_intersects(x, x, sparse = FALSE)\n\n# write & read:\nx = st_sf(a = 2:1, geom = structure(st_sfc(st_linestring(), st_linestring(matrix(1:4,2)))))\nwrite_sf(x, \"empty.gpkg\")\ny = st_read(\"empty.gpkg\", quiet = TRUE)\nall.equal(x, y)\n\n# https://github.com/edzer/sfr/issues/398 :\npt = st_sfc(st_point(c(0,92)), crs = 4267)\nrobin_crs <- \"+proj=robin +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs\"\n# india_crs <- \"EPSG:24383\"  # India-centered Lambert conformal conic projection\nindia_crs <- \"+proj=lcc +lat_1=12 +lat_0=12 +lon_0=80 +k_0=0.99878641 +x_0=2743195.5 +y_0=914398.5 +a=6377299.151 +b=6356098.145120132 +towgs84=295,736,257,0,0,0,0 +units=m +no_defs\"\nst_transform(st_transform(pt, robin_crs), india_crs)[[1]]\n"
  },
  {
    "path": "tests/empty.Rout.save",
    "content": "\nR Under development (unstable) (2025-11-05 r88988 ucrt) -- \"Unsuffered Consequences\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-w64-mingw32/x64\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> \n> # create empty geometries:\n> st_point(rep(NA_real_,2))\nPOINT EMPTY\n> st_point(rep(NA_real_,3), dim = \"XYZ\")\nPOINT Z EMPTY\n> st_point(rep(NA_real_,3), dim = \"XYM\")\nPOINT M EMPTY\n> st_point(rep(NA_real_,4), dim = \"XYZM\")\nPOINT ZM EMPTY\n> \n> st_multipoint()\nMULTIPOINT EMPTY\n> st_multipoint(matrix(numeric(0), 0, 3), dim = \"XYZ\")\nMULTIPOINT Z EMPTY\n> st_multipoint(matrix(numeric(0), 0, 3), dim = \"XYM\")\nMULTIPOINT M EMPTY\n> st_multipoint(matrix(numeric(0), 0, 4), dim = \"XYZM\")\nMULTIPOINT ZM EMPTY\n> \n> st_linestring(matrix(numeric(0), 0, 2), \"XY\")\nLINESTRING EMPTY\n> st_linestring(matrix(numeric(0), 0, 3), \"XYZ\")\nLINESTRING Z EMPTY\n> st_linestring(matrix(numeric(0), 0, 3), \"XYM\")\nLINESTRING M EMPTY\n> st_linestring(matrix(numeric(0), 0, 4), \"XYZM\")\nLINESTRING ZM EMPTY\n> \n> st_multilinestring(list(), \"XY\")\nMULTILINESTRING EMPTY\n> st_multilinestring(list(), \"XYZ\")\nMULTILINESTRING Z EMPTY\n> st_multilinestring(list(), \"XYM\")\nMULTILINESTRING M EMPTY\n> st_multilinestring(list(), \"XYZM\")\nMULTILINESTRING ZM EMPTY\n> \n> st_polygon(list(), \"XY\")\nPOLYGON EMPTY\n> st_polygon(list(), \"XYZ\")\nPOLYGON Z EMPTY\n> st_polygon(list(), \"XYM\")\nPOLYGON M EMPTY\n> st_polygon(list(), \"XYZM\")\nPOLYGON ZM EMPTY\n> \n> st_multipolygon(list(), \"XY\")\nMULTIPOLYGON EMPTY\n> st_multipolygon(list(), \"XYZ\")\nMULTIPOLYGON Z EMPTY\n> st_multipolygon(list(), \"XYM\")\nMULTIPOLYGON M EMPTY\n> st_multipolygon(list(), \"XYZM\")\nMULTIPOLYGON ZM EMPTY\n> \n> st_geometrycollection()\nGEOMETRYCOLLECTION EMPTY\n> st_geometrycollection(dim = \"XYZ\")\nGEOMETRYCOLLECTION Z EMPTY\n> st_geometrycollection(dim = \"XYM\")\nGEOMETRYCOLLECTION M EMPTY\n> st_geometrycollection(dim = \"XYZM\")\nGEOMETRYCOLLECTION ZM EMPTY\n> \n> st_point(rep(NA_real_,2))\nPOINT EMPTY\n> st_multipoint()\nMULTIPOINT EMPTY\n> st_linestring(matrix(numeric(0), 0, 2))\nLINESTRING EMPTY\n> st_multilinestring(list(), \"XY\")\nMULTILINESTRING EMPTY\n> st_polygon(list(), \"XY\")\nPOLYGON EMPTY\n> st_multipolygon(list(), \"XY\")\nMULTIPOLYGON EMPTY\n> st_geometrycollection(, \"XY\")\nGEOMETRYCOLLECTION EMPTY\n> \n> (e1 = st_sfc(\n+ st_point(rep(NA_real_,2)),\n+ st_multipoint(),\n+ st_linestring(matrix(numeric(0), 0, 2)),\n+ st_multilinestring(list(), \"XY\"),\n+ st_polygon(list(), \"XY\"),\n+ st_multipolygon(list(), \"XY\"),\n+ st_geometrycollection(, \"XY\")))\nGeometry set for 7 features  (with 7 geometries empty)\nGeometry type: GEOMETRY\nDimension:     XY\nBounding box:  xmin: NA ymin: NA xmax: NA ymax: NA\nCRS:           NA\nFirst 5 geometries:\nPOINT EMPTY\nMULTIPOINT EMPTY\nLINESTRING EMPTY\nMULTILINESTRING EMPTY\nPOLYGON EMPTY\n> \n> (e2 = st_sfc(st_point(rep(NA_real_,3), \"XYZ\"),\n+ st_multipoint(matrix(numeric(0),0,3), dim = \"XYZ\"),\n+ st_linestring(matrix(numeric(0), 0, 3)),\n+ st_multilinestring(list(), \"XYZ\"),\n+ st_polygon(list(), \"XYZ\"),\n+ st_multipolygon(list(), \"XYZ\"),\n+ st_geometrycollection(dim = \"XYZ\")))\nGeometry set for 7 features  (with 7 geometries empty)\nGeometry type: GEOMETRY\nDimension:     XYZ\nBounding box:  xmin: NA ymin: NA xmax: NA ymax: NA\nz_range:       zmin: NA zmax: NA\nCRS:           NA\nFirst 5 geometries:\nPOINT Z EMPTY\nMULTIPOINT Z EMPTY\nLINESTRING Z EMPTY\nMULTILINESTRING Z EMPTY\nPOLYGON Z EMPTY\n> \n> (e3 = st_sfc(st_point(rep(NA_real_,3), \"XYM\"),\n+ st_multipoint(matrix(numeric(0),0,3), dim = \"XYM\"),\n+ st_linestring(matrix(numeric(0), 0, 3), \"XYM\"),\n+ st_multilinestring(list(), \"XYM\"),\n+ st_polygon(list(), \"XYM\"),\n+ st_multipolygon(list(), \"XYM\"),\n+ st_geometrycollection(dim = \"XYM\")))\nGeometry set for 7 features  (with 7 geometries empty)\nGeometry type: GEOMETRY\nDimension:     XYM\nBounding box:  xmin: NA ymin: NA xmax: NA ymax: NA\nm_range:       mmin: NA mmax: NA\nCRS:           NA\nFirst 5 geometries:\nPOINT M EMPTY\nMULTIPOINT M EMPTY\nLINESTRING M EMPTY\nMULTILINESTRING M EMPTY\nPOLYGON M EMPTY\n> \n> (e4 = st_sfc(st_point(rep(NA_real_,4)),\n+ st_multipoint(matrix(numeric(0),0,4), dim = \"XYZM\"),\n+ st_linestring(matrix(numeric(0), 0, 4)),\n+ st_multilinestring(list(), \"XYZM\"),\n+ st_polygon(list(), \"XYZM\"),\n+ st_multipolygon(list(), \"XYZM\"),\n+ st_geometrycollection(dim = \"XYZM\")))\nGeometry set for 7 features  (with 7 geometries empty)\nGeometry type: GEOMETRY\nDimension:     XYZM\nBounding box:  xmin: NA ymin: NA xmax: NA ymax: NA\nz_range:       zmin: NA zmax: NA\nm_range:       mmin: NA mmax: NA\nCRS:           NA\nFirst 5 geometries:\nPOINT ZM EMPTY\nMULTIPOINT ZM EMPTY\nLINESTRING ZM EMPTY\nMULTILINESTRING ZM EMPTY\nPOLYGON ZM EMPTY\n> \n> st_as_sfc(st_as_binary(e1, pureR = TRUE))\nGeometry set for 7 features  (with 7 geometries empty)\nGeometry type: GEOMETRY\nDimension:     XY\nBounding box:  xmin: NA ymin: NA xmax: NA ymax: NA\nCRS:           NA\nFirst 5 geometries:\nPOINT EMPTY\nMULTIPOINT EMPTY\nLINESTRING EMPTY\nMULTILINESTRING EMPTY\nPOLYGON EMPTY\n> st_as_sfc(st_as_binary(e1, pureR = FALSE))\nGeometry set for 7 features  (with 7 geometries empty)\nGeometry type: GEOMETRY\nDimension:     XY\nBounding box:  xmin: NA ymin: NA xmax: NA ymax: NA\nCRS:           NA\nFirst 5 geometries:\nPOINT EMPTY\nMULTIPOINT EMPTY\nLINESTRING EMPTY\nMULTILINESTRING EMPTY\nPOLYGON EMPTY\n> st_as_sfc(st_as_binary(e2, pureR = FALSE))\nGeometry set for 7 features  (with 7 geometries empty)\nGeometry type: GEOMETRY\nDimension:     XYZ\nBounding box:  xmin: NA ymin: NA xmax: NA ymax: NA\nz_range:       zmin: NA zmax: NA\nCRS:           NA\nFirst 5 geometries:\nPOINT Z EMPTY\nMULTIPOINT Z EMPTY\nLINESTRING Z EMPTY\nMULTILINESTRING Z EMPTY\nPOLYGON Z EMPTY\n> st_as_sfc(st_as_binary(e3, pureR = FALSE))\nGeometry set for 7 features  (with 7 geometries empty)\nGeometry type: GEOMETRY\nDimension:     XYM\nBounding box:  xmin: NA ymin: NA xmax: NA ymax: NA\nm_range:       mmin: NA mmax: NA\nCRS:           NA\nFirst 5 geometries:\nPOINT M EMPTY\nMULTIPOINT M EMPTY\nLINESTRING M EMPTY\nMULTILINESTRING M EMPTY\nPOLYGON M EMPTY\n> st_as_sfc(st_as_binary(e4, pureR = FALSE))\nGeometry set for 7 features  (with 7 geometries empty)\nGeometry type: GEOMETRY\nDimension:     XYZM\nBounding box:  xmin: NA ymin: NA xmax: NA ymax: NA\nz_range:       zmin: NA zmax: NA\nm_range:       mmin: NA mmax: NA\nCRS:           NA\nFirst 5 geometries:\nPOINT ZM EMPTY\nMULTIPOINT ZM EMPTY\nLINESTRING ZM EMPTY\nMULTILINESTRING ZM EMPTY\nPOLYGON ZM EMPTY\n> st_as_sfc(st_as_binary(e1, pureR = FALSE))\nGeometry set for 7 features  (with 7 geometries empty)\nGeometry type: GEOMETRY\nDimension:     XY\nBounding box:  xmin: NA ymin: NA xmax: NA ymax: NA\nCRS:           NA\nFirst 5 geometries:\nPOINT EMPTY\nMULTIPOINT EMPTY\nLINESTRING EMPTY\nMULTILINESTRING EMPTY\nPOLYGON EMPTY\n> \n> # sfc_GEOMETRY:\n> x = st_sfc(st_point(0:1), st_linestring(matrix(1:4,2,2)))\n> st_intersects(x, x, sparse = FALSE)\n      [,1]  [,2]\n[1,]  TRUE FALSE\n[2,] FALSE  TRUE\n> \n> # two empty geoms:\n> x = st_sfc(st_multipoint(), st_linestring())\n> st_intersects(x, x, sparse = FALSE)\n      [,1]  [,2]\n[1,] FALSE FALSE\n[2,] FALSE FALSE\n> \n> # write & read:\n> x = st_sf(a = 2:1, geom = structure(st_sfc(st_linestring(), st_linestring(matrix(1:4,2)))))\n> write_sf(x, \"empty.gpkg\")\nwriting: substituting ENGCRS[\"Undefined Cartesian SRS with unknown unit\"] for missing CRS\n> y = st_read(\"empty.gpkg\", quiet = TRUE)\n> all.equal(x, y)\n[1] \"Component \\\"geom\\\": Attributes: < Component \\\"crs\\\": Component \\\"input\\\": 'is.NA' value mismatch: 0 in current 1 in target >\"\n[2] \"Component \\\"geom\\\": Attributes: < Component \\\"crs\\\": Component \\\"wkt\\\": 'is.NA' value mismatch: 0 in current 1 in target >\"  \n> \n> # https://github.com/edzer/sfr/issues/398 :\n> pt = st_sfc(st_point(c(0,92)), crs = 4267)\n> robin_crs <- \"+proj=robin +lon_0=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs\"\n> # india_crs <- \"EPSG:24383\"  # India-centered Lambert conformal conic projection\n> india_crs <- \"+proj=lcc +lat_1=12 +lat_0=12 +lon_0=80 +k_0=0.99878641 +x_0=2743195.5 +y_0=914398.5 +a=6377299.151 +b=6356098.145120132 +towgs84=295,736,257,0,0,0,0 +units=m +no_defs\"\n> st_transform(st_transform(pt, robin_crs), india_crs)[[1]]\nPOINT EMPTY\n> \n> proc.time()\n   user  system elapsed \n   0.54    0.23    0.71 \n"
  },
  {
    "path": "tests/full.R",
    "content": "suppressPackageStartupMessages(library(sf))\n\n# create full polygon:\n(f = st_as_sfc(\"POLYGON FULL\"))\ng = st_sfc(st_polygon(list(matrix(c(0,-90,0,-90), 2, byrow = TRUE))))\nidentical(f, g)\nold = sf_use_s2(FALSE)\ntry(st_as_sfc(\"POLYGON FULL\")) # errors\nsf_use_s2(old)\n(f = st_as_sfc(c(\"POLYGON FULL\", \"POLYGON((0 0,1 0,1 1,0 1,0 0))\")))\nst_is_full(f)\nst_bbox(f[1])\nst_bbox(f[2])\nst_is_valid(f) # full polygon NA: right, we don't know the CRS\nst_crs(f) = 'OGC:CRS84' # geodetic:\nst_is_valid(f)\ntry(st_set_crs(f, NA)) # errors\nst_crs(f) = 'OGC:CRS84' # geodetic:\nst_make_valid(f)\n# mixed geometries:\n(f = st_as_sfc(c(\"POLYGON FULL\", \"POLYGON((0 0,1 0,1 1,0 1,0 0))\", \"POINT(3 1)\"), crs = 'OGC:CRS84'))\nst_bbox(f[1])\nst_bbox(f[3])\nst_is_valid(f)\nst_make_valid(f)\nst_make_valid(f[2:3])\n\n# roundtrip:\nsf = st_as_sf(data.frame(attr = 1:3, geom = f[1:3]))\nwrite_sf(sf, fn <- tempfile(fileext=\".gpkg\"))\ng = read_sf(fn)\ng\n\nst_is_empty(g)\nst_is_full(g)\nst_is_valid(g)\nst_is_simple(g)\nst_dimension(g)\nst_area(g)\nst_length(g)\nst_distance(g)\n"
  },
  {
    "path": "tests/full.Rout.save",
    "content": "\nR Under development (unstable) (2025-11-05 r88988 ucrt) -- \"Unsuffered Consequences\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-w64-mingw32/x64\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> \n> # create full polygon:\n> (f = st_as_sfc(\"POLYGON FULL\"))\nGeometry set for 1 feature \nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: -180 ymin: -90 xmax: 180 ymax: 90\nCRS:           NA\nPOLYGON FULL\n> g = st_sfc(st_polygon(list(matrix(c(0,-90,0,-90), 2, byrow = TRUE))))\n> identical(f, g)\n[1] TRUE\n> old = sf_use_s2(FALSE)\nSpherical geometry (s2) switched off\n> try(st_as_sfc(\"POLYGON FULL\")) # errors\nOGR: Corrupt data\nError : OGR error\n> sf_use_s2(old)\nSpherical geometry (s2) switched on\n> (f = st_as_sfc(c(\"POLYGON FULL\", \"POLYGON((0 0,1 0,1 1,0 1,0 0))\")))\nGeometry set for 2 features \nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: -180 ymin: -90 xmax: 180 ymax: 90\nCRS:           NA\nPOLYGON FULL\nPOLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))\n> st_is_full(f)\n[1]  TRUE FALSE\n> st_bbox(f[1])\nxmin ymin xmax ymax \n-180  -90  180   90 \n> st_bbox(f[2])\nxmin ymin xmax ymax \n   0    0    1    1 \n> st_is_valid(f) # full polygon NA: right, we don't know the CRS\n[1]   NA TRUE\n> st_crs(f) = 'OGC:CRS84' # geodetic:\n> st_is_valid(f)\n[1] TRUE TRUE\n> try(st_set_crs(f, NA)) # errors\nError in `st_crs<-.sfc`(`*tmp*`, value = value) : \n  To set the crs to NA, first remove the full polygons; see: st_is_full()\n> st_crs(f) = 'OGC:CRS84' # geodetic:\n> st_make_valid(f)\nGeometry set for 2 features \nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: -180 ymin: -90 xmax: 180 ymax: 90\nGeodetic CRS:  WGS 84 (CRS84)\nPOLYGON FULL\nPOLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))\n> # mixed geometries:\n> (f = st_as_sfc(c(\"POLYGON FULL\", \"POLYGON((0 0,1 0,1 1,0 1,0 0))\", \"POINT(3 1)\"), crs = 'OGC:CRS84'))\nGeometry set for 3 features \nGeometry type: GEOMETRY\nDimension:     XY\nBounding box:  xmin: -180 ymin: -90 xmax: 180 ymax: 90\nGeodetic CRS:  WGS 84 (CRS84)\nPOLYGON FULL\nPOLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))\nPOINT (3 1)\n> st_bbox(f[1])\nxmin ymin xmax ymax \n-180  -90  180   90 \n> st_bbox(f[3])\nxmin ymin xmax ymax \n   3    1    3    1 \n> st_is_valid(f)\n[1] TRUE TRUE TRUE\n> st_make_valid(f)\nGeometry set for 3 features \nGeometry type: GEOMETRY\nDimension:     XY\nBounding box:  xmin: -180 ymin: -90 xmax: 180 ymax: 90\nGeodetic CRS:  WGS 84 (CRS84)\nPOLYGON FULL\nPOLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))\nPOINT (3 1)\n> st_make_valid(f[2:3])\nGeometry set for 2 features \nGeometry type: GEOMETRY\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 3 ymax: 1\nGeodetic CRS:  WGS 84 (CRS84)\nPOLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))\nPOINT (3 1)\n> \n> # roundtrip:\n> sf = st_as_sf(data.frame(attr = 1:3, geom = f[1:3]))\n> write_sf(sf, fn <- tempfile(fileext=\".gpkg\"))\n> g = read_sf(fn)\n> g\nSimple feature collection with 3 features and 1 field\nGeometry type: GEOMETRY\nDimension:     XY\nBounding box:  xmin: -180 ymin: -90 xmax: 180 ymax: 90\nGeodetic CRS:  WGS 84 (CRS84)\n# A tibble: 3 × 2\n   attr                                geom\n  <int>                      <GEOMETRY [°]>\n1     1                        POLYGON FULL\n2     2 POLYGON ((0 0, 1 0, 1 1, 0 1, 0 0))\n3     3                         POINT (3 1)\n> \n> st_is_empty(g)\n[1] FALSE FALSE FALSE\n> st_is_full(g)\n[1]  TRUE FALSE FALSE\n> st_is_valid(g)\n[1] TRUE TRUE TRUE\n> st_is_simple(g)\n[1] TRUE TRUE TRUE\n> st_dimension(g)\n[1] 2 2 0\n> st_area(g)\nUnits: [m^2]\n[1] 5.100661e+14 1.236404e+10 0.000000e+00\n> st_length(g)\nUnits: [m]\n[1] 0 0 0\n> st_distance(g)\nUnits: [m]\n     [,1]     [,2]     [,3]\n[1,]    0      0.0      0.0\n[2,]    0      0.0 222356.3\n[3,]    0 222356.3      0.0\n> \n> proc.time()\n   user  system elapsed \n   0.90    0.18    1.00 \n"
  },
  {
    "path": "tests/gdal_geom.R",
    "content": "suppressPackageStartupMessages(library(sf))\n\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), \"nc\", crs = 4267,\n\tagr = c(AREA = \"aggregate\", PERIMETER = \"aggregate\", CNTY_ = \"identity\",\n\t\tCNTY_ID = \"identity\", NAME = \"identity\", FIPS = \"identity\", FIPSNO = \"identity\",\n\t\tCRESS_ID = \"identity\", BIR74 = \"aggregate\", SID74 = \"aggregate\", NWBIR74 = \"aggregate\",\n\t\tBIR79 = \"aggregate\", SID79 = \"aggregate\", NWBIR79  = \"aggregate\"), quiet = TRUE)\n\nst_is_valid(nc)\n\nst_is_simple(nc)\n\nnc_tr = st_transform(nc, 3857)\n\nx = st_buffer(nc_tr, 1000)\n\nx = st_boundary(nc)\n\nx = st_convex_hull(nc)\n\nx = st_simplify(nc_tr, dTolerance = 1e4)\n\nx = st_simplify(nc_tr, dTolerance = rep(1e4, nrow(nc_tr)))\n\nx = st_simplify(nc_tr, preserveTopology = TRUE)\n\nif (sf:::CPL_geos_version() >= \"3.4.0\")\n\tx = st_triangulate(nc_tr)\n\nmls = st_multilinestring(list(matrix(c(0,0,0,1,1,1,0,0),,2,byrow=TRUE)))\nx = st_polygonize(mls)\n\nx = st_segmentize(nc_tr, 5e4)\n\ntry(x <- st_segmentize(nc_tr, -0.1))\n\nx = st_centroid(nc_tr)\nx = st_point_on_surface(nc_tr)\n\na = nc[1:5,]\nb = nc[4:10,]\n\nx <- st_intersection(a[1,] ,b)\n\nu = st_union(b) \n\nx <- st_intersection(st_geometry(a), st_geometry(u))\n\nx = st_union(a[1,], b)\n\nx = st_union(a, st_union(b))\n\nx = st_difference(a[1,], b)\n\nx = st_difference(a, st_union(b))\n\nx = st_sym_difference(a[1,], b)\n\nx = st_sym_difference(a, st_union(b))\n\nx = st_drivers()\n#cat(paste(\"GDAL has\", nrow(x), \"drivers\\n\"))\n\n# GEOS ops:\n\nst_relate(a, b)\n\nst_disjoint(a, b)\n\nst_touches(a, b)\n\nst_crosses(a, b)\n\nst_within(a, b)\n\nst_contains(a, b)\n\nst_overlaps(a, b)\n\nst_equals(a, b)\n\nst_covers(a, b)\n\nst_covered_by(a, b)\n\nst_equals_exact(a, b, 0.01)\n\n# st_is_within_distance(a, b, 2)\n\nst_geometry_type(st_sfc(st_point(1:2), st_linestring(matrix(1:4,2,2))))\n\nst_geometry_type(st_sfc(st_point(1:2), st_linestring(matrix(1:4,2,2))), by_geometry = FALSE)\n\nst_zm(list(st_point(1:3), st_linestring(matrix(1:6,2,3))))\n\nst_zm(list(st_point(1:2), st_linestring(matrix(1:6,3,2))), add = TRUE, \"Z\")\n\nst_transform(st_sfc(st_point(c(0,0)), crs=4326), st_crs(\"+proj=geocent\"))[[1]]\n\ncbind(st_area(nc_tr[1:5,]), a$AREA)\n\nst_area(st_polygon(list(rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0)))))\n\nst_length(st_linestring(rbind(c(0,0),c(0,1))))\n\nst_length(st_multilinestring(list(rbind(c(0,0),c(0,1)))))\n\ntry(st_length(st_polygon(list(rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0))))))\n\nst_area(st_multilinestring(list(rbind(c(0,0),c(0,1)))))\n\n# adds the (0.5 0.5) node:\nst_union(st_multilinestring(list(rbind(c(0,0),c(1,1)), rbind(c(0,1), c(1,0)))))\n\np1 = st_point(c(7,52))\np2 = st_point(c(-30,20))\nsfc = st_sfc(p1, p2)\ntry(st_buffer(sfc, units::set_units(1000, km))) # error: no crs\nsfc = st_sfc(p1, p2, crs = 4326)\ntry(zzz <- st_buffer(sfc, units::set_units(1000, km))) # error: wrong units\nif (version$os == \"linux-gnu\") { # FIXME: why does this break on windows - degree symbol?\n  x = st_buffer(sfc, units::set_units(0.1, rad))      # OK: will convert to arc_degrees\n}\nx = st_transform(sfc, 3857)\nx = st_buffer(x, units::set_units(1000, km)) # success\n\ncr = st_as_sfc(\"CIRCULARSTRING(0 0,1 0,1 1)\")\ncr1 = st_sf(a = 1, geometry = cr)\nplot(cr)\nst_as_grob(cr[[1]])\n\nx = st_as_sfc(\"MULTISURFACE(CURVEPOLYGON(COMPOUNDCURVE(LINESTRING(-159.399779123 22.226016471, -159.399699153 22.226276431, -159.398736217 22.226118372, -159.398260872 22.226095318, -159.398140792 22.2260564590001, -159.398163058 22.2257268010001, -159.397882642 22.225394244, -159.397397157 22.225057335, -159.397318825 22.2251780230001, -159.396993115 22.225177984, -159.396748242 22.2248808800001, -159.396901679 22.224770398, -159.396876329 22.224673093, -159.399167008 22.224731392, -159.399502204 22.225551382), CIRCULARSTRING(-159.399502204 22.225551382, -159.399622762077 22.2257930044972, -159.399779123 22.226016471))))\")\nmp <- x[[1]] |> st_cast(\"MULTIPOLYGON\")\n\nx = st_as_sfc(\"COMPOUNDCURVE(CIRCULARSTRING(0 0, 1 1, 1 0),(1 0, 0 1))\")\nls <- x[[1]] |> st_cast()\nclass(ls)\n\nis.na(st_bbox(ls))\n\nmp = st_combine(st_buffer(st_sfc(lapply(1:3, function(x) st_point(c(x,x)))), 0.2 * 1:3))\nplot(st_centroid(mp), add = TRUE, col = 'red') # centroid of combined geometry\nplot(st_centroid(mp, of_largest_polygon = TRUE), add = TRUE, col = 'blue', pch = 3) # center of largest sub-polygon\n\nx = st_sfc(st_polygon(list(rbind(c(0,0),c(0.5,0),c(0.5,0.5),c(0.5,0),c(1,0),c(1,1),c(0,1),c(0,0)))))\nsuppressWarnings(st_is_valid(x))\ny = st_make_valid(x)\ny = st_make_valid(x[[1]])\ny = st_make_valid(st_sf(a = 1, geom = x))\nst_is_valid(y)\n"
  },
  {
    "path": "tests/gdal_geom.Rout.save",
    "content": "\nR version 4.5.2 (2025-10-31) -- \"[Not] Part in a Rumble\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-pc-linux-gnu\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> \n> nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), \"nc\", crs = 4267,\n+ \tagr = c(AREA = \"aggregate\", PERIMETER = \"aggregate\", CNTY_ = \"identity\",\n+ \t\tCNTY_ID = \"identity\", NAME = \"identity\", FIPS = \"identity\", FIPSNO = \"identity\",\n+ \t\tCRESS_ID = \"identity\", BIR74 = \"aggregate\", SID74 = \"aggregate\", NWBIR74 = \"aggregate\",\n+ \t\tBIR79 = \"aggregate\", SID79 = \"aggregate\", NWBIR79  = \"aggregate\"), quiet = TRUE)\n> \n> st_is_valid(nc)\n  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [16] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [31] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [46] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [61] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [76] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [91] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n> \n> st_is_simple(nc)\n  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [16] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [31] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [46] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [61] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [76] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [91] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n> \n> nc_tr = st_transform(nc, 3857)\n> \n> x = st_buffer(nc_tr, 1000)\n> \n> x = st_boundary(nc)\n> \n> x = st_convex_hull(nc)\n> \n> x = st_simplify(nc_tr, dTolerance = 1e4)\n> \n> x = st_simplify(nc_tr, dTolerance = rep(1e4, nrow(nc_tr)))\n> \n> x = st_simplify(nc_tr, preserveTopology = TRUE)\n> \n> if (sf:::CPL_geos_version() >= \"3.4.0\")\n+ \tx = st_triangulate(nc_tr)\n> \n> mls = st_multilinestring(list(matrix(c(0,0,0,1,1,1,0,0),,2,byrow=TRUE)))\n> x = st_polygonize(mls)\n> \n> x = st_segmentize(nc_tr, 5e4)\n> \n> try(x <- st_segmentize(nc_tr, -0.1))\nError : argument dfMaxLength should be positive\n\n> \n> x = st_centroid(nc_tr)\nWarning message:\nst_centroid assumes attributes are constant over geometries \n> x = st_point_on_surface(nc_tr)\nWarning message:\nst_point_on_surface assumes attributes are constant over geometries \n> \n> a = nc[1:5,]\n> b = nc[4:10,]\n> \n> x <- st_intersection(a[1,] ,b)\nWarning message:\nattribute variables are assumed to be spatially constant throughout all geometries \n> \n> u = st_union(b) \n> \n> x <- st_intersection(st_geometry(a), st_geometry(u))\n> \n> x = st_union(a[1,], b)\nWarning message:\nattribute variables are assumed to be spatially constant throughout all geometries \n> \n> x = st_union(a, st_union(b))\nWarning message:\nattribute variables are assumed to be spatially constant throughout all geometries \n> \n> x = st_difference(a[1,], b)\nWarning message:\nattribute variables are assumed to be spatially constant throughout all geometries \n> \n> x = st_difference(a, st_union(b))\nWarning message:\nattribute variables are assumed to be spatially constant throughout all geometries \n> \n> x = st_sym_difference(a[1,], b)\nWarning message:\nattribute variables are assumed to be spatially constant throughout all geometries \n> \n> x = st_sym_difference(a, st_union(b))\nWarning message:\nattribute variables are assumed to be spatially constant throughout all geometries \n> \n> x = st_drivers()\n> #cat(paste(\"GDAL has\", nrow(x), \"drivers\\n\"))\n> \n> # GEOS ops:\n> \n> st_relate(a, b)\nalthough coordinates are longitude/latitude, st_relate assumes that they are\nplanar\n     [,1]        [,2]        [,3]        [,4]        [,5]        [,6]       \n[1,] \"FF2FF1212\" \"FF2FF1212\" \"FF2FF1212\" \"FF2FF1212\" \"FF2FF1212\" \"FF2FF1212\"\n[2,] \"FF2FF1212\" \"FF2FF1212\" \"FF2FF1212\" \"FF2FF1212\" \"FF2FF1212\" \"FF2FF1212\"\n[3,] \"FF2FF1212\" \"FF2FF1212\" \"FF2FF1212\" \"FF2FF1212\" \"FF2FF1212\" \"FF2FF1212\"\n[4,] \"2FFF1FFF2\" \"FF2FF1212\" \"FF2FF1212\" \"FF2F11212\" \"FF2FF1212\" \"FF2FF1212\"\n[5,] \"FF2FF1212\" \"2FFF1FFF2\" \"FF2F11212\" \"FF2FF1212\" \"FF2FF1212\" \"FF2F11212\"\n     [,7]       \n[1,] \"FF2FF1212\"\n[2,] \"FF2FF1212\"\n[3,] \"FF2F11212\"\n[4,] \"FF2FF1212\"\n[5,] \"FF2FF1212\"\n> \n> st_disjoint(a, b)\nSparse geometry binary predicate list of length 5, where the predicate\nwas `disjoint'\n 1: 1, 2, 3, 4, 5, 6, 7\n 2: 1, 2, 3, 4, 5, 6, 7\n 3: 1, 2, 3, 4, 5, 6\n 4: 2, 3, 5, 6, 7\n 5: 1, 4, 5, 7\n> \n> st_touches(a, b)\nSparse geometry binary predicate list of length 5, where the predicate\nwas `touches'\n 1: (empty)\n 2: (empty)\n 3: 7\n 4: 4\n 5: 3, 6\n> \n> st_crosses(a, b)\nalthough coordinates are longitude/latitude, st_crosses assumes that they are\nplanar\nSparse geometry binary predicate list of length 5, where the predicate\nwas `crosses'\n 1: (empty)\n 2: (empty)\n 3: (empty)\n 4: (empty)\n 5: (empty)\n> \n> st_within(a, b)\nSparse geometry binary predicate list of length 5, where the predicate\nwas `within'\n 1: (empty)\n 2: (empty)\n 3: (empty)\n 4: 1\n 5: 2\n> \n> st_contains(a, b)\nSparse geometry binary predicate list of length 5, where the predicate\nwas `contains'\n 1: (empty)\n 2: (empty)\n 3: (empty)\n 4: 1\n 5: 2\n> \n> st_overlaps(a, b)\nalthough coordinates are longitude/latitude, st_overlaps assumes that they are\nplanar\nSparse geometry binary predicate list of length 5, where the predicate\nwas `overlaps'\n 1: (empty)\n 2: (empty)\n 3: (empty)\n 4: (empty)\n 5: (empty)\n> \n> st_equals(a, b)\nSparse geometry binary predicate list of length 5, where the predicate\nwas `equals'\n 1: (empty)\n 2: (empty)\n 3: (empty)\n 4: 1\n 5: 2\n> \n> st_covers(a, b)\nSparse geometry binary predicate list of length 5, where the predicate\nwas `covers'\n 1: (empty)\n 2: (empty)\n 3: (empty)\n 4: 1\n 5: 2\n> \n> st_covered_by(a, b)\nSparse geometry binary predicate list of length 5, where the predicate\nwas `covered_by'\n 1: (empty)\n 2: (empty)\n 3: (empty)\n 4: 1\n 5: 2\n> \n> st_equals_exact(a, b, 0.01)\nSparse geometry binary predicate list of length 5, where the predicate\nwas `equals_exact'\n 1: (empty)\n 2: (empty)\n 3: (empty)\n 4: 1\n 5: 2\n> \n> # st_is_within_distance(a, b, 2)\n> \n> st_geometry_type(st_sfc(st_point(1:2), st_linestring(matrix(1:4,2,2))))\n[1] POINT      LINESTRING\n18 Levels: GEOMETRY POINT LINESTRING POLYGON MULTIPOINT ... TRIANGLE\n> \n> st_geometry_type(st_sfc(st_point(1:2), st_linestring(matrix(1:4,2,2))), by_geometry = FALSE)\n[1] GEOMETRY\n18 Levels: GEOMETRY POINT LINESTRING POLYGON MULTIPOINT ... TRIANGLE\n> \n> st_zm(list(st_point(1:3), st_linestring(matrix(1:6,2,3))))\n[[1]]\nPOINT (1 2)\n\n[[2]]\nLINESTRING (1 3, 2 4)\n\n> \n> st_zm(list(st_point(1:2), st_linestring(matrix(1:6,3,2))), add = TRUE, \"Z\")\n[[1]]\nPOINT (1 2)\n\n[[2]]\nLINESTRING (1 4, 2 5, 3 6)\n\n> \n> st_transform(st_sfc(st_point(c(0,0)), crs=4326), st_crs(\"+proj=geocent\"))[[1]]\nPOINT Z (6378137 0 0)\n> \n> cbind(st_area(nc_tr[1:5,]), a$AREA)\nUnits: [m^2]\n           [,1]  [,2]\n[1,] 1760230516 0.114\n[2,]  946417787 0.061\n[3,] 2202223078 0.143\n[4,] 1074332698 0.070\n[5,] 2352528086 0.153\n> \n> st_area(st_polygon(list(rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0)))))\n[1] 1\n> \n> st_length(st_linestring(rbind(c(0,0),c(0,1))))\n[1] 1\n> \n> st_length(st_multilinestring(list(rbind(c(0,0),c(0,1)))))\n[1] 1\n> \n> try(st_length(st_polygon(list(rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0))))))\n[1] 0\n> \n> st_area(st_multilinestring(list(rbind(c(0,0),c(0,1)))))\n[1] 0\n> \n> # adds the (0.5 0.5) node:\n> st_union(st_multilinestring(list(rbind(c(0,0),c(1,1)), rbind(c(0,1), c(1,0)))))\nMULTILINESTRING ((0 0, 1 1), (0 1, 1 0))\n> \n> p1 = st_point(c(7,52))\n> p2 = st_point(c(-30,20))\n> sfc = st_sfc(p1, p2)\n> try(st_buffer(sfc, units::set_units(1000, km))) # error: no crs\nError in st_buffer.sfc(sfc, units::set_units(1000, km)) : \n  x does not have a crs set: can't convert units\n> sfc = st_sfc(p1, p2, crs = 4326)\n> try(zzz <- st_buffer(sfc, units::set_units(1000, km))) # error: wrong units\n> if (version$os == \"linux-gnu\") { # FIXME: why does this break on windows - degree symbol?\n+   x = st_buffer(sfc, units::set_units(0.1, rad))      # OK: will convert to arc_degrees\n+ }\n> x = st_transform(sfc, 3857)\n> x = st_buffer(x, units::set_units(1000, km)) # success\n> \n> cr = st_as_sfc(\"CIRCULARSTRING(0 0,1 0,1 1)\")\n> cr1 = st_sf(a = 1, geometry = cr)\n> plot(cr)\n> st_as_grob(cr[[1]])\nlines[GRID.lines.1] \n> \n> x = st_as_sfc(\"MULTISURFACE(CURVEPOLYGON(COMPOUNDCURVE(LINESTRING(-159.399779123 22.226016471, -159.399699153 22.226276431, -159.398736217 22.226118372, -159.398260872 22.226095318, -159.398140792 22.2260564590001, -159.398163058 22.2257268010001, -159.397882642 22.225394244, -159.397397157 22.225057335, -159.397318825 22.2251780230001, -159.396993115 22.225177984, -159.396748242 22.2248808800001, -159.396901679 22.224770398, -159.396876329 22.224673093, -159.399167008 22.224731392, -159.399502204 22.225551382), CIRCULARSTRING(-159.399502204 22.225551382, -159.399622762077 22.2257930044972, -159.399779123 22.226016471))))\")\n> mp <- x[[1]] |> st_cast(\"MULTIPOLYGON\")\n> \n> x = st_as_sfc(\"COMPOUNDCURVE(CIRCULARSTRING(0 0, 1 1, 1 0),(1 0, 0 1))\")\n> ls <- x[[1]] |> st_cast()\n> class(ls)\n[1] \"XY\"         \"LINESTRING\" \"sfg\"       \n> \n> is.na(st_bbox(ls))\n[1] FALSE\n> \n> mp = st_combine(st_buffer(st_sfc(lapply(1:3, function(x) st_point(c(x,x)))), 0.2 * 1:3))\n> plot(st_centroid(mp), add = TRUE, col = 'red') # centroid of combined geometry\n> plot(st_centroid(mp, of_largest_polygon = TRUE), add = TRUE, col = 'blue', pch = 3) # center of largest sub-polygon\n> \n> x = st_sfc(st_polygon(list(rbind(c(0,0),c(0.5,0),c(0.5,0.5),c(0.5,0),c(1,0),c(1,1),c(0,1),c(0,0)))))\n> suppressWarnings(st_is_valid(x))\n[1] FALSE\n> y = st_make_valid(x)\n> y = st_make_valid(x[[1]])\n> y = st_make_valid(st_sf(a = 1, geom = x))\n> st_is_valid(y)\n[1] TRUE\n> \n> proc.time()\n   user  system elapsed \n  0.844   1.405   0.746 \n"
  },
  {
    "path": "tests/geos.R",
    "content": "suppressPackageStartupMessages(library(sf))\n# nc = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"))\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\nnc_checked = st_transform(nc, 32119, check = TRUE)\nncm = st_transform(nc, 32119)\n\nx = st_transform(nc[1:10,], 32119)\nst_distance(x)\n\nst_is_valid(nc)\n\nst_is_empty(st_sfc(st_point(), st_linestring()))\n\nops = c(\"intersects\", #\"disjoint\", \n\"touches\", \"crosses\", \"within\", \"contains\", \"overlaps\", \"equals\", \"covers\", \"covered_by\", \"equals_exact\")\nfor (op in ops) {\n\tx = sf:::st_geos_binop(op, ncm[1:50,], ncm[51:100,], 0, NA_character_, FALSE)\n\tx = sf:::st_geos_binop(op, ncm[1:50,], ncm[51:100,], 0, NA_character_, TRUE)\n}\n\nops = c(\"intersects\", #\"disjoint\", \n\"touches\", \"crosses\", \"within\", \"contains\", \"overlaps\", \"covers\", \"covered_by\")\ndf = data.frame(ops = ops)\ndf$equal = NA\nfor (op in ops)\n\tdf[df$ops == op, \"equal\"] = identical(\n\t\tsf:::st_geos_binop(op, ncm[1:50,], ncm[51:100,], 0, NA_character_, TRUE, FALSE),\n\t\tsf:::st_geos_binop(op, ncm[1:50,], ncm[51:100,], 0, NA_character_, TRUE,  TRUE)\n\t)\ndf\n\nst_contains_properly(ncm[1:3,], ncm[1:3])\n\nst_combine(nc)\n\nst_dimension(st_sfc(st_point(0:1), st_linestring(rbind(c(0,0),c(1,1))), \n\tst_polygon(list(rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0))))))\n\nncbb = st_as_sfc(st_bbox(nc))\ng = st_make_grid(ncbb)\nx = st_intersection(nc, g)\nx = st_intersection(g, nc)\n\nls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))),\nst_linestring(rbind(c(0,0),c(10,0))))\n\nsuppressWarnings(RNGversion(\"3.5.3\"))\nset.seed(13531)\n\nst_line_sample(ls, density = 1, type = \"random\")\n\ng = st_make_grid(ncbb, n = c(20,10))\n\na1 = st_interpolate_aw(nc[\"BIR74\"], g, FALSE)\nsum(a1$BIR74) / sum(nc$BIR74) # not close to one: property is assumed spatially intensive\na2 = st_interpolate_aw(nc[\"BIR74\"], g, extensive = TRUE)\nsum(a2$BIR74) / sum(nc$BIR74)\n\n# missing x:\ng = st_make_grid(offset = c(0,0), cellsize = c(1,1), n = c(10,10))\ng = st_make_grid(what = \"centers\")\nlength(g)\ng = st_make_grid(what = \"corners\")\nlength(g)\n\ng1 = st_make_grid(ncbb, 0.1, what = \"polygons\", square = FALSE)\ng2 = st_make_grid(ncbb, 0.1, what = \"points\", square = FALSE)\n\n# st_line_merge:\nmls = st_multilinestring(list(rbind(c(0,0), c(1,1)), rbind(c(2,0), c(1,1))))\nst_line_merge(mls)\n\nif (isTRUE(try(compareVersion(sf_extSoftVersion()[\"GEOS\"], \"3.5.0\") > -1, silent = TRUE))) {\n # voronoi:\n set.seed(1)\n m = matrix(runif(10),,2)\n x = st_multipoint(m)\n box = st_polygon(list(rbind(c(0,0),c(1,0),c(1,1),c(0,1),c(0,0))))\n v = st_sfc(st_voronoi(x, st_sfc(box)))\n plot(v, col = 0, border = 1, axes = TRUE)\n plot(box, add = TRUE, col = 0, border = 1) # a larger box is returned, as documented\n plot(x, add = TRUE, col = 'red', cex=2, pch=16)\n plot(st_intersection(st_cast(v), box)) # clip to smaller box\n plot(x, add = TRUE, col = 'red', cex=2, pch=16)\n v0 = st_sfc(st_voronoi(st_sfc(x), st_sfc(box)))\n pal <- c(\"black\", \"red\", \"green\", \"blue\", \"orange\")\n opar = par(mfrow=c(1,2))\n plot(st_collection_extract(v0, \"POLYGON\"), col=pal)\n text(m[,1], m[,2], label=1:5, col=\"white\")\n if (isTRUE(try(compareVersion(sf_extSoftVersion()[\"GEOS\"], \"3.12.0\") > -1, silent = TRUE))) {\n  v2 = st_sfc(st_voronoi(st_sfc(x), st_sfc(box), point_order=TRUE))\n  plot(st_collection_extract(v2, \"POLYGON\"), col=pal)\n  text(m[,1], m[,2], label=1:5, col=\"white\")\n }\n par(opar)\n\n v = st_voronoi(x)\n print(class(v))\n v = st_sfc(st_voronoi(st_sfc(x)))\n print(class(v))\n v = st_voronoi(st_sf(a = 1, geom = st_sfc(x)))\n print(class(v))\n}\n\ni = st_intersects(ncm, ncm[1:88,])\nall.equal(i, t(t(i)))\n\n# check use of pattern in st_relate:\nsfc = st_as_sfc(st_bbox(st_sfc(st_point(c(0,0)), st_point(c(3,3)))))\ngrd = st_make_grid(sfc, n = c(3,3))\nst_intersects(grd)\nst_relate(grd, pattern = \"****1****\")\nst_relate(grd, pattern = \"****0****\")\nst_rook = function(a, b = a, ...) st_relate(a, b, pattern = \"F***1****\", ...)\nst_rook(grd, sparse = FALSE)\n\n#if (Sys.getenv(\"USER\") %in% c(\"edzer\", \"travis\")) { # memory leaks:\n  try(st_relate(st_point(), st_point(), pattern = \"FF*FF****\")) # error: use st_disjoint\n#}\n\na = st_is_within_distance(nc[c(1:3,20),], nc[1:3,], 100000, sparse = FALSE)\nb = st_is_within_distance(nc[c(1:3,20),], nc[1:3,], units::set_units(100000, m), sparse = FALSE)\nall.equal(a, b)\nx = st_is_within_distance(nc[1:3,], nc[1:5,], 100000)\ny = st_is_within_distance(nc[1:3,], nc[1:5,], units::set_units(100, km))\nall.equal(x, y)\n\nnc_3857 = st_transform(nc, 3857)\na = st_is_within_distance(nc_3857[c(1:3,20),], nc_3857[1:3,], 100000, sparse = FALSE)\nb = st_is_within_distance(nc_3857[c(1:3,20),], nc_3857[1:3,], units::set_units(100000, m), sparse = FALSE)\nall.equal(a, b)\nx = st_is_within_distance(nc_3857, nc_3857, 100000)\ny = st_is_within_distance(nc_3857, nc_3857, units::set_units(100, km))\nall.equal(x, y)\n\npe = st_sfc(st_point())\np = st_sfc(st_point(c(0,0)), st_point(c(0,1)), st_point(c(0,2)))\nst_distance(p, p)\nst_distance(p, pe)\nst_distance(p, p, by_element = TRUE)\nst_crs(p) = 4326\nst_distance(p, p[c(2,3,1)], by_element = TRUE)\np = st_transform(p, 3587)\nst_distance(p, p[c(2,3,1)], by_element = TRUE)\n\n# from https://github.com/r-spatial/sf/issues/458 :\npts <- st_sfc(st_point(c(.5,.5)), st_point(c(1.5, 1.5)), st_point(c(2.5, 2.5)))\npol <- st_polygon(list(rbind(c(0,0), c(2,0), c(2,2), c(0,2), c(0,0))))\npol_df <- data.frame(id = 1) \nst_geometry(pol_df) <- st_sfc(pol)\nst_intersects(pts, pol_df[pol_df$id == 2,]) # with empty sf/sfc\nst_intersects(pts, pol_df[pol_df$id == 2,], sparse = FALSE) # with empty sf/sfc\n\n# st_node\nl = st_linestring(rbind(c(0,0), c(1,1), c(0,1), c(1,0), c(0,0)))\nst_node(l)\nst_node(st_sfc(l))\nst_node(st_sf(a = 1, st_sfc(l)))\n\n# print.sgbp:\n(lst = st_disjoint(nc, nc))\n# dim.sgbp:\ndim(lst)\n# as.matrix.sgbp:\nas.matrix(lst)[1:5, 1:5]\n# negate:\n!lst\n# as.data.frame:\nhead(as.data.frame(lst), 10)\n\n# snap:\nnc1 = st_transform(nc, 32119)\ng = st_make_grid(nc1, c(5000,5000), what = \"centers\")\ns = st_snap(nc1[1:3,], g, 2501*sqrt(2))\nsfg = st_snap(st_geometry(nc1)[[1]], g, 2501*sqrt(2))\nsfg = st_snap(st_geometry(nc1)[[1]], st_combine(g), 2501*sqrt(2))\n\n# Hausdorff distance: http://geos.refractions.net/ro/doxygen_docs/html/classgeos_1_1algorithm_1_1distance_1_1DiscreteHausdorffDistance.html\nA = st_as_sfc(\"LINESTRING (0 0, 100 0, 10 100, 10 100)\")\nB = st_as_sfc(\"LINESTRING (0 100, 0 10, 80 10)\")\nst_distance(c(A,B))\nst_distance(c(A,B), which = \"Hausdorff\")\nst_distance(c(A,B), which = \"Hausdorff\", par = 0.001)\nLE = st_as_sfc(\"LINESTRING EMPTY\")\nst_distance(c(A, LE), which = \"Hausdorff\", par = 0.001)\n\n# one-argument st_intersection and st_difference:\nset.seed(131)\nm = rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0))\np = st_polygon(list(m))\nn = 100\nl = vector(\"list\", n)\nfor (i in 1:n)\n   l[[i]] = p + 10 * runif(2)\ns = st_sfc(l)\nplot(s, col = sf.colors(categorical = TRUE, alpha = .5))\nd = st_difference(s) # sequential differences: s1, s2-s1, s3-s2-s1, ...\nplot(d, col = sf.colors(categorical = TRUE, alpha = .5))\ni = st_intersection(s) # all intersections\nplot(i, col = sf.colors(categorical = TRUE, alpha = .5))\nsummary(lengths(st_overlaps(s, s)))\nsummary(lengths(st_overlaps(d, d)))\nsummary(lengths(st_overlaps(i, i)))\n\nsf = st_sf(s)\ni = st_intersection(sf) # all intersections\nplot(i[\"n.overlaps\"])\nsummary(i$n.overlaps - lengths(i$origins))\n\n# st_nearest_points:\npt1 = st_point(c(.1,.1))\npt2 = st_point(c(.9,.9))\nb1 = st_buffer(pt1, 0.1)\nb2 = st_buffer(pt2, 0.1)\nplot(b1, xlim = c(0,1), ylim = c(0,1))\nplot(b2, add = TRUE)\n(ls0 = try(st_nearest_points(b1, b2))) # sfg\n(ls = try(st_nearest_points(st_sfc(b1), st_sfc(b2)))) # sfc\n(ls = try(st_nearest_points(st_sfc(b1), st_sfc(b2), pairwise = TRUE))) # sfc\nidentical(ls0, ls)\n# plot(ls, add = TRUE, col = 'red')\n\nnc = read_sf(system.file(\"gpkg/nc.gpkg\", package=\"sf\"))\nplot(st_geometry(nc))\nls = try(st_nearest_points(nc[1,], nc))\n# plot(ls, col = 'red', add = TRUE)\npts = st_cast(ls, \"POINT\") # gives all start & end points\n# starting, \"from\" points, corresponding to x:\nplot(pts[seq(1, 200, 2)], add = TRUE, col = 'blue')\n# ending, \"to\" points, corresponding to y:\nplot(pts[seq(2, 200, 2)], add = TRUE, col = 'red')\n\n# points to nearest features\nls1 = st_linestring(rbind(c(0,0), c(1,0)))\nls2 = st_linestring(rbind(c(0,0.1), c(1,0.1)))\nls3 = st_linestring(rbind(c(0,1), c(1,1)))\n(l = st_sfc(ls1, ls2, ls3))\n\np1 = st_point(c(0.1, -0.1))\np2 = st_point(c(0.1, 0.11))\np3 = st_point(c(0.1, 0.09))\np4 = st_point(c(0.1, 0.9))\np5 = st_point()\n\n(p = st_sfc(p1, p2, p3, p4, p5))\n#st_nearest_points(p, l)\nn = try(st_nearest_feature(p,l))\nif (!inherits(n, \"try-error\")) {\n  print(st_nearest_points(p, l[n], pairwise = TRUE))\n  print(st_nearest_feature(p, l))\n  print(st_nearest_feature(p, st_sfc()))\n  print(st_nearest_feature(st_sfc(), l))\n}\n\n# can do centroid of empty geom:\nst_centroid(st_polygon())\n\n#999:\npt = data.frame(x=1:2, y=1:2,a=letters[1:2])\npt = st_as_sf(pt, coords=c(\"x\",\"y\"))\n\nbf =st_buffer(pt, dist=0.3)\n\nst_within(pt,bf, sparse=FALSE)\nst_within(pt[1,], bf[1,], sparse = FALSE)\nst_relate(pt[1,], bf[1,], pattern = \"T*F**F***\", sparse = FALSE)\n\nsf:::is_symmetric(pattern = \"010121010\")\nsf:::is_symmetric(pattern = \"010121021\")\n\nst_intersects(st_point(0:1), st_point(2:3)) # sfg method\n\nif (isTRUE(try(compareVersion(sf_extSoftVersion()[\"GEOS\"], \"3.7.0\") > -1, silent = TRUE))) {\n\tls = st_linestring(rbind(c(1,1), c(2,2), c(3,3)))\n\tprint(st_reverse(ls))\n\tprint(st_reverse(st_sfc(ls)))\n\tprint(st_reverse(st_sf(a = 2, geom = st_sfc(ls))))\n}\n\np = st_polygon(list(rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0))))\ny = st_sfc(p)\nx = st_sfc(p + 1.001)\n\nx |> st_set_precision(0) |> st_intersects(y)\nx |> st_set_precision(10000) |> st_intersects(y)\nx |> st_set_precision(1000) |> st_intersects(y)\nx |> st_set_precision(501) |> st_intersects(y) # no\nx |> st_set_precision(500) |> st_intersects(y) # yes\nx |> st_set_precision(100) |> st_intersects(y)\nx |> st_set_precision(10) |> st_intersects(y)\n\np1 = st_point(0:1)\np2 = st_point(2:1)\np = st_sf(a = letters[1:8], geom = st_sfc(p1, p1, p2, p1, p1, p2, p2, p1))\nst_equals(p)\nst_equals(p, remove_self = TRUE)\n(u = st_equals(p, retain_unique = TRUE))\n# retain the records with unique geometries:\np[-unlist(u),]\n"
  },
  {
    "path": "tests/geos.Rout.save",
    "content": "\nR version 4.5.2 (2025-10-31) -- \"[Not] Part in a Rumble\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-pc-linux-gnu\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> # nc = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"))\n> nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\n> nc_checked = st_transform(nc, 32119, check = TRUE)\n> ncm = st_transform(nc, 32119)\n> \n> x = st_transform(nc[1:10,], 32119)\n> st_distance(x)\nUnits: [m]\n           [,1]      [,2]      [,3]      [,4]      [,5]      [,6]      [,7]\n [1,]      0.00      0.00  25651.99 440561.48 299772.34 361529.73 419671.66\n [2,]      0.00      0.00      0.00 409429.44 268945.05 332590.52 388545.58\n [3,]  25651.99      0.00      0.00 367556.52 227018.38 290298.04 346669.14\n [4,] 440561.48 409429.44 367556.52      0.00  67226.86  45537.62      0.00\n [5,] 299772.34 268945.05 227018.38  67226.86      0.00      0.00  46527.56\n [6,] 361529.73 332590.52 290298.04  45537.62      0.00      0.00  30213.17\n [7,] 419671.66 388545.58 346669.14      0.00  46527.56  30213.17      0.00\n [8,] 384593.29 354295.06 312351.76  16130.19  11926.86      0.00      0.00\n [9,] 262353.97 231217.73 189310.73 140455.97      0.00  64606.27 119564.00\n[10,]  71138.53  41943.71      0.00 330752.58 190183.42 252373.26 309863.33\n           [,8]      [,9]     [,10]\n [1,] 384593.29 262353.97  71138.53\n [2,] 354295.06 231217.73  41943.71\n [3,] 312351.76 189310.73      0.00\n [4,]  16130.19 140455.97 330752.58\n [5,]  11926.86      0.00 190183.42\n [6,]      0.00  64606.27 252373.26\n [7,]      0.00 119564.00 309863.33\n [8,]      0.00  85533.33 275391.07\n [9,]  85533.33      0.00 152489.45\n[10,] 275391.07 152489.45      0.00\n> \n> st_is_valid(nc)\n  [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [16] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [31] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [46] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [61] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [76] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n [91] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n> \n> st_is_empty(st_sfc(st_point(), st_linestring()))\n[1] TRUE TRUE\n> \n> ops = c(\"intersects\", #\"disjoint\", \n+ \"touches\", \"crosses\", \"within\", \"contains\", \"overlaps\", \"equals\", \"covers\", \"covered_by\", \"equals_exact\")\n> for (op in ops) {\n+ \tx = sf:::st_geos_binop(op, ncm[1:50,], ncm[51:100,], 0, NA_character_, FALSE)\n+ \tx = sf:::st_geos_binop(op, ncm[1:50,], ncm[51:100,], 0, NA_character_, TRUE)\n+ }\n> \n> ops = c(\"intersects\", #\"disjoint\", \n+ \"touches\", \"crosses\", \"within\", \"contains\", \"overlaps\", \"covers\", \"covered_by\")\n> df = data.frame(ops = ops)\n> df$equal = NA\n> for (op in ops)\n+ \tdf[df$ops == op, \"equal\"] = identical(\n+ \t\tsf:::st_geos_binop(op, ncm[1:50,], ncm[51:100,], 0, NA_character_, TRUE, FALSE),\n+ \t\tsf:::st_geos_binop(op, ncm[1:50,], ncm[51:100,], 0, NA_character_, TRUE,  TRUE)\n+ \t)\n> df\n         ops equal\n1 intersects  TRUE\n2    touches  TRUE\n3    crosses  TRUE\n4     within  TRUE\n5   contains  TRUE\n6   overlaps  TRUE\n7     covers  TRUE\n8 covered_by  TRUE\n> \n> st_contains_properly(ncm[1:3,], ncm[1:3])\nSparse geometry binary predicate list of length 3, where the predicate\nwas `contains_properly'\n 1: (empty)\n 2: (empty)\n 3: (empty)\n> \n> st_combine(nc)\nGeometry set for 1 feature \nGeometry type: MULTIPOLYGON\nDimension:     XY\nBounding box:  xmin: -84.32385 ymin: 33.88199 xmax: -75.45698 ymax: 36.58965\nGeodetic CRS:  NAD27\nMULTIPOLYGON (((-81.47276 36.23436, -81.54084 3...\n> \n> st_dimension(st_sfc(st_point(0:1), st_linestring(rbind(c(0,0),c(1,1))), \n+ \tst_polygon(list(rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0))))))\n[1] 0 1 2\n> \n> ncbb = st_as_sfc(st_bbox(nc))\n> g = st_make_grid(ncbb)\n> x = st_intersection(nc, g)\nWarning message:\nattribute variables are assumed to be spatially constant throughout all geometries \n> x = st_intersection(g, nc)\n> \n> ls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))),\n+ st_linestring(rbind(c(0,0),c(10,0))))\n> \n> suppressWarnings(RNGversion(\"3.5.3\"))\n> set.seed(13531)\n> \n> st_line_sample(ls, density = 1, type = \"random\")\nGeometry set for 2 features \nGeometry type: MULTIPOINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 6.880179 ymax: 0.8878369\nCRS:           NA\nMULTIPOINT ((0 0.8878369))\nMULTIPOINT ((0.2986488 0), (2.48417 0), (2.5678...\n> \n> g = st_make_grid(ncbb, n = c(20,10))\n> \n> a1 = st_interpolate_aw(nc[\"BIR74\"], g, FALSE)\nWarning message:\nIn st_interpolate_aw.sf(nc[\"BIR74\"], g, FALSE) :\n  st_interpolate_aw assumes attributes are constant or uniform over areas of x\n> sum(a1$BIR74) / sum(nc$BIR74) # not close to one: property is assumed spatially intensive\n[1] 1.436123\n> a2 = st_interpolate_aw(nc[\"BIR74\"], g, extensive = TRUE)\nWarning message:\nIn st_interpolate_aw.sf(nc[\"BIR74\"], g, extensive = TRUE) :\n  st_interpolate_aw assumes attributes are constant or uniform over areas of x\n> sum(a2$BIR74) / sum(nc$BIR74)\n[1] 1\n> \n> # missing x:\n> g = st_make_grid(offset = c(0,0), cellsize = c(1,1), n = c(10,10))\n> g = st_make_grid(what = \"centers\")\n> length(g)\n[1] 648\n> g = st_make_grid(what = \"corners\")\n> length(g)\n[1] 703\n> \n> g1 = st_make_grid(ncbb, 0.1, what = \"polygons\", square = FALSE)\n> g2 = st_make_grid(ncbb, 0.1, what = \"points\", square = FALSE)\n> \n> # st_line_merge:\n> mls = st_multilinestring(list(rbind(c(0,0), c(1,1)), rbind(c(2,0), c(1,1))))\n> st_line_merge(mls)\nLINESTRING (0 0, 1 1, 2 0)\n> \n> if (isTRUE(try(compareVersion(sf_extSoftVersion()[\"GEOS\"], \"3.5.0\") > -1, silent = TRUE))) {\n+  # voronoi:\n+  set.seed(1)\n+  m = matrix(runif(10),,2)\n+  x = st_multipoint(m)\n+  box = st_polygon(list(rbind(c(0,0),c(1,0),c(1,1),c(0,1),c(0,0))))\n+  v = st_sfc(st_voronoi(x, st_sfc(box)))\n+  plot(v, col = 0, border = 1, axes = TRUE)\n+  plot(box, add = TRUE, col = 0, border = 1) # a larger box is returned, as documented\n+  plot(x, add = TRUE, col = 'red', cex=2, pch=16)\n+  plot(st_intersection(st_cast(v), box)) # clip to smaller box\n+  plot(x, add = TRUE, col = 'red', cex=2, pch=16)\n+  v0 = st_sfc(st_voronoi(st_sfc(x), st_sfc(box)))\n+  pal <- c(\"black\", \"red\", \"green\", \"blue\", \"orange\")\n+  opar = par(mfrow=c(1,2))\n+  plot(st_collection_extract(v0, \"POLYGON\"), col=pal)\n+  text(m[,1], m[,2], label=1:5, col=\"white\")\n+  if (isTRUE(try(compareVersion(sf_extSoftVersion()[\"GEOS\"], \"3.12.0\") > -1, silent = TRUE))) {\n+   v2 = st_sfc(st_voronoi(st_sfc(x), st_sfc(box), point_order=TRUE))\n+   plot(st_collection_extract(v2, \"POLYGON\"), col=pal)\n+   text(m[,1], m[,2], label=1:5, col=\"white\")\n+  }\n+  par(opar)\n+ \n+  v = st_voronoi(x)\n+  print(class(v))\n+  v = st_sfc(st_voronoi(st_sfc(x)))\n+  print(class(v))\n+  v = st_voronoi(st_sf(a = 1, geom = st_sfc(x)))\n+  print(class(v))\n+ }\n[1] \"XY\"                 \"GEOMETRYCOLLECTION\" \"sfg\"               \n[1] \"sfc_GEOMETRYCOLLECTION\" \"sfc\"                   \n[1] \"sf\"         \"data.frame\"\n> \n> i = st_intersects(ncm, ncm[1:88,])\n> all.equal(i, t(t(i)))\n[1] TRUE\n> \n> # check use of pattern in st_relate:\n> sfc = st_as_sfc(st_bbox(st_sfc(st_point(c(0,0)), st_point(c(3,3)))))\n> grd = st_make_grid(sfc, n = c(3,3))\n> st_intersects(grd)\nSparse geometry binary predicate list of length 9, where the predicate\nwas `intersects'\n 1: 1, 2, 4, 5\n 2: 1, 2, 3, 4, 5, 6\n 3: 2, 3, 5, 6\n 4: 1, 2, 4, 5, 7, 8\n 5: 1, 2, 3, 4, 5, 6, 7, 8, 9\n 6: 2, 3, 5, 6, 8, 9\n 7: 4, 5, 7, 8\n 8: 4, 5, 6, 7, 8, 9\n 9: 5, 6, 8, 9\n> st_relate(grd, pattern = \"****1****\")\nSparse geometry binary predicate list of length 9, where the predicate\nwas `relate_pattern'\n 1: 1, 2, 4\n 2: 1, 2, 3, 5\n 3: 2, 3, 6\n 4: 1, 4, 5, 7\n 5: 2, 4, 5, 6, 8\n 6: 3, 5, 6, 9\n 7: 4, 7, 8\n 8: 5, 7, 8, 9\n 9: 6, 8, 9\n> st_relate(grd, pattern = \"****0****\")\nSparse geometry binary predicate list of length 9, where the predicate\nwas `relate_pattern'\n 1: 5\n 2: 4, 6\n 3: 5\n 4: 2, 8\n 5: 1, 3, 7, 9\n 6: 2, 8\n 7: 5\n 8: 4, 6\n 9: 5\n> st_rook = function(a, b = a, ...) st_relate(a, b, pattern = \"F***1****\", ...)\n> st_rook(grd, sparse = FALSE)\n       [,1]  [,2]  [,3]  [,4]  [,5]  [,6]  [,7]  [,8]  [,9]\n [1,] FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE FALSE\n [2,]  TRUE FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE FALSE\n [3,] FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE\n [4,]  TRUE FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE\n [5,] FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE  TRUE FALSE\n [6,] FALSE FALSE  TRUE FALSE  TRUE FALSE FALSE FALSE  TRUE\n [7,] FALSE FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE\n [8,] FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE  TRUE\n [9,] FALSE FALSE FALSE FALSE FALSE  TRUE FALSE  TRUE FALSE\n> \n> #if (Sys.getenv(\"USER\") %in% c(\"edzer\", \"travis\")) { # memory leaks:\n>   try(st_relate(st_point(), st_point(), pattern = \"FF*FF****\")) # error: use st_disjoint\nError : use st_disjoint for this pattern\n> #}\n> \n> a = st_is_within_distance(nc[c(1:3,20),], nc[1:3,], 100000, sparse = FALSE)\n> b = st_is_within_distance(nc[c(1:3,20),], nc[1:3,], units::set_units(100000, m), sparse = FALSE)\n> all.equal(a, b)\n[1] TRUE\n> x = st_is_within_distance(nc[1:3,], nc[1:5,], 100000)\n> y = st_is_within_distance(nc[1:3,], nc[1:5,], units::set_units(100, km))\n> all.equal(x, y)\n[1] TRUE\n> \n> nc_3857 = st_transform(nc, 3857)\n> a = st_is_within_distance(nc_3857[c(1:3,20),], nc_3857[1:3,], 100000, sparse = FALSE)\n> b = st_is_within_distance(nc_3857[c(1:3,20),], nc_3857[1:3,], units::set_units(100000, m), sparse = FALSE)\n> all.equal(a, b)\n[1] TRUE\n> x = st_is_within_distance(nc_3857, nc_3857, 100000)\n> y = st_is_within_distance(nc_3857, nc_3857, units::set_units(100, km))\n> all.equal(x, y)\n[1] TRUE\n> \n> pe = st_sfc(st_point())\n> p = st_sfc(st_point(c(0,0)), st_point(c(0,1)), st_point(c(0,2)))\n> st_distance(p, p)\n     [,1] [,2] [,3]\n[1,]    0    1    2\n[2,]    1    0    1\n[3,]    2    1    0\n> st_distance(p, pe)\n     [,1]\n[1,]   NA\n[2,]   NA\n[3,]   NA\n> st_distance(p, p, by_element = TRUE)\n[1] 0 0 0\n> st_crs(p) = 4326\n> st_distance(p, p[c(2,3,1)], by_element = TRUE)\nUnits: [m]\n[1] 111195.1 111195.1 222390.2\n> p = st_transform(p, 3587)\n> st_distance(p, p[c(2,3,1)], by_element = TRUE)\nUnits: [m]\n[1] 144589.5 142873.3 287462.8\n> \n> # from https://github.com/r-spatial/sf/issues/458 :\n> pts <- st_sfc(st_point(c(.5,.5)), st_point(c(1.5, 1.5)), st_point(c(2.5, 2.5)))\n> pol <- st_polygon(list(rbind(c(0,0), c(2,0), c(2,2), c(0,2), c(0,0))))\n> pol_df <- data.frame(id = 1) \n> st_geometry(pol_df) <- st_sfc(pol)\n> st_intersects(pts, pol_df[pol_df$id == 2,]) # with empty sf/sfc\nSparse geometry binary predicate list of length 3, where the predicate\nwas `intersects'\n 1: (empty)\n 2: (empty)\n 3: (empty)\n> st_intersects(pts, pol_df[pol_df$id == 2,], sparse = FALSE) # with empty sf/sfc\n    \n[1,]\n[2,]\n[3,]\n> \n> # st_node\n> l = st_linestring(rbind(c(0,0), c(1,1), c(0,1), c(1,0), c(0,0)))\n> st_node(l)\nMULTILINESTRING ((0 0, 0.5 0.5), (0.5 0.5, 1 1, 0 1, 0.5 0.5), (0.5 0.5, 1 0, 0 0))\n> st_node(st_sfc(l))\nGeometry set for 1 feature \nGeometry type: MULTILINESTRING\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\nMULTILINESTRING ((0 0, 0.5 0.5), (0.5 0.5, 1 1,...\n> st_node(st_sf(a = 1, st_sfc(l)))\nSimple feature collection with 1 feature and 1 field\nGeometry type: MULTILINESTRING\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\n  a                      st_sfc.l.\n1 1 MULTILINESTRING ((0 0, 0.5 ...\n> \n> # print.sgbp:\n> (lst = st_disjoint(nc, nc))\nSparse geometry binary predicate list of length 100, where the\npredicate was `disjoint'\nfirst 10 elements:\n 1: 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, ...\n 2: 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, ...\n 3: 1, 4, 5, 6, 7, 8, 9, 11, 12, 13, ...\n 4: 1, 2, 3, 5, 6, 8, 9, 10, 11, 12, ...\n 5: 1, 2, 3, 4, 7, 8, 10, 11, 12, 13, ...\n 6: 1, 2, 3, 4, 7, 9, 10, 11, 12, 13, ...\n 7: 1, 2, 3, 5, 6, 9, 10, 11, 12, 13, ...\n 8: 1, 2, 3, 4, 5, 9, 10, 11, 12, 13, ...\n 9: 1, 2, 3, 4, 6, 7, 8, 10, 11, 12, ...\n 10: 1, 2, 4, 5, 6, 7, 8, 9, 11, 13, ...\n> # dim.sgbp:\n> dim(lst)\n[1] 100 100\n> # as.matrix.sgbp:\n> as.matrix(lst)[1:5, 1:5]\n      [,1]  [,2]  [,3]  [,4]  [,5]\n[1,] FALSE FALSE  TRUE  TRUE  TRUE\n[2,] FALSE FALSE FALSE  TRUE  TRUE\n[3,]  TRUE FALSE FALSE  TRUE  TRUE\n[4,]  TRUE  TRUE  TRUE FALSE  TRUE\n[5,]  TRUE  TRUE  TRUE  TRUE FALSE\n> # negate:\n> !lst\nSparse geometry binary predicate list of length 100, where the\npredicate was `!disjoint'\nfirst 10 elements:\n 1: 1, 2, 18, 19\n 2: 1, 2, 3, 18\n 3: 2, 3, 10, 18, 23, 25\n 4: 4, 7, 56\n 5: 5, 6, 9, 16, 28\n 6: 5, 6, 8, 28\n 7: 4, 7, 8, 17\n 8: 6, 7, 8, 17, 20, 21\n 9: 5, 9, 15, 16, 24, 31\n 10: 3, 10, 12, 25, 26\n> # as.data.frame:\n> head(as.data.frame(lst), 10)\n   row.id col.id\n1       1      3\n2       1      4\n3       1      5\n4       1      6\n5       1      7\n6       1      8\n7       1      9\n8       1     10\n9       1     11\n10      1     12\n> \n> # snap:\n> nc1 = st_transform(nc, 32119)\n> g = st_make_grid(nc1, c(5000,5000), what = \"centers\")\n> s = st_snap(nc1[1:3,], g, 2501*sqrt(2))\n> sfg = st_snap(st_geometry(nc1)[[1]], g, 2501*sqrt(2))\n> sfg = st_snap(st_geometry(nc1)[[1]], st_combine(g), 2501*sqrt(2))\n> \n> # Hausdorff distance: http://geos.refractions.net/ro/doxygen_docs/html/classgeos_1_1algorithm_1_1distance_1_1DiscreteHausdorffDistance.html\n> A = st_as_sfc(\"LINESTRING (0 0, 100 0, 10 100, 10 100)\")\n> B = st_as_sfc(\"LINESTRING (0 100, 0 10, 80 10)\")\n> st_distance(c(A,B))\n         [,1]     [,2]\n[1,] 0.000000 8.176236\n[2,] 8.176236 0.000000\n> st_distance(c(A,B), which = \"Hausdorff\")\n         [,1]     [,2]\n[1,]  0.00000 22.36068\n[2,] 22.36068  0.00000\n> st_distance(c(A,B), which = \"Hausdorff\", par = 0.001)\n             [,1]         [,2]\n[1,] 2.929643e-14 4.789000e+01\n[2,] 4.789000e+01 2.131628e-14\n> LE = st_as_sfc(\"LINESTRING EMPTY\")\n> st_distance(c(A, LE), which = \"Hausdorff\", par = 0.001)\n             [,1] [,2]\n[1,] 2.929643e-14   NA\n[2,]           NA   NA\n> \n> # one-argument st_intersection and st_difference:\n> set.seed(131)\n> m = rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0))\n> p = st_polygon(list(m))\n> n = 100\n> l = vector(\"list\", n)\n> for (i in 1:n)\n+    l[[i]] = p + 10 * runif(2)\n> s = st_sfc(l)\n> plot(s, col = sf.colors(categorical = TRUE, alpha = .5))\n> d = st_difference(s) # sequential differences: s1, s2-s1, s3-s2-s1, ...\n> plot(d, col = sf.colors(categorical = TRUE, alpha = .5))\n> i = st_intersection(s) # all intersections\n> plot(i, col = sf.colors(categorical = TRUE, alpha = .5))\n> summary(lengths(st_overlaps(s, s)))\n   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. \n   0.00    2.00    3.50    3.66    5.00    8.00 \n> summary(lengths(st_overlaps(d, d)))\n   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. \n      0       0       0       0       0       0 \n> summary(lengths(st_overlaps(i, i)))\n   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. \n      0       0       0       0       0       0 \n> \n> sf = st_sf(s)\n> i = st_intersection(sf) # all intersections\n> plot(i[\"n.overlaps\"])\n> summary(i$n.overlaps - lengths(i$origins))\n   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. \n      0       0       0       0       0       0 \n> \n> # st_nearest_points:\n> pt1 = st_point(c(.1,.1))\n> pt2 = st_point(c(.9,.9))\n> b1 = st_buffer(pt1, 0.1)\n> b2 = st_buffer(pt2, 0.1)\n> plot(b1, xlim = c(0,1), ylim = c(0,1))\n> plot(b2, add = TRUE)\n> (ls0 = try(st_nearest_points(b1, b2))) # sfg\nGeometry set for 1 feature \nGeometry type: LINESTRING\nDimension:     XY\nBounding box:  xmin: 0.1707107 ymin: 0.1707107 xmax: 0.8292893 ymax: 0.8292893\nCRS:           NA\nLINESTRING (0.1707107 0.1707107, 0.8292893 0.82...\n> (ls = try(st_nearest_points(st_sfc(b1), st_sfc(b2)))) # sfc\nGeometry set for 1 feature \nGeometry type: LINESTRING\nDimension:     XY\nBounding box:  xmin: 0.1707107 ymin: 0.1707107 xmax: 0.8292893 ymax: 0.8292893\nCRS:           NA\nLINESTRING (0.1707107 0.1707107, 0.8292893 0.82...\n> (ls = try(st_nearest_points(st_sfc(b1), st_sfc(b2), pairwise = TRUE))) # sfc\nGeometry set for 1 feature \nGeometry type: LINESTRING\nDimension:     XY\nBounding box:  xmin: 0.1707107 ymin: 0.1707107 xmax: 0.8292893 ymax: 0.8292893\nCRS:           NA\nLINESTRING (0.1707107 0.1707107, 0.8292893 0.82...\n> identical(ls0, ls)\n[1] TRUE\n> # plot(ls, add = TRUE, col = 'red')\n> \n> nc = read_sf(system.file(\"gpkg/nc.gpkg\", package=\"sf\"))\n> plot(st_geometry(nc))\n> ls = try(st_nearest_points(nc[1,], nc))\n> # plot(ls, col = 'red', add = TRUE)\n> pts = st_cast(ls, \"POINT\") # gives all start & end points\nThere were 50 or more warnings (use warnings() to see the first 50)\n> # starting, \"from\" points, corresponding to x:\n> plot(pts[seq(1, 200, 2)], add = TRUE, col = 'blue')\n> # ending, \"to\" points, corresponding to y:\n> plot(pts[seq(2, 200, 2)], add = TRUE, col = 'red')\n> \n> # points to nearest features\n> ls1 = st_linestring(rbind(c(0,0), c(1,0)))\n> ls2 = st_linestring(rbind(c(0,0.1), c(1,0.1)))\n> ls3 = st_linestring(rbind(c(0,1), c(1,1)))\n> (l = st_sfc(ls1, ls2, ls3))\nGeometry set for 3 features \nGeometry type: LINESTRING\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\nLINESTRING (0 0, 1 0)\nLINESTRING (0 0.1, 1 0.1)\nLINESTRING (0 1, 1 1)\n> \n> p1 = st_point(c(0.1, -0.1))\n> p2 = st_point(c(0.1, 0.11))\n> p3 = st_point(c(0.1, 0.09))\n> p4 = st_point(c(0.1, 0.9))\n> p5 = st_point()\n> \n> (p = st_sfc(p1, p2, p3, p4, p5))\nGeometry set for 5 features  (with 1 geometry empty)\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0.1 ymin: -0.1 xmax: 0.1 ymax: 0.9\nCRS:           NA\nPOINT (0.1 -0.1)\nPOINT (0.1 0.11)\nPOINT (0.1 0.09)\nPOINT (0.1 0.9)\nPOINT EMPTY\n> #st_nearest_points(p, l)\n> n = try(st_nearest_feature(p,l))\n> if (!inherits(n, \"try-error\")) {\n+   print(st_nearest_points(p, l[n], pairwise = TRUE))\n+   print(st_nearest_feature(p, l))\n+   print(st_nearest_feature(p, st_sfc()))\n+   print(st_nearest_feature(st_sfc(), l))\n+ }\nGeometry set for 5 features  (with 1 geometry empty)\nGeometry type: LINESTRING\nDimension:     XY\nBounding box:  xmin: 0.1 ymin: -0.1 xmax: 0.1 ymax: 1\nCRS:           NA\nLINESTRING (0.1 -0.1, 0.1 0)\nLINESTRING (0.1 0.11, 0.1 0.1)\nLINESTRING (0.1 0.09, 0.1 0.1)\nLINESTRING (0.1 0.9, 0.1 1)\nLINESTRING EMPTY\n[1]  1  2  2  3 NA\n[1] NA NA NA NA NA\ninteger(0)\n> \n> # can do centroid of empty geom:\n> st_centroid(st_polygon())\nPOINT EMPTY\n> \n> #999:\n> pt = data.frame(x=1:2, y=1:2,a=letters[1:2])\n> pt = st_as_sf(pt, coords=c(\"x\",\"y\"))\n> \n> bf =st_buffer(pt, dist=0.3)\n> \n> st_within(pt,bf, sparse=FALSE)\n      [,1]  [,2]\n[1,]  TRUE FALSE\n[2,] FALSE  TRUE\n> st_within(pt[1,], bf[1,], sparse = FALSE)\n     [,1]\n[1,] TRUE\n> st_relate(pt[1,], bf[1,], pattern = \"T*F**F***\", sparse = FALSE)\n     [,1]\n[1,] TRUE\n> \n> sf:::is_symmetric(pattern = \"010121010\")\n[1] TRUE\n> sf:::is_symmetric(pattern = \"010121021\")\n[1] FALSE\n> \n> st_intersects(st_point(0:1), st_point(2:3)) # sfg method\nSparse geometry binary predicate list of length 1, where the predicate\nwas `intersects'\n 1: (empty)\n> \n> if (isTRUE(try(compareVersion(sf_extSoftVersion()[\"GEOS\"], \"3.7.0\") > -1, silent = TRUE))) {\n+ \tls = st_linestring(rbind(c(1,1), c(2,2), c(3,3)))\n+ \tprint(st_reverse(ls))\n+ \tprint(st_reverse(st_sfc(ls)))\n+ \tprint(st_reverse(st_sf(a = 2, geom = st_sfc(ls))))\n+ }\nLINESTRING (3 3, 2 2, 1 1)\nGeometry set for 1 feature \nGeometry type: LINESTRING\nDimension:     XY\nBounding box:  xmin: 1 ymin: 1 xmax: 3 ymax: 3\nCRS:           NA\nLINESTRING (3 3, 2 2, 1 1)\nSimple feature collection with 1 feature and 1 field\nGeometry type: LINESTRING\nDimension:     XY\nBounding box:  xmin: 1 ymin: 1 xmax: 3 ymax: 3\nCRS:           NA\n  a                       geom\n1 2 LINESTRING (3 3, 2 2, 1 1)\n> \n> p = st_polygon(list(rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0))))\n> y = st_sfc(p)\n> x = st_sfc(p + 1.001)\n> \n> x |> st_set_precision(0) |> st_intersects(y)\nSparse geometry binary predicate list of length 1, where the predicate\nwas `intersects'\n 1: (empty)\n> x |> st_set_precision(10000) |> st_intersects(y)\nSparse geometry binary predicate list of length 1, where the predicate\nwas `intersects'\n 1: (empty)\n> x |> st_set_precision(1000) |> st_intersects(y)\nSparse geometry binary predicate list of length 1, where the predicate\nwas `intersects'\n 1: (empty)\n> x |> st_set_precision(501) |> st_intersects(y) # no\nSparse geometry binary predicate list of length 1, where the predicate\nwas `intersects'\n 1: (empty)\n> x |> st_set_precision(500) |> st_intersects(y) # yes\nSparse geometry binary predicate list of length 1, where the predicate\nwas `intersects'\n 1: 1\n> x |> st_set_precision(100) |> st_intersects(y)\nSparse geometry binary predicate list of length 1, where the predicate\nwas `intersects'\n 1: 1\n> x |> st_set_precision(10) |> st_intersects(y)\nSparse geometry binary predicate list of length 1, where the predicate\nwas `intersects'\n 1: 1\n> \n> p1 = st_point(0:1)\n> p2 = st_point(2:1)\n> p = st_sf(a = letters[1:8], geom = st_sfc(p1, p1, p2, p1, p1, p2, p2, p1))\n> st_equals(p)\nSparse geometry binary predicate list of length 8, where the predicate\nwas `equals'\n 1: 1, 2, 4, 5, 8\n 2: 1, 2, 4, 5, 8\n 3: 3, 6, 7\n 4: 1, 2, 4, 5, 8\n 5: 1, 2, 4, 5, 8\n 6: 3, 6, 7\n 7: 3, 6, 7\n 8: 1, 2, 4, 5, 8\n> st_equals(p, remove_self = TRUE)\nSparse geometry binary predicate list of length 8, where the predicate\nwas `equals', with remove_self = TRUE\n 1: 2, 4, 5, 8\n 2: 1, 4, 5, 8\n 3: 6, 7\n 4: 1, 2, 5, 8\n 5: 1, 2, 4, 8\n 6: 3, 7\n 7: 3, 6\n 8: 1, 2, 4, 5\n> (u = st_equals(p, retain_unique = TRUE))\nSparse geometry binary predicate list of length 8, where the predicate\nwas `equals', with retain_unique = TRUE\n 1: 2, 4, 5, 8\n 2: 4, 5, 8\n 3: 6, 7\n 4: 5, 8\n 5: 8\n 6: 7\n 7: (empty)\n 8: (empty)\n> # retain the records with unique geometries:\n> p[-unlist(u),]\nSimple feature collection with 2 features and 1 field\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 2 ymax: 1\nCRS:           NA\n  a        geom\n1 a POINT (0 1)\n3 c POINT (2 1)\n> \n> proc.time()\n   user  system elapsed \n 11.306   1.440  11.246 \n"
  },
  {
    "path": "tests/graticule.R",
    "content": "if (require(maps, quietly = TRUE)) {\nm = map('usa', plot = FALSE, fill = TRUE)\nsuppressPackageStartupMessages(library(sf))\nm0 <- st_as_sfc(m)\nm <- st_as_sf(m)\n\nlaea = st_crs(\"+proj=laea +lat_0=30 +lon_0=-95\") # Lambert equal area\nm <- st_transform(st_as_sf(m), laea)\n\nbb = st_bbox(m)\nbbox = st_linestring(rbind(c( bb[1],bb[2]),c( bb[3],bb[2]),c( bb[3],bb[4]),c( bb[1],bb[4]),c( bb[1],bb[2])))\n\ng = st_graticule(m)\nplot(m, xlim = 1.2 * c(-2450853.4, 2186391.9))\nplot(g[1], add = TRUE, col = 'grey')\nplot(bbox, add = TRUE)\npoints(g$x_start, g$y_start, col = 'red')\npoints(g$x_end, g$y_end, col = 'blue')\n\ninvisible(lapply(seq_len(nrow(g)), function(i) {\n\tif (g$type[i] == \"N\" && g$x_start[i] - min(g$x_start) < 1000)\n\t\ttext(g$x_start[i], g$y_start[i], labels = parse(text = g$degree_label[i]), \n\t\t\tsrt = g$angle_start[i], pos = 2, cex = .7)\n\tif (g$type[i] == \"E\" && g$y_start[i] - min(g$y_start) < 1000)\n\t\ttext(g$x_start[i], g$y_start[i], labels = parse(text = g$degree_label[i]), \n\t\t\tsrt = g$angle_start[i] - 90, pos = 1, cex = .7)\n\tif (g$type[i] == \"N\" && g$x_end[i] - max(g$x_end) > -1000)\n\t\ttext(g$x_end[i], g$y_end[i], labels = parse(text = g$degree_label[i]), \n\t\t\tsrt = g$angle_end[i], pos = 4, cex = .7)\n\tif (g$type[i] == \"E\" && g$y_end[i] - max(g$y_end) > -1000)\n\t\ttext(g$x_end[i], g$y_end[i], labels = parse(text = g$degree_label[i]), \n\t\t\tsrt = g$angle_end[i] - 90, pos = 3, cex = .7)\n}))\n\nplot(m, graticule = st_crs(4326))\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\n# options(warn=2)\ng = st_graticule(nc, datum = st_crs(nc))\n#g = st_graticule(nc)\n\nplot(nc[1], graticule = st_crs(nc))\n\nplot(nc[1], graticule = st_crs(nc), axes = TRUE)\n\ng = st_graticule()\n\nif (require(ggplot2, quietly = TRUE) && utils::packageVersion(\"ggplot2\") > \"2.2.1\") {\n  ggplot() + geom_sf(data = st_set_crs(nc, NA_crs_)) # NA_crs_ for crs\n}\n\nlibrary(maps) #421\n(wrld2 = st_as_sf(map('world2', plot=FALSE, fill=TRUE )))\ntry(plot(wrld2, graticule = TRUE))\n}\n"
  },
  {
    "path": "tests/graticule.Rout.save",
    "content": "\nR Under development (unstable) (2025-11-05 r88988 ucrt) -- \"Unsuffered Consequences\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-w64-mingw32/x64\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> if (require(maps, quietly = TRUE)) {\n+ m = map('usa', plot = FALSE, fill = TRUE)\n+ suppressPackageStartupMessages(library(sf))\n+ m0 <- st_as_sfc(m)\n+ m <- st_as_sf(m)\n+ \n+ laea = st_crs(\"+proj=laea +lat_0=30 +lon_0=-95\") # Lambert equal area\n+ m <- st_transform(st_as_sf(m), laea)\n+ \n+ bb = st_bbox(m)\n+ bbox = st_linestring(rbind(c( bb[1],bb[2]),c( bb[3],bb[2]),c( bb[3],bb[4]),c( bb[1],bb[4]),c( bb[1],bb[2])))\n+ \n+ g = st_graticule(m)\n+ plot(m, xlim = 1.2 * c(-2450853.4, 2186391.9))\n+ plot(g[1], add = TRUE, col = 'grey')\n+ plot(bbox, add = TRUE)\n+ points(g$x_start, g$y_start, col = 'red')\n+ points(g$x_end, g$y_end, col = 'blue')\n+ \n+ invisible(lapply(seq_len(nrow(g)), function(i) {\n+ \tif (g$type[i] == \"N\" && g$x_start[i] - min(g$x_start) < 1000)\n+ \t\ttext(g$x_start[i], g$y_start[i], labels = parse(text = g$degree_label[i]), \n+ \t\t\tsrt = g$angle_start[i], pos = 2, cex = .7)\n+ \tif (g$type[i] == \"E\" && g$y_start[i] - min(g$y_start) < 1000)\n+ \t\ttext(g$x_start[i], g$y_start[i], labels = parse(text = g$degree_label[i]), \n+ \t\t\tsrt = g$angle_start[i] - 90, pos = 1, cex = .7)\n+ \tif (g$type[i] == \"N\" && g$x_end[i] - max(g$x_end) > -1000)\n+ \t\ttext(g$x_end[i], g$y_end[i], labels = parse(text = g$degree_label[i]), \n+ \t\t\tsrt = g$angle_end[i], pos = 4, cex = .7)\n+ \tif (g$type[i] == \"E\" && g$y_end[i] - max(g$y_end) > -1000)\n+ \t\ttext(g$x_end[i], g$y_end[i], labels = parse(text = g$degree_label[i]), \n+ \t\t\tsrt = g$angle_end[i] - 90, pos = 3, cex = .7)\n+ }))\n+ \n+ plot(m, graticule = st_crs(4326))\n+ nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\n+ # options(warn=2)\n+ g = st_graticule(nc, datum = st_crs(nc))\n+ #g = st_graticule(nc)\n+ \n+ plot(nc[1], graticule = st_crs(nc))\n+ \n+ plot(nc[1], graticule = st_crs(nc), axes = TRUE)\n+ \n+ g = st_graticule()\n+ \n+ if (require(ggplot2, quietly = TRUE) && utils::packageVersion(\"ggplot2\") > \"2.2.1\") {\n+   ggplot() + geom_sf(data = st_set_crs(nc, NA_crs_)) # NA_crs_ for crs\n+ }\n+ \n+ library(maps) #421\n+ (wrld2 = st_as_sf(map('world2', plot=FALSE, fill=TRUE )))\n+ try(plot(wrld2, graticule = TRUE))\n+ }\n> \n> proc.time()\n   user  system elapsed \n   1.68    0.37    2.04 \n"
  },
  {
    "path": "tests/grid.R",
    "content": "# MULTIPOLYGONS\nsuppressPackageStartupMessages(library(sf))\nlibrary(grid)\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\ngrid.newpage()\n# pushViewport(viewport(width = 0.8, height = 0.8))\npushViewport(st_viewport(nc))\ninvisible(lapply(st_geometry(nc), function(x) grid.draw(st_as_grob(x, gp = gpar(fill = 'red')))))\n\n# POLYGONS\n# nc = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), \"nc.gpkg\", type = 3)\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), type = 3, quiet = TRUE)\ngrid.newpage()\npushViewport(st_viewport(nc))\ninvisible(lapply(st_geometry(nc), function(x) grid.draw(st_as_grob(x, gp = gpar(fill = 'red')))))\n\n# POINTS:\nif (suppressPackageStartupMessages(require(sp, quietly = TRUE))) {\n data(meuse, package = \"sp\")\n meuse_sf = st_as_sf(meuse, coords = c(\"x\", \"y\"), crs = 28992, agr = \"constant\")\n grid.newpage()\n pushViewport(st_viewport(meuse_sf))\n invisible(lapply(st_geometry(meuse_sf), \n\tfunction(x) grid.draw(st_as_grob(x, gp = gpar(fill = 'red')))))\n}\n\n# MULTIPOINTS\nmp = st_multipoint(cbind(runif(100), runif(100)))\ngrid.newpage()\npushViewport(st_viewport(mp))\ngrid.draw(st_as_grob(mp, gp = gpar(fill = 'red')))\n\n# LINESTRING\nls = st_linestring(cbind(1:10, rnorm(10)))\ngrid.newpage()\npushViewport(st_viewport(ls))\ngrid.draw(st_as_grob(ls, gp = gpar(fill = 'red')))\n\n# MULTILINESTRING\nls = st_multilinestring(list(cbind(1:10, 5+rnorm(10)), cbind(1:10, rnorm(10)), cbind(1:10, -5+rnorm(10))))\ngrid.newpage()\npushViewport(st_viewport(ls))\ngrid.draw(st_as_grob(ls, gp = gpar(fill = 'red')))\n\nif (require(sp, quietly = TRUE)) {\n# POINTS, right aspect in Long/Lat:\nmeuse_ll = st_transform(meuse_sf, 4326)\ngrid.newpage()\npushViewport(st_viewport(meuse_ll))\ninvisible(lapply(st_geometry(meuse_ll), \n\tfunction(x) grid.draw(st_as_grob(x, gp = gpar(fill = 'red')))))\n\n# WRONG aspect:\nst_crs(meuse_ll) = NA\ngrid.newpage()\npushViewport(st_viewport(meuse_ll))\ninvisible(lapply(st_geometry(meuse_ll), \n\tfunction(x) grid.draw(st_as_grob(x, gp = gpar(fill = 'red')))))\n}\n\ngc = st_geometrycollection(list(st_point(0:1), st_linestring(matrix(1:4,2))))\ngrb = st_as_grob(gc)\n"
  },
  {
    "path": "tests/grid.Rout.save",
    "content": "\nR Under development (unstable) (2025-11-05 r88988 ucrt) -- \"Unsuffered Consequences\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-w64-mingw32/x64\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> # MULTIPOLYGONS\n> suppressPackageStartupMessages(library(sf))\n> library(grid)\n> nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\n> grid.newpage()\n> # pushViewport(viewport(width = 0.8, height = 0.8))\n> pushViewport(st_viewport(nc))\n> invisible(lapply(st_geometry(nc), function(x) grid.draw(st_as_grob(x, gp = gpar(fill = 'red')))))\n> \n> # POLYGONS\n> # nc = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), \"nc.gpkg\", type = 3)\n> nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), type = 3, quiet = TRUE)\n> grid.newpage()\n> pushViewport(st_viewport(nc))\n> invisible(lapply(st_geometry(nc), function(x) grid.draw(st_as_grob(x, gp = gpar(fill = 'red')))))\n> \n> # POINTS:\n> if (suppressPackageStartupMessages(require(sp, quietly = TRUE))) {\n+  data(meuse, package = \"sp\")\n+  meuse_sf = st_as_sf(meuse, coords = c(\"x\", \"y\"), crs = 28992, agr = \"constant\")\n+  grid.newpage()\n+  pushViewport(st_viewport(meuse_sf))\n+  invisible(lapply(st_geometry(meuse_sf), \n+ \tfunction(x) grid.draw(st_as_grob(x, gp = gpar(fill = 'red')))))\n+ }\n> \n> # MULTIPOINTS\n> mp = st_multipoint(cbind(runif(100), runif(100)))\n> grid.newpage()\n> pushViewport(st_viewport(mp))\n> grid.draw(st_as_grob(mp, gp = gpar(fill = 'red')))\n> \n> # LINESTRING\n> ls = st_linestring(cbind(1:10, rnorm(10)))\n> grid.newpage()\n> pushViewport(st_viewport(ls))\n> grid.draw(st_as_grob(ls, gp = gpar(fill = 'red')))\n> \n> # MULTILINESTRING\n> ls = st_multilinestring(list(cbind(1:10, 5+rnorm(10)), cbind(1:10, rnorm(10)), cbind(1:10, -5+rnorm(10))))\n> grid.newpage()\n> pushViewport(st_viewport(ls))\n> grid.draw(st_as_grob(ls, gp = gpar(fill = 'red')))\n> \n> if (require(sp, quietly = TRUE)) {\n+ # POINTS, right aspect in Long/Lat:\n+ meuse_ll = st_transform(meuse_sf, 4326)\n+ grid.newpage()\n+ pushViewport(st_viewport(meuse_ll))\n+ invisible(lapply(st_geometry(meuse_ll), \n+ \tfunction(x) grid.draw(st_as_grob(x, gp = gpar(fill = 'red')))))\n+ \n+ # WRONG aspect:\n+ st_crs(meuse_ll) = NA\n+ grid.newpage()\n+ pushViewport(st_viewport(meuse_ll))\n+ invisible(lapply(st_geometry(meuse_ll), \n+ \tfunction(x) grid.draw(st_as_grob(x, gp = gpar(fill = 'red')))))\n+ }\n> \n> gc = st_geometrycollection(list(st_point(0:1), st_linestring(matrix(1:4,2))))\n> grb = st_as_grob(gc)\n> \n> proc.time()\n   user  system elapsed \n   0.90    0.15    1.04 \n"
  },
  {
    "path": "tests/maps.R",
    "content": "suppressPackageStartupMessages(library(sf))\n\nif (require(maps, quietly = TRUE)) {\n m = map(xlim = c(4,9), ylim = c(48,55), fill = TRUE, plot = FALSE)\n st_as_sf(m)\n m = map(xlim = c(4,9), ylim = c(48,55), plot = FALSE)\n st_as_sf(m, fill = FALSE)\n st_as_sf(map(), fill = FALSE)\n st_as_sf(map(fill = TRUE))\n st_as_sf(map(), fill = FALSE, group = FALSE)\n st_as_sf(map(fill = TRUE), group = FALSE)\n}\n"
  },
  {
    "path": "tests/maps.Rout.save",
    "content": "\nR Under development (unstable) (2025-11-05 r88988 ucrt) -- \"Unsuffered Consequences\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-w64-mingw32/x64\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> \n> if (require(maps, quietly = TRUE)) {\n+  m = map(xlim = c(4,9), ylim = c(48,55), fill = TRUE, plot = FALSE)\n+  st_as_sf(m)\n+  m = map(xlim = c(4,9), ylim = c(48,55), plot = FALSE)\n+  st_as_sf(m, fill = FALSE)\n+  st_as_sf(map(), fill = FALSE)\n+  st_as_sf(map(fill = TRUE))\n+  st_as_sf(map(), fill = FALSE, group = FALSE)\n+  st_as_sf(map(fill = TRUE), group = FALSE)\n+ }\nSimple feature collection with 1627 features and 1 field\nGeometry type: MULTIPOLYGON\nDimension:     XY\nBounding box:  xmin: -180 ymin: -85.19218 xmax: 190.2708 ymax: 83.59961\nGeodetic CRS:  +proj=longlat +ellps=clrk66 +no_defs +type=crs\nFirst 10 features:\n                                                                 ID\nAruba                                                         Aruba\nAfghanistan                                             Afghanistan\nAngola                                                       Angola\nAngola:Cabinda                                       Angola:Cabinda\nAnguilla                                                   Anguilla\nAlbania                                                     Albania\nFinland:Aland Islands:Foglo             Finland:Aland Islands:Foglo\nFinland:Aland Islands:Eckero           Finland:Aland Islands:Eckero\nFinland:Aland Islands:Fasta Aland Finland:Aland Islands:Fasta Aland\nAndorra                                                     Andorra\n                                                            geom\nAruba                             MULTIPOLYGON (((-69.89912 1...\nAfghanistan                       MULTIPOLYGON (((74.89131 37...\nAngola                            MULTIPOLYGON (((23.9665 -10...\nAngola:Cabinda                    MULTIPOLYGON (((12.21367 -5...\nAnguilla                          MULTIPOLYGON (((-63.00122 1...\nAlbania                           MULTIPOLYGON (((20.06396 42...\nFinland:Aland Islands:Foglo       MULTIPOLYGON (((20.61133 60...\nFinland:Aland Islands:Eckero      MULTIPOLYGON (((19.6623 60....\nFinland:Aland Islands:Fasta Aland MULTIPOLYGON (((19.98955 60...\nAndorra                           MULTIPOLYGON (((1.706055 42...\n> \n> proc.time()\n   user  system elapsed \n   1.28    0.18    1.45 \n"
  },
  {
    "path": "tests/plot.R",
    "content": "suppressPackageStartupMessages(library(sf))\noptions(rgdal_show_exportToProj4_warnings = \"none\")\n\nif (require(dplyr, quietly = TRUE)) {\n\n# plot linestrings:\nl1 = st_linestring(matrix(runif(6)-0.5,,2))\nl2 = st_linestring(matrix(runif(6)-0.5,,2))\nl3 = st_linestring(matrix(runif(6)-0.5,,2))\ns = st_sf(a=2:4, b=st_sfc(l1,l2,l3))\nplot(s, col = s$a, axes = FALSE)\nplot(s, col = s$a)\nif (suppressPackageStartupMessages(require(sp, quietly = TRUE))) {\n  attr(s$b, \"proj4string\") = sp::CRS(\"+proj=longlat +ellps=WGS84 +no_defs\")@projargs\n}\nplot(s, col = s$a, axes = TRUE)\nplot(s, col = s$a, lty = s$a, lwd = s$a, pch = s$a, type = 'b')\nl4 = st_linestring(matrix(runif(6),,2))\nplot(st_sf(a=1,b=st_sfc(l4)), add = TRUE)\n# plot multilinestrings:\nml1 = st_multilinestring(list(l1, l2))\nml2 = st_multilinestring(list(l3, l4))\nml = st_sf(a = 2:3, b = st_sfc(ml1, ml2))\nplot(ml, col = ml$a, lty = ml$a, lwd = ml$a, pch = ml$a, type = 'b')\n# plot points:\np1 = st_point(c(1,2))\np2 = st_point(c(3,3))\np3 = st_point(c(3,0))\np = st_sf(a=2:4, b=st_sfc(p1,p2,p3))\nplot(p, col = s$a, axes = TRUE)\nplot(p, col = s$a)\nplot(p, col = p$a, pch = p$a, cex = p$a, bg = s$a, lwd = 2, lty = 2, type = 'b')\np4 = st_point(c(2,2))\nplot(st_sf(a=1, st_sfc(p4)), add = TRUE)\n# multipoints:\nmp1 = st_multipoint(matrix(1:4,2))\nmp2 = st_multipoint(matrix(5:8,2))\nmp = st_sf(a = 2:3, b = st_sfc(mp1, mp2))\nplot(mp)\nplot(mp, col = mp$a, pch = mp$a, cex = mp$a, bg = mp$a, lwd = mp$a, lty = mp$a, type = 'b')\n# polygon:\nouter = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\nhole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\nhole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\npl1 = st_polygon(list(outer, hole1, hole2))\npl2 = st_polygon(list(outer+10, hole1+10, hole2+10))\npo = st_sf(a = 2:3, st_sfc(pl1,pl2))\nplot(po, col = po$a, border = rev(po$a), lwd=3)\n# multipolygon\nr10 = matrix(rep(c(0,10),each=5),5)\npl1 = list(outer, hole1, hole2)\npl2 = list(outer+10, hole1+10, hole2+10)\npl3 = list(outer+r10, hole1+r10, hole2+r10)\nmpo1 = st_multipolygon(list(pl1,pl2))\nmpo2 = st_multipolygon(list(pl3))\nmpo = st_sf(a=2:3, b=st_sfc(mpo1,mpo2))\nplot(mpo, col = mpo$a, border = rev(mpo$a), lwd = 2)\n# geometrycollection:\ngc1 = st_geometrycollection(list(mpo1, st_point(c(21,21)), l1 * 2 + 21))\ngc2 = st_geometrycollection(list(mpo2, l2 - 2, l3 - 2, st_point(c(-1,-1))))\ngc = st_sf(a=2:3, b = st_sfc(gc1,gc2))\nplot(gc, cex = gc$a, col = gc$a, border = rev(gc$a) + 2, lwd = 2)\n\nplot(gc1)\n\nplot(st_sfc(mp1, mpo1))\n\n# color ramp\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\nplot(nc)\nplot(nc, axes = TRUE)\nplot(nc, col=\"lightgrey\") \nplot(st_centroid(nc), add = TRUE, col = 1)\nif (\"geometry\" %in% names(nc)) {\n nc |> \n  select(geometry) |> \n  plot()\n}\n\nnc$f = cut(nc[[1]], 5)\nplot(nc[\"f\"], key.pos = 1)\nplot(nc[1],   key.pos = 1)\n\n# test background map plotting:\nload(\"bgmap.rda\")\nmerc = st_crs(3857)\nWGS84 = st_crs(4326)\nnc = st_transform(nc, WGS84)\n## ggmap:\n#library(ggmap)\n#bgMap = get_map(unname(st_bbox(nc)), source = \"google\", zoom = 8) \nplot(st_transform(nc[1], merc), bgMap = bgMap)\n\n# RgoogleMaps:\n#library(RgoogleMaps)\n#center = c(mean(st_bbox(nc)[c(2,4)]), mean(st_bbox(nc)[c(1,3)]))\n#g = GetMap(center=center, zoom=6) # google\npar(mar = c(0,0,1,0))\nplot(st_transform(nc, merc), bgMap = g)\n\nm = st_make_grid()\nst_crs(m) = NA_crs_\nm = st_segmentize(m, 2)\nst_crs(m) = 4326\nplot(m, axes = TRUE)\ng = st_transform(m, st_crs(\"+proj=ortho +lat_0=30 +lon_0=45\"), check = TRUE)\nplot(g, axes = TRUE)\n\nnc[[1]] = NA\nnc[[10]] = 1\nplot(nc, pal = rainbow, nbreaks = 3)\nplot(nc, pal = rainbow, breaks = \"jenks\", nbreaks = 3)\nplot(nc, pal = rainbow, breaks = (0:10)/3)\n\n# logz:\nnc$e = 10^(nc$SID74)\nplot(nc[\"e\"], logz = TRUE)\n\n# shared key:\nplot(nc[c(\"SID74\", \"SID79\")], key.pos = -1)\nplot(nc[c(\"BIR74\", \"BIR79\")], key.pos = 1, logz=TRUE)\n}\n"
  },
  {
    "path": "tests/plot.Rout.save",
    "content": "\nR version 4.5.2 (2025-10-31) -- \"[Not] Part in a Rumble\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-pc-linux-gnu\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> options(rgdal_show_exportToProj4_warnings = \"none\")\n> \n> if (require(dplyr, quietly = TRUE)) {\n+ \n+ # plot linestrings:\n+ l1 = st_linestring(matrix(runif(6)-0.5,,2))\n+ l2 = st_linestring(matrix(runif(6)-0.5,,2))\n+ l3 = st_linestring(matrix(runif(6)-0.5,,2))\n+ s = st_sf(a=2:4, b=st_sfc(l1,l2,l3))\n+ plot(s, col = s$a, axes = FALSE)\n+ plot(s, col = s$a)\n+ if (suppressPackageStartupMessages(require(sp, quietly = TRUE))) {\n+   attr(s$b, \"proj4string\") = sp::CRS(\"+proj=longlat +ellps=WGS84 +no_defs\")@projargs\n+ }\n+ plot(s, col = s$a, axes = TRUE)\n+ plot(s, col = s$a, lty = s$a, lwd = s$a, pch = s$a, type = 'b')\n+ l4 = st_linestring(matrix(runif(6),,2))\n+ plot(st_sf(a=1,b=st_sfc(l4)), add = TRUE)\n+ # plot multilinestrings:\n+ ml1 = st_multilinestring(list(l1, l2))\n+ ml2 = st_multilinestring(list(l3, l4))\n+ ml = st_sf(a = 2:3, b = st_sfc(ml1, ml2))\n+ plot(ml, col = ml$a, lty = ml$a, lwd = ml$a, pch = ml$a, type = 'b')\n+ # plot points:\n+ p1 = st_point(c(1,2))\n+ p2 = st_point(c(3,3))\n+ p3 = st_point(c(3,0))\n+ p = st_sf(a=2:4, b=st_sfc(p1,p2,p3))\n+ plot(p, col = s$a, axes = TRUE)\n+ plot(p, col = s$a)\n+ plot(p, col = p$a, pch = p$a, cex = p$a, bg = s$a, lwd = 2, lty = 2, type = 'b')\n+ p4 = st_point(c(2,2))\n+ plot(st_sf(a=1, st_sfc(p4)), add = TRUE)\n+ # multipoints:\n+ mp1 = st_multipoint(matrix(1:4,2))\n+ mp2 = st_multipoint(matrix(5:8,2))\n+ mp = st_sf(a = 2:3, b = st_sfc(mp1, mp2))\n+ plot(mp)\n+ plot(mp, col = mp$a, pch = mp$a, cex = mp$a, bg = mp$a, lwd = mp$a, lty = mp$a, type = 'b')\n+ # polygon:\n+ outer = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\n+ hole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\n+ hole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\n+ pl1 = st_polygon(list(outer, hole1, hole2))\n+ pl2 = st_polygon(list(outer+10, hole1+10, hole2+10))\n+ po = st_sf(a = 2:3, st_sfc(pl1,pl2))\n+ plot(po, col = po$a, border = rev(po$a), lwd=3)\n+ # multipolygon\n+ r10 = matrix(rep(c(0,10),each=5),5)\n+ pl1 = list(outer, hole1, hole2)\n+ pl2 = list(outer+10, hole1+10, hole2+10)\n+ pl3 = list(outer+r10, hole1+r10, hole2+r10)\n+ mpo1 = st_multipolygon(list(pl1,pl2))\n+ mpo2 = st_multipolygon(list(pl3))\n+ mpo = st_sf(a=2:3, b=st_sfc(mpo1,mpo2))\n+ plot(mpo, col = mpo$a, border = rev(mpo$a), lwd = 2)\n+ # geometrycollection:\n+ gc1 = st_geometrycollection(list(mpo1, st_point(c(21,21)), l1 * 2 + 21))\n+ gc2 = st_geometrycollection(list(mpo2, l2 - 2, l3 - 2, st_point(c(-1,-1))))\n+ gc = st_sf(a=2:3, b = st_sfc(gc1,gc2))\n+ plot(gc, cex = gc$a, col = gc$a, border = rev(gc$a) + 2, lwd = 2)\n+ \n+ plot(gc1)\n+ \n+ plot(st_sfc(mp1, mpo1))\n+ \n+ # color ramp\n+ nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\n+ plot(nc)\n+ plot(nc, axes = TRUE)\n+ plot(nc, col=\"lightgrey\") \n+ plot(st_centroid(nc), add = TRUE, col = 1)\n+ if (\"geometry\" %in% names(nc)) {\n+  nc |> \n+   select(geometry) |> \n+   plot()\n+ }\n+ \n+ nc$f = cut(nc[[1]], 5)\n+ plot(nc[\"f\"], key.pos = 1)\n+ plot(nc[1],   key.pos = 1)\n+ \n+ # test background map plotting:\n+ load(\"bgmap.rda\")\n+ merc = st_crs(3857)\n+ WGS84 = st_crs(4326)\n+ nc = st_transform(nc, WGS84)\n+ ## ggmap:\n+ #library(ggmap)\n+ #bgMap = get_map(unname(st_bbox(nc)), source = \"google\", zoom = 8) \n+ plot(st_transform(nc[1], merc), bgMap = bgMap)\n+ \n+ # RgoogleMaps:\n+ #library(RgoogleMaps)\n+ #center = c(mean(st_bbox(nc)[c(2,4)]), mean(st_bbox(nc)[c(1,3)]))\n+ #g = GetMap(center=center, zoom=6) # google\n+ par(mar = c(0,0,1,0))\n+ plot(st_transform(nc, merc), bgMap = g)\n+ \n+ m = st_make_grid()\n+ st_crs(m) = NA_crs_\n+ m = st_segmentize(m, 2)\n+ st_crs(m) = 4326\n+ plot(m, axes = TRUE)\n+ g = st_transform(m, st_crs(\"+proj=ortho +lat_0=30 +lon_0=45\"), check = TRUE)\n+ plot(g, axes = TRUE)\n+ \n+ nc[[1]] = NA\n+ nc[[10]] = 1\n+ plot(nc, pal = rainbow, nbreaks = 3)\n+ plot(nc, pal = rainbow, breaks = \"jenks\", nbreaks = 3)\n+ plot(nc, pal = rainbow, breaks = (0:10)/3)\n+ \n+ # logz:\n+ nc$e = 10^(nc$SID74)\n+ plot(nc[\"e\"], logz = TRUE)\n+ \n+ # shared key:\n+ plot(nc[c(\"SID74\", \"SID79\")], key.pos = -1)\n+ plot(nc[c(\"BIR74\", \"BIR79\")], key.pos = 1, logz=TRUE)\n+ }\n\nAttaching package: 'dplyr'\n\nThe following objects are masked from 'package:stats':\n\n    filter, lag\n\nThe following objects are masked from 'package:base':\n\n    intersect, setdiff, setequal, union\n\nThere were 13 warnings (use warnings() to see them)\n> \n> proc.time()\n   user  system elapsed \n  3.065   1.396   3.020 \n"
  },
  {
    "path": "tests/read.R",
    "content": "Sys.setenv(TZ=\"UTC\")\nsuppressPackageStartupMessages(library(sf))\nif (\"GPKG\" %in% st_drivers()$name) {\n\ttst = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), \"nc.gpkg\", crs = 4267, quiet = TRUE)\n\ttst = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), quiet = TRUE) # default layer name\n}\n\ntst = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE) # no layer specified\n\n# data from https://github.com/edzer/sfr/issues/6\ntst = st_read(system.file(\"shape/storms_xyz.shp\", package=\"sf\"), quiet = TRUE)\nclass(st_geometry(tst))\nclass(st_geometry(tst)[[1]])\ntst = st_read(system.file(\"shape/storms_xyzm.shp\", package=\"sf\"), quiet = TRUE)\nclass(st_geometry(tst))\nclass(st_geometry(tst)[[1]])\ntst = st_read(system.file(\"shape/storms_xyz_feature.shp\", package=\"sf\"), quiet = TRUE)\nclass(st_geometry(tst))\nclass(st_geometry(tst)[[1]])\ntst = st_read(system.file(\"shape/storms_xyzm_feature.shp\", package=\"sf\"), quiet = TRUE)\nclass(st_geometry(tst))\nclass(st_geometry(tst)[[1]])\n\nif (\"GPKG\" %in% st_drivers()$name) { # read Int64\n    print(st_read(system.file(\"gpkg/tl.gpkg\", package=\"sf\"), quiet = TRUE)$AWATER)\n    print(st_read(system.file(\"gpkg/tl.gpkg\", package=\"sf\"), quiet = TRUE, int64_as_string = TRUE)$AWATER)\n}\n\n# see https://github.com/edzer/sfr/issues/45 :\nif (\"OSM\" %in% st_drivers()$name && Sys.info()['sysname'] != \"Darwin\") {\n\tosm = system.file(\"osm/overpass.osm\", package=\"sf\")\n\tosm_l = st_layers(osm)\n\tosm_lc = suppressWarnings(st_layers(osm, do_count = TRUE))\n\tosm_r = suppressWarnings(st_read(osm, \"multipolygons\", quiet = TRUE))\n}\n\n# layer opening option:\nst_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE,\n\toptions = c(\"ADJUST_TYPE=YES\", \"ENCODING=CPL_ENC_UTF8\"))\n\nx <- st_sf(a = 1:2, geom = st_sfc(st_point(0:1), st_multipoint(matrix(1:4,2,2))))\n\ntry(st_layers(\"foo\")) # cannot open datasource\ntry(st_read(\"foo\")) # cannot open datasource\ntry(st_read(\"x.gpkg\", \"xyz\")) # cannot open layer\ntry(st_write(c(\"foo\", \"bar\")))\ntry(st_write(x, c(\"foo\", \"bar\")))\ntry(st_write(x, \"foo\", driver = \"foo\"))\nif (Sys.getenv(\"USER\") == \"travis\") {\n\ttry(st_write(x, \"/x\", driver = \"ESRI Shapefile\"))\n\tst_write(x, \"xxx.gpkg\")\n\tst_write(x, \"xxx.gpkg\", append = TRUE, quiet = FALSE) # appends to layer\n\ty <- st_sf(b = 1:2, geom = st_sfc(st_point(0:1), st_multipoint(matrix(1:4,2,2))))\n\ttry(st_write(y, \"xxx.gpkg\"))\n}\n\ngeom = st_sfc(st_point(0:1), st_multipoint(matrix(1:4,2,2)))\nst_write(geom, \"geom.gpkg\")\nst_write(geom, \"geom1.gpkg\", layer = \"foo\")\n\ndf <- data.frame(\n    a = c(0, 1, NA, -Inf, Inf),\n    b = c(\"a\", \"b\", NA, \"c\", \"\"),\n    c = c(as.Date(\"2001-01-01\"),\n          as.Date(c(NA, -99, 0, 1), origin = \"1970-01-01\")),\n    d = c(as.POSIXct(\"2001-01-01\"),\n          as.POSIXct(c(NA, -99, 0, 1), origin = \"1970-01-01\")),\n    x = 1:5,\n    y = 1:5)\n\nx  = st_as_sf(df, coords = c(\"x\", \"y\"))\n\nif (\"GPKG\" %in% st_drivers()$name) {\n st_write(x, \"x2.gpkg\", quiet = TRUE)\n y = st_read(\"x2.gpkg\", quiet = TRUE)\n print(y)\n}\n\nif (\"SQLite\" %in% st_drivers()$name && require(RSQLite)) {\n\tdb = system.file(\"sqlite/meuse.sqlite\", package = \"sf\")\n\tdbcon <- dbConnect(dbDriver(\"SQLite\"), db)\n\tm = dbReadTable(dbcon, \"meuse.sqlite\")\n\tm$GEOMETRY = st_as_sfc(m$GEOMETRY, spatialite = FALSE) # ISO wkb\n\tprint(st_sf(m), n = 3)\n\t# or:\n\t(s = st_read(dbcon, \"meuse.sqlite\"))[1:3,]\n\tdbDisconnect(dbcon)\n\n\tdb = system.file(\"sqlite/nc.sqlite\", package = \"sf\")\n\tdbcon <- dbConnect(dbDriver(\"SQLite\"), db)\n\tm = dbReadTable(dbcon, \"nc.sqlite\")\n\tm$GEOMETRY = st_as_sfc(m$GEOMETRY, spatialite = FALSE) # ISO wkb\n\tprint(st_sf(m), n = 3)\n\tdbDisconnect(dbcon)\n\n\tdb = system.file(\"sqlite/b.sqlite\", package = \"sf\") # has an INT8 field\n\tb = st_read(db, quiet = TRUE)\n\tprint(b)\n\tb = st_read(db, int64_as_string = TRUE, quiet = TRUE)\n\tprint(b)\n\n\tif (.Platform$endian == \"little\") {\n\t  db = system.file(\"sqlite/test3.sqlite\", package = \"sf\")\n\t  dbcon <- dbConnect(dbDriver(\"SQLite\"), db)\n\t  m = dbReadTable(dbcon, \"HighWays\")\n\t  m$Geometry = st_as_sfc(m$Geometry, spatialite = TRUE) # spatialite wkb\n\t  print(st_sf(m), n = 1)\n\t  m = dbReadTable(dbcon, \"Towns\")\n\t  m$Geometry = st_as_sfc(m$Geometry, spatialite = TRUE) # spatialite wkb\n\t  print(st_sf(m), n = 1)\n\t  m = dbReadTable(dbcon, \"Regions\")\n\t  m$Geometry = st_as_sfc(m$Geometry, spatialite = TRUE) # spatialite wkb\n\t  print(st_sf(m), n = 1)\n\t}\n}\n\ncsv = system.file(\"csv/pt.csv\", package = \"sf\")\nidentical(st_read(quiet = TRUE, csv, options = \"AUTODETECT_TYPE=Yes\")$Int64[3], NA_real_)\nidentical(st_read(quiet = TRUE, csv, int64_as_string = TRUE, stringsAsFactors = FALSE,\n\toptions = \"AUTODETECT_TYPE=Yes\")$Int64[3], NA_character_)\nidentical(st_read(quiet = TRUE, csv, options = \"AUTODETECT_TYPE=Yes\")$Int32[3], NA_integer_)\n\nif (\"GML\" %in% st_drivers()$name) {\n  gml = system.file(\"gml/fmi_test.gml\", package = \"sf\")\n  print(dim(st_read(gml, quiet = TRUE, use_stream = FALSE)))\n  gml = system.file(\"gml/20170930_OB_530964_UKSH.xml.gz\", package = \"sf\")\n  print(dim(st_read(gml, layer = \"Parcely\", quiet = TRUE, use_stream = FALSE)))\n  print(dim(st_read(gml, layer = \"Parcely\", int64_as_string=TRUE, quiet = TRUE, use_stream = FALSE)))\n}\n\n# logical:\nif (\"GPKG\" %in% st_drivers()$name) {\n\ttst = read_sf(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), quiet = TRUE) # default layer name\n\ttst$bool = tst$NWBIR79 > 800 # logical\n\ttst$bool[1:3] = NA\n\twrite_sf(tst, \"tst__.gpkg\")\n\ttst2 = read_sf(\"tst__.gpkg\")\n\tstopifnot(identical(tst$bool, tst2$bool))\n}\n\n# spatial filter:\nnc = read_sf(system.file(\"gpkg/nc.gpkg\", package=\"sf\"))\nwkt = st_as_text(st_geometry(nc[1,]))\nwkt\nnc_filtered = read_sf(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), wkt_filter = wkt)\ntry(read_sf(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), wkt_filter = \"wrong\"))\nnc_filtered$NAME\n"
  },
  {
    "path": "tests/read.Rout.save",
    "content": "\nR Under development (unstable) (2025-11-05 r88988 ucrt) -- \"Unsuffered Consequences\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-w64-mingw32/x64\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> Sys.setenv(TZ=\"UTC\")\n> suppressPackageStartupMessages(library(sf))\n> if (\"GPKG\" %in% st_drivers()$name) {\n+ \ttst = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), \"nc.gpkg\", crs = 4267, quiet = TRUE)\n+ \ttst = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), quiet = TRUE) # default layer name\n+ }\n> \n> tst = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE) # no layer specified\n> \n> # data from https://github.com/edzer/sfr/issues/6\n> tst = st_read(system.file(\"shape/storms_xyz.shp\", package=\"sf\"), quiet = TRUE)\n> class(st_geometry(tst))\n[1] \"sfc_LINESTRING\" \"sfc\"           \n> class(st_geometry(tst)[[1]])\n[1] \"XYZ\"        \"LINESTRING\" \"sfg\"       \n> tst = st_read(system.file(\"shape/storms_xyzm.shp\", package=\"sf\"), quiet = TRUE)\n> class(st_geometry(tst))\n[1] \"sfc_LINESTRING\" \"sfc\"           \n> class(st_geometry(tst)[[1]])\n[1] \"XYM\"        \"LINESTRING\" \"sfg\"       \n> tst = st_read(system.file(\"shape/storms_xyz_feature.shp\", package=\"sf\"), quiet = TRUE)\n> class(st_geometry(tst))\n[1] \"sfc_LINESTRING\" \"sfc\"           \n> class(st_geometry(tst)[[1]])\n[1] \"XYZ\"        \"LINESTRING\" \"sfg\"       \n> tst = st_read(system.file(\"shape/storms_xyzm_feature.shp\", package=\"sf\"), quiet = TRUE)\n> class(st_geometry(tst))\n[1] \"sfc_LINESTRING\" \"sfc\"           \n> class(st_geometry(tst)[[1]])\n[1] \"XYM\"        \"LINESTRING\" \"sfg\"       \n> \n> if (\"GPKG\" %in% st_drivers()$name) { # read Int64\n+     print(st_read(system.file(\"gpkg/tl.gpkg\", package=\"sf\"), quiet = TRUE)$AWATER)\n+     print(st_read(system.file(\"gpkg/tl.gpkg\", package=\"sf\"), quiet = TRUE, int64_as_string = TRUE)$AWATER)\n+ }\n[1] 1028678842\n[1] \"1028678842\"\n> \n> # see https://github.com/edzer/sfr/issues/45 :\n> if (\"OSM\" %in% st_drivers()$name && Sys.info()['sysname'] != \"Darwin\") {\n+ \tosm = system.file(\"osm/overpass.osm\", package=\"sf\")\n+ \tosm_l = st_layers(osm)\n+ \tosm_lc = suppressWarnings(st_layers(osm, do_count = TRUE))\n+ \tosm_r = suppressWarnings(st_read(osm, \"multipolygons\", quiet = TRUE))\n+ }\n> \n> # layer opening option:\n> st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE,\n+ \toptions = c(\"ADJUST_TYPE=YES\", \"ENCODING=CPL_ENC_UTF8\"))\nSimple feature collection with 100 features and 14 fields\nGeometry type: MULTIPOLYGON\nDimension:     XY\nBounding box:  xmin: -84.32385 ymin: 33.88199 xmax: -75.45698 ymax: 36.58965\nGeodetic CRS:  NAD27\nFirst 10 features:\n    AREA PERIMETER CNTY_ CNTY_ID        NAME  FIPS FIPSNO CRESS_ID BIR74 SID74\n1  0.114     1.442  1825    1825        Ashe 37009  37009        5  1091     1\n2  0.061     1.231  1827    1827   Alleghany 37005  37005        3   487     0\n3  0.143     1.630  1828    1828       Surry 37171  37171       86  3188     5\n4  0.070     2.968  1831    1831   Currituck 37053  37053       27   508     1\n5  0.153     2.206  1832    1832 Northampton 37131  37131       66  1421     9\n6  0.097     1.670  1833    1833    Hertford 37091  37091       46  1452     7\n7  0.062     1.547  1834    1834      Camden 37029  37029       15   286     0\n8  0.091     1.284  1835    1835       Gates 37073  37073       37   420     0\n9  0.118     1.421  1836    1836      Warren 37185  37185       93   968     4\n10 0.124     1.428  1837    1837      Stokes 37169  37169       85  1612     1\n   NWBIR74 BIR79 SID79 NWBIR79                       geometry\n1       10  1364     0      19 MULTIPOLYGON (((-81.47276 3...\n2       10   542     3      12 MULTIPOLYGON (((-81.23989 3...\n3      208  3616     6     260 MULTIPOLYGON (((-80.45634 3...\n4      123   830     2     145 MULTIPOLYGON (((-76.00897 3...\n5     1066  1606     3    1197 MULTIPOLYGON (((-77.21767 3...\n6      954  1838     5    1237 MULTIPOLYGON (((-76.74506 3...\n7      115   350     2     139 MULTIPOLYGON (((-76.00897 3...\n8      254   594     2     371 MULTIPOLYGON (((-76.56251 3...\n9      748  1190     2     844 MULTIPOLYGON (((-78.30876 3...\n10     160  2038     5     176 MULTIPOLYGON (((-80.02567 3...\n> \n> x <- st_sf(a = 1:2, geom = st_sfc(st_point(0:1), st_multipoint(matrix(1:4,2,2))))\n> \n> try(st_layers(\"foo\")) # cannot open datasource\nCannot open data source foo\nError : Open failed.\n\n> try(st_read(\"foo\")) # cannot open datasource\nError : Cannot open \"foo\"; The file doesn't seem to exist.\n> try(st_read(\"x.gpkg\", \"xyz\")) # cannot open layer\nError : Cannot open \"x.gpkg\"; The file doesn't seem to exist.\n> try(st_write(c(\"foo\", \"bar\")))\nError in UseMethod(\"st_write\") : \n  no applicable method for 'st_write' applied to an object of class \"character\"\n> try(st_write(x, c(\"foo\", \"bar\")))\nwriting: substituting ENGCRS[\"Undefined Cartesian SRS with unknown unit\"] for missing CRS\nError in guess_driver(dns) : length(dsn) == 1 is not TRUE\n> try(st_write(x, \"foo\", driver = \"foo\"))\nwriting: substituting ENGCRS[\"Undefined Cartesian SRS with unknown unit\"] for missing CRS\ndriver `foo' not available.\nError : Driver not available.\n\n> if (Sys.getenv(\"USER\") == \"travis\") {\n+ \ttry(st_write(x, \"/x\", driver = \"ESRI Shapefile\"))\n+ \tst_write(x, \"xxx.gpkg\")\n+ \tst_write(x, \"xxx.gpkg\", append = TRUE, quiet = FALSE) # appends to layer\n+ \ty <- st_sf(b = 1:2, geom = st_sfc(st_point(0:1), st_multipoint(matrix(1:4,2,2))))\n+ \ttry(st_write(y, \"xxx.gpkg\"))\n+ }\n> \n> geom = st_sfc(st_point(0:1), st_multipoint(matrix(1:4,2,2)))\n> st_write(geom, \"geom.gpkg\")\nwriting: substituting ENGCRS[\"Undefined Cartesian SRS with unknown unit\"] for missing CRS\nWriting layer `geom' to data source `geom.gpkg' using driver `GPKG'\nWriting 2 features with 0 fields and geometry type Unknown (any).\n> st_write(geom, \"geom1.gpkg\", layer = \"foo\")\nwriting: substituting ENGCRS[\"Undefined Cartesian SRS with unknown unit\"] for missing CRS\nWriting layer `foo' to data source `geom1.gpkg' using driver `GPKG'\nWriting 2 features with 0 fields and geometry type Unknown (any).\n> \n> df <- data.frame(\n+     a = c(0, 1, NA, -Inf, Inf),\n+     b = c(\"a\", \"b\", NA, \"c\", \"\"),\n+     c = c(as.Date(\"2001-01-01\"),\n+           as.Date(c(NA, -99, 0, 1), origin = \"1970-01-01\")),\n+     d = c(as.POSIXct(\"2001-01-01\"),\n+           as.POSIXct(c(NA, -99, 0, 1), origin = \"1970-01-01\")),\n+     x = 1:5,\n+     y = 1:5)\n> \n> x  = st_as_sf(df, coords = c(\"x\", \"y\"))\n> \n> if (\"GPKG\" %in% st_drivers()$name) {\n+  st_write(x, \"x2.gpkg\", quiet = TRUE)\n+  y = st_read(\"x2.gpkg\", quiet = TRUE)\n+  print(y)\n+ }\nwriting: substituting ENGCRS[\"Undefined Cartesian SRS with unknown unit\"] for missing CRS\nSimple feature collection with 5 features and 4 fields\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 1 ymin: 1 xmax: 5 ymax: 5\nProjected CRS: Undefined Cartesian SRS with unknown unit\n     a    b          c                   d        geom\n1    0    a 2001-01-01 2001-01-01 00:00:00 POINT (1 1)\n2    1    b       <NA>                <NA> POINT (2 2)\n3   NA <NA> 1969-09-24 1969-12-31 23:58:21 POINT (3 3)\n4 -Inf    c 1970-01-01 1970-01-01 00:00:00 POINT (4 4)\n5  Inf      1970-01-02 1970-01-01 00:00:01 POINT (5 5)\n> \n> if (\"SQLite\" %in% st_drivers()$name && require(RSQLite)) {\n+ \tdb = system.file(\"sqlite/meuse.sqlite\", package = \"sf\")\n+ \tdbcon <- dbConnect(dbDriver(\"SQLite\"), db)\n+ \tm = dbReadTable(dbcon, \"meuse.sqlite\")\n+ \tm$GEOMETRY = st_as_sfc(m$GEOMETRY, spatialite = FALSE) # ISO wkb\n+ \tprint(st_sf(m), n = 3)\n+ \t# or:\n+ \t(s = st_read(dbcon, \"meuse.sqlite\"))[1:3,]\n+ \tdbDisconnect(dbcon)\n+ \n+ \tdb = system.file(\"sqlite/nc.sqlite\", package = \"sf\")\n+ \tdbcon <- dbConnect(dbDriver(\"SQLite\"), db)\n+ \tm = dbReadTable(dbcon, \"nc.sqlite\")\n+ \tm$GEOMETRY = st_as_sfc(m$GEOMETRY, spatialite = FALSE) # ISO wkb\n+ \tprint(st_sf(m), n = 3)\n+ \tdbDisconnect(dbcon)\n+ \n+ \tdb = system.file(\"sqlite/b.sqlite\", package = \"sf\") # has an INT8 field\n+ \tb = st_read(db, quiet = TRUE)\n+ \tprint(b)\n+ \tb = st_read(db, int64_as_string = TRUE, quiet = TRUE)\n+ \tprint(b)\n+ \n+ \tif (.Platform$endian == \"little\") {\n+ \t  db = system.file(\"sqlite/test3.sqlite\", package = \"sf\")\n+ \t  dbcon <- dbConnect(dbDriver(\"SQLite\"), db)\n+ \t  m = dbReadTable(dbcon, \"HighWays\")\n+ \t  m$Geometry = st_as_sfc(m$Geometry, spatialite = TRUE) # spatialite wkb\n+ \t  print(st_sf(m), n = 1)\n+ \t  m = dbReadTable(dbcon, \"Towns\")\n+ \t  m$Geometry = st_as_sfc(m$Geometry, spatialite = TRUE) # spatialite wkb\n+ \t  print(st_sf(m), n = 1)\n+ \t  m = dbReadTable(dbcon, \"Regions\")\n+ \t  m$Geometry = st_as_sfc(m$Geometry, spatialite = TRUE) # spatialite wkb\n+ \t  print(st_sf(m), n = 1)\n+ \t}\n+ }\nLoading required package: RSQLite\nSimple feature collection with 155 features and 13 fields\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 178605 ymin: 329714 xmax: 181390 ymax: 333611\nCRS:           NA\nFirst 3 features:\n  ogc_fid cadmium copper lead zinc  elev       dist   om ffreq soil lime\n1       1    11.7     85  299 1022 7.909 0.00135803 13.6     1    1    1\n2       2     8.6     81  277 1141 6.983 0.01222430 14.0     1    1    1\n3       3     6.5     68  199  640 7.800 0.10302900 13.0     1    1    1\n  landuse dist.m              GEOMETRY\n1      Ah     50 POINT (181072 333611)\n2      Ah     30 POINT (181025 333558)\n3      Ah    150 POINT (181165 333537)\nSimple feature collection with 100 features and 15 fields\nGeometry type: MULTIPOLYGON\nDimension:     XY\nBounding box:  xmin: -84.32385 ymin: 33.88199 xmax: -75.45698 ymax: 36.58965\nCRS:           NA\nFirst 3 features:\n  ogc_fid  area perimeter cnty_ cnty_id      name  fips fipsno cress_id bir74\n1       1 0.114     1.442  1825    1825      Ashe 37009  37009        5  1091\n2       2 0.061     1.231  1827    1827 Alleghany 37005  37005        3   487\n3       3 0.143     1.630  1828    1828     Surry 37171  37171       86  3188\n  sid74 nwbir74 bir79 sid79 nwbir79                       GEOMETRY\n1     1      10  1364     0      19 MULTIPOLYGON (((-81.47276 3...\n2     0      10   542     3      12 MULTIPOLYGON (((-81.23989 3...\n3     5     208  3616     6     260 MULTIPOLYGON (((-80.45634 3...\nInteger64 values larger than 9.0072e+15 lost significance after conversion to double;\nuse argument int64_as_string = TRUE to import them lossless, as character\nSimple feature collection with 1 feature and 2 fields\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1\nCRS:           NA\n  a       bigint    GEOMETRY\n1 1 4.611686e+18 POINT (0 1)\nSimple feature collection with 1 feature and 2 fields\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1\nCRS:           NA\n  a              bigint    GEOMETRY\n1 1 4611686018427387904 POINT (0 1)\nSimple feature collection with 10 features and 2 fields\nGeometry type: LINESTRING\nDimension:     XY\nBounding box:  xmin: 645003 ymin: 4822568 xmax: 748805.6 ymax: 4992001\nProjected CRS: WGS 84 / UTM zone 32N\nFirst 1 features:\n  PK_UID    Name                       Geometry\n1      1 Unknown LINESTRING (668540.7 485826...\nSimple feature collection with 8101 features and 6 fields\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 319224 ymin: 3934674 xmax: 1308585 ymax: 5214373\nProjected CRS: WGS 84 / UTM zone 32N\nFirst 1 features:\n  PK_UID    Name Peoples LocalCounc County Region                 Geometry\n1      1 Brozolo     435          1      0      0 POINT (427002.8 4996361)\nSimple feature collection with 10 features and 2 fields\nGeometry type: MULTIPOLYGON\nDimension:     XY\nBounding box:  xmin: 378359.8 ymin: 4198234 xmax: 1211486 ymax: 5036803\nProjected CRS: WGS 84 / UTM zone 32N\nFirst 1 features:\n  PK_UID   Name                       Geometry\n1      1 VENETO MULTIPOLYGON (((752912.3 50...\n> \n> csv = system.file(\"csv/pt.csv\", package = \"sf\")\n> identical(st_read(quiet = TRUE, csv, options = \"AUTODETECT_TYPE=Yes\")$Int64[3], NA_real_)\n[1] TRUE\n> identical(st_read(quiet = TRUE, csv, int64_as_string = TRUE, stringsAsFactors = FALSE,\n+ \toptions = \"AUTODETECT_TYPE=Yes\")$Int64[3], NA_character_)\n[1] TRUE\n> identical(st_read(quiet = TRUE, csv, options = \"AUTODETECT_TYPE=Yes\")$Int32[3], NA_integer_)\n[1] TRUE\n> \n> if (\"GML\" %in% st_drivers()$name) {\n+   gml = system.file(\"gml/fmi_test.gml\", package = \"sf\")\n+   print(dim(st_read(gml, quiet = TRUE, use_stream = FALSE)))\n+   gml = system.file(\"gml/20170930_OB_530964_UKSH.xml.gz\", package = \"sf\")\n+   print(dim(st_read(gml, layer = \"Parcely\", quiet = TRUE, use_stream = FALSE)))\n+   print(dim(st_read(gml, layer = \"Parcely\", int64_as_string=TRUE, quiet = TRUE, use_stream = FALSE)))\n+ }\n[1] 22 11\n[1] 644  25\n[1] 644  25\nWarning messages:\n1: In CPL_read_ogr(dsn, layer, query, as.character(options), quiet,  :\n  GDAL Message 1: Field with same name (identifier) already exists in (PointTimeSeriesObservation). Skipping newer ones\n2: In CPL_read_ogr(dsn, layer, query, as.character(options), quiet,  :\n  GDAL Message 1: Field with same name (name) already exists in (PointTimeSeriesObservation). Skipping newer ones\n> \n> # logical:\n> if (\"GPKG\" %in% st_drivers()$name) {\n+ \ttst = read_sf(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), quiet = TRUE) # default layer name\n+ \ttst$bool = tst$NWBIR79 > 800 # logical\n+ \ttst$bool[1:3] = NA\n+ \twrite_sf(tst, \"tst__.gpkg\")\n+ \ttst2 = read_sf(\"tst__.gpkg\")\n+ \tstopifnot(identical(tst$bool, tst2$bool))\n+ }\n> \n> # spatial filter:\n> nc = read_sf(system.file(\"gpkg/nc.gpkg\", package=\"sf\"))\n> wkt = st_as_text(st_geometry(nc[1,]))\n> wkt\n[1] \"MULTIPOLYGON (((-81.47276 36.23436, -81.54084 36.27251, -81.56198 36.27359, -81.63306 36.34069, -81.74107 36.39178, -81.69828 36.47178, -81.7028 36.51934, -81.67 36.58965, -81.3453 36.57286, -81.34754 36.53791, -81.32478 36.51368, -81.31332 36.4807, -81.26624 36.43721, -81.26284 36.40504, -81.24069 36.37942, -81.23989 36.36536, -81.26424 36.35241, -81.32899 36.3635, -81.36137 36.35316, -81.36569 36.33905, -81.35413 36.29972, -81.36745 36.2787, -81.40639 36.28505, -81.41233 36.26729, -81.43104 36.26072, -81.45289 36.23959, -81.47276 36.23436)))\"\n> nc_filtered = read_sf(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), wkt_filter = wkt)\n> try(read_sf(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), wkt_filter = \"wrong\"))\nCannot create geometry from: wrong\nError : wkt parse error.\n\n> nc_filtered$NAME\n[1] \"Watauga\"   \"Ashe\"      \"Wilkes\"    \"Alleghany\"\n> \n> proc.time()\n   user  system elapsed \n   1.46    0.46    1.92 \n"
  },
  {
    "path": "tests/roundtrip.R",
    "content": "#library(rgdal2)\n#openOGRLayer(\"PG:dbname=postgis\" , \"meuse2\")\n\nsuppressPackageStartupMessages(library(sf))\noptions(rgdal_show_exportToProj4_warnings = \"none\")\nouter = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\nhole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\nhole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\npol1 = list(outer, hole1, hole2)\npol2 = list(outer + 12, hole1 + 12)\npol3 = list(outer + 24)\nmp = list(pol1,pol2,pol3)\nmp1 = st_multipolygon(mp)\nsf = st_sf(a=1, st_sfc(mp1))\nif (suppressPackageStartupMessages(require(sp, quietly = TRUE))) {\n a = as(sf, \"Spatial\")\n print(class(a))\n b = st_as_sf(a)\n a2 = as(a, \"SpatialPolygonsDataFrame\")\n print(all.equal(a, a2)) # round-trip\n\n b1 = as(a, \"sf\")\n print(all.equal(b, b1))\n b = st_as_sfc(a)\n b1 = as(a, \"sfc\")\n print(all.equal(b, b1))\n}\n\n# SpatialMultiPoints\nif (require(sp, quietly = TRUE)) {\nsuppressWarnings(RNGversion(\"3.5.3\"))\nset.seed(1331)\n# example(SpatialMultiPoints, ask = FALSE, echo = FALSE) # loads mpdf\ncl1 = cbind(rnorm(3, 10), rnorm(3, 10))\ncl2 = cbind(rnorm(5, 10), rnorm(5,  0))\ncl3 = cbind(rnorm(7,  0), rnorm(7, 10))\nmpdf = SpatialMultiPointsDataFrame(list(a=cl1, b=cl2, c=cl3), data.frame(a = 1:3, row.names=c(\"a\", \"b\", \"c\")))\nm = st_as_sf(mpdf)\nall.equal(as(m, \"Spatial\"), mpdf) # TRUE\n\ndemo(meuse, ask = FALSE, echo = FALSE)\n#meuse = spTransform(meuse, CRS(\"+proj=longlat +ellps=WGS84 +no_defs\"))\npol.grd = as(meuse.grid, \"SpatialPolygonsDataFrame\")\n#meuse.grd = spTransform(meuse.grid, CRS(\"+proj=longlat +ellps=WGS84 +no_defs\"))\n#pol.grd = spTransform(pol.grd, CRS(\"+proj=longlat +ellps=WGS84 +no_defs\"))\n#meuse.area = spTransform(meuse.area, CRS(\"+proj=longlat +ellps=WGS84 +no_defs\"))\n#meuse.riv = spTransform(meuse.riv, CRS(\"+proj=longlat +ellps=WGS84 +no_defs\"))\n#summary(st_as_sf(meuse))\n#summary(st_as_sf(meuse.grd))\n#x <- st_as_sf(meuse.grid) # don't print: CRS variations.\n#summary(st_as_sf(meuse.area))\n#summary(st_as_sf(meuse.riv))\n#summary(st_as_sf(as(meuse.riv, \"SpatialLines\")))\n#summary(st_as_sf(pol.grd))\n#summary(st_as_sf(as(pol.grd, \"SpatialLinesDataFrame\")))\n\nnc = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), \"nc.gpkg\", quiet = TRUE)\nall.equal(nc, st_as_sf(as(nc, \"Spatial\")))\nst_crs(nc) == st_crs(st_as_sf(as(nc, \"Spatial\")))\n\ndetach(\"package:sp\")\n}\n"
  },
  {
    "path": "tests/roundtrip.Rout.save",
    "content": "\nR Under development (unstable) (2025-11-05 r88988 ucrt) -- \"Unsuffered Consequences\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-w64-mingw32/x64\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> #library(rgdal2)\n> #openOGRLayer(\"PG:dbname=postgis\" , \"meuse2\")\n> \n> suppressPackageStartupMessages(library(sf))\n> options(rgdal_show_exportToProj4_warnings = \"none\")\n> outer = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\n> hole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\n> hole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\n> pol1 = list(outer, hole1, hole2)\n> pol2 = list(outer + 12, hole1 + 12)\n> pol3 = list(outer + 24)\n> mp = list(pol1,pol2,pol3)\n> mp1 = st_multipolygon(mp)\n> sf = st_sf(a=1, st_sfc(mp1))\n> if (suppressPackageStartupMessages(require(sp, quietly = TRUE))) {\n+  a = as(sf, \"Spatial\")\n+  print(class(a))\n+  b = st_as_sf(a)\n+  a2 = as(a, \"SpatialPolygonsDataFrame\")\n+  print(all.equal(a, a2)) # round-trip\n+ \n+  b1 = as(a, \"sf\")\n+  print(all.equal(b, b1))\n+  b = st_as_sfc(a)\n+  b1 = as(a, \"sfc\")\n+  print(all.equal(b, b1))\n+ }\n[1] \"SpatialPolygonsDataFrame\"\nattr(,\"package\")\n[1] \"sp\"\n[1] TRUE\n[1] TRUE\n[1] TRUE\n> \n> # SpatialMultiPoints\n> if (require(sp, quietly = TRUE)) {\n+ suppressWarnings(RNGversion(\"3.5.3\"))\n+ set.seed(1331)\n+ # example(SpatialMultiPoints, ask = FALSE, echo = FALSE) # loads mpdf\n+ cl1 = cbind(rnorm(3, 10), rnorm(3, 10))\n+ cl2 = cbind(rnorm(5, 10), rnorm(5,  0))\n+ cl3 = cbind(rnorm(7,  0), rnorm(7, 10))\n+ mpdf = SpatialMultiPointsDataFrame(list(a=cl1, b=cl2, c=cl3), data.frame(a = 1:3, row.names=c(\"a\", \"b\", \"c\")))\n+ m = st_as_sf(mpdf)\n+ all.equal(as(m, \"Spatial\"), mpdf) # TRUE\n+ \n+ demo(meuse, ask = FALSE, echo = FALSE)\n+ #meuse = spTransform(meuse, CRS(\"+proj=longlat +ellps=WGS84 +no_defs\"))\n+ pol.grd = as(meuse.grid, \"SpatialPolygonsDataFrame\")\n+ #meuse.grd = spTransform(meuse.grid, CRS(\"+proj=longlat +ellps=WGS84 +no_defs\"))\n+ #pol.grd = spTransform(pol.grd, CRS(\"+proj=longlat +ellps=WGS84 +no_defs\"))\n+ #meuse.area = spTransform(meuse.area, CRS(\"+proj=longlat +ellps=WGS84 +no_defs\"))\n+ #meuse.riv = spTransform(meuse.riv, CRS(\"+proj=longlat +ellps=WGS84 +no_defs\"))\n+ #summary(st_as_sf(meuse))\n+ #summary(st_as_sf(meuse.grd))\n+ #x <- st_as_sf(meuse.grid) # don't print: CRS variations.\n+ #summary(st_as_sf(meuse.area))\n+ #summary(st_as_sf(meuse.riv))\n+ #summary(st_as_sf(as(meuse.riv, \"SpatialLines\")))\n+ #summary(st_as_sf(pol.grd))\n+ #summary(st_as_sf(as(pol.grd, \"SpatialLinesDataFrame\")))\n+ \n+ nc = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), \"nc.gpkg\", quiet = TRUE)\n+ all.equal(nc, st_as_sf(as(nc, \"Spatial\")))\n+ st_crs(nc) == st_crs(st_as_sf(as(nc, \"Spatial\")))\n+ \n+ detach(\"package:sp\")\n+ }\n> \n> proc.time()\n   user  system elapsed \n   1.10    0.12    1.21 \n"
  },
  {
    "path": "tests/s2.R",
    "content": "suppressPackageStartupMessages(library(sf))\nd = data.frame(z = 1:100, x = runif(100), y = runif(100))\nn0 = st_as_sf(d, coords = c(\"x\", \"y\"), crs = 4326)\nn1 = st_transform(n0, 3857)\n\n# st_nearest_points\ncp1 = st_nearest_points(n0[1:50,], n0[51:100,])\ncp2 = st_transform(st_nearest_points(n1[1:50,], n1[51:100,]), 4326)\nlength(cp1)\nall.equal(cp1, cp2)\n\n# st_nearest_points, pairwise\ncp1 = st_nearest_points(n0[1:50,], n0[51:100,], pairwise = TRUE)\ncp2 = st_transform(st_nearest_points(n1[1:50,], n1[51:100,], pairwise = TRUE), 4326)\nlength(cp1)\nall.equal(cp1, cp2)\n\nif (compareVersion(sf_extSoftVersion()[\"GEOS\"], \"3.6.1\") > -1) {\n# st_nearest_feature\n  nf1 = st_nearest_feature(n0[1:50,], n0[51:100,])\n  nf2 = st_nearest_feature(n1[1:50,], n1[51:100,])\n  print(all.equal(nf1, nf2))\n}\n\nset.seed(131)\nn = 1000\npts = st_as_sf(data.frame(x = runif(n), y = runif(n)), coords = c(\"x\", \"y\"), crs = 4326)\n# unit square in degrees: 111 x 111 km\n\nsize = 15000 \nw <- st_is_within_distance(pts[1,], pts, size)[[1]]\n\nbs = units::set_units(size / s2::s2_earth_radius_meters(), rad)\nb1 = st_buffer(pts[1,], bs)\nb2 = st_buffer(pts[1,], size)\nall.equal(b1, b2)\n\n#plot(pts)\n#plot(pts[1,], add = TRUE, pch = 16, cex = 2, col = 'blue')\n#plot(st_buffer(pts[1,], bs), add = TRUE)\n#plot(pts[w,], add = TRUE, col = 'red')\n"
  },
  {
    "path": "tests/s2.Rout.save",
    "content": "\nR Under development (unstable) (2025-11-05 r88988 ucrt) -- \"Unsuffered Consequences\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-w64-mingw32/x64\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> d = data.frame(z = 1:100, x = runif(100), y = runif(100))\n> n0 = st_as_sf(d, coords = c(\"x\", \"y\"), crs = 4326)\n> n1 = st_transform(n0, 3857)\n> \n> # st_nearest_points\n> cp1 = st_nearest_points(n0[1:50,], n0[51:100,])\n> cp2 = st_transform(st_nearest_points(n1[1:50,], n1[51:100,]), 4326)\n> length(cp1)\n[1] 2500\n> all.equal(cp1, cp2)\n[1] TRUE\n> \n> # st_nearest_points, pairwise\n> cp1 = st_nearest_points(n0[1:50,], n0[51:100,], pairwise = TRUE)\n> cp2 = st_transform(st_nearest_points(n1[1:50,], n1[51:100,], pairwise = TRUE), 4326)\n> length(cp1)\n[1] 50\n> all.equal(cp1, cp2)\n[1] TRUE\n> \n> if (compareVersion(sf_extSoftVersion()[\"GEOS\"], \"3.6.1\") > -1) {\n+ # st_nearest_feature\n+   nf1 = st_nearest_feature(n0[1:50,], n0[51:100,])\n+   nf2 = st_nearest_feature(n1[1:50,], n1[51:100,])\n+   print(all.equal(nf1, nf2))\n+ }\n[1] TRUE\n> \n> set.seed(131)\n> n = 1000\n> pts = st_as_sf(data.frame(x = runif(n), y = runif(n)), coords = c(\"x\", \"y\"), crs = 4326)\n> # unit square in degrees: 111 x 111 km\n> \n> size = 15000 \n> w <- st_is_within_distance(pts[1,], pts, size)[[1]]\n> \n> bs = units::set_units(size / s2::s2_earth_radius_meters(), rad)\n> b1 = st_buffer(pts[1,], bs)\n> b2 = st_buffer(pts[1,], size)\n> all.equal(b1, b2)\n[1] TRUE\n> \n> #plot(pts)\n> #plot(pts[1,], add = TRUE, pch = 16, cex = 2, col = 'blue')\n> #plot(st_buffer(pts[1,], bs), add = TRUE)\n> #plot(pts[w,], add = TRUE, col = 'red')\n> \n> proc.time()\n   user  system elapsed \n   1.07    0.18    1.25 \n"
  },
  {
    "path": "tests/sample.R",
    "content": "suppressPackageStartupMessages(library(sf))\nbb = st_bbox(c(xmin=0, ymin=1, xmax=3, ymax=2))\nxx <- st_make_grid(st_as_sfc(bb), square = FALSE, what = \"polygons\")\nplot(xx, border = 'green', main = \"pointy topped\")\nx <- st_make_grid(st_as_sfc(bb), square = FALSE, what = \"points\")\nplot(x, add = TRUE)\nx <- st_make_grid(st_as_sfc(bb), square = FALSE, what = \"corners\")\nplot(x, col = 'orange', add = TRUE)\nplot(st_as_sfc(bb), add = TRUE, border = 'red')\nst_overlaps(xx) |> \n\tlengths() |> \n\tsum()\n\nst_as_sfc(bb) |>\n\tst_difference(st_union(xx)) |>\n\tst_area()\n\nxx <- st_make_grid(st_as_sfc(bb), square = FALSE, what = \"polygons\", flat_topped = TRUE)\nplot(xx, border = 'green', main = \"flat topped\")\nx <- st_make_grid(st_as_sfc(bb), square = FALSE, what = \"points\", flat_topped = TRUE)\nplot(x, add = TRUE)\nx <- st_make_grid(st_as_sfc(bb), square = FALSE, what = \"corners\", flat_topped = TRUE)\nplot(x, col = 'orange', add = TRUE)\nplot(st_as_sfc(bb), add = TRUE, border = 'red')\nst_overlaps(xx) |> \n\tlengths() |> \n\tsum()\n\nst_as_sfc(bb) |>\n\tst_difference(st_union(xx)) |>\n\tst_area()\n"
  },
  {
    "path": "tests/sample.Rout.save",
    "content": "\nR version 4.5.2 (2025-10-31) -- \"[Not] Part in a Rumble\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-pc-linux-gnu\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> bb = st_bbox(c(xmin=0, ymin=1, xmax=3, ymax=2))\n> xx <- st_make_grid(st_as_sfc(bb), square = FALSE, what = \"polygons\")\n> plot(xx, border = 'green', main = \"pointy topped\")\n> x <- st_make_grid(st_as_sfc(bb), square = FALSE, what = \"points\")\n> plot(x, add = TRUE)\n> x <- st_make_grid(st_as_sfc(bb), square = FALSE, what = \"corners\")\n> plot(x, col = 'orange', add = TRUE)\n> plot(st_as_sfc(bb), add = TRUE, border = 'red')\n> st_overlaps(xx) |> \n+ \tlengths() |> \n+ \tsum()\n[1] 0\n> \n> st_as_sfc(bb) |>\n+ \tst_difference(st_union(xx)) |>\n+ \tst_area()\nnumeric(0)\n> \n> xx <- st_make_grid(st_as_sfc(bb), square = FALSE, what = \"polygons\", flat_topped = TRUE)\n> plot(xx, border = 'green', main = \"flat topped\")\n> x <- st_make_grid(st_as_sfc(bb), square = FALSE, what = \"points\", flat_topped = TRUE)\n> plot(x, add = TRUE)\n> x <- st_make_grid(st_as_sfc(bb), square = FALSE, what = \"corners\", flat_topped = TRUE)\n> plot(x, col = 'orange', add = TRUE)\n> plot(st_as_sfc(bb), add = TRUE, border = 'red')\n> st_overlaps(xx) |> \n+ \tlengths() |> \n+ \tsum()\n[1] 0\n> \n> st_as_sfc(bb) |>\n+ \tst_difference(st_union(xx)) |>\n+ \tst_area()\nnumeric(0)\n> \n> proc.time()\n   user  system elapsed \n  0.580   1.388   0.463 \n"
  },
  {
    "path": "tests/sfc.R",
    "content": "suppressPackageStartupMessages(library(sf))\n\np = st_point(c(1/3,1/6))\nst_sfc(p, precision = 1000)\nst_as_sfc(st_as_binary(st_sfc(p, precision = 0L)))\nst_as_sfc(st_as_binary(st_sfc(p, precision = 1000)))\nst_as_sfc(st_as_binary(st_sfc(p, precision = 1000000)))\nst_as_sfc(st_as_binary(st_sfc(p, precision = 10L)))\nst_as_sfc(st_as_binary(st_sfc(p, precision = -1)))\n\nd = data.frame(a = 1:2)\nd$geom = c(\"POINT(0 0)\", \"POINT(1 1)\")\n\nst_as_sf(d, wkt = \"geom\")\nst_as_sf(d, wkt = 2)\nst_as_sf(d, wkt = \"geom\", remove = FALSE)\n\nst_as_sfc(c(\"POINT(0 0)\", \"POINT(1 1)\"))\nst_as_sfc(c(\"POINT(0 0)\", \"POINT(1 1)\", \"POLYGON((0 0,1 1,0 1,0 0))\"))\nst_as_sfc(character(0))\nx = st_as_sfc(character(0), 4326)\ny = st_as_sfc(character(0), crs = 4326)\nall.equal(x, y)\nst_as_sfc(c(\"POINT(0 0)\", \"POINT(1 1)\", \"POLYGON((0 0,1 1,0 1,0 0))\"),\n\t\"+proj=longlat +datum=WGS84\")\ndg = st_as_sf(d, wkt = \"geom\")\nprint(dg, n = 1)\nhead(st_as_sf(d, wkt = \"geom\"), 1)\n\nd$geom = st_as_sfc(d$geom)\nd1 = d\nattr(d1, \"sf_col\") = \"geom\"\nst_geometry(d1) = d$geom\n\nd$geometry = d$geom # second geometry list-column\nif (require(testthat, quietly = TRUE)) {\n expect_warning(st_geometry(d) <- d$geom)\n}\nd\n\nx = st_sfc(list(st_point(0:1), st_point(0:1)), crs = 4326)\n# don't warn when replacing crs with identical value:\nst_sfc(x, crs = 4326)\ny = st_sfc(x, crs = \"+proj=longlat +datum=WGS84 +no_defs\")\n# but do when it changes:\ny = st_sfc(x, crs = 3857)\n\np = st_point(0:1)\nst_cast(p, \"MULTIPOINT\")\nmp = st_multipoint(rbind(c(0,1), c(2,2)))\nst_cast(mp, \"POINT\")\nst_cast(mp, \"MULTIPOINT\")\n\n# geometry collection to its elements:\nst_cast(st_geometrycollection(list(mp)), \"POINT\")\nst_cast(st_geometrycollection(list(mp)), \"MULTIPOINT\")\nst_cast(st_geometrycollection(list(p,mp)), \"MULTIPOINT\")\n\nmp = st_multipoint(rbind(c(0,1)))\nx = st_sfc(p, mp)\nst_cast(x, \"POINT\")\n\nsf = st_sf(a = 3:2, geom = x)\nst_cast(sf, \"POINT\")\n\n\nx |> st_cast(\"POINT\")\n\n# points:\nmp = st_multipoint(rbind(c(0,1))) # single-point multipoint\nst_sfc(p,mp) |> st_cast(\"POINT\")\nst_sfc(p,mp) |> st_cast(\"MULTIPOINT\")\n\n# lines:\npts = rbind(c(0,0), c(1,1), c(2,1))\nst_sfc(st_linestring(pts), st_multilinestring(list(pts))) |> st_cast(\"LINESTRING\")\nst_sfc(st_linestring(pts), st_multilinestring(list(pts))) |> st_cast(\"MULTILINESTRING\")\n\n# polygons:\npts = rbind(c(0,0), c(1,1), c(0,1), c(0,0))\nst_sfc(st_polygon(list(pts)), st_multipolygon(list(list(pts)))) |> st_cast(\"POLYGON\")\nst_sfc(st_polygon(list(pts)), st_multipolygon(list(list(pts)))) |> st_cast(\"MULTIPOLYGON\")\n\n\nst_sfc(st_geometrycollection(list(p)), st_geometrycollection(list(mp))) |> st_cast()\nst_sfc(st_geometrycollection(list(p)), st_geometrycollection(list(mp))) |>\n\tst_cast() |>\n\tst_cast(\"POINT\")\n\np = rbind(c(0,0),c(1,0),c(1,1),c(0,1),c(0,0))\npol = st_polygon(list(p))\n# plot(pol)\ntry(plot(st_polygonize(pol))) # --> breaks\nst_length(st_sfc(st_point(c(0,0))))\n\ntry(as(st_sfc(st_linestring(matrix(1:9,3))), \"Spatial\"))\n\n# check conus is present:\nx = st_sfc(st_point(c(-90,35)), st_point(c(-80,36)),\n\tcrs = \"+proj=longlat +datum=NAD27\")\ny = st_transform(x, 3857)\n\n## IGNORE_RDIFF_BEGIN\nsf_extSoftVersion()[1:3]\n## IGNORE_RDIFF_END\n\n# Ops.sfc:\nls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))))\nls * 2\nls - 2\n(ls + 2) %% 3\nls / ls\np_ = st_point(0:1)\nll = st_sfc(ls[[1]], p_)\nll & st_sfc(p_)\nll | st_sfc(p_)\nll %/% st_sfc(p_)\nll == st_sfc(p_)\nll != st_sfc(p_)\n\n\nstr(x)\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\nstr(nc)\nbb = st_as_sfc(st_bbox(nc))\nformat(st_bbox(nc))\n\nst_agr(\"constant\")\nst_agr()\nx <- st_sf(a = 1:2, b = 3:4, geom = x, agr = c(\"constant\", \"aggregate\"))\ny <- x |> st_set_agr(\"constant\")\ny\n\nsf1 <- st_sf(a = c(\"x\", \"y\"), geom = st_sfc(st_point(3:4), st_point(3:4)))\nsf1[names(sf1)]\n\nst_bbox(sf1)\nbb = st_bbox(nc)\nbb\nst_crs(bb)\nst_bbox(c(xmin = 16.1, xmax = 16.6, ymin = 48.6, ymax = 47.9), crs = st_crs(4326))\nst_bbox(c(xmin = 16.1, xmax = 16.6, ymin = 48.6, ymax = 47.9), crs = 4326)\n\nbb$xrange\nbb$yrange\nbb$xmin\nbb$ymin\nbb$xmax\nbb$ymax\ntry(bb$foo)\n\n# merge:\na = data.frame(a = 1:3, b = 5:7)\nst_geometry(a) = st_sfc(st_point(c(0,0)), st_point(c(1,1)), st_point(c(2,2)))\nb = data.frame(x = c(\"a\", \"b\", \"c\"), b = c(2,5,6))\nmerge(a, b)\nmerge(a, b, all = TRUE)\n\nif (require(dplyr, quietly = TRUE)) {\n# joins:\ninner_join(a, b)\nleft_join(a, b)\nright_join(a, b)\nfull_join(a, b)\nsemi_join(a, b)\nanti_join(a, b)\nleft_join(a, data.frame(b, geometry = 1), by = \"b\")\n}\n\n# st_joins:\na = st_sf(a = 1:3,\n geom = st_sfc(st_point(c(1,1)), st_point(c(2,2)), st_point(c(3,3))))\nb = st_sf(a = 11:14,\n geom = st_sfc(st_point(c(10,10)), st_point(c(2,2)), st_point(c(2,2)), st_point(c(3,3))))\nst_join(a, b)\nst_join(a, b, left = FALSE)\n# st_join, largest = TRUE:\nnc <- st_transform(st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE), 2264)\ngr = st_sf(\n    label = apply(expand.grid(1:10, LETTERS[10:1])[,2:1], 1, paste0, collapse = \" \"),\n\tgeom = st_make_grid(st_as_sfc(st_bbox(nc))))\ngr$col = sf.colors(10, categorical = TRUE, alpha = .3)\n# cut, to check, NA's work out:\ngr = gr[-(1:30),]\nst_join(nc, gr, largest = TRUE)\n\n# rbind:\nx = st_sf(a = 1:2, geom = st_sfc(list(st_point(0:1), st_point(0:1)), crs = 4326))\nrbind(x, x, x)\nnc2 = rbind(nc[1:50, ], nc[51:100, ])\nall.equal(nc, nc2)\n\n# st_sample:\nsuppressWarnings(RNGversion(\"3.5.3\"))\nset.seed(131)\noptions(digits=6)\nx = st_sfc(st_polygon(list(rbind(c(0,1),c(90,1),c(90,90),c(0,90),c(0,1)))), crs = st_crs(4326))\n  (p <- st_sample(x, 10))\n  p <- st_sample(x[[1]], 10) # sfg method\nx = st_sfc(st_polygon(list(rbind(c(0,0),c(90,0),c(90,90),c(0,90),c(0,0))))) # NOT long/lat:\np <- st_sample(x, 10)\nx = st_sfc(st_polygon(list(rbind(c(-180,-90),c(180,-90),c(180,90),c(-180,90),c(-180,-90)))),\n crs=st_crs(4326))\n#FIXME:\n# if (sf_extSoftVersion()[[\"proj.4\"]] >= \"4.9.0\") # lwgeom breaks on this\n#   (p <- st_sample(x, 10))\npt = st_multipoint(matrix(1:20,,2))\nst_sample(p, 3)\ntry(st_sample(p, 3.3))\nls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))),\n st_linestring(rbind(c(0,0),c(.1,0))),\n st_linestring(rbind(c(0,1),c(.1,1))),\n st_linestring(rbind(c(2,2),c(2,2.00001))))\nst_sample(ls, 80)\nst_sample(nc[1:2,], size = c(10,20))\n# try with LINES, LongLat, should generate a warning:\nnc[1:2,] |> st_transform(4326) |> st_cast(\"MULTILINESTRING\") |> st_sample(size = c(10,20))\nst_sample(ls, 80, type = \"regular\")\np_sample = lapply(1:10, function(i) st_sample(nc[i, ], 100, exact = FALSE))\nlengths(p_sample)\np_sample_exact = lapply(1:10, function(i) st_sample(nc[i, ], 100, exact = TRUE))\nlengths(p_sample_exact)\n#plot(nc$geometry[1])\n#plot(p_sample[[1]], add = TRUE)\n#plot(p_sample_exact[[1]], add = TRUE)\n\nif (require(dplyr, quietly = TRUE)) {\n #class(st_bind_cols(nc, as.data.frame(nc)[1:3]))\n print(class(dplyr::bind_cols(nc, as.data.frame(nc)[1:3])))\n}\nclass(rbind(nc, nc))\nclass(cbind(nc, nc))\n\nx = st_sfc(st_point(0:1), st_point(2:3))\nx[c(NA,1,NA,2,NA)]\n\n# jitter\npts = st_centroid(st_geometry(nc))\nplot(pts)\nplot(st_jitter(pts, .05), add = TRUE, col = 'red')\nplot(st_geometry(nc))\nplot(st_jitter(st_geometry(nc), factor = .01), add = TRUE, col = '#ff8888')\nst_jitter(st_sfc(st_point(0:1)), amount = .1)\n\n# st_bbox:\nif (suppressPackageStartupMessages(require(sp, quietly = TRUE)) && require(raster, quietly = TRUE)) {\ndemo(meuse, ask = FALSE, echo = FALSE)\nsuppressWarnings(st_bbox(meuse))\ncrs = suppressWarnings(st_crs(meuse))\nsuppressWarnings(st_bbox(raster(meuse.grid)))\nst_bbox(extent(raster()))\n}\n\n# st_to_s2\nif (FALSE) { # stops working with GDAL 2.3.0 / PROJ 5.0.1:\n x = sf:::st_to_s2(nc)\n x1 = st_geometry(x)\n cc = st_coordinates(x1)\n summary(sqrt(cc[,1]^2+cc[,2]^2+cc[,3]^2))\n}\n\n# check_ring_dir\nm = rbind(c(0,0), c(0,1), c(1,1), c(1,0), c(0,0))\nmi = m[nrow(m):1,]\npol = st_polygon(list(m * 10, m + .5, mi + 1.5, mi + 3.5, m + 5, mi + 6.5))\nst_sfc(pol)\nx = st_sfc(pol, check_ring_dir=TRUE)\ny = st_sf(a = 1, geom = st_sfc(pol), check_ring_dir=TRUE)\nstr(x)\nx = st_sfc(st_polygon(), st_polygon(), check_ring_dir=TRUE)\nstr(x)\n# empty ring/zero area:\nx = st_sfc(st_polygon(list(m[c(1,3,1),])), check_ring_dir=TRUE)\n\nmp = st_multipolygon(list(pol, pol))\ntry(x <- st_sfc(mp, st_polygon(), check_ring_dir=TRUE))\nx <- st_sfc(mp, pol) |> st_cast(\"MULTIPOLYGON\") |> st_sfc(check_ring_dir=TRUE)\nx\nstr(x)\n\nx = st_sfc(st_linestring(rbind(c(-179,0),c(179,0))), crs = 4326)\nst_wrap_dateline(st_sf(a = 1, geometry = x))\nst_wrap_dateline(x)\nst_wrap_dateline(x[[1]])\n\ngeo <- c(\"{\\\"geodesic\\\":true,\\\"type\\\":\\\"Point\\\",\\\"coordinates\\\":[-118.68152563269095,36.43764870908927]}\",\n         \"{\\\"geodesic\\\":true,\\\"type\\\":\\\"Point\\\",\\\"coordinates\\\":[-118.67408758213843,36.43366018922779]}\",\n         \"{\\\"geodesic\\\":true,\\\"type\\\":\\\"Point\\\",\\\"coordinates\\\":[-118.67708346361097,36.44208638659282]}\",\n         \"{\\\"geodesic\\\":true,\\\"type\\\":\\\"Point\\\",\\\"coordinates\\\":[-118.67886661944996,36.44110273135671]}\",\n         \"{\\\"geodesic\\\":true,\\\"type\\\":\\\"Point\\\",\\\"coordinates\\\":[-118.68089232041565,36.44173155205561]}\")\nst_as_sfc(geo, GeoJSON = TRUE)\nst_as_sfc(geo, GeoJSON = TRUE, crs = 4326)\n\nst_as_sfc(st_as_binary(st_sfc(st_point(0:1)))[[1]], crs = 4326)\n\nx = nc\nx$geom = NULL\nclass(x)\n\nst_as_sfc(list(st_point(0:1)), crs = 4326)\n\n# crop:\nbox = c(xmin = 0, ymin = 0, xmax = 1, ymax = 1)\n\npol = st_sfc(st_buffer(st_point(c(.5, .5)), .65))\npol_sf = st_sf(a=1, geom=pol)\n\nst_crop(pol, box)\nst_crop(pol, st_bbox(box))\nst_crop(pol_sf, box)\nst_crop(pol_sf, st_bbox(box))\n\n# new sample methods:\nx = st_sfc(st_polygon(list(rbind(c(0,0),c(90,0),c(90,90),c(0,90),c(0,0))))) # NOT long/lat:\np <- st_sample(x, 10, type = \"regular\")\np <- st_sample(x, 10, type = \"hexagonal\")\n\nall.equal(st_drop_geometry(pol_sf), st_set_geometry(pol_sf, NULL))\n\n# https://github.com/r-spatial/sf/issues/1024\nshape1 <-st_sfc(st_polygon(list(rbind(c(0,0), c(1,0), c(3,2), c(2,4), c(1,4), c(0,0)))))\nshape2 <- st_sfc(st_polygon())\nshape3 <- st_sfc(st_polygon())\n\nshape4 = st_intersection(shape2, shape3) # has zero features\n\nst_difference(shape1, shape4)\nst_difference(shape4, shape1)\nst_sym_difference(shape1, shape4)\nst_union(shape1, shape4)\nst_union(shape4, shape1)\n\n# transform empty:\ntr = st_sf(geom=st_sfc()) |> st_set_crs(3587) |> st_transform(4326)\n\n# NA values are converted to empty; #1114:\nx <- data.frame(name=LETTERS)\ny <- data.frame(name=LETTERS[1:13], letters[14:26])\ny$geometry <- st_sfc(st_point(c(0,0)))\ny <- st_sf(y)\nout = merge(x, y, all.x=TRUE)\nclass(out)\n\nst_as_sf(st_sfc(st_point(0:1)))\n\n# st_exterior_ring():\nouter = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\nhole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\nhole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\npts = list(outer, hole1, hole2)\npl1 = st_polygon(pts)\nmpl1 = st_multipolygon(list(pl1,pl1+20))\n\nspl1 = st_as_sfc(list(pl1),crs=4326)\nsmpl1 = st_as_sfc(list(mpl1),crs=4326)\n\nst_exterior_ring(spl1[[1]])\nst_exterior_ring(spl1)\nst_exterior_ring(st_sf(a = 1, geom = spl1))\nst_exterior_ring(smpl1[[1]])\nst_exterior_ring(st_sfc(smpl1))\nst_exterior_ring(st_sf(a = 1, geom = st_sfc(smpl1)))\n\n'{\"type\":\"Polygon\",\"coordinates\":[[]]}' |> read_sf() |> st_is_empty()\n# '{\"type\":\"Polygon\",\"coordinates\":[]}' |> read_sf() |> st_is_empty() # breaks on GDAL < 3.9 or so\n'{\"type\":\"MultiPolygon\",\"coordinates\":[[[]]]}' |> read_sf() |> st_is_empty()\n'{\"type\":\"MultiPolygon\",\"coordinates\":[[]]}' |> read_sf() |> st_is_empty()\n"
  },
  {
    "path": "tests/sfc.Rout.save",
    "content": "\nR version 4.5.2 (2025-10-31) -- \"[Not] Part in a Rumble\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-pc-linux-gnu\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> \n> p = st_point(c(1/3,1/6))\n> st_sfc(p, precision = 1000)\nGeometry set for 1 feature \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0.3333333 ymin: 0.1666667 xmax: 0.3333333 ymax: 0.1666667\nCRS:           NA\nPrecision:     1000 \nPOINT (0.3333333 0.1666667)\n> st_as_sfc(st_as_binary(st_sfc(p, precision = 0L)))\nGeometry set for 1 feature \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0.3333333 ymin: 0.1666667 xmax: 0.3333333 ymax: 0.1666667\nCRS:           NA\nPOINT (0.3333333 0.1666667)\n> st_as_sfc(st_as_binary(st_sfc(p, precision = 1000)))\nGeometry set for 1 feature \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0.333 ymin: 0.167 xmax: 0.333 ymax: 0.167\nCRS:           NA\nPOINT (0.333 0.167)\n> st_as_sfc(st_as_binary(st_sfc(p, precision = 1000000)))\nGeometry set for 1 feature \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0.333333 ymin: 0.166667 xmax: 0.333333 ymax: 0.166667\nCRS:           NA\nPOINT (0.333333 0.166667)\n> st_as_sfc(st_as_binary(st_sfc(p, precision = 10L)))\nGeometry set for 1 feature \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0.3 ymin: 0.2 xmax: 0.3 ymax: 0.2\nCRS:           NA\nPOINT (0.3 0.2)\n> st_as_sfc(st_as_binary(st_sfc(p, precision = -1)))\nGeometry set for 1 feature \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0.3333333 ymin: 0.1666667 xmax: 0.3333333 ymax: 0.1666667\nCRS:           NA\nPOINT (0.3333333 0.1666667)\n> \n> d = data.frame(a = 1:2)\n> d$geom = c(\"POINT(0 0)\", \"POINT(1 1)\")\n> \n> st_as_sf(d, wkt = \"geom\")\nSimple feature collection with 2 features and 1 field\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\n  a        geom\n1 1 POINT (0 0)\n2 2 POINT (1 1)\n> st_as_sf(d, wkt = 2)\nSimple feature collection with 2 features and 1 field\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\n  a        geom\n1 1 POINT (0 0)\n2 2 POINT (1 1)\n> st_as_sf(d, wkt = \"geom\", remove = FALSE)\nSimple feature collection with 2 features and 2 fields\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\n  a       geom    geometry\n1 1 POINT(0 0) POINT (0 0)\n2 2 POINT(1 1) POINT (1 1)\n> \n> st_as_sfc(c(\"POINT(0 0)\", \"POINT(1 1)\"))\nGeometry set for 2 features \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\nPOINT (0 0)\nPOINT (1 1)\n> st_as_sfc(c(\"POINT(0 0)\", \"POINT(1 1)\", \"POLYGON((0 0,1 1,0 1,0 0))\"))\nGeometry set for 3 features \nGeometry type: GEOMETRY\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\nPOINT (0 0)\nPOINT (1 1)\nPOLYGON ((0 0, 1 1, 0 1, 0 0))\n> st_as_sfc(character(0))\nGeometry set for 0 features \nBounding box:  xmin: NA ymin: NA xmax: NA ymax: NA\nCRS:           NA\n> x = st_as_sfc(character(0), 4326)\n> y = st_as_sfc(character(0), crs = 4326)\n> all.equal(x, y)\n[1] TRUE\n> st_as_sfc(c(\"POINT(0 0)\", \"POINT(1 1)\", \"POLYGON((0 0,1 1,0 1,0 0))\"),\n+ \t\"+proj=longlat +datum=WGS84\")\nGeometry set for 3 features \nGeometry type: GEOMETRY\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nGeodetic CRS:  +proj=longlat +datum=WGS84\nPOINT (0 0)\nPOINT (1 1)\nPOLYGON ((0 0, 1 1, 0 1, 0 0))\n> dg = st_as_sf(d, wkt = \"geom\")\n> print(dg, n = 1)\nSimple feature collection with 2 features and 1 field\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\nFirst 1 features:\n  a        geom\n1 1 POINT (0 0)\n> head(st_as_sf(d, wkt = \"geom\"), 1)\nSimple feature collection with 1 feature and 1 field\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 0 ymax: 0\nCRS:           NA\n  a        geom\n1 1 POINT (0 0)\n> \n> d$geom = st_as_sfc(d$geom)\n> d1 = d\n> attr(d1, \"sf_col\") = \"geom\"\n> st_geometry(d1) = d$geom\n> \n> d$geometry = d$geom # second geometry list-column\n> if (require(testthat, quietly = TRUE)) {\n+  expect_warning(st_geometry(d) <- d$geom)\n+ }\n> d\nSimple feature collection with 2 features and 1 field\nActive geometry column: geom\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\n  a        geom    geometry\n1 1 POINT (0 0) POINT (0 0)\n2 2 POINT (1 1) POINT (1 1)\n> \n> x = st_sfc(list(st_point(0:1), st_point(0:1)), crs = 4326)\n> # don't warn when replacing crs with identical value:\n> st_sfc(x, crs = 4326)\nGeometry set for 2 features \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1\nGeodetic CRS:  WGS 84\nPOINT (0 1)\nPOINT (0 1)\n> y = st_sfc(x, crs = \"+proj=longlat +datum=WGS84 +no_defs\")\n> # but do when it changes:\n> y = st_sfc(x, crs = 3857)\nWarning message:\nst_crs<- : replacing crs does not reproject data; use st_transform for that \n> \n> p = st_point(0:1)\n> st_cast(p, \"MULTIPOINT\")\nMULTIPOINT ((0 1))\n> mp = st_multipoint(rbind(c(0,1), c(2,2)))\n> st_cast(mp, \"POINT\")\nPOINT (0 1)\nWarning message:\nIn st_cast.MULTIPOINT(mp, \"POINT\") : point from first coordinate only\n> st_cast(mp, \"MULTIPOINT\")\nMULTIPOINT ((0 1), (2 2))\n> \n> # geometry collection to its elements:\n> st_cast(st_geometrycollection(list(mp)), \"POINT\")\nPOINT (0 1)\nWarning message:\nIn st_cast.MULTIPOINT(x[[1]], to, ...) : point from first coordinate only\n> st_cast(st_geometrycollection(list(mp)), \"MULTIPOINT\")\nMULTIPOINT ((0 1), (2 2))\n> st_cast(st_geometrycollection(list(p,mp)), \"MULTIPOINT\")\nMULTIPOINT ((0 1))\nWarning message:\nIn st_cast.GEOMETRYCOLLECTION(st_geometrycollection(list(p, mp)),  :\n  only first part of geometrycollection is retained\n> \n> mp = st_multipoint(rbind(c(0,1)))\n> x = st_sfc(p, mp)\n> st_cast(x, \"POINT\")\nGeometry set for 2 features \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1\nCRS:           NA\nPOINT (0 1)\nPOINT (0 1)\nWarning message:\nIn st_cast.MULTIPOINT(X[[i]], ...) : point from first coordinate only\n> \n> sf = st_sf(a = 3:2, geom = x)\n> st_cast(sf, \"POINT\")\nSimple feature collection with 2 features and 1 field\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1\nCRS:           NA\n  a        geom\n1 3 POINT (0 1)\n2 2 POINT (0 1)\nWarning message:\nIn st_cast.MULTIPOINT(X[[i]], ...) : point from first coordinate only\n> \n> \n> x |> st_cast(\"POINT\")\nGeometry set for 2 features \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1\nCRS:           NA\nPOINT (0 1)\nPOINT (0 1)\nWarning message:\nIn st_cast.MULTIPOINT(X[[i]], ...) : point from first coordinate only\n> \n> # points:\n> mp = st_multipoint(rbind(c(0,1))) # single-point multipoint\n> st_sfc(p,mp) |> st_cast(\"POINT\")\nGeometry set for 2 features \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1\nCRS:           NA\nPOINT (0 1)\nPOINT (0 1)\nWarning message:\nIn st_cast.MULTIPOINT(X[[i]], ...) : point from first coordinate only\n> st_sfc(p,mp) |> st_cast(\"MULTIPOINT\")\nGeometry set for 2 features \nGeometry type: MULTIPOINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1\nCRS:           NA\nMULTIPOINT ((0 1))\nMULTIPOINT ((0 1))\n> \n> # lines:\n> pts = rbind(c(0,0), c(1,1), c(2,1))\n> st_sfc(st_linestring(pts), st_multilinestring(list(pts))) |> st_cast(\"LINESTRING\")\nGeometry set for 2 features \nGeometry type: LINESTRING\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 2 ymax: 1\nCRS:           NA\nLINESTRING (0 0, 1 1, 2 1)\nLINESTRING (0 0, 1 1, 2 1)\n> st_sfc(st_linestring(pts), st_multilinestring(list(pts))) |> st_cast(\"MULTILINESTRING\")\nGeometry set for 2 features \nGeometry type: MULTILINESTRING\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 2 ymax: 1\nCRS:           NA\nMULTILINESTRING ((0 0, 1 1, 2 1))\nMULTILINESTRING ((0 0, 1 1, 2 1))\n> \n> # polygons:\n> pts = rbind(c(0,0), c(1,1), c(0,1), c(0,0))\n> st_sfc(st_polygon(list(pts)), st_multipolygon(list(list(pts)))) |> st_cast(\"POLYGON\")\nGeometry set for 2 features \nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\nPOLYGON ((0 0, 1 1, 0 1, 0 0))\nPOLYGON ((0 0, 1 1, 0 1, 0 0))\n> st_sfc(st_polygon(list(pts)), st_multipolygon(list(list(pts)))) |> st_cast(\"MULTIPOLYGON\")\nGeometry set for 2 features \nGeometry type: MULTIPOLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\nMULTIPOLYGON (((0 0, 1 1, 0 1, 0 0)))\nMULTIPOLYGON (((0 0, 1 1, 0 1, 0 0)))\n> \n> \n> st_sfc(st_geometrycollection(list(p)), st_geometrycollection(list(mp))) |> st_cast()\nGeometry set for 2 features \nGeometry type: GEOMETRY\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1\nCRS:           NA\nPOINT (0 1)\nMULTIPOINT ((0 1))\n> st_sfc(st_geometrycollection(list(p)), st_geometrycollection(list(mp))) |>\n+ \tst_cast() |>\n+ \tst_cast(\"POINT\")\nGeometry set for 2 features \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1\nCRS:           NA\nPOINT (0 1)\nPOINT (0 1)\nWarning message:\nIn st_cast.MULTIPOINT(X[[i]], ...) : point from first coordinate only\n> \n> p = rbind(c(0,0),c(1,0),c(1,1),c(0,1),c(0,0))\n> pol = st_polygon(list(p))\n> # plot(pol)\n> try(plot(st_polygonize(pol))) # --> breaks\nError in st_polygonize.sfc(st_sfc(x)) : \n  inherits(x, \"sfc_LINESTRING\") || inherits(x, \"sfc_MULTILINESTRING\") is not TRUE\n> st_length(st_sfc(st_point(c(0,0))))\n[1] 0\n> \n> try(as(st_sfc(st_linestring(matrix(1:9,3))), \"Spatial\"))\nError in StopZ(zm) : \n  sp supports Z dimension only for POINT and MULTIPOINT.\nuse `st_zm(...)` to coerce to XY dimensions\n> \n> # check conus is present:\n> x = st_sfc(st_point(c(-90,35)), st_point(c(-80,36)),\n+ \tcrs = \"+proj=longlat +datum=NAD27\")\n> y = st_transform(x, 3857)\n> \n> ## IGNORE_RDIFF_BEGIN\n> sf_extSoftVersion()[1:3]\n    GEOS     GDAL   proj.4 \n\"3.12.2\" \"3.11.4\"  \"9.4.1\" \n> ## IGNORE_RDIFF_END\n> \n> # Ops.sfc:\n> ls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))))\n> ls * 2\nGeometry set for 1 feature \nGeometry type: LINESTRING\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 0 ymax: 2\nCRS:           NA\nLINESTRING (0 0, 0 2)\n> ls - 2\nGeometry set for 1 feature \nGeometry type: LINESTRING\nDimension:     XY\nBounding box:  xmin: -2 ymin: -2 xmax: -2 ymax: -1\nCRS:           NA\nLINESTRING (-2 -2, -2 -1)\n> (ls + 2) %% 3\nGeometry set for 1 feature \nGeometry type: LINESTRING\nDimension:     XY\nBounding box:  xmin: 2 ymin: 0 xmax: 2 ymax: 2\nCRS:           NA\nLINESTRING (2 2, 2 0)\n> ls / ls\nGeometry set for 1 feature  (with 1 geometry empty)\nGeometry type: GEOMETRYCOLLECTION\nDimension:     XY\nBounding box:  xmin: NA ymin: NA xmax: NA ymax: NA\nCRS:           NA\nGEOMETRYCOLLECTION EMPTY\n> p_ = st_point(0:1)\n> ll = st_sfc(ls[[1]], p_)\n> ll & st_sfc(p_)\nGeometry set for 2 features \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1\nCRS:           NA\nPOINT (0 1)\nPOINT (0 1)\n> ll | st_sfc(p_)\nGeometry set for 2 features \nGeometry type: GEOMETRY\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 0 ymax: 1\nCRS:           NA\nLINESTRING (0 0, 0 1)\nPOINT (0 1)\n> ll %/% st_sfc(p_)\nGeometry set for 2 features  (with 1 geometry empty)\nGeometry type: GEOMETRY\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 0 ymax: 1\nCRS:           NA\nLINESTRING (0 0, 0 1)\nGEOMETRYCOLLECTION EMPTY\n> ll == st_sfc(p_)\n[1] FALSE  TRUE\n> ll != st_sfc(p_)\n[1]  TRUE FALSE\n> \n> \n> str(x)\nsfc_POINT of length 2; first list element:  'XY' num [1:2] -90 35\n> nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\n> str(nc)\nClasses 'sf' and 'data.frame':\t100 obs. of  15 variables:\n $ AREA     : num  0.114 0.061 0.143 0.07 0.153 0.097 0.062 0.091 0.118 0.124 ...\n $ PERIMETER: num  1.44 1.23 1.63 2.97 2.21 ...\n $ CNTY_    : num  1825 1827 1828 1831 1832 ...\n $ CNTY_ID  : num  1825 1827 1828 1831 1832 ...\n $ NAME     : chr  \"Ashe\" \"Alleghany\" \"Surry\" \"Currituck\" ...\n $ FIPS     : chr  \"37009\" \"37005\" \"37171\" \"37053\" ...\n $ FIPSNO   : num  37009 37005 37171 37053 37131 ...\n $ CRESS_ID : int  5 3 86 27 66 46 15 37 93 85 ...\n $ BIR74    : num  1091 487 3188 508 1421 ...\n $ SID74    : num  1 0 5 1 9 7 0 0 4 1 ...\n $ NWBIR74  : num  10 10 208 123 1066 ...\n $ BIR79    : num  1364 542 3616 830 1606 ...\n $ SID79    : num  0 3 6 2 3 5 2 2 2 5 ...\n $ NWBIR79  : num  19 12 260 145 1197 ...\n $ geometry :sfc_MULTIPOLYGON of length 100; first list element: List of 1\n  ..$ :List of 1\n  .. ..$ : num [1:27, 1:2] -81.5 -81.5 -81.6 -81.6 -81.7 ...\n  ..- attr(*, \"class\")= chr [1:3] \"XY\" \"MULTIPOLYGON\" \"sfg\"\n - attr(*, \"sf_column\")= chr \"geometry\"\n - attr(*, \"agr\")= Factor w/ 3 levels \"constant\",\"aggregate\",..: NA NA NA NA NA NA NA NA NA NA ...\n  ..- attr(*, \"names\")= chr [1:14] \"AREA\" \"PERIMETER\" \"CNTY_\" \"CNTY_ID\" ...\n> bb = st_as_sfc(st_bbox(nc))\n> format(st_bbox(nc))\n[1] \"((-84.32385,33.88199),(-75.45698,36.58965))\"\n> \n> st_agr(\"constant\")\n[1] constant\nLevels: constant aggregate identity\n> st_agr()\n[1] <NA>\nLevels: constant aggregate identity\n> x <- st_sf(a = 1:2, b = 3:4, geom = x, agr = c(\"constant\", \"aggregate\"))\n> y <- x |> st_set_agr(\"constant\")\n> y\nSimple feature collection with 2 features and 2 fields\nAttribute-geometry relationships: constant (2)\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: -90 ymin: 35 xmax: -80 ymax: 36\nGeodetic CRS:  +proj=longlat +datum=NAD27\n  a b           geom\n1 1 3 POINT (-90 35)\n2 2 4 POINT (-80 36)\n> \n> sf1 <- st_sf(a = c(\"x\", \"y\"), geom = st_sfc(st_point(3:4), st_point(3:4)))\n> sf1[names(sf1)]\nSimple feature collection with 2 features and 1 field\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 3 ymin: 4 xmax: 3 ymax: 4\nCRS:           NA\n  a        geom\n1 x POINT (3 4)\n2 y POINT (3 4)\n> \n> st_bbox(sf1)\nxmin ymin xmax ymax \n   3    4    3    4 \n> bb = st_bbox(nc)\n> bb\n     xmin      ymin      xmax      ymax \n-84.32385  33.88199 -75.45698  36.58965 \n> st_crs(bb)\nCoordinate Reference System:\n  User input: NAD27 \n  wkt:\nGEOGCRS[\"NAD27\",\n    DATUM[\"North American Datum 1927\",\n        ELLIPSOID[\"Clarke 1866\",6378206.4,294.978698213898,\n            LENGTHUNIT[\"metre\",1]]],\n    PRIMEM[\"Greenwich\",0,\n        ANGLEUNIT[\"degree\",0.0174532925199433]],\n    CS[ellipsoidal,2],\n        AXIS[\"latitude\",north,\n            ORDER[1],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n        AXIS[\"longitude\",east,\n            ORDER[2],\n            ANGLEUNIT[\"degree\",0.0174532925199433]],\n    ID[\"EPSG\",4267]]\n> st_bbox(c(xmin = 16.1, xmax = 16.6, ymin = 48.6, ymax = 47.9), crs = st_crs(4326))\nxmin ymin xmax ymax \n16.1 48.6 16.6 47.9 \n> st_bbox(c(xmin = 16.1, xmax = 16.6, ymin = 48.6, ymax = 47.9), crs = 4326)\nxmin ymin xmax ymax \n16.1 48.6 16.6 47.9 \n> \n> bb$xrange\n     xmin      xmax \n-84.32385 -75.45698 \n> bb$yrange\n    ymin     ymax \n33.88199 36.58965 \n> bb$xmin\n     xmin \n-84.32385 \n> bb$ymin\n    ymin \n33.88199 \n> bb$xmax\n     xmax \n-75.45698 \n> bb$ymax\n    ymax \n36.58965 \n> try(bb$foo)\nError in `$.bbox`(bb, foo) : unsupported name\n> \n> # merge:\n> a = data.frame(a = 1:3, b = 5:7)\n> st_geometry(a) = st_sfc(st_point(c(0,0)), st_point(c(1,1)), st_point(c(2,2)))\n> b = data.frame(x = c(\"a\", \"b\", \"c\"), b = c(2,5,6))\n> merge(a, b)\nSimple feature collection with 2 features and 3 fields\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\n  b a x    geometry\n1 5 1 b POINT (0 0)\n2 6 2 c POINT (1 1)\n> merge(a, b, all = TRUE)\nSimple feature collection with 4 features and 3 fields (with 1 geometry empty)\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 2 ymax: 2\nCRS:           NA\n  b  a    x    geometry\n1 2 NA    a POINT EMPTY\n2 5  1    b POINT (0 0)\n3 6  2    c POINT (1 1)\n4 7  3 <NA> POINT (2 2)\n> \n> if (require(dplyr, quietly = TRUE)) {\n+ # joins:\n+ inner_join(a, b)\n+ left_join(a, b)\n+ right_join(a, b)\n+ full_join(a, b)\n+ semi_join(a, b)\n+ anti_join(a, b)\n+ left_join(a, data.frame(b, geometry = 1), by = \"b\")\n+ }\n\nAttaching package: 'dplyr'\n\nThe following objects are masked from 'package:stats':\n\n    filter, lag\n\nThe following objects are masked from 'package:base':\n\n    intersect, setdiff, setequal, union\n\nJoining with `by = join_by(b)`\nJoining with `by = join_by(b)`\nJoining with `by = join_by(b)`\nJoining with `by = join_by(b)`\nJoining with `by = join_by(b)`\nJoining with `by = join_by(b)`\nSimple feature collection with 3 features and 4 fields\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 2 ymax: 2\nCRS:           NA\n  a b    x geometry.y  geometry.x\n1 1 5    b          1 POINT (0 0)\n2 2 6    c          1 POINT (1 1)\n3 3 7 <NA>         NA POINT (2 2)\n> \n> # st_joins:\n> a = st_sf(a = 1:3,\n+  geom = st_sfc(st_point(c(1,1)), st_point(c(2,2)), st_point(c(3,3))))\n> b = st_sf(a = 11:14,\n+  geom = st_sfc(st_point(c(10,10)), st_point(c(2,2)), st_point(c(2,2)), st_point(c(3,3))))\n> st_join(a, b)\nSimple feature collection with 4 features and 2 fields\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 1 ymin: 1 xmax: 3 ymax: 3\nCRS:           NA\n    a.x a.y        geom\n1     1  NA POINT (1 1)\n2     2  12 POINT (2 2)\n2.1   2  13 POINT (2 2)\n3     3  14 POINT (3 3)\n> st_join(a, b, left = FALSE)\nSimple feature collection with 3 features and 2 fields\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 2 ymin: 2 xmax: 3 ymax: 3\nCRS:           NA\n    a.x a.y        geom\n2     2  12 POINT (2 2)\n2.1   2  13 POINT (2 2)\n3     3  14 POINT (3 3)\n> # st_join, largest = TRUE:\n> nc <- st_transform(st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE), 2264)\n> gr = st_sf(\n+     label = apply(expand.grid(1:10, LETTERS[10:1])[,2:1], 1, paste0, collapse = \" \"),\n+ \tgeom = st_make_grid(st_as_sfc(st_bbox(nc))))\n> gr$col = sf.colors(10, categorical = TRUE, alpha = .3)\n> # cut, to check, NA's work out:\n> gr = gr[-(1:30),]\n> st_join(nc, gr, largest = TRUE)\nSimple feature collection with 100 features and 16 fields\nGeometry type: MULTIPOLYGON\nDimension:     XY\nBounding box:  xmin: 406265 ymin: 48359.7 xmax: 3052877 ymax: 1044143\nProjected CRS: NAD83 / North Carolina (ftUS)\nFirst 10 features:\n    AREA PERIMETER CNTY_ CNTY_ID        NAME  FIPS FIPSNO CRESS_ID BIR74 SID74\n1  0.114     1.442  1825    1825        Ashe 37009  37009        5  1091     1\n2  0.061     1.231  1827    1827   Alleghany 37005  37005        3   487     0\n3  0.143     1.630  1828    1828       Surry 37171  37171       86  3188     5\n4  0.070     2.968  1831    1831   Currituck 37053  37053       27   508     1\n5  0.153     2.206  1832    1832 Northampton 37131  37131       66  1421     9\n6  0.097     1.670  1833    1833    Hertford 37091  37091       46  1452     7\n7  0.062     1.547  1834    1834      Camden 37029  37029       15   286     0\n8  0.091     1.284  1835    1835       Gates 37073  37073       37   420     0\n9  0.118     1.421  1836    1836      Warren 37185  37185       93   968     4\n10 0.124     1.428  1837    1837      Stokes 37169  37169       85  1612     1\n   NWBIR74 BIR79 SID79 NWBIR79 label       col                       geometry\n1       10  1364     0      19  A  4 #fb80724d MULTIPOLYGON (((1270813 913...\n2       10   542     3      12  A  4 #fb80724d MULTIPOLYGON (((1340553 959...\n3      208  3616     6     260  A  5 #80b1d34d MULTIPOLYGON (((1570586 910...\n4      123   830     2     145  A 10 #bc80bd4d MULTIPOLYGON (((2881206 948...\n5     1066  1606     3    1197  A  8 #fccde54d MULTIPOLYGON (((2525700 911...\n6      954  1838     5    1237  A  9 #d9d9d94d MULTIPOLYGON (((2665112 911...\n7      115   350     2     139  A 10 #bc80bd4d MULTIPOLYGON (((2881206 948...\n8      254   594     2     371  A  9 #d9d9d94d MULTIPOLYGON (((2717988 951...\n9      748  1190     2     844  A  8 #fccde54d MULTIPOLYGON (((2203888 914...\n10     160  2038     5     176  A  5 #80b1d34d MULTIPOLYGON (((1697618 911...\nWarning message:\nattribute variables are assumed to be spatially constant throughout all geometries \n> \n> # rbind:\n> x = st_sf(a = 1:2, geom = st_sfc(list(st_point(0:1), st_point(0:1)), crs = 4326))\n> rbind(x, x, x)\nSimple feature collection with 6 features and 1 field\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1\nGeodetic CRS:  WGS 84\n  a        geom\n1 1 POINT (0 1)\n2 2 POINT (0 1)\n3 1 POINT (0 1)\n4 2 POINT (0 1)\n5 1 POINT (0 1)\n6 2 POINT (0 1)\n> nc2 = rbind(nc[1:50, ], nc[51:100, ])\n> all.equal(nc, nc2)\n[1] TRUE\n> \n> # st_sample:\n> suppressWarnings(RNGversion(\"3.5.3\"))\n> set.seed(131)\n> options(digits=6)\n> x = st_sfc(st_polygon(list(rbind(c(0,1),c(90,1),c(90,90),c(0,90),c(0,1)))), crs = st_crs(4326))\n>   (p <- st_sample(x, 10))\nGeometry set for 10 features \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 11.2448 ymin: 3.16385 xmax: 82.3451 ymax: 60.1703\nGeodetic CRS:  WGS 84\nFirst 5 geometries:\nPOINT (18.5793 25.2416)\nPOINT (11.2448 20.8596)\nPOINT (26.3946 60.1703)\nPOINT (33.8202 19.146)\nPOINT (76.1712 32.1029)\n>   p <- st_sample(x[[1]], 10) # sfg method\n> x = st_sfc(st_polygon(list(rbind(c(0,0),c(90,0),c(90,90),c(0,90),c(0,0))))) # NOT long/lat:\n> p <- st_sample(x, 10)\n> x = st_sfc(st_polygon(list(rbind(c(-180,-90),c(180,-90),c(180,90),c(-180,90),c(-180,-90)))),\n+  crs=st_crs(4326))\n> #FIXME:\n> # if (sf_extSoftVersion()[[\"proj.4\"]] >= \"4.9.0\") # lwgeom breaks on this\n> #   (p <- st_sample(x, 10))\n> pt = st_multipoint(matrix(1:20,,2))\n> st_sample(p, 3)\nGeometry set for 1 feature \nGeometry type: MULTIPOINT\nDimension:     XY\nBounding box:  xmin: 41.0557 ymin: 27.8024 xmax: 80.9558 ymax: 65.5424\nCRS:           NA\nMULTIPOINT ((57.2118 52.329), (80.9558 65.5424)...\n> try(st_sample(p, 3.3))\nGeometry set for 1 feature \nGeometry type: MULTIPOINT\nDimension:     XY\nBounding box:  xmin: 19.3415 ymin: 9.17624 xmax: 80.9558 ymax: 65.5424\nCRS:           NA\nMULTIPOINT ((19.3415 18.6622), (57.1389 9.17624...\nWarning message:\nIn st_sample.sfc(p, 3.3) : size is not an integer\n> ls = st_sfc(st_linestring(rbind(c(0,0),c(0,1))),\n+  st_linestring(rbind(c(0,0),c(.1,0))),\n+  st_linestring(rbind(c(0,1),c(.1,1))),\n+  st_linestring(rbind(c(2,2),c(2,2.00001))))\n> st_sample(ls, 80)\nGeometry set for 4 features  (with 1 geometry empty)\nGeometry type: MULTIPOINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 0.0914728 ymax: 1\nCRS:           NA\nMULTIPOINT ((0 0.137868), (0 0.777635), (0 0.40...\nMULTIPOINT ((0.0914728 0), (0.073852 0), (0.003...\nMULTIPOINT ((0.0488222 1), (0.0716508 1), (0.08...\nMULTIPOINT EMPTY\n> st_sample(nc[1:2,], size = c(10,20))\nGeometry set for 30 features \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 1216510 ymin: 935852 xmax: 1428880 ymax: 1031490\nProjected CRS: NAD83 / North Carolina (ftUS)\nFirst 5 geometries:\nPOINT (1264558 935852)\nPOINT (1256623 949369)\nPOINT (1222665 972624)\nPOINT (1333528 968263)\nPOINT (1310837 958630)\n> # try with LINES, LongLat, should generate a warning:\n> nc[1:2,] |> st_transform(4326) |> st_cast(\"MULTILINESTRING\") |> st_sample(size = c(10,20))\nalthough coordinates are longitude/latitude, st_sample assumes that they are\nplanar\nalthough coordinates are longitude/latitude, st_sample assumes that they are\nplanar\nGeometry set for 2 features \nGeometry type: MULTIPOINT\nDimension:     XY\nBounding box:  xmin: -81.6893 ymin: 36.2491 xmax: -80.914 ymax: 36.5726\nGeodetic CRS:  WGS 84\nMULTIPOINT ((-81.2401 36.3717), (-81.6893 36.36...\nMULTIPOINT ((-81.2629 36.4076), (-81.1375 36.56...\n> st_sample(ls, 80, type = \"regular\")\nGeometry set for 4 features  (with 1 geometry empty)\nGeometry type: MULTIPOINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 0.095454 ymax: 1\nCRS:           NA\nMULTIPOINT ((0 0.0104441), (0 0.0254442), (0 0....\nMULTIPOINT ((0.000452334 0), (0.0154525 0), (0....\nMULTIPOINT ((0.00545321 1), (0.0204533 1), (0.0...\nMULTIPOINT EMPTY\n> p_sample = lapply(1:10, function(i) st_sample(nc[i, ], 100, exact = FALSE))\n> lengths(p_sample)\n [1] 104 106 110  96  98 120  87 105 104  99\n> p_sample_exact = lapply(1:10, function(i) st_sample(nc[i, ], 100, exact = TRUE))\n> lengths(p_sample_exact)\n [1] 100 100 100 100 100 100 100 100 100 100\n> #plot(nc$geometry[1])\n> #plot(p_sample[[1]], add = TRUE)\n> #plot(p_sample_exact[[1]], add = TRUE)\n> \n> if (require(dplyr, quietly = TRUE)) {\n+  #class(st_bind_cols(nc, as.data.frame(nc)[1:3]))\n+  print(class(dplyr::bind_cols(nc, as.data.frame(nc)[1:3])))\n+ }\nNew names:\n• `AREA` -> `AREA...1`\n• `PERIMETER` -> `PERIMETER...2`\n• `CNTY_` -> `CNTY_...3`\n• `AREA` -> `AREA...16`\n• `PERIMETER` -> `PERIMETER...17`\n• `CNTY_` -> `CNTY_...18`\n[1] \"sf\"         \"data.frame\"\n> class(rbind(nc, nc))\n[1] \"sf\"         \"data.frame\"\n> class(cbind(nc, nc))\n[1] \"sf\"         \"data.frame\"\n> \n> x = st_sfc(st_point(0:1), st_point(2:3))\n> x[c(NA,1,NA,2,NA)]\nGeometry set for 5 features  (with 3 geometries empty)\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 2 ymax: 3\nCRS:           NA\nPOINT EMPTY\nPOINT (0 1)\nPOINT EMPTY\nPOINT (2 3)\nPOINT EMPTY\n> \n> # jitter\n> pts = st_centroid(st_geometry(nc))\n> plot(pts)\n> plot(st_jitter(pts, .05), add = TRUE, col = 'red')\n> plot(st_geometry(nc))\n> plot(st_jitter(st_geometry(nc), factor = .01), add = TRUE, col = '#ff8888')\n> st_jitter(st_sfc(st_point(0:1)), amount = .1)\nGeometry set for 1 feature \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: -0.0500922 ymin: 0.992953 xmax: -0.0500922 ymax: 0.992953\nCRS:           NA\nPOINT (-0.0500922 0.992953)\n> \n> # st_bbox:\n> if (suppressPackageStartupMessages(require(sp, quietly = TRUE)) && require(raster, quietly = TRUE)) {\n+ demo(meuse, ask = FALSE, echo = FALSE)\n+ suppressWarnings(st_bbox(meuse))\n+ crs = suppressWarnings(st_crs(meuse))\n+ suppressWarnings(st_bbox(raster(meuse.grid)))\n+ st_bbox(extent(raster()))\n+ }\n\nAttaching package: 'raster'\n\nThe following object is masked from 'package:dplyr':\n\n    select\n\nxmin ymin xmax ymax \n-180  -90  180   90 \n> \n> # st_to_s2\n> if (FALSE) { # stops working with GDAL 2.3.0 / PROJ 5.0.1:\n+  x = sf:::st_to_s2(nc)\n+  x1 = st_geometry(x)\n+  cc = st_coordinates(x1)\n+  summary(sqrt(cc[,1]^2+cc[,2]^2+cc[,3]^2))\n+ }\n> \n> # check_ring_dir\n> m = rbind(c(0,0), c(0,1), c(1,1), c(1,0), c(0,0))\n> mi = m[nrow(m):1,]\n> pol = st_polygon(list(m * 10, m + .5, mi + 1.5, mi + 3.5, m + 5, mi + 6.5))\n> st_sfc(pol)\nGeometry set for 1 feature \nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 10 ymax: 10\nCRS:           NA\nPOLYGON ((0 0, 0 10, 10 10, 10 0, 0 0), (0.5 0....\n> x = st_sfc(pol, check_ring_dir=TRUE)\n> y = st_sf(a = 1, geom = st_sfc(pol), check_ring_dir=TRUE)\n> str(x)\nsfc_POLYGON of length 1; first list element: List of 6\n $ : num [1:5, 1:2] 0 10 10 0 0 0 0 10 10 0\n $ : num [1:5, 1:2] 0.5 0.5 1.5 1.5 0.5 0.5 1.5 1.5 0.5 0.5\n $ : num [1:5, 1:2] 1.5 1.5 2.5 2.5 1.5 1.5 2.5 2.5 1.5 1.5\n $ : num [1:5, 1:2] 3.5 3.5 4.5 4.5 3.5 3.5 4.5 4.5 3.5 3.5\n $ : num [1:5, 1:2] 5 5 6 6 5 5 6 6 5 5\n $ : num [1:5, 1:2] 6.5 6.5 7.5 7.5 6.5 6.5 7.5 7.5 6.5 6.5\n - attr(*, \"class\")= chr [1:3] \"XY\" \"POLYGON\" \"sfg\"\n> x = st_sfc(st_polygon(), st_polygon(), check_ring_dir=TRUE)\n> str(x)\nsfc_POLYGON of length 2; first list element:  list()\n - attr(*, \"class\")= chr [1:3] \"XY\" \"POLYGON\" \"sfg\"\n> # empty ring/zero area:\n> x = st_sfc(st_polygon(list(m[c(1,3,1),])), check_ring_dir=TRUE)\n> \n> mp = st_multipolygon(list(pol, pol))\n> try(x <- st_sfc(mp, st_polygon(), check_ring_dir=TRUE))\nError in check_ring_dir(lst) : \n  check_ring_dir: not supported for class sfc_GEOMETRY\n> x <- st_sfc(mp, pol) |> st_cast(\"MULTIPOLYGON\") |> st_sfc(check_ring_dir=TRUE)\n> x\nGeometry set for 2 features \nGeometry type: MULTIPOLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 10 ymax: 10\nCRS:           NA\nMULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0), (...\nMULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0), (...\n> str(x)\nsfc_MULTIPOLYGON of length 2; first list element: List of 2\n $ :List of 6\n  ..$ : num [1:5, 1:2] 0 10 10 0 0 0 0 10 10 0\n  ..$ : num [1:5, 1:2] 0.5 0.5 1.5 1.5 0.5 0.5 1.5 1.5 0.5 0.5\n  ..$ : num [1:5, 1:2] 1.5 1.5 2.5 2.5 1.5 1.5 2.5 2.5 1.5 1.5\n  ..$ : num [1:5, 1:2] 3.5 3.5 4.5 4.5 3.5 3.5 4.5 4.5 3.5 3.5\n  ..$ : num [1:5, 1:2] 5 5 6 6 5 5 6 6 5 5\n  ..$ : num [1:5, 1:2] 6.5 6.5 7.5 7.5 6.5 6.5 7.5 7.5 6.5 6.5\n  ..- attr(*, \"class\")= chr [1:3] \"XY\" \"POLYGON\" \"sfg\"\n $ :List of 6\n  ..$ : num [1:5, 1:2] 0 10 10 0 0 0 0 10 10 0\n  ..$ : num [1:5, 1:2] 0.5 0.5 1.5 1.5 0.5 0.5 1.5 1.5 0.5 0.5\n  ..$ : num [1:5, 1:2] 1.5 1.5 2.5 2.5 1.5 1.5 2.5 2.5 1.5 1.5\n  ..$ : num [1:5, 1:2] 3.5 3.5 4.5 4.5 3.5 3.5 4.5 4.5 3.5 3.5\n  ..$ : num [1:5, 1:2] 5 5 6 6 5 5 6 6 5 5\n  ..$ : num [1:5, 1:2] 6.5 6.5 7.5 7.5 6.5 6.5 7.5 7.5 6.5 6.5\n  ..- attr(*, \"class\")= chr [1:3] \"XY\" \"POLYGON\" \"sfg\"\n - attr(*, \"class\")= chr [1:3] \"XY\" \"MULTIPOLYGON\" \"sfg\"\n> \n> x = st_sfc(st_linestring(rbind(c(-179,0),c(179,0))), crs = 4326)\n> st_wrap_dateline(st_sf(a = 1, geometry = x))\nSimple feature collection with 1 feature and 1 field\nGeometry type: MULTILINESTRING\nDimension:     XY\nBounding box:  xmin: -180 ymin: 0 xmax: 180 ymax: 0\nGeodetic CRS:  WGS 84\n  a                       geometry\n1 1 MULTILINESTRING ((-179 0, -...\n> st_wrap_dateline(x)\nGeometry set for 1 feature \nGeometry type: MULTILINESTRING\nDimension:     XY\nBounding box:  xmin: -180 ymin: 0 xmax: 180 ymax: 0\nGeodetic CRS:  WGS 84\nMULTILINESTRING ((-179 0, -180 0), (180 0, 179 0))\n> st_wrap_dateline(x[[1]])\nMULTILINESTRING ((-179 0, -180 0), (180 0, 179 0))\n> \n> geo <- c(\"{\\\"geodesic\\\":true,\\\"type\\\":\\\"Point\\\",\\\"coordinates\\\":[-118.68152563269095,36.43764870908927]}\",\n+          \"{\\\"geodesic\\\":true,\\\"type\\\":\\\"Point\\\",\\\"coordinates\\\":[-118.67408758213843,36.43366018922779]}\",\n+          \"{\\\"geodesic\\\":true,\\\"type\\\":\\\"Point\\\",\\\"coordinates\\\":[-118.67708346361097,36.44208638659282]}\",\n+          \"{\\\"geodesic\\\":true,\\\"type\\\":\\\"Point\\\",\\\"coordinates\\\":[-118.67886661944996,36.44110273135671]}\",\n+          \"{\\\"geodesic\\\":true,\\\"type\\\":\\\"Point\\\",\\\"coordinates\\\":[-118.68089232041565,36.44173155205561]}\")\n> st_as_sfc(geo, GeoJSON = TRUE)\nGeometry set for 5 features \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: -118.682 ymin: 36.4337 xmax: -118.674 ymax: 36.4421\nGeodetic CRS:  WGS 84\nPOINT (-118.682 36.4376)\nPOINT (-118.674 36.4337)\nPOINT (-118.677 36.4421)\nPOINT (-118.679 36.4411)\nPOINT (-118.681 36.4417)\n> st_as_sfc(geo, GeoJSON = TRUE, crs = 4326)\nGeometry set for 5 features \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: -118.682 ymin: 36.4337 xmax: -118.674 ymax: 36.4421\nGeodetic CRS:  WGS 84\nPOINT (-118.682 36.4376)\nPOINT (-118.674 36.4337)\nPOINT (-118.677 36.4421)\nPOINT (-118.679 36.4411)\nPOINT (-118.681 36.4417)\n> \n> st_as_sfc(st_as_binary(st_sfc(st_point(0:1)))[[1]], crs = 4326)\nGeometry set for 1 feature \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1\nGeodetic CRS:  WGS 84\nPOINT (0 1)\n> \n> x = nc\n> x$geom = NULL\n> class(x)\n[1] \"sf\"         \"data.frame\"\n> \n> st_as_sfc(list(st_point(0:1)), crs = 4326)\nGeometry set for 1 feature \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1\nGeodetic CRS:  WGS 84\nPOINT (0 1)\n> \n> # crop:\n> box = c(xmin = 0, ymin = 0, xmax = 1, ymax = 1)\n> \n> pol = st_sfc(st_buffer(st_point(c(.5, .5)), .65))\n> pol_sf = st_sf(a=1, geom=pol)\n> \n> st_crop(pol, box)\nGeometry set for 1 feature \nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\nPOLYGON ((0.983044 0.0650651, 0.959619 0.040380...\n> st_crop(pol, st_bbox(box))\nGeometry set for 1 feature \nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\nPOLYGON ((0.983044 0.0650651, 0.959619 0.040380...\n> st_crop(pol_sf, box)\nSimple feature collection with 1 feature and 1 field\nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\n  a                           geom\n1 1 POLYGON ((0.983044 0.065065...\nWarning message:\nattribute variables are assumed to be spatially constant throughout all geometries \n> st_crop(pol_sf, st_bbox(box))\nSimple feature collection with 1 feature and 1 field\nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 1 ymax: 1\nCRS:           NA\n  a                           geom\n1 1 POLYGON ((0.983044 0.065065...\nWarning message:\nattribute variables are assumed to be spatially constant throughout all geometries \n> \n> # new sample methods:\n> x = st_sfc(st_polygon(list(rbind(c(0,0),c(90,0),c(90,90),c(0,90),c(0,0))))) # NOT long/lat:\n> p <- st_sample(x, 10, type = \"regular\")\n> p <- st_sample(x, 10, type = \"hexagonal\")\n> \n> all.equal(st_drop_geometry(pol_sf), st_set_geometry(pol_sf, NULL))\n[1] TRUE\n> \n> # https://github.com/r-spatial/sf/issues/1024\n> shape1 <-st_sfc(st_polygon(list(rbind(c(0,0), c(1,0), c(3,2), c(2,4), c(1,4), c(0,0)))))\n> shape2 <- st_sfc(st_polygon())\n> shape3 <- st_sfc(st_polygon())\n> \n> shape4 = st_intersection(shape2, shape3) # has zero features\n> \n> st_difference(shape1, shape4)\nGeometry set for 1 feature \nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 3 ymax: 4\nCRS:           NA\nPOLYGON ((0 0, 1 0, 3 2, 2 4, 1 4, 0 0))\n> st_difference(shape4, shape1)\nGeometry set for 0 features \nBounding box:  xmin: NA ymin: NA xmax: NA ymax: NA\nCRS:           NA\n> st_sym_difference(shape1, shape4)\nGeometry set for 1 feature \nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 3 ymax: 4\nCRS:           NA\nPOLYGON ((0 0, 1 0, 3 2, 2 4, 1 4, 0 0))\n> st_union(shape1, shape4)\nGeometry set for 1 feature \nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 3 ymax: 4\nCRS:           NA\nPOLYGON ((0 0, 1 0, 3 2, 2 4, 1 4, 0 0))\n> st_union(shape4, shape1)\nGeometry set for 1 feature \nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 3 ymax: 4\nCRS:           NA\nPOLYGON ((0 0, 1 0, 3 2, 2 4, 1 4, 0 0))\n> \n> # transform empty:\n> tr = st_sf(geom=st_sfc()) |> st_set_crs(3587) |> st_transform(4326)\n> \n> # NA values are converted to empty; #1114:\n> x <- data.frame(name=LETTERS)\n> y <- data.frame(name=LETTERS[1:13], letters[14:26])\n> y$geometry <- st_sfc(st_point(c(0,0)))\n> y <- st_sf(y)\n> out = merge(x, y, all.x=TRUE)\n> class(out)\n[1] \"data.frame\"\n> \n> st_as_sf(st_sfc(st_point(0:1)))\nSimple feature collection with 1 feature and 0 fields\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0 ymin: 1 xmax: 0 ymax: 1\nCRS:           NA\n            x\n1 POINT (0 1)\n> \n> # st_exterior_ring():\n> outer = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\n> hole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\n> hole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\n> pts = list(outer, hole1, hole2)\n> pl1 = st_polygon(pts)\n> mpl1 = st_multipolygon(list(pl1,pl1+20))\n> \n> spl1 = st_as_sfc(list(pl1),crs=4326)\n> smpl1 = st_as_sfc(list(mpl1),crs=4326)\n> \n> st_exterior_ring(spl1[[1]])\nPOLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))\n> st_exterior_ring(spl1)\nGeometry set for 1 feature \nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 10 ymax: 10\nGeodetic CRS:  WGS 84\nPOLYGON ((0 0, 10 0, 10 10, 0 10, 0 0))\n> st_exterior_ring(st_sf(a = 1, geom = spl1))\nSimple feature collection with 1 feature and 1 field\nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 10 ymax: 10\nGeodetic CRS:  WGS 84\n  a                           geom\n1 1 POLYGON ((0 0, 10 0, 10 10,...\n> st_exterior_ring(smpl1[[1]])\nMULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0)), ((20 20, 30 20, 30 30, 20 30, 20 20)))\n> st_exterior_ring(st_sfc(smpl1))\nGeometry set for 1 feature \nGeometry type: MULTIPOLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 30 ymax: 30\nGeodetic CRS:  WGS 84\nMULTIPOLYGON (((0 0, 10 0, 10 10, 0 10, 0 0)), ...\n> st_exterior_ring(st_sf(a = 1, geom = st_sfc(smpl1)))\nSimple feature collection with 1 feature and 1 field\nGeometry type: MULTIPOLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0 xmax: 30 ymax: 30\nGeodetic CRS:  WGS 84\n  a                           geom\n1 1 MULTIPOLYGON (((0 0, 10 0, ...\n> \n> '{\"type\":\"Polygon\",\"coordinates\":[[]]}' |> read_sf() |> st_is_empty()\n[1] TRUE\n> # '{\"type\":\"Polygon\",\"coordinates\":[]}' |> read_sf() |> st_is_empty() # breaks on GDAL < 3.9 or so\n> '{\"type\":\"MultiPolygon\",\"coordinates\":[[[]]]}' |> read_sf() |> st_is_empty()\n[1] TRUE\n> '{\"type\":\"MultiPolygon\",\"coordinates\":[[]]}' |> read_sf() |> st_is_empty()\n[1] TRUE\n> \n> proc.time()\n   user  system elapsed \n  5.476   1.458   5.453 \n"
  },
  {
    "path": "tests/sfg.R",
    "content": "suppressPackageStartupMessages(library(sf))\nc(st_point(1:2), st_point(5:6))\nc(st_point(1:2), st_multipoint(matrix(5:8,2)))\nc(st_multipoint(matrix(1:4,2)), st_multipoint(matrix(5:8,2)))\nc(st_linestring(matrix(1:6,3)), st_linestring(matrix(11:16,3)))\nc(st_linestring(matrix(1:6,3)), st_multilinestring(list(matrix(11:16,3))))\nc(st_multilinestring(list(matrix(1:6,3))), st_multilinestring(list(matrix(11:16,3))))\npl = list(rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0)))\nc(st_polygon(pl), st_polygon(pl))\nc(st_polygon(pl), st_multipolygon(list(pl)))\nc(st_linestring(matrix(1:6,3)), st_point(1:2))\nc(st_geometrycollection(list(st_point(1:2), st_linestring(matrix(1:6,3)))),\n  st_geometrycollection(list(st_multilinestring(list(matrix(11:16,3))))))\nc(st_geometrycollection(list(st_point(1:2), st_linestring(matrix(1:6,3)))),\n  st_multilinestring(list(matrix(11:16,3))), st_point(5:6), \n  st_geometrycollection(list(st_point(10:11))))\nhead(st_point(0:1), 2)\n\n# Ops.sfg:\nls = st_linestring(rbind(c(0,0),c(0,1)))\npt = st_point(1:0)\nls | pt\nls / pt\nls & pt\nls %/% pt\n# arith:\nls + pt\nls - pt\nls * pt\nls / pt\n# unary:\n+pt\n-pt\ntry(!pt)\n"
  },
  {
    "path": "tests/sfg.Rout.save",
    "content": "\nR Under development (unstable) (2025-11-05 r88988 ucrt) -- \"Unsuffered Consequences\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-w64-mingw32/x64\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> c(st_point(1:2), st_point(5:6))\nMULTIPOINT ((1 2), (5 6))\n> c(st_point(1:2), st_multipoint(matrix(5:8,2)))\nMULTIPOINT ((1 2), (5 7), (6 8))\n> c(st_multipoint(matrix(1:4,2)), st_multipoint(matrix(5:8,2)))\nMULTIPOINT ((1 3), (2 4), (5 7), (6 8))\n> c(st_linestring(matrix(1:6,3)), st_linestring(matrix(11:16,3)))\nMULTILINESTRING ((1 4, 2 5, 3 6), (11 14, 12 15, 13 16))\n> c(st_linestring(matrix(1:6,3)), st_multilinestring(list(matrix(11:16,3))))\nMULTILINESTRING ((11 14, 12 15, 13 16), (1 4, 2 5, 3 6))\n> c(st_multilinestring(list(matrix(1:6,3))), st_multilinestring(list(matrix(11:16,3))))\nMULTILINESTRING ((1 4, 2 5, 3 6), (11 14, 12 15, 13 16))\n> pl = list(rbind(c(0,0), c(1,0), c(1,1), c(0,1), c(0,0)))\n> c(st_polygon(pl), st_polygon(pl))\nMULTIPOLYGON (((0 0, 1 0, 1 1, 0 1, 0 0)), ((0 0, 1 0, 1 1, 0 1, 0 0)))\n> c(st_polygon(pl), st_multipolygon(list(pl)))\nMULTIPOLYGON (((0 0, 1 0, 1 1, 0 1, 0 0)), ((0 0, 1 0, 1 1, 0 1, 0 0)))\n> c(st_linestring(matrix(1:6,3)), st_point(1:2))\nGEOMETRYCOLLECTION (LINESTRING (1 4, 2 5, 3 6), POINT (1 2))\n> c(st_geometrycollection(list(st_point(1:2), st_linestring(matrix(1:6,3)))),\n+   st_geometrycollection(list(st_multilinestring(list(matrix(11:16,3))))))\nGEOMETRYCOLLECTION (POINT (1 2), LINESTRING (1 4, 2 5, 3 6), MULTILINESTRING ((11 14, 12 15, 13 16)))\n> c(st_geometrycollection(list(st_point(1:2), st_linestring(matrix(1:6,3)))),\n+   st_multilinestring(list(matrix(11:16,3))), st_point(5:6), \n+   st_geometrycollection(list(st_point(10:11))))\nGEOMETRYCOLLECTION (MULTILINESTRING ((11 14, 12 15, 13 16)), POINT (5 6), POINT (1 2), LINESTRING (1 4, 2 5, 3 6), POINT (10 11))\n> head(st_point(0:1), 2)\nPOINT (0 1)\n> \n> # Ops.sfg:\n> ls = st_linestring(rbind(c(0,0),c(0,1)))\n> pt = st_point(1:0)\n> ls | pt\nGEOMETRYCOLLECTION (LINESTRING (0 0, 0 1), POINT (1 0))\n> ls / pt\nLINESTRING (0 0, 0 1)\n> ls & pt\nGEOMETRYCOLLECTION EMPTY\n> ls %/% pt\nGEOMETRYCOLLECTION (LINESTRING (0 0, 0 1), POINT (1 0))\n> # arith:\n> ls + pt\nLINESTRING (1 0, 1 1)\n> ls - pt\nLINESTRING (-1 0, -1 1)\n> ls * pt\nLINESTRING (0 0, 0 0)\n> ls / pt\nLINESTRING (0 0, 0 1)\n> # unary:\n> +pt\nPOINT (1 0)\n> -pt\nPOINT (-1 0)\n> try(!pt)\nError in Ops.sfg(pt) : unary ! not defined for \"sfg\" objects\n> \n> proc.time()\n   user  system elapsed \n   0.42    0.14    0.54 \n"
  },
  {
    "path": "tests/spatstat.R",
    "content": "suppressPackageStartupMessages(library(sf))\n## IGNORE_RDIFF_BEGIN\nif (require(spatstat.random, quietly = TRUE)) {\n\ndata(chicago)\nst_as_sf(chicago)\n# ppp:\ng = gorillas\nst_as_sf(g)\nmarks(g) = NULL\nst_as_sf(g)\n\n# multipolygon: https://github.com/r-spatial/sf/issues/1161\nwindow = read_sf(system.file(\"shape/nc.shp\", package = \"sf\")) |>\n  st_transform(32119)\n\nwin = spatstat.geom::as.owin(window)\n\nset.seed(1331)\npp2a = runifpoint(n = 50, win = win)\nprint(st_as_sf(pp2a))\n\n# st_sample going the spatstat way\nx <- sf::st_sfc(sf::st_polygon(list(rbind(c(0, 0), c(10, 0), c(10, 10), c(0, 0)))))\ntry(pts <- st_sample(x, type = \"thomas\"))\ntry(pts <- st_sample(x, kappa = 1, mu = 10, type = \"Thomas\"))\n# points expected\nset.seed(1331)\npts <- st_sample(x, kappa = 1, mu = 10, scale = 0.1, type = \"Thomas\")\n#plot(x)\n#plot(pts, add = TRUE)\npts\n\n# see https://github.com/r-spatial/sf/issues/1233\n# png(\"/tmp/spa%03d.png\")\n\np1 = st_point(0:1)\np2 = st_point(1:2)\np3 = st_point(c(-1,2))\np = st_sfc(p1, p2, p3)\nas.ppp(p)\ntry(as.ppp(st_set_crs(p, 4326)))\n\nsf = st_sf(geom = p)\ntry(as.ppp(sf))\nsf = st_sf(a = 1:3, geom = p)\nas.ppp(sf)\nsf = st_sf(a = 1:3, b=3:1, geom = p)\nas.ppp(sf) # warns\n\nw = st_as_sfc(st_bbox(st_sfc(p1, p2)))\nsf = st_sf(a = 1:3, geom = p)\n(p0 = rbind(st_sf(a = 0, geom = w), sf))\nsuppressWarnings(try(as.ppp(p0))) # errors: one point outside window\n\nw = st_as_sfc(st_bbox(p))\nsf = st_sf(a = 1:3, geom = p)\n(p0 = rbind(st_sf(a = 0, geom = w), sf))\nas.ppp(p0)\n\n# as.owin.sf, as.owin.sfc_*\nnc = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), check_ring_dir = TRUE, quiet = TRUE)\ntry(as.owin(nc)) # should be projected\nnc = st_transform(nc, 32119)\nplot(as.owin(nc), col = 'grey')\nplot(as.owin(st_geometry(nc)), col = 'grey')\n\nsq = rbind(c(-1,-1), c(1, -1), c(1,1), c(-1,1), c(-1,-1))\npol = st_polygon(list(0.5 * sq, sq[5:1,] * 0.45)) # w hole\nplot(as.owin(pol), col = 'grey')\nplot(as.owin(st_sfc(pol)), col = 'grey')\nmpol = st_multipolygon(list(\n\tlist(sq, sq[5:1,] * 0.9),\n\tlist(sq * 2, sq[5:1,] * 1.8)))\nplot(as.owin(mpol), col = 'grey')\nplot(as.owin(st_sfc(mpol)), col = 'grey')\nplot(as.owin(st_sfc(pol, mpol)), col = 'grey')\nplot(as.owin(st_sf(a=1:2, st_sfc(pol, mpol))), col = 'grey')\n(o = as.owin(st_sf(a=1:2, st_sfc(pol, mpol))))\nst_as_sfc(o)\n\nplot(st_as_sfc(o), col = 'blue', main = 'st_as_sfc(o)')\nplot(st_as_sf(o), col = 'blue', main = 'st_as_sf(o)')\n\ndata(japanesepines)\nst_as_sf(japanesepines) # warns about multiplier\njp = rescale(japanesepines)\nst_as_sf(jp) # No warning\n\ndata(nztrees)\nqNZ <- quadratcount(nztrees, nx=4, ny=3)\nts = as.tess(qNZ)\nplot(st_as_sfc(ts))\n\nls = st_linestring(rbind(c(0,0), c(1,1), c(2,0)))\nplot(as.psp(ls))\nmls = st_multilinestring(list(rbind(c(0,0), c(1,1), c(2,0)), rbind(c(3,3), c(4,2))))\nplot(as.psp(mls))\n\nplot(as.psp(st_sfc(ls)))\nplot(as.psp(st_sfc(mls)))\nplot(as.psp(st_sfc(ls, mls)))\n\nsf = st_sf(st_cast(st_sfc(ls, mls), \"MULTILINESTRING\"), marks = 1:2, foo = 2:1)\nas.psp(sf) # picks marks itself\nas.psp(sf, marks = 5:1)\n\n(x = st_as_sf(as.psp(sf)))\n(y = st_as_sfc(as.psp(sf)))\nall.equal(st_geometry(x), y)\n\n# Test sf -> ppp conversion when the conversion involves more than 1 column of mark(s)\n# (https://github.com/r-spatial/sf/issues/2450)\nreference_ppp <- ppp(\n\tx = c(0.25, 0.75),\n\ty = c(0.25, 0.75), \n\t# We consider a data.frame of marks which includes several types of columns\n\t# (and also a list column)\n\tmarks = data.frame(\n\t\ta = TRUE, b = 1L, c = pi, d = I(list(list(1, 2), list(\"A\", \"B\", \"C\"))), \n\t\t#NB: row.names should always defined as a vector with character character\n\t\t#since they are converted as characters when applying st_as_sf (see line\n\t\t#below) which mixes NA and not-NA row.names\n\t\trow.names = c(\"point1\", \"point2\")\n\t)\n)\n# The st_as_sf conversion returns an sf object where the first row is the Window\n# and the other rows are the points\ntmp <- st_as_sf(reference_ppp)\npts <- tmp[tmp$label == \"point\", 1:4]\ntarget_ppp <- as.ppp(pts)\nWindow(target_ppp) <- owin()\nall.equal(reference_ppp, target_ppp)\n}\n## IGNORE_RDIFF_END\n"
  },
  {
    "path": "tests/spatstat.Rout.save",
    "content": "\nR Under development (unstable) (2025-11-05 r88988 ucrt) -- \"Unsuffered Consequences\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-w64-mingw32/x64\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> ## IGNORE_RDIFF_BEGIN\n> if (require(spatstat.random, quietly = TRUE)) {\n+ \n+ data(chicago)\n+ st_as_sf(chicago)\n+ # ppp:\n+ g = gorillas\n+ st_as_sf(g)\n+ marks(g) = NULL\n+ st_as_sf(g)\n+ \n+ # multipolygon: https://github.com/r-spatial/sf/issues/1161\n+ window = read_sf(system.file(\"shape/nc.shp\", package = \"sf\")) %>%\n+   st_transform(32119)\n+ \n+ win = spatstat.geom::as.owin(window)\n+ \n+ set.seed(1331)\n+ pp2a = runifpoint(n = 50, win = win)\n+ print(st_as_sf(pp2a))\n+ \n+ # st_sample going the spatstat way\n+ x <- sf::st_sfc(sf::st_polygon(list(rbind(c(0, 0), c(10, 0), c(10, 10), c(0, 0)))))\n+ try(pts <- st_sample(x, type = \"thomas\"))\n+ try(pts <- st_sample(x, kappa = 1, mu = 10, type = \"Thomas\"))\n+ # points expected\n+ set.seed(1331)\n+ pts <- st_sample(x, kappa = 1, mu = 10, scale = 0.1, type = \"Thomas\")\n+ #plot(x)\n+ #plot(pts, add = TRUE)\n+ pts\n+ \n+ # see https://github.com/r-spatial/sf/issues/1233\n+ # png(\"/tmp/spa%03d.png\")\n+ \n+ p1 = st_point(0:1)\n+ p2 = st_point(1:2)\n+ p3 = st_point(c(-1,2))\n+ p = st_sfc(p1, p2, p3)\n+ as.ppp(p)\n+ try(as.ppp(st_set_crs(p, 4326)))\n+ \n+ sf = st_sf(geom = p)\n+ try(as.ppp(sf))\n+ sf = st_sf(a = 1:3, geom = p)\n+ as.ppp(sf)\n+ sf = st_sf(a = 1:3, b=3:1, geom = p)\n+ as.ppp(sf) # warns\n+ \n+ w = st_as_sfc(st_bbox(st_sfc(p1, p2)))\n+ sf = st_sf(a = 1:3, geom = p)\n+ (p0 = rbind(st_sf(a = 0, geom = w), sf))\n+ suppressWarnings(try(as.ppp(p0))) # errors: one point outside window\n+ \n+ w = st_as_sfc(st_bbox(p))\n+ sf = st_sf(a = 1:3, geom = p)\n+ (p0 = rbind(st_sf(a = 0, geom = w), sf))\n+ as.ppp(p0)\n+ \n+ # as.owin.sf, as.owin.sfc_*\n+ nc = st_read(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), check_ring_dir = TRUE, quiet = TRUE)\n+ try(as.owin(nc)) # should be projected\n+ nc = st_transform(nc, 32119)\n+ plot(as.owin(nc), col = 'grey')\n+ plot(as.owin(st_geometry(nc)), col = 'grey')\n+ \n+ sq = rbind(c(-1,-1), c(1, -1), c(1,1), c(-1,1), c(-1,-1))\n+ pol = st_polygon(list(0.5 * sq, sq[5:1,] * 0.45)) # w hole\n+ plot(as.owin(pol), col = 'grey')\n+ plot(as.owin(st_sfc(pol)), col = 'grey')\n+ mpol = st_multipolygon(list(\n+ \tlist(sq, sq[5:1,] * 0.9),\n+ \tlist(sq * 2, sq[5:1,] * 1.8)))\n+ plot(as.owin(mpol), col = 'grey')\n+ plot(as.owin(st_sfc(mpol)), col = 'grey')\n+ plot(as.owin(st_sfc(pol, mpol)), col = 'grey')\n+ plot(as.owin(st_sf(a=1:2, st_sfc(pol, mpol))), col = 'grey')\n+ (o = as.owin(st_sf(a=1:2, st_sfc(pol, mpol))))\n+ st_as_sfc(o)\n+ \n+ plot(st_as_sfc(o), col = 'blue', main = 'st_as_sfc(o)')\n+ plot(st_as_sf(o), col = 'blue', main = 'st_as_sf(o)')\n+ \n+ data(japanesepines)\n+ st_as_sf(japanesepines) # warns about multiplier\n+ jp = rescale(japanesepines)\n+ st_as_sf(jp) # No warning\n+ \n+ data(nztrees)\n+ qNZ <- quadratcount(nztrees, nx=4, ny=3)\n+ ts = as.tess(qNZ)\n+ plot(st_as_sfc(ts))\n+ \n+ ls = st_linestring(rbind(c(0,0), c(1,1), c(2,0)))\n+ plot(as.psp(ls))\n+ mls = st_multilinestring(list(rbind(c(0,0), c(1,1), c(2,0)), rbind(c(3,3), c(4,2))))\n+ plot(as.psp(mls))\n+ \n+ plot(as.psp(st_sfc(ls)))\n+ plot(as.psp(st_sfc(mls)))\n+ plot(as.psp(st_sfc(ls, mls)))\n+ \n+ sf = st_sf(st_cast(st_sfc(ls, mls), \"MULTILINESTRING\"), marks = 1:2, foo = 2:1)\n+ as.psp(sf) # picks marks itself\n+ as.psp(sf, marks = 5:1)\n+ \n+ (x = st_as_sf(as.psp(sf)))\n+ (y = st_as_sfc(as.psp(sf)))\n+ all.equal(st_geometry(x), y)\n+ \n+ # Test sf -> ppp conversion when the conversion involves more than 1 column of mark(s)\n+ # (https://github.com/r-spatial/sf/issues/2450)\n+ reference_ppp <- ppp(\n+ \tx = c(0.25, 0.75),\n+ \ty = c(0.25, 0.75), \n+ \t# We consider a data.frame of marks which includes several types of columns\n+ \t# (and also a list column)\n+ \tmarks = data.frame(\n+ \t\ta = TRUE, b = 1L, c = pi, d = I(list(list(1, 2), list(\"A\", \"B\", \"C\"))), \n+ \t\t#NB: row.names should always defined as a vector with character character\n+ \t\t#since they are converted as characters when applying st_as_sf (see line\n+ \t\t#below) which mixes NA and not-NA row.names\n+ \t\trow.names = c(\"point1\", \"point2\")\n+ \t)\n+ )\n+ # The st_as_sf conversion returns an sf object where the first row is the Window\n+ # and the other rows are the points\n+ tmp <- st_as_sf(reference_ppp)\n+ pts <- tmp[tmp$label == \"point\", 1:4]\n+ target_ppp <- as.ppp(pts)\n+ Window(target_ppp) <- owin()\n+ all.equal(reference_ppp, target_ppp)\n+ }\nspatstat.univar 3.1-4\nspatstat.geom 3.6-0\nspatstat.random 3.4-2\nSimple feature collection with 51 features and 1 field\nGeometry type: GEOMETRY\nDimension:     XY\nBounding box:  xmin: 123829.8 ymin: 14740.06 xmax: 930518.6 ymax: 318255.5\nCRS:           NA\nFirst 10 features:\n    label                           geom\n1  window MULTIPOLYGON (((886135.8 31...\n2   point      POINT (339121.1 257811.6)\n3   point      POINT (827440.4 246568.3)\n4   point      POINT (451339.2 207943.6)\n5   point      POINT (268749.7 203323.4)\n6   point      POINT (516676.5 198556.1)\n7   point        POINT (692366 238643.1)\n8   point      POINT (843278.5 287241.6)\n9   point      POINT (648477.7 235466.6)\n10  point        POINT (852593 267248.3)\nError in st_poly_sample(x, size = size, ..., type = type, by_polygon = by_polygon,  : \n  rthomas is not an exported function from spatstat.random.\nError in st_poly_sample(x, size = size, ..., type = type, by_polygon = by_polygon,  : \n  The spatstat function rThomas did not return a valid result. Consult the help file.\nError message from spatstat:\nError in spatstat_fun(..., win = spatstat.geom::as.owin(x)) : \n  argument \"scale\" is missing, with no default\n\nError : Only projected coordinates may be converted to spatstat class objects\nError in `marks<-.ppp`(`*tmp*`, value = value) : \n  number of rows of data frame != number of points\nError : Only projected coordinates may be converted to spatstat class objects\n[1] TRUE\nWarning message:\nIn st_as_sfc.owin(spatstat.geom::as.owin(x)) :\n  The spatstat object has an measurement unit multiplier != 1. Consider rescaling before converting.\n> ## IGNORE_RDIFF_END\n> \n> proc.time()\n   user  system elapsed \n   1.92    0.46    2.39 \n"
  },
  {
    "path": "tests/stars.R",
    "content": "suppressPackageStartupMessages(library(sf))\n\ntif = system.file(\"tif/geomatrix.tif\", package = \"sf\")\n\ngdal_metadata(tif)\ngdal_metadata(tif, NA_character_)\ntry(gdal_metadata(tif, \"wrongDomain\")) \ngdal_metadata(tif, c(\"IMAGE_STRUCTURE\"))\ntry(length(gdal_metadata(tif, c(\"DERIVED_SUBDATASETS\")))) # fails on Fedora 26\n\nif (require(stars, quietly = TRUE)) {\n  tif = system.file(\"tif/geomatrix.tif\", package = \"sf\")\n  r = read_stars(tif)\n  d = (st_dimensions(r))\n  gt =  c(1841001.75, 1.5, -5, 1144003.25, -5, -1.5)\n  x1 = st_as_sfc(d, as_points = TRUE, use_cpp = TRUE, geotransform = gt)\n  x2 = st_as_sfc(d, as_points = TRUE, use_cpp = FALSE, geotransform = gt)\n  print(identical(x1, x2))\n  y1 = st_as_sfc(d, as_points = FALSE, use_cpp = TRUE, geotransform = gt)\n  y2 = st_as_sfc(d, as_points = FALSE, use_cpp = FALSE, geotransform = gt)\n  print(identical(y1, y2))\n\n  # rectilinear grid:\n  m = matrix(1:20, nrow = 5, ncol = 4)\n  x = c(0,0.5,1,2,4,5)\n  y = c(0.3,0.5,1,2,2.2)\n  r = st_as_stars(list(m = m), dimensions = st_dimensions(x = x, y = y, .raster = c(\"x\", \"y\")))\n  print(st_as_sfc(st_dimensions(r), as_points = TRUE))\n  print(st_as_sfc(st_dimensions(r), as_points = FALSE))\n\n  # curvilinear grid:\n  lon = st_as_stars(matrix(1:5, 4, 5, byrow = TRUE))\n  lat = st_as_stars(matrix(1:4, 4, 5))\n  ll = c(X1 = lon, X2 = lat)\n  curv = st_as_stars(st_as_stars(t(m)), curvilinear = setNames(ll, c(\"X1\", \"X2\")))\n  print(st_as_sfc(st_dimensions(curv), as_points = TRUE))\n  print(st_as_sfc(st_dimensions(curv), as_points = FALSE))\n\n  demo(nc, echo = FALSE, ask = FALSE)\n  print(x <- st_rasterize(nc)) # default grid:\n  print(p <- st_as_sf(x, as_points = FALSE)) # polygonize: follow raster boundaries\n  print(p <- st_as_sf(x, as_points = FALSE, use_integer = TRUE)) # polygonize integers: follow raster boundaries\n  print(try(p <- st_as_sf(x, as_points = TRUE))) # polygonize: contour, requies GDAL >= 2.4.0\n  if (utils::packageVersion(\"stars\") >= \"0.2-1\") {\n    write_stars(read_stars(tif), tempfile(fileext = \".tif\"))\n    write_stars(read_stars(tif, proxy = TRUE), tempfile(fileext = \".tif\"))\n    write_stars(read_stars(tif, proxy = TRUE), tempfile(fileext = \".tif\"), chunk_size = c(200,200))\n  \tna.tif = read_stars(system.file(\"tif/na.tif\", package = \"stars\"))\n  \twrite_stars(na.tif, \"na.tif\")\n  \twrite_stars(na.tif, \"na.tif\", NA_value = -999)\n  \tna.tif = read_stars(system.file(\"tif/na.tif\", package = \"stars\"), NA_value = -999)\n  \twrite_stars(na.tif, \"na.tif\")\n  \twrite_stars(na.tif, \"na.tif\", NA_value = -999)\n  \tna.tif = read_stars(system.file(\"tif/na.tif\", package = \"stars\"), NA_value = -999, proxy = TRUE)\n  \twrite_stars(na.tif, \"na.tif\")\n  \twrite_stars(na.tif, \"na.tif\", NA_value = -999)\n  }\n  # https://github.com/mtennekes/tmap/issues/368\n  if (utils::packageVersion(\"stars\") > \"0.4-0\") {\n    lc = system.file('tif/lc.tif', package = 'stars')\n    if (lc != \"\") {\n\t    r = read_stars(lc, RAT = \"Land Cover Class\")\n\t    r <- droplevels(r)\n    }\n  }\n}\n\nr = gdal_read(tif)\ngt = c(0,1,0,0,0,1)\ngdal_inv_geotransform(gt)\nrc = expand.grid(x=1:3, y = 1:3)\n#(xy = xy_from_colrow(rc, gt))\n#xy_from_colrow(xy, gt, inverse = TRUE)\ncrs <- gdal_crs(tif)\n\ntry(gdal_metadata(\"foo\"))\ngdal_metadata(tif)\n\nsuppressMessages(\nsuppressWarnings(\nif (require(stars, quietly = TRUE)) {\n\tp = normalizePath(system.file(\"nc/ones.zarr.zip\", package = \"sf\"))\n\tz = paste0('ZARR:/vsizip/\"', p, '\"/ones.zarr')\n\td = try(gdal_utils(\"mdiminfo\", z), silent = TRUE)\n\tif (!inherits(d, \"try-error\")) {\n\t\tprint(d)\n\t\tcat(\"\\n\")\n\t}\n\te = try(read_stars(z, normalize_path = FALSE), silent = TRUE)\n\tf = try(read_mdim(z, normalize_path = FALSE), silent = TRUE)\n\tif (inherits(e, \"try-error\") || inherits(f, \"try-error\")) {\n\t\tprint(\"Cannot read blosc-compressed Zarr file: blosc not supported?\")\n\t} else { \n\t\tprint(e)\n\t\tprint(f)\n\t}\n}\n))\n"
  },
  {
    "path": "tests/stars.Rout.save",
    "content": "\nR version 4.5.2 (2025-10-31) -- \"[Not] Part in a Rumble\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-pc-linux-gnu\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> \n> tif = system.file(\"tif/geomatrix.tif\", package = \"sf\")\n> \n> gdal_metadata(tif)\n[1] \"AREA_OR_POINT=Point\"\n> gdal_metadata(tif, NA_character_)\n[1] \"IMAGE_STRUCTURE\"     \"DERIVED_SUBDATASETS\" \"\"                   \n> try(gdal_metadata(tif, \"wrongDomain\")) \nError in gdal_metadata(tif, \"wrongDomain\") : \n  domain_item[1] not found in available metadata domains\n> gdal_metadata(tif, c(\"IMAGE_STRUCTURE\"))\n$INTERLEAVE\n[1] \"BAND\"\n\nattr(,\"class\")\n[1] \"gdal_metadata\"\n> try(length(gdal_metadata(tif, c(\"DERIVED_SUBDATASETS\")))) # fails on Fedora 26\n[1] 2\n> \n> if (require(stars, quietly = TRUE)) {\n+   tif = system.file(\"tif/geomatrix.tif\", package = \"sf\")\n+   r = read_stars(tif)\n+   d = (st_dimensions(r))\n+   gt =  c(1841001.75, 1.5, -5, 1144003.25, -5, -1.5)\n+   x1 = st_as_sfc(d, as_points = TRUE, use_cpp = TRUE, geotransform = gt)\n+   x2 = st_as_sfc(d, as_points = TRUE, use_cpp = FALSE, geotransform = gt)\n+   print(identical(x1, x2))\n+   y1 = st_as_sfc(d, as_points = FALSE, use_cpp = TRUE, geotransform = gt)\n+   y2 = st_as_sfc(d, as_points = FALSE, use_cpp = FALSE, geotransform = gt)\n+   print(identical(y1, y2))\n+ \n+   # rectilinear grid:\n+   m = matrix(1:20, nrow = 5, ncol = 4)\n+   x = c(0,0.5,1,2,4,5)\n+   y = c(0.3,0.5,1,2,2.2)\n+   r = st_as_stars(list(m = m), dimensions = st_dimensions(x = x, y = y, .raster = c(\"x\", \"y\")))\n+   print(st_as_sfc(st_dimensions(r), as_points = TRUE))\n+   print(st_as_sfc(st_dimensions(r), as_points = FALSE))\n+ \n+   # curvilinear grid:\n+   lon = st_as_stars(matrix(1:5, 4, 5, byrow = TRUE))\n+   lat = st_as_stars(matrix(1:4, 4, 5))\n+   ll = c(X1 = lon, X2 = lat)\n+   curv = st_as_stars(st_as_stars(t(m)), curvilinear = setNames(ll, c(\"X1\", \"X2\")))\n+   print(st_as_sfc(st_dimensions(curv), as_points = TRUE))\n+   print(st_as_sfc(st_dimensions(curv), as_points = FALSE))\n+ \n+   demo(nc, echo = FALSE, ask = FALSE)\n+   print(x <- st_rasterize(nc)) # default grid:\n+   print(p <- st_as_sf(x, as_points = FALSE)) # polygonize: follow raster boundaries\n+   print(p <- st_as_sf(x, as_points = FALSE, use_integer = TRUE)) # polygonize integers: follow raster boundaries\n+   print(try(p <- st_as_sf(x, as_points = TRUE))) # polygonize: contour, requies GDAL >= 2.4.0\n+   if (utils::packageVersion(\"stars\") >= \"0.2-1\") {\n+     write_stars(read_stars(tif), tempfile(fileext = \".tif\"))\n+     write_stars(read_stars(tif, proxy = TRUE), tempfile(fileext = \".tif\"))\n+     write_stars(read_stars(tif, proxy = TRUE), tempfile(fileext = \".tif\"), chunk_size = c(200,200))\n+   \tna.tif = read_stars(system.file(\"tif/na.tif\", package = \"stars\"))\n+   \twrite_stars(na.tif, \"na.tif\")\n+   \twrite_stars(na.tif, \"na.tif\", NA_value = -999)\n+   \tna.tif = read_stars(system.file(\"tif/na.tif\", package = \"stars\"), NA_value = -999)\n+   \twrite_stars(na.tif, \"na.tif\")\n+   \twrite_stars(na.tif, \"na.tif\", NA_value = -999)\n+   \tna.tif = read_stars(system.file(\"tif/na.tif\", package = \"stars\"), NA_value = -999, proxy = TRUE)\n+   \twrite_stars(na.tif, \"na.tif\")\n+   \twrite_stars(na.tif, \"na.tif\", NA_value = -999)\n+   }\n+   # https://github.com/mtennekes/tmap/issues/368\n+   if (utils::packageVersion(\"stars\") > \"0.4-0\") {\n+     lc = system.file('tif/lc.tif', package = 'stars')\n+     if (lc != \"\") {\n+ \t    r = read_stars(lc, RAT = \"Land Cover Class\")\n+ \t    r <- droplevels(r)\n+     }\n+   }\n+ }\n[1] TRUE\n[1] TRUE\nGeometry set for 20 features \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 0.25 ymin: 0.4 xmax: 4.5 ymax: 2.1\nCRS:           NA\nFirst 5 geometries:\nPOINT (0.25 0.4)\nPOINT (0.75 0.4)\nPOINT (1.5 0.4)\nPOINT (3 0.4)\nPOINT (4.5 0.4)\nGeometry set for 20 features \nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0 ymin: 0.3 xmax: 5 ymax: 2.2\nCRS:           NA\nFirst 5 geometries:\nPOLYGON ((0 0.3, 0.5 0.3, 0.5 0.5, 0 0.5, 0 0.3))\nPOLYGON ((0.5 0.3, 1 0.3, 1 0.5, 0.5 0.5, 0.5 0...\nPOLYGON ((1 0.3, 2 0.3, 2 0.5, 1 0.5, 1 0.3))\nPOLYGON ((2 0.3, 4 0.3, 4 0.5, 2 0.5, 2 0.3))\nPOLYGON ((4 0.3, 5 0.3, 5 0.5, 4 0.5, 4 0.3))\nGeometry set for 20 features \nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: 1 ymin: 1 xmax: 5 ymax: 4\nGeodetic CRS:  WGS 84 (CRS84)\nFirst 5 geometries:\nPOINT (1 1)\nPOINT (1 2)\nPOINT (1 3)\nPOINT (1 4)\nPOINT (2 1)\nGeometry set for 20 features \nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: 0.5 ymin: 0.5 xmax: 5.5 ymax: 4.5\nGeodetic CRS:  WGS 84 (CRS84)\nFirst 5 geometries:\nPOLYGON ((0.5 0.5, 0.5 1.5, 1.5 1.5, 1.5 0.5, 0...\nPOLYGON ((0.5 1.5, 0.5 2.5, 1.5 2.5, 1.5 1.5, 0...\nPOLYGON ((0.5 2.5, 0.5 3.5, 1.5 3.5, 1.5 2.5, 0...\nPOLYGON ((0.5 3.5, 0.5 4.5, 1.5 4.5, 1.5 3.5, 0...\nPOLYGON ((1.5 0.5, 1.5 1.5, 2.5 1.5, 2.5 0.5, 1...\nstars object with 2 dimensions and 12 attributes\nattribute(s):\n                Min.   1st Qu.    Median         Mean   3rd Qu.      Max.   NAs\nAREA           0.042     0.108     0.142 1.451932e-01     0.181     0.241 30904\nPERIMETER      0.999     1.461     1.716 1.786110e+00     2.004     3.640 30904\nCNTY_       1825.000  1907.000  1989.000 1.998403e+03  2085.000  2241.000 30904\nCNTY_ID     1825.000  1907.000  1989.000 1.998403e+03  2085.000  2241.000 30904\nFIPSNO     37001.000 37049.000 37101.000 3.710042e+04 37153.000 37199.000 30904\nCRESS_ID       1.000    25.000    51.000 5.071206e+01    77.000   100.000 30904\nBIR74        248.000  1323.000  2648.000 3.791637e+03  4139.000 21588.000 30904\nSID74          0.000     3.000     5.000 7.891985e+00    10.000    44.000 30904\nNWBIR74        1.000   297.000   844.000 1.246210e+03  1396.000  8027.000 30904\nBIR79        319.000  1606.000  3108.000 4.852046e+03  5400.000 30757.000 30904\nSID79          0.000     3.000     6.000 9.584098e+00    13.000    57.000 30904\nNWBIR79        3.000   360.000  1058.000 1.604642e+03  1524.000 11631.000 30904\ndimension(s):\n  from  to offset    delta refsys point x/y\nx    1 461 -84.32  0.01925  NAD27 FALSE [x]\ny    1 141  36.59 -0.01925  NAD27 FALSE [y]\nSimple feature collection with 34097 features and 12 fields\nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: -84.32385 ymin: 33.87563 xmax: -75.45034 ymax: 36.58965\nGeodetic CRS:  NAD27\nFirst 10 features:\n    AREA PERIMETER CNTY_ CNTY_ID FIPSNO CRESS_ID BIR74 SID74 NWBIR74 BIR79\n1  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n2  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n3  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n4  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n5  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n6  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n7  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n8  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n9  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n10 0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n   SID79 NWBIR79                       geometry\n1      0      19 POLYGON ((-81.66757 36.5896...\n2      0      19 POLYGON ((-81.64833 36.5896...\n3      0      19 POLYGON ((-81.62908 36.5896...\n4      0      19 POLYGON ((-81.60983 36.5896...\n5      0      19 POLYGON ((-81.59058 36.5896...\n6      0      19 POLYGON ((-81.57133 36.5896...\n7      0      19 POLYGON ((-81.55208 36.5896...\n8      0      19 POLYGON ((-81.53283 36.5896...\n9      0      19 POLYGON ((-81.51359 36.5896...\n10     0      19 POLYGON ((-81.49434 36.5896...\nSimple feature collection with 34097 features and 12 fields\nGeometry type: POLYGON\nDimension:     XY\nBounding box:  xmin: -84.32385 ymin: 33.87563 xmax: -75.45034 ymax: 36.58965\nGeodetic CRS:  NAD27\nFirst 10 features:\n    AREA PERIMETER CNTY_ CNTY_ID FIPSNO CRESS_ID BIR74 SID74 NWBIR74 BIR79\n1  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n2  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n3  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n4  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n5  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n6  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n7  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n8  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n9  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n10 0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n   SID79 NWBIR79                       geometry\n1      0      19 POLYGON ((-81.66757 36.5896...\n2      0      19 POLYGON ((-81.64833 36.5896...\n3      0      19 POLYGON ((-81.62908 36.5896...\n4      0      19 POLYGON ((-81.60983 36.5896...\n5      0      19 POLYGON ((-81.59058 36.5896...\n6      0      19 POLYGON ((-81.57133 36.5896...\n7      0      19 POLYGON ((-81.55208 36.5896...\n8      0      19 POLYGON ((-81.53283 36.5896...\n9      0      19 POLYGON ((-81.51359 36.5896...\n10     0      19 POLYGON ((-81.49434 36.5896...\nSimple feature collection with 34097 features and 12 fields\nGeometry type: POINT\nDimension:     XY\nBounding box:  xmin: -84.31423 ymin: 33.88525 xmax: -75.45997 ymax: 36.58003\nGeodetic CRS:  NAD27\nFirst 10 features:\n    AREA PERIMETER CNTY_ CNTY_ID FIPSNO CRESS_ID BIR74 SID74 NWBIR74 BIR79\n1  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n2  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n3  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n4  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n5  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n6  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n7  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n8  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n9  0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n10 0.114     1.442  1825    1825  37009        5  1091     1      10  1364\n   SID79 NWBIR79                   geometry\n1      0      19 POINT (-81.65795 36.58003)\n2      0      19  POINT (-81.6387 36.58003)\n3      0      19 POINT (-81.61945 36.58003)\n4      0      19  POINT (-81.6002 36.58003)\n5      0      19 POINT (-81.58096 36.58003)\n6      0      19 POINT (-81.56171 36.58003)\n7      0      19 POINT (-81.54246 36.58003)\n8      0      19 POINT (-81.52321 36.58003)\n9      0      19 POINT (-81.50396 36.58003)\n10     0      19 POINT (-81.48471 36.58003)\n\n\n\n\n> \n> r = gdal_read(tif)\n> gt = c(0,1,0,0,0,1)\n> gdal_inv_geotransform(gt)\n[1] 0 1 0 0 0 1\n> rc = expand.grid(x=1:3, y = 1:3)\n> #(xy = xy_from_colrow(rc, gt))\n> #xy_from_colrow(xy, gt, inverse = TRUE)\n> crs <- gdal_crs(tif)\n> \n> try(gdal_metadata(\"foo\"))\n[1] NA\n> gdal_metadata(tif)\n[1] \"AREA_OR_POINT=Point\"\n> \n> suppressMessages(\n+ suppressWarnings(\n+ if (require(stars, quietly = TRUE)) {\n+ \tp = normalizePath(system.file(\"nc/ones.zarr.zip\", package = \"sf\"))\n+ \tz = paste0('ZARR:/vsizip/\"', p, '\"/ones.zarr')\n+ \td = try(gdal_utils(\"mdiminfo\", z), silent = TRUE)\n+ \tif (!inherits(d, \"try-error\")) {\n+ \t\tprint(d)\n+ \t\tcat(\"\\n\")\n+ \t}\n+ \te = try(read_stars(z, normalize_path = FALSE), silent = TRUE)\n+ \tf = try(read_mdim(z, normalize_path = FALSE), silent = TRUE)\n+ \tif (inherits(e, \"try-error\") || inherits(f, \"try-error\")) {\n+ \t\tprint(\"Cannot read blosc-compressed Zarr file: blosc not supported?\")\n+ \t} else { \n+ \t\tprint(e)\n+ \t\tprint(f)\n+ \t}\n+ }\n+ ))\n{\n  \"type\": \"group\",\n  \"driver\": \"Zarr\",\n  \"name\": \"/\",\n  \"arrays\": {\n    \"ones\": {\n      \"datatype\": \"Int32\",\n      \"dimensions\": [\n        {\n          \"name\": \"dim0\",\n          \"full_name\": \"dim0\",\n          \"size\": 100\n        },\n        {\n          \"name\": \"dim1\",\n          \"full_name\": \"dim1\",\n          \"size\": 100\n        }\n      ],\n      \"dimension_size\": [\n        100,\n        100\n      ],\n      \"block_size\": [\n        50,\n        50\n      ],\n      \"nodata_value\": 0,\n      \"structural_info\": {\n        \"COMPRESSOR\": \"{ \\\"blocksize\\\": 0, \\\"clevel\\\": 5, \\\"cname\\\": \\\"lz4\\\", \\\"id\\\": \\\"blosc\\\", \\\"shuffle\\\": 1 }\"\n      }\n    }\n  }\n}[1] \"{\\n  \\\"type\\\": \\\"group\\\",\\n  \\\"driver\\\": \\\"Zarr\\\",\\n  \\\"name\\\": \\\"/\\\",\\n  \\\"arrays\\\": {\\n    \\\"ones\\\": {\\n      \\\"datatype\\\": \\\"Int32\\\",\\n      \\\"dimensions\\\": [\\n        {\\n          \\\"name\\\": \\\"dim0\\\",\\n          \\\"full_name\\\": \\\"dim0\\\",\\n          \\\"size\\\": 100\\n        },\\n        {\\n          \\\"name\\\": \\\"dim1\\\",\\n          \\\"full_name\\\": \\\"dim1\\\",\\n          \\\"size\\\": 100\\n        }\\n      ],\\n      \\\"dimension_size\\\": [\\n        100,\\n        100\\n      ],\\n      \\\"block_size\\\": [\\n        50,\\n        50\\n      ],\\n      \\\"nodata_value\\\": 0,\\n      \\\"structural_info\\\": {\\n        \\\"COMPRESSOR\\\": \\\"{ \\\\\\\"blocksize\\\\\\\": 0, \\\\\\\"clevel\\\\\\\": 5, \\\\\\\"cname\\\\\\\": \\\\\\\"lz4\\\\\\\", \\\\\\\"id\\\\\\\": \\\\\\\"blosc\\\\\\\", \\\\\\\"shuffle\\\\\\\": 1 }\\\"\\n      }\\n    }\\n  }\\n}\"\n\nstars object with 2 dimensions and 1 attribute\nattribute(s):\n           Min. 1st Qu. Median Mean 3rd Qu. Max.\nones.zarr     1       1      1    1       1    1\ndimension(s):\n  from  to offset delta x/y\nx    1 100      0     1 [x]\ny    1 100    100    -1 [y]\nstars object with 2 dimensions and 1 attribute\nattribute(s):\n      Min. 1st Qu. Median Mean 3rd Qu. Max.\nones     1       1      1    1       1    1\ndimension(s):\n     from  to offset delta x/y\ndim1    1 100    0.5     1 [x]\ndim0    1 100    0.5     1 [y]\n> \n> proc.time()\n   user  system elapsed \n  1.948   4.046   1.515 \n"
  },
  {
    "path": "tests/test-by-element.R",
    "content": "suppressPackageStartupMessages(library(sf))\n\n# setup\nb0 = st_polygon(list(rbind(c(0,0), c(2,0), c(2,2), c(0,2), c(0,0))))\nb1 = st_polygon(list(rbind(c(1,1), c(3,1), c(3,3), c(1,3), c(1,1))))\nb2 = st_polygon(list(rbind(c(5,5), c(6,5), c(6,6), c(5,6), c(5,5))))\na0 = st_polygon(list(rbind(c(0.5,0.5), c(1.5,0.5), c(1.5,1.5), c(0.5,1.5), c(0.5,0.5))))\na1 = st_polygon(list(rbind(c(1.5,1.5), c(2.5,1.5), c(2.5,2.5), c(1.5,2.5), c(1.5,1.5))))\na2 = st_polygon(list(rbind(c(5.1,5.1), c(5.9,5.1), c(5.9,5.9), c(5.1,5.9), c(5.1,5.1))))\nx = st_sfc(b0, b1, b2)\ny = st_sfc(a0, a1, a2)\n\n# predicates\nr = st_intersects(x, y, by_element = TRUE)\nstopifnot(is.logical(r), length(r) == 3, all(r))\nr = st_contains(x, y, by_element = TRUE)\nstopifnot(is.logical(r), all(r))\nr = !st_intersects(st_sfc(b0, b2), st_sfc(b2, b0), by_element = TRUE)\nstopifnot(is.logical(r), all(r))\n\n# relate\nr = st_relate(x, y, by_element = TRUE)\nstopifnot(is.character(r), length(r) == 3, all(nchar(r) == 9))\nr = st_relate(x, y, pattern = \"T********\", by_element = TRUE)\nstopifnot(is.logical(r), length(r) == 3)\n\n# geometric ops: correctness\nr = st_intersection(x, y, by_element = TRUE)\nm = st_sfc(st_intersection(b0, a0), st_intersection(b1, a1), st_intersection(b2, a2))\nstopifnot(inherits(r, \"sfc\"), length(r) == 3)\nstopifnot(all(st_equals(r, m, sparse = FALSE)[cbind(1:3, 1:3)]))\n\n# geometric ops: empty result for disjoint pair\nr = st_intersection(st_sfc(b0), st_sfc(b2), by_element = TRUE)\nstopifnot(st_is_empty(r[1]))\n\n# difference and sym_difference\nr = st_difference(st_sfc(b0), st_sfc(a0), by_element = TRUE)\nstopifnot(st_equals(r[[1]], st_difference(b0, a0), sparse = FALSE)[1,1])\nr = st_sym_difference(st_sfc(b0), st_sfc(a0), by_element = TRUE)\nstopifnot(st_equals(r[[1]], st_sym_difference(b0, a0), sparse = FALSE)[1,1])\n\n# unequal lengths error\ntry(st_intersects(st_sfc(b0, b1), st_sfc(a0), by_element = TRUE))\ntry(st_intersection(st_sfc(b0, b1), st_sfc(a0), by_element = TRUE))\n\n# distance: non-POINT geometries\nl = st_sfc(st_linestring(rbind(c(0,0), c(1,0))), st_linestring(rbind(c(0,1), c(1,1))))\nm = st_sfc(st_linestring(rbind(c(0,2), c(1,2))), st_linestring(rbind(c(0,3), c(1,3))))\nd = st_distance(l, m, by_element = TRUE)\nstopifnot(all.equal(as.numeric(d), c(2, 2)))\n\n# defaults unchanged\nstopifnot(length(st_intersection(x, x)) >= 3)\nstopifnot(inherits(st_intersects(x, y), \"sgbp\"))"
  },
  {
    "path": "tests/test-by-element.Rout.save",
    "content": "\nR version 4.5.3 (2026-03-11) -- \"Reassured Reassurer\"\nCopyright (C) 2026 The R Foundation for Statistical Computing\nPlatform: x86_64-pc-linux-gnu\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> \n> # setup\n> b0 = st_polygon(list(rbind(c(0,0), c(2,0), c(2,2), c(0,2), c(0,0))))\n> b1 = st_polygon(list(rbind(c(1,1), c(3,1), c(3,3), c(1,3), c(1,1))))\n> b2 = st_polygon(list(rbind(c(5,5), c(6,5), c(6,6), c(5,6), c(5,5))))\n> a0 = st_polygon(list(rbind(c(0.5,0.5), c(1.5,0.5), c(1.5,1.5), c(0.5,1.5), c(0.5,0.5))))\n> a1 = st_polygon(list(rbind(c(1.5,1.5), c(2.5,1.5), c(2.5,2.5), c(1.5,2.5), c(1.5,1.5))))\n> a2 = st_polygon(list(rbind(c(5.1,5.1), c(5.9,5.1), c(5.9,5.9), c(5.1,5.9), c(5.1,5.1))))\n> x = st_sfc(b0, b1, b2)\n> y = st_sfc(a0, a1, a2)\n> \n> # predicates\n> r = st_intersects(x, y, by_element = TRUE)\n> stopifnot(is.logical(r), length(r) == 3, all(r))\n> r = st_contains(x, y, by_element = TRUE)\n> stopifnot(is.logical(r), all(r))\n> r = !st_intersects(st_sfc(b0, b2), st_sfc(b2, b0), by_element = TRUE)\n> stopifnot(is.logical(r), all(r))\n> \n> # relate\n> r = st_relate(x, y, by_element = TRUE)\n> stopifnot(is.character(r), length(r) == 3, all(nchar(r) == 9))\n> r = st_relate(x, y, pattern = \"T********\", by_element = TRUE)\n> stopifnot(is.logical(r), length(r) == 3)\n> \n> # geometric ops: correctness\n> r = st_intersection(x, y, by_element = TRUE)\n> m = st_sfc(st_intersection(b0, a0), st_intersection(b1, a1), st_intersection(b2, a2))\n> stopifnot(inherits(r, \"sfc\"), length(r) == 3)\n> stopifnot(all(st_equals(r, m, sparse = FALSE)[cbind(1:3, 1:3)]))\n> \n> # geometric ops: empty result for disjoint pair\n> r = st_intersection(st_sfc(b0), st_sfc(b2), by_element = TRUE)\n> stopifnot(st_is_empty(r[1]))\n> \n> # difference and sym_difference\n> r = st_difference(st_sfc(b0), st_sfc(a0), by_element = TRUE)\n> stopifnot(st_equals(r[[1]], st_difference(b0, a0), sparse = FALSE)[1,1])\n> r = st_sym_difference(st_sfc(b0), st_sfc(a0), by_element = TRUE)\n> stopifnot(st_equals(r[[1]], st_sym_difference(b0, a0), sparse = FALSE)[1,1])\n> \n> # unequal lengths error\n> try(st_intersects(st_sfc(b0, b1), st_sfc(a0), by_element = TRUE))\nError in st_geos_binop(\"intersects\", x, y, sparse = sparse, prepared = prepared,  : \n  length(x) == length(y) is not TRUE\n> try(st_intersection(st_sfc(b0, b1), st_sfc(a0), by_element = TRUE))\nError in geos_op2_geom(\"intersection\", x, y, ...) : \n  length(x) == length(y) is not TRUE\n> \n> # distance: non-POINT geometries\n> l = st_sfc(st_linestring(rbind(c(0,0), c(1,0))), st_linestring(rbind(c(0,1), c(1,1))))\n> m = st_sfc(st_linestring(rbind(c(0,2), c(1,2))), st_linestring(rbind(c(0,3), c(1,3))))\n> d = st_distance(l, m, by_element = TRUE)\n> stopifnot(all.equal(as.numeric(d), c(2, 2)))\n> \n> # defaults unchanged\n> stopifnot(length(st_intersection(x, x)) >= 3)\n> stopifnot(inherits(st_intersects(x, y), \"sgbp\"))\n> \n> proc.time()\n   user  system elapsed \n  0.548   1.286   0.421 \n"
  },
  {
    "path": "tests/testthat/test-aw.R",
    "content": "test_that(\"st_interpolate_aw\", {\nsq = function(x, y, s=1) st_polygon(list(rbind(c(x,y),c(x+s,y),c(x+s,y+s),c(x,y+s),c(x,y))))\nsq2 = function(x, y) st_polygon(list(rbind(c(x,y),c(x+1,y),c(x+1,y+2),c(x,y+2),c(x,y))))\nx = st_sf(a = 1:2, b = c(10,1), geom = st_sfc(sq(2,3), sq(2,4)))\n# plot(st_geometry(x))\ny1 = st_sfc(sq2(2, 3))\n# plot(y, add = TRUE, lty = 2, lwd = 3)\nst_agr(x) = \"constant\"\nexpect_equal(st_interpolate_aw(x, y1, extensive = TRUE)$a,  3)\nexpect_equal(st_interpolate_aw(x, y1, extensive = FALSE)$a, 1.5)\ny2 = st_sf(a = 5, st_sfc(sq2(1.5, 2.5)))\nst_agr(y2) = \"constant\"\n# plot(y, add = TRUE, lty = 3, lwd = 3)\nst_interpolate_aw(x, y2, extensive = TRUE)\nexpect_equal(st_interpolate_aw(x, y2, extensive = TRUE)$a, 1)\nexpect_equal(st_interpolate_aw(x, y2, extensive = FALSE)$a, 1 + 1/3)\nexpect_equal(st_interpolate_aw(x, y2, extensive = FALSE, include_non_intersected = TRUE)$a, 0.5)\nexpect_equal(st_interpolate_aw(x, y2, extensive = TRUE, weights = \"a\")$b, 11)\nexpect_error(st_interpolate_aw(x, y2, extensive = FALSE, weights = \"a\"))\nexpect_error(st_interpolate_aw(x, y2, extensive = TRUE, include_non_intersected = TRUE, weights = \"a\"), \"include\")\n\nt1 = sq(0, 1)\nt2 = sq(0, 0, 2)\nt = st_difference(t2, t1)\nto = st_sf(a = c(9,1), geom = st_sfc(t1,t))\nx = st_sf(s = 20, geom = st_sfc(sq(0, 0, 2)))\nst_agr(to) = \"constant\"\nexpect_equal(st_interpolate_aw(x, to, extensive = TRUE, weights = \"a\")$s, c(18,2))\n\nx = st_sf(s = 20, geom = st_sfc(sq(0, .5, 1)))\nexpect_equal(st_interpolate_aw(x, to, extensive = TRUE, weights = \"a\")$s, c(4.5/(4.5+1/6)*20, (1/6)/(4.5+1/6)*20))\n\n\nx = st_sf(s = 20, geom = st_sfc(sq(-.5, .5, 1)))\nexpect_equal(st_interpolate_aw(x, to, extensive = TRUE, weights = \"a\")$s, c(4.5/(4.5+1/6)*20, (1/6)/(4.5+1/6)*20))\n\nx = st_sf(s = 20, geom = st_sfc(sq(-1, .5, 1)))\nexpect_equal(st_interpolate_aw(x, to, extensive = TRUE, weights = \"a\")$s, c(NA_real_,NA_real_))\n\ngeom = st_sfc(\n  sq(0, 0, 1),\n  sq(1, 0, 1),\n  sq(0, 1, 1),\n  sq(1, 1, 1))\nx = st_sf(s = 1:4, geom = geom)\nexpect_equal(st_interpolate_aw(x, to, extensive = TRUE, weights = \"a\")$s, c(3,7))\n})\n"
  },
  {
    "path": "tests/testthat/test-bbox.R",
    "content": "test_that(\"st_bbox\", {\n  p1 = st_point(1:3)\n  bb = st_bbox(p1)\n  expect_true(all(st_bbox(p1) == c(1,2,1,2)))\n  expect_true(all(names(st_bbox(p1)) == c(\"xmin\",\"ymin\",\"xmax\",\"ymax\")))\n  x = st_geometrycollection(list(st_point(1:2),st_linestring(matrix(1:4,2))))\n  expect_true(all(st_bbox(x) == c(1,2,2,4)))\n  expect_true(all(names(st_bbox(x)) == c(\"xmin\",\"ymin\",\"xmax\",\"ymax\")))\n  x = st_sf(a = 1, geom = st_sfc(x))\n  expect_true(all(st_bbox(x) == c(1,2,2,4)))\n  bb = st_bbox(x)\n  expect_identical(st_bbox(bb), bb)\n})\n"
  },
  {
    "path": "tests/testthat/test-collection_extract.R",
    "content": "pt <- st_point(c(1, 0))\nls <- st_linestring(matrix(c(4, 3, 0, 0), ncol = 2))\npoly1 <- st_polygon(list(matrix(c(5.5, 7, 7, 6, 5.5, 0, 0, -0.5, -0.5, 0), ncol = 2)))\npoly2 <- st_polygon(list(matrix(c(6.6, 8, 8, 7, 6.6, 1, 1, 1.5, 1.5, 1), ncol = 2)))\nmultipoly <- st_multipolygon(list(poly1, poly2))\n\ni <- st_geometrycollection(list(pt, ls, poly1, poly2))\n\nj <- st_geometrycollection(list(pt, ls, poly1, poly2, multipoly))\n\n## A GEOMETRYCOLLECTION\naa <- rbind(st_sf(a=1, geom = st_sfc(i)),\n\t\t\tst_sf(a=2, geom = st_sfc(j)))\n\n##\n## A GEOMETRY of single types\nbb <- rbind(\n\tst_sf(a = 1, geom = st_sfc(pt)),\n\tst_sf(a = 2, geom = st_sfc(ls)),\n\tst_sf(a = 3, geom = st_sfc(poly1)),\n\tst_sf(a = 4, geom = st_sfc(multipoly))\n)\n\n## A GEOMETRY of mixed single types and GEOMETRYCOLLECTIONS\ncc <- rbind(aa, bb)\n\ntest_that(\"st_collection_extract works with sfg objects\", {\n\texpect_s3_class(st_collection_extract(i, \"POLYGON\"), \"sfc_POLYGON\")\n\texpect_s3_class(st_collection_extract(j, \"POLYGON\"), \"sfc_MULTIPOLYGON\")\n\texpect_s3_class(st_collection_extract(i, \"POINT\"), \"POINT\")\n\texpect_s3_class(st_collection_extract(i, \"LINESTRING\"), \"LINESTRING\")\n})\n\ntest_that(\"st_collection_extract works with sfc objects\", {\n\texpect_s3_class(st_collection_extract(st_geometry(aa), \"POLYGON\"), \"sfc_MULTIPOLYGON\")\n\texpect_s3_class(st_collection_extract(st_geometry(aa), \"LINESTRING\"), \"sfc_LINESTRING\")\n\texpect_s3_class(st_collection_extract(st_geometry(aa), \"POINT\"), \"sfc_POINT\")\n\texpect_s3_class(st_collection_extract(st_geometry(bb), \"POINT\"), \"sfc_POINT\")\n\texpect_s3_class(st_collection_extract(st_geometry(cc), \"POLYGON\"), \"sfc_MULTIPOLYGON\")\n})\n\n\ntest_that(\"st_collection_extract works with sf objects\", {\n\texpect_s3_class(st_geometry(st_collection_extract(aa, \"POLYGON\")), \"sfc_MULTIPOLYGON\")\n\texpect_s3_class(st_geometry(st_collection_extract(aa, \"LINESTRING\")), \"sfc_LINESTRING\")\n\texpect_s3_class(st_geometry(st_collection_extract(aa, \"POINT\")), \"sfc_POINT\")\n\texpect_s3_class(st_geometry(st_collection_extract(bb, \"POLYGON\")), \"sfc_MULTIPOLYGON\")\n\texpect_s3_class(st_geometry(st_collection_extract(cc, \"POLYGON\")), \"sfc_MULTIPOLYGON\")\n})\n\ntest_that(\"st_collection_extract behaves with unexpected inputs\", {\n\texpect_warning(st_collection_extract(poly1, \"POLYGON\"),\n\t\t\t\t   \"x is already of type POLYGON\")\n\texpect_error(st_collection_extract(st_sfc(pt), \"POLYGON\"),\n\t\t\t\t \"x is of singular geometry type that is different to supplied type\")\n\texpect_error(st_collection_extract(st_sf(a = \"a\", geom = st_sfc(pt)), \"POLYGON\"),\n\t\t\t\t \"x is of singular geometry type that is different to supplied type\")\n\t## Returns empty geometry\n\texpect_warning(st_collection_extract(st_sfc(pt, ls), \"POLYGON\"),\n\t\t\t\t   \"x contains no geometries of specified type\")\n\texpect_warning(st_collection_extract(st_sf(a = c(\"a\", \"b\"), geom = st_sfc(ls, pt)),\n\t\t\t\t\t\t\t\t\t\t\"POLYGON\"),\n\t\t\t\t   \"x contains no geometries of specified type\")\n\texpect_warning(zero_len <- st_collection_extract(st_geometrycollection(list(pt, ls)), \"POLYGON\"),\n\t\"x contains no geometries of specified type\")\n\texpect_length(zero_len, 0L)\n\texpect_s3_class(zero_len, \"sfg\")\n\texpect_true(st_is(zero_len, \"POLYGON\"))\n})\n\n"
  },
  {
    "path": "tests/testthat/test-crs.R",
    "content": "test_that(\"st_crs works\", {\n  nc1 = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), \"nc\", crs = 4267, quiet = TRUE)\n  nc2 = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), \"nc\", quiet = TRUE)\n  nc3 = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), \"nc\", crs = NA, quiet = TRUE)\n  crs_4267 <- st_crs(4267)\n  expect_equal(st_crs(nc1)[1:2], crs_4267[1:2])\n  # expect_equal(st_crs(nc2)[1:2], crs_4267[1:2]) \n  expect_equal(st_crs(nc3), NA_crs_)\n  expect_equal(st_set_crs(nc3, 4267) |> st_crs(), crs_4267)\n  # expect_equal(st_crs(nc1)[1:2], st_crs(nc2)[1:2])\n\n  expect_warning(st_crs(nc2) <- 3857, \"replacing crs does not reproject data\")\n  expect_silent(st_crs(nc2) <- 3857)\n  #expect_warning(st_crs(nc2) <- 0, \"Failed to lookup UOM CODE\") -> changes in gdal 2.2:\n  #expect_warning(st_crs(nc2) <- 0)\n  #expect_warning(st_crs(nc2) <- 1000, \"not found in EPSG\") -> changes in gdal 2.5.0\n  expect_silent(st_crs(nc1) <- st_crs(nc1))\n\n  if (sf_extSoftVersion()[[\"GDAL\"]] > \"2.2.3\") {\n    suppressWarnings(expect_error(st_crs(\"+proj=ll\"), \"invalid crs\"))\n  \t# expect_error(st_crs(\"+proj=longlat +datum=NAD26\"))\n  }\n  expect_silent(st_crs(\"+proj=longlat\"))\n  expect_silent(st_crs(\"+proj=longlat +datum=NAD27\"))\n  a <- st_crs(4326)\n  expect_silent(wkt <- st_as_text(a, pretty = TRUE))\n  expect_silent(wkt <- st_as_text(a))\n  expect_silent(b <- st_crs(wkt))\n  # expect_equal(a, b) # -> breaks on CRAN/fedora\n  expect_true(st_crs(\"+proj=longlat +ellps=WGS84 +towgs84=0,0,0,0,0,0,0 +no_defs\") != st_crs(\"+proj=longlat +datum=WGS84 +no_defs\"))\n})\n\ntest_that(\"sf_proj_info works\", {\n  expect_silent(x <- sf_proj_info(\"proj\"))\n  expect_silent(x <- sf_proj_info(\"ellps\"))\n  expect_silent(x <- sf_proj_info(\"datum\"))\n  expect_silent(x <- sf_proj_info(\"units\"))\n  expect_silent(path <- sf_proj_info(\"path\")[1])\n  expect_type(sf_proj_info(path = path), \"logical\")\n  expect_type(sf_proj_info(\"network\"), \"logical\")\n})\n\ntest_that(\"sf_proj_info works for datum files\", {\n  skip_if(sf_extSoftVersion()[[\"proj.4\"]] >= \"6.0.0\")\n  expect_silent(x <- sf_proj_info(\"have_datum_files\"))\n})\n\ntest_that(\"$.crs works\", {\n  skip_if(sf_extSoftVersion()[[\"proj.4\"]] >= \"6.0.0\")\n  expect_false(is.null(st_crs(\"+init=epsg:3857\")$epsg))\n  expect_type(st_crs(\"+init=epsg:3857\")$proj4string, \"character\")\n})\n\ntest_that(\"$.crs works with +units\", {\n  skip_if(sf_extSoftVersion()[[\"proj.4\"]] >= \"6.0.0\")\n  expect_type(st_crs(\"+init=epsg:3857 +units=m\")$b, \"double\") \n  expect_type(st_crs(\"+init=epsg:3857 +units=m\")$units, \"character\")\n})\n\ntest_that(\"$.crs works 2\", {\n  skip_if_not(sf_extSoftVersion()[[\"GDAL\"]] < \"2.5.0\" && sf_extSoftVersion()[[\"proj.4\"]] < \"6.0.0\")\n  expect_type(st_crs(\"+init=epsg:3857 +units=km\")$b, \"double\")\n  expect_type(st_crs(\"+init=epsg:3857 +units=km\")$units, \"character\")\n})\n\ntest_that(\"CRS comparison uses ellipsoid and datum (#180)\", {\n#  skip_if_not(sf_extSoftVersion()[[\"GDAL\"]] < \"2.5.0\")\n#  expect_equal(\n#    st_crs(\"+proj=tmerc +lat_0=0 +lon_0=0 +k=0.9999 +x_0=304800 +y_0=0 +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +units=m +no_defs\"),\n#    st_crs(\"+proj=tmerc +lat_0=0 +lon_0=0 +k=0.9999 +x_0=304800 +y_0=0 +datum=NAD83 +units=m +no_defs\"))\n})\n\n#test_that(\"Can create dummy crs\", {\n#    #expect_equal(st_crs(0, valid = FALSE), structure(list(epsg = 0, proj4string = \"\"), class = \"crs\"))\n#    #expect_equal(st_crs(991115, proj4text = \"+random\", valid = FALSE),\n#    #             structure(list(epsg = 991115, proj4string = \"+random\"), class = \"crs\"))\n#})\n\n#test_that(\"Warning if trying to supply proj4 with numeric\", {\n#    expect_warning(st_crs(2939, proj4text = \"+random\"), \"`proj4text` is not used to validate crs\")\n#})\n\ntest_that(\"old-style crs are repaired\", {\n  x = structure(list(proj4string = \"+proj=longlat\", epsg = 4326), class = \"crs\")\n  x_new = st_crs(x)\n  expect_warning(x$proj4string)\n})\n\ntest_that(\"sp-style CRS objects are accepted\", {\n  skip_if_not_installed(\"sp\")\n  library(sp)\n  x = CRS(\"+proj=longlat\")\n  x_crs = st_crs(\"+proj=longlat\")\n  expect_equal(x_crs$wkt, st_crs(x)$wkt)\n  comment(x) = NULL\n  expect_equal(x_crs$wkt, st_crs(x)$wkt)\n})\n\ntest_that(\"print.crs works\", {\n  x = st_crs(4326)\n  print(x)\n  x$input = NA\n  print(x)\n})\n\ntest_that(\"crs.Raster works\", {\n  skip_if_not_installed(\"raster\")\n  library(raster)\n  r = raster()\n  x = st_crs(r)\n  expect_s3_class(x, \"crs\", exact = TRUE)\n})\n"
  },
  {
    "path": "tests/testthat/test-gdal.R",
    "content": "test_that(\"st_transform works\", {\n  skip_if_not_installed(\"sp\")\n  library(sp)\n\n  s = st_sfc(st_point(c(1,1)), st_point(c(10,10)), st_point(c(5,5)), crs = 4326)\n  s1.tr = st_transform(s, 3857)\n\n  sp = as(s, \"Spatial\")\n#  sp.tr = spTransform(sp, CRS(\"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +nadgrids=@null +no_defs\")) # web mercator\n#  s2.tr = st_as_sfc(sp.tr)\n  #attr(s1.tr, \"crs\")$proj4string = \"\"\n  #attr(s2.tr, \"crs\")$proj4string = \"\"\n  st_crs(s1.tr) = NA_crs_\n#  st_crs(s2.tr) = NA_crs_\n#  if (sf_extSoftVersion()[[\"proj.4\"]] < \"5.0.0\") # FIXME:\n#    expect_equal(s1.tr, s2.tr)\n\n  toCrs = 3857\n  s1.tr = st_transform(s, toCrs)\n  #attr(s1.tr, \"crs\")$proj4string = \"\"\n  st_crs(s1.tr) = NA_crs_\n#  st_crs(s2.tr) = NA_crs_\n#  if (sf_extSoftVersion()[[\"proj.4\"]] < \"5.0.0\") # FIXME:\n#    expect_equal(s1.tr, s2.tr)\n\n  expect_silent({\n    sf.tr = st_transform(st_sf(a=1:3, s), toCrs) # for sf\n    sfg.tr = st_transform(structure(s[[1]], proj4string=\"+proj=longlat +datum=WGS84 +no_defs\"), toCrs) # sfg\n  })\n})\n\n#test_that(\"gdal can be loaded, unloaded, and loaded\", {\n#  expect_silent({\n#  unload_gdal()\n#  load_gdal()\n#  }\n#  )\n#})\n\ntest_that(\"st_wrap_dateline works\", {\n\texpect_silent(x <- st_wrap_dateline(st_sfc(st_linestring(rbind(c(-179,0),c(179,0))), crs = 4326)))\n})\n\ntest_that('gdal_subdatasets works', {\n  skip_if(sf_extSoftVersion()[[\"GDAL\"]] < \"2.1.0\")\n  skip_if(sf_extSoftVersion()[[\"GDAL\"]] >= \"2.5.0\") # FIXME:\n  skip_on_os(\"mac\") # FIXME:\n  fname = system.file(\"nc/cropped.nc\", package = \"sf\")\n  sd2 = gdal_subdatasets(fname)[[2]]\n})\n\n# context(\"gdal utils\")\ntest_that('gdal_utils work', {\n  skip_on_appveyor() # FIXME:\n  skip_if_not(Sys.getenv(\"USER\") == \"edzer\")\n  skip_if_not(sf_extSoftVersion()[[\"GDAL\"]] >= \"2.1.0\")\n\n  fname = system.file(\"nc/cropped.nc\", package = \"sf\")\n  #fname = system.file(\"tif/geomatrix.tif\", package = \"sf\")\n  info = gdal_utils(\"info\", fname, quiet = TRUE)\n  sd2 = gdal_subdatasets(fname)[[2]]\n  info = gdal_utils(\"info\", sd2, quiet = TRUE)\n  tf = tempfile()\n  tf2 = tempfile()\n  tf3 = tempfile()\n  #tf = \"foo\"\n  #gdal_utils(\"rasterize\", points, tif) -> need a good example\n  #gdal_utils(\"warp\", sd2, tf, c(\"-t_srs\", \"+proj=utm +zone=11 +datum=WGS84\"))\n  #expect_true(gdal_utils(\"warp\", sd2, tf, c(\"-t_srs\", \"+proj=utm +zone=11 +datum=WGS84\")))\n  #gdal_utils(\"warp\", sd2, tf, c(\"-t_srs\", \"+proj=utm +zone=11 +datum=WGS84\"))\n  #expect_true(gdal_utils(\"warp\", sd2, tf))\n  #expect_true(gdal_utils(\"rasterize\", sd2, tf))\n  expect_true(gdal_utils(\"translate\", sd2, tf))\n  expect_true(gdal_utils(\"vectortranslate\", sd2, tf2))\n  shp = system.file(\"shape/nc.shp\", package=\"sf\")\n  gpkg = paste0(tempfile(), \".gpkg\")\n  options = c(\"-f\", \"GPKG\", \"-overwrite\", \"-nlt\", \"PROMOTE_TO_MULTI\", \n  \t\"-oo\", \"ADJUST_TYPE=NO\", \"-doo\", \"FLATTEN_NESTED_ATTRIBUTES=NO\")\n  expect_true(gdal_utils(\"vectortranslate\", shp, gpkg, options = options))\n  expect_warning(gdal_utils(\"nearblack\", sd2, tf))\n  # create point geom:\n  points = system.file(\"gpkg/nc.gpkg\", package=\"sf\")\n  expect_true(gdal_utils(\"grid\", points, tf))\n  expect_true(gdal_utils(\"buildvrt\", sd2, tf3))\n  expect_warning(gdal_utils(\"buildvrt\", sd2, tf3, c(\"-oo\", \"FOO=BAR\"))) # fake opening options\n  expect_error(gdal_utils(\"buildvrt\", \"foo.tif\", tf3, c(\"-oo\", \"FOO=BAR\")), \"cannot open source dataset\")\n  expect_true(gdal_utils(\"demprocessing\", sd2, tf, processing = \"hillshade\"))\n  # check gdalfootprint\n  skip_if_not(sf_extSoftVersion()[[\"GDAL\"]] >= \"3.8.0\")\n  tif <- system.file(\"tif/geomatrix.tif\", package=\"sf\")\n  tf4 <- tempfile(fileext = \".gpkg\")\n  expect_true(gdal_utils(\"footprint\", tif, tf4))\n})\n\n# gdalwarp -t_srs '+proj=utm +zone=11 +datum=WGS84' -overwrite NETCDF:avhrr-only-v2.19810901.nc:anom utm11.tif\n# becomes:\n# st_gdalwarp(\"NETCDF:avhrr-only-v2.19810901.nc:anom\", \"utm11.tif\", c(\"-t_srs\", \"+proj=utm +zone=11 +datum=WGS84\"))\n\ntest_that('gdal_addo works', {\n\n    skip_on_cran()\n\n    has_overviews = function(x){\n        info = gdal_utils(source = x, quiet = TRUE)\n        grepl(\"overview\", info, ignore.case = TRUE)\n    }\n\n   has_compressed_overviews = function(x){\n        # Check if sidecar overview file has compression, x is tif path\n        path = paste0(x, \".ovr\") # overview file\n        info = gdal_utils(source = path, quiet = TRUE)\n        if(!file.exists(path))\n            return(NA)\n        grepl(\"compression\", info, ignore.case = TRUE)\n    }\n\n    # setup\n    dir = file.path(tempdir(), \"gdal_addo\")\n    dir.create(dir)\n    on.exit(unlink(dir, recursive = TRUE))  # cleanup when done\n    tif = file.path(dir, \"geomatrix.tif\")\n    file.copy(system.file(\"tif/geomatrix.tif\", package = \"sf\"),\n                           tif, overwrite = TRUE)\n\n    expect_false(has_overviews(tif))\n\n    # Default arguments\n    expect_no_error(gdal_addo(tif)) # internal overview\n    expect_true(has_overviews(tif))\n    expect_true(is.na(has_compressed_overviews(tif))) # no overview file\n\n    # Clean overviews\n    expect_no_error(gdal_addo(tif, clean = TRUE))\n    expect_false(has_overviews(tif))\n\n    # Overviews in separate file\n    expect_no_error(gdal_addo(tif, read_only = TRUE))\n    expect_false(has_compressed_overviews(tif)) # uncompressed overview file\n\n    # Clean overviews\n    expect_no_error(gdal_addo(tif, clean = TRUE))\n    expect_false(has_overviews(tif))\n\n    # Compression via config_options works\n    expect_no_error(gdal_addo(tif, read_only = TRUE,\n                              config_options = c(COMPRESS_OVERVIEW=\"LZW\")))\n    expect_true(has_compressed_overviews(tif))\n\n})\n"
  },
  {
    "path": "tests/testthat/test-geos.R",
    "content": "test_that(\"CPL_geos_is_valid works\", {\n  expect_true( sf:::CPL_geos_is_valid(\n  \tst_sfc(st_polygon(list(cbind(c(0,1,1,0,0), c(0,0,1, 1,0)))))))\n  expect_warning(\n    expect_false(sf:::CPL_geos_is_valid(\n  \tst_sfc(st_polygon(list(cbind(c(0,1,1,.5,0),c(0,0,1,-1,0))))), FALSE))\n    )\n  expect_false(st_is_valid(st_sfc(st_polygon(list(cbind(c(0,1,1,.5,0),c(0,0,1,-1,0)))))))\n  p0 = st_as_sfc(factor(\"POLYGON((0 0, 0 10, 10 0, 10 10, 0 0))\"))\n  p1 = st_as_sfc(\"POLYGON((0 0, 0 10, 10 0, 10 10, 0 0))\")\n  expect_equal(p0, p1)\n  expect_false(st_is_valid(p1))\n  expect_equal(st_is_valid(p1, reason = TRUE), \"Self-intersection[5 5]\")\n  expect_warning(st_is_valid(p1, NA_on_exception = FALSE), \"Self-intersection at or near point 5 5\")\n  expect_false(st_is_valid(p1[[1]]))\n})\n\ntest_that(\"geos ops give warnings and errors on longlat\", {\n    skip_if_not_installed(\"lwgeom\")\n    skip_if(sf_use_s2())\n\n\tnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\n\tx = nc[1:2,]\n\ty = nc[2:3,]\n\texpect_silent(st_equals(x, y))\n\texpect_silent(st_equals_exact(x, y, 0.01))\n\tl = st_sfc(st_linestring(matrix(1:10, ncol=2)), crs = st_crs(nc))\n\texpect_silent(st_polygonize(l))\n\n\texpect_message(st_intersects(x,y))\n\texpect_message(st_disjoint(x,y))\n\texpect_message(st_touches(x,y))\n\texpect_message(st_crosses(x,y))\n\texpect_message(st_within(x,y))\n\texpect_message(st_contains(x,y))\n\texpect_message(st_overlaps (x,y))\n\texpect_message(st_covers(x,y))\n\texpect_message(st_covered_by(x,y))\n\n\texpect_warning(st_buffer(x, .1))\n\texpect_warning(st_buffer(x, .1, joinStyle = \"BEVEL\"))\n\texpect_warning(st_simplify(x, dTolerance = .1))\n\texpect_warning(st_centroid(x))\n\texpect_silent(st_segmentize(l, 1e5))\n\texpect_silent(st_segmentize(l, 1e5))\n\n\texpect_silent(out <- st_segmentize(l, units::set_units(0.001, rad)))\n\texpect_silent(out <- st_segmentize(l, units::set_units(100, km)))\n\n\tif (CPL_geos_version() >= \"3.4.0\")\n\t\texpect_warning(st_triangulate(x))\n\telse\n\t\texpect_error(st_triangulate(x))\n\n\texpect_silent(st_area(x))\n\texpect_silent(st_length(l))\n\n\t# distance on long/lat:\n\tif (utils::packageVersion(\"lwgeom\") <= \"0.1-0\")\n\t\texpect_error(st_distance(x, y))\n\telse\n\t\texpect_silent(st_distance(x, y))\n})\n\ntest_that(\"st_area() works on GEOMETRY in longlat (#131)\", {\n  skip_if_not_installed(\"lwgeom\")\n  single <- list(rbind(c(0,0), c(1,0), c(1, 1), c(0,1), c(0,0))) |> st_polygon()\n  multi <- list(single + 2, single + 4) |> st_multipolygon()\n\n  w <- st_sfc(single + 0.1, multi)\n  expect_equal(st_area(w), 1:2)\n  expect_silent(st_area(st_set_crs(w, 4326))) # outcome might depend on backend used: lwgeom if proj.4 < 490, else proj.4\n})\n\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\npnc <- st_transform(nc[4:6, ], \"+proj=laea +lon_0=-90\")\ngpnc <- st_geometry(pnc)\n\nsuppressWarnings(lnc <- st_cast(pnc, \"MULTILINESTRING\"))\nglnc <- st_geometry(lnc)\n\ntest_that(\"geom operations work on sfg or sfc or sf\", {\n\texpect_silent(st_buffer(pnc, 1000))\n\texpect_silent(st_buffer(gpnc, 1000))\n\texpect_silent(st_buffer(gpnc[[1L]], 1000))\n\n\texpect_silent(st_buffer(pnc, 1000, endCapStyle = \"SQUARE\"))\n\texpect_silent(st_buffer(gpnc, 1000, joinStyle = \"BEVEL\"))\n\texpect_silent(st_buffer(gpnc[[1L]], 1000, joinStyle = \"MITRE\", mitreLimit = 0.2))\n\n\texpect_silent(st_boundary(pnc))\n\texpect_s3_class(st_boundary(gpnc), \"sfc_MULTILINESTRING\")\n\texpect_s3_class(st_boundary(gpnc[[1L]]), \"MULTILINESTRING\")\n\n\texpect_s3_class(st_convex_hull(pnc)$geometry, \"sfc_POLYGON\")\n\texpect_s3_class(st_convex_hull(gpnc), \"sfc_POLYGON\")\n\texpect_s3_class(st_convex_hull(gpnc[[1L]]), \"POLYGON\")\n\n\texpect_silent(st_simplify(pnc, FALSE, 1e4))\n\texpect_silent(st_simplify(gpnc, FALSE, 1e4))\n\texpect_silent(st_simplify(gpnc[[1L]], FALSE, 1e4))\n\n\tif (sf:::CPL_geos_version() >= \"3.4.0\") {\n\t\texpect_silent(st_triangulate(pnc))\n\t\texpect_s3_class(st_triangulate(gpnc), \"sfc_GEOMETRYCOLLECTION\")\n\t\texpect_s3_class(st_triangulate(gpnc[[1]]), \"GEOMETRYCOLLECTION\")\n\t}\n\n\texpect_silent(st_polygonize(lnc))\n\texpect_silent(st_polygonize(glnc))\n\texpect_silent(st_polygonize(glnc[[1]]))\n\n\texpect_s3_class(st_line_merge(lnc), \"sf\")\n\texpect_s3_class(st_line_merge(glnc), \"sfc\")\n\texpect_s3_class(st_line_merge(glnc[[3]]), \"sfg\")\n\n\texpect_warning(st_centroid(lnc)) # was: silent\n\texpect_s3_class(st_centroid(glnc),  \"sfc_POINT\")\n\texpect_s3_class(st_centroid(glnc[[1]]),  \"POINT\")\n\n\texpect_warning(st_point_on_surface(lnc)) # was: silent\n\texpect_s3_class(st_point_on_surface(glnc),  \"sfc_POINT\")\n\texpect_s3_class(st_point_on_surface(glnc[[1]]),  \"POINT\")\n\n\texpect_silent(st_segmentize(lnc, 10000))\n\texpect_silent(st_segmentize(glnc, 10000))\n\texpect_silent(st_segmentize(glnc[[1]], 10000))\n})\n\n\ntest_that(\"st_union/difference/sym_difference/intersection work, for all types\", {\n  p = st_point(0:1)\n  l = st_linestring(matrix(1:10,,2))\n  pl = st_polygon(list(rbind(c(0,0),c(1,0),c(1,1),c(0,1),c(0,0))))\n  x = list(\n  \tpl,\n\tst_sfc(pl,l,pl),\n\tst_sf(a=5:7, st_sfc(pl,l,pl), agr = \"constant\")\n  )\n  y = x\n  for (f in list(st_union, st_difference, st_sym_difference, st_intersection)) {\n  \tfor (xx in x)\n\t  for (yy in y)\n\t  \texpect_silent(f(xx,yy))\n  }\n  for (f in list(st_difference, st_sym_difference, st_intersection)) {\n  \tfor (xx in x)\n\t  for (yy in y)\n\t  \texpect_equal(tail(class(f(xx,yy)),1), tail(class(xx),1))\n  }\n})\n\n\ntest_that(\"st_union works with by_feature\", {\n  p = st_point(0:1)\n  l = st_linestring(matrix(1:10,,2))\n  pl = st_polygon(list(rbind(c(0,0),c(1,0),c(1,1),c(0,1),c(0,0))))\n  x = list(\n  \tpl,\n\tst_sfc(pl,l,pl),\n\tst_sf(a=5:7, st_sfc(pl,l,pl), agr = \"constant\")\n  )\n  expect_silent(z <- st_union(x[[1]], by_feature = TRUE))\n  expect_silent(z <- st_union(x[[2]], by_feature = TRUE))\n  expect_silent(z <- st_union(x[[3]], by_feature = TRUE))\n})\n\ntest_that(\"st_difference works with partially overlapping geometries\", {\n\t# create input testing data\n\tpl1 = st_polygon(list(matrix(c(0, 0, 2, 0, 1, 1, 0 ,0), byrow = TRUE, ncol=2)))\n\tpl2 = st_polygon(list(matrix(c(0, 0.5, 2, 0.5, 1, 1.5, 0, 0.5), byrow = TRUE, ncol = 2)))\n\tpl3 = st_polygon(list(matrix(c(0, 1.25, 2, 1.25, 1, 2.5, 0, 1.25), byrow = TRUE, ncol = 2)))\n\tin1 = st_sfc(list(pl1, pl2, pl3))\n\tin2 = st_sf(order = c(\"A\", \"B\", \"C\"), geometry = st_sfc(list(pl1, pl2, pl3), crs = 4326), agr = \"constant\")\n\tif (package_version(gsub(\"[a-zA-Z]\", \"\", sf_extSoftVersion()[[\"GEOS\"]])) < \"3.9.0\") {\n\t\tcorrect_geom = st_sfc(list(\n\t\tst_polygon(list(matrix(c(0, 2, 1, 0, 0, 0, 1, 0), ncol = 2))),\n\t\tst_polygon(list(matrix(c(0.5, 0, 1, 2, 1.5, 1, 0.5, 0.5, 0.5, 1.5, 0.5, 0.5, 1, 0.5), ncol = 2))),\n\t\tst_polygon(list(matrix(c(0.75, 0, 1, 2, 1.25, 1, 0.75, 1.25, 1.25, 2.5, 1.25, 1.25, 1.5, 1.25), ncol = 2)))))\n\t} else {\n\t\tcorrect_geom = st_sfc(list(\n\t\tst_polygon(list(matrix(c(0, 2, 1, 0, 0, 0, 1, 0), ncol = 2))),\n\t\tst_polygon(list(matrix(c(0, 1, 2, 1.5, 1, 0.5, 0, 0.5, 1.5, 0.5, 0.5, 1, 0.5, 0.5), ncol = 2))),\n\t\tst_polygon(list(matrix(c(0, 1, 2, 1.25, 1, 0.75, 0, 1.25, 2.5, 1.25, 1.25, 1.5, 1.25, 1.25), ncol = 2)))))\n\t}\n\t# erase overlaps\n\tout1 = st_difference(in1)\n\tout2 = st_difference(in2)\n\t# check that output class is correct\n\texpect_s3_class(out1, \"sfc\")\n\texpect_s3_class(out2, \"sf\")\n\t# check that output geometries are valid\n\texpect_true(all(sf::st_is_valid(out1)))\n\texpect_true(all(sf::st_is_valid(out2)))\n\t# check that output geometries have correct attributes\n\texpect_equal(attr(out1, \"idx\"), seq_len(3))\n\t#expect_equal(attr(out2, \"idx\"), seq_len(3))\n\texpect_equal(attr(out1, \"crs\"), attr(in1, \"crs\"))\n\texpect_equal(st_crs(out2), st_crs(in2))\n\t# check that output geometries are actually correct\n\texpect_length(out1, 3)\n\texpect_equal(nrow(out2), 3)\n\texpect_equal(out1[[1]][[1]], correct_geom[[1]][[1]])\n\texpect_equal(out1[[2]][[1]], correct_geom[[2]][[1]])\n\texpect_equal(out1[[3]][[1]], correct_geom[[3]][[1]])\n})\n\ntest_that(\"st_difference works with fully contained geometries\", {\n\t# create input testing data\n\tpl1 = st_polygon(list(matrix(c(0, 0, 2, 0, 2, 2, 0, 2, 0, 0), byrow = TRUE, ncol=2)))\n\tpl2 = st_polygon(list(matrix(c(0.5, 0.5, 1.5, 0.5, 1.5, 1.5, 0.5, 1.5, 0.5, 0.5), byrow = TRUE, ncol = 2)))\n\tpl3 = st_polygon(list(matrix(c(5, 5, 7, 5, 7, 7, 5, 7, 5, 5), byrow = TRUE, ncol = 2)))\n\tin1 = st_sfc(list(pl1, pl2, pl3))\n\tin2 = st_sf(order = c(\"A\", \"B\", \"C\"), geometry = st_sfc(list(pl1, pl2, pl3), crs = 4326), agr = \"constant\")\n\tcorrect_geom = st_sfc(list(pl1, pl3))\n\t# erase overlaps\n\tout1 = st_difference(in1)\n\tout2 = st_difference(in2)\n\t# check that output class is correct\n\texpect_s3_class(out1, \"sfc\")\n\texpect_s3_class(out2, \"sf\")\n\t# check that output geometries are valid\n\texpect_true(all(sf::st_is_valid(out1)))\n\texpect_true(all(sf::st_is_valid(out2)))\n\t# check that output geometries have correct attributes\n\texpect_equal(attr(out1, \"idx\"), c(1L, 3L))\n\t#expect_equal(attr(out2, \"idx\"), c(1L, 3L))\n\texpect_equal(attr(out1, \"crs\"), attr(in1, \"crs\"))\n\texpect_equal(st_crs(out2), st_crs(in2))\n\t# check that output geometries are actually correct\n\texpect_length(out1, 2)\n\texpect_length(out2, 2)\n\texpect_equal(out1[[1]][[1]], correct_geom[[1]][[1]])\n\t#expect_equal(out1[[2]][[1]], correct_geom[[2]][[1]])\n\t#expect_equal(out2[[1]][[1]], correct_geom[[1]][[1]])\n\t#expect_equal(out2[[2]][[1]], correct_geom[[2]][[1]])\n\t# check change in order\n\tin3 = st_sfc(list(pl2, pl1))\n\tcorrect_geom = list(pl2, st_difference(pl1, pl2))\n\tout3 = st_difference(in3)\n\texpect_equal(correct_geom[[1]], out3[[1]])\n\texpect_equal(correct_geom[[2]], out3[[2]])\n})\n\ntest_that(\"binary operations work on sf objects with common column names\", {\n\tpol1 <- st_sfc(st_polygon(list(cbind(c(0,3,3,0,0),c(0,0,3,3,0)))))\n\tpol2 <- pol1 + 1\n\tsf1 <- st_sf(id = 1, pol1)\n\tsf2 <- st_sf(id = 2, pol2)\n\t# Test as regular data.frames\n\texpect_s3_class(st_intersection(sf1, sf2), \"sf\")\n\t# Convert to tibbles\n\tsf1 <- st_as_sf(tibble::as_tibble(sf1))\n\tsf2 <- st_as_sf(tibble::as_tibble(sf2))\n\texpect_s3_class(st_intersection(sf1, sf2), c(\"sf\", \"tbl_df\"))\n})\n\ntest_that(\"binary operations on empty sfg objects return NA\", {\n  x = st_point() == st_linestring()\n  expect_equal(x, NA)\n})\n"
  },
  {
    "path": "tests/testthat/test-grid.R",
    "content": "test_that(\"point grob constructors work\", {\n\tp1 <- st_point(c(0, 1))\n\tp2 <- st_point(c(2, 3))\n\tp3 <- st_multipoint(matrix(11:20, ncol = 2))\n\tp4 <- st_sfc(list(p1, p2, p3))\n\tg1 <- st_as_grob(p1)\n\texpect_s3_class(g1, c('points', 'grob'))\n\tg2 <- st_as_grob(p4, gp = grid::gpar(col = c('red', 'green', 'blue')))\n\texpect_s3_class(g2, c('points', 'grob'))\n\texpect_equal(as.numeric(g2$x), unname(rbind(p1, p2, p3)[,1]))\n\texpect_equal(g2$gp$col, rep(c('red', 'green', 'blue'), c(1, 1, 5)))\n})\n\ntest_that(\"linestring grob construction work\", {\n\tlines <- list(\n\t\tmatrix(11:20, ncol = 2),\n\t\tmatrix(21:30, ncol = 2),\n\t\tmatrix(31:50, ncol = 2)\n\t)\n\tl1 <- st_linestring(lines[[1]])\n\tl2 <- st_multilinestring(lines[2:3])\n\tl3 <- st_sfc(list(l1, l2))\n\tg1 <- st_as_grob(l1)\n\texpect_s3_class(g1, c('lines', 'grob'))\n\tg2 <- st_as_grob(l3, gp = grid::gpar(lwd = c(2, 4)))\n\texpect_s3_class(g2, c('lines', 'grob'))\n\texpect_equal(as.numeric(g2$x), do.call(rbind, lines)[, 1])\n\texpect_equal(g2$gp$lwd, rep(c(2, 4), c(1, 2)))\n\texpect_equal(g2$id.lengths, c(5, 5, 10))\n})\n\nholed_rect <- function(x0, y0, width, height, hole) {\n\touter <- cbind(\n\t\tc(x0 - width/2, x0 + width/2, x0 + width/2, x0 - width/2, x0 - width/2),\n\t\tc(y0 - height/2, y0 - height/2, y0 + height/2, y0 + height/2, y0 - height/2)\n\t)\n\tinner <- outer\n\tinner[,1] <- (inner[,1] - x0) * hole + x0\n\tinner[,2] <- (inner[,2] - y0) * hole + y0\n\tlist(outer, inner)\n}\ntest_that(\"polygon grob construction work\", {\n\tpolys <- list(\n\t\tholed_rect(0, 0, 1, 1, 0.5),\n\t\tholed_rect(10, 5, 5, 1, 0.25),\n\t\tholed_rect(-3, -10, 4, 10, 0.7)\n\t)\n\tp1 <- st_polygon(polys[[1]])\n\tp2 <- st_multipolygon(polys[2:3])\n\tp3 <- st_sfc(list(p1, p2))\n\tg1 <- st_as_grob(p1)\n\texpect_s3_class(g1, c('pathgrob', 'grob'))\n\tg2 <- st_as_grob(p3, gp = grid::gpar(fill = c('red', 'blue')))\n\tif (getRversion() <  as.numeric_version(\"3.6\")) {\n\t\texpect_s3_class(g2, 'gList')\n\t\texpect_equal(g2[[1]]$gp$fill, 'red')\n\t\texpect_equal(g2[[2]]$gp$fill, 'blue')\n\t} else {\n\t\texpect_s3_class(g2, c('pathgrob', 'grob'))\n\t\tcoords <- do.call(rbind, unlist(polys, recursive = FALSE))\n\t\texpect_equal(as.numeric(g2$x), coords[, 1])\n\t\texpect_equal(g2$id.lengths, rep(5, 6))\n\t\texpect_equal(g2$pathId.lengths, rep(10, 3))\n\t\texpect_equal(g2$gp$fill, c('red', 'blue', 'blue'))\n\t}\n})\n\ntest_that(\"mixed sfc grob construction works\", {\n\tp1 <- st_point(c(0, 1))\n\tp2 <- st_multipoint(matrix(11:20, ncol = 2))\n\tl1 <- st_linestring(matrix(21:30, ncol = 2))\n\tp3 <- st_polygon(holed_rect(0, 0, 1, 1, 0.5))\n\tsfc <- st_sfc(list(p1, p2, l1, p3))\n\tg1 <- st_as_grob(sfc, pch = 1:4, gp = grid::gpar(col = 'blue', fill = c('red', 'red', 'blue', 'green')))\n\texpect_s3_class(g1[[1]], c('points', 'grob'))\n\texpect_s3_class(g1[[2]], c('points', 'grob'))\n\texpect_s3_class(g1[[3]], c('lines', 'grob'))\n\texpect_s3_class(g1[[4]], c('pathgrob', 'grob'))\n\texpect_equal(g1[[1]]$pch, 1)\n\texpect_equal(g1[[2]]$pch, 2)\n\texpect_null(g1[[3]]$pch)\n\texpect_null(g1[[4]]$pch)\n\texpect_equal(g1[[1]]$gp$col, 'blue')\n\texpect_equal(g1[[2]]$gp$col, 'blue')\n\texpect_equal(g1[[3]]$gp$col, 'blue')\n\texpect_equal(g1[[4]]$gp$col, 'blue')\n\texpect_equal(g1[[1]]$gp$fill, 'red')\n\texpect_equal(g1[[2]]$gp$fill, 'red')\n\texpect_equal(g1[[3]]$gp$fill, 'blue')\n\texpect_equal(g1[[4]]$gp$fill, 'green')\n})\n"
  },
  {
    "path": "tests/testthat/test-normalize.R",
    "content": "set.seed(1)\ntest_that(\"normalize\", {\n  p0 <- st_point(c(0,1))\n  p0_norm <- st_normalize(p0, c(0,0,10,10))\n  expect_equal(p0_norm, st_point(c(0,0.1)))\n\n  p1 <- st_multipoint(matrix(runif(20, max = 25), ncol = 2))\n  p1_norm <- st_normalize(p1)\n  expect_equal(unclass(st_bbox(p1_norm)), c(0,0,1,1), check.attributes = FALSE)\n\n  p2 <- st_polygon(list(matrix(runif(10, max = 100), ncol = 2)[c(1:5, 1), ]))\n  sfc <- st_sfc(p1, p2)\n  sfc_norm <- st_normalize(sfc)\n  expect_equal(unclass(st_bbox(sfc_norm)), c(0,0,1,1), check.attributes = FALSE)\n\n  sf <- st_sf(geometry = sfc)\n  sf_norm <- st_normalize(sf)\n  expect_equal(unclass(st_bbox(sf_norm)), c(0,0,1,1), check.attributes = FALSE)\n  expect_equal(sfc_norm, sf_norm$geometry)\n\n})\n\ntest_that(\"ops\", {\n  p0 <- st_point(c(0, 1, 2))\n  expect_equal(st_sfc(p0) - st_sfc(st_point(c(1,2,3))), st_sfc(st_point(c(-1,-1,-1))))\n  expect_equal(st_sfc(p0) * st_sfc(st_point(c(1,2,3))), st_sfc(st_point(c(0,2,6))))\n})\n\ntest_that(\"grob stuff\", {\n  p0 <- st_point(c(0,1))\n  g <- st_as_grob(st_sfc(p0))\n  p1 <- st_linestring(matrix(runif(20, max = 25), ncol = 2))\n  g <- st_as_grob(st_sfc(p1))\n  p2 <- st_polygon(list(matrix(runif(10, max = 100), ncol = 2)[c(1:5, 1), ]))\n  g <- st_as_grob(st_sfc(p2))\n})\n"
  },
  {
    "path": "tests/testthat/test-plot.R",
    "content": "test_that(\"plot.sf() support characters\", {\n  m <- list(rbind(c(0,0), c(1,0), c(1, 1), c(0,1), c(0,0))) |> st_polygon()\n  x <- data.frame(a = c(\"a\", \"b\"), stringsAsFactors = FALSE) |> st_as_sf(geom = st_sfc(m, m + 2))\n  expect_silent(plot(x))\n})\n\ntest_that(\"plot.sf warns on more than 15 attributes\", {\n  nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), \"nc\", quiet = TRUE)\n  x = cbind(nc,nc)\n  expect_warning(plot(x))\n})\n\ntest_that(\"plot.sf deals with key.length in cm\", {\n  nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), \"nc\", quiet = TRUE)\n  expect_silent(plot(nc[1], key.length = lcm(5), key.pos = 2))\n  expect_silent(plot(nc[1], key.length = lcm(5), key.pos = 1))\n  nc$f = factor(rep(c(\"a\", \"b\"), each = 50))\n  expect_silent(plot(nc[\"f\"], key.length = lcm(5), key.pos = 2))\n  expect_silent(plot(nc[\"f\"], key.length = lcm(5), key.pos = 1))\n})\n"
  },
  {
    "path": "tests/testthat/test-postgis_ODBC.R",
    "content": "skip_if_not_installed(\"RPostgres\")\nlibrary(sf)\nlibrary(DBI)\nlibrary(RPostgreSQL)\nlibrary(testthat)\n\ncan_con <- function(x) inherits(x, \"DBIObject\")\n\ndb_drop_table_schema <- function(con, schema, table = NULL) {\n    if (is.null(table)) {\n        table <- paste(c(\"public\", schema), collapse = \".\")\n    } else {\n        table <- paste(c(schema, table), collapse = \".\")\n    }\n    DBI::dbSendQuery(pg, paste(\"DROP TABLE \", table, \" CASCADE;\"))\n}\nrequire(\"sp\")\ndata(meuse)\npts <- st_as_sf(meuse, coords = c(\"x\", \"y\"), crs = 28992)\n\nepsg_31370 = paste0(\"+proj=lcc +lat_1=51.16666723333333 +lat_2=49.8333339 \",\n                    \"+lat_0=90 +lon_0=4.367486666666666 +x_0=150000.013 \",\n                    \"+y_0=5400088.438 +ellps=intl +towgs84=-106.869,52.2978,\",\n                    \"-103.724,0.3366,-0.457,1.8422,-1.2747 +units=m +no_defs\")\n\npg <- NULL\ntest_that(\"check utils\", expect_false(can_con(pg)))\n# requires to apt-get install odbc-postgresql\ntry(pg <- dbConnect(odbc::odbc(), \"PostgreSQL\"), silent=TRUE)\npg <- NULL\n# tests ------------------------------------------------------------------------\ntest_that(\"can write to db\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\texpect_silent(suppressMessages(st_write(pts, pg, \"sf_meuse__\")))\n\texpect_error(st_write(pts, pg, \"sf_meuse__\"), \"exists\")\n\texpect_true(st_write(pts, pg, \"sf_meuse__\", overwrite = TRUE))\n\texpect_true(st_write(pts, pg, \"sf_meuse2__\", binary = FALSE))\n\texpect_warning(z <- st_set_crs(pts, epsg_31370))\n\texpect_message(st_write(z, pg, \"sf_meuse3__\"), \"Inserted local crs\")\n\texpect_silent(st_write(z, pg, \"sf_meuse3__\", append = TRUE))\n\texpect_warning(expect_equal(nrow(DBI::dbReadTable(pg, \"sf_meuse3__\")), nrow(z) * 2), \"Unknown field type\")\n\texpect_silent(st_write(z, pg, \"sf_meuse3__\", overwrite = TRUE))\n})\n\ntest_that(\"can handle multiple geom columns\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tmulti <- cbind(pts[[\"geometry\"]], st_transform(pts, 4326))\n\texpect_silent(st_write(multi, pg, \"meuse_multi\", overwrite = TRUE))\n\texpect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi\", quiet = TRUE))\n\texpect_equal(st_crs(x[[\"geometry\"]]), st_crs(multi[[\"geometry\"]]))\n\texpect_equal(st_crs(x[[\"geometry.1\"]]), st_crs(multi[[\"geometry.1\"]]))\n\texpect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi\", quiet = TRUE, type = c(1,4)))\n\texpect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi\", quiet = TRUE, type = c(4,4)))\n\texpect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi\", quiet = TRUE, promote_to_multi = FALSE))\n\texpect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi\", quiet = TRUE, geometry_column = \"geometry.1\"))\n\tx <- st_layers(\"PG:host=localhost dbname=postgis\")\n\tmulti2 <- cbind(pts[[\"geometry\"]], st_set_crs(st_transform(pts, 4326), NA))\n\texpect_silent(st_write(multi2, pg, \"meuse_multi2\", overwrite = TRUE))\n\texpect_silent(x <- st_read(pg, \"meuse_multi2\"))\n\texpect_equal(st_crs(x[[\"geometry\"]]), st_crs(multi2[[\"geometry\"]]))\n\texpect_equal(st_crs(x[[\"geometry.1\"]]), st_crs(multi2[[\"geometry.1\"]]))\n\texpect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi2\", quiet = TRUE))\n\t#expect_equal(st_crs(x[[\"geometry\"]]), st_crs(multi2[[\"geometry\"]]))\n\texpect_equal(st_crs(x[[\"geometry.1\"]]), st_crs(multi2[[\"geometry.1\"]]))\n})\n\ntest_that(\"sf can write units to database (#264)\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tptsu <- pts\n\tptsu[[\"u\"]] <- ptsu[[\"cadmium\"]]\n\tunits(ptsu[[\"u\"]]) <- units::as_units(\"km\")\n\texpect_silent(st_write(ptsu, pg, \"sf_units__\", overwrite = TRUE))\n\tr <- st_read(pg, \"sf_units__\")\n\texpect_type(r[[\"u\"]], \"double\")\n\texpect_equal(sort(r[[\"u\"]]), sort(as.numeric(ptsu[[\"u\"]])))\n\tdbRemoveTable(pg, \"sf_units__\")\n})\n\ntest_that(\"sf can preserve types (#592)\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tdtypes <- data.frame(\n\t\tlogi = c(TRUE, FALSE, NA),\n\t\tchara = c(\"a\", \"\", NA),\n\t\tnume = c(1.1e1, 2.2e2, NA),\n\t\tinte = c(1L, 2L, NA),\n\t\tfact = factor(c(\"a\", \"b\", NA), levels = letters),\n\t\t#comp = c(complex(1, 2), complex(2, 3)),\n\t\tdate = c(rep(Sys.Date(), 2), NA),\n\t\ttime = c(rep(Sys.time(), 2), NA),\n\t\tx = c(1, 2, 4),\n\t\ty = c(1, 2, 4), stringsAsFactors = FALSE)\n\t# cannot write lists\n\t#dtypes$lst <- c(list(matrix(\"a\")), list(matrix(c(\"b\", \"c\"))), list(NA))\n\tdtypes <- st_as_sf(dtypes, coords = c(\"x\", \"y\"))\n\tst_write(dtypes, pg, overwrite = TRUE)\n\tx <- st_read(pg, \"dtypes\")\n\tdtypes$fact <- as.character(dtypes$fact)\n\texpect_equal(x, dtypes)\n\tDBI::dbRemoveTable(pg, \"dtypes\")\n})\n\ntest_that(\"can write to other schema\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\ttry(DBI::dbSendQuery(pg, \"CREATE SCHEMA sf_test__;\"), silent = TRUE)\n\tq <- \"SELECT schema_name FROM information_schema.schemata WHERE schema_name = 'sf_test__';\"\n\tsuppressWarnings(could_schema <- DBI::dbGetQuery(pg, q) |> nrow() > 0)\n\n\tskip_if_not(could_schema, \"Could not create schema (might need to run 'GRANT CREATE ON DATABASE postgis TO <user>')\")\n\texpect_error(st_write(pts, pg, Id(schema = \"public\", table = \"sf_meuse__\")), \"exists\")\n\texpect_silent(st_write(pts, pg, Id(schema = \"sf_test__\", table = \"sf_meuse__\")))\n\texpect_error(st_write(pts, pg, Id(schema = \"sf_test__\", table = \"sf_meuse__\")), \"exists\")\n\texpect_silent(st_write(pts, pg, Id(schema = \"sf_test__\", table = \"sf_meuse__\"), overwrite = TRUE))\n\texpect_warning(z <- st_set_crs(pts, epsg_31370))\n\texpect_silent(st_write(z, pg, Id(schema = \"sf_test__\", table = \"sf_meuse33__\")))\n\texpect_silent(st_write(z, pg, Id(schema = \"sf_test__\", table = \"sf_meuse4__\")))\n\n\t# weird name work\n\texpect_silent(st_write(pts, pg, c(NULL, \"sf_test__.meuse__\"), overwrite = TRUE))\n\texpect_silent(st_write(pts.2 <- pts, pg, overwrite = TRUE))\n\texpect_true(DBI::dbRemoveTable(pg, \"pts.2 <- pts\"))\n})\n\ntest_that(\"support for capital names (#571)\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\texpect_silent(st_write(pts, pg, \"Meuse_tbl\"))\n\texpect_true(DBI::dbRemoveTable(pg, \"Meuse_tbl\"))\n\ttry(DBI::dbSendQuery(pg, \"CREATE SCHEMA \\\"CAP__\\\";\"), silent = TRUE)\n\tq <- \"SELECT schema_name FROM information_schema.schemata WHERE schema_name = 'CAP__';\"\n\tsuppressWarnings(could_schema <- DBI::dbGetQuery(pg, q) |> nrow() > 0)\n\tskip_if_not(could_schema, \"Could not create schema (might need to run 'GRANT CREATE ON DATABASE postgis TO <user>')\")\n\texpect_silent(st_write(pts, pg, Id(schema = \"CAP__\", table = \"Meuse_tbl\")))\n\texpect_true(DBI::dbRemoveTable(pg, Id(schema = \"CAP__\", table = \"Meuse_tbl\")))\n\tdbExecute(pg, 'DROP SCHEMA \"CAP__\" CASCADE;')\n})\n\ntest_that(\"can read from db\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tq <- \"select * from sf_meuse__\"\n\t#expect_warning(x <- st_read(pg, query = q), \"crs\")\n\texpect_silent(x <- st_read(pg, query = q))\n\n\texpect_error(st_read(pg), \"table name or a query\")\n\n\ty <- st_read(pg, \"sf_meuse__\")\n\texpect_equal(dim(pts), dim(y))\n\texpect_identical(st_crs(pts), st_crs(y))\n\texpect_identical(st_precision(pts), st_precision(y))\n\n\texpect_warning(z <- st_read(pg, \"sf_meuse3__\"), \"code \\\\d+ not found\")\n\texpect_equal(dim(pts), dim(z))\n\t#expect_identical(st_crs(NA), st_crs(z))\n\texpect_true(st_crs(epsg_31370) == st_crs(z))\n\texpect_identical(st_precision(pts), st_precision(z))\n\n\tw <- st_read(pg, c(\"sf_test__\", \"sf_meuse__\"))\n\texpect_equal(dim(y), dim(w))\n\texpect_identical(st_crs(y), st_crs(w))\n\texpect_identical(st_precision(y), st_precision(w))\n\n\texpect_error(st_read(pg, \"missing\"), \"not exist\")\n\texpect_error(st_read(pg, c(\"missing\", \"missing\")), \"not exist\")\n\t# make sure it reads in the correct schema\n\texpect_error(st_read(pg, c(\"sf_test__\", \"sf_meuse3__\")), \"not exist\")\n})\n\ntest_that(\"can read views (#212)\", {\n\tskip_if_not(Sys.getenv(\"USER\") != \"edzer\") # this stopped working for me\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\texpect_equal(DBI::dbExecute(pg,\n\t\t\t\t\t\t\t\t\"CREATE VIEW sf_view__ AS SELECT * FROM sf_meuse__;\"), 0)\n\texpect_equal(DBI::dbExecute(pg,\n\t\t\t\t\t\t\t\t\"CREATE VIEW sf_test__.sf_view__ AS SELECT * FROM sf_meuse__;\"), 0)\n\texpect_equal(DBI::dbExecute(pg,\n\t\t\t\t\t\t\t\t\"CREATE MATERIALIZED VIEW sf_viewm__ AS SELECT * FROM sf_meuse__;\"), 155)\n\texpect_equal(DBI::dbExecute(pg,\n\t\t\t\t\t\t\t\t\"CREATE MATERIALIZED VIEW sf_test__.sf_viewm__ AS SELECT * FROM sf_meuse__;\"), 155)\n\tx <- st_read(pg, \"sf_meuse__\")\n\texpect_identical(st_read(pg, \"sf_view__\"), x)\n\texpect_identical(st_read(pg, c(\"public\", \"sf_view__\")), x)\n\texpect_identical(st_read(pg, c(\"sf_test__\", \"sf_view__\")), x)\n\texpect_identical(st_read(pg, c(\"sf_viewm__\")), x)\n\texpect_identical(st_read(pg, c(\"sf_test__\", \"sf_viewm__\")), x)\n\n\ttry(DBI::dbExecute(pg, \"DROP VIEW sf_view__\"), silent = TRUE)\n\ttry(DBI::dbExecute(pg, \"DROP VIEW sf_test__.sf_view__\"), silent = TRUE)\n\ttry(DBI::dbExecute(pg, \"DROP MATERIALIZED VIEW sf_viewm__\"), silent = TRUE)\n\ttry(DBI::dbExecute(pg, \"DROP MATERIALIZED VIEW sf_test__.sf_viewm__\"), silent = TRUE)\n})\n\ntest_that(\"round trips\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tround_trip = function(conn, wkt) {\n\t\tquery = paste0(\"SELECT '\", wkt, \"'::geometry;\")\n\t\treturnstr = suppressWarnings(DBI::dbGetQuery(conn, query)$geometry)\n\t\twkb = structure(returnstr, class = \"WKB\")\n\t\tret = st_as_sfc(wkb, EWKB = TRUE)\n\t\tmessage(paste(\"IN:  \", wkt, \"\\n\"))\n\t\t# OUT contains WKB created in PostGIS from wkt, interpreted to R by sf, printed as WKT by sf\n\t\tmessage(paste(\"OUT: \", txt <- st_as_text(ret, EWKT=TRUE)[[1]], \"\\n\"))\n\t\tif (length(grep(\"SRID\", txt)) == 0) {\n\t\t\tquery = paste0(\"SELECT ST_AsText('\",sf:::CPL_raw_to_hex(st_as_binary(ret[[1]])),\"');\")\n\t\t\treceived = suppressWarnings(DBI::dbGetQuery(conn, query)$st_astext)\n\t\t\t# PG: contains the PostGIS WKT, after reading the WKB created by sf from R native\n\t\t\tmessage(paste(\"PG:  \", received, \"\\n\"))\n\t\t}\n\t\texpect_equal(wkt, txt)\n\t}\n\tround_trip(pg, \"SRID=4326;POINT M (0 0 0)\")\n\tround_trip(pg, \"POINT Z (0 0 0)\")\n\tround_trip(pg, \"POINT ZM (0 0 0 0)\")\n\tround_trip(pg, \"POINT (0 0)\")\n\tround_trip(pg, \"LINESTRING (0 0, 1 1, 2 2)\")\n\tround_trip(pg, \"MULTIPOINT (0 0, 1 1, 2 2)\")\n\tround_trip(pg, \"POLYGON ((0 0, 1 0, 1 1, 0 0))\")\n\tround_trip(pg, \"MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((2 2, 3 2, 3 3, 2 2)))\")\n\tround_trip(pg, paste(\"MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0),\",\n\t\t\t\t\t\t \"(0.2 0.2, 0.8 0.2, 0.8 0.8, 0.2 0.2)),\",\n\t\t\t\t\t\t \"((2 2, 3 2, 3 3, 2 2)))\"))\n\tround_trip(pg, paste(\"MULTILINESTRING ((0 0, 1 0, 1 1, 0 0),\",\n\t\t\t\t\t\t \"(0.2 0.2, 0.8 0.2, 0.8 0.8, 0.2 0.2),\",\n\t\t\t\t\t\t \"(2 2, 3 2, 3 3, 2 2))\"))\n\n\t# other types; examples taken from the PostGIS manuals (ch 4):\n\tround_trip(pg, \"CIRCULARSTRING (0 0, 1 1, 1 0)\")\n\tround_trip(pg, \"CIRCULARSTRING (0 0, 4 0, 4 4, 0 4, 0 0)\")\n\tround_trip(pg, paste(\"CURVEPOLYGON (CIRCULARSTRING (0 0, 4 0, 4 4, 0 4, 0 0),\",\n\t\t\t\t\t\t \"LINESTRING (1 1, 3 3, 3 1, 1 1))\"))\n\tround_trip(pg, paste(\"COMPOUNDCURVE (CIRCULARSTRING (0 0, 1 1, 1 0),\",\n\t\t\t\t\t\t \"LINESTRING (1 0, 0 1))\"))\n\tround_trip(pg, paste0(\"CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (0 0, 2 0, 2 1, 2 3, 4 3), \",\n\t\t\t\t\t\t  \"LINESTRING (4 3, 4 5, 1 4, 0 0)), \",\n\t\t\t\t\t\t  \"CIRCULARSTRING (1.7 1, 1.4 0.4, 1.6 0.4, 1.6 0.5, 1.7 1))\"))\n\tround_trip(pg, \"MULTICURVE (LINESTRING (0 0, 5 5), CIRCULARSTRING (4 0, 4 4, 8 4))\")\n\tround_trip(pg, paste(\"MULTISURFACE (CURVEPOLYGON (CIRCULARSTRING (0 0, 4 0, 4 4, 0 4, 0 0),\",\n\t\t\t\t\t\t \"LINESTRING (1 1, 3 3, 3 1, 1 1)),\",\n\t\t\t\t\t\t \"POLYGON ((10 10, 14 12, 11 10, 10 10),\",\n\t\t\t\t\t\t \"(11 11, 11.5 11, 11 11.5, 11 11)))\"))\n\n\tround_trip(pg, paste(\"MULTICURVE (LINESTRING (0 0, 5 5),\",\n\t\t\t\t\t\t \"CIRCULARSTRING (4 0, 4 4, 8 4))\"))\n\tround_trip(pg, paste(\"POLYHEDRALSURFACE Z (((0 0 0, 0 0 1, 0 1 1, 0 1 0, 0 0 0)),\",\n\t\t\t\t\t\t \"((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)),\",\n\t\t\t\t\t\t \"((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)),\",\n\t\t\t\t\t\t \"((1 1 0, 1 1 1, 1 0 1, 1 0 0, 1 1 0)),\",\n\t\t\t\t\t\t \"((0 1 0, 0 1 1, 1 1 1, 1 1 0, 0 1 0)),\",\n\t\t\t\t\t\t \"((0 0 1, 1 0 1, 1 1 1, 0 1 1, 0 0 1)))\"))\n\tround_trip(pg, \"TRIANGLE ((0 0, 0 9, 9 0, 0 0))\")\n\tround_trip(pg, \"TIN Z (((0 0 0, 0 0 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 0 0 0)))\")\n})\n\ntest_that(\"can read using driver\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tlayers <- st_layers(\"PG:host=localhost dbname=postgis\")\n\tlyr_expect <- sort(c(\"sf_meuse__\", \"sf_meuse2__\", \"sf_meuse3__\", \"meuse_multi2\",\n\t\t\t\t\t\t \"sf_test__.sf_meuse__\",  \"sf_test__.meuse__\",\n\t\t\t\t\t\t \"sf_test__.sf_meuse33__\", \"sf_test__.sf_meuse4__\"))\n\texpect_true(all(lyr_expect %in% layers$name))\n\texpect_true(all(layers$features == 155))\n\texpect_true(all(layers$fields == 12))\n\n\tskip_if_not(can_con(try(DBI::dbConnect(RPostgres::Postgres(), dbname = \"empty\"), silent=TRUE)),\n\t\t\t\t\"could not connect to 'empty' database\")\n\texpect_error(st_read(\"PG:host=localhost dbname=empty\", quiet = TRUE), \"No layers\")\n})\n\ntest_that(\"Can safely manipulate crs\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tsrid <- 4326\n\texpect_true(get_postgis_crs(pg, srid) == st_crs(srid))\n\texpect_error(set_postgis_crs(pg, st_crs(srid)))\n\texpect_warning(expect_true(is.na(st_crs(get_new_postgis_srid(pg)))), \"not found\")\n\tnew_crs <- st_crs(get_new_postgis_srid(pg), \"+proj=longlat +datum=WGS84 +no_defs\", valid = FALSE)\n\texpect_message(set_postgis_crs(pg, new_crs, auth_name = \"sf_test\"), \"Inserted local crs\")\n\texpect_warning(expect_error(set_postgis_crs(pg, new_crs), \"duplicate key\"),\n\t\t\t\t   \"not found\")\n\texpect_equal(delete_postgis_crs(pg, new_crs), 1)\n\texpect_equal(delete_postgis_crs(pg, new_crs), 0)\n})\n\ntest_that(\"new SRIDs are handled correctly\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tdata(meuse, package = \"sp\")\n\tmeuse_sf = st_as_sf(meuse, coords = c(\"x\", \"y\"), crs = NA_crs_)\n\n\tcrs = st_crs(NA_integer_, paste(\"+proj=sterea +lat_0=52 +lon_0=5\", # creates FALSE, but new one\n\t\t\t\t\t\t\t\t\t\"+k=1.0 +x_0=155000 +y_0=463000 +ellps=bessel\",\n\t\t\t\t\t\t\t\t\t\"+towgs84=565.4171,50.3319,465.5524,-0.398957,0.343988,\",\n\t\t\t\t\t\t\t\t\t\"-1.87740,4.0725 +units=m +no_defs\"), valid = FALSE)\n\tst_crs(meuse_sf) = crs\n\texpect_message(st_write(meuse_sf, pg, overwrite = TRUE), \"Inserted local crs\")\n\texpect_warning(x <- st_read(pg, query = \"select * from meuse_sf limit 3;\"),\n\t\t\t\t   \"not found in EPSG support files\")\n\texpect_true(st_crs(x)$proj4string == crs$proj4string)\n\texpect_silent(st_write(meuse_sf, pg, overwrite = TRUE))\n})\n\ntest_that(\"schema_table\", {\n\texpect_error(sf:::schema_table(pg, NA), \"character vector\")\n\texpect_error(sf:::schema_table(pg, NA_character_), \"cannot be NA\")\n\texpect_error(sf:::schema_table(pg, \"a\", NA), \"cannot be NA\")\n\texpect_error(sf:::schema_table(pg, letters), \"longer than 2\")\n\texpect_equal(sf:::schema_table(pg, \"a\", \"b\"), c(\"b\", \"a\"))\n\texpect_equal(sf:::schema_table(pg, \"a\"), c(\"public\", \"a\"))\n})\n\nif (can_con(pg)) {\n\t# cleanup\n\ttry(db_drop_table_schema(pg, \"meuse_sf\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"meuse_multi\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"sf_meuse__\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"sf_meuse2__\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"sf_meuse3__\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"meuse_multi2\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, '\"sf_test__.meuse__\"'), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"sf_test__\", \"sf_meuse__\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"sf_test__\", \"sf_meuse2__\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"sf_test__\", \"sf_meuse33__\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"sf_test__\", \"sf_meuse4__\"), silent = TRUE)\n\ttry(DBI::dbExecute(pg, \"DROP SCHEMA sf_test__ CASCADE;\"), silent = TRUE)\n\ttry(DBI::dbExecute(pg, \"DELETE FROM spatial_ref_sys WHERE auth_name = 'sf';\"), silent = TRUE)\n\ttry(DBI::dbDisconnect(pg), silent = TRUE)\n}\n"
  },
  {
    "path": "tests/testthat/test-postgis_RPostgreSQL.R",
    "content": "skip_if_not_installed(\"RPostgres\")\nlibrary(sf)\nlibrary(DBI)\nlibrary(RPostgreSQL)\nlibrary(testthat)\n\ncan_con <- function(x) inherits(x, \"PostgreSQLConnection\")\n\ndb_drop_table_schema <- function(con, schema, table = NULL) {\n    if (is.null(table)) {\n        table <- paste(c(\"public\", schema), collapse = \".\")\n    } else {\n        table <- paste(c(schema, table), collapse = \".\")\n    }\n    DBI::dbExecute(pg, paste(\"DROP TABLE \", table, \" CASCADE;\"))\n}\nrequire(\"sp\")\ndata(meuse)\npts <- st_as_sf(meuse, coords = c(\"x\", \"y\"), crs = 28992)\n\nepsg_31370 = paste0(\"+proj=lcc +lat_1=51.16666723333333 +lat_2=49.8333339 \",\n                    \"+lat_0=90 +lon_0=4.367486666666666 +x_0=150000.013 \",\n                    \"+y_0=5400088.438 +ellps=intl +towgs84=-106.869,52.2978,\",\n                    \"-103.724,0.3366,-0.457,1.8422,-1.2747 +units=m +no_defs\")\n\npg <- NULL\ntest_that(\"check utils\", expect_false(can_con(pg)))\n#try(pg <- DBI::dbConnect(RPostgreSQL::PostgreSQL(), host = \"localhost\", dbname = \"postgis\"), silent=TRUE)\n\n\n# tests ------------------------------------------------------------------------\ntest_that(\"can write to db\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\texpect_silent(suppressMessages(st_write(pts, pg, \"sf_meuse__\")))\n\texpect_error(st_write(pts, pg, \"sf_meuse__\"), \"exists\")\n\texpect_silent(st_write(pts, pg, \"sf_meuse__\", overwrite = TRUE))\n\texpect_silent(st_write(pts, pg, \"sf_meuse2__\", binary = FALSE))\n\texpect_warning(z <- st_set_crs(pts, epsg_31370))\n\texpect_message(st_write(z, pg, \"sf_meuse3__\"), \"Inserted local crs\")\n\texpect_silent(st_write(z, pg, \"sf_meuse3__\", append = TRUE))\n\texpect_warning(expect_equal(nrow(DBI::dbReadTable(pg, \"sf_meuse3__\")), nrow(z) * 2), \"unrecognized PostgreSQL field type geometry\")\n\texpect_silent(st_write(z, pg, \"sf_meuse3__\", overwrite = TRUE))\n})\n\ntest_that(\"can handle multiple geom columns\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tmulti <- cbind(pts[[\"geometry\"]], st_transform(pts, 4326))\n\texpect_silent(st_write(multi, pg, \"meuse_multi\", overwrite = TRUE))\n\tmulti2 <- cbind(pts[[\"geometry\"]], st_set_crs(st_transform(pts, 4326), NA))\n\texpect_silent(st_write(multi2, pg, \"meuse_multi2\", overwrite = TRUE))\n\texpect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi\", quiet = TRUE))\n\t# expect_equal(st_crs(x[[\"geometry\"]]), st_crs(multi[[\"geometry\"]])) -->> not generally true in case of different EPSG databases\n\texpect_equal(st_crs(x[[\"geometry.1\"]]), st_crs(multi[[\"geometry.1\"]]))\n\texpect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi\", quiet = TRUE, type = c(1,4)))\n\texpect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi\", quiet = TRUE, type = c(4,4)))\n\texpect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi\", quiet = TRUE, promote_to_multi = FALSE))\n\texpect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi\", quiet = TRUE, geometry_column = \"geometry.1\"))\n\tx <- st_layers(\"PG:host=localhost dbname=postgis\")\n\texpect_silent(x <- st_read(pg, \"meuse_multi2\"))\n\t# expect_equal(st_crs(x[[\"geometry\"]]), st_crs(multi2[[\"geometry\"]])) #-->> not generally the case, this CRS varies accross installations (EPSG db versions)\n\texpect_equal(st_crs(x[[\"geometry.1\"]]), st_crs(multi2[[\"geometry.1\"]]))\n\texpect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi2\", quiet = TRUE))\n\t#expect_equal(st_crs(x[[\"geometry\"]]), st_crs(multi2[[\"geometry\"]]))\n\texpect_equal(st_crs(x[[\"geometry.1\"]]), st_crs(multi2[[\"geometry.1\"]]))\n})\n\ntest_that(\"RPostgreSQL driver can use `geometry_column` (#1045)\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tquery <- \"SELECT 'POINT(0 0)'::geometry as a, 'POINT(1 0)'::geometry as b\"\n\tx <- st_read(pg, query = query)\n\texpect_equal(x$a, st_sfc(st_point(c(0, 0))))\n\texpect_equal(x$b, st_sfc(st_point(c(1, 0))))\n\tx <- st_read(pg, query = query, geometry_column = c(\"a\", \"b\"))\n\texpect_equal(x$a, st_sfc(st_point(c(0, 0))))\n\texpect_equal(x$b, st_sfc(st_point(c(1, 0))))\n\tx <- st_read(pg, query = query, geometry_column = c(\"b\"))\n\texpect_equal(x$a, \"010100000000000000000000000000000000000000\")\n\texpect_equal(x$b, st_sfc(st_point(c(1, 0))))\n\texpect_error(st_read(pg, query = query, geometry_column = c(\"b\", \"c\")), \"Could not find\")\n})\n\ntest_that(\"sf can write units to database (#264)\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tptsu <- pts\n\tptsu[[\"u\"]] <- ptsu[[\"cadmium\"]]\n\tunits(ptsu[[\"u\"]]) <- units::as_units(\"km\")\n\texpect_silent(st_write(ptsu, pg, \"sf_units__\", overwrite = TRUE))\n\tr <- st_read(pg, \"sf_units__\")\n\texpect_type(r[[\"u\"]], \"double\")\n\texpect_equal(sort(r[[\"u\"]]), sort(as.numeric(ptsu[[\"u\"]])))\n\tdbRemoveTable(pg, \"sf_units__\")\n})\n\ntest_that(\"sf can preserve types (#592)\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tdtypes <- data.frame(\n\t\tlogi = c(TRUE, FALSE, NA),\n\t\tchara = c(\"a\", \"\", NA),\n\t\tnume = c(1.1e1, 2.2e2, NA),\n\t\tinte = c(1L, 2L, NA),\n\t\tfact = factor(c(\"a\", \"b\", NA), levels = letters),\n\t\t#comp = c(complex(1, 2), complex(2, 3)),\n\t\tdate = rep(Sys.Date(), 3),\n\t\ttime = rep(Sys.time(), 3),\n\t\tx = c(1, 2, 4),\n\t\ty = c(1, 2, 4), stringsAsFactors = FALSE)\n\t# cannot write lists\n\t#dtypes$lst <- c(list(matrix(\"a\")), list(matrix(c(\"b\", \"c\"))), list(NA))\n\tdtypes <- st_as_sf(dtypes, coords = c(\"x\", \"y\"))\n\tst_write(dtypes, pg, overwrite = TRUE)\n\tx <- st_read(pg, \"dtypes\")\n\tdtypes$fact <- as.character(dtypes$fact)\n\tdtypes$fact <- as.character(dtypes$fact)\n\texpect_equal(x[-7], dtypes[-7])  # ignore POSIXct timezone issue\n\tDBI::dbRemoveTable(pg, \"dtypes\")\n})\n\ntest_that(\"can write to other schema\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\ttry(DBI::dbSendQuery(pg, \"CREATE SCHEMA sf_test__;\"), silent = TRUE)\n\tq <- \"SELECT schema_name FROM information_schema.schemata WHERE schema_name = 'sf_test__';\"\n\tsuppressWarnings(could_schema <- DBI::dbGetQuery(pg, q) |> nrow() > 0)\n\n\tskip_if_not(could_schema, \"Could not create schema (might need to run 'GRANT CREATE ON DATABASE postgis TO <user>')\")\n\texpect_error(st_write(pts, pg, c(\"public\", \"sf_meuse__\")), \"exists\")\n\texpect_silent(st_write(pts, pg, c(\"sf_test__\", \"sf_meuse__\")))\n\texpect_error(st_write(pts, pg, c(\"sf_test__\", \"sf_meuse__\")), \"exists\")\n\texpect_silent(st_write(pts, pg, c(\"sf_test__\", \"sf_meuse__\"), overwrite = TRUE))\n\texpect_warning(z <- st_set_crs(pts, epsg_31370))\n\texpect_silent(st_write(z, pg, c(\"sf_test__\", \"sf_meuse33__\")))\n\texpect_silent(st_write(z, pg, c(\"sf_test__\", \"sf_meuse4__\")))\n\n\t# weird name work\n\texpect_silent(st_write(pts, pg, c(NULL, \"sf_test__.meuse__\"), overwrite = TRUE))\n\texpect_silent(st_write(pts.2 <- pts, pg, overwrite = TRUE))\n\texpect_true(DBI::dbRemoveTable(pg, \"pts.2 <- pts\"))\n})\n\ntest_that(\"support for capital names (#571)\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\texpect_silent(st_write(pts, pg, \"Meuse_tbl\"))\n\texpect_true(DBI::dbRemoveTable(pg, \"Meuse_tbl\"))\n\ttry(DBI::dbSendQuery(pg, \"CREATE SCHEMA \\\"CAP__\\\";\"), silent = TRUE)\n\tq <- \"SELECT schema_name FROM information_schema.schemata WHERE schema_name = 'CAP__';\"\n\tsuppressWarnings(could_schema <- DBI::dbGetQuery(pg, q) |> nrow() > 0)\n\tskip_if_not(could_schema, \"Could not create schema (might need to run 'GRANT CREATE ON DATABASE postgis TO <user>')\")\n\texpect_silent(st_write(pts, pg, c(\"CAP__\", \"Meuse_tbl\")))\n\texpect_true(DBI::dbRemoveTable(pg, c(\"CAP__\", \"Meuse_tbl\")))\n\tdbExecute(pg, 'DROP SCHEMA \"CAP__\" CASCADE;')\n})\n\ntest_that(\"can read from db\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tq <- \"select * from sf_meuse__\"\n\t#expect_warning(x <- st_read(pg, query = q), \"crs\")\n\texpect_silent(x <- st_read(pg, query = q))\n\n\texpect_error(st_read(pg), \"Provide either a `layer` or a `query`\")\n\n\ty <- st_read(pg, \"sf_meuse__\")\n\texpect_equal(dim(pts), dim(y))\n\texpect_identical(st_crs(pts), st_crs(y))\n\texpect_identical(st_precision(pts), st_precision(y))\n\n\texpect_warning(z <- st_read(pg, \"sf_meuse3__\"), \"code \\\\d+ not found\")\n\texpect_equal(dim(pts), dim(z))\n\t#expect_identical(st_crs(NA), st_crs(z))\n\texpect_true(st_crs(epsg_31370) == st_crs(z))\n\texpect_identical(st_precision(pts), st_precision(z))\n\n\tw <- st_read(pg, c(\"sf_test__\", \"sf_meuse__\"))\n\texpect_equal(dim(y), dim(w))\n\texpect_identical(st_crs(y), st_crs(w))\n\texpect_identical(st_precision(y), st_precision(w))\n\n\t#Make sure it doesn't set column with all NAs to geometry:\n\tsf_meuseNA__ <- pts\n\tsf_meuseNA__$dummy <- rep(NA_character_, nrow(sf_meuseNA__))\n\tst_write(sf_meuseNA__, pg, c(\"sf_test__\", \"sf_meuse_na__\"), quiet = TRUE)\n\tz <- st_read(pg, query = \"SELECT * FROM sf_test__.sf_meuse_na__\", quiet = TRUE)\n\texpect_equal(sum(vapply(z, inherits, logical(1), \"sfc\")), 1)\n\texpect_equal(attr(z, \"sf_column\"), \"geometry\")\n\texpect_true(dbRemoveTable(pg, c(\"sf_test__\", \"sf_meuse_na__\")))\n\n\texpect_error(st_read(pg, \"missing\"), \"attempt to set an attribute on NULL\")\n\texpect_error(st_read(pg, c(\"missing\", \"missing\")), \"attempt to set an attribute on NULL\")\n\t# make sure it reads in the correct schema\n\texpect_error(st_read(pg, c(\"sf_test__\", \"sf_meuse3__\")), \"attempt to set an attribute on NULL\")\n})\n\ntest_that(\"can read views (#212)\", {\n\tskip_if_not(Sys.getenv(\"USER\") != \"edzer\") # this stopped working for me\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\texpect_equal(DBI::dbExecute(pg,\n\t\t\t\t\t\t\t\t\"CREATE VIEW sf_view__ AS SELECT * FROM sf_meuse__;\"), 0)\n\texpect_equal(DBI::dbExecute(pg,\n\t\t\t\t\t\t\t\t\"CREATE VIEW sf_test__.sf_view__ AS SELECT * FROM sf_meuse__;\"), 0)\n\texpect_equal(DBI::dbExecute(pg,\n\t\t\t\t\t\t\t\t\"CREATE MATERIALIZED VIEW sf_viewm__ AS SELECT * FROM sf_meuse__;\"), 155)\n\texpect_equal(DBI::dbExecute(pg,\n\t\t\t\t\t\t\t\t\"CREATE MATERIALIZED VIEW sf_test__.sf_viewm__ AS SELECT * FROM sf_meuse__;\"), 155)\n\tx <- st_read(pg, \"sf_meuse__\")\n\texpect_identical(st_read(pg, \"sf_view__\"), x)\n\texpect_identical(st_read(pg, c(\"public\", \"sf_view__\")), x)\n\texpect_identical(st_read(pg, c(\"sf_test__\", \"sf_view__\")), x)\n\texpect_identical(st_read(pg, c(\"sf_viewm__\")), x)\n\texpect_identical(st_read(pg, c(\"sf_test__\", \"sf_viewm__\")), x)\n\n\ttry(DBI::dbExecute(pg, \"DROP VIEW sf_view__\"), silent = TRUE)\n\ttry(DBI::dbExecute(pg, \"DROP VIEW sf_test__.sf_view__\"), silent = TRUE)\n\ttry(DBI::dbExecute(pg, \"DROP MATERIALIZED VIEW sf_viewm__\"), silent = TRUE)\n\ttry(DBI::dbExecute(pg, \"DROP MATERIALIZED VIEW sf_test__.sf_viewm__\"), silent = TRUE)\n})\n\ntest_that(\"round trips\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tround_trip = function(conn, wkt) {\n\t\tquery = paste0(\"SELECT '\", wkt, \"'::geometry;\")\n\t\treturnstr = suppressWarnings(DBI::dbGetQuery(conn, query)$geometry)\n\t\twkb = structure(returnstr, class = \"WKB\")\n\t\tret = st_as_sfc(wkb, EWKB = TRUE)\n\t\tmessage(paste(\"IN:  \", wkt, \"\\n\"))\n\t\t# OUT contains WKB created in PostGIS from wkt, interpreted to R by sf, printed as WKT by sf\n\t\tmessage(paste(\"OUT: \", txt <- st_as_text(ret, EWKT=TRUE)[[1]], \"\\n\"))\n\t\tif (length(grep(\"SRID\", txt)) == 0) {\n\t\t\tquery = paste0(\"SELECT ST_AsText('\",sf:::CPL_raw_to_hex(st_as_binary(ret[[1]])),\"');\")\n\t\t\treceived = suppressWarnings(DBI::dbGetQuery(conn, query)$st_astext)\n\t\t\t# PG: contains the PostGIS WKT, after reading the WKB created by sf from R native\n\t\t\tmessage(paste(\"PG:  \", received, \"\\n\"))\n\t\t}\n\t\texpect_equal(wkt, txt)\n\t}\n\tround_trip(pg, \"SRID=4326;POINT M (0 0 0)\")\n\tround_trip(pg, \"POINT Z (0 0 0)\")\n\tround_trip(pg, \"POINT ZM (0 0 0 0)\")\n\tround_trip(pg, \"POINT (0 0)\")\n\tround_trip(pg, \"LINESTRING (0 0, 1 1, 2 2)\")\n\tround_trip(pg, \"MULTIPOINT ((0 0), (1 1), (2 2))\")\n\tround_trip(pg, \"POLYGON ((0 0, 1 0, 1 1, 0 0))\")\n\tround_trip(pg, \"MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((2 2, 3 2, 3 3, 2 2)))\")\n\tround_trip(pg, paste(\"MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0),\",\n\t\t\t\t\t\t \"(0.2 0.2, 0.8 0.2, 0.8 0.8, 0.2 0.2)),\",\n\t\t\t\t\t\t \"((2 2, 3 2, 3 3, 2 2)))\"))\n\tround_trip(pg, paste(\"MULTILINESTRING ((0 0, 1 0, 1 1, 0 0),\",\n\t\t\t\t\t\t \"(0.2 0.2, 0.8 0.2, 0.8 0.8, 0.2 0.2),\",\n\t\t\t\t\t\t \"(2 2, 3 2, 3 3, 2 2))\"))\n\n\t# other types; examples taken from the PostGIS manuals (ch 4):\n\tround_trip(pg, \"CIRCULARSTRING (0 0, 1 1, 1 0)\")\n\tround_trip(pg, \"CIRCULARSTRING (0 0, 4 0, 4 4, 0 4, 0 0)\")\n\tround_trip(pg, paste(\"CURVEPOLYGON (CIRCULARSTRING (0 0, 4 0, 4 4, 0 4, 0 0),\",\n\t\t\t\t\t\t \"LINESTRING (1 1, 3 3, 3 1, 1 1))\"))\n\tround_trip(pg, paste(\"COMPOUNDCURVE (CIRCULARSTRING (0 0, 1 1, 1 0),\",\n\t\t\t\t\t\t \"LINESTRING (1 0, 0 1))\"))\n\tround_trip(pg, paste0(\"CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (0 0, 2 0, 2 1, 2 3, 4 3), \",\n\t\t\t\t\t\t  \"LINESTRING (4 3, 4 5, 1 4, 0 0)), \",\n\t\t\t\t\t\t  \"CIRCULARSTRING (1.7 1, 1.4 0.4, 1.6 0.4, 1.6 0.5, 1.7 1))\"))\n\tround_trip(pg, \"MULTICURVE (LINESTRING (0 0, 5 5), CIRCULARSTRING (4 0, 4 4, 8 4))\")\n\tround_trip(pg, paste(\"MULTISURFACE (CURVEPOLYGON (CIRCULARSTRING (0 0, 4 0, 4 4, 0 4, 0 0),\",\n\t\t\t\t\t\t \"LINESTRING (1 1, 3 3, 3 1, 1 1)),\",\n\t\t\t\t\t\t \"POLYGON ((10 10, 14 12, 11 10, 10 10),\",\n\t\t\t\t\t\t \"(11 11, 11.5 11, 11 11.5, 11 11)))\"))\n\n\tround_trip(pg, paste(\"MULTICURVE (LINESTRING (0 0, 5 5),\",\n\t\t\t\t\t\t \"CIRCULARSTRING (4 0, 4 4, 8 4))\"))\n\tround_trip(pg, paste(\"POLYHEDRALSURFACE Z (((0 0 0, 0 0 1, 0 1 1, 0 1 0, 0 0 0)),\",\n\t\t\t\t\t\t \"((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)),\",\n\t\t\t\t\t\t \"((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)),\",\n\t\t\t\t\t\t \"((1 1 0, 1 1 1, 1 0 1, 1 0 0, 1 1 0)),\",\n\t\t\t\t\t\t \"((0 1 0, 0 1 1, 1 1 1, 1 1 0, 0 1 0)),\",\n\t\t\t\t\t\t \"((0 0 1, 1 0 1, 1 1 1, 0 1 1, 0 0 1)))\"))\n\tround_trip(pg, \"TRIANGLE ((0 0, 0 9, 9 0, 0 0))\")\n\tround_trip(pg, \"TIN Z (((0 0 0, 0 0 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 0 0 0)))\")\n})\n\ntest_that(\"can read using driver\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tlayers <- st_layers(\"PG:host=localhost dbname=postgis\")\n\tlyr_expect <- sort(c(\"sf_meuse__\", \"sf_meuse2__\", \"sf_meuse3__\", \"meuse_multi2\",\n\t\t\t\t\t\t \"sf_test__.sf_meuse__\",  \"sf_test__.meuse__\",\n\t\t\t\t\t\t \"sf_test__.sf_meuse33__\", \"sf_test__.sf_meuse4__\"))\n\texpect_true(all(lyr_expect %in% layers$name))\n\texpect_true(all(layers$features == 155))\n\texpect_true(all(layers$fields == 12))\n\n    empty <- try(\n        DBI::dbConnect(\n            RPostgres::Postgres(),\n            host = \"localhost\",\n            dbname = \"empty\"),\n        silent=TRUE\n    )\n    skip_if_not(\n        can_con(empty),\n        \"could not connect to 'empty' database\"\n    )\n    expect_error(st_read(\"PG:dbname=empty\", quiet = TRUE), \"No layers\")\n})\n\ntest_that(\"Can safely manipulate crs\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tsrid <- 4326\n\texpect_true(sf:::get_postgis_crs(pg, srid) == st_crs(srid))\n\texpect_error(sf:::set_postgis_crs(pg, st_crs(srid)))\n\texpect_warning(expect_true(is.na(st_crs(sf:::get_new_postgis_srid(pg)))), \"not found\")\n\tnew_crs <- st_crs(sf:::get_new_postgis_srid(pg), \"+proj=longlat +datum=WGS84 +no_defs\", valid = FALSE)\n\texpect_message(sf:::set_postgis_crs(pg, new_crs, auth_name = \"sf_test\"), \"Inserted local crs\")\n\texpect_warning(expect_error(sf:::set_postgis_crs(pg, new_crs), \"duplicate key\"),\n\t\t\t\t   \"not found\")\n\texpect_equal(sf:::delete_postgis_crs(pg, new_crs), 1)\n\texpect_equal(sf:::delete_postgis_crs(pg, new_crs), 0)\n})\n\ntest_that(\"new SRIDs are handled correctly\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tdata(meuse, package = \"sp\")\n\tmeuse_sf = st_as_sf(meuse, coords = c(\"x\", \"y\"), crs = NA_crs_)\n\n\tcrs = st_crs(NA_integer_, paste(\"+proj=sterea +lat_0=52 +lon_0=5\", # creates FALSE, but new one\n\t\t\t\t\t\t\t\t\t\"+k=1.0 +x_0=155000 +y_0=463000 +ellps=bessel\",\n\t\t\t\t\t\t\t\t\t\"+towgs84=565.4171,50.3319,465.5524,-0.398957,0.343988,\",\n\t\t\t\t\t\t\t\t\t\"-1.87740,4.0725 +units=m +no_defs\"), valid = FALSE)\n\tst_crs(meuse_sf) = crs\n\texpect_message(st_write(meuse_sf, pg, overwrite = TRUE), \"Inserted local crs\")\n\texpect_warning(x <- st_read(pg, query = \"select * from meuse_sf limit 3;\"),\n\t\t\t\t   \"not found in EPSG support files\")\n\texpect_true(st_crs(x)$proj4string == crs$proj4string)\n\texpect_silent(st_write(meuse_sf, pg, overwrite = TRUE))\n})\n\ntest_that(\"schema_table\", {\n\texpect_error(sf:::schema_table(pg, NA), \"character vector\")\n\texpect_error(sf:::schema_table(pg, NA_character_), \"cannot be NA\")\n\texpect_error(sf:::schema_table(pg, \"a\", NA), \"cannot be NA\")\n\texpect_error(sf:::schema_table(pg, letters), \"longer than 2\")\n\texpect_equal(sf:::schema_table(pg, \"a\", \"b\"), c(\"b\", \"a\"))\n\texpect_equal(sf:::schema_table(pg, \"a\"), c(\"public\", \"a\"))\n})\n\nif (can_con(pg)) {\n\t# cleanup\n\ttry(db_drop_table_schema(pg, \"meuse_sf\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"meuse_multi\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"sf_meuse__\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"sf_meuse2__\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"sf_meuse3__\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"meuse_multi2\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, '\"sf_test__.meuse__\"'), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"sf_test__\", \"sf_meuse__\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"sf_test__\", \"sf_meuse2__\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"sf_test__\", \"sf_meuse33__\"), silent = TRUE)\n\ttry(db_drop_table_schema(pg, \"sf_test__\", \"sf_meuse4__\"), silent = TRUE)\n\ttry(DBI::dbExecute(pg, \"DROP SCHEMA sf_test__ CASCADE;\"), silent = TRUE)\n\ttry(DBI::dbExecute(pg, \" DELETE FROM spatial_ref_sys WHERE auth_name = 'sf';\"), silent = TRUE)\n\ttry(DBI::dbDisconnect(pg), silent = TRUE)\n}\n"
  },
  {
    "path": "tests/testthat/test-postgis_RPostgres.R",
    "content": "#' To run the tests from the database, you can setup a docker container\n#' and run it as needed.\n#' docker run \\\n#'   --name \"postgis_test\" \\\n#'   -p 5432:5432 \\\n#'   -e POSTGRES_USER=$USER \\\n#'   -e POSTGRES_PASS=$USER \\\n#'   -e POSTGRES_DBNAME=postgis \\\n#'   -d -t kartoza/postgis\n#'  docker start postgis\nskip_on_os(\"solaris\")\nskip_if_not_installed(\"RPostgres\")\n\nlibrary(sf)\nlibrary(DBI)\nlibrary(RPostgres)\nlibrary(testthat)\n\ncan_con <- function(x) inherits(x, \"PqConnection\")\n\ndb_drop_table_schema <- function(con, schema, table = NULL) {\n    if (is.null(table)) {\n        table <- paste(c(\"public\", schema), collapse = \".\")\n    } else {\n        table <- paste(c(schema, table), collapse = \".\")\n    }\n    DBI::dbExecute(pg, paste(\"DROP TABLE \", table, \" CASCADE;\"))\n}\nrequire(\"sp\")\ndata(meuse)\npts <- st_as_sf(meuse, coords = c(\"x\", \"y\"), crs = 28992)\n\nepsg_31370 = paste0(\"+proj=lcc +lat_1=51.16666723333333 +lat_2=49.8333339 \",\n                    \"+lat_0=90 +lon_0=4.367486666666666 +x_0=150000.013 \",\n                    \"+y_0=5400088.438 +ellps=intl +towgs84=-106.869,52.2978,\",\n                    \"-103.724,0.3366,-0.457,1.8422,-1.2747 +units=m +no_defs\")\n\npg <- NULL\ntest_that(\"check utils\", expect_false(can_con(pg)))\ntry(pg <- DBI::dbConnect(\n\tRPostgres::Postgres(),\n\thost = \"localhost\",\n\tdbname = \"postgis\",\n\tpassword = Sys.info()[[\"user\"]]), silent=TRUE)\n\n# tests ------------------------------------------------------------------------\ntest_that(\"can write to db\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    expect_silent(suppressMessages(st_write(pts, pg, \"sf_meuse__\")))\n    expect_error(st_write(pts, pg, \"sf_meuse__\", append = FALSE, delete_layer = FALSE), \"exists\")\n    expect_silent(st_write(pts, pg, \"sf_meuse__\", delete_layer = TRUE))\n    expect_silent(st_write(pts, pg, \"sf_meuse2__\", binary = FALSE))\n    suppressWarnings(z <- st_set_crs(pts, epsg_31370))\n    expect_message(st_write(z, pg, \"sf_meuse3__\"), \"Inserted local crs\")\n    expect_silent(st_write(z, pg, \"sf_meuse3__\", append = TRUE))\n    expect_equal(nrow(DBI::dbReadTable(pg, \"sf_meuse3__\")), nrow(z) * 2)\n    expect_silent(sf3 <- st_write(z, pg, \"sf_meuse3__\", delete_layer = TRUE))\n    expect_true(st_crs(sf3) == st_crs(epsg_31370))\n    # also test write_sf options\n    expect_error(write_sf(pts, pg, \"sf_meuse__\", append = FALSE, delete_layer = FALSE), \"exists\")\n    expect_silent(write_sf(pts, pg, \"sf_meuse__\", delete_layer = TRUE))\n    expect_error(write_sf(pts, pg, \"sf_meuse__\", append = FALSE, delete_layer = FALSE))\n    expect_error(write_sf(pts[1, ], pg, \"sf_meuse__\", append = TRUE, delete_layer = TRUE))\n    expect_error(write_sf(pts, pg, \"sf_meuse__\", overwrite = TRUE), \"deprecated\")\n    expect_silent(write_sf(pts[1, ], pg, \"sf_meuse__\", append = TRUE))\n\n    p2 <- st_read(pg, \"sf_meuse__\")\n    expect_equal(nrow(p2), nrow(pts) + 1)\n    expect_silent(write_sf(pts, pg, \"sf_meuse__\", delete_layer = TRUE))\n})\n\ntest_that(\"can create a missing table even if append is TRUE (#2206)\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tx <- st_sf(geometry = st_sfc(st_point(1:2)))\n\tdbWriteTable(pg, \"x\", x, append = TRUE, temporary = TRUE)\n\tcol_type <- dbGetQuery(pg, \"SELECT pg_typeof(geometry) as col_type FROM x\")\n\texpect_equal(unclass(col_type[[\"col_type\"]]), \"geometry\")\n\tdbExecute(pg, \"drop table if exists x\")\n})\n\ntest_that(\"can handle multiple geom columns\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    multi <- cbind(pts[[\"geometry\"]], st_transform(pts, 4326))\n    expect_silent(st_write(multi, pg, \"meuse_multi\", delete_layer = TRUE))\n    expect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi\", quiet = TRUE))\n    # expect_equal(st_crs(x[[\"geometry\"]]), st_crs(multi[[\"geometry\"]])) -> fails if EPSG databases differ\n    expect_true(st_crs(x[[\"geometry.1\"]]) == st_crs(multi[[\"geometry.1\"]]))\n    expect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi\", quiet = TRUE, type = c(1,4)))\n    expect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi\", quiet = TRUE, type = c(4,4)))\n    expect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi\", quiet = TRUE, promote_to_multi = FALSE))\n    expect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi\", quiet = TRUE, geometry_column = \"geometry.1\"))\n    x <- st_layers(\"PG:host=localhost dbname=postgis\")\n    multi2 <- cbind(pts[[\"geometry\"]], st_set_crs(st_transform(pts, 4326), NA))\n    expect_silent(st_write(multi2, pg, \"meuse_multi2\", delete_layer = TRUE))\n    expect_silent(x <- st_read(pg, \"meuse_multi2\"))\n    expect_equal(st_crs(x[[\"geometry\"]]), st_crs(multi2[[\"geometry\"]]))\n    expect_equal(st_crs(x[[\"geometry.1\"]]), st_crs(multi2[[\"geometry.1\"]]))\n    expect_silent(x <- st_read(\"PG:host=localhost dbname=postgis\", \"meuse_multi2\", quiet = TRUE))\n    #expect_equal(st_crs(x[[\"geometry\"]]), st_crs(multi2[[\"geometry\"]]))\n    expect_equal(st_crs(x[[\"geometry.1\"]]), st_crs(multi2[[\"geometry.1\"]]))\n})\n\ntest_that(\"sf can write units to database (#264)\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    ptsu <- pts\n    ptsu[[\"u\"]] <- ptsu[[\"cadmium\"]]\n    units(ptsu[[\"u\"]]) <- units::as_units(\"km\")\n    expect_silent(st_write(ptsu, pg, \"sf_units__\", delete_layer = TRUE))\n    r <- st_read(pg, \"sf_units__\")\n    expect_type(r[[\"u\"]], \"double\")\n    expect_equal(sort(r[[\"u\"]]), sort(as.numeric(ptsu[[\"u\"]])))\n    dbRemoveTable(pg, \"sf_units__\")\n})\n\ntest_that(\"sf can read non-sf tables with geometries\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    expect_warning(st_read(pg, query = \"select 1 as a\"), \"Could not find a simple features geometry column.\")\n    expect_silent(st_read(pg, query = \"SELECT 'POINT(1 1)'::geometry\"))\n    expect_silent(st_read(pg, query = \"SELECT 'POINT(1 1)'::geometry as a, 'POINT(2 2)'::geometry as b\"))\n})\n\ntest_that(\"returns an `sf` object (#1039)\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    expect_s3_class(st_read(pg, query = \"SELECT 'POINT(1 1)'::geometry\"), \"sf\")\n    expect_s3_class(st_read(pg, query = \"SELECT 'POINT(1 1)'::geometry\", as_tibble = TRUE), \"sf\")\n    expect_s3_class(read_sf(pg, query = \"SELECT 'POINT(1 1)'::geometry\"), \"sf\")\n})\n\ntest_that(\"validates arguments\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    expect_error(st_read(pg), \"Provide either a `layer` or a `query`\")\n    expect_warning(st_read(pg, \"sf_meuse__\", query = \"select * from sf_meuse__\"), \"You provided both `layer` and `query`\")\n    expect_error(st_read(pg, \"sf_meuse__\", random_arg = \"a\"), \"Unused arguments:\")\n    expect_error(st_read(pg, \"sf_meuse__\", table = \"a\"), \"`layer` rather than `table`\")\n    expect_error(st_read(pg, \"sf_meuse__\", table = \"a\", x = 1, y = 2), \"`layer` rather than `table`\")\n})\n\ntest_that(\"sf can write non-sf tables with geometries\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    df <- as.data.frame(pts)\n    expect_silent(st_write(df, pg, \"df\"))\n    expect_silent(dfx <- st_read(pg, \"df\"))\n    expect_equal(df[[\"geometry\"]], dfx[[\"geometry\"]])\n    expect_silent(DBI::dbRemoveTable(pg, \"df\"))\n})\n\ntest_that(\"sf can write non-sf tables with multiple geometries\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    df <- as.data.frame(pts)\n    df$geography <- st_transform(df$geometry, 4326)\n    expect_silent(st_write(df, pg, \"df\"))\n    expect_silent(dfx <- st_read(pg, \"df\"))\n    expect_equal(df[[\"geometry\"]], dfx[[\"geometry\"]])\n    expect_equal(df[[\"geography\"]], dfx[[\"geography\"]])\n    expect_silent(DBI::dbRemoveTable(pg, \"df\"))\n})\n\ntest_that(\"tidy workflow can write multiple geometries\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    df <- tibble::as_tibble(pts)\n    df <- dplyr::mutate(df, geography = st_transform(geometry, 4326))\n    expect_silent(write_sf(df, pg, \"df\"))\n    on.exit(DBI::dbRemoveTable(pg, \"df\"))\n    expect_silent(dfx <- read_sf(pg, \"df\"))\n    expect_equal(df[[\"geometry\"]], dfx[[\"geometry\"]])\n    expect_equal(df[[\"geography\"]], dfx[[\"geography\"]])\n})\n\ntest_that(\"sf can preserve types (#592)\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    dtypes <- data.frame(\n        logi = c(TRUE, FALSE, NA),\n        chara = c(\"a\", \"\", NA),\n        nume = c(1.1e1, 2.2e2, NA),\n        inte = c(1L, 2L, NA),\n        fact = factor(c(\"a\", \"b\", NA), levels = letters),\n        #comp = c(complex(1, 2), complex(2, 3)),\n        date = c(rep(Sys.Date(), 2), NA),\n        time = c(rep(Sys.time(), 2), NA),\n        x = c(1, 2, 4),\n        y = c(1, 2, 4), stringsAsFactors = FALSE)\n    # cannot write lists\n    #dtypes$lst <- c(list(matrix(\"a\")), list(matrix(c(\"b\", \"c\"))), list(NA))\n    dtypes <- st_as_sf(dtypes, coords = c(\"x\", \"y\"))\n    st_write(dtypes, pg, delete_layer = TRUE)\n    x <- st_read(pg, \"dtypes\")\n    dtypes$fact <- as.character(dtypes$fact)\n    # R 4.1; EP:\n    attr(x$time, \"tzone\") = attr(dtypes$time, \"tzone\") = NULL\n    expect_equal(x, dtypes)\n    DBI::dbRemoveTable(pg, \"dtypes\")\n})\n\ntest_that(\"can write to other schema\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    try(DBI::dbSendQuery(pg, \"CREATE SCHEMA sf_test__;\"), silent = TRUE)\n    q <- \"SELECT schema_name FROM information_schema.schemata WHERE schema_name = 'sf_test__';\"\n    suppressWarnings(could_schema <- DBI::dbGetQuery(pg, q) |> nrow() > 0)\n    skip_if_not(could_schema, \"Could not create schema (might need to run 'GRANT CREATE ON DATABASE postgis TO <user>')\")\n    tbl_meuse_public <- Id(schema = \"public\", table = \"sf_meuse__\")\n    tbl_meuse_test <- Id(schema = \"sf_test__\", table = \"sf_meuse__\")\n    expect_error(st_write(pts, pg, tbl_meuse_public, append = FALSE, delete_layer = FALSE), \"exists\")\n    expect_silent(st_write(pts, pg, tbl_meuse_test))\n    expect_error(st_write(pts, pg, tbl_meuse_test, append = FALSE, delete_layer = FALSE), \"exists\")\n    expect_silent(st_write(pts, pg, tbl_meuse_test, delete_layer = TRUE))\n    expect_warning(z <- st_set_crs(pts, epsg_31370))\n    expect_silent(st_write(z, pg, Id(schema = \"sf_test__\", table = \"sf_meuse33__\")))\n    expect_silent(st_write(z, pg, Id(schema = \"sf_test__\", table = \"sf_meuse4__\")))\n\n    # weird name work\n    expect_silent(st_write(pts, pg, c(NULL, \"sf_test__.meuse__\"), delete_layer = TRUE))\n    expect_silent(st_write(pts.2 <- pts, pg, delete_layer = TRUE))\n    expect_true(DBI::dbRemoveTable(pg, \"pts.2 <- pts\"))\n})\n\ntest_that(\"support for capital names (#571)\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    expect_silent(st_write(pts, pg, \"Meuse_tbl\"))\n    expect_true(DBI::dbRemoveTable(pg, \"Meuse_tbl\"))\n    try(DBI::dbSendQuery(pg, \"CREATE SCHEMA \\\"CAP__\\\";\"), silent = TRUE)\n    q <- \"SELECT schema_name FROM information_schema.schemata WHERE schema_name = 'CAP__';\"\n    suppressWarnings(could_schema <- DBI::dbGetQuery(pg, q) |> nrow() > 0)\n    skip_if_not(could_schema, \"Could not create schema (might need to run 'GRANT CREATE ON DATABASE postgis TO <user>')\")\n    expect_silent(st_write(pts, pg, Id(schema = \"CAP__\", table = \"Meuse_tbl\")))\n    expect_true(DBI::dbRemoveTable(pg, Id(schema = \"CAP__\", table = \"Meuse_tbl\")))\n    dbExecute(pg, 'DROP SCHEMA \"CAP__\" CASCADE;')\n})\n\ntest_that(\"can read from db\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    q <- \"select * from sf_meuse__\"\n    #expect_warning(x <- st_read(pg, query = q), \"crs\")\n    expect_silent(x <- st_read(pg, query = q))\n\n    expect_error(st_read(pg), \"Provide either a `layer` or a `query`\")\n\n    y <- st_read(pg, \"sf_meuse__\")\n    expect_equal(dim(pts), dim(y))\n    expect_identical(st_crs(pts), st_crs(y))\n    expect_identical(st_precision(pts), st_precision(y))\n\n    expect_warning(z <- st_read(pg, \"sf_meuse3__\"), \"Could not find database srid\")\n    expect_equal(dim(pts), dim(z))\n    #expect_identical(st_crs(NA), st_crs(z))\n    expect_true(st_crs(epsg_31370) == st_crs(z))\n    expect_identical(st_precision(pts), st_precision(z))\n\n    w <- st_read(pg, DBI::Id(schema = \"sf_test__\", table = \"sf_meuse__\"))\n    expect_equal(dim(y), dim(w))\n    expect_identical(st_crs(y), st_crs(w))\n    expect_identical(st_precision(y), st_precision(w))\n\n    expect_error(st_read(pg, \"missing\"), \"not exist\")\n    expect_error(st_read(pg,  DBI::Id(schema = \"missing\", table = \"missing\")), \"not exist\")\n    # make sure it reads in the correct schema\n    expect_error(st_read(pg, DBI::Id(schema = \"sf_test__\", table = \"sf_meuse3__\")), \"not exist\")\n})\n\ntest_that(\"can read views (#212)\", {\n    skip_if_not(Sys.getenv(\"USER\") != \"edzer\") # this stopped working for me\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    expect_equal(DBI::dbExecute(pg,\n                                \"CREATE VIEW sf_view__ AS SELECT * FROM sf_meuse__;\"), 0)\n    expect_equal(DBI::dbExecute(pg,\n                                \"CREATE VIEW sf_test__.sf_view__ AS SELECT * FROM sf_meuse__;\"), 0)\n    expect_equal(DBI::dbExecute(pg,\n                                \"CREATE MATERIALIZED VIEW sf_viewm__ AS SELECT * FROM sf_meuse__;\"), 155)\n    expect_equal(DBI::dbExecute(pg,\n                                \"CREATE MATERIALIZED VIEW sf_test__.sf_viewm__ AS SELECT * FROM sf_meuse__;\"), 155)\n    x <- st_read(pg, \"sf_meuse__\")\n    expect_identical(st_read(pg, \"sf_view__\"), x)\n    expect_identical(st_read(pg, DBI::Id(schema = \"public\", table = \"sf_view__\")), x)\n    expect_identical(st_read(pg, DBI::Id(schema = \"sf_test__\", table = \"sf_view__\")), x)\n    expect_identical(st_read(pg, \"sf_viewm__\"), x)\n    expect_identical(st_read(pg, DBI::Id(schema = \"sf_test__\", table = \"sf_viewm__\")), x)\n\n    # cleanup ------------------------------------------------------------------\n    try(DBI::dbExecute(pg, \"DROP VIEW sf_view__\"), silent = TRUE)\n    try(DBI::dbExecute(pg, \"DROP VIEW sf_test__.sf_view__\"), silent = TRUE)\n    try(DBI::dbExecute(pg, \"DROP MATERIALIZED VIEW sf_viewm__\"), silent = TRUE)\n    try(DBI::dbExecute(pg, \"DROP MATERIALIZED VIEW sf_test__.sf_viewm__\"), silent = TRUE)\n})\n\ntest_that(\"round trips\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    round_trip = function(conn, wkt) {\n        query = paste0(\"SELECT '\", wkt, \"'::geometry;\")\n        returnstr = suppressWarnings(DBI::dbGetQuery(conn, query)$geometry)\n        wkb = structure(returnstr, class = \"WKB\")\n        ret = st_as_sfc(wkb, EWKB = TRUE)\n        message(paste(\"IN:  \", wkt, \"\\n\"))\n        # OUT contains WKB created in PostGIS from wkt, interpreted to R by sf, printed as WKT by sf\n        message(paste(\"OUT: \", txt <- st_as_text(ret, EWKT=TRUE)[[1]], \"\\n\"))\n        if (length(grep(\"SRID\", txt)) == 0) {\n            query = paste0(\"SELECT ST_AsText('\",sf:::CPL_raw_to_hex(st_as_binary(ret[[1]])),\"');\")\n            received = suppressWarnings(DBI::dbGetQuery(conn, query)$st_astext)\n            # PG: contains the PostGIS WKT, after reading the WKB created by sf from R native\n            message(paste(\"PG:  \", received, \"\\n\"))\n        }\n        expect_equal(wkt, txt)\n    }\n    round_trip(pg, \"SRID=4326;POINT M (0 0 0)\")\n    round_trip(pg, \"POINT Z (0 0 0)\")\n    round_trip(pg, \"POINT ZM (0 0 0 0)\")\n    round_trip(pg, \"POINT (0 0)\")\n    round_trip(pg, \"LINESTRING (0 0, 1 1, 2 2)\")\n    round_trip(pg, \"MULTIPOINT ((0 0), (1 1), (2 2))\")\n    round_trip(pg, \"POLYGON ((0 0, 1 0, 1 1, 0 0))\")\n    round_trip(pg, \"MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((2 2, 3 2, 3 3, 2 2)))\")\n    round_trip(pg, paste(\"MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0),\",\n                         \"(0.2 0.2, 0.8 0.2, 0.8 0.8, 0.2 0.2)),\",\n                         \"((2 2, 3 2, 3 3, 2 2)))\"))\n    round_trip(pg, paste(\"MULTILINESTRING ((0 0, 1 0, 1 1, 0 0),\",\n                         \"(0.2 0.2, 0.8 0.2, 0.8 0.8, 0.2 0.2),\",\n                         \"(2 2, 3 2, 3 3, 2 2))\"))\n\n    # other types; examples taken from the PostGIS manuals (ch 4):\n    round_trip(pg, \"CIRCULARSTRING (0 0, 1 1, 1 0)\")\n    round_trip(pg, \"CIRCULARSTRING (0 0, 4 0, 4 4, 0 4, 0 0)\")\n    round_trip(pg, paste(\"CURVEPOLYGON (CIRCULARSTRING (0 0, 4 0, 4 4, 0 4, 0 0),\",\n                         \"LINESTRING (1 1, 3 3, 3 1, 1 1))\"))\n    round_trip(pg, paste(\"COMPOUNDCURVE (CIRCULARSTRING (0 0, 1 1, 1 0),\",\n                         \"LINESTRING (1 0, 0 1))\"))\n    round_trip(pg, paste0(\"CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (0 0, 2 0, 2 1, 2 3, 4 3), \",\n                          \"LINESTRING (4 3, 4 5, 1 4, 0 0)), \",\n                          \"CIRCULARSTRING (1.7 1, 1.4 0.4, 1.6 0.4, 1.6 0.5, 1.7 1))\"))\n    round_trip(pg, \"MULTICURVE (LINESTRING (0 0, 5 5), CIRCULARSTRING (4 0, 4 4, 8 4))\")\n    round_trip(pg, paste(\"MULTISURFACE (CURVEPOLYGON (CIRCULARSTRING (0 0, 4 0, 4 4, 0 4, 0 0),\",\n                         \"LINESTRING (1 1, 3 3, 3 1, 1 1)),\",\n                         \"POLYGON ((10 10, 14 12, 11 10, 10 10),\",\n                         \"(11 11, 11.5 11, 11 11.5, 11 11)))\"))\n\n    round_trip(pg, paste(\"MULTICURVE (LINESTRING (0 0, 5 5),\",\n                         \"CIRCULARSTRING (4 0, 4 4, 8 4))\"))\n    round_trip(pg, paste(\"POLYHEDRALSURFACE Z (((0 0 0, 0 0 1, 0 1 1, 0 1 0, 0 0 0)),\",\n                         \"((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0)),\",\n                         \"((0 0 0, 1 0 0, 1 0 1, 0 0 1, 0 0 0)),\",\n                         \"((1 1 0, 1 1 1, 1 0 1, 1 0 0, 1 1 0)),\",\n                         \"((0 1 0, 0 1 1, 1 1 1, 1 1 0, 0 1 0)),\",\n                         \"((0 0 1, 1 0 1, 1 1 1, 0 1 1, 0 0 1)))\"))\n    round_trip(pg, \"TRIANGLE ((0 0, 0 9, 9 0, 0 0))\")\n    round_trip(pg, \"TIN Z (((0 0 0, 0 0 1, 0 1 0, 0 0 0)), ((0 0 0, 0 1 0, 1 1 0, 0 0 0)))\")\n})\n\ntest_that(\"can read using driver\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    layers <- st_layers(\"PG:host=localhost dbname=postgis\")\n    lyr_expect <- sort(c(\"sf_meuse__\", \"sf_meuse2__\", \"sf_meuse3__\", \"meuse_multi2\",\n                         \"sf_test__.sf_meuse__\",  \"sf_test__.meuse__\",\n                         \"sf_test__.sf_meuse33__\", \"sf_test__.sf_meuse4__\"))\n    expect_true(all(lyr_expect %in% layers$name))\n    expect_true(all(layers$features == 155))\n    expect_true(all(layers$fields == 12))\n\n    empty <- try(\n        DBI::dbConnect(\n            RPostgres::Postgres(),\n            host = \"localhost\",\n            dbname = \"empty\"),\n        silent = TRUE\n    )\n    skip_if_not(\n        can_con(empty),\n        \"could not connect to 'empty' database\"\n    )\n    expect_error(st_read(\"PG:dbname=empty\", quiet = TRUE), \"No layers\") # EJP: removed host=localhost\n})\n\ntest_that(\"Can override local crs\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\tewkb <- c(\n\t\twgs84 =       sf:::db_binary(st_set_crs(st_sfc(st_point(1:2)), 4326)),\n\t\tunavailable = sf:::db_binary(st_set_crs(st_sfc(st_point(1:2)), sf:::make_empty_crs(1111))),\n\t\tmissing =     sf:::db_binary(st_sfc(st_point(1:2)))\n\t)\n\n\tqueries <- paste0(\"select st_srid('\", ewkb, \"'::geometry) as srid\")\n\n\texpect_equal(dbGetQuery(pg, queries[1])[[\"srid\"]], 4326)\n\texpect_equal(dbGetQuery(pg, queries[2])[[\"srid\"]], 1111)\n\texpect_equal(dbGetQuery(pg, queries[3])[[\"srid\"]], 0)\n})\n\ntest_that(\"Can safely manipulate crs\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    srid <- 4326\n    crs <- st_crs(srid)\n    expect_true(sf:::db_find_srid(pg, srid = srid) == st_crs(srid))\n    expect_true(sf:::db_find_srtext(pg, crs) == st_crs(srid))\n    expect_error(sf:::db_insert_crs(pg, st_crs(srid)), \"already exists\")\n    expect_warning(expect_true(is.na(st_crs(sf:::get_new_postgis_srid(pg)))), \"not found\")\n    new_crs <- sf:::make_empty_crs(\n    \tepsg = sf:::get_new_postgis_srid(pg),\n    \ttext = \"+proj=longlat +datum=WGS84 +no_defs\"\n    )\n    expect_message(sf:::db_insert_crs(pg, new_crs, auth_name = \"sf_test\"), \"Inserted local crs\")\n    expect_error(sf:::db_insert_crs(pg, new_crs), \"duplicate key\")\n    expect_equal(sf:::delete_postgis_crs(pg, new_crs), 1)\n    expect_equal(sf:::delete_postgis_crs(pg, new_crs), 0)\n\n    # set and delete\n    new_crs <- sf:::make_empty_crs(\n    \tepsg = NA,\n    \ttext = st_as_text(st_crs(epsg_31370))\n    )\n    expect_message(new_srid <- sf:::db_insert_crs(pg, new_crs), \"Inserted local crs\")\n    expect_error(sf:::delete_postgis_crs(pg, new_crs), \"Missing SRID\")\n\n    crs2 <- sf:::make_empty_crs(sf:::epsg(new_srid), st_as_text(st_crs(3857)))\n    expect_equal(sf:::delete_postgis_crs(pg, crs2), 0)  # crs doesn't match any crs\n    expect_equal(sf:::delete_postgis_crs(pg, new_srid), 1)\n\n    # udpate\n    expect_message(sf:::db_insert_crs(pg, new_srid), \"Inserted local crs\")\n    new_srid[[\"wkt\"]] <- crs2[[\"wkt\"]]\n    expect_error(sf:::db_insert_crs(pg, new_srid), \"already exists\")\n    expect_message(sf:::db_insert_crs(pg, new_srid, update = TRUE), \"Inserted local crs\")\n})\n\n\ntest_that(\"new SRIDs are handled correctly\", {\n\tskip_if_not(can_con(pg), \"could not connect to postgis database\")\n\n\tcrs <- sf:::make_empty_crs(\n\t\tepsg = NA,\n\t\twkt = st_as_text(st_crs(epsg_31370))\n\t)\n\tsuppressWarnings(st_crs(pts) <- crs)\n\n\texpect_warning(x <- st_read(pg, query = \"select * from sf_meuse3__ limit 3;\"),\n\t\t\t\t   \"Could not find database srid\")\n\texpect_true(st_as_text(st_crs(x)) == st_as_text(crs))\n})\n\ntest_that(\"schema_table\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n\texpect_error(sf:::schema_table(pg, NA), \"character vector\")\n\texpect_error(sf:::schema_table(pg, NA_character_), \"cannot be NA\")\n\texpect_error(sf:::schema_table(pg, \"a\", NA), \"cannot be NA\")\n\texpect_error(sf:::schema_table(pg, letters), \"longer than 2\")\n\texpect_equal(sf:::schema_table(pg, \"a\", \"b\"), c(\"b\", \"a\"))\n\texpect_equal(sf:::schema_table(pg, \"a\"), c(\"public\", \"a\"))\n})\n\ntest_that(\"Can find a crs\", {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    expect_equal(sf:::db_find_srid(pg, st_crs(NA)), st_crs(NA))\n    expect_error(sf:::delete_postgis_crs(pg, st_crs(NA)), \"M|missing (crs)|(SRID)\")\n})\n\nif (can_con(pg)) {\n    skip_if_not(can_con(pg), \"could not connect to postgis database\")\n    # cleanup\n    try(db_drop_table_schema(pg, \"meuse_sf\"), silent = TRUE)\n    try(db_drop_table_schema(pg, \"meuse_multi\"), silent = TRUE)\n    try(db_drop_table_schema(pg, \"sf_meuse__\"), silent = TRUE)\n    try(db_drop_table_schema(pg, \"sf_meuse2__\"), silent = TRUE)\n    try(db_drop_table_schema(pg, \"sf_meuse3__\"), silent = TRUE)\n    try(db_drop_table_schema(pg, \"meuse_multi2\"), silent = TRUE)\n    try(db_drop_table_schema(pg, '\"sf_test__.meuse__\"'), silent = TRUE)\n    try(db_drop_table_schema(pg, \"sf_test__\", \"sf_meuse__\"), silent = TRUE)\n    try(db_drop_table_schema(pg, \"sf_test__\", \"sf_meuse2__\"), silent = TRUE)\n    try(db_drop_table_schema(pg, \"sf_test__\", \"sf_meuse33__\"), silent = TRUE)\n    try(db_drop_table_schema(pg, \"sf_test__\", \"sf_meuse4__\"), silent = TRUE)\n    try(DBI::dbExecute(pg, \"DROP SCHEMA sf_test__ CASCADE;\"), silent = TRUE)\n    try(DBI::dbExecute(pg, \" DELETE FROM spatial_ref_sys WHERE auth_name = 'sf';\"), silent = TRUE)\n    try(DBI::dbDisconnect(pg), silent = TRUE)\n}\n\n"
  },
  {
    "path": "tests/testthat/test-proj.R",
    "content": "test_that(\"sf_project works\", {\n  sf_project(pts = matrix(0:1, 1, 2), st_crs(4326), st_crs(3587))\n})\n"
  },
  {
    "path": "tests/testthat/test-read.R",
    "content": "test_that(\"we can read a shapefile using st_read\", {\n  nc <- st_read(system.file(\"shape/nc.shp\", package = \"sf\"), \"nc\", crs = 4267, quiet = TRUE)\n  expect_s3_class(nc, c(\"sf\", \"data.frame\"), exact = TRUE)\n  expect_equal(dim(nc), c(100, 15))\n})\n\ntest_that(\"we can read shapefiles with a query string\", {\n    nc <- st_read(system.file(\"shape/nc.shp\", package=\"sf\"), \"nc\", crs = 4267, quiet = TRUE)\n    nc_all <- st_read(system.file(\"shape/nc.shp\", package=\"sf\"), query = \"select * from nc\", crs = 4267, quiet = TRUE)\n    nc_some <- st_read(system.file(\"shape/nc.shp\", package=\"sf\"), query = \"select * from nc where SID79 > 50\", crs = 4267, quiet = TRUE)\n})\n\ntest_that(\"st_read.default gives error messages\", {\n  expect_error(st_read(), \"dsn should specify a data source or filename\")\n  expect_error(st_read(NULL), \"no st_read method available for objects of class NULL\")\n})\n\ntest_that(\"st_write.sf gives error messages on unknown dsn\", {\n  expect_error(st_write(st_sf(st_sfc(st_point())), NULL), \"no st_write method available for dsn of class NULL\")\n})\n\ntest_that(\"stringsAsFactors = FALSE produces a data.frame with no factors\", {\n  nc <-  st_read(system.file(\"shape/nc.shp\", package=\"sf\"), \"nc\", crs = 4267,\n                 stringsAsFactors = FALSE, quiet = TRUE)\n  expect_false(any(sapply(nc, class) == \"factor\"))\n})\n\ntest_that(\"stringsAsFactors = TRUE produces a data.frame with factors\", {\n  nc <-  st_read(system.file(\"shape/nc.shp\", package=\"sf\"), \"nc\", crs = 4267,\n                 stringsAsFactors = TRUE, quiet = TRUE)\n  expect_true(any(sapply(nc, class) == \"factor\"))\n})\n\ntest_that(\"drivers extensions are all lowercase\", {\n  expect_equal(names(extension_map), tolower(names(extension_map)))\n  expect_equal(names(prefix_map), tolower(names(prefix_map)))\n})\n\ntest_that(\"guess_driver is strict\", {\n  expect_error(guess_driver(c(\"PG:xyz\", \"x.shp\")), \"length\")\n  expect_error(guess_driver(1), \"character\")\n})\n\ntest_that(\"guess_driver works on extensions\", {\n  # for repeatability, this is how I turned the list to tests\n  # `^\"(\\w+)\" = (\"[\\w\\s]+\"),?`\n  # to `expect_equal(guess_driver(\"nc.\\1\"), c(\"\\1\" = \\2))`\n\n  expect_equal(guess_driver(\"nc.bna\"), c(\"bna\" = \"BNA\"))\n  expect_equal(guess_driver(\"nc.csv\"), c(\"csv\" = \"CSV\"))\n  expect_equal(guess_driver(\"nc.e00\"), c(\"e00\" = \"AVCE00\"))\n  expect_equal(guess_driver(\"nc.gdb\"), c(\"gdb\" = \"OpenFileGDB\"))\n  expect_equal(guess_driver(\"nc.geojson\"), c(\"geojson\" = \"GeoJSON\"))\n  expect_equal(guess_driver(\"nc.gml\"), c(\"gml\" = \"GML\"))\n  expect_equal(guess_driver(\"nc.gmt\"), c(\"gmt\" = \"GMT\"))\n  expect_equal(guess_driver(\"nc.gpkg\"), c(\"gpkg\" = \"GPKG\"))\n  expect_equal(guess_driver(\"nc.gps\"), c(\"gps\" = \"GPSBabel\"))\n  expect_equal(guess_driver(\"nc.gtm\"), c(\"gtm\" = \"GPSTrackMaker\"))\n  expect_equal(guess_driver(\"nc.gxt\"), c(\"gxt\" = \"Geoconcept\"))\n  expect_equal(guess_driver(\"nc.kml\"), c(\"kml\" = \"KML\"))\n  expect_equal(guess_driver(\"nc.jml\"), c(\"jml\" = \"JML\"))\n  expect_equal(guess_driver(\"nc.map\"), c(\"map\" = \"WAsP\"))\n  expect_equal(guess_driver(\"nc.mdb\"), c(\"mdb\" = \"Geomedia\"))\n  expect_equal(guess_driver(\"nc.nc\"), c(\"nc\" = \"netCDF\"))\n  expect_equal(guess_driver(\"nc.ods\"), c(\"ods\" = \"ODS\"))\n  expect_equal(guess_driver(\"nc.osm\"), c(\"osm\" = \"OSM\"))\n  expect_equal(guess_driver(\"nc.pbf\"), c(\"pbf\" = \"OSM\"))\n  expect_equal(guess_driver(\"nc.shp\"), c(\"shp\" = \"ESRI Shapefile\"))\n  expect_equal(guess_driver(\"nc.sqlite\"), c(\"sqlite\" = \"SQLite\"))\n  expect_equal(guess_driver(\"nc.vdv\"), c(\"vdv\" = \"VDV\"))\n  expect_equal(guess_driver(\"nc.xls\"), c(\"xls\" = \"xls\"))\n  expect_equal(guess_driver(\"nc.xlsx\"), c(\"xlsx\" = \"XLSX\"))\n\n  # unsuported\n  expect_equal(guess_driver(\"nc.notsupported\"), NA)\n})\n\ntest_that(\"guess_driver works on suffixes\", {\n  # for repeatability, this is how I turned the list to tests\n  # `^\"(\\w+)\" = (\"[\\w\\s]+\"),?`\n  # to `expect_equal(guess_driver(\"nc.\\1\"), c(\"\\1\" = \\2))`\n\n  expect_equal(guess_driver(\"couchdb:nc\"), c(\"couchdb\" = \"CouchDB\"))\n  expect_equal(guess_driver(\"db2odbc:nc\"), c(\"db2odbc\" = \"DB2ODBC\"))\n  expect_equal(guess_driver(\"dods:nc\"), c(\"dods\" = \"DODS\"))\n  expect_equal(guess_driver(\"gft:nc\"), c(\"gft\" = \"GFT\"))\n  expect_equal(guess_driver(\"mssql:nc\"), c(\"mssql\" = \"MSSQLSpatial\"))\n  expect_equal(guess_driver(\"mysql:nc\"), c(\"mysql\" = \"MySQL\"))\n  expect_equal(guess_driver(\"oci:nc\"), c(\"oci\" = \"OCI\"))\n  expect_equal(guess_driver(\"odbc:nc\"), c(\"odbc\" = \"ODBC\"))\n  expect_equal(guess_driver(\"pg:nc\"), c(\"pg\" = \"PostgreSQL\"))\n  expect_equal(guess_driver(\"sde:nc\"), c(\"sde\" = \"SDE\"))\n\n  # upper case\n  expect_equal(guess_driver(\"CouchDB:nc\"), c(\"couchdb\" = \"CouchDB\"))\n  expect_equal(guess_driver(\"db2ODBC:nc\"), c(\"db2odbc\" = \"DB2ODBC\"))\n  expect_equal(guess_driver(\"DODS:nc\"), c(\"dods\" = \"DODS\"))\n  expect_equal(guess_driver(\"GFT:nc\"), c(\"gft\" = \"GFT\"))\n  expect_equal(guess_driver(\"MSSQL:nc\"), c(\"mssql\" = \"MSSQLSpatial\"))\n  expect_equal(guess_driver(\"MYSQL:nc\"), c(\"mysql\" = \"MySQL\"))\n  expect_equal(guess_driver(\"OCI:nc\"), c(\"oci\" = \"OCI\"))\n  expect_equal(guess_driver(\"ODBC:nc\"), c(\"odbc\" = \"ODBC\"))\n  expect_equal(guess_driver(\"PG:nc\"), c(\"pg\" = \"PostgreSQL\"))\n  expect_equal(guess_driver(\"SDE:nc\"), c(\"sde\" = \"SDE\"))\n\n  # unsuported\n  expect_equal(guess_driver(\"notsupported:nc\"), NA)\n})\n\ntest_that(\"weird names are supported\", {\n  expect_equal(guess_driver(\"pg:nc.shp\"), c(\"pg\" = \"PostgreSQL\"))\n  expect_equal(guess_driver(\"pg:nc.shp.e00\"), c(\"pg\" = \"PostgreSQL\"))\n  expect_equal(guess_driver(\"nc.shp.e00\"), c(\"e00\" = \"AVCE00\"))\n  expect_equal(guess_driver(\"couchdb:shp\"), c(\"couchdb\" = \"CouchDB\"))\n\n  expect_equal(guess_driver(\"notsupported:nc.shp\"), NA)\n  expect_equal(guess_driver(\"notsupported\"), NA)\n})\n\ntest_that(\"driver utils work\", {\n  expect_true(is_driver_available(\"shp\", data.frame(name = c(\"x\", \"y\", \"shp\"))))\n  expect_true(is_driver_available(\"shp\", data.frame(name = c(\"shp\"))))\n  expect_false(is_driver_available(\"shp\", data.frame(name = c(\"x\", \"y\", \"z\"))))\n  expect_false(is_driver_available(\"shp\", data.frame(name = c(\"x\", \"y\", \"z\"))))\n\n  expect_error(is_driver_can(\"shp\", data.frame(name = c(\"x\", \"y\", \"shp\")), operation = \"nothing\"))\n  expect_error(is_driver_can(\"shp\", data.frame(name = c(\"x\", \"y\")), operation = \"nothing\"))\n  expect_true(is_driver_can(\"shp\", data.frame(name = c(\"x\", \"y\", \"shp\"), write = rep(TRUE, 3)), operation = \"write\"))\n  expect_false(is_driver_can(\"shp\", data.frame(name = c(\"x\", \"y\", \"shp\"), write = c(TRUE, TRUE, FALSE)), operation = \"write\"))\n})\n\ntest_that(\"guess_driver_can_write\", {\n  expect_error(guess_driver_can_write(\"x.e00\", NA), \"Could not guess\")\n  expect_error(guess_driver_can_write(\"x.not\", c(\"nothing\" = \"nothing\")), \"not available\")\n  expect_equal(guess_driver_can_write(\"x.csv\"), c(\"csv\" = \"CSV\"))\n  expect_equal(guess_driver_can_write(\"c:/x.csv\"), c(\"csv\" = \"CSV\"))\n\n  expect_error(guess_driver_can_write(\"x.unsuported\"), \"Could not guess driver\")\n  expect_error(guess_driver_can_write(\"unsuported:x\"), \"Could not guess driver\")\n})\n\ntest_that(\"driver operations\", {\n  # These tests are driver specifics to GDAL version and OS.\n  expect_error(guess_driver_can_write(\"x.e00\"), \"AVCE00 driver not available|cannot write\")\n  # expect_error(guess_driver_can_write(\"x.gdb\"), \"cannot write\") -> no longer the case when GDAL >= 3.6.0\n\n  expect_equal(guess_driver_can_write(\"x.geojson\"), c(\"geojson\" = \"GeoJSON\"))\n  expect_equal(guess_driver_can_write(\"x.csv\"), c(\"csv\" = \"CSV\"))\n  expect_equal(guess_driver_can_write(\"x.gml\"), c(\"gml\" = \"GML\"))\n})\n\ntest_that(\"guess driver on windows with backslashes (#127)\", {\n    expect_identical(guess_driver(\"c:\\\\Temp\\\\this.shp\"),\n                     guess_driver(\"c:/Temp/this.shp\"))\n})\n\ntest_that(\"the first layer is selected with a warning\", {\n    skip_on_os(\"mac\")\n\n\texpect_warning(st_read(system.file(\"osm/overpass.osm\", package=\"sf\"), quiet = TRUE),\n\t\t\"automatically selected the first layer\")\n\texpect_error(st_read(system.file(\"osm/overpass.osm\", package=\"sf\"), \"foo\", quiet = TRUE),\n\t\t\"Opening layer failed\")\n})\n\ntest_that(\"we get a warning when not specifying one of multiple layers\", {\n \tskip_if_not(\"OSM\" %in% st_drivers()$name && Sys.info()['sysname'] != \"Darwin\")\n\n\tSys.setenv(OSM_USE_CUSTOM_INDEXING=\"NO\")\n\tosm = system.file(\"osm/overpass.osm\", package=\"sf\")\n\texpect_warning(st_read(osm, quiet = TRUE),\n\t\t\"automatically selected the first layer in a data source containing more than one.\")\n})\n\ntest_that(\"reading non-spatial table works\", {\n    skip_if_not(sf_extSoftVersion()[[\"GDAL\"]] >= \"2.2.0\") # error on OSX for 2.1.3\n\n    expect_warning(st_read(system.file(\"gpkg/nospatial.gpkg\", package = \"sf\")),\n                   \"no simple feature geometries present\")\n    expect_warning(\n        expect_s3_class(st_read(system.file(\"gpkg/nospatial.gpkg\", package = \"sf\")),\n                        \"data.frame\"),\n        \"no simple feature geometries\"\n    )\n#   expect_warning(\n#       expect_s3_class(read_sf(system.file(\"gpkg/nospatial.gpkg\", package = \"sf\")),\n#             \"tbl_df\"),\n#       \"no simple feature geometries\"\n#   )\n})\n\ntest_that(\"Missing data sources have useful error message (#967)\", {\n\t# write temporary file\n\tx <- tempfile(fileext = \".kml\")\n\tcat(\"empty\", file = x)\n\n\texpect_error(st_read(tempfile(fileext = \".csv\")), \"The file doesn't seem to exist.\")\n\texpect_error(st_read(\"PG:host=wrong\"), \"Check connection parameters.\")\n\texpect_error(st_read(x), \"The source could be corrupt or not supported.\")\n\texpect_error(st_read(\"\"), \"not an empty string.\")\n\n\t# delete temp file\n\tfile.remove(x)\n})\n"
  },
  {
    "path": "tests/testthat/test-s2.R",
    "content": "skip_if_not_installed(\"s2\")\ntest_that(\"s2 roundtrips work\", {\n  library(s2)\n  nc = st_geometry(st_read(system.file(\"shape/nc.shp\", package=\"sf\")))\n  s2 = st_as_sfc(st_as_s2(nc), crs = st_crs(nc))\n\n  # precision?\n  # FIXME this test appears to be failing?\n  # expect_equal(sum(lengths(st_equals(s2, nc))), 0L)\n  expect_equal(sum(lengths(st_equals(st_set_precision(s2, 1e8), st_set_precision(nc, 1e8))) == 1), 98L)\n  expect_equal(sum(lengths(st_equals(st_set_precision(s2, 1e7), st_set_precision(nc, 1e7))) == 1), 100L)\n})\n\ntest_that(\"as_s2_geography() is defined for sf and sfc objects\", {\n  nc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\n  expect_s3_class(s2::as_s2_geography(nc), \"s2_geography\")\n  expect_s3_class(s2::as_s2_geography(st_geometry(nc)), \"s2_geography\")\n})\n\ntest_that(\"s2 polygon creation\", {\n  outer = rbind(c(10,35),  # CCW:\n      c(20,10),\n      c(40,15),\n      c(45,45),\n      c(10,35))\n  inner = rbind(c(30,20), # CW:\n      c(20,30),\n      c(35,35),\n      c(30,20))\n#  expect_silent(l <- s2polyline(outer))\n#  expect_error(p <- s2polygon(l))\n#  expect_silent(l <- s2polyline(outer[1:4,]))\n#  expect_silent(p <- s2polygon(l))\n\n#  expect_silent(i <- s2polyline(inner))\n#  expect_error(p <- s2polygon(i))\n#  expect_silent(i <- s2polyline(inner[1:3,]))\n#  expect_silent(p <- s2polygon(i))\n})\n"
  },
  {
    "path": "tests/testthat/test-sample.R",
    "content": "test_that(\"st_sample works\", {\n\tskip_if_not_installed(\"lwgeom\")\n\tnc = read_sf(system.file(\"shape/nc.shp\", package=\"sf\"))\n\tn = 100\n\tsample_default = st_sample(x = nc, size = n)\n\texpect_s3_class(sample_default, \"sfc\")\n\tsample_exact = st_sample(x = nc, size = n, exact = TRUE)\n\texpect_length(sample_exact, n)\n})\n"
  },
  {
    "path": "tests/testthat/test-sf.R",
    "content": "test_that(\"we can subset sf objects\", {\n  pt1 = st_point(1:2)\n  pt2 = st_point(3:4)\n  s1 = st_sf(a = c(\"x\", \"y\"), geom = st_sfc(pt1, pt2))\n  expect_equal(as.character(s1[[1]]), c(\"x\", \"y\"))\n  expect_equal(s1[,1], s1) #data.frame(x = c(\"x\", \"y\")))\n\n  expect_equal(nrow(s1[1,]), 1)\n  expect_equal(c(st_bbox(s1[1,])), c(xmin=1,ymin=2,xmax=1,ymax=2))\n\n  a = c(\"x\", \"y\")\n  g = st_sfc(pt1, pt2)\n  expect_silent(xxx <- st_sf(a, g, g))\n  expect_silent(st_sf(a, geom1 = g, geom2 = g, sf_column_name = \"geom2\"))\n  x = st_sf(a, geom1 = g, geom2 = g, sf_column_name = \"geom2\")\n  expect_silent(st_geometry(x) <- \"geom2\")\n  expect_silent(st_geometry(x) <- \"geom1\")\n})\n\ntest_that(\"we can create points sf from data.frame\", {\n  skip_if_not_installed(\"sp\")\n  data(meuse, package = \"sp\") # load data.frame from sp\n  meuse_sf = st_as_sf(meuse, coords = c(\"x\", \"y\"), crs = 28992)\n  meuse_sf[1:5,]\n  summary(meuse_sf[1:5,])\n  expect_s3_class(meuse_sf, c(\"sf\", \"data.frame\"), exact = TRUE)\n})\n\ntest_that(\"st_zm works\", {\n  pt = st_point(1:2)\n  ptz = st_point(1:3, \"XYZ\")\n  ptm = st_point(1:3, \"XYM\")\n  ptzm = st_point(1:4, \"XYZM\")\n  pl = st_multilinestring(list(matrix(1:10,,2), matrix(1:10,,2)))\n  plz = st_multilinestring(list(matrix(1:15,,3), matrix(1:15,,3)), \"XYZ\")\n  plm = st_multilinestring(list(matrix(1:15,,3), matrix(1:15,,3)), \"XYM\")\n  plzm = st_multilinestring(list(matrix(1:20,,4), matrix(1:20,,4)), \"XYZM\")\n  expect_identical(pt, st_zm(ptz))\n  expect_identical(pt, st_zm(ptm))\n  expect_identical(pt, st_zm(ptzm))\n  expect_identical(pl, st_zm(plz))\n  expect_identical(pl, st_zm(plm))\n  expect_identical(pl, st_zm(plzm))\n  expect_identical(st_sfc(pt,pl), st_zm(st_sfc(ptz,plz)))\n  expect_identical(st_sfc(pt,pl), st_zm(st_sfc(ptm,plm)))\n  expect_identical(st_sfc(pt,pl), st_zm(st_sfc(ptzm,plzm)))\n  expect_identical(st_sf(a = 1:2, geom = st_sfc(pt,pl)), st_zm(st_sf(a = 1:2, geom = st_sfc(ptzm,plzm))))\n  expect_identical(st_zm(pt, drop = FALSE, what = \"Z\"), st_point(c(1:2,0)))\n  expect_silent(st_zm(pl, drop = FALSE, what = \"Z\"))\n})\n\ntest_that(\"rbind/cbind work\", {\n  # cbind/rbind:\n  x = st_sf(a = 1:2, geom = st_sfc(list(st_point(0:1), st_point(0:1)), crs = 4326))\n  # don't warn when replacing crs with identical value:\n  if (version$major == \"3\") {\n  \tif (version$minor >= \"3.0\") {\n      expect_silent(xxx <- cbind(x, x, x))\n      rbind(x, x, x)\n\t}\n  }\n})\n\ntest_that(\"st_as_sf bulk points work\", {\n  skip_if_not_installed(\"sp\")\n  data(meuse, package = \"sp\") # load data.frame from sp\n  x <- meuse\n  meuse_sf = st_as_sf(x, coords = c(\"x\", \"y\"), crs = 28992)\n  xyz_sf = st_as_sf(x, coords = c(\"y\", \"x\", \"dist\"))\n  xym_sf = st_as_sf(x, coords = c(\"y\", \"x\", \"dist\"), dim = \"XYM\")\n  xyzm_sf = st_as_sf(x, coords = c(\"x\", \"y\", \"dist\", \"zinc\"), dim = \"XYZM\")\n  expect_s3_class(meuse_sf, c(\"sf\", \"data.frame\"), exact = TRUE)\n  expect_s3_class(xyz_sf,   c(\"sf\", \"data.frame\"), exact = TRUE)\n  expect_s3_class(xym_sf,   c(\"sf\", \"data.frame\"), exact = TRUE)\n  expect_s3_class(xyzm_sf,  c(\"sf\", \"data.frame\"), exact = TRUE)\n  expect_length(st_geometry(meuse_sf)[[1]], 2L)\n  expect_length(st_geometry(xyz_sf)[[1]], 3L)\n  expect_length(st_geometry(xym_sf)[[1]], 3L)\n  expect_length(st_geometry(xyzm_sf)[[1]], 4L)\n\n\n})\n\ntest_that(\"transform work\", {\n  skip_if_not_installed(\"sp\")\n  data(meuse, package = \"sp\")\n  x  = st_as_sf(meuse, coords = c(\"x\", \"y\"), crs = 28992)\n  x2 = transform(x, elev2 = elev^2, lead_zinc = lead/zinc)\n  expect_s3_class(x, \"sf\")\n  expect_identical(class(x2), class(x))\n  expect_identical(st_bbox(x), st_bbox(x))\n  expect_identical(st_crs(x), st_crs(x))\n  expect_identical(x$elev^2, x2$elev2)\n})\n\ntest_that(\"empty agr attribute is named after subset\", {\n\tsf = st_sf(data.frame(x = st_sfc(st_point(1:2))))\n\tout = sf[, \"geometry\"]\n\tagr = attr(out, \"agr\")\n\texpect_named(agr, character())\n})\ntest_that(\"duplicated work\",{\n\tsf = st_sf(data.frame(x = st_sfc(st_point(1:2))[rep(1,4)], a=gl(2,2), b=as.numeric(gl(2,2))))\n\texpect_identical(duplicated(sf), c(FALSE,TRUE,FALSE,TRUE))\n\texpect_s3_class(unique(sf), \"sf\")\n})\n"
  },
  {
    "path": "tests/testthat/test-sfc.R",
    "content": "test_that(\"we can print sfc objects\", {\n  pt1 = st_point(1:2)\n  pt2 = st_point(3:4)\n  s1 = st_sf(a = c(\"x\", \"y\"), geom = st_sfc(pt1, pt2))\n  expect_output(print(s1), \"Simple feature collection\")\n  expect_output(print(st_sfc()), \"Geometry set for 0 features\")\n  expect_length(st_sfc(), 0)\n})\n\ntest_that(\"st_is_longlat works\", {\n  pt1 = st_point(1:2)\n  pt2 = st_point(3:4)\n  s1 = st_sf(a = c(\"x\", \"y\"), geom = st_sfc(pt1, pt2))\n  expect_equal(st_is_longlat(s1), NA)\n  s2 = s1\n  st_crs(s2) = 3857\n  expect_false(st_is_longlat(s2))\n  st_crs(s1) = 4326\n  expect_true(st_is_longlat(s1))\n})\n\ntest_that(\"st_crs returns NA for sfg objects\", {\n  pt1 = st_point(1:2)\n  expect_true(is.na(st_crs(pt1)))\n})\n\ntest_that(\"st_as_binary handles non-native big endian\", {\n  gc = st_geometrycollection()\n  r = st_as_binary(gc)\n  r[1] = if (r[1] == 1) {\n  \tas.raw(0)\n  } else {\n  \tas.raw(1)\n  }\n  r[2:5] = rev(r[2:5]) # swap bytes\n  expect_identical(gc, st_as_sfc(structure(list(r), class = \"WKB\"), pureR = TRUE)[[1]])\n  expect_identical(gc, st_as_sfc(structure(list(r), class = \"WKB\"), pureR = TRUE, EWKB = TRUE)[[1]])\n})\n\ntest_that(\"st_crs<- gives warnings on changing crs\", {\n\tx = st_sfc(list(st_point(0:1), st_point(0:1)))\n\ty = x\n\texpect_silent(st_crs(y) <- 4326)\n\texpect_silent(st_crs(y) <- 4326)\n\texpect_warning(st_crs(y) <- 3857)\n\tx = st_sfc(list(st_point(0:1), st_point(0:1)), crs = 4326)\n\t#expect_silent(st_sfc(x, crs = \"+proj=longlat +datum=WGS84 +no_defs\"))\n\t#expect_silent(st_sfc(x, crs = \"+proj=longlat +datum=WGS84\")) #-->> breaks build on CRAN flavor fedora-gcc\n\t# but do when it changes:\n\texpect_warning(st_sfc(x, crs = \"+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs\"))\n})\n\ntest_that(\"st_precision()\", {\n    x <- st_sfc(st_point(c(pi, pi)), precision = 1e-4, crs = 3857) # units m\n    expect_equal(st_precision(x), 1e-4)\n    expect_error(st_set_precision(x, NULL))\n    expect_error(st_set_precision(x, NA), \"numeric\")\n    expect_error(st_set_precision(x, list()), \"length\")\n    expect_error(st_set_precision(x, list(x = 1)), \"numeric\")\n    expect_error(st_set_precision(x, 1:4), \"length\")\n    expect_error(st_set_precision(x, NA_real_), \"numeric\")\n    st_precision(x) <- 1e-2\n    expect_identical(st_set_precision(x, 1e-2), x)\n\n\texpect_identical(x, st_set_precision(x, units::set_units(100, m)))\n\texpect_error(st_set_precision(x, units::set_units(100, kg)))\n\tx <- st_transform(x, 4326)\n\texpect_silent(st_set_precision(x, units::set_units(0.001, rad)))\n\texpect_silent(st_set_precision(x, units::set_units(0.1, degree)))\n\texpect_error(st_set_precision(x, units::set_units(0.001, degree_C)))\n})\n\ntest_that(\"st_precision() works for sf\", {\n    x <- st_as_sf(data.frame(\"a\" = 1), \n                  st_sfc(st_point(c(pi, pi)), precision = 1e-4))\n    expect_equal(st_precision(x), 1e-4)\n    expect_error(st_set_precision(x, NULL))\n    expect_error(st_set_precision(x, NA), \"numeric\")\n    expect_error(st_set_precision(x, list()), \"length\")\n    expect_error(st_set_precision(x, list(x = 1)), \"numeric\")\n    expect_error(st_set_precision(x, 1:4), \"length\")\n    expect_error(st_set_precision(x, NA_real_), \"numeric\")\n    st_precision(x) <- 1e-2\n    expect_identical(st_set_precision(x, 1e-2), x)\n})\n\ntest_that(\"st_as_sfc breaks on wrong input\", {\n  expect_error(st_as_sfc(\"foo\"))\n})\n\ntest_that(\"st_coordinates works\", {\n    x <- st_sfc(st_point(c(pi, pi)), precision = 1e-4)\n\texpect_true(is.matrix(st_coordinates(st_sf(a = 1, geom = x))))\n\texpect_true(is.matrix(st_coordinates(x)))\n\texpect_true(is.matrix(st_coordinates(x[[1]])))\n\tnc <- st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\n\texpect_true(is.matrix(st_coordinates(nc)))\n\t# expect_true(is.matrix(st_coordinates(st_geometrycollection(list(st_point)))))\n})\n\ntest_that(\"as.data.frame.sfc works\", {\n  sfc = st_sfc(st_point(0:1), st_point(3:4))\n  expect_silent(as.data.frame(sfc))\n})\n\ntest_that(\"rep.sfc works\", {\n  expect_equal(\n\tst_sfc(st_point(0:1), st_point(0:1), crs = 4326),\n  \trep(st_sfc(st_point(0:1), crs=4326), 2))\n})\n\ntest_that(\"c.sfc n_empty returns sum of st_is_empty(sfg)\", {\n\tpt1 <- st_point(c(NA_real_, NA_real_))\n\tpt2 <- st_point(0:1)\n\texpect_equal(attr(c(st_sfc(pt1), st_sfc(pt1)), \"n_empty\"), 2L)\n\texpect_equal(attr(c(st_sfc(pt1), st_sfc(pt2)), \"n_empty\"), 1L)\n})\n\ntest_that(\"st_is_longlat warns on invalid bounding box\", {\n\texpect_warning(st_is_longlat(st_sfc(st_point(c(0,-95)), crs = 4326)))\n})\n\ntest_that(\"bounding box is flipped when geometry is flipped\", {\n\tfoo <- st_bbox(c(xmin = 0, xmax = 100, ymin = 0, ymax = 200)) |> st_as_sfc()\n\tbar <- foo * matrix(c(1,0,0,-1), nrow = 2)\n\texpect_equal(st_bbox(bar), st_bbox(c(xmin=0, ymin=-200, xmax=100, ymax=0)))\n})\n\n\n"
  },
  {
    "path": "tests/testthat/test-sfg.R",
    "content": "test_that(\"MtrxSet is being called\", {\n  outer = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\n  hole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\n  hole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\n  pts = list(outer, hole1, hole2)\n  pl1 = st_polygon(pts)\n  expect_identical(st_as_text(pl1),\n  \"POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1), (5 5, 5 6, 6 6, 6 5, 5 5))\")\n  expect_identical(st_as_text(st_sfc(pl1, crs = 4326), EWKT=TRUE), \n  \"SRID=4326;POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1), (5 5, 5 6, 6 6, 6 5, 5 5))\")\n})\n\ntest_that(\"Dimension works\", {\n  expect_identical(sf:::Dimension(st_point(1:2)), \"XY\")\n  expect_identical(sf:::Dimension(st_point(1:3)), \"XYZ\")\n  expect_identical(sf:::Dimension(st_point(1:3, \"XYZ\")), \"XYZ\")\n  expect_identical(sf:::Dimension(st_point(1:3, \"XYM\")), \"XYM\")\n  expect_identical(sf:::Dimension(st_point(1:4)), \"XYZM\")\n})\n\ntest_that(\"st_multilinestring works\", {\n  outer = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\n  hole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\n  hole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\n  pts = list(outer, hole1, hole2)\n  ml1 = st_multilinestring(pts)\n  expect_identical(st_as_text(ml1), \"MULTILINESTRING ((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 1 2, 2 2, 2 1, 1 1), (5 5, 5 6, 6 6, 6 5, 5 5))\")\n})\n\ntest_that(\"xx2multixx works\", {\n  expect_identical(sf:::POINT2MULTIPOINT(st_point(1:2)), st_multipoint(matrix(1:2,1)))\n  m = matrix(1:6,,2)\n  expect_identical(sf:::LINESTRING2MULTILINESTRING(st_linestring(m)), st_multilinestring(list(m)))\n  outer = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\n  hole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\n  hole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\n  pts = list(outer, hole1, hole2)\n  expect_identical(sf:::POLYGON2MULTIPOLYGON(st_polygon(pts)), st_multipolygon(list(pts)))\n})\n\ntest_that(\"print.sfg returns sfg\", {\n  x = st_point(1:2)\n  expect_identical(print(x), x)\n})\n\ntest_that(\"format works\", {\n\tdigits = options(\"digits\")[[1]]\n\toptions(digits = 16)\n\texpect_identical(format(st_multipoint(matrix(1:6/6,3))), \"MULTIPOINT ((0.166666666666...\")\n\texpect_identical(format(st_sfc(st_multipoint(matrix(1:6/6,3)))),\n\t\t\"MULTIPOINT ((0.166666666666...\")\n\toptions(digits = digits)\n\texpect_identical(obj_sum.sfc(st_sfc(st_multipoint(matrix(1:6/6,3)))),\n\t\t\"MULTIPOINT (...\")\n\texpect_identical(type_sum.sfc(st_sfc(st_multipoint(matrix(1:6/6,3)))), \"MULTIPOINT\")\n})\n\ntest_that(\"Ops work for sfc\", {\n\texpect_identical(st_point(c(1,2,3)) + 4, st_point(c(5,6,7)))\n\texpect_identical(st_point(c(1,2,3)) * 3 + 4, st_point(c(7, 10, 13)))\n\tm = matrix(0, 2, 2)\n\tdiag(m) = c(1, 3)\n\texpect_identical(st_point(c(1,2)) * m + c(2,5), st_point(c(3,11)))\n\tm = matrix(1:6,,2)\n\texpect_identical(sf:::LINESTRING2MULTILINESTRING(st_linestring(m)), st_multilinestring(list(m)))\n\touter = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\n\thole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\n\thole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\n\tpts = list(outer, hole1, hole2)\n\texpect_s3_class(st_multipolygon(list(pts)) * 2 + 3, \"MULTIPOLYGON\")\n\tgc = st_geometrycollection(list(st_multipolygon(list(pts)), st_point(c(2,2))))\n\tm = matrix(0, 2, 2)\n\tdiag(m) = c(1, 3)\n\texpect_s3_class(gc * m - 3, \"GEOMETRYCOLLECTION\")\n})\n\ntest_that(\"Ops work for sfg\", {\n\tx = st_sfc(st_point(0:1), st_point(1:2))\n\ty = st_sfc(st_point(2:3), st_point(3:4))\n\texpect_equal(x + 2, y)\n})\n\ntest_that(\"st_dimension returns NA\", {\n\texpect_equal(st_dimension(st_point()), NA_integer_)\n})\n"
  },
  {
    "path": "tests/testthat/test-shift_longitude.R",
    "content": "test_that(\"st_shift_longitude\", {\n\tpt1 = st_point(c(-170, 50))\n\tpt2 = st_point(c(170, 50))\n\t(sfc = st_sfc(pt1, pt2))\n\tsfc = st_set_crs(sfc, 4326)\n\n\tcrd1 = st_coordinates(st_shift_longitude(sfc))[1, \"X\"]\n\tcrd2 = st_coordinates(st_shift_longitude(sfc))[2, \"X\"]\n\n\t# sfc\n\t## pt1 should be shifted but pt2 should not\n\texpect_equal(crd1, st_coordinates(sfc)[1, \"X\"] + 360)\n\texpect_equal(crd2, st_coordinates(sfc)[2, \"X\"])\n\n\t# sf\n\td = st_as_sf(data.frame(id = 1:2, geometry = sfc))\n\n\t## same as above\n\texpect_equal(crd1, st_coordinates(st_shift_longitude(d))[1, \"X\"])\n\texpect_equal(crd2, st_coordinates(d)[2, \"X\"])\n\n\t# non-projected crs\n\t## NA\n\td = st_set_crs(d, NA)\n\texpect_error(st_shift_longitude(d))\n\n\t## arbitrary crs\n\tsfc = st_transform(sfc, 3035)\n\texpect_error(st_shift_longitude(sfc))\n})\n\n"
  },
  {
    "path": "tests/testthat/test-sp.R",
    "content": "test_that(\"we can convert points & lines to and from sp objects\", {\n  skip_if_not_installed(\"sp\")\n  pt1 = st_point(1:2)\n  pt2 = st_point(3:4)\n  s1 = st_sf(a = c(\"x\", \"y\"), geom = st_sfc(pt1, pt2))\n  sp = as(s1, \"Spatial\")\n  s2 = st_as_sf(sp)\n  # expect_identical(s1, s2) -> name differences\n  expect_s3_class(st_geometry(s2), c(\"sfc_POINT\", \"sfc\"), exact = TRUE) #-> name differences\n\n  l = st_linestring(matrix(1:6,3))\n  l1 = st_sf(a = 1, geom = st_sfc(l))\n  sp_l = as(l1, \"Spatial\")\n  expect_s4_class(sp_l, \"SpatialLinesDataFrame\") #-> name differences\n  \n  l2 = st_as_sf(sp_l)\n  expect_s3_class(st_geometry(l2), c(\"sfc_LINESTRING\", \"sfc\"), exact = TRUE) #-> name differences\n  # test multilinestring -> sp\n  l = st_multilinestring(list(matrix(1:6,3), matrix(11:16,3), matrix(21:26,3)))\n  l1 = st_sf(a = 1, geom = st_sfc(l))\n  sp_l = as(l1, \"Spatial\")\n  expect_s4_class(sp_l, \"SpatialLinesDataFrame\") #-> name differences\n  \n  l2 = st_as_sf(sp_l)\n  expect_s3_class(st_geometry(l2), c(\"sfc_MULTILINESTRING\", \"sfc\"), exact = TRUE) #-> name differences\n})\n\ntest_that(\"we can convert SpatialPolygons objects without SF comments to sfc and back\", {\n  skip_if_not_installed(\"sp\")\n  # skip_if_not(package_version(sf_extSoftVersion()[[\"GEOS\"]]) >= \"3.11.0\"); #2079\n  library(sp)\n# nested holes https://github.com/r-spatial/evolution/issues/9\n  p1 <- Polygon(cbind(x=c(0, 0, 10, 10, 0), y=c(0, 10, 10, 0, 0)), hole=FALSE) # I\n  p2 <- Polygon(cbind(x=c(3, 3, 7, 7, 3), y=c(3, 7, 7, 3, 3)), hole=TRUE) # H\n  p8 <- Polygon(cbind(x=c(1, 1, 2, 2, 1), y=c(1, 2, 2, 1, 1)), hole=TRUE) # H\n  p9 <- Polygon(cbind(x=c(1, 1, 2, 2, 1), y=c(5, 6, 6, 5, 5)), hole=TRUE) # H\n  p3 <- Polygon(cbind(x=c(20, 20, 30, 30, 20), y=c(20, 30, 30, 20, 20)), hole=FALSE) # I\n  p4 <- Polygon(cbind(x=c(21, 21, 29, 29, 21), y=c(21, 29, 29, 21, 21)), hole=TRUE) # H\n  p5 <- Polygon(cbind(x=c(22, 22, 28, 28, 22), y=c(22, 28, 28, 22, 22)), hole=FALSE) # I\n  p6 <- Polygon(cbind(x=c(23, 23, 27, 27, 23), y=c(23, 27, 27, 23, 23)), hole=TRUE) # H\n  p7 <- Polygon(cbind(x=c(13, 13, 17, 17, 13), y=c(13, 17, 17, 13, 13)), hole=FALSE) # I\n  p10 <- Polygon(cbind(x=c(24, 24, 26, 26, 24), y=c(24, 26, 26, 24, 24)), hole=FALSE) # I\n  p11 <- Polygon(cbind(x=c(24.25, 24.25, 25.75, 25.75, 24.25), y=c(24.25, 25.75, 25.75, 24.25, 24.25)), hole=TRUE) # H\n  p12 <- Polygon(cbind(x=c(24.5, 24.5, 25.5, 25.5, 24.5), y=c(24.5, 25.5, 25.5, 24.5, 24.5)), hole=FALSE) # I\n  p13 <- Polygon(cbind(x=c(24.75, 24.75, 25.25, 25.25, 24.75), y=c(24.75, 25.25, 25.25, 24.75, 24.75)), hole=TRUE) # H\n  p9a <- Polygon(cbind(x=c(1, 1, 2, 2, 1), y=c(6, 7, 7, 6, 6)), hole=TRUE) # H\n  p7a <- Polygon(cbind(x=c(14, 14, 15, 15, 14), y=c(13, 14, 14, 13, 13)), hole=TRUE) # H\n  lp <- list(p1, p2, p13, p7, p7a, p6, p5, p4, p3, p8, p11, p12, p9, p9a, p10)\n  spls <- SpatialPolygons(list(Polygons(lp, ID=\"1\")))\n  expect_equal(comment(spls), \"FALSE\")\n  expect_null(comment(slot(spls, \"polygons\")[[1]]))\n  spls_sfc <- sf::st_as_sfc(spls)\n# rsbivand fork coerce_comments 2022-12-21\n  spls_rt <- as(spls_sfc, \"Spatial\")\n  expect_equal(comment(spls_rt), \"TRUE\")\n  expect_equal(comment(slot(spls_rt, \"polygons\")[[1]]), \"0 1 1 1 0 0 6 0 8 0 10 0 12\")\n})\n\ntest_that(\"as() can convert GEOMETRY to Spatial (#131)\", {\n  skip_if_not_installed(\"sp\")\n  single <- list(rbind(c(0,0), c(1,0), c(1, 1), c(0,1), c(0,0))) |> st_polygon()\n  multi <- list(single + 2, single + 4) |> st_multipolygon()\n\n  # polygons\n  w <- st_sfc(single, multi)\n  # class is GEOMETRY\n  expect_s4_class(as(w, \"Spatial\"), \"SpatialPolygons\")\n  expect_s4_class(as(st_cast(w, \"MULTIPOLYGON\"), \"Spatial\"), \"SpatialPolygons\")\n\n  # lines\n  lns <- st_cast(w, \"MULTILINESTRING\")\n  expect_s4_class(as(lns, \"Spatial\"), \"SpatialLines\")\n\n  expect_warning(ln <- st_cast(w, \"LINESTRING\"), \"first ring\")\n  expect_s4_class(as(ln, \"Spatial\"), \"SpatialLines\")\n\n  # points\n  expect_warning(pt <- st_cast(w, \"POINT\"), \"first coordinate\")\n  expect_s4_class(as(pt, \"Spatial\"), \"SpatialPoints\")\n\n  pts <- st_cast(w, \"MULTIPOINT\")\n  expect_s4_class(as(pts, \"Spatial\"), \"SpatialMultiPoints\")\n\n  expect_warning(pt <- st_cast(w, \"POINT\"), \"first coordinate\")\n  expect_s4_class(as(pt, \"Spatial\"), \"SpatialPoints\")\n})\n\ntest_that(\"as_Spatial can convert sf (#519)\", {\n  skip_if_not_installed(\"sp\")\n  h <- st_read(system.file(\"shape/nc.shp\", package = \"sf\"), quiet = TRUE)\n\n  u <- as(h, \"Spatial\")\n  s <- as_Spatial(h)\n  g <- as_Spatial(st_geometry(h))\n\n  identical(u, s)\n  expect_s4_class(s, \"SpatialPolygonsDataFrame\")\n  expect_s4_class(g, \"SpatialPolygons\")\n  expect_s4_class(as(st_geometry(h), \"Spatial\"), \"SpatialPolygons\")\n})\n\ntest_that(\"Can convert `XY` objects to sp\", {\n  skip_if_not_installed(\"sp\")\n  expect_s4_class(as(st_point(1:2), \"Spatial\"), \"SpatialPoints\")\n  expect_error(as(st_point(1:3), \"Spatial\"))\n  expect_error(as(st_point(1:4), \"Spatial\"))\n})\n\ntest_that(\"Can't convert `M` dimension to sp\", {\n  skip_if_not_installed(\"sp\")\n  skip_if_not(sf_extSoftVersion()[[\"GDAL\"]] >= \"2.1.0\")\n  x <- read_sf(system.file(\"shape/storms_xyzm_feature.shp\", package = \"sf\"), quiet = TRUE)\n  expect_error(as_Spatial(x), \"not supported by sp\")\n})\n\ntest_that(\"conversion to sp breaks on empty geometries\", {\n  skip_if_not_installed(\"sp\")\n  mysfc <- st_sfc(list(\n    st_polygon(list(matrix(c(1,3,2,1,0,0,1,0), 4, 2))),\n    st_polygon()  # empty polygon\n  ))\n  expect_error(as_Spatial(mysfc), \"conversion failed\")\n})\n"
  },
  {
    "path": "tests/testthat/test-st_cast.R",
    "content": "m <- rbind(c(0,0), c(1,0), c(1, 1), c(0,1), c(0,0))\ns <- matrix(c(2, 0), 5, 2, byrow = TRUE)\ncc <- list(\n  points = list(\n    single = m[1, ] |> st_point(),\n    multi = m |> st_multipoint(),\n    multi_empty = st_multipoint()\n  ),\n  lines = list(\n    single = m |> st_linestring(), \n    multi = list(m, m + s) |> st_multilinestring()\n  ),\n  polygons = list(\n    single = list(m + s)  |> st_polygon(), \n    multi = list(list(m), list(m + s)) |> st_multipolygon()\n  )\n)\n\ntest_that(\"st_cast() can coerce to MULTI* or GEOMETRY\", {\n  # st_cast\n  # ======\n  # points\n  pt <- st_sfc(cc$points$single, cc$points$single)\n  expect_s3_class(st_cast(pt), \"sfc_POINT\")\n  pts <- st_sfc(cc$points$single, cc$points$multi, cc$points$multi_empty)\n  expect_s3_class(st_cast(pts), \"sfc_MULTIPOINT\")\n  expect_warning(pt <- st_cast(pts, \"POINT\"), \"first coordinate\")\n  expect_s3_class(pt, \"sfc_POINT\")\n  expect_s3_class(st_cast(pts, \"MULTIPOINT\"), \"sfc_MULTIPOINT\")\n  expect_error(st_cast(pts, \"LINESTRING\"), \"cannot create LINESTRING from POINT\")\n  expect_error(st_cast(pts, \"MULTILINESTRING\"), \"cannot create MULTILINESTRING from POINT\")\n  expect_error(st_cast(pts, \"POLYGON\"), \"cannot create POLYGON from POINT\")\n  expect_error(st_cast(pts, \"MULTIPOLYGON\"), \"cannot create MULTIPOLYGON from POINT\")\n\n  # multipoints\n  mp <- st_sfc(st_multipoint(m[1:4,]))\n  expect_s3_class(mp, \"sfc_MULTIPOINT\")\n  expect_s3_class(st_cast(mp, \"MULTIPOINT\"), \"sfc_MULTIPOINT\")\n  expect_s3_class(st_cast(mp, \"POINT\"), \"sfc_POINT\")\n  expect_silent(st_cast(mp, \"POINT\"))\n  expect_warning(st_cast(mp[[1]], \"POINT\"), \"point from first coordinate only\")\n  expect_s3_class(st_cast(mp, \"POLYGON\"), \"sfc_POLYGON\")\n  expect_s3_class(st_cast(mp[[1]], \"POLYGON\"), \"POLYGON\")\n  expect_s3_class(st_cast(mp, \"LINESTRING\"), \"sfc_LINESTRING\")\n  expect_s3_class(st_cast(mp[[1]], \"LINESTRING\"), \"LINESTRING\")\n  expect_error(st_cast(mp, \"MULTIPOLYGON\"), \"smaller steps\")\n  expect_s3_class(st_cast(mp[[1]], \"MULTIPOLYGON\"), \"MULTIPOLYGON\")\n  expect_s3_class(st_cast(mp, \"MULTILINESTRING\"), \"sfc_MULTILINESTRING\")\n  expect_s3_class(st_cast(mp[[1]], \"MULTILINESTRING\"), \"MULTILINESTRING\")\n  expect_error(st_cast(mp, \"GEOMETRYCOLLECTION\"), \"smaller steps\")\n  expect_s3_class(st_cast(mp[[1]], \"GEOMETRYCOLLECTION\"), \"GEOMETRYCOLLECTION\")\n  \n  # lines\n  ln <- st_sfc(cc$lines$single, cc$lines$single)\n  expect_s3_class(st_cast(ln), \"sfc_LINESTRING\")\n  lns <- st_sfc(cc$lines$single, cc$lines$multi)\n  expect_s3_class(st_cast(lns), \"sfc_MULTILINESTRING\")\n  expect_warning(ln <- st_cast(lns, \"POINT\"), \"first coordinate\")\n  expect_s3_class(ln, \"sfc_POINT\") \n  expect_s3_class(st_cast(lns, \"MULTIPOINT\"), \"sfc_MULTIPOINT\")\n  expect_warning(ln2 <- st_cast(lns, \"LINESTRING\"), \"first linestring\")\n  expect_s3_class(ln2, \"sfc_LINESTRING\")\n  expect_s3_class(st_cast(lns, \"MULTILINESTRING\"), \"sfc_MULTILINESTRING\")\n  expect_s3_class(st_cast(lns, \"POLYGON\"), \"sfc_POLYGON\")\n  expect_s3_class(st_cast(lns, \"MULTIPOLYGON\"), \"sfc_MULTIPOLYGON\")\n  \n  # polygons\n  pl <- st_sfc(cc$polygons$single, cc$polygons$single)\n  expect_s3_class(st_cast(pl), \"sfc_POLYGON\")\n  pls <- st_sfc(cc$polygons$single, cc$polygons$multi)\n  expect_s3_class(st_cast(pls), \"sfc_MULTIPOLYGON\")\n  expect_warning(pl <- st_cast(pls, \"POINT\"), \"first coordinate\")\n  expect_s3_class(pl, \"sfc_POINT\") \n  expect_s3_class(st_cast(pls, \"MULTIPOINT\"), \"sfc_MULTIPOINT\")\n  expect_warning(pl2 <- st_cast(pls, \"LINESTRING\"), \"first ring\")\n  expect_s3_class(pl2, \"sfc_LINESTRING\")\n  expect_s3_class(st_cast(pls, \"MULTILINESTRING\"), \"sfc_MULTILINESTRING\")\n  expect_warning(pl3 <- st_cast(pls, \"POLYGON\"), \"first part\")\n  expect_s3_class(pl3, \"sfc_POLYGON\")\n  expect_s3_class(st_cast(pls, \"MULTIPOLYGON\"), \"sfc_MULTIPOLYGON\")\n  \n  # mixed\n  expect_s3_class(st_cast(st_sfc(cc$points$single, cc$lines$multi)), \"sfc_GEOMETRY\")\n  expect_s3_class(st_cast(st_sfc(cc$lines$multi, cc$polygons$multi)), \"sfc_GEOMETRY\")\n  \n  expect_s3_class(st_cast(st_sfc(cc$lines$multi, cc$polygons$multi)), \"sfc_GEOMETRY\")\n  expect_s3_class(st_cast(st_sfc(cc$points$multi, cc$polygons$multi)), \"sfc_GEOMETRY\")\n  expect_s3_class(st_cast(st_sfc(cc$points$multi, cc$lines$multi, cc$polygons$multi)), \n                  \"sfc_GEOMETRY\")\n  expect_s3_class(st_cast(st_sfc(list(cc$points$multi, cc$lines$multi, cc$polygons$multi))), \n                  \"sfc_GEOMETRY\")\n})\n\ntest_that(\"st_cast preserves crs (#154)\", {\n  expect_identical(st_cast(st_sfc(cc$points$single, cc$lines$multi, crs = 4326)) |> st_crs(), \n              st_sfc(cc$points$single, cc$lines$multi, crs = 4326) |> st_crs())\n})\n\ntest_that(\"st_cast can crack GEOMETRYCOLLECTION\", {\n  gc1 <- st_geometrycollection(list(st_linestring(rbind(c(0,0),c(1,1),c(2,1)))))\n  gc2 <- st_geometrycollection(list(st_multilinestring(list(\n    rbind(c(2,2),c(1,3)), rbind(c(0,0),c(1,1),c(2,1))))))\n  gc3 <- st_geometrycollection(list(st_multilinestring(list(\n    rbind(c(4,4),c(4,3)), rbind(c(2,2),c(2,1),c(3,1))))))\n  gc4 <- st_geometrycollection(list(st_multipoint(rbind(c(1,5), c(4,3)))))\n  \n  sfc <- st_sfc(gc1, gc2, gc3)\n  expect_s3_class(st_cast(sfc), \"sfc_GEOMETRY\")  # first, it cracks the collection\n  expect_s3_class(st_cast(st_cast(sfc)), \"sfc_MULTILINESTRING\")  # then cast to multi*\n#  expect_warning(expect_s3_class(st_cast(sfc, \"POINT\"), \"sfc_POINT\"), \"first coordinate\")\n#  expect_equal(st_cast(sfc, \"POINT\") |> length, sfc |> length)\n# @etienne: I think this is more useful; attr(x, \"ids\") contains the original lengths\n  expect_s3_class(st_cast(sfc, \"MULTIPOINT\"), \"sfc_MULTIPOINT\")\n  # expect_s3_class(st_cast(sfc, \"LINESTRING\"), \"sfc_LINESTRING\")\n  expect_error(st_cast(sfc, \"LINESTRING\"))\n  expect_error(st_cast(sfc, \"MULTILINESTRING\"))\n  expect_s3_class(st_cast(sfc) |> st_cast(\"MULTILINESTRING\"), \"sfc_MULTILINESTRING\")\n\n  # Can deal with GCs containing empty geometries - #1767\n  gc5 <- st_as_sfc(\n    c(\"GEOMETRYCOLLECTION (POLYGON ((5.5 0, 7 0, 7 -0.5, 6 -0.5, 5.5 0)))\",\n      \"GEOMETRYCOLLECTION (POLYGON EMPTY)\"\n    )\n  )\n  expect_s3_class(st_cast(gc5), \"sfc_POLYGON\")\n  expect_equal(st_is_empty(st_cast(gc5)), c(FALSE, TRUE))\n\n  sfc2 <- st_sfc(gc1, gc2, gc4)\n  expect_s3_class(sfc2 |> st_cast(), \"sfc_GEOMETRY\")\n  expect_equal(sapply(sfc2 |> st_cast(), class)[2, ], c(\"LINESTRING\", \"MULTILINESTRING\", \"MULTIPOINT\"))\n})\n\ntest_that(\"can cast empty polygon (#1094)\", {\n  poly <- st_as_sfc(c('MULTIPOLYGON(((3 1,3 5,6 5,3 1)))', 'POLYGON EMPTY'))\n  expect_s3_class(st_cast(poly), \"sfc_MULTIPOLYGON\")\n})\n"
  },
  {
    "path": "tests/testthat/test-tidyverse-vctrs.R",
    "content": "test_that(\"`sfc` vectors are treated as vectors\", {\n\texpect_true(vctrs::vec_is(st_sfc(st_point())))\n\texpect_true(vctrs::vec_is(st_sfc(st_linestring())))\n\texpect_true(vctrs::vec_is(st_sfc(st_point(), st_linestring())))\n})\n\ntest_that(\"`sfc` vector proxy is correct\", {\n\tx = st_sfc(st_point())\n\tproxy = x\n\tattributes(proxy) = NULL\n\texpect_identical(vctrs::vec_proxy(x), proxy)\n\n\tx = st_sfc(st_linestring())\n\tproxy = x\n\tattributes(proxy) = NULL\n\texpect_identical(vctrs::vec_proxy(x), proxy)\n\n\tx = st_sfc(st_point(), st_linestring())\n\tproxy = x\n\tattributes(proxy) = NULL\n\texpect_identical(vctrs::vec_proxy(x), proxy)\n})\n\ntest_that(\"`sfc` restore proxy is correct\", {\n\tx = st_sfc(st_point())\n\tproxy = vctrs::vec_proxy(x)\n\texpect_identical(vctrs::vec_restore(proxy, x), x)\n\n\tx = st_sfc(st_linestring())\n\tproxy = vctrs::vec_proxy(x)\n\texpect_identical(vctrs::vec_restore(proxy, x), x)\n\n\tx = st_sfc(st_point(), st_linestring())\n\tproxy = vctrs::vec_proxy(x)\n\texpect_identical(vctrs::vec_restore(proxy, x), x)\n})\n\ntest_that(\"`sfc` vector ptype is correct\", {\n\tx = st_sfc(st_point())\n\texpect_identical(vctrs::vec_ptype(x), x[0])\n\texpect_s3_class(vctrs::vec_ptype(x), \"sfc_POINT\")\n\n\tx = st_sfc(st_linestring())\n\texpect_identical(vctrs::vec_ptype(x), x[0])\n\texpect_s3_class(vctrs::vec_ptype(x), \"sfc_LINESTRING\")\n\n\tx = st_sfc(st_point(), st_linestring())\n\texpect_identical(vctrs::vec_ptype(x), x[0])\n\texpect_s3_class(vctrs::vec_ptype(x), \"sfc_GEOMETRY\")\n})\n\ntest_that(\"`sfc` vector ptype2 is correct\", {\n\tx = st_sfc(st_point())\n\ty = st_sfc(st_point(), crs = 3857)\n\tz = st_sfc(st_point(), precision = 1e-4)\n\texpect_identical(vctrs::vec_ptype2(x, x), x[0])\n\texpect_error(vctrs::vec_ptype2(x, y))\n\texpect_error(vctrs::vec_ptype2(x, z))\n\txl = vctrs::vec_ptype2(x, st_sfc(st_linestring()))\n\texpect_true(inherits(xl, \"sfc_GEOMETRY\"))\n\texpect_true(inherits(xl, \"sfc\"))\n\n\tx = st_sfc(st_linestring())\n\ty = st_sfc(st_linestring(), crs = 3857)\n\tz = st_sfc(st_linestring(), precision = 1e-4)\n\texpect_identical(vctrs::vec_ptype2(x, x), x[0])\n\texpect_error(vctrs::vec_ptype2(x, y))\n\texpect_error(vctrs::vec_ptype2(x, z))\n\tlp = vctrs::vec_ptype2(x, st_sfc(st_point()))\n\texpect_true(inherits(lp, \"sfc_GEOMETRY\"))\n\texpect_true(inherits(lp, \"sfc\"))\n\n\tx = st_sfc(st_point(), st_linestring())\n\ty = st_sfc(st_point(), st_linestring(), crs = 3857)\n\tz = st_sfc(st_point(), st_linestring(), precision = 1e-4)\n\texpect_identical(vctrs::vec_ptype2(x, x), x[0])\n\texpect_error(vctrs::vec_ptype2(x, y))\n\texpect_error(vctrs::vec_ptype2(x, z))\n\txp = vctrs::vec_ptype2(x, st_sfc(st_point()))\n\texpect_true(inherits(xp, \"sfc_GEOMETRY\"))\n\texpect_true(inherits(xp, \"sfc\"))\n})\n\ntest_that(\"`sfc` vector cast is correct\", {\n\tx = st_sfc(st_point())\n\texpect_identical(vctrs::vec_cast(x, x), x)\n\ty = vctrs::vec_cast(x, st_sfc(st_linestring()))\n\texpect_true(inherits(y, \"sfc_GEOMETRY\"))\n\texpect_true(inherits(y, \"sfc\"))\n\n\tx = st_sfc(st_linestring())\n\texpect_identical(vctrs::vec_cast(x, x), x)\n\ty = vctrs::vec_cast(x, st_sfc(st_point()))\n\texpect_true(inherits(y, \"sfc_GEOMETRY\"))\n\texpect_true(inherits(y, \"sfc\"))\n\n\tx = st_sfc(st_point(), st_linestring())\n\texpect_identical(vctrs::vec_cast(x, x), x)\n\ty = vctrs::vec_cast(x, st_sfc(st_point()))\n\texpect_true(inherits(y, \"sfc_GEOMETRY\"))\n\texpect_true(inherits(y, \"sfc\"))\n})\n\ntest_that(\"`sfc` vectors can be sliced\", {\n\tx = st_sfc(st_point(1:2), st_point(3:4))\n\texpect_identical(vctrs::vec_slice(x, 1), x[1])\n\texpect_identical(vctrs::vec_slice(x, 0), x[0])\n\n\tx = st_sfc(\n\t\tst_linestring(matrix(1:2, ncol = 2)),\n\t\tst_linestring(matrix(3:4, ncol = 2))\n\t)\n\texpect_identical(vctrs::vec_slice(x, 1), x[1])\n\texpect_identical(vctrs::vec_slice(x, 0), x[0])\n\n\tx = st_sfc(\n\t\tst_point(1:2),\n\t\tst_linestring(matrix(3:4, ncol = 2))\n\t)\n\texpect_identical(vctrs::vec_slice(x, 1), x[1])\n\texpect_identical(vctrs::vec_slice(x, 0), x[0])\n})\n\ntest_that(\"`sfc` vectors can be initialized with correct missing value\", {\n\tx = st_sfc(st_point())\n\texpect_identical(\n\t\tvctrs::vec_init(x, 2),\n\t\tst_sfc(st_point(), st_point())\n\t)\n\n\tx = st_sfc(st_linestring())\n\texpect_identical(\n\t\tvctrs::vec_init(x, 2),\n\t\tst_sfc(st_linestring(), st_linestring())\n\t)\n\n\tx = st_sfc(st_point(), st_linestring())\n\texpect_identical(\n\t\tvctrs::vec_init(x, 2),\n\t\t# This doesn't give a `sfc_GEOMETRY`, it gives an `sfc_GEOMETRYCOLLECTION`\n\t\t# st_sfc(st_geometrycollection(), st_geometrycollection())\n\t\tx[0][c(NA_integer_, NA_integer_)]\n\t)\n})\n\ntest_that(\"`sfc` vectors can combine with unspecified in `vec_c()`\", {\n\tna = st_point()\n\tx = st_point(1:2)\n\tout = vctrs::vec_c(c(NA, NA), st_sfc(x), NA)\n\texpect_identical(out, st_sfc(na, na, x, na))\n\n\tna = st_linestring()\n\tx = st_linestring(matrix(1:2, nrow = 1))\n\tout = vctrs::vec_c(c(NA, NA), st_sfc(x), NA)\n\texpect_identical(out, st_sfc(na, na, x, na))\n\n\tna = st_geometrycollection()\n\tpoint = st_point(1:2)\n\tline = st_linestring(matrix(3:4, nrow = 1))\n\tout = vctrs::vec_c(c(NA, NA), st_sfc(point, line), NA)\n\texpect_identical(out, st_sfc(na, na, point, line, na))\n})\n\ntest_that(\"`sfc` vectors can combine with unspecified in `vec_rbind()`\", {\n\tna = st_point()\n\tone = st_point(1:2)\n\tx = st_sfc(one)\n\ty = st_sfc(one, one)\n\tout = vctrs::vec_rbind(\n\t\tvctrs::data_frame(x = x),\n\t\tvctrs::data_frame(y = y)\n\t)\n\texpect_identical(\n\t\tout,\n\t\tvctrs::data_frame(\n\t\t\tx = st_sfc(one, na, na),\n\t\t\ty = st_sfc(na, one, one)\n\t\t)\n\t)\n\n\tna = st_linestring()\n\tone = st_linestring(matrix(1:2, nrow = 1))\n\tx = st_sfc(one)\n\ty = st_sfc(one, one)\n\tout = vctrs::vec_rbind(\n\t\tvctrs::data_frame(x = x),\n\t\tvctrs::data_frame(y = y)\n\t)\n\texpect_identical(\n\t\tout,\n\t\tvctrs::data_frame(\n\t\t\tx = st_sfc(one, na, na),\n\t\t\ty = st_sfc(na, one, one)\n\t\t)\n\t)\n\n\tna = st_geometrycollection()\n\tpoint = st_point(1:2)\n\tline = st_linestring(matrix(3:4, nrow = 1))\n\tx = st_sfc(point, line)\n\ty = st_sfc(line, point)\n\tout = vctrs::vec_rbind(\n\t\tvctrs::data_frame(x = x),\n\t\tvctrs::data_frame(y = y)\n\t)\n\texpect_identical(\n\t\tout,\n\t\tvctrs::data_frame(\n\t\t\tx = st_sfc(point, line, na, na),\n\t\t\ty = st_sfc(na, na, line, point)\n\t\t)\n\t)\n})\n\ntest_that(\"`sfc` vector `n_empty` attribute is recomputed when slicing\", {\n\tx = st_sfc(st_point(), st_point(0:1))\n\texpect_identical(attr(vctrs::vec_slice(x, 1), \"n_empty\"), 1L)\n\texpect_identical(attr(vctrs::vec_slice(x, 2), \"n_empty\"), 0L)\n\n\tx = st_sfc(st_linestring(), st_linestring(matrix(1:2, nrow = 1)))\n\texpect_identical(attr(vctrs::vec_slice(x, 1), \"n_empty\"), 1L)\n\texpect_identical(attr(vctrs::vec_slice(x, 2), \"n_empty\"), 0L)\n\n\tx = st_sfc(st_point(), st_linestring(matrix(1:2, nrow = 1)))\n\texpect_identical(attr(vctrs::vec_slice(x, 1), \"n_empty\"), 1L)\n\texpect_identical(attr(vctrs::vec_slice(x, 2), \"n_empty\"), 0L)\n})\n\ntest_that(\"`sfc` vector `n_empty` attribute is recomputed when combining\", {\n\tx = st_sfc(st_point())\n\ty = st_sfc(st_point(0:1))\n\tcombined = vctrs::vec_c(x, y, x)\n\texpect_length(combined, 3)\n\texpect_identical(attr(combined, \"n_empty\"), 2L)\n\n\tx = st_sfc(st_linestring())\n\ty = st_sfc(st_linestring(matrix(1:2, nrow = 1)))\n\tcombined = vctrs::vec_c(x, y, x)\n\texpect_length(combined, 3)\n\texpect_identical(attr(combined, \"n_empty\"), 2L)\n\n\tx = st_sfc(st_point(), st_linestring())\n\ty = st_sfc(st_point(), st_linestring(matrix(1:2, nrow = 1)))\n\tcombined = vctrs::vec_c(x, y, x)\n\texpect_length(combined, 6)\n\texpect_identical(attr(combined, \"n_empty\"), 5L)\n})\n\ntest_that(\"`sfc` vectors `bbox` attribute is recomputed when slicing\", {\n\tx = st_sfc(st_point(c(1, 2)))\n\ty = st_sfc(st_point(c(10, 20)))\n\tcombined = c(x, y)\n\texpect_identical(st_bbox(vctrs::vec_slice(combined, 1)), st_bbox(x))\n\texpect_identical(st_bbox(vctrs::vec_slice(combined, 2)), st_bbox(y))\n\n\tx = st_sfc(st_linestring(matrix(1:2, nrow = 1)))\n\ty = st_sfc(st_linestring(matrix(10:11, nrow = 1)))\n\tcombined = c(x, y)\n\texpect_identical(st_bbox(vctrs::vec_slice(combined, 1)), st_bbox(x))\n\texpect_identical(st_bbox(vctrs::vec_slice(combined, 2)), st_bbox(y))\n\n\tx = st_sfc(st_linestring(matrix(1:2, nrow = 1)), st_point(3:4))\n\ty = st_sfc(st_linestring(matrix(10:11, nrow = 1)), st_point(12:15))\n\tcombined = c(x, y)\n\texpect_identical(st_bbox(vctrs::vec_slice(combined, 1:2)), st_bbox(x))\n\texpect_identical(st_bbox(vctrs::vec_slice(combined, 3:4)), st_bbox(y))\n})\n\ntest_that(\"`precision` and `crs` attributes of `sfc` vectors are restored when slicing\", {\n\tx = st_sfc(st_point(), st_point(), precision = 1e-4, crs = 3857)\n\tout = vctrs::vec_slice(x, 1)\n\texpect_identical(st_precision(x), st_precision(out))\n\texpect_identical(st_crs(x), st_crs(out))\n\n\tx = st_sfc(st_linestring(), st_linestring(), precision = 1e-4, crs = 3857)\n\tout = vctrs::vec_slice(x, 1)\n\texpect_identical(st_precision(x), st_precision(out))\n\texpect_identical(st_crs(x), st_crs(out))\n\n\tx = st_sfc(st_point(), st_linestring(), precision = 1e-4, crs = 3857)\n\tout = vctrs::vec_slice(x, 1)\n\texpect_identical(st_precision(x), st_precision(out))\n\texpect_identical(st_crs(x), st_crs(out))\n})\n\ntest_that(\"`precision` and `crs` attributes of `sfc` vectors must be the same when combining\", {\n\tx = st_sfc(st_point(c(pi, pi)), precision = 1e-4, crs = 3857)\n\ty = st_sfc(st_point(c(0, 0)), precision = 1e-2, crs = 3857)\n\tz = st_sfc(st_point(c(0, 0)), precision = 1e-4, crs = 4326)\n\texpect_identical(st_precision(x), st_precision(vctrs::vec_c(x, x)))\n\texpect_identical(st_crs(x), st_crs(vctrs::vec_c(x, x)))\n\texpect_error(vctrs::vec_c(x, y), \"Precision mismatch: 1e-04 vs 0.01\")\n\texpect_error(vctrs::vec_c(x, z), \"CRS mismatch: EPSG:3857 vs EPSG:4326\")\n\texpect_error(c(x, z), \"arguments have different crs\")\n\n\tx = st_sfc(st_linestring(matrix(1:2, nrow = 1)), precision = 1e-4, crs = 3857)\n\ty = st_sfc(st_linestring(matrix(1:2, nrow = 1)), precision = 1e-2, crs = 3857)\n\tz = st_sfc(st_linestring(matrix(1:2, nrow = 1)), precision = 1e-4, crs = 4326)\n\texpect_identical(st_precision(x), st_precision(vctrs::vec_c(x, x)))\n\texpect_identical(st_crs(x), st_crs(vctrs::vec_c(x, x)))\n\texpect_error(vctrs::vec_c(x, y), \"Precision mismatch: 1e-04 vs 0.01\")\n\texpect_error(vctrs::vec_c(x, z), \"CRS mismatch: EPSG:3857 vs EPSG:4326\")\n\texpect_error(c(x, z), \"arguments have different crs\")\n\n\tpoint = st_point()\n\tline = st_linestring(matrix(1:2, nrow = 1))\n\tx = st_sfc(point, line, precision = 1e-4, crs = 3857)\n\ty = st_sfc(point, line, precision = 1e-2, crs = 3857)\n\tz = st_sfc(point, line, precision = 1e-4, crs = 4326)\n\texpect_identical(st_precision(x), st_precision(vctrs::vec_c(x, x)))\n\texpect_identical(st_crs(x), st_crs(vctrs::vec_c(x, x)))\n\texpect_error(vctrs::vec_c(x, y), \"Precision mismatch: 1e-04 vs 0.01\")\n\texpect_error(vctrs::vec_c(x, z), \"CRS mismatch: EPSG:3857 vs EPSG:4326\")\n\texpect_error(c(x, z), \"arguments have different crs\")\n})\n\n# ------------------------------------------------------------------------------\n# Miscellaneous\n\ntest_that(\"`vec_locate_matches()` works with `sfc` vectors\", {\n\tx = c(\n\t\tst_sfc(st_point(c(0, 0))),\n\t\tst_sfc(st_point(c(0, 1))),\n\t\tst_sfc(st_point(c(2, 1)))\n\t)\n\n\ty = c(\n\t\tst_sfc(st_point(c(0, 0))),\n\t\tst_sfc(st_point(c(0, 3))),\n\t\tst_sfc(st_point(c(0, 0))),\n\t\tst_sfc(st_point(c(0, 1)))\n\t)\n\n\tout = vctrs::vec_locate_matches(x, y)\n\texpect_identical(out$needles, c(1L, 1L, 2L, 3L))\n\texpect_identical(out$haystack, c(1L, 3L, 4L, NA))\n})\n\ntest_that(\"`vec_ptype2(<sf>, <sf>)` retains CRS and precision\", {\n  g = st_sfc(st_point(1:2))\n  x = st_sf(a = 3, g, crs = 8123, precision = .1)\n  out = vctrs::vec_ptype2(x, x)\n  expect_identical(st_crs(out), st_crs(x))\n  expect_identical(st_precision(out), st_precision(x))\n})\n\ntest_that(\"`vec_proxy_order(<sfc>)` works\", {\n  x = st_sfc(st_point(1:2), st_point(2:3), st_point(1:2))\n#  expect_identical(vctrs::vec_proxy_order(x), c(1, 1, 1))\n  x = st_sfc(st_polygon(), st_linestring(rbind(c(0,0),c(10,10))), st_point(1:2))\n#  expect_identical(vctrs::vec_proxy_order(x), c(4.2,4.1,1.0))\n})\n"
  },
  {
    "path": "tests/testthat/test-tidyverse.R",
    "content": "suppressMessages(require(dplyr, quietly = TRUE))\nnc <- st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\n\ntest_that(\"select works\", {\n  skip_if_not_installed(\"dplyr\")\n  expect_s3_class(nc |> select(\"AREA\", attr(nc, \"sf_column\")), \"sf\")\n  expect_s3_class(nc |> select(AREA), \"sf\")\n})\n\ntest_that(\"filter to sfc works\", {\n  skip_if_not_installed(\"dplyr\")\n  tbl = tibble(a = c(\"A\", \"B\", \"C\"),\n              geometry = st_sfc(st_point(c(1, 1)),\n                                st_point(),\n                                st_linestring()))\n  d = st_sf(tbl)\n  expect_identical(d |> filter(!st_is_empty(geometry)) |> st_cast(),\n                   d[1, ])\n  expect_identical(d |> filter(st_is(geometry, \"POINT\")) |> st_cast(),\n                   d[1:2, ])\n})\n\nsuppressMessages(require(tidyr, quietly = TRUE))\ntest_that(\"separate and unite work\", {\n  skip_if_not_installed(\"dplyr\")\n  skip_if_not_installed(\"tidyr\")\n  expect_s3_class(nc |> separate(CNTY_ID, c(\"a\", \"b\"), sep = 2), \"sf\")\n  expect_s3_class(nc |> separate(CNTY_ID, c(\"a\", \"b\"), sep = 2) |>\n\tunite(CNTY_ID_NEW, c(\"a\", \"b\"), sep = \"\"), \"sf\")\n})\n\ntest_that(\"separate_rows work\", {\n  skip_if_not_installed(\"dplyr\")\n  skip_if_not_installed(\"tidyr\")\n  d <- st_as_sf(data.frame(\n    x = seq_len(3),\n    y = c(\"a\", \"d,e,f\", \"g,h\"),\n    geometry = st_sfc(st_point(c(1, 1)),\n                      st_point(c(2, 2)),\n                      st_point(c(3, 3))),\n    stringsAsFactors = FALSE))\n  expect_s3_class(separate_rows(d, y, convert = TRUE), \"sf\")\n  expect_identical(d |>\n      separate_rows(y, convert = TRUE) |>\n      st_geometry(),\n    st_sfc(st_point(c(1, 1)),\n           st_point(c(2, 2)),\n           st_point(c(2, 2)),\n           st_point(c(2, 2)),\n           st_point(c(3, 3)),\n           st_point(c(3, 3))))\n})\n\ntest_that(\"group/ungroup works\", {\n skip_if_not_installed(\"dplyr\")\n tbl = tibble(a = c(1,1,2,2), g = st_sfc(st_point(0:1), st_point(1:2), st_point(2:3), st_point(3:4)))\n d = st_sf(tbl)\n e <- d |> group_by(a) |> ungroup()\n expect_equal(as.data.frame(d), as.data.frame(e))\n})\n\ntest_that(\"sample_n etc work\", {\n  skip_if_not_installed(\"dplyr\")\n  tbl = tibble(a = c(1,1,2,2), g = st_sfc(st_point(0:1), st_point(1:2), st_point(2:3), st_point(3:4)))\n  d = st_sf(tbl)\n\n  expect_sampled <- function(x) {\n    expect_s3_class(x, c(\"sf\", \"tbl_df\"))\n    expect_named(x, c(\"a\", \"g\"))\n    expect_equal(nrow(x), 2)\n    expect_s3_class(x$g, \"sfc_POINT\")\n  }\n\n  expect_sampled(sample_n(d, 2))\n  expect_sampled(sample_frac(d, .5))\n})\n\ntest_that(\"nest() works\", {\n\tskip_if_not_installed(\"dplyr\")\n\tskip_if_not_installed(\"tidyr\")\n\ttbl = tibble(a = c(1,1,2,2), g = st_sfc(st_point(0:1), st_point(1:2), st_point(2:3), st_point(3:4)))\n\td = st_sf(tbl)\n\tout = d |> group_by(a) |> nest()\n\n\texp_data = list(d[1:2, \"g\"], d[3:4, \"g\"])\n\n\texp = tibble(a = c(1, 2), data = exp_data) |> group_by(a)\n\texpect_identical(out, exp)\n})\n\ntest_that(\"st_intersection of tbl returns tbl\", {\n nc = read_sf(system.file(\"shape/nc.shp\", package=\"sf\"))\n nc = st_transform(nc[1:3,], 3857)\n st_agr(nc) = \"constant\"\n expect_s3_class(nc, \"tbl_df\")\n expect_s3_class(st_intersection(nc[1:3], nc[4:6]), \"tbl_df\")\n})\n\ntest_that(\"unnest works\", {\n  skip_if_not_installed(\"dplyr\")\n  skip_if_not_installed(\"tidyr\")\n  skip_if_not(utils::packageVersion(\"tidyr\") > \"0.7.2\")\n  nc = read_sf(system.file(\"shape/nc.shp\", package = \"sf\")) |>\n    slice(1:2) |>\n    transmute(y = list(c(\"a\"), c(\"b\", \"c\")))\n  unnest_explicit = unnest(nc, y)\n  # The second row is duplicated because the \"b\" and \"c\" become separate rows\n  expected = nc[c(1,2,2), ] |> mutate(y = c(\"a\", \"b\", \"c\"))\n  # Would use expect_equal, but doesn't work with geometry cols\n  expect_identical(unnest_explicit, expected)\n})\n\ntest_that(\"bind_rows() returns type of first input\", {\n\tskip_if_not_installed(\"dplyr\", \"0.8.99\")\n\tskip_if_not_installed(\"vctrs\", \"0.3.0.9000\")\n\n\tsf1 = st_sf(x = 1, y = st_sfc(st_point(0:1)))\n\tsf2 = st_sf(z = st_sfc(st_point(2:3)), x = 2)\n\n\t# Avoid as.data.frame.sfc() method\n\tdata_frame = function(...) {\n\t\tdf = tibble(...)\n\t\tclass(df) = \"data.frame\"\n\t\tdf\n\t}\n\n\t# Output is a data frame if first input is a data frame\n\tout = bind_rows(data.frame(x = 1), sf2)\n\texp = data_frame(\n\t\tx = c(1, 2),\n\t\tz = st_sfc(NA, st_point(2:3))\n\t)\n\texpect_identical(out, exp)\n\n\tout = bind_rows(sf1, data.frame(x = 1))\n\texp = st_as_sf(data_frame(\n\t\tx = c(1, 1),\n\t\ty = st_sfc(st_point(0:1), NA)\n\t))\n\texpect_identical(out, exp)\n\n\tout = bind_rows(sf1, sf2)\n\texp = st_as_sf(data_frame(\n\t\tx = c(1, 2),\n\t\ty = st_sfc(st_point(0:1), NA),\n\t\tz = st_sfc(NA, st_point(2:3))\n\t))\n\texpect_identical(out, exp)\n\n\tout = bind_rows(sf2, sf1)\n\texp = st_as_sf(sf_column_name = \"z\", data_frame(\n\t\tx = c(2, 1),\n\t\tz = st_sfc(st_point(2:3), NA),\n\t\ty = st_sfc(NA, st_point(0:1))\n\t))\n\texpect_identical(out, exp)\n})\n\ntest_that(\"bind_cols() returns type of first input\", {\n\tskip_if_not_installed(\"dplyr\", \"0.8.99\")\n\n\tsf1 = st_sf(x = 1, y = st_sfc(st_point(0:1)))\n\tsf2 = st_sf(z = st_sfc(st_point(2:3)), w = 2)\n\n\t# Avoid as.data.frame.sfc() method\n\tdata_frame = function(...) {\n\t\tdf = tibble(...)\n\t\tclass(df) = \"data.frame\"\n\t\tdf\n\t}\n\n\t# Output is a data frame if first input is a data frame\n\tout = bind_cols(data.frame(x = 1), sf2)\n\texp = data_frame(\n\t\tx = 1,\n\t\tw = 2,\n\t\tz = st_sfc(st_point(2:3))\n\t)\n\texpect_identical(out, exp)\n\n\tout = bind_cols(sf1, data.frame(w = 2))\n\texp = st_as_sf(data_frame(\n\t\tx = 1,\n\t\tw = 2,\n\t\ty = st_sfc(st_point(0:1))\n\t))\n\texpect_identical(out, exp)\n\n\tout = bind_cols(sf1, sf2)\n\texp = st_as_sf(data_frame(\n\t\tx = 1,\n\t\tw = 2,\n\t\ty = st_sfc(st_point(0:1)),\n\t\tz = st_sfc(st_point(2:3))\n\t))\n\texpect_identical(out, exp)\n\n\tout = bind_cols(sf2, sf1)\n\texp = st_as_sf(data_frame(\n\t\tw = 2,\n\t\tx = 1,\n\t\tz = st_sfc(st_point(2:3)),\n\t\ty = st_sfc(st_point(0:1))\n\t))\n\texpect_identical(out, exp)\n})\n\ntest_that(\"can rename geometry column with `select()`\", {\n    skip_if_not_installed(\"dplyr\")\n\tsf = st_sf(\n\t\tx = 1,\n\t\tgeo = st_sfc(st_point(1:2)),\n\t\ty = \"foo\"\n\t)\n\tout = dplyr::select(sf, foo = geo)\n\texpect_identical(out, st_sf(foo = sf$geo))\n\n\t# geometry column is sticky\n\tout = dplyr::select(sf, y)\n\texpect_identical(out, st_sf(geo = sf$geo, y = sf$y))\n})\n\ntest_that(\"can rename geometry column with `rename()` (#1431)\", {\n  skip_if_not_installed(\"dplyr\")\n  geo_pt = st_sfc(st_point())\n  geo_ln = st_sfc(st_linestring())\n  sf = st_sf(x = 1, geo2 = geo_pt, geo1 = geo_ln, sf_column_name = \"geo1\")\n\n  expect_identical(\n    dplyr::rename(sf, y = x),\n    st_sf(y = 1, geo2 = geo_pt, geo1 = geo_ln, sf_column_name = \"geo1\")\n  )\n\n  expect_identical(\n    dplyr::rename(sf, foo = geo1),\n    st_sf(x = 1, geo2 = geo_pt, foo = geo_ln, sf_column_name = \"foo\")\n  )\n  expect_identical(\n    dplyr::rename(sf, foo = geo1, y = x),\n    st_sf(y = 1, geo2 = geo_pt, foo = geo_ln, sf_column_name = \"foo\")\n  )\n  expect_identical(\n    dplyr::rename(sf, foo = geo1, y = x, bar = geo2),\n    st_sf(y = 1, bar = geo_pt, foo = geo_ln, sf_column_name = \"foo\")\n  )\n})\n\ntest_that(\"`rename_with()` correctly changes the sf_column attribute (#2215)\", {\n\tskip_if_not_installed(\"dplyr\")\n\t\n\tsf_column = attr(nc, \"sf_column\")\n\tfn = function(x) paste0(x, \"_renamed\")\n\t\n\texpect_equal(nc |> rename_with(fn) |> attr(\"sf_column\"), fn(sf_column))\n\texpect_equal(nc |> rename_with(fn, \"NAME\") |> attr(\"sf_column\"), sf_column)\n\texpect_equal(nc |> rename_with(fn, \"geometry\") |> attr(\"sf_column\"), fn(sf_column))\n})\n\ntest_that(\"`rename_with()` works for unquoted `.cols` (#2220)\", {\n\tskip_if_not_installed(\"dplyr\")\n\t\n\tsf_column = attr(nc, \"sf_column\")\n\tfn = function(x) paste0(x, \"_renamed\")\n\t\n\texpect_identical(nc |> rename_with(fn, c(FIPS, FIPSNO)), \n\t\t\t\t\t nc |> rename_with(fn, c(\"FIPS\", \"FIPSNO\")))\n})\n\ntest_that(\"`select()` and `transmute()` observe back-stickiness of geometry column (#1425)\", {\n\tskip_if_not_installed(\"dplyr\")\n\tsf = read_sf(system.file(\"shape/nc.shp\", package = \"sf\"))\n\texp = sf[, c(\"NAME\", \"FIPS\")]\n\texpect_identical(dplyr::select(sf, NAME, FIPS), exp)\n\texpect_identical(dplyr::transmute(sf, NAME, FIPS), exp)\n})\n\ntest_that(\"rowwise_df class is retained on row slice\", {\n\tskip_if_not_installed(\"dplyr\")\n\texpect_s3_class(slice(rowwise(nc), 1), \"rowwise_df\")\n})\n\ntest_that(\"grouped_df class is retained on row slice\", {\n\tskip_if_not_installed(\"dplyr\")\n\texpect_s3_class(nc |> group_by(PERIMETER > 2) |> slice(1), \"grouped_df\")\n})\n\ntest_that(\"rowwise_df class is retained on filtered rows\", {\n\tskip_if_not_installed(\"dplyr\")\n\texpect_s3_class(nc |> rowwise() |> filter(AREA > .1), \"rowwise_df\")\n})\n\ntest_that(\"`group_split.sf()` ignores `.keep` for rowwise_df class\", {\n\tskip_if_not_installed(\"dplyr\")\n\texpect_no_warning(nc |> rowwise() |> group_split())\n})\n\ntest_that(\"group_split.sf()` does not ignore `.keep` for grouped_df class\", {\n\tskip_if_not_installed(\"dplyr\")\n\n\tnc_kept <- nc |>\n\t\tgroup_by(CNTY_ID) |>\n\t\tgroup_split(.keep = TRUE)\n\n\tnc_notkept <- nc |>\n\t\tgroup_by(CNTY_ID) |>\n\t\tgroup_split(.keep = FALSE)\n\n\texpect_identical(names(nc_kept[[1]]), names(nc))\n\texpect_identical(names(nc_notkept[[1]]), setdiff(names(nc), \"CNTY_ID\"))\n})\n\ntest_that(\"`pivot_wider()` works\", {\n\tskip_if_not_installed(\"dplyr\")\n\tskip_if_not_installed(\"tidyr\")\n\n\t# Work for unquoted arguments (#2220)\n\texpect_identical(nc |>\n\t\t\t\t\t \ttidyr::pivot_wider(names_from = NAME,\n\t\t\t\t\t \t\t\t\t\t   values_from = AREA),\n\t\t\t\t\t nc |>\n\t\t\t\t\t \ttidyr::pivot_wider(names_from = \"NAME\",\n\t\t\t\t\t \t\t\t\t\t   values_from = \"AREA\"))\n\t\n\t# Pivot data from long sf to wide sf\n\tnc2 = nc |>\n\t\tmutate(name1 = \"value_1\",\n\t\t\t   name2 = \"value_2\",\n\t\t\t   name3 = \"value_3\") |>\n\t\tas_tibble() |>\n\t\tst_as_sf() \n\tnc2_longer = nc2 |>\n\t\ttidyr::pivot_longer(c(name1, name2, name3),\n\t\t\t\t\t\t\tnames_to = \"foo\",\n\t\t\t\t\t\t\tvalues_to = \"bar\")\n\tnc2_wider = nc2_longer |>\n\t\ttidyr::pivot_wider(names_from = foo,\n\t\t\t\t\t\t   values_from = bar)\n\texpect_identical(st_geometry(nc2), st_geometry(nc2_wider))\n\texpect_identical(st_drop_geometry(nc2), st_drop_geometry(nc2_wider))\n})\n\ntest_that(\"`count()` works\", {\n\t\tskip_if_not_installed(\"dplyr\")\n\t\tnc$area_cl <- cut(nc$AREA, c(0, .1, .12, .15, .25))\n\t\tunsorted <- count(nc, area_cl, .drop_geometry = TRUE)\n\t\tsorted_and_named <- count(nc, area_cl, sort = TRUE, name = \"number\", .drop_geometry = TRUE)\n\t\texpect_equal(unsorted$n, c(35, 15, 22, 28))\n\t\texpect_equal(sorted_and_named$number, c(35, 28, 22, 15))\n\t\texpect_false(\"sf\" %in% class(unsorted))\n\t\texpect_true(inherits(count(nc[\"AREA\"]), \"sf\")) # preserves geometries\n\t})\n"
  },
  {
    "path": "tests/testthat/test-tm.R",
    "content": "test_that(\"st_read and write handle date and time\", {\n  Sys.setenv(TZ=\"\") # local time\n  x = st_sf(a = 1:2, b=c(5.6,3), dt = Sys.Date()+1:2, tm = Sys.time()+2:3,\n            geometry = structure(st_sfc(st_point(c(1,1)), st_point(c(2,2)))))\n  shp <- paste0(tempfile(), \".shp\")\n  gpkg <- paste0(tempfile(), \".gpkg\")\n\n  st_crs(x) = st_crs(\"ENGCRS[\\\"Undefined Cartesian SRS with unknown unit\\\",EDATUM[\\\"Unknown engineering datum\\\"],CS[Cartesian,2],AXIS[\\\"X\\\",unspecified,ORDER[1],LENGTHUNIT[\\\"unknown\\\",0]],AXIS[\\\"Y\\\",unspecified,ORDER[2],LENGTHUNIT[\\\"unknown\\\",0]]]\")\n\n  st_write(x[-4], shp[1], quiet = TRUE)\n  x2 = st_read(shp[1], quiet = TRUE)\n  expect_equal(x[-4], x2, check.attributes=FALSE)\n# WKT2 CRS do not roundtrip for ESRI Shapefile\n\n  st_write(x, gpkg, quiet = TRUE)\n  x2 = st_read(gpkg, quiet = TRUE)\n  expect_equal(x[[\"a\"]], x2[[\"a\"]])\n  expect_equal(x[[\"b\"]], x2[[\"b\"]])\n  expect_equal(x[[\"dt\"]], x2[[\"dt\"]])\n  expect_equal(x[[\"tm\"]], x2[[\"tm\"]])\n\n  Sys.setenv(TZ=\"UTC\") # GMT\n  x = st_sf(a = 1:2, b=c(5.6,3), dt = Sys.Date()+1:2, tm = Sys.time()+2:3,\n            geometry = structure(st_sfc(st_point(c(1,1)), st_point(c(2,2)))))\n  shp <- paste0(tempfile(), \".shp\")\n  gpkg <- paste0(tempfile(), \".gpkg\")\n\n  st_crs(x) = st_crs(\"ENGCRS[\\\"Undefined Cartesian SRS with unknown unit\\\",EDATUM[\\\"Unknown engineering datum\\\"],CS[Cartesian,2],AXIS[\\\"X\\\",unspecified,ORDER[1],LENGTHUNIT[\\\"unknown\\\",0]],AXIS[\\\"Y\\\",unspecified,ORDER[2],LENGTHUNIT[\\\"unknown\\\",0]]]\")\n\n  st_write(x[-4], shp[1], quiet = TRUE)\n  x2 = st_read(shp[1], quiet = TRUE)\n  expect_equal(x[-4], x2, check.attributes=FALSE)\n# WKT2 CRS do not roundtrip for ESRI Shapefile\n\n  st_write(x, gpkg, quiet = TRUE)\n  x2 = st_read(gpkg, quiet = TRUE)\n  expect_equal(x[[\"a\"]], x2[[\"a\"]])\n  expect_equal(x[[\"b\"]], x2[[\"b\"]])\n  expect_equal(x[[\"dt\"]], x2[[\"dt\"]])\n  expect_equal(x[[\"tm\"]], x2[[\"tm\"]])\n})\n"
  },
  {
    "path": "tests/testthat/test-valid.R",
    "content": "context(\"st_is_valid\")\n\n# https://github.com/r-spatial/sf/issues/1760\ntest_that(\"st_is_valid\", {\n  p1 <- st_as_sfc(\"POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))\")\n  p2 <- st_as_sfc(\"POLYGON((0 0, 0 10, 10 0))\")\n  set1 <- c(p1, p2, p1, p2, p1, p2)\n  expect_identical(st_is_valid(set1), c(TRUE, NA, TRUE, NA, TRUE, NA))\n  expect_identical(st_is_valid(set1, reason = TRUE), \n    c(\"Valid Geometry\", NA, \"Valid Geometry\", NA, \"Valid Geometry\", NA))\n})\n\n\n"
  },
  {
    "path": "tests/testthat/test-wkb.R",
    "content": "test_that(\"well-known binary is read correctly\", {\n  wkb = structure(list(\"01010000204071000000000000801A064100000000AC5C1441\"), class = \"WKB\")\n  g = st_as_sfc(wkb, EWKB = TRUE)[[1]]\n  attr(g, \"epsg\") <- NULL\n  expect_true(identical(g, st_point(c(181072,333611))))\n  wkb = structure(list(\"0x01010000204071000000000000801A064100000000AC5C1441\"), class = \"WKB\")\n  g = st_as_sfc(wkb, EWKB = TRUE)[[1]]\n  attr(g, \"epsg\") <- NULL\n  expect_true(identical(g, st_point(c(181072,333611))))\n  wkb = structure(list(\"0x01010000204071000000000000801A064100000000AC5C1441\"))\n  g = st_as_sfc(wkb, EWKB = TRUE)[[1]]\n  attr(g, \"epsg\") <- NULL\n  expect_true(identical(g, st_point(c(181072,333611))))\n})\n\ntest_that(\"Char -> Raw conversion in R and C++ gives identical results\", {\n  expect_identical(\n    sf:::hex_to_raw(           \"0x01010000204071000000000000801A064100000000AC5C1441\"),\n\tsf:::CPL_hex_to_raw(skip0x(\"0x01010000204071000000000000801A064100000000AC5C1441\"))[[1]]\n  )\n  expect_identical(\n    sf:::hex_to_raw(     \"01010000204071000000000000801A064100000000AC5C1441\"),\n\tsf:::CPL_hex_to_raw( \"01010000204071000000000000801A064100000000AC5C1441\")[[1]]\n  )\n  expect_identical( # upper case, lower case:\n    sf:::CPL_hex_to_raw(\"01010000204071000000000000801A064100000000AC5C1441\"),\n\tsf:::CPL_hex_to_raw(\"01010000204071000000000000801a064100000000ac5c1441\")\n  )\n  expect_error(sf:::CPL_hex_to_raw(\"01010000204071000000000000801A064100000000AC5C144z\")) # note the z\n})\n\ntest_that(\"Reading of big-endian and little-endian gives the same result\", {\n  x = structure(list(\"0x01010000204071000000000000801A064100000000AC5C1441\"), class = \"WKB\")\n  y = structure(list(\"0x00200000010000714041061A800000000041145CAC00000000\"), class = \"WKB\")\n  expect_identical(st_as_sfc(x, EWKB = TRUE), st_as_sfc(y, EWKB = TRUE))\n  expect_identical(st_as_sfc(x, EWKB = TRUE, pureR = TRUE), st_as_sfc(y, EWKB = TRUE, pureR = TRUE))\n  expect_identical(st_as_sfc(x, EWKB = TRUE), st_as_sfc(y, EWKB = TRUE, pureR = TRUE))\n})\n\ntest_that(\"Reading of truncated buffers results in a proper error\", {\n  skip_on_os(\"mac\") # doesn't give the message thrown\n\n  wkb = structure(list(\"010100002040710000\"), class = \"WKB\")\n  expect_error(st_as_sfc(wkb, EWKB = TRUE), \"WKB buffer too small. Input file corrupt?\")\n  wkb = structure(list(\"01\"), class = \"WKB\")\n  expect_error(st_as_sfc(wkb, EWKB = FALSE), \"WKB buffer too small. Input file corrupt?\")\n  wkb = structure(list(\"0x01010000204071000000000000801A064100000000AC5C144\"), class = \"WKB\")\n  expect_error(st_as_sfc(wkb, EWKB = TRUE), \"WKB buffer too small. Input file corrupt?\")\n})\n\ntest_that(\"st_as_sfc() honors crs argument\", {\n  skip_if_not_installed(\"blob\")\n  raw = st_as_binary(st_point(c(26e5, 12e5)))\n\n  list = list(raw)\n  blob = blob::blob(raw)\n  wkb = structure(list, class = \"WKB\")\n\n  expect_identical(st_as_sfc(raw, crs = 2056), st_as_sfc(wkb, crs = 2056))\n  expect_identical(st_as_sfc(list, crs = 2056), st_as_sfc(wkb, crs = 2056))\n  expect_identical(st_as_sfc(blob, crs = 2056), st_as_sfc(wkb, crs = 2056))\n})\n"
  },
  {
    "path": "tests/testthat/test-wkt.R",
    "content": "test_that(\"well-known text\", {\n  gcol <- st_geometrycollection(list(st_point(1:2), st_linestring(matrix(1:4,2))))\n  expect_message(x <- print(gcol), \n                 \"GEOMETRYCOLLECTION \\\\(POINT \\\\(1 2\\\\), LINESTRING \\\\(1 3, 2 4\\\\)\\\\)\", all = TRUE)\n  expect_equal(x, gcol)\n  \n  p1 = st_point(1:3)\n  p2 = st_point(5:7)\n  sfc = st_sfc(p1,p2)\n  expect_identical(st_as_text(sfc), c(\"POINT Z (1 2 3)\", \"POINT Z (5 6 7)\"))\n  expect_equal(st_sfc(gcol), st_as_sfc(list(\"GEOMETRYCOLLECTION (POINT (1 2), LINESTRING (1 3, 2 4))\")))\n})\n\ntest_that(\"detect ewkt\", {\n\texpect_equal(is_ewkt(c(\"LINESTRING(1663106 -105415,1664320 -104617)\",\n\t\t\t  \"SRID=4326;POLYGON(1.0 -2.5,3.2 -5.70000)\")),\n\t\t\t\t c(FALSE, TRUE))\n})\n\ntest_that(\"can parse ewkt\", {\n\texpect_equal(get_crs_ewkt(\"SRID=4326;POINT(1.0 -2.5,3.2 -5.7)\"), 4326)\n\texpect_equal(ewkt_to_wkt(\"SRID=4326;POINT(1.0 -2.5, 3.2 -5.7)\"),\n\t\t\t\t \"POINT(1.0 -2.5, 3.2 -5.7)\")\n\texpect_equal(ewkt_to_wkt(\"POINT(1.0 -2.5, 3.2 -5.7)\"),\n\t\t\t\t \"POINT(1.0 -2.5, 3.2 -5.7)\")\n})\n\ntest_that(\"can read ewkt\", {\n\texpect_equal(st_as_sfc(\"SRID=3879;LINESTRING(1663106 -105415,1664320 -104617)\"),\n\t\t\t\t st_as_sfc(\"LINESTRING(1663106 -105415,1664320 -104617)\", 3879))\n\texpect_equal(st_as_sfc(c(\"SRID=3879;LINESTRING(1663106 -105415,1664320 -104617)\",\n\t\t\t\t\t\t\t \"SRID=3879;LINESTRING(0 0,1 1)\")),\n\t\t\t\t st_as_sfc(c(\"LINESTRING(1663106 -105415,1664320 -104617)\",\n\t\t\t\t \t\t\t\"LINESTRING(0 0,1 1)\"), 3879)\n\t\t\t\t )\n\texpect_equal(st_crs(st_as_sfc(c(\"SRID=3879;LINESTRING(1663106 -105415,1664320 -104617)\",\n\t\t\t\t\t\t\t \"SRID=3879;LINESTRING(0 0,1 1)\"))), st_crs(3879))\n\texpect_error(st_as_sfc(c(\"SRID=3879;LINESTRING(1663106 -105415,1664320 -104617)\",\n\t\t\t\t\t\t\t\t\t\"SRID=4326;LINESTRING(0 0,1 1)\")), \"3879, 4326\")\n})\n"
  },
  {
    "path": "tests/testthat/test-write.R",
    "content": "if (require(sp, quietly = TRUE)) {\ndata(meuse, package = \"sp\")\nmeuse <- st_as_sf(meuse, coords = c(\"x\", \"y\"), crs = 28992)\ndrvs <- st_drivers()$name[sapply(st_drivers()$name,\n\tfunction(x) is_driver_can(x, operation = \"write\"))] |> as.character()\n}\n\ntest_that(\"sf can write to all writable formats\", {\n\tskip_if_not_installed(\"sp\")\n\t# write to all formats available\n\ttf <- tempfile()\n\texcluded_drivers = c(\"gps\", # requires options\n\t\t\t\t\"gtm\", # doesn't handle attributes\n\t\t\t\t\"nc\",  # requires appropriate datum -> but writes in 4326, see below\n\t\t\t\t\"map\", # doesn't support points\n\t\t\t\t\"ods\", # generates valgrind error\n\t\t\t\t\"gdb\", # https://github.com/r-spatial/sf/issues/2027\n\t\t\t\t\"gpx\") # needs specially named attributes\n    for (ext in setdiff(names(extension_map[extension_map %in% drvs]), excluded_drivers)) {\n        expect_silent(st_write(meuse, paste0(tf, \".\", ext), quiet = TRUE))\n\t}\n})\n\ntest_that(\"sf can write to netcdf\", {\n\tskip_if_not_installed(\"sp\")\n\tskip_on_os(\"windows\")\n\ttf <- tempfile()\n\tif (\"netCDF\" %in% drvs) {\n\t\texpect_silent(st_write(st_transform(meuse, st_crs(4326)), paste0(tf, \".nc\"), quiet = TRUE))\n\t}\n})\n\ntest_that(\"sf can write units (#264)\", {\n  skip_if_not_installed(\"sp\")\n  tf <- tempfile(fileext = \".gpkg\")\n  meuse[[\"length\"]] <- meuse[[\"cadmium\"]]\n  units(meuse$length) <- units::as_units(\"km\")\n  st_write(meuse, tf, quiet = TRUE)\n  disc <- st_read(tf, quiet = TRUE)\n  expect_type(disc[[\"length\"]], \"double\")\n  expect_equal(as.numeric(meuse[[\"length\"]]), disc[[\"length\"]])\n})\n\ntest_that(\"delete and update work (#304)\", {\n  skip_if_not(\"GPKG\" %in% st_drivers()$name)  # shapefiles can't write point+multipoint mix:\n  skip_on_os(\"mac\")\n  skip_if_not(Sys.getenv(\"USER\") == \"edzer\")\n  # FIXME: conditional, because it caused memory leaks on CRAN testing\n\n  gpkg <- tempfile(fileext = \".gpkg\")\n  shp <- tempfile(fileext = \".shp\")\n\n  x <- st_sf(a = 1:2, geom = st_sfc(st_point(0:1), st_multipoint(matrix(1:4,2,2)), crs = 'EPSG:3857'))\n  expect_error(st_write(x, gpkg, layer = c(\"a\", \"b\"), driver = \"GPKG\", quiet = TRUE)) # error\n  expect_error(st_write(x, gpkg,  driver = \"foo\", quiet = TRUE)) # error\n  expect_warning(st_write(x, gpkg, update = NA, quiet = TRUE), \"deprecated\")\n  expect_silent(write_sf(x, gpkg, layer = \"foo\", delete_layer = TRUE))\n  expect_output(st_write(x, gpkg, layer = \"foo\", delete_layer = TRUE), \"Deleting layer `foo' using\")\n  expect_output(st_write(x, gpkg, layer = \"foo\", delete_layer = TRUE), \"Deleting layer `foo'\")\n  expect_silent(st_write(x, gpkg, \"bar\", quiet = TRUE))\n  expect_error(st_write(x, gpkg, \"bar\", quiet = TRUE), \"Dataset already exists\")\n  i = which(st_layers(gpkg)$name == \"bar\")\n  expect_true(st_layers(gpkg)$features[i] == 2)\n  expect_silent(st_write(x, gpkg, \"bar\", append = FALSE, quiet = TRUE))\n  expect_true(st_layers(gpkg)$features[i] == 2)\n  expect_silent(st_write(x, gpkg, \"bar\", append = TRUE, quiet = TRUE))\n  expect_true(st_layers(gpkg)$features[i] == 4)\n  expect_output(st_write(x, gpkg, delete_dsn = TRUE), \"Writing 2 features\")\n  expect_error(st_write(x, gpkg, quiet = TRUE), \"Dataset already exists\")\n  expect_silent(st_write(x, gpkg, append = FALSE, quiet = TRUE))\n  expect_silent(st_write(x, gpkg, append = TRUE, quiet = TRUE))\n  expect_silent(write_sf(x, gpkg, layer = \"foo\", delete_layer = TRUE))\n  expect_output(st_write(x, gpkg, layer = \"foo\", delete_layer = TRUE), \"Deleting layer `foo' using\")\n  expect_output(st_write(x, gpkg, layer = \"foo\", delete_layer = TRUE), \"Deleting layer `foo'\")\n\n  expect_warning(\n  \texpect_error(st_write(x, gpkg, layer = \".\", quiet = TRUE),\n  \t\t\t\t \"Write error\"),\n  \t\"special characters\")\n  expect_silent(st_layers(gpkg))\n  expect_output(st_write(x, gpkg, layer = \"foo\", delete_dsn = TRUE), \"Deleting source\")\n  expect_silent(st_layers(gpkg))\n  expect_warning(\n  \texpect_error(write_sf(x, shp, \"x\"), \"Feature creation failed\"),\n    \"non-point\")                  # on osx el capitan: \"c++ exception (unknown reason)\"\n  expect_silent(x <- st_read(gpkg, quiet = TRUE))\n  x <- st_sf(a = 1:2, geom = st_sfc(st_linestring(matrix(1:4,2,2)),\n\tst_multilinestring(list(matrix(1:4,2,2), matrix(10:13,2,2)))))\n  expect_message(write_sf(x, shp, \"x\"), \"writing: substituting ENGCRS\")\n  expect_message(write_sf(x, shp, delete_dsn = TRUE), \"writing: substituting ENGCRS\")\n  expect_silent(x <- st_read(shp, quiet = TRUE))\n  expect_silent(x <- read_sf(shp))\n  expect_error(st_write(x, shp, driver = character(0), quiet = TRUE)) # err\n})\n\ntest_that(\"layer is deleted when fails to create features (#549)\", {\n\tskip_if_not_installed(\"sp\")\n\tskip_on_os(\"mac\")\n\tshp <- tempfile(fileext = \".shp\")\n\tx <- st_sf(a = 1:2, geom = st_sfc(st_point(0:1), st_multipoint(matrix(1:4,2,2))))\n\texpect_warning(expect_error(st_write(x, shp, \"x\", quiet = TRUE), \"Feature creation failed\"),\n\t\t\t\t   \"non-point\")\n\texpect_warning(expect_error(st_write(x, shp, \"x\", quiet = TRUE), \"Feature creation failed\"),\n\t\t\t\t   \"non-point\")\n})\n\ntest_that(\"esri shapefiles shorten long field names\", {\n  shpx <- tempfile(fileext = \".shp\")\n  shpy <- tempfile(fileext = \".shp\")\n  nc <- st_read(system.file(\"shape/nc.shp\", package=\"sf\"), \"nc\", crs = 4267, quiet = TRUE)\n  nc$this.is.a.very.long.field.name = 1\n  expect_warning(st_write(nc, shpx, quiet = TRUE), \"Field names abbreviated for ESRI Shapefile driver\")\n  nc$this.is.a.very.long.field.name2 = 2\n  expect_warning(st_write(nc, shpy, quiet = TRUE), \"Field names abbreviated for ESRI Shapefile driver\")\n  # expect_error(st_write(nc, shpz, quiet = TRUE), \"Non-unique field names\")\n})\n\ntest_that(\"FID feature ID gets written and read\", {\n  nc <- read_sf(system.file(\"shape/nc.shp\", package=\"sf\"), \"nc\", crs = 4267, quiet = TRUE, \n  \tfid_column_name = \"f_id\")\n  f_id = nc$f_id = rev(nc$f_id)\n  tf <- paste0(tempfile(), \".geojson\")\n  write_sf(nc, tf, fid_column_name = \"f_id\")\n  nc2 = read_sf(tf, fid_column_name = \"f_id\")\n  if (sf_extSoftVersion()[[\"GDAL\"]] >= \"2.3.2\")\n  \texpect_equal(nc$f_id, nc2$f_id)\n})\n\ntest_that(\"append errors work\", {\n  skip_if_not(Sys.getenv(\"USER\") == \"edzer\")\n\n  # update to non-writable, non-existing file:\n  x = st_sf(a = 1, geom = st_sfc(st_point(0:1)))\n  expect_error(\n    expect_message(st_write(x, \"/x.gpkg\", update = TRUE), \"Creating dataset /x.gpkg failed.\"),\n    \"Creation failed.\")\n\n  # update to non-writable, existing file:\n  f = paste0(tempfile(), \".gpkg\")\n  st_write(x, f, update = FALSE)\n  system(paste(\"chmod -w\", f))\n  expect_error(\n  expect_message(st_write(x, f, append = TRUE),\n    \"cannot append to do you have write permission?\"),\n    \"Cannot append to existing dataset.\")\n  \n  system(paste(\"chmod +w\", f))\n})\n\ntest_that(\"non-spatial tables can be written to GPKG; #1345\", {\n  nc = system.file(\"gpkg/nc.gpkg\", package = \"sf\")\n  tf = tempfile(fileext = \".gpkg\")\n  file.copy(nc, tf)\n  # how does an aspatial layer look like? NA geometry_type\n  l = st_layers(system.file(\"gpkg/nospatial.gpkg\", package = \"sf\"))\n  expect_true(is.na(l$geomtype[[1]]))\n  # demo:\n  #a = data.frame(a = c(1L,-3L), b = c(\"foo\", \"bar\"))\n  a = data.frame(a = c(1L,-3L), b = c(3.5, 7.33))\n  # generates warnings on GDAL 3.1.1:\n  write_sf(a, tf, \n           layer = \"nonspatial_table1\",\n           driver = \"GPKG\",\n\t\t   delete_layer = TRUE,\n           layer_options = \"ASPATIAL_VARIANT=GPKG_ATTRIBUTES\")\n  l2 = st_layers(tf)\n  expect_true(is.na(l2$geomtype[[2]])) # hence is aspatial\n  a2 = as.data.frame(read_sf(tf, \"nonspatial_table1\"))\n  expect_identical(a, a2)\n  expect_output(\n\t\t  expect_warning(st_read(tf, \"nonspatial_table1\"), \n\t\t\t  \"no simple feature geometries present:\"),\n\t  \"Reading layer `nonspatial_table1' from data source\")\n})\n"
  },
  {
    "path": "tests/testthat/test-zm_range.R",
    "content": "# Expect the z range, strip attributes to only compare values.\nexpect_st_z_range <- function(object, expected) {\n\texpect_equal(unclass(st_z_range(object)), expected, check.attributes = FALSE)\n}\n\ntest_that(\"st_z_range and st_z_range returns correct value from sfg objects\", {\n\t\n\tpt <- st_point(x = c(0,1,3,3))\n\t\n\texpect_st_z_range(pt, c(3,3))\n\texpect_equal(st_z_range(pt), st_z_range(pt))\n\n\tmp <- st_multipoint(x = matrix(c(0,1,1,1,0,2,5,5), ncol = 4, byrow = TRUE))\n\texpect_st_z_range(mp, c(1, 5))\n\texpect_equal(st_z_range(mp), st_z_range(mp))\n\n\tls <- st_linestring(x = matrix(c(0,1,1,1,0,2,5,5,0,3,10,10), ncol = 4, byrow = TRUE))\n\texpect_st_z_range(ls, c(1, 10))\n\texpect_equal(st_z_range(ls), st_z_range(ls))\n\n\tmls <- st_multilinestring(x = list(ls, matrix(c(0,1,5,5,0,1,-1,-1), ncol = 4, byrow = TRUE)))\n\texpect_st_z_range(mls, c(-1, 10))\n\texpect_equal(st_z_range(mls), st_z_range(mls))\n\n\tpl <- st_polygon(x = list(matrix(c(0,0,1,1,0,1,2,2,1,1,3,3,1,0,4,4,0,0,1,1), ncol = 4, byrow = T)))\n\texpect_st_z_range(pl, c(1, 4))\n\texpect_equal(st_z_range(pl), st_z_range(pl))\n\n\tmpl <- st_multipolygon(\n\t\tx = list(pl, st_polygon(\n\t\t\tx = list(matrix(c(0,0,10,10,0,-1,9,9,-1,-1,-10,-10,-1,0,-5,-5,0,0,10,10),\n\t\t\t\t\t\t\t ncol = 4, byrow = TRUE))))\n\t\t)\n\texpect_st_z_range(mpl, c(-10, 10))\n\texpect_equal(st_z_range(mpl), st_z_range(mpl))\n\n\tgc <- st_geometrycollection(x = list(pt, mp))\n\texpect_st_z_range(gc, c(1, 5))\n\texpect_equal(st_z_range(gc), st_z_range(gc))\n\n\tgc <- st_geometrycollection(x = list(ls, pl))\n\texpect_st_z_range(gc, c(1, 10))\n\texpect_equal(st_z_range(gc), st_z_range(gc))\n\n\tgc <- st_geometrycollection(x = list(pt, mpl))\n\texpect_st_z_range(gc, c(-10, 10))\n\texpect_equal(st_z_range(gc), st_z_range(gc))\n})\n\n\ntest_that(\"sf::st_z_range and sf::st_z_range returns correct value from sfc objects\", {\n\tpt <- st_sfc(st_point( x = c(0,1,3,3)))\n\t# expect_equal(attr( pt, \"zbox\" ), c(3, 3)) # FIXME: now NULL\n\texpect_st_z_range(pt, c(3, 3))\n\texpect_equal(st_z_range(pt), st_z_range(pt))\n\n\tmp <- st_sfc(st_multipoint( x = matrix(c(0,1,1,1,0,2,5,5), ncol = 4, byrow = TRUE)))\n\texpect_st_z_range(mp, c(1, 5))\n\texpect_equal(st_z_range(mp), st_z_range(mp))\n\n\tls <- st_sfc(st_linestring(x = matrix(c(0,1,1,1,0,2,5,5,0,3,10,10), ncol = 4, byrow = TRUE)))\n\texpect_st_z_range(ls, c(1, 10))\n\texpect_equal(st_z_range(ls), st_z_range(ls))\n\n\tmls <- st_sfc(st_multilinestring(x = list(ls[[1]], matrix(c(0,1,5,5,0,1,-1,-1), ncol = 4, byrow = TRUE))))\n\texpect_st_z_range(mls, c(-1, 10))\n\texpect_equal(st_z_range(mls), st_z_range(mls))\n\n\tpl <- st_sfc(st_polygon(x = list(matrix(c(0,0,1,1,0,1,2,2,1,1,3,3,1,0,4,4,0,0,1,1), ncol = 4, byrow = TRUE))))\n\texpect_st_z_range(pl, c(1, 4))\n\texpect_equal(st_z_range(pl), st_z_range(pl))\n\n\tmpl <- st_sfc(st_multipolygon(x = list(pl[[1]], st_polygon( x = list( matrix(c(0,0,10,10,0,-1,9,9,-1,-1,-10,-10,-1,0,-5,-5,0,0,10,10), ncol = 4, byrow = TRUE))))))\n\texpect_st_z_range(mpl, c(-10, 10))\n\texpect_equal(st_z_range(mpl), st_z_range(mpl))\n\n\tgc <- st_sfc(st_geometrycollection(x = list(pt[[1]], mp[[1]])))\n\texpect_st_z_range(gc, c(1, 5))\n\texpect_equal(st_z_range(gc), st_z_range(gc))\n\n\tgc <- st_sfc(st_geometrycollection(x = list(ls[[1]], pl[[1]])))\n\texpect_st_z_range(gc, c(1, 10))\n\texpect_equal(st_z_range(gc), st_z_range(gc))\n\n\tgc <- st_sfc(st_geometrycollection(x = list(pt[[1]], mpl[[1]])))\n\texpect_st_z_range(gc, c(-10, 10))\n\texpect_equal(st_z_range(gc), st_z_range(gc))\n\n})\n\ntest_that(\"zmrange works on more compliated examples\", {\n\n\tset.seed(123)\n\tm <- matrix(rnorm(300), ncol = 3)\n\texpected <- c(min(m[,3]), max(m[,3]))\n\n\tls <- st_linestring(x = m)\n\texpect_st_z_range(ls, expected)\n\n\tls <- st_sfc(ls)\n\texpect_st_z_range(ls, expected)\n\texpect_equal(\n\t\tunclass(attr(ls, \"z_range\")),\n\t\texpected,\n\t\tcheck.attributes = FALSE\n\t)\n\n\tls <- st_sf(geometry = ls)\n\texpect_st_z_range(ls, expected)\n\texpect_equal(\n\t\tunclass(attr(ls$geometry, \"z_range\")),\n\t\texpected,\n\t\tcheck.attributes = FALSE\n\t)\n    n <- 100\n    lst <- list()\n    min_z <- numeric(n)\n    max_z <- numeric(n)\n\n    set.seed(123)\n\n    for(i in seq_along(n)) {\n    \tm <- matrix(rnorm(sample(seq(3,300, by = 3), size = 1)), ncol = 3)\n    \tmin_z[i] <- min(m[,3])\n    \tmax_z[i] <- max(m[,3])\n    \tlst[[i]] <- st_linestring(m)\n    }\n\n    sfc <- st_sfc(lst)\n    expect_st_z_range(sfc, c(min(min_z), max(max_z)))\n\n})\n\ntest_that(\"transform includes zm in output\", {\n\n\tskip_if(sf_extSoftVersion()[[\"GDAL\"]] <= \"2.1.0\")\n\n\tp1 = st_point(c(7,52,52))\n\tp2 = st_point(c(-30,20,20))\n\tsfc = st_sfc(p1, p2, crs = 4326)\n\n\tres <- st_transform(sfc, 3857)\n\texpect_contains(names(attributes(res)), \"z_range\")\n\texpect_equal(st_z_range(res[[1]]), st_z_range(sfc[[1]]))\n\n\tp1 = st_point(c(7,52,52,7))\n\tp2 = st_point(c(-30,20,20,-30))\n\tsfc = st_sfc(p1, p2, crs = 4326)\n\n\tres <- st_transform(sfc, 3857)\n\texpect_contains(names(attributes(res)), c(\"z_range\", \"m_range\"))\n\texpect_equal(st_z_range(res[[1]]), st_z_range(sfc[[1]]))\n\texpect_equal(st_m_range(res[[1]]), st_m_range(sfc[[1]]))\n\n})\n\n\ntest_that(\"XYM-only objects correctly calculate M (and not Z)\", {\n\tskip_if(sf_extSoftVersion()[[\"GDAL\"]] <= \"2.1.0\")\n\n\tsf_m <- st_read(system.file(\"/shape/storms_xyzm.shp\", package = \"sf\"), quiet = TRUE)\n\tm <- st_coordinates(sf_m)\n\n\tmmin <- min(m[, 3])\n\tmmax <- max(m[, 3])\n\texpect_equal(unclass(st_m_range(sf_m)), c(mmin, mmax), check.attributes = FALSE)\n\n\tsf_z <- st_read(system.file(\"/shape/storms_xyz.shp\", package = \"sf\"), quiet = TRUE)\n\n\texpect_equal(\n\t\tunclass(st_m_range(sf_m)),\n\t\tunclass(st_z_range(sf_z)),\n\t\tcheck.attributes = FALSE\n\t)\n\n\texpect_null(st_z_range(sf_m))\n\texpect_null(st_m_range(sf_z))\n})\n"
  },
  {
    "path": "tests/testthat.R",
    "content": "if (require(testthat, quietly = TRUE)) {\n suppressPackageStartupMessages(library(sf))\n test_check(\"sf\")\n}\n"
  },
  {
    "path": "tests/units.R",
    "content": "suppressPackageStartupMessages(library(sf))\nsuppressPackageStartupMessages(library(units))\n\nif (utils::packageVersion(\"units\") >= \"0.5-0\")\n\tunits_options(auto_convert_names_to_symbols = FALSE)\n\nst_crs(4326)$ud_unit\n\nu = names(sf:::udunits_from_proj)[1:21]\n\nunrecognized = NULL\nout = sapply(u, function(x) { \n  p4s = paste0(\"+proj=laea +units=\", x)\n  cat(x, \": \")\n  ret = try(st_crs(p4s)$ud_unit, silent = TRUE)\n  if (! inherits(ret, \"try-error\"))\n  \tprint(ret)\n  else\n    unrecognized = c(unrecognized, x)\n})\n\nif (length(unrecognized))\n\tprint(paste(\"unrecognized units:\", paste(unrecognized, collapse = \", \"), \": older GDAL version?\"))\n"
  },
  {
    "path": "tests/units.Rout.save",
    "content": "\nR Under development (unstable) (2025-11-05 r88988 ucrt) -- \"Unsuffered Consequences\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-w64-mingw32/x64\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> suppressPackageStartupMessages(library(units))\n> \n> if (utils::packageVersion(\"units\") >= \"0.5-0\")\n+ \tunits_options(auto_convert_names_to_symbols = FALSE)\n> \n> st_crs(4326)$ud_unit\n1 [degree]\n> \n> u = names(sf:::udunits_from_proj)[1:21]\n> \n> unrecognized = NULL\n> out = sapply(u, function(x) { \n+   p4s = paste0(\"+proj=laea +units=\", x)\n+   cat(x, \": \")\n+   ret = try(st_crs(p4s)$ud_unit, silent = TRUE)\n+   if (! inherits(ret, \"try-error\"))\n+   \tprint(ret)\n+   else\n+     unrecognized = c(unrecognized, x)\n+ })\nkm : 1 [km]\nm : 1 [m]\ndm : 1 [dm]\ncm : 1 [cm]\nmm : 1 [mm]\nkmi : 1 [nautical_mile]\nin : 1 [inch]\nft : 1 [foot]\nyd : 1 [yard]\nmi : 1 [mi]\nfath : 1 [fathom]\nch : 1 [chain]\nlink : 1 [link]\nus-in : 1 [us_in]\nus-ft : 1 [US_survey_foot]\nus-yd : 1 [US_survey_yard]\nus-ch : 1 [chain]\nus-mi : 1 [US_survey_mile]\nind-yd : 1 [ind_yd]\nind-ft : 1 [ind_ft]\nind-ch : 1 [ind_ch]\n> \n> if (length(unrecognized))\n+ \tprint(paste(\"unrecognized units:\", paste(unrecognized, collapse = \", \"), \": older GDAL version?\"))\n> \n> proc.time()\n   user  system elapsed \n   0.57    0.15    0.71 \n"
  },
  {
    "path": "tests/wkb.R",
    "content": "suppressPackageStartupMessages(library(sf))\nround_trip = function(x, EWKB = FALSE, pureR = FALSE) {\n\tif (inherits(x, \"sfg\"))\n\t\tx = st_sfc(x)\n\twkb = st_as_binary(x, EWKB = EWKB, pureR = pureR)\n\tclass(wkb) = \"WKB\"\n\t# print(wkb)\n\ty = st_as_sfc(wkb, EWKB = EWKB, pureR = pureR)\n\ta = all.equal(x, y)\n\tif (length(a) == 1 && is.logical(a) && a)\n\t\tTRUE\n\telse {\n\t\tprint(x)\n\t\tprint(wkb)\n\t\tprint(y)\n\t\tFALSE\n\t}\n}\n\np3 = st_point(c(0,0,0))\np3m = st_point(c(0,0,0), \"XYM\")\np4 = st_point(c(0,0,0,0))\np2 = st_point(c(0,0))\nls = st_linestring(matrix(1:6,3))\nmp = st_multipoint(matrix(1:6,3))\n\nouter = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\nhole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\nhole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\npts = list(outer, hole1, hole2)\npl1 = st_polygon(pts)\n\npol1 = list(outer, hole1, hole2)\npol2 = list(outer + 12, hole1 + 12)\npol3 = list(outer + 24)\nmp1 = st_multipolygon(list(pol1,pol2,pol3))\n\nml1 = st_multilinestring(list(outer, hole1, hole2))\ngc = st_geometrycollection(list(p2, ls, pl1, mp1))\n\nsapply(list(p3, p3m, p4, p2, ls, mp, pl1, mp1, ml1, gc), round_trip, EWKB = FALSE)\nsapply(list(p3, p3m, p4, p2, ls, mp, pl1, mp1, ml1, gc), round_trip, EWKB = FALSE, pureR = TRUE)\nsapply(list(p3, p3m, p4, p2, ls, mp, pl1, mp1, ml1, gc), round_trip, EWKB = TRUE)\nsapply(list(p3, p3m, p4, p2, ls, mp, pl1, mp1, ml1, gc), round_trip, EWKB = TRUE, pureR = TRUE)\n\nrawToHex(st_as_binary(st_multipoint(matrix(1:6,3))))\nrawToHex(st_as_binary(st_sfc(st_point(c(0,1)), st_multipoint(matrix(1:6,3)))))\ntry(rawToHex(\"error\"))\n\n# debug roundtrips sf -> GDAL -> sf; \n# the first WKT is what GDAL reports, and will lack M\nst_as_text(st_sfc(sf:::CPL_roundtrip(st_sfc(st_linestring(matrix(1:18,6,3),dim=\"XYZ\")))))\nst_as_text(st_sfc(sf:::CPL_roundtrip(st_sfc(st_multipoint(matrix(1:18,6,3),dim=\"XYZ\")))))\nst_as_text(st_sfc(sf:::CPL_roundtrip(st_sfc(st_point(c(0,0,0), dim=\"XYZ\")))))\n\nif (sf:::CPL_gdal_version() >= \"2.1.0\") { # address GDAL/Fedora (gdal 2.0.2) error:\n  st_as_text(st_sfc(sf:::CPL_roundtrip(st_sfc(st_linestring(matrix(1:18,6,3),dim=\"XYM\")))))\n  st_as_text(st_sfc(sf:::CPL_roundtrip(st_sfc(st_multipoint(matrix(1:18,6,3),dim=\"XYM\")))))\n  st_as_text(st_sfc(sf:::CPL_roundtrip(st_sfc(st_point(c(0,0,0), dim=\"XYM\")))))\n} else {\n\t\"(output expected when gdal <= 2.1.0, e.g. CRAN/fedora)\"\n}\n"
  },
  {
    "path": "tests/wkb.Rout.save",
    "content": "\nR Under development (unstable) (2025-11-05 r88988 ucrt) -- \"Unsuffered Consequences\"\nCopyright (C) 2025 The R Foundation for Statistical Computing\nPlatform: x86_64-w64-mingw32/x64\n\nR is free software and comes with ABSOLUTELY NO WARRANTY.\nYou are welcome to redistribute it under certain conditions.\nType 'license()' or 'licence()' for distribution details.\n\nR is a collaborative project with many contributors.\nType 'contributors()' for more information and\n'citation()' on how to cite R or R packages in publications.\n\nType 'demo()' for some demos, 'help()' for on-line help, or\n'help.start()' for an HTML browser interface to help.\nType 'q()' to quit R.\n\n> suppressPackageStartupMessages(library(sf))\n> round_trip = function(x, EWKB = FALSE, pureR = FALSE) {\n+ \tif (inherits(x, \"sfg\"))\n+ \t\tx = st_sfc(x)\n+ \twkb = st_as_binary(x, EWKB = EWKB, pureR = pureR)\n+ \tclass(wkb) = \"WKB\"\n+ \t# print(wkb)\n+ \ty = st_as_sfc(wkb, EWKB = EWKB, pureR = pureR)\n+ \ta = all.equal(x, y)\n+ \tif (length(a) == 1 && is.logical(a) && a)\n+ \t\tTRUE\n+ \telse {\n+ \t\tprint(x)\n+ \t\tprint(wkb)\n+ \t\tprint(y)\n+ \t\tFALSE\n+ \t}\n+ }\n> \n> p3 = st_point(c(0,0,0))\n> p3m = st_point(c(0,0,0), \"XYM\")\n> p4 = st_point(c(0,0,0,0))\n> p2 = st_point(c(0,0))\n> ls = st_linestring(matrix(1:6,3))\n> mp = st_multipoint(matrix(1:6,3))\n> \n> outer = matrix(c(0,0,10,0,10,10,0,10,0,0),ncol=2, byrow=TRUE)\n> hole1 = matrix(c(1,1,1,2,2,2,2,1,1,1),ncol=2, byrow=TRUE)\n> hole2 = matrix(c(5,5,5,6,6,6,6,5,5,5),ncol=2, byrow=TRUE)\n> pts = list(outer, hole1, hole2)\n> pl1 = st_polygon(pts)\n> \n> pol1 = list(outer, hole1, hole2)\n> pol2 = list(outer + 12, hole1 + 12)\n> pol3 = list(outer + 24)\n> mp1 = st_multipolygon(list(pol1,pol2,pol3))\n> \n> ml1 = st_multilinestring(list(outer, hole1, hole2))\n> gc = st_geometrycollection(list(p2, ls, pl1, mp1))\n> \n> sapply(list(p3, p3m, p4, p2, ls, mp, pl1, mp1, ml1, gc), round_trip, EWKB = FALSE)\n [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n> sapply(list(p3, p3m, p4, p2, ls, mp, pl1, mp1, ml1, gc), round_trip, EWKB = FALSE, pureR = TRUE)\n [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n> sapply(list(p3, p3m, p4, p2, ls, mp, pl1, mp1, ml1, gc), round_trip, EWKB = TRUE)\n [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n> sapply(list(p3, p3m, p4, p2, ls, mp, pl1, mp1, ml1, gc), round_trip, EWKB = TRUE, pureR = TRUE)\n [1] TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE TRUE\n> \n> rawToHex(st_as_binary(st_multipoint(matrix(1:6,3))))\n[1] \"0104000000030000000101000000000000000000f03f0000000000001040010100000000000000000000400000000000001440010100000000000000000008400000000000001840\"\n> rawToHex(st_as_binary(st_sfc(st_point(c(0,1)), st_multipoint(matrix(1:6,3)))))\n[1] \"01010000000000000000000000000000000000f03f\"                                                                                                      \n[2] \"0104000000030000000101000000000000000000f03f0000000000001040010100000000000000000000400000000000001440010100000000000000000008400000000000001840\"\n> try(rawToHex(\"error\"))\nError in rawToHex(\"error\") : \n  not implemented for objects of class character\n> \n> # debug roundtrips sf -> GDAL -> sf; \n> # the first WKT is what GDAL reports, and will lack M\n> st_as_text(st_sfc(sf:::CPL_roundtrip(st_sfc(st_linestring(matrix(1:18,6,3),dim=\"XYZ\")))))\nLINESTRING (1 7 13,2 8 14,3 9 15,4 10 16,5 11 17,6 12 18)\n[1] \"LINESTRING Z (1 7 13, 2 8 14, 3 9 15, 4 10 16, 5 11 17, 6 12 18)\"\n> st_as_text(st_sfc(sf:::CPL_roundtrip(st_sfc(st_multipoint(matrix(1:18,6,3),dim=\"XYZ\")))))\nMULTIPOINT (1 7 13,2 8 14,3 9 15,4 10 16,5 11 17,6 12 18)\n[1] \"MULTIPOINT Z ((1 7 13), (2 8 14), (3 9 15), (4 10 16), (5 11 17), (6 12 18))\"\n> st_as_text(st_sfc(sf:::CPL_roundtrip(st_sfc(st_point(c(0,0,0), dim=\"XYZ\")))))\nPOINT (0 0 0)\n[1] \"POINT Z (0 0 0)\"\n> \n> if (sf:::CPL_gdal_version() >= \"2.1.0\") { # address GDAL/Fedora (gdal 2.0.2) error:\n+   st_as_text(st_sfc(sf:::CPL_roundtrip(st_sfc(st_linestring(matrix(1:18,6,3),dim=\"XYM\")))))\n+   st_as_text(st_sfc(sf:::CPL_roundtrip(st_sfc(st_multipoint(matrix(1:18,6,3),dim=\"XYM\")))))\n+   st_as_text(st_sfc(sf:::CPL_roundtrip(st_sfc(st_point(c(0,0,0), dim=\"XYM\")))))\n+ } else {\n+ \t\"(output expected when gdal <= 2.1.0, e.g. CRAN/fedora)\"\n+ }\nLINESTRING (1 7,2 8,3 9,4 10,5 11,6 12)\nMULTIPOINT (1 7,2 8,3 9,4 10,5 11,6 12)\nPOINT (0 0)\n[1] \"POINT M (0 0 0)\"\n> \n> proc.time()\n   user  system elapsed \n   0.50    0.14    0.60 \n"
  },
  {
    "path": "tic.R",
    "content": "# installs dependencies, runs R CMD check, runs covr::codecov()\ndo_package_checks()\n\nif (ci_on_ghactions() && ci_has_env(\"BUILD_PKGDOWN\")) {\n  # creates pkgdown site and pushes to gh-pages branch\n  # only for the runner with the \"BUILD_PKGDOWN\" env var set\n  do_pkgdown()\n}\n"
  },
  {
    "path": "tools/winlibs.R",
    "content": "if(getRversion() < \"3.3.0\") {\n  stop(\"Your version of R is too old. This package requires R-3.3.0 or newer on Windows.\")\n}\n\n# For details see: https://github.com/rwinlib/gdal3\nVERSION <- commandArgs(TRUE)\n# wrong path: if(!file.exists(sprintf(\"../windows/gdal3-%s/include/gdal/gdal.h\", VERSION))){\ntestfile <- sprintf(\"../windows/gdal3-%s/include/gdal-%s/gdal.h\", VERSION, VERSION)\nif(!file.exists(testfile)){  \n  if(getRversion() < \"3.3.0\") setInternet2()\n  download.file(sprintf(\"https://github.com/rwinlib/gdal3/archive/v%s.zip\", VERSION), \"lib.zip\", quiet = TRUE)\n  dir.create(\"../windows\", showWarnings = FALSE)\n  unzip(\"lib.zip\", exdir = \"../windows\")\n  unlink(\"lib.zip\")\n}\n"
  },
  {
    "path": "vignettes/sf.fig",
    "content": "#FIG 3.2  Produced by xfig version 3.2.5c\nLandscape\nCenter\nMetric\nA4      \n100.00\nSingle\n-2\n1200 2\n2 2 0 3 12 7 50 -1 -1 0.000 0 0 -1 0 0 5\n\t 630 4275 15570 4275 15570 4815 630 4815 630 4275\n2 2 0 3 10 7 50 -1 -1 0.000 0 0 -1 0 0 5\n\t 8820 4365 15165 4365 15165 4770 8820 4770 8820 4365\n2 1 0 3 12 7 50 -1 -1 0.000 0 0 -1 1 0 2\n\t1 1 2.00 75.00 180.00\n\t 6975 6390 7605 4815\n2 1 0 3 4 7 50 -1 -1 0.000 0 0 -1 1 0 2\n\t1 1 2.00 75.00 180.00\n\t 10710 6435 10800 5895\n2 1 0 3 10 7 50 -1 -1 0.000 0 0 -1 1 0 2\n\t1 1 2.00 75.00 180.00\n\t 15390 6165 14850 4770\n2 5 0 1 0 -1 54 -1 -1 0.000 0 0 -1 0 0 5\n\t0 sf2.png\n\t 0 0 16044 0 16044 5929 0 5929 0 0\n2 2 0 3 4 7 50 -1 -1 0.000 0 0 -1 0 0 5\n\t 8775 3915 15345 3915 15345 5895 8775 5895 8775 3915\n4 0 10 50 -1 16 16 0.0000 4 180 2610 12195 6390 Simple feature geometry (sfg)\\001\n4 0 12 50 -1 16 16 0.0000 4 165 1260 6075 6660 Simple feature\\001\n4 0 4 50 -1 16 16 0.0000 4 180 3600 8280 6660 Simple feature geometry list-colum (sfc)\\001\n"
  },
  {
    "path": "vignettes/sf1.Rmd",
    "content": "---\ntitle: \"1. Simple Features for R\"\nauthor: \"Edzer Pebesma\"\noutput:\n  html_document:\n    toc: true\n    toc_float:\n      collapsed: false\n      smooth_scroll: false\n    toc_depth: 2\nvignette: >\n  %\\VignetteIndexEntry{1. Simple Features for R}\n  %\\VignetteEngine{knitr::rmarkdown}\n  %\\VignetteEncoding{UTF-8}\n---\n\n```{r, echo=FALSE, include=FALSE}\nknitr::opts_chunk$set(collapse = TRUE)\nif (file.exists(\"nc.shp\"))\n\tfile.remove(\"nc.shp\", \"nc.dbf\", \"nc.shx\")\n```\n\n[Simple features](https://en.wikipedia.org/wiki/Simple_Features) or _simple feature access_ refers to a formal standard (ISO 19125-1:2004) that describes how objects in the real world can be represented in computers, with emphasis on the _spatial_ geometry of these objects. It also describes how such objects can be stored in and retrieved from databases, and which geometrical operations should be defined for them.\n\nThe standard is widely implemented in spatial\ndatabases (such as [PostGIS](https://postgis.net/)), commercial GIS (e.g., [ESRI\nArcGIS](https://www.esri.com/en-us/home)) and forms the vector data basis for\nlibraries such as [GDAL](https://gdal.org/). A subset of\nsimple features forms the [GeoJSON](https://geojson.org/) standard.\n\nThis vignette:\n\n* explains what is meant by features, and by `simple features`\n* shows how they are implemented in R\n* provides examples of how you can work with them\n* shows how they can be read from and written to external files or resources (I/O)\n* discusses how they can be converted to and from `sp` objects\n* shows how they can be used for meaningful and applied spatial analysis\n\n# What is a feature?\n\nA `feature` is thought of as a thing, or an object in the real world,\nsuch as a building or a tree. As is the case with objects,\nthey often consist of other objects. This is the case with features\ntoo: a set of features can form a single feature. A forest stand can\nbe a feature, a forest can be a feature, a city can be a feature.\nA satellite image pixel can be a feature, a complete image can be\na feature too.\n\nFeatures have a _geometry_ describing _where_ on Earth the\nfeature is located, and they have attributes, which describe other\nproperties. The geometry of a tree can be the delineation of\nits crown, of its stem, or the point indicating its centre. Other\nproperties may include its height, color, diameter at breast height\nat a particular date, and so on.\n\nThe standard says: \"_A simple feature is defined by the OpenGIS\nAbstract specification to have both spatial and non-spatial\nattributes. Spatial attributes are geometry valued, and simple\nfeatures are based on 2D geometry with linear interpolation between\nvertices._\"  We will see soon that the same standard will extend\nits coverage beyond 2D and beyond linear interpolation. Here, we\ntake simple features as the data structures and operations described\nin the standard.\n\n## Dimensions\n\nAll geometries are composed of points. Points are coordinates in a\n2-, 3- or 4-dimensional space.  All points in a geometry have the\nsame dimensionality. In addition to X and Y coordinates, there are\ntwo optional additional dimensions:\n\n* a Z coordinate, denoting altitude\n* an M coordinate (rarely used), denoting some _measure_ that is associated with the point, rather than with the feature as a whole (in which case it would be a feature attribute); examples could be time of measurement, or measurement error of the coordinates\n\nThe four possible cases then are:\n\n1. two-dimensional points refer to x and y, easting and northing, or longitude and latitude, we refer to them as XY\n2. three-dimensional points as XYZ\n3. three-dimensional points as XYM\n4. four-dimensional points as XYZM (the third axis is Z, fourth M)\n\n## Simple feature geometry types\n\nThe following seven simple feature types are the most common, and are for instance the only ones used for [GeoJSON](https://www.rfc-editor.org/rfc/rfc7946):\n\n| type | description                                        |\n| ---- | -------------------------------------------------- |\n| `POINT` | zero-dimensional geometry containing a single point |\n| `LINESTRING` | sequence of points connected by straight, non-self intersecting line segments; one-dimensional geometry |\n| `POLYGON` | geometry with a positive area (two-dimensional); sequence of points form a closed, non-self intersecting ring; the first ring denotes the exterior ring, zero or more subsequent rings denote holes in this exterior ring |\n| `MULTIPOINT` | set of points; a MULTIPOINT is simple if no two Points in the MULTIPOINT are equal |\n| `MULTILINESTRING` | set of linestrings |\n| `MULTIPOLYGON` | set of polygons |\n| `GEOMETRYCOLLECTION` | set of geometries of any type except GEOMETRYCOLLECTION |\n\nEach of the geometry types can also be a (typed) empty set, containing zero coordinates (for `POINT` the standard is not clear how to represent the empty geometry). Empty geometries can be thought of being analogues to missing (`NA`) attributes, NULL values or empty lists.\n\nThe remaining ten geometries are rare but are increasingly found:\n\n| type | description                                        |\n| ---- | -------------------------------------------------- |\n| `CIRCULARSTRING` | The CIRCULARSTRING is the basic curve type, similar to a LINESTRING in the linear world. A single segment requires three points, the start and end points (first and third) and any other point on the arc. The exception to this is for a closed circle, where the start and end points are the same. In this case the second point MUST be the center of the arc, i.e., the opposite side of the circle. To chain arcs together, the last point of the previous arc becomes the first point of the next arc, just like in LINESTRING. This means that a valid circular string must have an odd number of points greater than 1. |\n| `COMPOUNDCURVE` | A compound curve is a single, continuous curve that has both curved (circular) segments and linear segments. That means that in addition to having well-formed components, the end point of every component (except the last) must be coincident with the start point of the following component. |\n| `CURVEPOLYGON` | Example compound curve in a curve polygon: CURVEPOLYGON(COMPOUNDCURVE(CIRCULARSTRING(0 0,2 0, 2 1, 2 3, 4 3),(4 3, 4 5, 1 4, 0 0)), CIRCULARSTRING(1.7 1, 1.4 0.4, 1.6 0.4, 1.6 0.5, 1.7 1) ) |\n| `MULTICURVE` |  A MultiCurve is a 1-dimensional GeometryCollection whose elements are Curves, it can include linear strings, circular strings or compound strings.  |\n| `MULTISURFACE` | A MultiSurface is a 2-dimensional GeometryCollection whose elements are Surfaces, all using coordinates from the same coordinate reference system. |\n| `CURVE` | A Curve is a 1-dimensional geometric object usually stored as a sequence of Points, with the subtype of Curve specifying the form of the interpolation between Points |\n| `SURFACE` | A Surface is a 2-dimensional geometric object |\n| `POLYHEDRALSURFACE` | A PolyhedralSurface is a contiguous collection of polygons, which share common boundary segments  |\n| `TIN` | A TIN (triangulated irregular network) is a PolyhedralSurface consisting only of Triangle patches.|\n| `TRIANGLE` | A Triangle is a polygon with 3 distinct, non-collinear vertices and no interior boundary |\n\nNote that `CIRCULASTRING`, `COMPOUNDCURVE` and `CURVEPOLYGON` are not described in the SFA standard, but in the [SQL-MM part 3 standard](https://www.iso.org/standard/38651.html). The descriptions above were copied from the [PostGIS manual](http://postgis.net/docs/using_postgis_dbmanagement.html).\n\n\n## Coordinate reference system\n\nCoordinates can only be placed on the Earth's surface when their coordinate\nreference system (CRS) is known; this may be a spheroid CRS such\nas [WGS84](https://en.wikipedia.org/wiki/World_Geodetic_System), a\nprojected, two-dimensional (Cartesian) CRS such as a UTM zone or Web\nMercator, or a CRS in three-dimensions, or including time. Similarly,\nM-coordinates need an attribute reference system, e.g. a [measurement\nunit](https://CRAN.R-project.org/package=units).\n\n# How simple features in R are organized\n\nPackage `sf` represents simple features as native R objects.\nSimilar to [PostGIS](http://postgis.net/), all functions and methods\nin `sf` that operate on spatial data are prefixed by `st_`, which\nrefers to _spatial type_; this makes them easily findable\nby command-line completion.  Simple features are implemented as\nR native data, using simple data structures (S3 classes, lists,\nmatrix, vector).  Typical use involves reading, manipulating and\nwriting of sets of features, with attributes and geometries.\n\nAs attributes are typically stored in `data.frame` objects (or the\nvery similar `tbl_df`), we will also store feature geometries in\na `data.frame` column. Since geometries are not single-valued,\nthey are put in a list-column, a list of length equal to the number\nof records in the `data.frame`, with each list element holding the simple\nfeature geometry of that feature.  The three classes used to\nrepresent simple features are:\n\n* `sf`, the table (`data.frame`) with feature attributes and feature geometries, which contains\n* `sfc`, the list-column with the geometries for each feature (record), which is composed of\n* `sfg`, the feature geometry of an individual simple feature.\n\nWe will now discuss each of these three classes.\n\n## sf: objects with simple features\n\nAs we usually do not work with geometries of single `simple features`,\nbut with datasets consisting of sets of features with attributes, the\ntwo are put together in `sf` (simple feature) objects.  The following\ncommand reads the `nc` dataset from a file that is contained in the\n`sf` package:\n\n```{r}\nlibrary(sf)\nnc <- st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\n```\n\n(Note that users will not use `system.file()` but give a `filename` directly, and that shapefiles consist of more than one file, all with identical basename, which reside in the same directory.)\nThe short report printed gives the file name, the driver (ESRI Shapefile), mentions that there are 100 features (records, represented as rows) and 14\nfields (attributes, represented as columns). This object is of class\n\n```{r}\nclass(nc)\n```\n\nmeaning it extends (and \"is\" a) `data.frame`, but with a single\nlist-column with geometries, which is held in the column with name\n\n```{r}\nattr(nc, \"sf_column\")\n```\n\nIf we print the first three features, we see their attribute values\nand an abridged version of the geometry\n\n```{r, echo=TRUE, eval=FALSE}\nprint(nc[9:15], n = 3)\n```\nwhich would give the following output:\n\n![](sf_fig.png)\n\nIn the output we see:\n\n* in green a simple feature: a single record, or `data.frame` row, consisting of attributes and geometry\n* in blue a single simple feature geometry (an object of class `sfg`)\n* in red a simple feature list-column (an object of class `sfc`, which is a column in the `data.frame`)\n* that although geometries are native R objects, they are printed as [well-known text](#wkb)\n\nMethods for `sf` objects are:\n```{r}\nmethods(class = \"sf\")\n```\n\nIt is also possible to create `data.frame` objects with geometry list-columns that are not of class `sf`, e.g. by:\n```{r}\nnc.no_sf <- as.data.frame(nc)\nclass(nc.no_sf)\n```\n\nHowever, such objects:\n\n* no longer register which column is the geometry list-column\n* no longer have a plot method, and\n* lack all of the other dedicated methods listed above for class `sf`\n\n## sfc: simple feature geometry list-column\n\nThe column in the `sf` data.frame that contains the geometries is a list, of class `sfc`.\nWe can retrieve the geometry list-column in this case by `nc$geom` or `nc[[15]]`, but the\nmore general way uses `st_geometry()`:\n\n```{r}\n(nc_geom <- st_geometry(nc))\n```\n\nGeometries are printed in abbreviated form, but we can\nview a complete geometry by selecting it, e.g. the first one by:\n\n```{r}\nnc_geom[[1]]\n```\n\nThe way this is printed is called _well-known text_, and is part of the standards. The word `MULTIPOLYGON` is followed by three parentheses, because it can consist of multiple polygons, in the form of `MULTIPOLYGON(POL1,POL2)`, where `POL1` might consist of an exterior ring and zero or more interior rings, as of `(EXT1,HOLE1,HOLE2)`. Sets of coordinates belonging to a single polygon are held together with parentheses, so we get `((crds_ext)(crds_hole1)(crds_hole2))` where `crds_` is a comma-separated set of coordinates of a ring. This leads to the case above, where `MULTIPOLYGON(((crds_ext)))` refers to the exterior ring (1), without holes (2), of the first polygon (3) - hence three parentheses.\n\nWe can see there is a single polygon with no rings:\n\n```{r fig.height=3}\npar(mar = c(0,0,1,0))\nplot(nc[1], reset = FALSE) # reset = FALSE: we want to add to a plot with a legend\nplot(nc[1,1], col = 'grey', add = TRUE)\n```\n\nbut some of the polygons in this dataset have multiple exterior rings; they can be identified by:\n```{r fig.height=3.5}\npar(mar = c(0,0,1,0))\n(w <- which(sapply(nc_geom, length) > 1))\nplot(nc[w,1], col = 2:7)\n```\n\nFollowing the `MULTIPOLYGON` datastructure, in R we have a list of lists of lists of matrices. For instance,\nwe get the first 3 coordinate pairs of the second exterior ring (first ring is always exterior) for the geometry\nof feature 4 by:\n\n```{r}\nnc_geom[[4]][[2]][[1]][1:3,]\n```\n\nGeometry columns have their own class,\n\n```{r}\nclass(nc_geom)\n```\n\nMethods for geometry list-columns include:\n```{r}\nmethods(class = 'sfc')\n```\n\nCoordinate reference systems (`st_crs()` and `st_transform()`) are discussed in the section on [coordinate reference systems](#crs).\n`st_as_wkb()` and `st_as_text()` convert geometry list-columns into well-known-binary or well-known-text, explained [below](#wkb).\n`st_bbox()` retrieves the coordinate bounding box.\n\nAttributes include:\n```{r}\nattributes(nc_geom)\n```\n\n## Mixed geometry types\n\nThe class of `nc_geom` is `c(\"sfc_MULTIPOLYGON\", \"sfc\")`: `sfc`\nis shared with all geometry types, and `sfc_TYPE` with `TYPE`\nindicating the type of the particular geometry at hand.\n\nThere are two \"special\" types: `GEOMETRYCOLLECTION`, and `GEOMETRY`.\n`GEOMETRYCOLLECTION` indicates that each of the geometries may contain\na mix of geometry types, as in\n```{r}\n(mix <- st_sfc(st_geometrycollection(list(st_point(1:2))),\n    st_geometrycollection(list(st_linestring(matrix(1:4,2))))))\nclass(mix)\n```\nStill, the geometries are here of a single type.\n\nThe second `GEOMETRY`, indicates that the geometries in the geometry\nlist-column are of varying type:\n```{r}\n(mix <- st_sfc(st_point(1:2), st_linestring(matrix(1:4,2))))\nclass(mix)\n```\n\nThese two are fundamentally different: `GEOMETRY` is a superclass without instances, `GEOMETRYCOLLECTION` is a geometry instance. `GEOMETRY` list-columns occur when we read in a data source with a mix of geometry types. `GEOMETRYCOLLECTION` *is* a single feature's geometry: the intersection of two feature polygons may consist of points, lines and polygons, see the example [below](#geometrycollection).\n\n## sfg: simple feature geometry\n\nSimple feature geometry (`sfg`) objects carry the geometry for a\nsingle feature, e.g. a point, linestring or polygon.\n\nSimple feature geometries are implemented as R native data, using the following rules\n\n1. a single POINT is a numeric vector\n2. a set of points, e.g. in a LINESTRING or ring of a POLYGON is a `matrix`, each row containing a point\n3. any other set is a `list`\n\nCreator functions are rarely used in practice, since we typically\nbulk read and write spatial data. They are useful for illustration:\n\n```{r}\n(x <- st_point(c(1,2)))\nstr(x)\n(x <- st_point(c(1,2,3)))\nstr(x)\n(x <- st_point(c(1,2,3), \"XYM\"))\nstr(x)\n(x <- st_point(c(1,2,3,4)))\nstr(x)\nst_zm(x, drop = TRUE, what = \"ZM\")\n```\nThis means that we can represent 2-, 3- or 4-dimensional\ncoordinates. All geometry objects inherit from `sfg` (simple feature\ngeometry), but also have a type (e.g. `POINT`), and a dimension\n(e.g. `XYM`) class name. A figure illustrates six of the seven most\ncommon types.\n\nWith the exception of the `POINT` which has a single point as\ngeometry, the remaining six common single simple feature geometry\ntypes that correspond to single features (single records, or rows\nin a `data.frame`) are created like this\n\n```{r}\np <- rbind(c(3.2,4), c(3,4.6), c(3.8,4.4), c(3.5,3.8), c(3.4,3.6), c(3.9,4.5))\n(mp <- st_multipoint(p))\ns1 <- rbind(c(0,3),c(0,4),c(1,5),c(2,5))\n(ls <- st_linestring(s1))\ns2 <- rbind(c(0.2,3), c(0.2,4), c(1,4.8), c(2,4.8))\ns3 <- rbind(c(0,4.4), c(0.6,5))\n(mls <- st_multilinestring(list(s1,s2,s3)))\np1 <- rbind(c(0,0), c(1,0), c(3,2), c(2,4), c(1,4), c(0,0))\np2 <- rbind(c(1,1), c(1,2), c(2,2), c(1,1))\npol <-st_polygon(list(p1,p2))\np3 <- rbind(c(3,0), c(4,0), c(4,1), c(3,1), c(3,0))\np4 <- rbind(c(3.3,0.3), c(3.8,0.3), c(3.8,0.8), c(3.3,0.8), c(3.3,0.3))[5:1,]\np5 <- rbind(c(3,3), c(4,2), c(4,3), c(3,3))\n(mpol <- st_multipolygon(list(list(p1,p2), list(p3,p4), list(p5))))\n(gc <- st_geometrycollection(list(mp, mpol, ls)))\n```\n\nThe objects created are shown here:\n\n```{r, echo=FALSE}\npar(mar = c(0.1, 0.1, 1.3, 0.1), mfrow = c(2, 3))\nplot(mp, col = 'red')\nbox()\ntitle(\"MULTIPOINT\")\n\nplot(ls, col = 'red')\nbox()\ntitle(\"LINESTRING\")\n\nplot(mls, col = 'red')\nbox()\ntitle(\"MULTILINESTRING\")\n\nplot(pol, border = 'red', col = 'grey', xlim = c(0,4))\nbox()\ntitle(\"POLYGON\")\n\nplot(mpol, border = 'red', col = 'grey')\nbox()\ntitle(\"MULTIPOLYGON\")\n\nplot(gc, border = 'grey', col = 'grey')\nbox()\ntitle(\"GEOMETRYCOLLECTION\")\npar(mfrow = c(1, 1))\n```\n\nGeometries can also be empty, as in\n\n```{r}\n(x <- st_geometrycollection())\nlength(x)\n```\n\n## Well-known text, well-known binary, precision {#wkb}\n\n### WKT and WKB\n\nWell-known text (WKT) and well-known binary (WKB) are two encodings\nfor simple feature geometries. Well-known text, e.g. seen in\n```{r}\nx <- st_linestring(matrix(10:1,5))\nst_as_text(x)\n```\n(but without the leading `## [1]` and quotes), is\nhuman-readable. Coordinates are usually floating point numbers,\nand moving large amounts of information as text is slow and\nimprecise. For that reason, we use well-known binary (WKB) encoding\n\n```{r}\nst_as_binary(x)\n```\n\nWKT and WKB can both be transformed back into R native objects by\n\n```{r}\nst_as_sfc(\"LINESTRING(10 5, 9 4, 8 3, 7 2, 6 1)\")[[1]]\nst_as_sfc(structure(list(st_as_binary(x)), class = \"WKB\"))[[1]]\n```\n\nGDAL, GEOS, spatial databases and GIS read and write WKB which\nis fast and precise. Conversion between R native objects and WKB\nis done by package `sf` in compiled (C++/Rcpp) code, making this a\nreusable and fast route for I/O of simple feature geometries in R.\n\n### Precision\n\nOne of the attributes of a geometry list-column (`sfc`) is the\n`precision`: a double number that, when non-zero, causes some\nrounding during conversion to WKB, which might help certain\ngeometrical operations succeed that would otherwise fail due to\nfloating point representation. The model is that of GEOS, which\ncopies from the Java Topology Suite\n([JTS](https://locationtech.github.io/jts/)), and works like this:\n\n* if precision is zero (default, unspecified), nothing is modified\n* negative values convert to float (4-byte real) precision\n* positive values convert to `round(x*precision)/precision`.\n\nFor the precision model, see also\n[here](https://locationtech.github.io/jts/javadoc/org/locationtech/jts/geom/PrecisionModel.html),\nwhere it is written that: \"... to specify 3 decimal places of\nprecision, use a scale factor of 1000. To specify -3 decimal places\nof precision (i.e. rounding to the nearest 1000), use a scale\nfactor of 0.001.\" Note that all coordinates, so also `Z` or `M`\nvalues (if present) are affected. Choosing values for `precision`\nmay require some experimenting.\n\n## Reading and writing\n\nAs we've seen above, reading spatial data from an external file can be done by:\n\n```{r}\nfilename <- system.file(\"shape/nc.shp\", package=\"sf\")\nnc <- st_read(filename)\n```\nwe can suppress the output by adding argument `quiet=TRUE` or\nby using the otherwise nearly identical but more quiet\n```{r}\nnc <- read_sf(filename)\n```\n\nWriting takes place in the same fashion, using `st_write()`:\n\n```{r}\nst_write(nc, \"nc.shp\")\n```\n\nIf we repeat this, we get an error message that the file already\nexists, and we can overwrite by:\n\n```{r}\nst_write(nc, \"nc.shp\", delete_layer = TRUE)\n```\n\nor its quiet alternative that does this by default,\n\n```{r}\nwrite_sf(nc, \"nc.shp\") # silently overwrites\n```\n\n### Driver-specific options\n\nThe `dsn` and `layer` arguments to `st_read()` and `st_write()`\ndenote a data source name and optionally a layer name.  Their exact\ninterpretation as well as the options they support vary per driver,\nthe [GDAL driver documentation](https://gdal.org/en/latest/drivers/vector/index.html)\nis best consulted for this.  For instance, a PostGIS table in\ndatabase `postgis` might be read by:\n\n```{r eval=FALSE}\nmeuse <- st_read(\"PG:dbname=postgis\", \"meuse\")\n```\n\nwhere the `PG:` string indicates this concerns the PostGIS driver,\nfollowed by database name, and possibly port and user credentials.\nWhen the `layer` and `driver` arguments are not specified, `st_read()`\ntries to guess them from the datasource, or else simply reads the\nfirst layer, giving a warning in case there are more.\n\n`st_read()` typically reads the coordinate reference system as\n`proj4string`, but not the EPSG (SRID).  GDAL cannot retrieve SRID\n(EPSG code) from `proj4string` strings, and, when needed, it has\nto be set by the user. See also the section on [coordinate reference systems](#crs).\n\n`st_drivers()` returns a `data.frame` listing available drivers,\nand their metadata: names, whether a driver can write, and whether\nit is a raster and/or vector driver. All drivers can read. Reading\nof some common data formats is illustrated below:\n\n`st_layers(dsn)` lists the layers present in data source `dsn`,\nand gives the number of fields, features and geometry type for each\nlayer:\n```{r eval=FALSE}\nst_layers(system.file(\"osm/overpass.osm\", package=\"sf\"))\n```\nwe see that in this case, the number of features is `NA` because\nfor this xml file the whole file needs to be read, which may be\ncostly for large files. We can force counting by:\n```{r eval=FALSE}\nSys.setenv(OSM_USE_CUSTOM_INDEXING=\"NO\")\nst_layers(system.file(\"osm/overpass.osm\", package=\"sf\"), do_count = TRUE)\n```\n\nAnother example of reading kml and kmz files is:\n```{r, eval=FALSE}\n# Download .shp data\nu_shp <- \"http://coagisweb.cabq.gov/datadownload/biketrails.zip\"\ndownload.file(u_shp, \"biketrails.zip\")\nunzip(\"biketrails.zip\")\nu_kmz <- \"http://coagisweb.cabq.gov/datadownload/BikePaths.kmz\"\ndownload.file(u_kmz, \"BikePaths.kmz\")\n\n# Read file formats\nbiketrails_shp <- st_read(\"biketrails.shp\")\nif(Sys.info()[1] == \"Linux\") # may not work if not Linux\n  biketrails_kmz <- st_read(\"BikePaths.kmz\")\nu_kml = \"http://www.northeastraces.com/oxonraces.com/nearme/safe/6.kml\"\ndownload.file(u_kml, \"bikeraces.kml\")\nbikraces <- st_read(\"bikeraces.kml\")\n```\n\n### Create, read, update and delete {#crud}\n\nGDAL provides the\n[crud](https://en.wikipedia.org/wiki/Create,_read,_update_and_delete)\n(create, read, update, delete) functions to persistent storage.\n`st_read()` (or `read_sf()`) are used for reading. `st_write()` (or `write_sf()`)\ncreates, and has the following arguments to control update and delete:\n\n* `update=TRUE` causes an existing data source to be updated, if it\nexists; this option is by default `TRUE` for all database drivers,\nwhere the database is updated by adding a table.\n* `delete_layer=TRUE` causes `st_write` try to open the data\nsource and delete the layer; no errors are given if the data source is\nnot present, or the layer does not exist in the data source.\n* `delete_dsn=TRUE` causes `st_write` to delete the data source when\npresent, before writing the layer in a newly created data source. No\nerror is given when the data source does not exist. This option\nshould be handled with care, as it may wipe complete directories\nor databases.\n\n### Connection to spatial databases\n\nRead and write functions, `st_read()` and `st_write()`, can handle \nconnections to spatial databases to read WKB or WKT directly\nwithout using GDAL.\nAlthough intended to use the DBI interface, current use and testing of these \nfunctions are limited to PostGIS.\n\n## Coordinate reference systems and transformations {#crs}\n\nCoordinate reference systems (CRS) are like measurement units\nfor coordinates: they specify which location on Earth a particular\ncoordinate pair refers to. We saw above that `sfc` objects (geometry\nlist-columns) have an attribute of class `crs` that stores the\nCRS. This implies that all geometries in a geometry list-column\nhave the same CRS. It may be `NA` in case the CRS is unknown, or\nwhen we work with local coordinate systems (e.g. inside a building,\na body, or an abstract space); in that case coordinates are assumed\nto be Cartesian (in case of 2D: defining positions on in a flat\nplane).\n\nA `crs` object contains two character fields: `input` for the\nname (if existing) or the user-definition of the CRS, and `wkt`\nfor the WKT-2 specification; WKT-2 is a standard encoding for\ndescribing CRS that is used throughout the spatial data science\nindustry.  When defining a CRS, a PROJ string may be used that is\nunderstood by the [PROJ](https://proj.org/) library. It defines\nprojection types and (often) defines parameter values for particular\nprojections, and hence can cover an infinite amount of different\nprojections. Alternatively, codes like `EPSG:3035` or `OGC:CRS84`\nmay be used; these are well-known identifiers of CRS defined in\nthe PROJ database.\n\nCoordinate reference system transformations are carried out using\n`st_transform()`, e.g. converting longitudes/latitudes in NAD27 to\nWeb Mercator (EPSG:3857) can be done by:\n\n```{r}\nnc.web_mercator <- st_transform(nc, \"EPSG:3857\")\nst_geometry(nc.web_mercator)[[4]][[2]][[1]][1:3,]\n```\n\n## Conversion, including to and from sp\n\n`sf` objects and objects deriving from `Spatial` (package `sp`) can be coerced both ways:\n\n```{r}\nshowMethods(\"coerce\", classes = \"sf\")\nmethods(st_as_sf)\nmethods(st_as_sfc)\n\n# anticipate that sp::CRS will expand proj4strings:\np4s <- \"+proj=longlat +datum=NAD27 +no_defs +ellps=clrk66 +nadgrids=@conus,@alaska,@ntv2_0.gsb,@ntv1_can.dat\"\nst_crs(nc) <- p4s\n\n# anticipate geometry column name changes:\nnames(nc)[15] = \"geometry\"\nattr(nc, \"sf_column\") = \"geometry\"\nnc.sp <- as(nc, \"Spatial\")\nclass(nc.sp)\nnc2 <- st_as_sf(nc.sp)\nall.equal(nc, nc2)\n```\n\nAs the `Spatial*` objects only support `MULTILINESTRING` and `MULTIPOLYGON`, `LINESTRING` and `POLYGON` geometries\nare automatically coerced into their `MULTI` form. When converting `Spatial*` into `sf`, if all geometries consist of a single\n`POLYGON` (possibly with holes), a `POLYGON` and otherwise all geometries are returned as `MULTIPOLYGON`: a\nmix of `POLYGON` and `MULTIPOLYGON` (such as common in shapefiles) is not created. Argument `forceMulti=TRUE`\nwill override this, and create `MULTIPOLYGON`s in all cases. For `LINES` the situation is identical.\n\n## Geometrical operations {#geometrycollection}\n\nThe standard for simple feature access defines a number of geometrical operations.\n\n`st_is_valid()` and `st_is_simple()` return a Boolean indicating whether\na geometry is valid or simple.\n\n```{r}\nst_is_valid(nc[1:2,])\n```\n\n`st_distance()` returns a dense numeric matrix with distances\nbetween geometries. `st_relate()` returns a character matrix with the\n[DE9-IM](https://en.wikipedia.org/wiki/DE-9IM#Illustration) values\nfor each pair of geometries:\n\n```{r}\nx = st_transform(nc, 32119)\nst_distance(x[c(1,4,22),], x[c(1, 33,55,56),])\nst_relate(nc[1:5,], nc[1:4,])\n```\n\n`st_intersects()`, `st_disjoint()`, `st_touches()`,\n`st_crosses()`, `st_within()`, `st_contains()`, `st_overlaps()`,\n`st_equals()`, `st_covers()`, `st_covered_by()`, `st_equals_exact()` and\n`st_is_within_distance()` return a sparse matrix (`sgbp` object) with matching (`TRUE`)\nindexes, or a full logical matrix:\n\n```{r}\nst_intersects(nc[1:5,], nc[1:4,])\nst_intersects(nc[1:5,], nc[1:4,], sparse = FALSE)\n```\n\n`st_buffer()`, `st_boundary()`, `st_convexhull()`,\n`st_union_cascaded`, `st_simplify`, `st_triangulate()`,\n`st_polygonize()`, `st_centroid()`, `st_segmentize()`, and `st_union()`\nreturn new geometries, e.g.:\n\n```{r fig.height=3}\nsel <- c(1,5,14)\ngeom = st_geometry(nc.web_mercator[sel,])\nbuf <- st_buffer(geom, dist = 30000)\nplot(buf, border = 'red')\nplot(geom, add = TRUE)\nplot(st_buffer(geom, -5000), add = TRUE, border = 'blue')\n```\n\n`st_intersection()`, `st_union()`, `st_difference()`, and\n`st_sym_difference()` return new geometries that are a function of\npairs of geometries:\n\n```{r fig.height=3}\npar(mar = rep(0,4))\nu <- st_union(nc)\nplot(u)\n```\n\nThe following code shows how computing an intersection between two polygons\nmay yield a `GEOMETRYCOLLECTION` with a point, line and polygon:\n\n```{r fig.height=3, fig.width=7}\nopar <- par(mfrow = c(1, 2))\na <- st_polygon(list(cbind(c(0,0,7.5,7.5,0),c(0,-1,-1,0,0))))\nb <- st_polygon(list(cbind(c(0,1,2,3,4,5,6,7,7,0),c(1,0,.5,0,0,0.5,-0.5,-0.5,1,1))))\nplot(a, ylim = c(-1,1))\ntitle(\"intersecting two polygons:\")\nplot(b, add = TRUE, border = 'red')\n(i <- st_intersection(a,b))\nplot(a, ylim = c(-1,1))\ntitle(\"GEOMETRYCOLLECTION\")\nplot(b, add = TRUE, border = 'red')\nplot(i, add = TRUE, col = 'green', lwd = 2)\npar(opar)\n```\n\n## Non-simple and non-valid geometries\n\nNon-simple geometries are for instance self-intersecting lines (left); non-valid geometries are for instance polygons with slivers (middle) or self-intersections (right).\n\n```{r}\nlibrary(sf)\nx1 <- st_linestring(cbind(c(0,1,0,1),c(0,1,1,0)))\nx2 <- st_polygon(list(cbind(c(0,1,1,1,0,0),c(0,0,1,0.6,1,0))))\nx3 <- st_polygon(list(cbind(c(0,1,0,1,0),c(0,1,1,0,0))))\nst_is_simple(st_sfc(x1))\nst_is_valid(st_sfc(x2,x3))\n```\n\n```{r echo=FALSE,fig=TRUE,fig.height=3}\nopar <- par(mfrow = c(1,3))\npar(mar=c(1,1,4,1))\nplot(st_sfc(x1), type = 'b', axes = FALSE, xlab = NULL, ylab = NULL);\ntitle(st_as_text(x1))\nplot(st_sfc(st_linestring((cbind(c(0,1,1,1,0,0),c(0,0,1,0.6,1,0))))), type='b', axes = FALSE)\ntitle(st_as_text(x2))\nplot(st_sfc(st_linestring(cbind(c(0,1,0,1,0),c(0,1,1,0,0)))), type = 'b', axes=F, xlab=NULL,ylab=NULL)\ntitle(st_as_text(x3))\npar(opar)\n```\n\n# Units\n\nWhere possible geometric operations such as `st_distance()`, `st_length()` and `st_area()` report results with a units attribute appropriate for the CRS:\n\n```{r}\na <- st_area(nc[1,])\nattributes(a)\n```\n\nThe **units** package can be used to convert between units:\n\n```{r}\nunits::set_units(a, km^2) # result in square kilometers\nunits::set_units(a, ha) # result in hectares\n```\n\nThe result can be stripped of their attributes if needs be:\n\n```{r}\nas.numeric(a)\n```\n\n# How attributes relate to geometries\n\n(This will eventually be the topic of a new vignette; now here to explain the last attribute of `sf` objects)\n\nThe standard documents about simple features are very detailed about the geometric aspects of features, but say nearly nothing about attributes, except that their values should be understood in another reference system (their units of measurement, e.g. as implemented in the package [**units**](https://CRAN.R-project.org/package=units)). But there is more to it. For variables like air temperature, interpolation usually makes sense, for others like human body temperature it doesn't. The difference is that air temperature is a field, which continues between sensors, where body temperature is an object property that doesn't extend beyond the body -- in spatial statistics bodies would be called a point pattern, their temperature the point marks. For geometries that have a non-zero size (positive length or area), attribute values may refer to the every sub-geometry (every point), or may summarize the geometry. For example, a state's population density summarizes the whole state, and is not a meaningful estimate of population density for a give point inside the state without the context of the state. On the other hand, land use or geological maps give polygons with constant land use or geology, every point inside the polygon is of that class.\nSome properties are spatially [extensive](https://en.wikipedia.org/wiki/Intensive_and_extensive_properties), meaning that attributes would summed up when two geometries are merged: population is an example. Other properties are spatially intensive, and should be averaged, with population density the example.\n\nSimple feature objects of class `sf` have an _agr_ attribute that points to the _attribute-geometry-relationship_, how attributes relate to their geometry. It can be defined at creation time:\n\n```{r}\nnc <- st_read(system.file(\"shape/nc.shp\", package=\"sf\"),\n    agr = c(AREA = \"aggregate\", PERIMETER = \"aggregate\", CNTY_ = \"identity\",\n        CNTY_ID = \"identity\", NAME = \"identity\", FIPS = \"identity\", FIPSNO = \"identity\",\n        CRESS_ID = \"identity\", BIR74 = \"aggregate\", SID74 = \"aggregate\", NWBIR74 = \"aggregate\",\n        BIR79 = \"aggregate\", SID79 = \"aggregate\", NWBIR79 = \"aggregate\"))\nst_agr(nc)\ndata(meuse, package = \"sp\")\nmeuse_sf <- st_as_sf(meuse, coords = c(\"x\", \"y\"), crs = 28992, agr = \"constant\")\nst_agr(meuse_sf)\n```\n\nWhen not specified, this field is filled with `NA` values, but if non-`NA`, it has one\nof three possibilities:\n\n| value | meaning                           |\n|-------| ----------------------------------|\n| constant | a variable that has a constant value at every location over a spatial extent; examples: soil type, climate zone, land use |\n| aggregate | values are summary values (aggregates) over the geometry, e.g. population density, dominant land use |\n| identity | values identify the geometry: they refer to (the whole of) this and only this geometry |\n\nWith this information (still to be done) we can for instance\n\n* either return missing values or generate warnings when a _aggregate_ value at a point location inside a polygon is retrieved, or\n* list the implicit assumptions made when retrieving attribute values at points inside a polygon when `relation_to_geometry` is missing.\n* decide what to do with attributes when a geometry is split: do nothing in case the attribute is constant, give an error or warning in case it is an aggregate, change the `relation_to_geometry` to _constant_ in case it was _identity_.\n\nFurther reading:\n\n1. S. Scheider, B. Gräler, E. Pebesma, C. Stasch, 2016. Modelling spatio-temporal information generation. Int J of Geographic Information Science, 30 (10), 1980-2008. ([open access](https://doi.org/10.1080/13658816.2016.1151520))\n2. Stasch, C., S. Scheider, E. Pebesma, W. Kuhn, 2014. Meaningful Spatial Prediction and Aggregation. Environmental Modelling & Software, 51, (149–165, [open access](http://dx.doi.org/10.1016/j.envsoft.2013.09.006)).\n"
  },
  {
    "path": "vignettes/sf2.Rmd",
    "content": "---\ntitle: \"2. Reading, Writing and Converting Simple Features\"\nauthor: \"Edzer Pebesma\"\noutput:\n  html_document:\n    toc: true\n    toc_float:\n      collapsed: false\n      smooth_scroll: false\n    toc_depth: 2\nvignette: >\n  %\\VignetteIndexEntry{2. Reading, Writing and Converting Simple Features}\n  %\\VignetteEngine{knitr::rmarkdown}\n  %\\VignetteEncoding{UTF-8}\n---\n\n```{r echo=FALSE, include=FALSE}\nknitr::opts_chunk$set(collapse = TRUE)\nif (file.exists(\"nc1.shp\"))\n\tfile.remove(\"nc1.shp\", \"nc1.dbf\", \"nc1.shx\")\n```\n\nThis vignette describes how simple features can be read in R\nfrom files or databases, and how they can be converted to other\nformats (text, [sp](https://cran.r-project.org/package=sp))\n\n## Reading and writing through GDAL\n\nThe Geospatial Data Abstraction Library\n([GDAL](https://gdal.org/)) is the Swiss Army Knife for spatial\ndata: it reads and writes vector and raster data from and to practically\nevery file format, or database, of significance. Package `sf` reads\nand writes using GDAL using `st_read()` and `st_write()`.\n\nThe data model GDAL uses needs\n\n* a data source, which may be a file, directory, or database\n* a layer, which is a single geospatial dataset inside a file or directory or e.g. a table in a database.\n* the specification of a driver (i.e., which format)\n* driver-specific reading or writing data sources, or layers\n\nThis may sound complex, but it is needed to map to over 200 data\nformats! Package `sf` tries hard to simplify this where possible\n(e.g. a file contains a single layer), but this vignette will try\nto point you to the options.\n\n### Using st_read\n\nAs an example, we read the North Carolina counties SIDS dataset,\nwhich comes shipped with the `sf` package by:\n\n```{r}\nlibrary(sf)\nfname <- system.file(\"shape/nc.shp\", package=\"sf\")\nfname\nnc <- st_read(fname)\n```\n\nTypical users will use a file name with path for `fname`, or\nfirst set R's working directory with `setwd()` and use file name\nwithout path.\n\nWe see here that a single argument is used to find both the\ndatasource and the layer. This works when the datasource contains a\nsingle layer. In case the number of layers is zero (e.g. a database\nwith no tables), an error message is given. In case there are more layers\nthan one, the first layer is returned, but a message and a\nwarning are given:\n\n```{r eval=FALSE}\n> st_read(\"PG:dbname=postgis\")\nMultiple layers are present in data source PG:dbname=postgis, reading layer `meuse'.\nUse `st_layers' to list all layer names and their type in a data source.\nSet the `layer' argument in `st_read' to read a particular layer.\nReading layer `meuse' from data source `PG:dbname=postgis' using driver `PostgreSQL'\nSimple feature collection with 155 features and 12 fields\ngeometry type:  POINT\ndimension:      XY\nbbox:           xmin: 178605 ymin: 329714 xmax: 181390 ymax: 333611\nepsg (SRID):    28992\nproj4string:    +proj=sterea +lat_0=52.15616055555555 ...\nWarning message:\nIn eval(substitute(expr), envir, enclos) :\n  automatically selected the first layer in a data source containing more than one.\n```\n\nThe message points to the `st_layers()` command, which lists the driver\nand layers in a datasource, e.g.\n\n```{r eval=FALSE}\n> st_layers(\"PG:dbname=postgis\")\nDriver: PostgreSQL \nAvailable layers:\n  layer_name geometry_type features fields\n1      meuse         Point      155     12\n2   meuse_sf         Point      155     12\n3       sids Multi Polygon      100     14\n4  meuse_tbl         Point      155     13\n5 meuse_tbl2         Point      155     13\n> \n```\n\nA particular layer can now be read by e.g.\n```{r eval=FALSE}\nst_read(\"PG:dbname=postgis\", \"sids\")\n```\n\n`st_layers()` has the option to count the number of features in case\nthese are missing: some datasources (e.g. OSM xml files) do not\nreport the number of features, but need to be completely read for\nthis. GDAL allows for more than one geometry column for a feature\nlayer; these are reported by `st_layers()`.\n\nIn case a layer contains only geometries but no attributes (fields),\n`st_read()` still returns an `sf` object, with a geometry column only.\n\nWe see that GDAL automatically detects the driver (file format)\nof the datasource, by trying them all in turn.\n\n`st_read()` follows the conventions of base R, similar to how it\nreads tabular data into `data.frame`s. This means that character\ndata are read as `character` vectors by default (since R 4.1.0).\nFor those who insist on retrieving character data as `factor`s,\nthe argument `stringsAsFactors` can be set to `TRUE`:\n\n```{r eval=FALSE}\nst_read(fname, stringsAsFactors = TRUE)\n```\n\nAlternatively, a user can set the global option `stringsAsFactors`, and this will have the same effect:\n\n```{r}\noptions(stringsAsFactors = TRUE)\nst_read(fname)\n```\n\n### Using st_write\n\nTo write a simple features object to a file, we need at least\ntwo arguments, the object and a filename:\n\n```{r eval=FALSE}\nst_write(nc, \"nc1.shp\")\n```\n\nThe file name is taken as the data source name. The default for\nthe layer name is the basename (filename without path) of the\ndata source name. For this, `st_write()` needs to guess the driver. The\nabove command is, for instance, equivalent to:\n\n```{r}\nst_write(nc, dsn = \"nc1.shp\", layer = \"nc.shp\", driver = \"ESRI Shapefile\")\n```\n\nHow the guessing of drivers works is explained in the next section.\n\n### Guessing a driver for output\n\nThe output driver is guessed from the datasource name, either from\nits extension (`.shp`: `ESRI Shapefile`), or its prefix (`PG:`:\n`PostgreSQL`). The list of extensions with corresponding driver \n(short driver name) is:\n\n| extension| driver short name |\n| ---------| -----------------------------------------------------|\n| `bna`    |`BNA` |\n| `csv`    |`CSV` |\n| `e00`    |`AVCE00` |\n| `gdb`    |`FileGDB` |\n| `geojson`|`GeoJSON` |\n| `gml`    |`GML` |\n| `gmt`    |`GMT` |\n| `gpkg`   |`GPKG` |\n| `gps`    |`GPSBabel` |\n| `gtm`    |`GPSTrackMaker`|\n| `gxt`    |`Geoconcept` |\n| `jml`    |`JML` |\n| `map`    |`WAsP` |\n| `mdb`    |`Geomedia` |\n| `nc`     |`netCDF` |\n| `ods`    |`ODS` |\n| `osm`    |`OSM` |\n| `pbf`    |`OSM` |\n| `shp`    |`ESRI Shapefile` |\n| `sqlite` |`SQLite` |\n| `vdv`    |`VDV` |\n| `xls`    |`xls` |\n| `xlsx`   |`XLSX` |\n\nThe list with prefixes is:\n\n| prefix    | driver short name |\n| ----------| ------------------------------------------------------------------|\n| `couchdb:`|`CouchDB`      |\n| `DB2ODBC:`|`DB2ODBC`      |\n| `DODS:`   |`DODS`         |\n| `GFT:`    |`GFT`          |\n| `MSSQL:`  |`MSSQLSpatial` |\n| `MySQL:`  |`MySQL`        |\n| `OCI:`    |`OCI`          |\n| `ODBC:`   |`ODBC`         |\n| `PG:`     |`PostgreSQL`   |\n| `SDE:`    |`SDE`          |\n\n\n### Dataset and layer reading or creation options\n\nVarious GDAL drivers have options that influences the reading\nor writing process, for example what the driver should do when a\ntable already exists in a database: append records to the table\nor overwrite it:\n\n```{r eval=FALSE}\nst_write(st_as_sf(meuse), \"PG:dbname=postgis\", \"meuse\", \n    layer_options = \"OVERWRITE=true\")\n```\n\nIn case the table exists and the option is not specified, the driver\nwill give an error. Driver-specific options are documented in the\ndriver manual of [gdal](https://gdal.org/en/latest/drivers/vector/index.html).\nMultiple options can be given by multiple strings in `options`.\n\nFor `st_read()`, there is only `options`; for `st_write()`, one needs\nto distinguish between `dataset_options` and `layer_options`, the\nfirst related to opening a dataset, the second to creating layers\nin the dataset.\n\n## Reading and writing directly to and from spatial databases\n\nPackage `sf` supports reading and\nwriting from and to spatial databases using the `DBI` interface.\nSo far, testing has mainly be done with `PostGIS`, other databases\nmight work but may also need more work. An example of reading is:\n\n```{r eval=FALSE}\nlibrary(RPostgreSQL) \nconn = dbConnect(PostgreSQL(), dbname = \"postgis\") \nmeuse = st_read(conn, \"meuse\")\nmeuse_1_3 = st_read(conn, query = \"select * from meuse limit 3;\") \ndbDisconnect(conn) \n```\n\nWe see here that in the second example a query is given. This\nquery may contain spatial predicates, which could be a way to work\nthrough massive spatial datasets in R without having to read them\ncompletely in memory.\n\nSimilarly, tables can be written:\n\n```{r eval=FALSE}\nconn = dbConnect(PostgreSQL(), dbname = \"postgis\")\nst_write(conn, meuse, drop = TRUE)\ndbDisconnect(conn)\n```\n\nHere, the default table (layer) name is taken from the object name\n(`meuse`). Argument `drop` informs to drop (remove) the table\nbefore writing; logical argument `binary` determines whether to\nuse well-known binary or well-known text when writing the geometry\n(where well-known binary is faster and lossless).\n\n## Conversion to other formats: WKT, WKB, sp\n\n### Conversion to and from well-known text\n\nThe usual form in which we see simple features printed is well-known text:\n\n```{r}\nst_point(c(0,1))\nst_linestring(matrix(0:9,ncol=2,byrow=TRUE))\n```\n\nWe can create these well-known text strings explicitly using `st_as_text`:\n\n```{r}\nx = st_linestring(matrix(0:9,ncol=2,byrow=TRUE))\nstr = st_as_text(x)\nx\n```\n\nWe can convert back from WKT by using `st_as_sfc()`:\n\n```{r}\nst_as_sfc(str)\n```\n\n### Conversion to and from well-known binary\n\nWell-known binary is created from simple features by `st_as_binary()`:\n\n```{r}\nx = st_linestring(matrix(0:9,ncol=2,byrow=TRUE))\n(x = st_as_binary(x))\nclass(x)\n```\n\nThe object returned by `st_as_binary()` is of class `WKB` and is\neither a list with raw vectors, or a single raw vector. These\ncan be converted into a hexadecimal character vector using `rawToHex()`:\n\n```{r}\nrawToHex(x)\n```\n\nConverting back to `sf` uses `st_as_sfc()`:\n\n```{r}\nx = st_as_binary(st_sfc(st_point(0:1), st_point(5:6)))\nst_as_sfc(x)\n```\n\n### Conversion to and from sp\n\nSpatial objects as maintained by package `sp` can be converted into\nsimple feature objects or geometries by `st_as_sf()` and `st_as_sfc()`,\nrespectively:\n\n```{r}\nmethods(st_as_sf)\nmethods(st_as_sfc)\n```\n\nAn example would be:\n\n```{r}\nlibrary(sp)\ndata(meuse)\ncoordinates(meuse) = ~x+y\nm.sf = st_as_sf(meuse)\nopar = par(mar=rep(0,4))\nplot(m.sf)\n```\n\nConversion of simple feature objects of class `sf` or `sfc` into corresponding \n`Spatial*` objects is done using the `as` method, coercing to `Spatial`:\n\n```{r}\nx = st_sfc(st_point(c(5,5)), st_point(c(6,9)), crs = 4326)\nas(x, \"Spatial\")\n```\n"
  },
  {
    "path": "vignettes/sf3.Rmd",
    "content": "---\ntitle: \"3. Manipulating Simple Feature Geometries\"\nauthor: \"Edzer Pebesma\"\noutput:\n  html_document:\n    toc: true\n    toc_float:\n      collapsed: false\n      smooth_scroll: false\n    toc_depth: 2\nvignette: >\n  %\\VignetteIndexEntry{3. Manipulating Simple Feature Geometries}\n  %\\VignetteEngine{knitr::rmarkdown}\n  %\\VignetteEncoding{UTF-8}\n---\n\n```{r echo=FALSE, include=FALSE}\nknitr::opts_chunk$set(collapse = TRUE)\n```\n\nThis vignette describes how simple feature geometries can be\nmanipulated, where manipulations include\n\n* type transformations (e.g., `POLYGON` to `MULTIPOLYGON`)\n* affine transformation (shift, scale, rotate)\n* transformation into a different coordinate reference system \n* geometrical operations, e.g. finding the centroid of a polygon, detecting whether pairs of feature geometries intersect, or find the union (overlap) of two polygons.\n\n## Type transformations\n\nThis sections discusses how simple feature geometries of one type can be converted to another. For converting lines to polygons, see also `st_polygonize()` below.\n\n### For single geometries\n\nFor single geometries, `st_cast()` will\n\n1. convert from XX to MULTIXX, e.g. `LINESTRING` to `MULTILINESTRING`\n2. convert from MULTIXX to XX if MULTIXX has length one (else, it will still convert but warn about loss of information)\n3. convert from MULTIXX to XX if MULTIXX does not have length one, but it will warn about the loss of information\n4. convert GEOMETRYCOLLECTION of length one to its component if \n\nExamples of the first three types are:\n```{r}\nlibrary(sf)\nsuppressPackageStartupMessages(library(dplyr))\nst_point(c(1,1)) |> st_cast(\"MULTIPOINT\")\nst_multipoint(rbind(c(1,1))) |> st_cast(\"POINT\")\nst_multipoint(rbind(c(1,1),c(2,2))) |> st_cast(\"POINT\")\n```\nExamples of the fourth type are:\n```{r}\nst_geometrycollection(list(st_point(c(1,1)))) |> st_cast(\"POINT\")\n```\n\n### For collections of geometry (sfc) and simple feature collections (sf)\n\nIt should be noted here that when reading geometries using `st_read()`, the `type` argument can be used to control the class of the returned geometry:\n```{r}\nshp = system.file(\"shape/nc.shp\", package=\"sf\")\nclass(st_geometry(st_read(shp, quiet = TRUE)))\nclass(st_geometry(st_read(shp, quiet = TRUE, type = 3)))\nclass(st_geometry(st_read(shp, quiet = TRUE, type = 1)))\n```\n\nThis option is handled by the GDAL library; in case of failure to convert to the target type, the original types are returned, which in this case is a mix of `POLYGON` and `MULTIPOLYGON` geometries, leading to a `GEOMETRY` as superclass. When we try to read multipolygons as polygons, all secondary rings of multipolygons get lost. \n\nWhen functions return objects with mixed geometry type (`GEOMETRY`), downstream functions such as `st_write()` may have difficulty handling them. For some of these cases, `st_cast()` may help modify their type.  For sets of geometry objects (`sfc`) and simple feature sets (`sf), `st_cast` can be used by specifying the target type, or without specifying it. \n\n```{r}\nls <- st_linestring(rbind(c(0,0),c(1,1),c(2,1)))\nmls <- st_multilinestring(list(rbind(c(2,2),c(1,3)), rbind(c(0,0),c(1,1),c(2,1))))\n(sfc <- st_sfc(ls,mls))\nst_cast(sfc, \"MULTILINESTRING\")\nsf <- st_sf(a = 5:4, geom = sfc)\nst_cast(sf, \"MULTILINESTRING\")\n```\nWhen no target type is given, `st_cast()` tries to be smart for two cases:\n\n1. if the class of the object is `GEOMETRY`, and all elements are of identical type, and\n2. if all elements are length-one `GEOMETRYCOLLECTION` objects, in which case `GEOMETRYCOLLECTION` objects are replaced by their content (which may be a `GEOMETRY` mix again)\n\nExamples are:\n\n```{r}\nls <- st_linestring(rbind(c(0,0),c(1,1),c(2,1)))\nmls1 <- st_multilinestring(list(rbind(c(2,2),c(1,3)), rbind(c(0,0),c(1,1),c(2,1))))\nmls2 <- st_multilinestring(list(rbind(c(4,4),c(4,3)), rbind(c(2,2),c(2,1),c(3,1))))\n(sfc <- st_sfc(ls,mls1,mls2))\nclass(sfc[2:3])\nclass(st_cast(sfc[2:3]))\n\ngc1 <- st_geometrycollection(list(st_linestring(rbind(c(0,0),c(1,1),c(2,1)))))\ngc2 <- st_geometrycollection(list(st_multilinestring(list(rbind(c(2,2),c(1,3)), rbind(c(0,0),c(1,1),c(2,1))))))\ngc3 <- st_geometrycollection(list(st_multilinestring(list(rbind(c(4,4),c(4,3)), rbind(c(2,2),c(2,1),c(3,1))))))\n(sfc <- st_sfc(gc1,gc2,gc3))\nclass(st_cast(sfc))\nclass(st_cast(st_cast(sfc), \"MULTILINESTRING\"))\n```\n\n## Affine transformations\n\nAffine transformations are transformations of the type $f(x) = xA + b$, where matrix $A$ is used to flatten, scale and/or rotate, and $b$ to translate $x$. Low-level examples are:\n```{r}\n(p = st_point(c(0,2)))\np + 1\np + c(1,2)\np + p\np * p\nrot = function(a) matrix(c(cos(a), sin(a), -sin(a), cos(a)), 2, 2)\np * rot(pi/4)\np * rot(pi/2)\np * rot(pi)\n```\n\nJust to make the point, we can for instance rotate the counties of North Carolina 90 degrees clockwise around their centroid, and shrink them to 75% of their original size:\n```{r,fig=TRUE}\nnc = st_read(system.file(\"shape/nc.shp\", package=\"sf\"), quiet = TRUE)\nncg = st_geometry(nc)\nplot(ncg, border = 'grey')\ncntrd = st_centroid(ncg)\nncg2 = (ncg - cntrd) * rot(pi/2) * .75 + cntrd\nplot(ncg2, add = TRUE)\nplot(cntrd, col = 'red', add = TRUE, cex = .5)\n```\n\n\n## Coordinate reference systems conversion and transformation\n\n### Getting and setting coordinate reference systems of sf objects\n\nThe coordinate reference system of objects of class `sf` or `sfc` is\nobtained by `st_crs()`, and replaced by `st_crs<-`:\n```{r}\nlibrary(sf)\ngeom = st_sfc(st_point(c(0,1)), st_point(c(11,12)))\ns = st_sf(a = 15:16, geometry = geom)\nst_crs(s)\ns1 = s\nst_crs(s1) <- 4326\nst_crs(s1)\ns2 = s\nst_crs(s2) <- \"+proj=longlat +datum=WGS84\"\nall.equal(s1, s2)\n```\nAn alternative, more pipe-friendly version of `st_crs<-` is \n```{r}\ns1 |> st_set_crs(4326)\n```\n\n### Coordinate reference system transformations\n\nIf we change the coordinate reference system from one non-missing\nvalue into another non-missing value, the CRS is is changed without\nmodifying any coordinates, but a warning is issued that this\ndid not reproject values:\n```{r}\ns3 <- s1 |> st_set_crs(4326) |> st_set_crs(3857)\n```\nA cleaner way to do this that better expresses intention and does\nnot generate this warning is to first wipe the CRS by assigning it \na missing value, and then set it to the intended value.\n```{r}\ns3 <- s1  |> st_set_crs(NA) |> st_set_crs(3857)\n```\nTo carry out a coordinate conversion or transformation, we use\n`st_transform()`\n```{r}\ns3 <- s1 |> st_transform(3857)\ns3\n```\nfor which we see that coordinates are actually modified (projected).\n\n## Geometrical operations\n\nAll geometrical operations `st_op(x)` or `st_op2(x,y)` work\nboth for `sf` objects and for `sfc` objects `x` and `y`; since\nthe operations work on the geometries, the non-geometry parts of\nan `sf` object are simply discarded. Also, all binary operations\n`st_op2(x,y)` called with a single argument, as `st_op2(x)`, are\nhandled as `st_op2(x,x)`.\n\nWe will illustrate the geometrical operations on a very simple dataset:\n\n```{r figure=TRUE}\nb0 = st_polygon(list(rbind(c(-1,-1), c(1,-1), c(1,1), c(-1,1), c(-1,-1))))\nb1 = b0 + 2\nb2 = b0 + c(-0.2, 2)\nx = st_sfc(b0, b1, b2)\na0 = b0 * 0.8\na1 = a0 * 0.5 + c(2, 0.7)\na2 = a0 + 1\na3 = b0 * 0.5 + c(2, -0.5)\ny = st_sfc(a0,a1,a2,a3)\nplot(x, border = 'red')\nplot(y, border = 'green', add = TRUE)\n```\n\n### Unary operations\n\n`st_is_valid()` returns whether polygon geometries are topologically valid:\n```{r}\nb0 = st_polygon(list(rbind(c(-1,-1), c(1,-1), c(1,1), c(-1,1), c(-1,-1))))\nb1 = st_polygon(list(rbind(c(-1,-1), c(1,-1), c(1,1), c(0,-1), c(-1,-1))))\nst_is_valid(st_sfc(b0,b1))\n```\nand `st_is_simple()` whether line geometries are simple:\n```{r}\ns = st_sfc(st_linestring(rbind(c(0,0), c(1,1))), \n\tst_linestring(rbind(c(0,0), c(1,1),c(0,1),c(1,0))))\nst_is_simple(s)\n```\n\n`st_area()` returns the area of polygon geometries, `st_length()` the\nlength of line geometries:\n```{r}\nst_area(x)\nst_area(st_sfc(st_point(c(0,0))))\nst_length(st_sfc(st_linestring(rbind(c(0,0),c(1,1),c(1,2))), st_linestring(rbind(c(0,0),c(1,0)))))\nst_length(st_sfc(st_multilinestring(list(rbind(c(0,0),c(1,1),c(1,2))),rbind(c(0,0),c(1,0))))) # ignores 2nd part!\n```\n\n### Binary operations: distance and relate\n`st_distance()` computes the shortest distance matrix between geometries; this is\na dense matrix:\n```{r}\nst_distance(x,y)\n```\n`st_relate()` returns a dense character matrix with the DE9-IM relationships\nbetween each pair of geometries:\n```{r}\nst_relate(x,y)\n```\nelement [i,j] of this matrix has nine characters, referring to relationship between x[i] and y[j], encoded as $I_xI_y,I_xB_y,I_xE_y,B_xI_y,B_xB_y,B_xE_y,E_xI_y,E_xB_y,E_xE_y$ where $I$ refers to interior, $B$ to boundary, and $E$ to exterior, and e.g. $B_xI_y$ the dimensionality of the intersection of the boundary $B_x$ of x[i] and the interior $I_y$ of y[j], which is one of {0,1,2,F}, indicating zero-, one-, two-dimension intersection, and (F) no intersection, respectively.\n\n### Binary logical operations: \nBinary logical operations return either a sparse matrix\n```{r}\nst_intersects(x,y)\n```\nor a dense matrix\n```{r}\nst_intersects(x, x, sparse = FALSE)\nst_intersects(x, y, sparse = FALSE)\n```\nwhere list element `i` of a sparse matrix contains the indices of\nthe `TRUE` elements in row `i` of the dense matrix. For large\ngeometry sets, dense matrices take up a lot of memory and are\nmostly filled with `FALSE` values, hence the default is to return\na sparse matrix.\n\n`st_intersects()` returns for every geometry pair whether they\nintersect (dense matrix), or which elements intersect (sparse).\nNote that `st_intersection()` in this package returns\na geometry for the intersection instead of logicals as in `st_intersects()` (see the next section of this vignette).\n\nOther binary predicates include (using sparse for readability):\n\n```{r}\nst_disjoint(x, y, sparse = FALSE)\nst_touches(x, y, sparse = FALSE)\nst_crosses(s, s, sparse = FALSE)\nst_within(x, y, sparse = FALSE)\nst_contains(x, y, sparse = FALSE)\nst_overlaps(x, y, sparse = FALSE)\nst_equals(x, y, sparse = FALSE)\nst_covers(x, y, sparse = FALSE)\nst_covered_by(x, y, sparse = FALSE)\nst_covered_by(y, y, sparse = FALSE)\nst_equals_exact(x, y,0.001, sparse = FALSE)\n```\n\n### Operations returning a geometry\n\n```{r, fig=TRUE}\nu = st_union(x)\nplot(u)\n```\n\n```{r, fig=TRUE}\npar(mfrow=c(1,2), mar = rep(0,4))\nplot(st_buffer(u, 0.2))\nplot(u, border = 'red', add = TRUE)\nplot(st_buffer(u, 0.2), border = 'grey')\nplot(u, border = 'red', add = TRUE)\nplot(st_buffer(u, -0.2), add = TRUE)\n```\n\n```{r}\nplot(st_boundary(x))\n```\n\n```{r}\npar(mfrow = c(1:2))\nplot(st_convex_hull(x))\nplot(st_convex_hull(u))\npar(mfrow = c(1,1))\n```\n\n```{r, fig=TRUE}\npar(mfrow=c(1,2))\nplot(x)\nplot(st_centroid(x), add = TRUE, col = 'red')\nplot(x)\nplot(st_centroid(u), add = TRUE, col = 'red')\n```\n\nThe intersection of two geometries is the geometry covered by both; it is obtained by `st_intersection()`:\n```{r, fig=TRUE}\nplot(x)\nplot(y, add = TRUE)\nplot(st_intersection(st_union(x),st_union(y)), add = TRUE, col = 'red')\n```\n\nNote that `st_intersects()` returns a logical matrix indicating whether each geometry pair intersects (see the previous section in this vignette).\n\nTo get _everything but_ the intersection, use `st_difference()` or `st_sym_difference()`:\n```{r,fig=TRUE}\npar(mfrow=c(2,2), mar = c(0,0,1,0))\nplot(x, col = '#ff333388'); \nplot(y, add=TRUE, col='#33ff3388')\ntitle(\"x: red, y: green\")\nplot(x, border = 'grey')\nplot(st_difference(st_union(x),st_union(y)), col = 'lightblue', add = TRUE)\ntitle(\"difference(x,y)\")\nplot(x, border = 'grey')\nplot(st_difference(st_union(y),st_union(x)), col = 'lightblue', add = TRUE)\ntitle(\"difference(y,x)\")\nplot(x, border = 'grey')\nplot(st_sym_difference(st_union(y),st_union(x)), col = 'lightblue', add = TRUE)\ntitle(\"sym_difference(x,y)\")\n```\n\n`st_segmentize()` adds points to straight line sections of a lines or polygon object:\n```{r,fig=TRUE}\npar(mfrow=c(1,3),mar=c(1,1,0,0))\npts = rbind(c(0,0),c(1,0),c(2,1),c(3,1))\nls = st_linestring(pts)\nplot(ls)\npoints(pts)\nls.seg = st_segmentize(ls, 0.3)\nplot(ls.seg)\npts = ls.seg\npoints(pts)\npol = st_polygon(list(rbind(c(0,0),c(1,0),c(1,1),c(0,1),c(0,0))))\npol.seg = st_segmentize(pol, 0.3)\nplot(pol.seg, col = 'grey')\npoints(pol.seg[[1]])\n```\n\n`st_polygonize()` polygonizes a multilinestring, as long as the points form a closed polygon:\n```{r,fig=TRUE}\npar(mfrow=c(1,2),mar=c(0,0,1,0))\nmls = st_multilinestring(list(matrix(c(0,0,0,1,1,1,0,0),,2,byrow=TRUE)))\nx = st_polygonize(mls)\nplot(mls, col = 'grey')\ntitle(\"multilinestring\")\nplot(x, col = 'grey')\ntitle(\"polygon\")\n```\n"
  },
  {
    "path": "vignettes/sf4.Rmd",
    "content": "---\ntitle: \"4. Manipulating Simple Features\"\nauthor: \"Edzer Pebesma\"\noutput:\n  html_document:\n    toc: true\n    toc_float:\n      collapsed: false\n      smooth_scroll: false\n    toc_depth: 2\nvignette: >\n  %\\VignetteIndexEntry{4. Manipulating Simple Features}\n  %\\VignetteEngine{knitr::rmarkdown}\n  %\\VignetteEncoding{UTF-8}\n---\n\n```{r echo=FALSE, include=FALSE}\nknitr::opts_chunk$set(collapse = TRUE)\n```\nThis vignette describes how simple features, i.e. records that come with a geometry, can be manipulated, for the case where these manipulations involve geometries. Manipulations include:\n\n* aggregating feature sets\n* summarising feature sets\n* joining two feature sets based on feature geometry\n\nFeatures are represented by records in an `sf` object, and have feature attributes (all non-geometry fields) and feature geometry. Since `sf` objects are a subclass of `data.frame` or `tbl_df`, operations on feature attributes work identically to how they work on `data.frame`s, e.g.\n\n```{r}\nlibrary(sf)\nnc <- st_read(system.file(\"shape/nc.shp\", package=\"sf\"))\nnc <- st_transform(nc, 2264)\nnc[1,]\n``` \nprints the first record.\n\nMany of the tidyverse/dplyr verbs have methods for `sf` objects. This means that if both `sf` and `dplyr` are loaded, manipulations such as selecting a single attribute will return an `sf` object:\n```{r}\nlibrary(dplyr)\nnc |> select(NWBIR74) |> head(2)\n```\nwhich implies that the geometry is sticky, and gets added automatically. If we want to drop geometry, we can coerce to `data.frame` first, this drops geometry list-columns:\n```{r}\nnc |> as.data.frame() |> select(NWBIR74) |> head(2)\n```\n\n## Subsetting feature sets\n\nWe can subset feature sets by using the square bracket notation\n\n```{r}\nnc[1, \"NWBIR74\"]\n```\nand use the `drop` argument to drop geometries:\n```{r}\nnc[1, \"NWBIR74\", drop = TRUE]\n```\nbut we can also use a spatial object as the row selector, to select features that intersect with another spatial feature:\n```{r}\nAshe = nc[nc$NAME == \"Ashe\",]\nclass(Ashe)\nnc[Ashe,]\n```\nWe see that in the result set `Ashe` is included, as the default value for argument `op` in `[.sf` is `st_intersects()`, and `Ashe` intersects with itself. We could exclude self-intersection by using predicate `st_touches()` (overlapping features don't touch):\n```{r}\nAshe = nc[nc$NAME == \"Ashe\",]\nnc[Ashe, op = st_touches]\n```\nUsing `dplyr`, we can do the same by calling the predicate directly:\n```{r}\nnc |> filter(lengths(st_touches(nc, Ashe)) > 0)\n```\n\n## Aggregating or summarizing feature sets\n\nSuppose we want to compare the 1974 fraction of SID (sudden infant death) of the counties that intersect with `Ashe` to the remaining ones. We can do this by:\n```{r}\na <- aggregate(nc[, c(\"SID74\", \"BIR74\")], list(Ashe_nb = lengths(st_intersects(nc, Ashe)) > 0), sum)\na <- a |> mutate(frac74 = SID74 / BIR74) |> select(frac74)\nplot(a[2], col = c(grey(.8), grey(.5)))\nplot(st_geometry(Ashe), border = '#ff8888', add = TRUE, lwd = 2)\n```\n\n## Joining two feature sets based on attributes\n\nThe usual join verbs of base R (`merge`) and of dplyr (`left_join()`, etc) work for `sf` objects as well; the joining takes place on attributes (ignoring geometries). In case of no matching geometry, an empty geometry is substituted. The second argument should be a `data.frame` (or similar), not an `sf` object:\n\n```{r}\nx = st_sf(a = 1:2, geom = st_sfc(st_point(c(0,0)), st_point(c(1,1))))\ny = data.frame(a = 2:3)\nmerge(x, y)\nmerge(x, y, all = TRUE)\nright_join(x, y)\n```\n\n## Joining two feature sets based on geometries\n\nFor joining based on spatial intersections (of any kind), `st_join()` is used:\n\n```{r fig=TRUE}\nx = st_sf(a = 1:3, geom = st_sfc(st_point(c(1,1)), st_point(c(2,2)), st_point(c(3,3))))\ny = st_buffer(x, 0.1)\nx = x[1:2,]\ny = y[2:3,]\nplot(st_geometry(x), xlim = c(.5, 3.5))\nplot(st_geometry(y), add = TRUE)\n```\n\nThe join method is a left join, retaining all records of the first attribute:\n\n```{r}\nst_join(x, y)\nst_join(y, x)\n```\n\nand the geometry retained is that of the first argument.\n\nThe spatial join predicate can be controlled with any function compatible with `st_intersects()` (the default), e.g.\n\n```{r}\nst_join(x, y, join = st_covers) # no matching y records: points don't cover circles\nst_join(y, x, join = st_covers) # matches for those circles covering a point\n```\n"
  },
  {
    "path": "vignettes/sf5.Rmd",
    "content": "---\ntitle: \"5. Plotting Simple Features\"\nauthor: \"Edzer Pebesma\"\noutput:\n  html_document:\n    toc: true\n    toc_float:\n      collapsed: false\n      smooth_scroll: false\n    toc_depth: 2\nvignette: >\n  %\\VignetteIndexEntry{5. Plotting Simple Features}\n  %\\VignetteEngine{knitr::rmarkdown}\n  %\\VignetteEncoding{UTF-8}\n---\n\nThis vignette describes the functions in `sf` that can help to plot \nsimple features. It tries to be complete about the plot methods \n`sf` provides, and give examples and pointers to options to plot\nsimple feature objects with other packages (mapview, tmap, ggplot2).\n\n# Plot methods for `sf` and `sfc` objects\n\n\n## Geometry only: `sfc`\n\nGeometry list-columns (objects of class `sfc`, obtained by the `st_geometry` method) only show the geometry:\n```{r}\nlibrary(sf)\ndemo(nc, ask = FALSE, echo = FALSE)\nplot(st_geometry(nc))\n```\n\nwhich can be further annotated with colors, symbols, etc., as the usual base plots, e.g. points are added to a polygon plot by:\n\n```{r}\nplot(st_geometry(nc), col = sf.colors(12, categorical = TRUE), border = 'grey', \n\t axes = TRUE)\nplot(st_geometry(st_centroid(nc)), pch = 3, col = 'red', add = TRUE)\n```\n\nand legends, titles and so on can be added afterwards. `border = NA` removes the polygon borders.\n\nAs can be seen, the axes plotted are sensitive to the CRS, and in case of longitude/latitude coordinates, degree symbols and orientation are added if `axes = TRUE`.\n\n## Geometry with attributes: `sf`\nThe default plot of an `sf` object is a multi-plot of all attributes, up to a reasonable maximum:\n```{r}\nplot(nc)\n```\n\nwith a warning when not all attributes can be reasonably plotted. One can increase the maximum number of maps to be plotted by\n```{r}\nplot(nc, max.plot = 14)\n```\n\nThe row/column layout is chosen such that the plotting area is maximally filled. The default value for `max.plot` can be controlled, e.g. by setting the global option `sf_max.plot`:\n\n```{r}\noptions(sf_max.plot=1)\nplot(nc)\n```\n\n# Color key place and size\nIn case a single attribute is selected, by default a color key is given the side of the plot where it leaves as much as possible room for the plotted map; for `nc` this is below:\n```{r}\nplot(nc[\"AREA\"])\n```\n\nbut this can be controlled, and set to a particular side (1=below, 2=left, 3=above and 4=right):\n```{r}\nplot(nc[\"AREA\"], key.pos = 4)\n```\n\nThe size of a color key can be controlled, using either relative units (a number between 0 and 1) or absolute units (like `lcm(2)` for 2 cm):\n```{r}\nplot(nc[\"AREA\"], key.pos = 1, axes = TRUE, key.width = lcm(1.3), key.length = 1.0)\n```\n\nKeys for factor variables are a bit different, as we typically don't want to rotate text for them:\n\n```{r}\nnc$f = cut(nc$AREA, 10)\nplot(nc[\"f\"], axes = TRUE, key.pos = 4, pal = sf.colors(10), key.width = lcm(5))\n```\n\n# Class intervals\n\nColor breaks (class intervals) can be controlled by plot arguments `breaks` and `nbreaks`. `nbreaks` specifies the number of breaks; `breaks` is either a vector with break values:\n\n```{r}\nplot(nc[\"AREA\"], breaks = c(0,.05,.1,.15,.2,.25))\n```\n\nor `breaks` is used to indicate a breaks-finding method that is passed as the `style` argument to `classInt::classIntervals()`. Its default value, `pretty`, results in rounded class breaks, and has as a side effect that `nbreaks` may be honoured only approximately. Other methods include `\"equal\"` to break the data range into `\"nbreaks\"` equal classes, `\"quantile\"` to use quantiles as class breaks, and `\"jenks\"`, used in other software.\n\n```{r}\nplot(nc[\"AREA\"], breaks = \"jenks\")\n```\n\n# How does `sf` project geographic coordinates?\n\nPackage `sf` plots projected maps in their native projection, meaning that easting and northing are mapped linearly to the x and y axis, keeping an aspect ratio of 1 (one unit east equals one unit north). For geographic data, where coordinates constitute degrees longitude and latitude, it chooses an [equirectangular projection](https://en.wikipedia.org/wiki/Equirectangular_projection) (also called _equidistant circular_), where at the center of the plot (or of the bounding box) one unit north equals one unit east.\n\nProj.4 also lets you project data to this projection, and the plot of\n```{r}\nplot(st_geometry(nc), axes = TRUE)\n```\n\nshould, apart from the values along axes, be otherwise identical to\n```{r}\nlat_ts = mean(st_bbox(nc)[c(2,4)]) # latitude of true scale\neqc = st_transform(nc, paste0(\"+proj=eqc +lat_ts=\", lat_ts))\nplot(st_geometry(eqc), axes = TRUE)\n```\n\n# Graticules\n\nGraticules are grid lines along equal longitude (meridians) or latitude (parallels) that, depending on the projection used, often plot as curved lines on a map, giving it reference in terms of longitude and latitude. `sf::st_graticule()` tries to create a graticule grid for arbitrary maps. As there are infinitely many projections, there are most likely many cases where it does not succeed in doing this well, and examples of these are welcomed as [sf issues](https://github.com/r-spatial/sf/issues).\n\nThe following plot shows a graticule geometry on itself,\n```{r}\nlibrary(maps)\nusa = st_as_sf(map('usa', plot = FALSE, fill = TRUE))\nlaea = st_crs(\"+proj=laea +lat_0=30 +lon_0=-95\") # Lambert equal area\nusa <- st_transform(usa, laea)\ng = st_graticule(usa)\nplot(st_geometry(g), axes = TRUE)\n```\n\nwhere we see that the graticule does not reach the plot boundaries (but is cut off at the bounding box of `usa`), and that the axes show projected coordinates.\n\nWhen we compute the graticule within the plotting function, we know the plotting region and can compute it up to the plot margins, and add axes in graticule units:\n```{r}\nplot(usa, graticule = TRUE, key.pos = NULL, axes = TRUE)\n```\n\nWe can also pass a `crs` object to `graticule` to obtain a graticule in a datum different from the default (WGS84). `st_graticule()` takes parameters, and we can pass an object returned by it to the `graticule` parameter of `plot`, to get finer control:\n```{r}\ng = st_graticule(usa, lon = seq(-130,-65,5))\nplot(usa, graticule = g, key.pos = NULL, axes = TRUE,\n\t xlim = st_bbox(usa)[c(1,3)], ylim = st_bbox(usa)[c(2,4)],\n\t xaxs = \"i\", yaxs = \"i\")\n```\n\nwhich still doesn't look great -- completely controlling the plotting region of base plots is not easy.\n\n# Plotting sf objects with other packages\n\n## grid: `st_as_grob`\n\nPackage `sf` provides a number of methods for `st_as_grob()`:\n```{r}\nmethods(st_as_grob)\n```\n\nwhich convert simple simple feature objects into `grob` (\"graphics objects\") objects; `grob`s are the graphic primitives of the `grid` plotting package. These methods can be used by plotting packages that build on `grid`, such as `ggplot2` (which uses them in `geom_sf()`) and `tmap`. In addition, `st_viewport()` can be used to set up a grid viewport from an `sf` object, with an aspect ratio similar to that of `plot.sf()`.\n\n\n## ggplot2\n\ncontains a geom specially for simple feature objects, with support for graticule white lines in the background using `sf::st_graticule()`. Support is currently good for polygons; for lines or points, your mileage may vary.\n\n```{r}\nlibrary(ggplot2)\nggplot() + geom_sf(data = usa)\n```\n\nPolygons can be colored using `aes`:\n```{r}\nggplot() + \n  geom_sf(data = nc, aes(fill = BIR74)) + \n  scale_y_continuous(breaks = 34:36)\n```\n\nand sets of maps can be plotted as facet plots after rearranging the `sf` object, e.g. by\n```{r}\nlibrary(dplyr)\nlibrary(tidyr)\nnc2 <- nc |> select(SID74, SID79, geom) |> gather(VAR, SID, -geom)\nggplot() + \n  geom_sf(data = nc2, aes(fill = SID)) + \n  facet_wrap(~VAR, ncol = 1) +\n  scale_y_continuous(breaks = 34:36)\n```\n\n## mapview\n\nPackage `mapview` creates interactive maps in html pages, using package `leaflet` as a workhorse. Extensive examples are found [here](https://r-spatial.github.io/mapview/).\n\nAn example is obtained by\n```{r, eval = FALSE}\nlibrary(mapview)\nmapviewOptions(fgb = FALSE) # needed when creating web pages\nmapview(nc[\"BIR74\"], col.regions = sf.colors(10), fgb = FALSE)\n```\n\ngives a map which is interactive: you can zoom and pan, and query features by clicking on them.\n\n## tmap\n\nPackage `tmap` is another package for plotting maps, with emphasis on production-ready maps.\n\n```{r eval=require(\"tmap\", quietly = TRUE)}\nlibrary(tmap)\nqtm(nc)\n```\n\n`tmap` also has interactive leaflet maps:\n```{r,eval=FALSE}\ntmap_mode(\"view\")\ntm_shape(nc) + tm_fill(\"BIR74\", palette = sf.colors(5))\n```\n\nReplotting the last map in non-interactive mode is as simple as:\n```{r,eval=FALSE}\nttm()\ntmap_last()\n```\n\nA draft version of the book _Elegant and informative maps\nwith tmap_ by Martijn Tennekes and Jakub Nowosad is found at\nhttps://r-tmap.github.io/\n"
  },
  {
    "path": "vignettes/sf6.Rmd",
    "content": "---\ntitle: \"6. Miscellaneous\"\nauthor: \"Edzer Pebesma\"\noutput:\n  html_document:\n    toc: true\n    toc_float:\n      collapsed: false\n      smooth_scroll: false\n    toc_depth: 2\nvignette: >\n  %\\VignetteIndexEntry{6. Miscellaneous}\n  %\\VignetteEngine{knitr::rmarkdown}\n  %\\VignetteEncoding{UTF-8}\n---\n\n```{r echo=FALSE, include=FALSE}\nknitr::opts_chunk$set(collapse = TRUE)\n```\nThis vignette describes a number of issues that did not come up in\nthe previous vignettes, and that may or may not be categorized as\n\"frequently asked questions\". Readers are encouraged to provide\nentries for this vignette (as for the others).\n\n# What is this EPSG code all about?\n\nEPSG stands for a maintained, well-understood registry of spatial\nreference systems, maintained by the International Association\nof Oil \\& Gas Producers (IOGP). `EPSG` stands for the authority,\ne.g. `EPSG:4326` stands for spatial reference system with ID 4326\nas it is maintained by the EPSG authority. The website for the EPSG\nregistry is found at the epsg.org domain. Using `4326` instead of\n`EPSG:4326` is allowed (`EPSG` is the default authority) but the\nlatter form, `EPSG:4326` is better (less ambiguous).\n\n# Why should we use `OGC:CRS84` instead of `EPSG:4326`?\n\nEPSG:4326 formally defines coordinate axes to be in the order\nlatitude-longitude, but practically all data sources and software\nenvironments use longitude-latitude axis order. OGC:CRS84 is\nequivalent to EPSG:4326 except that it defines coordinate axis\norder longitude-latitude, removing this ambiguity so to speak.\nSee also `st_axis_order()`\n\n# How does `sf` deal with secondary geometry columns?\n\n`sf` objects can have more than one geometry list-column,\nbut always only one geometry column is considered _active_,\nand returned by `st_geometry()`.  When there are multiple\ngeometry columns, the default `print` methods reports which\none is active:\n```{r}\nlibrary(sf)\ndemo(nc, ask = FALSE, echo = FALSE)\nnc$geom2 = st_centroid(st_geometry(nc))\nprint(nc, n = 2)\n```\n\nWe can switch the active geometry by using `st_geometry<-` or `st_set_geometry()`, as in \n```{r}\nplot(st_geometry(nc))\nst_geometry(nc) <- \"geom2\"\nplot(st_geometry(nc))\n```\n\n# Does `st_simplify` preserve topology?\n\n`st_simplify()` is a topology-preserving function, but does this on the\nlevel of individual feature geometries. That means, simply said, that\nafter applying it, a polygon will still be a polygon. However when\ntwo features have a longer shared boundary, applying `st_simplify`\nto the object does not guarantee that in the resulting object these\ntwo polygons still have the same boundary in common, since the\nsimplification is done independently, _for each feature geometry_.\n\n# Why do my dplyr verbs not work for `sf` objects?\n\nThey do! However, many developers like to write scripts that never\nload packages but address all functions by the `sf::` prefix, as in\n```{r,eval=FALSE}\ni = sf::st_intersects(sf1, sf2)\n```\n\nThis works up to the moment that a `dplyr` generic like `select` for an `sf` object\nis needed: should one call `dplyr::select` (won't know it should search\nin package `sf`) or `sf::select` (which doesn't exist)? Neither works.\nOne should in this case simply load `sf`, e.g. by\n```{r,eval=FALSE}\nlibrary(sf)\n```\n"
  },
  {
    "path": "vignettes/sf7.Rmd",
    "content": "---\ntitle: \"7. Spherical geometry in sf using s2geometry\"\nauthor: \"Edzer Pebesma and Dewey Dunnington\"\noutput:\n  html_document:\n    toc: true\n    toc_float:\n      collapsed: false\n      smooth_scroll: false\n    toc_depth: 2\nvignette: >\n  %\\VignetteIndexEntry{7. Spherical geometry in sf using s2geometry}\n  %\\VignetteEngine{knitr::rmarkdown}\n  %\\VignetteEncoding{UTF-8}\n---\n\n```{r echo=FALSE, include=FALSE}\nknitr::opts_chunk$set(collapse = TRUE)\n```\n\n# Introduction\n\nThis vignette describes what spherical geometry implies, and how\npackage `sf` uses the s2geometry library (https://s2geometry.io)\nfor geometrical measures, predicates and transformations.  \nAfter `sf` has been loaded, it will report whether `s2` is being\nused; it can be switched off (resorting to flat space geometry)\nby `sf_use_s2(FALSE)`.\n\n```{r}\nlibrary(sf)\n```\n\n```{r}\nlibrary(s2)\n```\n\nMost of the package's functions start with `s2_` in the same way\nthat most `sf` function names start with `st_`. Most `sf` functions\nautomatically use `s2` functions when working with ellipsoidal\ncoordinates; if this is not the case, e.g. for `st_voronoi()`,\na warning like\n\n```\nWarning message:\nIn st_voronoi.sfc(st_geometry(x), st_sfc(envelope), dTolerance,  :\n  st_voronoi does not correctly triangulate longitude/latitude data\n```\n\nis emitted.\n\n# Projected and geographic coordinates\n\nSpatial coordinates either refer to _projected_ (or Cartesian)\ncoordinates, meaning that they are associated to points on a flat\nspace, or to unprojected or _geographic_ coordinates, when they\nrefer to angles (latitude, longitude) pointing to locations on a\nsphere (or ellipsoid). The flat space is also referred to as $R^2$,\nthe sphere as $S^2$.\n\nPackage `sf` implements _simple features_, a standard for point,\nline, and polygon geometries where geometries are built from points\n(nodes) connected by straight lines (edges). The simple feature\nstandard does not say much about its suitability for dealing with\ngeographic coordinates, but the topological relational system it\nbuilds upon ([DE9-IM](https://en.wikipedia.org/wiki/DE-9IM)) refer\nto $R^2$, the two-dimensional flat space. \n\nYet, more and more data are routinely served or exchanged using\ngeographic coordinates. Using software that assumes an $R^2$, flat\nspace may work for some problems, and although `sf`\nhas some functions in place for spherical/ellipsoidal computations\n(from package `lwgeom`, for computing area,\nlength, distance, and for segmentizing), it has also happily warned \nthe user that it is doing $R^2$, flat computations with such coordinates with messages like\n```\nalthough coordinates are longitude/latitude, st_intersects assumes that they are planar\n```\nhinting to the responsibility of the user to take care of potential\nproblems. Doing this however leaves ambiguities, e.g. whether \n`LINESTRING(-179 0,179 0)`\n\n* passes through `POINT(0 0)`, or\n* passes through `POINT(180 0)`\n\nand whether it is\n\n* a straight line, cutting through the Earth's surface, or\n* a curved line following the Earth's surface\n\nStarting with `sf` version 1.0, if you provide a spatial object in a\ngeographical coordinate reference system, `sf` uses the new package `s2`\n(Dunnington, Pebesma, Rubak 2020) for spherical geometry, which\nhas functions for computing pretty much all measures, predicates\nand transformations _on the sphere_. This means:\n\n* no more hodge-podge of some functions working on $R^2$, with annoying messages, some on the ellipsoid\n* a considerable speed increase for some functions\n* no computations on the ellipsoid (which are considered more accurate, but are also slower)\n\nThe `s2` package is really a wrapper around the C++\n[s2geometry](https://s2geometry.io) library which was written by\nGoogle, and which is used in many of its products (e.g. Google\nMaps, Google Earth Engine, BigQuery GIS) and has been translated\nin several other programming languages.\n\nWith projected coordinates `sf` continues to work in $R^2$ as before.\n\n# Fundamental differences\n\nCompared to geometry on $R^2$, and DE9-IM, the `s2` package brings a\nfew fundamentally new concepts, which are discussed first.\n\n## Polygons on $S^2$ divide the sphere in two parts\n\nOn the sphere ($S^2$), any polygon defines two areas; when following the\nexterior ring, we need to define what is inside, and the definition\nis _the left side of the enclosing edges_. This also means that\nwe can flip a polygon (by inverting the edge order) to obtain the\nother part of the globe, and that in addition to an empty polygon\n(the empty set) we can have the full polygon (the entire globe).\n\nSimple feature geometries should obey a ring direction too: exterior\nrings should be counter clockwise, interior (hole) rings should\nbe clockwise, but in some sense this is obsolete as the difference\nbetween exterior ring and interior rings is defined by their position\n(exterior, followed by zero or more interior). `sf::read_sf()` has an\nargument `check_ring_dir` that checks, and corrects, ring directions\nand many (legacy) datasets have wrong ring directions. With wrong\nring directions, many things still work.\n\nFor $S^2$, ring direction is essential. For that reason, `st_as_s2`\nhas an argument `oriented = FALSE`, which will check and correct\nring directions, assuming that all exterior rings occupy an area\nsmaller than half the globe:\n```{r}\nnc = read_sf(system.file(\"gpkg/nc.gpkg\", package=\"sf\")) # wrong ring directions\ns2_area(st_as_s2(nc, oriented = FALSE)[1:3]) # corrects ring direction, correct area:\ns2_area(st_as_s2(nc, oriented = TRUE)[1:3]) # wrong direction: Earth's surface minus area\nnc = read_sf(system.file(\"gpkg/nc.gpkg\", package=\"sf\"), check_ring_dir = TRUE)\ns2_area(st_as_s2(nc, oriented = TRUE)[1:3]) # no second correction needed here:\n```\nThe default conversion from `sf` to `s2` uses `oriented = FALSE`, so that we\nget\n```{r}\nall(units::drop_units(st_area(nc)) == s2_area(st_as_s2(nc, oriented = FALSE)))\n```\n\n\nHere is an example where the oceans are computed as the difference\nfrom the full polygon representing the entire globe,\n```{r}\ng = st_as_sfc(\"POLYGON FULL\", crs = 'EPSG:4326')\ng\n```\n\nand the countries, and shown in an orthographic projection:\n```{r}\noptions(s2_oriented = TRUE) # don't change orientation from here on\nco = st_as_sf(s2_data_countries())\noc = st_difference(g, st_union(co)) # oceans\nb = st_buffer(st_as_sfc(\"POINT(-30 52)\", crs = 'EPSG:4326'), 9800000) # visible half\ni = st_intersection(b, oc) # visible ocean\nplot(st_transform(i, \"+proj=ortho +lat_0=52 +lon_0=-30\"), col = 'blue')\n```\n\n(Note that the printing of `POLYGON FULL` is not valid WKT according\nto the simple feature standard, which does not include this.)\n\nWe can now calculate the proportion of the Earth's surface covered\nby oceans:\n\n```{r}\nst_area(oc) / st_area(g)\n```\n\n\n## Semi-open polygon boundaries \n\nPolygons in `s2geometry` can be\n\n* CLOSED: they contain their boundaries, and a point on the boundary intersects with the polygon\n* OPEN: they do not contain their boundaries, points on the boundary do not intersect with the polygon\n* SEMI-OPEN: they contain part of their boundaries, but no boundary of non-overlapping polygons is contained by more than one polygon.\n\nIn principle the DE9-IM model deals with interior, boundary and\nexterior, and intersection predicates are sensitive to this (the\ndifference between _contains_ and _covers_ is all about boundaries).\nDE9-IM however cannot uniquely assign points to polygons when\npolygons form a polygon _coverage_ (no overlaps, but shared \nboundaries). This means that if we would count points by polygon,\nand some points fall _on_ shared polygon boundaries, we either miss\nthem (_contains_) or we count them double (_covers_, _intersects_);\nthis might lead to bias and require post-processing. Using SEMI-OPEN\nnon-overlapping polygons guarantees that every point is assigned\nto _maximally_ one polygon in an intersection. This corresponds\nto e.g. how this would be handled in a grid (raster) coverage,\nwhere every grid cell (typically) only contains its upper-left\ncorner and its upper and left sides.\n\n```{r}\na = st_as_sfc(\"POINT(0 0)\", crs = 'EPSG:4326')\nb = st_as_sfc(\"POLYGON((0 0,1 0,1 1,0 1,0 0))\", crs = 'EPSG:4326')\nst_intersects(a, b, model = \"open\")\nst_intersects(a, b, model = \"closed\")\nst_intersects(a, b, model = \"semi-open\") # a toss\nst_intersects(a, b) # default: closed\n```\n\n## Bounding cap, bounding rectangle\n\nComputing the minimum and maximum values over coordinate ranges,\nas `sf` does with `st_bbox()`, is of limited value for spherical\ncoordinates because due the spherical space, the _area covered_\nis not necessarily covered by the coordinate range. Two examples:\n\n* small regions covering the antimeridian (longitude +/- 180) end up with a huge longitude range, which doesn't make _clear_ the antimeridian is spanned\n* regions including a pole will end up with a latitude range not extending to +/- 90\n\nS2 has two alternatives: the bounding cap and the bounding rectangle:\n\n```{r}\nfiji = s2_data_countries(\"Fiji\")\naa = s2_data_countries(\"Antarctica\")\ns2_bounds_cap(fiji)\ns2_bounds_rect(c(fiji,aa))\n```\n\nThe cap reports a bounding cap (circle) as a mid point (lat, lng)\nand an angle around this point. The bounding rectangle reports the\n`_lo` and `_hi` bounds of `lat` and `lng` coordinates.  Note that\nfor Fiji, `lng_lo` being higher than `lng_hi` indicates that the\nregion covers (crosses) the antimeridian.\n\n# Switching between S2 and GEOS\n\nThe two-dimensional $R^2$ library that was formerly used by `sf` is\n[GEOS](https://libgeos.org), and `sf` can be instrumented to\nuse GEOS or `s2`. First we will ask if `s2` is being used by default:\n```{r}\nsf_use_s2()\n```\nthen we can switch it off (and use GEOS) by\n```{r}\nsf_use_s2(FALSE)\n```\nand switch it on (and use s2) by\n```{r}\nsf_use_s2(TRUE)\n```\n\n\n# Measures\n\nThis section compares the differences in results between the `s2`\nand `lwgeom` (`sf_use_s2(FALSE)`) packages for calculating area,\nlength and distance using geographic coordinates. Note that engaging\nthe `GEOS` engine would require reprojection of the vector layer\nto the planar coordinate system (e.g. `EPGS:3857`).\n\n## Area\n```{r eval=require(\"lwgeom\", quietly = TRUE)}\noptions(s2_oriented = FALSE) # correct orientation from here on\nlibrary(sf)\nlibrary(units)\nnc = read_sf(system.file(\"gpkg/nc.gpkg\", package=\"sf\"))\nsf_use_s2(TRUE)\na1 = st_area(nc)\nsf_use_s2(FALSE)\na2 = st_area(nc)\nplot(a1, a2)\nabline(0, 1)\nsummary((a1 - a2)/a1)\n```\n\n## Length\n```{r}\nnc_ls = st_cast(nc, \"MULTILINESTRING\")\nsf_use_s2(TRUE)\nl1 = st_length(nc_ls)\nsf_use_s2(FALSE)\nl2 = st_length(nc_ls)\nplot(l1 , l2)\nabline(0, 1)\nsummary((l1 - l2)/l1)\n```\n\n## Distances\n```{r}\nsf_use_s2(TRUE)\nd1 = st_distance(nc, nc[1:10,])\nsf_use_s2(FALSE)\nd2 = st_distance(nc, nc[1:10,])\nplot(as.vector(d1), as.vector(d2))\nabline(0, 1)\nsummary(as.vector(d1) - as.vector(d2))\n```\n\n# Predicates\n\nAll unary and binary predicates are available in `s2`, except for\n`st_relate()` with a pattern. In addition, when using the `s2` predicates,\ndepending on the `model`, intersections with neighbours are only reported\nwhen `model` is `closed` (the default):\n```{r}\nsf_use_s2(TRUE)\nst_intersects(nc[1:3,], nc[1:3,]) # self-intersections + neighbours\nsf_use_s2(TRUE)\nst_intersects(nc[1:3,], nc[1:3,], model = \"semi-open\") # only self-intersections\n```\n\n\n# Transformations\n\n`st_intersection()`, `st_union()`, `st_difference()`, and\n`st_sym_difference()` are available as `s2` equivalents. N-ary\nintersection and difference are not (yet) present; cascaded union\nis present; unioning by feature does not work with `s2`.\n\n## Buffers\n\nBuffers can be calculated for features with geographic coordinates as follows,\nusing an unprojected object representing the UK as an example:\n\n```{r, fig.show='hold', out.width=\"50%\"}\nuk = s2_data_countries(\"United Kingdom\")\nclass(uk)\nuk_sfc = st_as_sfc(uk) \nuk_buffer = st_buffer(uk_sfc, dist = 20000)\nuk_buffer2 = st_buffer(uk_sfc, dist = 20000, max_cells = 10000)\nuk_buffer3 = st_buffer(uk_sfc, dist = 20000, max_cells = 100)\nclass(uk_buffer)\nplot(uk_sfc)\nplot(uk_buffer)\nplot(uk_buffer2)\nplot(uk_buffer3)\nuk_sf = st_as_sf(uk) \n```\n\nThe plots above show that you can adjust the level of spatial precision in the \nresults of s2 buffer operations with the `max_cells` argument, set to 1000 by default.\nDeciding on an appropriate value is a balance between excessive detail increasing\ncomputational resources (represented by `uk_buffer2`, bottom left) and\nexcessive simplification (bottom right). Note that buffers created with s2 _always_\nfollow s2 cell boundaries, they are never smooth. Hence, choosing a large number\nfor `max_cells` leads to seemingly smooth but, zoomed in, very complex buffers.\n\nTo achieve a similar result, you could first transform the result and then use `sf::st_buffer()`. A simple benchmark shows the\ncomputational efficiency of the `s2` geometry engine in comparison\nwith transforming and then creating buffers:\n\n```{r}\n# the sf way\nsystem.time({\n  uk_projected = st_transform(uk_sfc, 27700)\n  uk_buffer_sf = st_buffer(uk_projected, dist = 20000)\n})\n# sf way with few than the 30 segments in the buffer\nsystem.time({\n  uk_projected = st_transform(uk_sfc, 27700)\n  uk_buffer_sf2 = st_buffer(uk_projected, dist = 20000, nQuadSegs = 4)\n})\n# s2 with default cell size\nsystem.time({\n  uk_buffer = s2_buffer_cells(uk, distance = 20000)\n})\n# s2 with 10000 cells\nsystem.time({\n  uk_buffer2 = s2_buffer_cells(uk, distance = 20000, max_cells = 10000)\n})\n# s2 with 100 cells\nsystem.time({\n  uk_buffer2 = s2_buffer_cells(uk, distance = 20000, max_cells = 100)\n})\n```\n\nThe result of the previous benchmarks emphasizes the point that there are\ntrade-offs between geographic resolution and computational resources,\nsomething that web developers working on geographic services\nsuch as Google Maps understand well.\nIn this case the default setting of 1000 cells, which runs slightly faster than\nthe default transform -> buffer workflow, is probably appropriate given the\nlow resolution of the input geometry representing the UK.\n\n## `st_buffer` or `st_is_within_distance`?\n\nAs discussed in the [`sf` issue tracker](https://github.com/r-spatial/sf/issues/1367),\ndeciding on workflows and selecting appropriate levels of level of geographic resolution can\nbe an iterative process.\n`st_buffer()` as powered by GEOS, for $R^2$ data, are smooth and (nearly) exact.\n`st_buffer()` as powered by $S^2$ is rougher, complex, non-smooth, and may need tuning.\nA common pattern where `st_buffer()` is used is this:\n\n* compute buffers around a set of features `x` (points, lines, polygons)\n* within each of these buffers, find all occurrences of some other spatial \nvariable `y` and aggregate them (e.g. count points, or average a raster \nvariable like precipitation or population density)\n* work with these aggregated values (discard the buffer)\n\nWhen this is the case, and you are working with geographic\ncoordinates, it may pay off to _not_ compute buffers, but instead\ndirectly work with `st_is_within_distance()` to select, for each\nfeature of `x`, all features of `y` that are within a certain\ndistance `d` from `x`. The $S^2$ version of this function uses spatial\nindexes, so is fast for large datasets.\n\n## References\n\n* Dewey Dunnington, Edzer Pebesma and Ege Rubak, 2020. s2:\nSpherical Geometry Operators Using the $S^2$ Geometry Library.\nhttps://r-spatial.github.io/s2/, https://github.com/r-spatial/s2\n\n"
  },
  {
    "path": "vignettes/sf_fig.drawio",
    "content": "<mxfile host=\"app.diagrams.net\" agent=\"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/132.0.0.0 Safari/537.36\" version=\"24.8.3\">\n  <diagram name=\"Page-1\" id=\"-hd35gYQx_tvxQIsEQCW\">\n    <mxGraphModel dx=\"2662\" dy=\"1211\" grid=\"1\" gridSize=\"10\" guides=\"1\" tooltips=\"1\" connect=\"1\" arrows=\"1\" fold=\"1\" page=\"1\" pageScale=\"1\" pageWidth=\"827\" pageHeight=\"1169\" math=\"0\" shadow=\"0\">\n      <root>\n        <mxCell id=\"0\" />\n        <mxCell id=\"1\" parent=\"0\" />\n        <mxCell id=\"zu04grs4943uOGONhxht-1\" value=\"\" style=\"shape=image;verticalLabelPosition=bottom;labelBackgroundColor=default;verticalAlign=top;aspect=fixed;imageAspect=0;image=data:image/png,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FaLbnhfrh7QGCUyOM3bDG246LSnR5Bei3boGrzkk45sYxzV1i8D/z979B7V93/m+fy7xd6hUR6oxDsa4GK+IR2yu7K7Ga9UXEkPqkLrEGdcZJ72k97C96+3UZ6fZu0mnt91z2jnTzJ7tzTTZu830ONPrvYn3NExjrl3GDnVNqCEpjFeMr1pb10HjoGugBkws5EhhpbJfR3v/kEACIxC2wdi8HjOeyRe++uqj7y+U9/v7eb/N1PW/toTSNbf2fy53zedfKAtxv1qgYwWAGSc0MpK8xgwL1pUWrCttFNqW0P/Bpj7/wLR74G35/LIw7obz6m6SiBP6/SDDo1FiGFhXFlD82RIKb3F3mtdGGBhKfQec6zvBveg23q/T36eBfMvs36fj0eS1kW/Dvmoe3+Vu43U15fu/YcFeVELp2iV87Bfgb6s5FmZ4JExkLE7MNDEMC1ZbAcXripJlTpeA2NU+BoY+JmKSvO43ZL/uzWiYUAys1vux36H/R4pd7SPQO0hoLHleFa5Zj2NTCfYle2Jlfm8lee3eru9Xy5gZHWF4KExobOJelbqultJuHRshcLGP4Y+S9xTrZ4pwbCpP95K7aSaRK6nv7PHkwwBWy/3Y1xYly7yKiIjInBY/UbTczJIoEhERERERERERERERuZOUshAREREREREREREREVmmlCgSERERERERERERERFZppQoEhERERERERERERERWaaUKBIREREREREREREREVmmlCgSERERERERERERERFZplbc6QHc89Z72LevDBPAWkKxUnMiIiIiIiIiIiIiIrJE/FH8D//273d6ECIiIiIiIiIiIiIiIrL4NL9FRERERERERERERERkmVKiSEREREREREREREREZJlSokhERERERERERERERGSZUqJIRERERERERERERERkmVKiSEREREREREREREREZJlSokhERERERERERERERGSZUqJIRERERERERERERERkmVKiSEREREREREREREREZJlSokhERERERERERERERGSZUqJIRERERERERERERERkmVKiSEREREREREREREREZJlSokhERERERERERERERGSZUqJIRERERERERERERERkmVKiSEREREREREREREREZJlSokhERERERERERERERGSZUqJIRERERERERERERERkmVKiSERERERERERERERE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V63M9a5EREREREREREQysDCJIsBYX8HRHxTjOd9MU/sVelKUMjOyHZSUOXE/WoG7JGfmmRRrXBx5qRhXcyNN7T4CqdbeycqhaPN2qndW4t4wi4Xbc8o58P0XcLY2Uv+Bj8Bgcp/jk0RZuZS5Kti7t5Ky2ZQ3WlvB0e9bqT95lpZrkXtLpNkcuKqf4vCuYmxXPRgkEkXmn+5OvzZQViFVz75I2cVm6n/vxXcjxb4tBvkbneyo3Em1K501QXJwHX6O59ec5fQHV+hLVXrOYiV/XSFFpeUULEqOIAfngRf48dZ2Gs6147nWT/SemRgG9vXl7PjyTqq3Fy5q53G+az8/3LiFlqbztFzqpC9FnUHbui3s2LWTmu3Tdb5nwOKg+hs78fy8kR4TGLrCydNeyr49PnFokL/tKX64aTttF96jzdsxdv3fw8C+rhTX9gqqHi2nIGsuG7tSWXHtqqDA2zxapm2ifjyertHPuN3poiyD4160zUXB75OvcesKnuv7KCqZxRMNK/acHArWF1PmdOHeVkr+kskNmpjD467VLJsSRSIiIiIiIiIiIrP0n2J/+j//d+Ff1iR8s5e+gTtEPwXDtgp7noOiNbNI5EwjOtBLz60Q0WEz0amZ56BgXS62+5iVMdf7jA504e/sJTiU2F/+mvWUbCrEPgcdrmakn76bIYJDMTCs2LJzKVjnwH5/hxUwCd/6mOAnEaJYsWVbsVut2FfnYCyl8k7DEfpufkzwdoxoHGzZq8hfV5goG7jkJD8Dg3eIDoNhTbZ19dJqqxnpp+9WiPBQ4pgahhVbTi4Fa+fiuhIRERERERERERGRxbZIiSIRERERERERERERERFZbEtpPoiIiIiIiIiIiIiIiIgsICWKREREREREREREREREViglikRERERERERERERERFYoJYpERERERERERERERERWKCWKREREREREREREREREViglikRERERERERERERERFYoJYpERERERERERERERERWKCWKREREREREREREREREViglikRERERERERERERERFYoJYpERERERERERERERERWKCWKREREREREREREREREViglikRERERERERERERERFYoJYpERERERERERERERERWKCWKREREREREREREREREViglikRERERERERERERERFYoJYpERERERERERERERERWKCWKREREREREREREREREViglikRERERERERERERERFYoJYpERERERERERERERERWKCWKREREREREREREREREViglikRERERERERERERERFYoJYpERERERERERERERERWKCWKREREREREREREREREViglikRERERERERERERERFaoBxe7AXMrguf1Y9RfTz7cuIcfPuPCtqhtks+C6M0OPJd8BG7003c7RtQ0AQPDeBCb1YrNnkP+F3Zy8BHHYjdVRERERERERERERGTWPmOJIojeDhEcTD7Ii2Euamtk2TP78Zyso+5i/4zXksEWJYpEREREREREREREZFmZ90SRecNLk3fmTvaULDmUPVpBWc5ct+qzJoLnzTpabkHJ7mc54DQWu0FTMgc78V68gu96L323I0SHAcOK/fN5FGwoxely4VpvXexmJpkE6mupvRga9zcDW14u+TlWbBYw78aIRk2isTufvaRkrIPTx5sJxB1Ufesp3KsXu0EiIiIiIiIiIiIiMtfmP1HU7aX+XEdmT7Y4MFzpJIqslDyyh5pNyS77h4pXRtm54W683i4Cw2CL3AWWYKJouB9P/SlOtnURjd/7z8FbvQT8V2g7d5Z8504OH9y5+AnCiJeGD8eSRLZNOznyzZ0485bg8Z0Pf+zAE+gibDFx3V3sxoiIiIiIiIiIiIjIfPiMlZ4zKHpkJ0WL3YyFdquLvqU8nWW4i/pjtTRcj439zcihYF0u9qwHMaMh+vpDRE0Ak6Cvkdd+GeHod/fjzF6sRoPZ6cc/nHyQVc6BZ/bgXOzk1QIKdvcSXuxGiIiIiIiIiIiIiMi8WthEUVY5B57dScmsJ2QY5K+ZzwZ9NkR7bhBMMUtnaYjhe/vEWJLIkoPzq09x8PFy8rPGb9aP99wp6s53EQXMW+2cfGcLPz5Yumjzo4L9g2Pl5DaUr6gkEZj09PQvdiNEREREREREREREZJ4tbKLoASsFpcWUWBb0VeeYSXQwRDB2F8PyIIY1B/tqa/rJDDNGOBLDjIORZcWek/m6PIHu3qW7Ps6gh4bRNX6slH39OZ6vzL13O6sDV82z2IZ/xivvJ7YP/psH39dLcWXdu/lCMIfHZkDZcnKxz+3eiQ6GCMfuYlqs2FfnYr/fpZniJtHbyX3yILacXPJzMkyzxT+m54+xmbdb6swY4cEQ4btgPGjFlr0Ke3a6x2Qe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;\" vertex=\"1\" parent=\"1\">\n          <mxGeometry x=\"20\" y=\"46\" width=\"1674\" height=\"539\" as=\"geometry\" />\n        </mxCell>\n        <mxCell id=\"zu04grs4943uOGONhxht-2\" value=\"\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=none;strokeColor=#00CC00;\" vertex=\"1\" parent=\"1\">\n          <mxGeometry x=\"-10\" y=\"400\" width=\"1660\" height=\"60\" as=\"geometry\" />\n        </mxCell>\n        <mxCell id=\"zu04grs4943uOGONhxht-3\" value=\"\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=none;strokeColor=#FF3333;\" vertex=\"1\" parent=\"1\">\n          <mxGeometry x=\"930\" y=\"345\" width=\"740\" height=\"245\" as=\"geometry\" />\n        </mxCell>\n        <mxCell id=\"zu04grs4943uOGONhxht-4\" value=\"\" style=\"rounded=0;whiteSpace=wrap;html=1;fillColor=none;strokeColor=#3333FF;\" vertex=\"1\" parent=\"1\">\n          <mxGeometry x=\"1210\" y=\"510\" width=\"440\" height=\"60\" as=\"geometry\" />\n        </mxCell>\n        <mxCell id=\"zu04grs4943uOGONhxht-5\" value=\"\" style=\"endArrow=classic;html=1;rounded=0;entryX=0.227;entryY=0.961;entryDx=0;entryDy=0;entryPerimeter=0;\" edge=\"1\" parent=\"1\" target=\"zu04grs4943uOGONhxht-4\">\n          <mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\">\n            <mxPoint x=\"1250\" y=\"630\" as=\"sourcePoint\" />\n            <mxPoint x=\"870\" y=\"590\" as=\"targetPoint\" />\n          </mxGeometry>\n        </mxCell>\n        <mxCell id=\"zu04grs4943uOGONhxht-6\" value=\"Simple feature geometry&lt;div&gt;list-colum (sfc)&lt;/div&gt;\" style=\"text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=26;fontColor=#CC0000;\" vertex=\"1\" parent=\"1\">\n          <mxGeometry x=\"790\" y=\"640\" width=\"350\" height=\"30\" as=\"geometry\" />\n        </mxCell>\n        <mxCell id=\"zu04grs4943uOGONhxht-7\" value=\"\" style=\"endArrow=classic;html=1;rounded=0;entryX=0.2;entryY=1.007;entryDx=0;entryDy=0;entryPerimeter=0;\" edge=\"1\" parent=\"1\" target=\"zu04grs4943uOGONhxht-3\">\n          <mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\">\n            <mxPoint x=\"1020\" y=\"620\" as=\"sourcePoint\" />\n            <mxPoint x=\"870\" y=\"590\" as=\"targetPoint\" />\n          </mxGeometry>\n        </mxCell>\n        <mxCell id=\"zu04grs4943uOGONhxht-8\" value=\"&lt;font color=&quot;#009900&quot;&gt;Simple feature&lt;/font&gt;\" style=\"text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=26;\" vertex=\"1\" parent=\"1\">\n          <mxGeometry x=\"540\" y=\"640\" width=\"230\" height=\"30\" as=\"geometry\" />\n        </mxCell>\n        <mxCell id=\"zu04grs4943uOGONhxht-9\" value=\"\" style=\"endArrow=classic;html=1;rounded=0;entryX=0.5;entryY=1;entryDx=0;entryDy=0;\" edge=\"1\" parent=\"1\" target=\"zu04grs4943uOGONhxht-2\">\n          <mxGeometry width=\"50\" height=\"50\" relative=\"1\" as=\"geometry\">\n            <mxPoint x=\"680\" y=\"630\" as=\"sourcePoint\" />\n            <mxPoint x=\"720\" y=\"600\" as=\"targetPoint\" />\n          </mxGeometry>\n        </mxCell>\n        <mxCell id=\"zu04grs4943uOGONhxht-10\" value=\"Simple feature geometry (sfg)\" style=\"text;html=1;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=26;fontColor=#0000CC;\" vertex=\"1\" parent=\"1\">\n          <mxGeometry x=\"1190\" y=\"650\" width=\"350\" height=\"30\" as=\"geometry\" />\n        </mxCell>\n      </root>\n    </mxGraphModel>\n  </diagram>\n</mxfile>\n"
  },
  {
    "path": "vignettes.awk",
    "content": "{\n\tif (NR == 4) {\n\t\tprint(\"output: rmarkdown::html_vignette\")\n\t} else if (NR > 4 && NR <= 10) {\n\t} else if (NR == 16) {\n\t\tprint(\"\\n**For a better version of the sf vignettes see** https://r-spatial.github.io/sf/articles/\\n\")\n\t} else if (NR == 17) {\n\t\tprint\n\t\tprint(\"knitr::opts_chunk$set(fig.height = 4.5)\")\n\t\tprint(\"knitr::opts_chunk$set(fig.width = 6)\")\n\t} else\n\t\tprint\n}\n"
  }
]