├── .Rbuildignore ├── .gitattributes ├── .github ├── .gitignore └── workflows │ ├── R-CMD-check.yaml │ └── pkgdown.yaml ├── .gitignore ├── CONDUCT.md ├── DESCRIPTION ├── NAMESPACE ├── NEWS.md ├── R ├── RcppExports.R ├── bearing.R ├── bounding_circle.R ├── clockwise.R ├── geod.R ├── geohash.R ├── init.R ├── perimeter.R ├── snap_to_grid.R ├── split.R ├── startpoint.R ├── subdivide.R ├── transform.R ├── twkb.R ├── valid.R ├── wkt.R └── wrap_x.R ├── README.md ├── _pkgdown.yml ├── cleanup ├── codecov.yml ├── configure ├── configure.ac ├── inst └── COPYRIGHTS ├── lwgeom.Rproj ├── man ├── bounding_circle.Rd ├── geod.Rd ├── lwgeom_extSoftVersion.Rd ├── lwgeom_make_valid.Rd ├── perimeter-deprecated.Rd ├── perimeter.Rd ├── st_as_sfc.TWKB.Rd ├── st_astext.Rd ├── st_force_polygon_cw.Rd ├── st_geod_azimuth.Rd ├── st_geohash.Rd ├── st_is_polygon_cw.Rd ├── st_linesubstring.Rd ├── st_snap_to_grid.Rd ├── st_split.Rd ├── st_startpoint.Rd ├── st_subdivide.Rd ├── st_transform_proj.Rd └── st_wrap_x.Rd ├── src ├── DIFFS ├── Makevars.in ├── Makevars.ucrt ├── Makevars.win ├── README ├── RcppExports.cpp ├── geodetic.cpp ├── geos.cpp ├── io.cpp ├── liblwgeom │ ├── DIFFS │ ├── bytebuffer.c │ ├── bytebuffer.h │ ├── effectivearea.c │ ├── effectivearea.h │ ├── gbox.c │ ├── gserialized.c │ ├── gserialized.h │ ├── gserialized1.c │ ├── gserialized1.h │ ├── gserialized2.c │ ├── gserialized2.h │ ├── liblwgeom.h │ ├── liblwgeom_internal.h │ ├── liblwgeom_topo.h │ ├── liblwgeom_topo_internal.h │ ├── lookup3.c │ ├── lwalgorithm.c │ ├── lwboundingcircle.c │ ├── lwchaikins.c │ ├── lwcircstring.c │ ├── lwcollection.c │ ├── lwcompound.c │ ├── lwcurvepoly.c │ ├── lwgeodetic.c │ ├── lwgeodetic.h │ ├── lwgeodetic_tree.c │ ├── lwgeodetic_tree.h │ ├── lwgeom.c │ ├── lwgeom_api.c │ ├── lwgeom_debug.c │ ├── lwgeom_geos.c │ ├── lwgeom_geos.h │ ├── lwgeom_geos_clean.c │ ├── lwgeom_geos_cluster.c │ ├── lwgeom_geos_node.c │ ├── lwgeom_geos_split.c │ ├── lwgeom_log.h │ ├── lwgeom_median.c │ ├── lwgeom_topo.c │ ├── lwgeom_transform.c │ ├── lwgeom_wrapx.c │ ├── lwhomogenize.c │ ├── lwin_encoded_polyline.c │ ├── lwin_twkb.c │ ├── lwin_wkb.c │ ├── lwin_wkt.c │ ├── lwin_wkt.h │ ├── lwin_wkt_lex.c │ ├── lwin_wkt_parse.c │ ├── lwin_wkt_parse.h │ ├── lwinline.h │ ├── lwiterator.c │ ├── lwkmeans.c │ ├── lwline.c │ ├── lwlinearreferencing.c │ ├── lwmcurve.c │ ├── lwmline.c │ ├── lwmpoint.c │ ├── lwmpoly.c │ ├── lwmsurface.c │ ├── lwmval.c │ ├── lwout_encoded_polyline.c │ ├── lwout_geojson.c │ ├── lwout_gml.c │ ├── lwout_kml.c │ ├── lwout_svg.c │ ├── lwout_twkb.c │ ├── lwout_twkb.h │ ├── lwout_wkb.c │ ├── lwout_wkt.c │ ├── lwout_x3d.c │ ├── lwout_x3d.h │ ├── lwpoint.c │ ├── lwpoly.c │ ├── lwprint.c │ ├── lwpsurface.c │ ├── lwrandom.c │ ├── lwrandom.h │ ├── lwspheroid.c │ ├── lwstroke.c │ ├── lwtin.c │ ├── lwtriangle.c │ ├── lwunionfind.c │ ├── lwunionfind.h │ ├── lwutil.c │ ├── measures.c │ ├── measures.h │ ├── measures3d.c │ ├── measures3d.h │ ├── ptarray.c │ ├── stringbuffer.c │ ├── stringbuffer.h │ ├── varint.c │ └── varint.h ├── lwgeom.cpp ├── lwgeom.h ├── postgis_config.h ├── postgis_config.h.in ├── postgis_config.win ├── postgis_svn_revision.h ├── proj.cpp └── sub.cpp ├── tests ├── azimuth.R ├── azimuth.Rout.save ├── dist.R ├── dist.Rout.save ├── geod.R ├── geod.Rout.save ├── perimeter.R ├── perimeter.Rout.save ├── testthat.R ├── testthat.Rout.save ├── testthat │ ├── test-as_text.R │ ├── test-clockwise.R │ └── test_lwgeom.R ├── twkb.R └── twkb.Rout.save ├── tic.R └── tools └── winlibs.R /.Rbuildignore: -------------------------------------------------------------------------------- 1 | README.md 2 | .travis.yml 3 | appveyor.yml 4 | codecov.yml 5 | ^docs$ 6 | tic.R 7 | ^.*\.Rproj$ 8 | ^\.Rproj\.user$ 9 | ^.github$ 10 | ^\.ccache$ 11 | ^\.github$ 12 | ^tic\.R$ 13 | ^_pkgdown\.yml$ 14 | ^pkgdown$ 15 | CONDUCT.md 16 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Do not convert line-endings on Windows 2 | * text eol=lf 3 | -------------------------------------------------------------------------------- /.github/.gitignore: -------------------------------------------------------------------------------- 1 | *.html 2 | -------------------------------------------------------------------------------- /.github/workflows/R-CMD-check.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | 9 | name: R-CMD-check 10 | 11 | jobs: 12 | R-CMD-check: 13 | runs-on: ${{ matrix.config.os }} 14 | 15 | name: ${{ matrix.config.os }} (${{ matrix.config.r }}) 16 | 17 | strategy: 18 | fail-fast: false 19 | matrix: 20 | config: 21 | - {os: macos-latest, r: 'release'} 22 | - {os: windows-latest, r: 'release'} 23 | - {os: ubuntu-latest, r: 'devel', http-user-agent: 'release'} 24 | - {os: ubuntu-latest, r: 'release'} 25 | - {os: ubuntu-latest, r: 'oldrel-1'} 26 | 27 | env: 28 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 29 | R_KEEP_PKG_SOURCE: yes 30 | 31 | steps: 32 | - uses: actions/checkout@v4 33 | 34 | - uses: r-lib/actions/setup-pandoc@v2 35 | 36 | - uses: r-lib/actions/setup-r@v2 37 | with: 38 | r-version: ${{ matrix.config.r }} 39 | http-user-agent: ${{ matrix.config.http-user-agent }} 40 | use-public-rspm: true 41 | 42 | - uses: r-lib/actions/setup-r-dependencies@v2 43 | with: 44 | extra-packages: any::rcmdcheck 45 | needs: check 46 | 47 | - name: Install system dependencies (MacOS) 48 | if: runner.os == 'macos' 49 | run: brew install geos proj 50 | 51 | - uses: r-lib/actions/check-r-package@v2 52 | with: 53 | upload-snapshots: true 54 | -------------------------------------------------------------------------------- /.github/workflows/pkgdown.yaml: -------------------------------------------------------------------------------- 1 | # Workflow derived from https://github.com/r-lib/actions/tree/v2/examples 2 | # Need help debugging build failures? Start at https://github.com/r-lib/actions#where-to-find-help 3 | on: 4 | push: 5 | branches: [main, master] 6 | pull_request: 7 | branches: [main, master] 8 | release: 9 | types: [published] 10 | workflow_dispatch: 11 | 12 | name: pkgdown 13 | 14 | jobs: 15 | pkgdown: 16 | runs-on: ubuntu-latest 17 | # Only restrict concurrency for non-PR jobs 18 | concurrency: 19 | group: pkgdown-${{ github.event_name != 'pull_request' || github.run_id }} 20 | env: 21 | GITHUB_PAT: ${{ secrets.GITHUB_TOKEN }} 22 | permissions: 23 | contents: write 24 | steps: 25 | - uses: actions/checkout@v4 26 | 27 | - uses: r-lib/actions/setup-pandoc@v2 28 | 29 | - uses: r-lib/actions/setup-r@v2 30 | with: 31 | use-public-rspm: true 32 | 33 | - uses: r-lib/actions/setup-r-dependencies@v2 34 | with: 35 | extra-packages: any::pkgdown, local::. 36 | needs: website 37 | 38 | - name: Build site 39 | run: pkgdown::build_site_github_pages(new_process = FALSE, install = FALSE) 40 | shell: Rscript {0} 41 | 42 | - name: Deploy to GitHub pages 🚀 43 | if: github.event_name != 'pull_request' 44 | uses: JamesIves/github-pages-deploy-action@v4.5.0 45 | with: 46 | clean: false 47 | branch: gh-pages 48 | folder: docs 49 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .Rproj.user 2 | .Rhistory 3 | .RData 4 | .Ruserdata 5 | **/*.o 6 | src/*.so 7 | src/*.dll 8 | docs/ 9 | docs 10 | -------------------------------------------------------------------------------- /CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Code of Conduct 2 | 3 | As contributors and maintainers of this project, we pledge to respect all people who 4 | contribute through reporting issues, posting feature requests, updating documentation, 5 | submitting pull requests or patches, and other activities. 6 | 7 | We are committed to making participation in this project a harassment-free experience for 8 | everyone, regardless of level of experience, gender, gender identity and expression, 9 | sexual orientation, disability, personal appearance, body size, race, ethnicity, age, or religion. 10 | 11 | Examples of unacceptable behavior by participants include the use of sexual language or 12 | imagery, derogatory comments or personal attacks, trolling, public or private harassment, 13 | insults, or other unprofessional conduct. 14 | 15 | Project maintainers have the right and responsibility to remove, edit, or reject comments, 16 | commits, code, wiki edits, issues, and other contributions that are not aligned to this 17 | Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed 18 | from the project team. 19 | 20 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by 21 | opening an issue or contacting one or more of the project maintainers. 22 | 23 | This Code of Conduct is adapted from the Contributor Covenant 24 | (http:contributor-covenant.org), version 1.0.0, available at 25 | http://contributor-covenant.org/version/1/0/0/ 26 | -------------------------------------------------------------------------------- /DESCRIPTION: -------------------------------------------------------------------------------- 1 | Package: lwgeom 2 | Version: 0.2-15 3 | Title: Bindings to Selected 'liblwgeom' Functions for Simple Features 4 | Description: Access to selected functions found in 'liblwgeom' , the light-weight geometry library used by 'PostGIS' . 5 | Authors@R: c(person("Edzer", "Pebesma", role = c("aut", "cre"), email = "edzer.pebesma@uni-muenster.de", comment = c(ORCID = "0000-0001-8049-7069")), 6 | person("Colin", "Rundel", role = "ctb"), 7 | person("Andy", "Teucher", role = "ctb"), 8 | person("liblwgeom developers", role = "cph")) 9 | Depends: 10 | R (>= 3.3.0) 11 | Imports: 12 | Rcpp, 13 | units, 14 | sf (>= 1.0-15) 15 | Suggests: 16 | covr, 17 | sp, 18 | geosphere, 19 | testthat 20 | LinkingTo: 21 | Rcpp, 22 | sf (>= 0.6-0) 23 | SystemRequirements: GEOS (>= 3.5.0), PROJ (>= 4.8.0), sqlite3 24 | License: GPL-2 25 | Copyright: file COPYRIGHTS 26 | Encoding: UTF-8 27 | URL: https://r-spatial.github.io/lwgeom/, https://github.com/r-spatial/lwgeom 28 | BugReports: https://github.com/r-spatial/lwgeom/issues 29 | Collate: 30 | init.R 31 | RcppExports.R 32 | geohash.R 33 | split.R 34 | subdivide.R 35 | valid.R 36 | transform.R 37 | bounding_circle.R 38 | bearing.R 39 | snap_to_grid.R 40 | startpoint.R 41 | twkb.R 42 | perimeter.R 43 | clockwise.R 44 | geod.R 45 | wkt.R 46 | wrap_x.R 47 | RoxygenNote: 7.3.2 48 | -------------------------------------------------------------------------------- /NAMESPACE: -------------------------------------------------------------------------------- 1 | # Generated by roxygen2: do not edit by hand 2 | 3 | S3method(st_as_sfc,TWKB) 4 | S3method(st_force_polygon_cw,sf) 5 | S3method(st_force_polygon_cw,sfc) 6 | S3method(st_force_polygon_cw,sfg) 7 | S3method(st_is_polygon_cw,sf) 8 | S3method(st_is_polygon_cw,sfc) 9 | S3method(st_is_polygon_cw,sfg) 10 | S3method(st_linesubstring,sf) 11 | S3method(st_linesubstring,sfc) 12 | S3method(st_linesubstring,sfg) 13 | S3method(st_minimum_bounding_circle,sf) 14 | S3method(st_minimum_bounding_circle,sfc) 15 | S3method(st_minimum_bounding_circle,sfg) 16 | S3method(st_snap_to_grid,sf) 17 | S3method(st_snap_to_grid,sfc) 18 | S3method(st_snap_to_grid,sfg) 19 | S3method(st_split,sf) 20 | S3method(st_split,sfc) 21 | S3method(st_split,sfg) 22 | S3method(st_subdivide,sf) 23 | S3method(st_subdivide,sfc) 24 | S3method(st_subdivide,sfg) 25 | S3method(st_transform_proj,sf) 26 | S3method(st_transform_proj,sfc) 27 | S3method(st_transform_proj,sfg) 28 | S3method(st_wrap_x,sf) 29 | S3method(st_wrap_x,sfc) 30 | S3method(st_wrap_x,sfg) 31 | export(lwgeom_extSoftVersion) 32 | export(lwgeom_make_valid) 33 | export(st_asewkt) 34 | export(st_astext) 35 | export(st_endpoint) 36 | export(st_force_polygon_cw) 37 | export(st_geod_area) 38 | export(st_geod_azimuth) 39 | export(st_geod_covered_by) 40 | export(st_geod_covers) 41 | export(st_geod_distance) 42 | export(st_geod_length) 43 | export(st_geod_segmentize) 44 | export(st_geohash) 45 | export(st_geom_from_geohash) 46 | export(st_is_polygon_cw) 47 | export(st_linesubstring) 48 | export(st_minimum_bounding_circle) 49 | export(st_perimeter) 50 | export(st_perimeter_2d) 51 | export(st_perimeter_lwgeom) 52 | export(st_snap_to_grid) 53 | export(st_split) 54 | export(st_startpoint) 55 | export(st_subdivide) 56 | export(st_transform_proj) 57 | export(st_wrap_x) 58 | import(sf) 59 | importFrom(Rcpp,evalCpp) 60 | importFrom(units,as_units) 61 | importFrom(units,set_units) 62 | importFrom(utils,tail) 63 | useDynLib(lwgeom) 64 | -------------------------------------------------------------------------------- /NEWS.md: -------------------------------------------------------------------------------- 1 | # version 0.2-15 2 | 3 | * add `st_geom_from_geohash()`; #37 4 | 5 | * fix default for argument `digits` in `st_astext()` 6 | 7 | # version 0.2-14 8 | 9 | * `st_perimeter()` is deprecated in favor of `st_perimeter_lwgeom()`, as `sf` takes over with `sf::st_perimeter()`. 10 | 11 | # version 0.2-13 12 | 13 | # version 0.2-11 14 | 15 | * replace `sprintf()` instances with `snprintf()` 16 | 17 | # version 0.2-10 18 | 19 | * fix -Wstrict-prototypes warnings 20 | 21 | # version 0.2-9 22 | 23 | * fix formatting issues for long long int 24 | 25 | # version 0.2-8 26 | 27 | * remove PROBLEM ... ERROR constructs from C code 28 | 29 | # version 0.2-5 30 | 31 | * GEOS requirement lowered to 3.5.0, which also seems to work; #59. 32 | 33 | # version 0.2-4 34 | 35 | * require sf >= 0.9-3, and use C API PROJ path setting (to work on CRAN windows binaries) 36 | 37 | * update to new GEOS (3.8.0) and PROJ (6.3.1) versions for CRAN windows binary builds 38 | 39 | * require GEOS 3.6.0 (required by PostGIS 3.0.0), and add check to configure 40 | 41 | # version 0.2-3 42 | 43 | * fix configure script to work with ubuntu/bionic and PROJ 4.9.3; #28 44 | 45 | * fix configure script to work with PROJ 5.x versions 46 | 47 | # version 0.2-2 48 | 49 | * adjust to sf >= 0.9-0 new crs representation 50 | 51 | * use `st_make_valid()` generic from package sf; https://github.com/r-spatial/sf/issues/1300 52 | 53 | # version 0.2-1 54 | 55 | * fix PROJ 5.x installation issue (has proj.h, but shouldn't use it) 56 | 57 | # version 0.2-0 58 | 59 | * export `lwgeom_make_valid()`, to gradually move `st_make_valid()` from `lwgeom` to `sf`; https://github.com/r-spatial/sf/issues/989 60 | 61 | * constrain argument `crs` in `st_transform_proj()` to take one or two character strings 62 | 63 | * update to POSTGIS 3.0.0 liblwgeom version 64 | 65 | * update to modern PROJ, use proj.h when available 66 | 67 | # version 0.1-5 68 | 69 | * check for user interrupts on `st_geod_distance()`, #29 by Dan Baston 70 | 71 | * add `st_astext()` for fast WKT writing, #25 by Etienne Racine 72 | 73 | * add `st_is_polygon_cw()`, #21 by Andy Teucher @ateucher; add Andy Teucher to contributors 74 | 75 | * add `st_perimeter()` and `st_perimeter_2d()` functions to compute the length measurement of the boundary of a surface. 76 | 77 | * allow `st_transform_proj()` to take two proj4 strings as crs, as `c(input_p4s, output_p4s)`, ignoring the CRS of x 78 | 79 | # version 0.1-4 80 | 81 | * tries to fix the CRAN error for r-release-osx (datum files missing in sf; removed test) 82 | 83 | # version 0.1-3 84 | 85 | * add `st_geod_covered_by()` binary geometry predicate 86 | 87 | # version 0.1-2 88 | 89 | * try to fix OSX compile on CRAN, tuning configure.ac 90 | 91 | # version 0.1-1 92 | 93 | * add `st_length()` 94 | 95 | * attempt to fix Solaris and OSX 96 | 97 | * report proj.4 and GEOS versions on startup, and on `lwgeom_extSoftwareVersions`; #10 98 | 99 | * add minimum bounding circle, by @rundel; #7 100 | 101 | * add `st_subdivide()`, see https://github.com/r-spatial/sf/issues/597 102 | 103 | # version 0.1-0 104 | 105 | * first CRAN submission 106 | -------------------------------------------------------------------------------- /R/RcppExports.R: -------------------------------------------------------------------------------- 1 | # Generated by using Rcpp::compileAttributes() -> do not edit by hand 2 | # Generator token: 10BE3573-1514-4C36-9D1C-5A225CD40393 3 | 4 | CPL_geodetic_area <- function(sfc, semi_major, inv_flattening) { 5 | .Call('_lwgeom_CPL_geodetic_area', PACKAGE = 'lwgeom', sfc, semi_major, inv_flattening) 6 | } 7 | 8 | CPL_geodetic_length <- function(sfc, semi_major, inv_flattening) { 9 | .Call('_lwgeom_CPL_geodetic_length', PACKAGE = 'lwgeom', sfc, semi_major, inv_flattening) 10 | } 11 | 12 | CPL_geodetic_azimuth <- function(sfc, semi_major, inv_flattening) { 13 | .Call('_lwgeom_CPL_geodetic_azimuth', PACKAGE = 'lwgeom', sfc, semi_major, inv_flattening) 14 | } 15 | 16 | CPL_geodetic_segmentize <- function(sfc, max_seg_length) { 17 | .Call('_lwgeom_CPL_geodetic_segmentize', PACKAGE = 'lwgeom', sfc, max_seg_length) 18 | } 19 | 20 | CPL_geodetic_covers <- function(sfc1, sfc2) { 21 | .Call('_lwgeom_CPL_geodetic_covers', PACKAGE = 'lwgeom', sfc1, sfc2) 22 | } 23 | 24 | CPL_geodetic_distance <- function(sfc1, sfc2, semi_major, inv_flattening, tolerance, sparse, semi_minor = -1.0) { 25 | .Call('_lwgeom_CPL_geodetic_distance', PACKAGE = 'lwgeom', sfc1, sfc2, semi_major, inv_flattening, tolerance, sparse, semi_minor) 26 | } 27 | 28 | CPL_geos_version <- function(b = FALSE) { 29 | .Call('_lwgeom_CPL_geos_version', PACKAGE = 'lwgeom', b) 30 | } 31 | 32 | CPL_init_lwgeom <- function(l) { 33 | .Call('_lwgeom_CPL_init_lwgeom', PACKAGE = 'lwgeom', l) 34 | } 35 | 36 | CPL_lwgeom_version <- function(b = FALSE) { 37 | .Call('_lwgeom_CPL_lwgeom_version', PACKAGE = 'lwgeom', b) 38 | } 39 | 40 | CPL_sfc_from_twkb <- function(twkb) { 41 | .Call('_lwgeom_CPL_sfc_from_twkb', PACKAGE = 'lwgeom', twkb) 42 | } 43 | 44 | CPL_make_valid <- function(sfc) { 45 | .Call('_lwgeom_CPL_make_valid', PACKAGE = 'lwgeom', sfc) 46 | } 47 | 48 | CPL_split <- function(sfc, blade) { 49 | .Call('_lwgeom_CPL_split', PACKAGE = 'lwgeom', sfc, blade) 50 | } 51 | 52 | CPL_wrap_x <- function(sfc, wrap, move) { 53 | .Call('_lwgeom_CPL_wrap_x', PACKAGE = 'lwgeom', sfc, wrap, move) 54 | } 55 | 56 | CPL_geohash <- function(sfc, prec) { 57 | .Call('_lwgeom_CPL_geohash', PACKAGE = 'lwgeom', sfc, prec) 58 | } 59 | 60 | CPL_bbox_from_geohash <- function(h, prec) { 61 | .Call('_lwgeom_CPL_bbox_from_geohash', PACKAGE = 'lwgeom', h, prec) 62 | } 63 | 64 | CPL_lwgeom_transform <- function(sfc, p4s) { 65 | .Call('_lwgeom_CPL_lwgeom_transform', PACKAGE = 'lwgeom', sfc, p4s) 66 | } 67 | 68 | CPL_minimum_bounding_circle <- function(sfc) { 69 | .Call('_lwgeom_CPL_minimum_bounding_circle', PACKAGE = 'lwgeom', sfc) 70 | } 71 | 72 | CPL_subdivide <- function(sfc, max_vertices = 256L) { 73 | .Call('_lwgeom_CPL_subdivide', PACKAGE = 'lwgeom', sfc, max_vertices) 74 | } 75 | 76 | CPL_snap_to_grid <- function(sfc, origin, size) { 77 | .Call('_lwgeom_CPL_snap_to_grid', PACKAGE = 'lwgeom', sfc, origin, size) 78 | } 79 | 80 | CPL_perimeter <- function(sfc, do2d = FALSE) { 81 | .Call('_lwgeom_CPL_perimeter', PACKAGE = 'lwgeom', sfc, do2d) 82 | } 83 | 84 | CPL_is_polygon_cw <- function(sfc) { 85 | .Call('_lwgeom_CPL_is_polygon_cw', PACKAGE = 'lwgeom', sfc) 86 | } 87 | 88 | CPL_force_polygon_cw <- function(sfc) { 89 | .Call('_lwgeom_CPL_force_polygon_cw', PACKAGE = 'lwgeom', sfc) 90 | } 91 | 92 | CPL_startpoint <- function(sfc) { 93 | .Call('_lwgeom_CPL_startpoint', PACKAGE = 'lwgeom', sfc) 94 | } 95 | 96 | CPL_endpoint <- function(sfc) { 97 | .Call('_lwgeom_CPL_endpoint', PACKAGE = 'lwgeom', sfc) 98 | } 99 | 100 | CPL_sfc_to_wkt <- function(sfc, precision) { 101 | .Call('_lwgeom_CPL_sfc_to_wkt', PACKAGE = 'lwgeom', sfc, precision) 102 | } 103 | 104 | CPL_proj_version <- function(b = FALSE) { 105 | .Call('_lwgeom_CPL_proj_version', PACKAGE = 'lwgeom', b) 106 | } 107 | 108 | CPL_use_proj4_init_rules <- function(v) { 109 | .Call('_lwgeom_CPL_use_proj4_init_rules', PACKAGE = 'lwgeom', v) 110 | } 111 | 112 | CPL_set_data_dir <- function(data_dir) { 113 | .Call('_lwgeom_CPL_set_data_dir', PACKAGE = 'lwgeom', data_dir) 114 | } 115 | 116 | CPL_linesubstring <- function(sfc, from, to, tolerance = 0.0) { 117 | .Call('_lwgeom_CPL_linesubstring', PACKAGE = 'lwgeom', sfc, from, to, tolerance) 118 | } 119 | 120 | -------------------------------------------------------------------------------- /R/bearing.R: -------------------------------------------------------------------------------- 1 | #' compute azimuth between sequence of points 2 | #' 3 | #' compute azimuth between sequence of points 4 | #' @param x object of class \code{sf}, \code{sfc} or \code{sfg} 5 | #' @export 6 | #' @examples 7 | #' library(sf) 8 | #' p = st_sfc(st_point(c(7,52)), st_point(c(8,53)), crs = 4326) 9 | #' st_geod_azimuth(p) 10 | st_geod_azimuth = function(x) { 11 | stopifnot(st_is_longlat(x)) 12 | stopifnot(all(st_is(x, "POINT"))) 13 | p = st_crs(st_geometry(x), parameters = TRUE) 14 | ret = CPL_geodetic_azimuth(st_geometry(x), p$SemiMajor, p$InvFlattening) 15 | units(ret) = as_units("rad") 16 | ret 17 | } 18 | -------------------------------------------------------------------------------- /R/bounding_circle.R: -------------------------------------------------------------------------------- 1 | #' Generate the minimum bounding circle 2 | #' @name bounding_circle 3 | #' @param x object of class \code{sfg}, \code{sfg} or \code{sf} 4 | #' @param nQuadSegs number of segments per quadrant (passed to \code{st_buffer}) 5 | #' @return Object of the same class as \code{x} 6 | #' @details \code{st_minimum_bounding_circle} uses the \code{lwgeom_calculate_mbc} method also used by the PostGIS command \code{ST_MinimumBoundingCircle}. 7 | #' @examples 8 | #' library(sf) 9 | #' 10 | #' x = st_multipoint(matrix(c(0,1,0,1),2,2)) 11 | #' y = st_multipoint(matrix(c(0,0,1,0,1,1),3,2)) 12 | #' 13 | #' mbcx = st_minimum_bounding_circle(x) 14 | #' mbcy = st_minimum_bounding_circle(y) 15 | #' 16 | #' if (.Platform$OS.type != "windows") { 17 | #' plot(mbcx, axes=TRUE); plot(x, add=TRUE) 18 | #' plot(mbcy, axes=TRUE); plot(y, add=TRUE) 19 | #' } 20 | #' 21 | #' nc = st_read(system.file("gpkg/nc.gpkg", package="sf")) 22 | #' state = st_union(st_geometry(nc)) 23 | #' 24 | #' if (.Platform$OS.type != "windows") { 25 | #' plot(st_minimum_bounding_circle(state), asp=1) 26 | #' plot(state, add=TRUE) 27 | #' } 28 | #' 29 | #' @export 30 | st_minimum_bounding_circle = function(x, nQuadSegs = 30) UseMethod("st_minimum_bounding_circle", x) 31 | 32 | generate_circles = function(geom, nQuadSegs = 30) { 33 | stopifnot(inherits(geom,"sfc")) 34 | 35 | circles = CPL_minimum_bounding_circle(geom) 36 | if (any(is.nan(unlist(circles)))) 37 | stop("NaN values returned by lwgeom's lwgeom_calculate_mbc.") #nocov 38 | 39 | mapply( 40 | function(xy, r, nQuadSegs) { 41 | st_buffer(st_point(xy), r, nQuadSegs) 42 | }, 43 | circles[["center"]], circles[["radius"]], 44 | MoreArgs = list(nQuadSegs = nQuadSegs), 45 | SIMPLIFY = FALSE 46 | ) 47 | } 48 | 49 | #' @export 50 | st_minimum_bounding_circle.sfg = function(x, nQuadSegs = 30) { 51 | st_minimum_bounding_circle(st_geometry(x), nQuadSegs)[[1]] 52 | } 53 | 54 | #' @export 55 | st_minimum_bounding_circle.sfc = function(x, nQuadSegs = 30) { 56 | st_sfc(generate_circles(x, nQuadSegs), crs = st_crs(x)) 57 | } 58 | 59 | #' @export 60 | st_minimum_bounding_circle.sf = function(x, nQuadSegs = 30) { 61 | st_set_geometry(x, st_minimum_bounding_circle(st_geometry(x), nQuadSegs)) 62 | } 63 | 64 | -------------------------------------------------------------------------------- /R/clockwise.R: -------------------------------------------------------------------------------- 1 | #' Force a POLYGON or MULTIPOLYGON to be clockwise 2 | #' 3 | #' Check if a POLYGON or MULTIPOLYGON is clockwise, and if not make it so. 4 | #' According to the 'Right-hand-rule', outer rings should be clockwise, and 5 | #' inner holes should be counter-clockwise 6 | #' 7 | #' 8 | #' @name st_force_polygon_cw 9 | #' @param x object with polygon geometries 10 | #' @return object of the same class as \code{x} 11 | #' @export 12 | #' 13 | #' @examples 14 | #' library(sf) 15 | #' polys <- st_sf(cw = c(FALSE, TRUE), 16 | #' st_as_sfc(c('POLYGON ((0 0, 1 0, 1 1, 0 0))', 17 | #' 'POLYGON ((1 1, 2 2, 2 1, 1 1))'))) 18 | #' 19 | #' st_force_polygon_cw(polys) 20 | #' st_force_polygon_cw(st_geometry(polys)) 21 | #' st_force_polygon_cw(st_geometry(polys)[[1]]) 22 | st_force_polygon_cw = function(x) UseMethod("st_force_polygon_cw") 23 | 24 | #' @export 25 | st_force_polygon_cw.sfg = function(x) { 26 | st_force_polygon_cw(st_geometry(x))[[1]] 27 | } 28 | 29 | #' @export 30 | st_force_polygon_cw.sfc = function(x) { 31 | st_sfc(CPL_force_polygon_cw(x), crs = st_crs(x)) 32 | } 33 | 34 | #' @export 35 | st_force_polygon_cw.sf = function(x) { 36 | st_set_geometry(x, st_force_polygon_cw(st_geometry(x))) 37 | } 38 | 39 | #' Check if a POLYGON or MULTIPOLYGON is clockwise 40 | #' 41 | #' Check if a POLYGON or MULTIPOLYGON is clockwise. According to the 42 | #' 'Right-hand-rule', outer rings should be clockwise, and inner holes 43 | #' should be counter-clockwise 44 | #' 45 | #' @name st_is_polygon_cw 46 | #' @param x object with polygon geometries 47 | #' @return logical with length the same number of features in `x` 48 | #' @export 49 | #' 50 | #' @examples 51 | #' library(sf) 52 | #' polys <- st_sf(cw = c(FALSE, TRUE), 53 | #' st_as_sfc(c('POLYGON ((0 0, 1 0, 1 1, 0 0))', 54 | #' 'POLYGON ((1 1, 2 2, 2 1, 1 1))'))) 55 | #' 56 | #' st_is_polygon_cw(polys) 57 | #' st_is_polygon_cw(st_geometry(polys)) 58 | #' st_is_polygon_cw(st_geometry(polys)[[1]]) 59 | st_is_polygon_cw = function(x) UseMethod("st_is_polygon_cw") 60 | 61 | #' @export 62 | st_is_polygon_cw.sfg = function(x) { 63 | st_is_polygon_cw(st_geometry(x))[[1]] 64 | } 65 | 66 | #' @export 67 | st_is_polygon_cw.sfc = function(x) { 68 | CPL_is_polygon_cw(x) 69 | } 70 | 71 | #' @export 72 | st_is_polygon_cw.sf = function(x) { 73 | st_is_polygon_cw(st_geometry(x)) 74 | } 75 | -------------------------------------------------------------------------------- /R/geod.R: -------------------------------------------------------------------------------- 1 | #' liblwgeom geodetic functions 2 | #' 3 | #' liblwgeom geodetic functions for length, area, segmentizing, covers 4 | #' @name geod 5 | #' @param x object of class \code{sf}, \code{sfc} or \code{sfg} 6 | #' @export 7 | #' @details \code{st_area} will give an error message when the area spans the equator and \code{lwgeom} is linked to a proj.4 version older than 4.9.0 (see \link{lwgeom_extSoftVersion}) 8 | #' @examples 9 | #' library(sf) 10 | #' nc = st_read(system.file("gpkg/nc.gpkg", package="sf")) 11 | #' st_geod_area(nc[1:3,]) 12 | #' # st_area(nc[1:3,]) 13 | st_geod_area = function(x) { 14 | stopifnot(st_is_longlat(x)) 15 | p = st_crs(st_geometry(x), parameters = TRUE) 16 | ret = CPL_geodetic_area(st_geometry(x), p$SemiMajor, p$InvFlattening) 17 | units(ret) = units(p$SemiMajor^2) 18 | ret 19 | } 20 | 21 | #' @name geod 22 | #' @export 23 | #' @examples 24 | #' l = st_sfc(st_linestring(rbind(c(7,52), c(8,53))), crs = 4326) 25 | #' st_geod_length(l) 26 | st_geod_length = function(x) { 27 | stopifnot(st_is_longlat(x)) 28 | p = st_crs(st_geometry(x), parameters = TRUE) 29 | ret = CPL_geodetic_length(st_geometry(x), p$SemiMajor, p$InvFlattening) 30 | units(ret) = units(p$SemiMajor) 31 | ret 32 | } 33 | 34 | #' @name geod 35 | #' @param max_seg_length segment length in degree, radians, or as a length unit (e.g., m) 36 | #' @export 37 | #' @examples 38 | #' library(units) 39 | #' pol = st_polygon(list(rbind(c(0,0), c(0,60), c(60,60), c(0,0)))) 40 | #' x = st_sfc(pol, crs = 4326) 41 | #' seg = st_geod_segmentize(x[1], set_units(10, km)) 42 | #' plot(seg, graticule = TRUE, axes = TRUE) 43 | #' @details 44 | #' longitude coordinates returned are rescaled to [-180,180) 45 | st_geod_segmentize = function(x, max_seg_length) { 46 | stopifnot(st_is_longlat(x)) 47 | p = st_crs(st_geometry(x), parameters = TRUE) 48 | if (inherits(max_seg_length, "units")) { 49 | tr = try(units(max_seg_length) <- as_units("rad"), silent = TRUE) 50 | if (inherits(tr, "try-error")) { 51 | units(max_seg_length) = units(p$SemiMajor) # -> m 52 | max_seg_length = max_seg_length / p$SemiMajor # m -> rad 53 | } 54 | } else 55 | stop("st_geod_segmentize needs a max_seg_length with units rad, degree, or a length unit") 56 | ret = st_sfc(CPL_geodetic_segmentize(st_geometry(x), max_seg_length)) 57 | st_set_crs((ret + c(180,90)) %% 360 - c(180, 90), st_crs(x)) # rescale lon to [-180,180) 58 | } 59 | 60 | #' @name geod 61 | #' @param y object of class \code{sf}, \code{sfc} or \code{sfg} 62 | #' @param sparse logical; if \code{TRUE}, return a sparse matrix (object of class \code{sgbp}), otherwise, return a dense logical matrix. 63 | #' @export 64 | #' @examples 65 | #' pole = st_polygon(list(rbind(c(0,80), c(120,80), c(240,80), c(0,80)))) 66 | #' pt = st_point(c(0,90)) 67 | #' x = st_sfc(pole, pt, crs = 4326) 68 | #' st_geod_covers(x[c(1,1,1)], x[c(2,2,2,2)]) 69 | st_geod_covers = function(x, y, sparse = TRUE) { 70 | stopifnot(st_is_longlat(x)) 71 | stopifnot(st_is_longlat(y)) 72 | if (!all(st_dimension(x) == 2)) 73 | stop("argument x must contain only polygons") 74 | if (!all(st_dimension(y) == 0)) 75 | stop("argument y must contain only points") 76 | if (is.null(id <- row.names(x))) 77 | id = as.character(seq_along(st_geometry(x))) 78 | ret = structure(CPL_geodetic_covers(st_geometry(x), st_geometry(y)), 79 | predicate = "covers", region.id = id, ncol = length(st_geometry(y)), class = "sgbp") 80 | if (sparse) 81 | ret 82 | else 83 | as.matrix(ret) 84 | } 85 | 86 | #' @name geod 87 | #' @export 88 | st_geod_covered_by = function(x, y, sparse = TRUE) { 89 | ret = structure(t(st_geod_covers(y, x)), predicate = "covered_by") 90 | if (sparse) 91 | ret 92 | else 93 | as.matrix(ret) 94 | } 95 | 96 | #' @name geod 97 | #' @export 98 | #' @param tolerance double or length \code{units} value: if positive, the first distance less than \code{tolerance} is returned, rather than the true distance 99 | #' @note this function should is used by \link[sf:geos_measures]{st_distance}, do not use it directly 100 | #' @examples 101 | #' pole = st_polygon(list(rbind(c(0,80), c(120,80), c(240,80), c(0,80)))) 102 | #' pt = st_point(c(30,70)) 103 | #' x = st_sfc(pole, pt, crs = 4326) 104 | #' st_geod_distance(x, x) 105 | st_geod_distance = function(x, y, tolerance = 0.0, sparse = FALSE) { 106 | stopifnot(st_is_longlat(x)) 107 | stopifnot(st_crs(x) == st_crs(y)) 108 | p = st_crs(st_geometry(x), parameters = TRUE) 109 | SemiMinor = if (is.null(p$SemiMinor)) -1.0 else p$SemiMinor 110 | units(tolerance) = as_units("m") 111 | ret = CPL_geodetic_distance(st_geometry(x), st_geometry(y), p$SemiMajor, p$InvFlattening, 112 | tolerance, sparse, SemiMinor)[[1]] 113 | if (! sparse) { 114 | ret[ret < 0] = NA # invalid/incalculable 115 | units(ret) = units(p$SemiMajor) 116 | ret 117 | } else { 118 | if (is.null(id <- row.names(x))) 119 | id = as.character(seq_along(st_geometry(x))) 120 | structure(ret, predicate = "st_is_within_distance", 121 | region.id = id, ncol = length(st_geometry(y)), class = "sgbp") 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /R/geohash.R: -------------------------------------------------------------------------------- 1 | #' compute geohash from (average) coordinates 2 | #' 3 | #' @param x object of class \code{sf}, \code{sfc} or \code{sfg} 4 | #' @param precision integer; precision (length) of geohash returned. From the liblwgeom source: ``where the precision is non-positive, a precision based on the bounds of the feature. Big features have loose precision. Small features have tight precision.'' 5 | #' @export 6 | #' @details see \url{https://en.wikipedia.org/wiki/Geohash}. 7 | #' @return `st_geohash` returns a character vector with geohashes; empty or full geometries result in `NA` 8 | #' 9 | #' `st_geom_from_geohash` returns a (bounding box) polygon for each geohash if `raw` is `FALSE`, if `raw` is `TRUE` a matrix is returned with bounding box coordinates on each row. 10 | #' @examples 11 | #' library(sf) 12 | #' lwgeom::st_geohash(st_sfc(st_point(c(1.5,3.5)), st_point(c(0,90))), 2) 13 | #' lwgeom::st_geohash(st_sfc(st_point(c(1.5,3.5)), st_point(c(0,90))), 10) 14 | st_geohash = function(x, precision = 0) { 15 | x = st_geometry(x) 16 | ret = vector("character", length(x)) 17 | is_na = st_is_empty(x) | st_is_full(x) 18 | ret[is_na] = NA_character_ 19 | ret[!is_na] = CPL_geohash(x[!is_na], precision) 20 | ret 21 | } 22 | 23 | #' @export 24 | #' @name st_geohash 25 | #' @param hash character vector with geohashes 26 | #' @param raw logical; if `TRUE`, return a matrix with bounding box coordinates on each row 27 | #' @param crs object of class `crs` 28 | #' @examples 29 | #' st_geom_from_geohash(c('9qqj7nmxncgyy4d0dbxqz0', 'up'), raw = TRUE) 30 | #' o = options(digits = 20) # for printing purposes 31 | #' st_geom_from_geohash(c('9qqj7nmxncgyy4d0dbxqz0', 'u1hzz631zyd63zwsd7zt')) 32 | #' st_geom_from_geohash('9qqj7nmxncgyy4d0dbxqz0', 4) 33 | #' st_geom_from_geohash('9qqj7nmxncgyy4d0dbxqz0', 10) 34 | #' options(o) 35 | st_geom_from_geohash = function(hash, precision = -1, crs = st_crs('OGC:CRS84'), raw = FALSE) { 36 | stopifnot(is.character(hash), is.numeric(precision), length(precision) == 1) 37 | m = CPL_bbox_from_geohash(hash, as.integer(precision)) 38 | bb = matrix(m, nrow = 4) 39 | rownames(bb) = c("xmin", "ymin", "xmax", "ymax") 40 | if (raw) 41 | t(bb) 42 | else { 43 | bb = apply(bb, 2, sf::st_bbox, simplify = FALSE) 44 | sf::st_set_crs(do.call(c, lapply(bb, sf::st_as_sfc)), crs) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /R/init.R: -------------------------------------------------------------------------------- 1 | #' @importFrom Rcpp evalCpp 2 | #' @import sf 3 | #' @importFrom utils tail 4 | #' @importFrom units set_units as_units 5 | #' @useDynLib lwgeom 6 | NULL 7 | 8 | .onLoad = function(libname, pkgname) { 9 | # SET PROJ.db path: 10 | if (file.exists(system.file("proj/nad.lst", package = "sf")[1])) { # we are on Windows: 11 | prj = system.file("proj", package = "sf")[1] 12 | CPL_set_data_dir(prj) # if existing, uses C API to set path 13 | CPL_use_proj4_init_rules(1L) 14 | } 15 | } 16 | 17 | .onAttach = function(libname, pkgname) { 18 | esv = lwgeom_extSoftVersion() 19 | m = paste0("Linking to liblwgeom ", esv["lwgeom"], 20 | ", GEOS ", esv["GEOS"], 21 | ", PROJ ", esv["proj.4"]) 22 | CPL_init_lwgeom(NA_character_) 23 | packageStartupMessage(m) 24 | sf = sf_extSoftVersion() 25 | if (sf["GEOS"] != esv["GEOS"]) 26 | warning(paste("GEOS versions differ: lwgeom has", esv["GEOS"], "sf has", sf["GEOS"])) 27 | if (sf["proj.4"] != esv["proj.4"]) 28 | warning(paste("PROJ versions differ: lwgeom has", esv["proj.4"], "sf has", sf["proj.4"])) 29 | 30 | 31 | } 32 | 33 | #' Provide the external dependencies versions of the libraries linked to sf 34 | #' 35 | #' Provide the external dependencies versions of the libraries linked to sf 36 | #' @export 37 | lwgeom_extSoftVersion = function() { 38 | structure(c(CPL_lwgeom_version(), CPL_geos_version(), CPL_proj_version()), 39 | names = c("lwgeom", "GEOS", "proj.4")) 40 | } 41 | -------------------------------------------------------------------------------- /R/perimeter.R: -------------------------------------------------------------------------------- 1 | #' Compute perimeter from polygons or other geometries 2 | #' 3 | #' @name perimeter 4 | #' @param x object of class \code{sf}, \code{sfc} or \code{sfg} 5 | #' @return numerical vector with perimeter for each feature (geometry), with unit of measure when possible 6 | #' @export 7 | st_perimeter_lwgeom = function(x) { 8 | if (isTRUE(st_is_longlat(x))) 9 | stop("for perimeter of longlat geometry, cast to LINESTRING and use st_length") # nocov 10 | ret = CPL_perimeter(st_geometry(x), FALSE) 11 | units(ret) = st_crs(x, parameters=TRUE)$ud_unit 12 | ret 13 | } 14 | 15 | #' compute perimeter from polygons or other geometries 16 | #' 17 | #' Deprecated. 18 | #' Use \code{sf::st_perimeter()} or \code{st_perimeter_lwgeom()} instead. 19 | #' @keywords internal 20 | #' @name perimeter-deprecated 21 | #' @param x object of class \code{sf}, \code{sfc} or \code{sfg} 22 | #' @export 23 | st_perimeter = function(x) { 24 | .Deprecated("sf::st_perimeter or lwgeom::st_perimeter_lwgeom") 25 | # for back compatibility 26 | st_perimeter_lwgeom(x) 27 | } 28 | 29 | #' @export 30 | #' @rdname perimeter 31 | st_perimeter_2d = function(x) { 32 | if (isTRUE(st_is_longlat(x))) 33 | stop("for perimeter of longlat geometry, cast to LINESTRING and use st_length") # nocov 34 | ret = CPL_perimeter(st_geometry(x), TRUE) 35 | units(ret) = st_crs(x, parameters=TRUE)$ud_unit 36 | ret 37 | } 38 | -------------------------------------------------------------------------------- /R/snap_to_grid.R: -------------------------------------------------------------------------------- 1 | #' Snap geometries to a grid 2 | #' 3 | #' @name st_snap_to_grid 4 | #' @param x object with geometries to be snapped 5 | #' @param size numeric or (length) units object; grid cell size in x-, y- (and possibly z- and m-) directions 6 | #' @param origin numeric; origin of the grid 7 | #' @return object of the same class as \code{x} 8 | #' @examples 9 | #' # obtain data 10 | #' library(sf) 11 | #' x = st_read(system.file("gpkg/nc.gpkg", package="sf"), quiet = TRUE)[1, ] %>% 12 | #' st_geometry %>% 13 | #' st_transform(3395) 14 | #' 15 | #' # snap to a grid of 5000 m 16 | #' err = try(y <- st_snap_to_grid(x, 5000)) 17 | #' 18 | #' # plot data for visual comparison 19 | #' if (!inherits(err, "try-error")) { 20 | #' opar = par(mfrow = c(1, 2)) 21 | #' plot(x, main = "orginal data") 22 | #' plot(y, main = "snapped to 5000 m") 23 | #' par(opar) 24 | #' } 25 | #' @export 26 | st_snap_to_grid = function(x, size, origin) UseMethod("st_snap_to_grid") 27 | 28 | #' @export 29 | st_snap_to_grid.sfg = function(x, size, origin = st_point(rep(0.0,4))) { 30 | st_snap_to_grid(st_geometry(x), size, origin)[[1]] 31 | } 32 | 33 | #' @export 34 | st_snap_to_grid.sfc = function(x, size, origin = st_point(rep(0.0,4))) { 35 | size = rep(as.numeric(size), length.out = 4) 36 | stopifnot(!isTRUE(st_is_longlat(x))) # FIXME 37 | units(size) = as_units("m") 38 | st_sfc(CPL_snap_to_grid(x, origin, size), crs = st_crs(x)) 39 | } 40 | 41 | #' @export 42 | st_snap_to_grid.sf = function(x, size, origin = st_point(rep(0.0,4))) { 43 | st_set_geometry(x, st_snap_to_grid(st_geometry(x), size, origin)) 44 | } 45 | -------------------------------------------------------------------------------- /R/split.R: -------------------------------------------------------------------------------- 1 | #' Return a collection of geometries resulting by splitting a geometry 2 | #' 3 | #' @name st_split 4 | #' @param x object with geometries to be splitted 5 | #' @param y object split with (blade); if \code{y} contains more than one feature geometry, the geometries are \link[sf:geos_combine]{st_combine} 'd 6 | #' @return object of the same class as \code{x} 7 | #' @examples 8 | #' library(sf) 9 | #' l = st_as_sfc('MULTILINESTRING((10 10, 190 190), (15 15, 30 30, 100 90))') 10 | #' pt = st_sfc(st_point(c(30,30))) 11 | #' st_split(l, pt) 12 | #' @export 13 | st_split = function(x, y) UseMethod("st_split") 14 | 15 | #' @export 16 | st_split.sfg = function(x, y) { 17 | st_split(st_geometry(x), st_geometry(y))[[1]] 18 | } 19 | 20 | #' @export 21 | st_split.sfc = function(x, y) { 22 | y = st_geometry(y) 23 | if (length(y) > 1) y = sf::st_combine(y) 24 | if (inherits(x, "sfc_POLYGON") || inherits(x, "sfc_MULTIPOLYGON")) 25 | stopifnot(inherits(y, "sfc_LINESTRING") || inherits(y, "sfc_MULTILINESTRING")) 26 | else 27 | stopifnot(inherits(x, "sfc_LINESTRING") || inherits(x, "sfc_MULTILINESTRING")) 28 | st_sfc(CPL_split(x, y), crs = st_crs(x)) 29 | } 30 | 31 | #' @export 32 | st_split.sf = function(x, y) { 33 | st_set_geometry(x, st_split(st_geometry(x), y)) 34 | } 35 | 36 | #' get substring from linestring 37 | #' @export 38 | #' @param x object of class \code{sfc}, \code{sf} or \code{sfg} 39 | #' @param from relative distance from origin (in [0,1]) 40 | #' @param to relative distance from origin (in [0,1]) 41 | #' @param ... ignored 42 | #' @param tolerance tolerance parameter, when to snap to line node node 43 | #' @return object of class \code{sfc} 44 | #' @examples 45 | #' library(sf) 46 | #' lines = st_sfc(st_linestring(rbind(c(0,0), c(1,2), c(2,0))), crs = 4326) 47 | #' spl = st_linesubstring(lines, 0.2, 0.8) # should warn 48 | #' plot(st_geometry(lines), col = 'red', lwd = 3) 49 | #' plot(spl, col = 'black', lwd = 3, add = TRUE) 50 | #' st_linesubstring(lines, 0.49999, 0.8) # three points 51 | #' st_linesubstring(lines, 0.49999, 0.8, 0.001) # two points: snap start to second node 52 | st_linesubstring = function(x, from, to, tolerance, ...) UseMethod("st_linesubstring") 53 | 54 | #' @export 55 | st_linesubstring.sfc = function(x, from, to, tolerance = 0.0, ...) { 56 | if (isTRUE(st_is_longlat(x))) 57 | warning("st_linesubstring does not follow a geodesic; you may want to use st_geod_segmentize first") 58 | st_sfc(CPL_linesubstring(x, from, to, tolerance), crs = st_crs(x)) 59 | } 60 | 61 | #' @export 62 | st_linesubstring.sf = function(x, from, to, tolerance = 0.0, ...) { 63 | if (isTRUE(st_is_longlat(x))) 64 | warning("st_linesubstring does not follow a geodesic; you may want to use st_geod_segmentize first") 65 | st_set_geometry(x, st_linesubstring(st_geometry(x), from, to, tolerance)) 66 | } 67 | 68 | #' @export 69 | st_linesubstring.sfg = function(x, from, to, tolerance = 0.0, ...) { 70 | CPL_linesubstring(st_geometry(x), from, to, tolerance)[[1]] 71 | } 72 | -------------------------------------------------------------------------------- /R/startpoint.R: -------------------------------------------------------------------------------- 1 | #' Return the start and end points from lines 2 | #' 3 | #' @param x line of class \code{sf}, \code{sfc} or \code{sfg} 4 | #' @export 5 | #' @details see \url{https://postgis.net/docs/ST_StartPoint.html} and \url{https://postgis.net/docs/ST_EndPoint.html}. 6 | #' @return \code{sf} object representing start and end points 7 | #' @examples 8 | #' library(sf) 9 | #' m = matrix(c(0, 1, 2, 0, 1, 4), ncol = 2) 10 | #' l = st_sfc(st_linestring(m)) 11 | #' lwgeom::st_startpoint(l) 12 | #' lwgeom::st_endpoint(l) 13 | #' l2 = st_sfc(st_linestring(m), st_linestring(m[3:1, ])) 14 | #' lwgeom::st_startpoint(l2) 15 | #' lwgeom::st_endpoint(l2) 16 | st_startpoint = function(x) { 17 | m <- CPL_startpoint(st_geometry(x)) 18 | st_sfc(lapply(seq_len(nrow(m)), function(i) st_point(m[i,])), crs = st_crs(x)) 19 | } 20 | #' @rdname st_startpoint 21 | #' @export 22 | st_endpoint = function(x) { 23 | m <- CPL_endpoint(st_geometry(x)) 24 | st_sfc(lapply(seq_len(nrow(m)), function(i) st_point(m[i,])), crs = st_crs(x)) 25 | } 26 | -------------------------------------------------------------------------------- /R/subdivide.R: -------------------------------------------------------------------------------- 1 | #' Return a collection of geometries resulting by subdividing a geometry 2 | #' 3 | #' @name st_subdivide 4 | #' @param x object with geometries to be subdivided 5 | #' @param max_vertices integer; maximum size of the subgeometries (at least 8) 6 | #' @return object of the same class as \code{x} 7 | #' @examples 8 | #' library(sf) 9 | #' demo(nc, ask = FALSE, echo = FALSE) 10 | #' x = st_subdivide(nc, 10) 11 | #' plot(x[1]) 12 | #' @export 13 | st_subdivide = function(x, max_vertices) UseMethod("st_subdivide") 14 | 15 | #' @export 16 | st_subdivide.sfg = function(x, max_vertices = 256) { 17 | st_subdivide(st_geometry(x), max_vertices)[[1]] 18 | } 19 | 20 | #' @export 21 | st_subdivide.sfc = function(x, max_vertices = 256) { 22 | st_sfc(CPL_subdivide(x, max_vertices), crs = st_crs(x)) 23 | } 24 | 25 | #' @export 26 | st_subdivide.sf = function(x, max_vertices = 256) { 27 | st_set_geometry(x, st_subdivide(st_geometry(x), max_vertices)) 28 | } 29 | -------------------------------------------------------------------------------- /R/transform.R: -------------------------------------------------------------------------------- 1 | #' Transform or convert coordinates of simple features directly with Proj.4 (bypassing GDAL) 2 | #' 3 | #' Transform or convert coordinates of simple features directly with Proj.4 (bypassing GDAL) 4 | #' 5 | #' @param x object of class sf, sfc or sfg 6 | #' @param crs character; target CRS, or, in case of a length 2 character vector, source and target CRS 7 | #' @param ... ignored 8 | #' @details Transforms coordinates of object to new projection, using PROJ directly rather than the GDAL API used by \link[sf]{st_transform}. 9 | #' 10 | #' If \code{crs} is a single CRS, it forms the target CRS, and in that case the source CRS is obtained as \code{st_crs(x)}. Since this presumes that the source CRS is accepted by GDAL (which is not always the case), a second option is to specify the source and target CRS as two proj4strings in argument \code{crs}. In the latter case, \code{st_crs(x)} is ignored and may well be \code{NA}. 11 | #' @examples 12 | #' library(sf) 13 | #' p1 = st_point(c(7,52)) 14 | #' p2 = st_point(c(-30,20)) 15 | #' sfc = st_sfc(p1, p2, crs = 4326) 16 | #' sfc 17 | #' st_transform_proj(sfc, "+proj=wintri") 18 | #' @export 19 | st_transform_proj = function(x, crs, ...) UseMethod("st_transform_proj") 20 | 21 | #' @name st_transform_proj 22 | #' @export 23 | st_transform_proj.sfc = function(x, crs, ...) { 24 | if (inherits(crs, "crs")) 25 | crs = if (sf_extSoftVersion()["proj.4"] >= "6.0.0") 26 | crs$wkt 27 | else 28 | crs$proj4string 29 | if (length(crs) == 1) # only target CRS given: get source crs 30 | crs = if (sf_extSoftVersion()["proj.4"] >= "6.0.0") 31 | c(st_crs(x)$wkt, crs) # c(input, output) 32 | else 33 | c(st_crs(x)$proj4string, crs) # c(input, output) 34 | stopifnot(is.character(crs), length(crs) == 2) 35 | ret = CPL_lwgeom_transform(x, crs) 36 | ret = try(st_sfc(ret, crs = crs[2])) 37 | if (inherits(ret, "try-error")) { 38 | warning("CRS of returned object is NA, since the target CRS is not recognized by GDAL") 39 | st_sfc(ret, crs = NA_crs_) 40 | } else 41 | ret 42 | } 43 | 44 | #' @name st_transform_proj 45 | #' @export 46 | #' @examples 47 | #' library(sf) 48 | #' nc = st_read(system.file("shape/nc.shp", package="sf")) 49 | #' st_transform_proj(nc[1,], "+proj=wintri +over") 50 | st_transform_proj.sf = function(x, crs, ...) { 51 | x[[ attr(x, "sf_column") ]] = st_transform_proj(st_geometry(x), crs, ...) 52 | x 53 | } 54 | 55 | #' @name st_transform_proj 56 | #' @export 57 | #' @details The \code{st_transform_proj} method for \code{sfg} objects assumes that the CRS of the object is available as an attribute of that name. 58 | #' @examples 59 | #' st_transform_proj(structure(p1, proj4string = "+init=epsg:4326"), "+init=epsg:3857") 60 | st_transform_proj.sfg = function(x, crs, ...) { 61 | if (missing(crs)) 62 | stop("argument crs cannot be missing") # nocov 63 | if (length(crs) == 1) { 64 | if (is.null(attr(x, "proj4string"))) 65 | stop("x does not have a proj4string attribute") # nocov 66 | if (!is.character(attr(x, "proj4string"))) 67 | stop("proj4string attribute should be a character string") # nocov 68 | crs = c(attr(x, "proj4string"), crs) 69 | } 70 | structure(st_transform_proj(st_sfc(x), crs, ...)[[1]], proj4string = tail(crs, 1)) 71 | } 72 | -------------------------------------------------------------------------------- /R/twkb.R: -------------------------------------------------------------------------------- 1 | #' create sfc object from tiny well-known binary (twkb) 2 | #' 3 | #' create sfc object from tiny well-known binary (twkb) 4 | #' @param x list with raw vectors, of class \code{TWKB} 5 | #' @param ... ignored 6 | #' @seealso https://github.com/TWKB/Specification/blob/master/twkb.md 7 | #' @examples 8 | #' l = structure(list(as.raw(c(0x02, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08))), class = "TWKB") 9 | #' library(sf) # load generic 10 | #' st_as_sfc(l) 11 | #' @export 12 | st_as_sfc.TWKB = function(x, ...) { 13 | st_sfc(CPL_sfc_from_twkb(x)) 14 | } 15 | -------------------------------------------------------------------------------- /R/valid.R: -------------------------------------------------------------------------------- 1 | #' Make an invalid geometry valid 2 | #' 3 | #' Make an invalid geometry valid 4 | #' @param x object of class \code{sfc} 5 | #' @export 6 | lwgeom_make_valid = function(x) { 7 | stopifnot(inherits(x, "sfc")) 8 | st_sfc(CPL_make_valid(x), crs = st_crs(x)) 9 | } 10 | -------------------------------------------------------------------------------- /R/wkt.R: -------------------------------------------------------------------------------- 1 | #' Return Well-known Text representation of simple feature geometry 2 | #' 3 | #' Return Well-known Text representation of simple feature geometry or coordinate reference system 4 | #' @param x object of class `sfg`, `sfc`, or `sf` 5 | #' @param digits integer; number of decimal digits to print 6 | #' @param ... ignored 7 | #' @param EWKT logical; use PostGIS Enhanced WKT (includes srid) 8 | #' @name st_astext 9 | #' @details The returned WKT representation of simple feature geometry conforms to the 10 | #' [simple features access](https://www.ogc.org/standards/sfa/) specification and extensions (if `EWKT = TRUE`), 11 | #' [known as EWKT](http://postgis.net/docs/using_postgis_dbmanagement.html#EWKB_EWKT), supported by 12 | #' PostGIS and other simple features implementations for addition of SRID to a WKT string. 13 | #' @md 14 | #' @examples 15 | #' library(sf) 16 | #' pt <- st_sfc(st_point(c(1.0002,2.3030303)), crs = 4326) 17 | #' st_astext(pt, 3) 18 | #' st_asewkt(pt, 3) 19 | #' @export 20 | st_astext <- function(x, digits = getOption("digits"), ..., EWKT = FALSE) { 21 | if (! EWKT && !inherits(x, "sfg")) 22 | st_crs(x) <- NA_crs_ 23 | CPL_sfc_to_wkt(st_geometry(x), as.integer(digits)) 24 | } 25 | 26 | #' @name st_astext 27 | #' @inheritParams st_astext 28 | #' @details `st_asewkt()` returns the Well-Known Text (WKT) representation of 29 | #' the geometry with SRID meta data. 30 | #' @md 31 | #' @export 32 | st_asewkt <- function(x, digits = options("digits")) { 33 | st_astext(x, digits = digits, EWKT = TRUE) 34 | } 35 | -------------------------------------------------------------------------------- /R/wrap_x.R: -------------------------------------------------------------------------------- 1 | #' Splits input geometries by a vertical line and moves components falling on 2 | #' one side of that line by a fixed amount 3 | #' 4 | #' @name st_wrap_x 5 | #' @param x object with geometries to be split 6 | #' @param wrap x value of split line 7 | #' @param move amount by which geometries falling to the left of the line 8 | #' should be translated to the right 9 | #' @return object of the same class as \code{x} 10 | #' @examples 11 | #' library(sf) 12 | #' demo(nc, ask = FALSE, echo = FALSE) 13 | #' x = st_wrap_x(nc, -78, 10) 14 | #' plot(x[1]) 15 | #' @export 16 | st_wrap_x = function(x, wrap, move) UseMethod("st_wrap_x") 17 | 18 | #' @export 19 | st_wrap_x.sfg = function(x, wrap, move) { 20 | st_wrap_x(st_geometry(x), wrap, move)[[1]] 21 | } 22 | 23 | #' @export 24 | st_wrap_x.sfc = function(x, wrap, move) { 25 | st_sfc(CPL_wrap_x(x, wrap, move), crs = st_crs(x)) 26 | } 27 | 28 | #' @export 29 | st_wrap_x.sf = function(x, wrap, move) { 30 | st_set_geometry(x, st_wrap_x(st_geometry(x), wrap, move)) 31 | } 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lwgeom 2 | R bindings to the [liblwgeom](https://github.com/postgis/postgis/tree/master/liblwgeom) library 3 | 4 | 5 | [![R-CMD-check](https://github.com/r-spatial/lwgeom/actions/workflows/R-CMD-check.yaml/badge.svg)](https://github.com/r-spatial/lwgeom/actions/workflows/R-CMD-check.yaml) 6 | [![Coverage Status](https://img.shields.io/codecov/c/github/r-spatial/lwgeom/master.svg)](https://app.codecov.io/github/r-spatial/lwgeom?branch=master) 7 | [![CRAN](http://www.r-pkg.org/badges/version/lwgeom)](https://cran.r-project.org/package=lwgeom) 8 | [![cran checks](https://badges.cranchecks.info/worst/lwgeom.svg)](https://cran.r-project.org/web/checks/check_results_lwgeom.html) 9 | [![Downloads](http://cranlogs.r-pkg.org/badges/lwgeom?color=brightgreen)](https://www.r-pkg.org:443/pkg/lwgeom) 10 | 11 | 12 | 13 | This package provides functions that use 14 | `liblwgeom`, including `st_geohash()`, 15 | `st_minimum_bounding_circle()`, `st_split()`, `st_subdivide()`, 16 | `st_transform_proj()` (transform through proj, omitting 17 | GDAL) and `st_as_sfc.TWKB()` (creates `sfc` from [tiny 18 | wkb](https://github.com/TWKB/Specification/blob/master/twkb.md)), 19 | as well as the geodetic (spherical/ellipsoidal) geometry 20 | functions `st_geod_area()`, 21 | `st_geod_length()`, 22 | `st_geod_distance()`, 23 | `st_geod_covers()`, 24 | `st_geod_azimuth()`, 25 | and `st_geod_segmentize()`. The previously offered `st_make_valid()` 26 | is now a generic in package `sf` (`sf::st_make_valid()`). 27 | 28 | ## Installing 29 | 30 | `lwgeom` depends on [sf](https://github.com/r-spatial/sf), which 31 | has to be installed first. This package uses the liblwgeom library, 32 | and compiles a shipped (and modified) version of liblwgeom. It links 33 | to the GEOS and PROJ libraries. 34 | 35 | To install from source, it should be enough to have installed 36 | `sf` from source; the resources for this package (PROJ, GEOS) 37 | are being reused. 38 | 39 | ## lwgeom source now included 40 | 41 | Previous to version 0.1-6, `lwgeom` would also try to link the system 42 | library liblwgeom; from 0.1-6 on only the shipped version is used. 43 | 44 | ## Contributing 45 | 46 | * Contributions of all sorts are most welcome, issues and pull requests are the preferred ways of sharing them. 47 | * 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) 48 | * This project is released with a [Contributor Code of Conduct](CONDUCT.md). By participating in this project you agree to abide by its terms. 49 | -------------------------------------------------------------------------------- /_pkgdown.yml: -------------------------------------------------------------------------------- 1 | url: https://r-spatial.github.io/lwgeom/ 2 | template: 3 | bootstrap: 5 4 | 5 | -------------------------------------------------------------------------------- /cleanup: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | rm -fr src/Makevars config.log config.status autom4te.cache src/*.o src/*.so src/liblwgeom/*.o */Rplots.pdf proj_conf_test proj_conf_test.c proj_conf_test.cpp 3 | -------------------------------------------------------------------------------- /codecov.yml: -------------------------------------------------------------------------------- 1 | comment: false 2 | ignore: 3 | - "src/liblwgeom" 4 | -------------------------------------------------------------------------------- /inst/COPYRIGHTS: -------------------------------------------------------------------------------- 1 | Copyright holders of the liblwgeom library (files in src/liblwgeom): 2 | 3 | Copyright (C) 2004-2015 Sandro Santilli 4 | Copyright (C) 2008-2011 Paul Ramsey 5 | Copyright (C) 2008 Mark Cave-Ayland 6 | Copyright 2015 Nicklas Avén 7 | Copyright 2017 Darafei Praliaskouski 8 | Copyright 2001-2006 Refractions Research Inc. 9 | Copyright 2015 Daniel Baston 10 | Copyright 2009 David Skea 11 | Copyright 2010 Olivier Courtin 12 | Copyright 2011 Kashif Rasul 13 | Copyright (C) 1984, 1989-1990, 2000-2015 Free Software Foundation, Inc. 14 | Copyright 2010-2012 Oslandia 15 | Copyright 2006 Corporacion Autonoma Regional de Santander 16 | Originally written by: Klaus Förster Refactored by: Olivier Courtin (Camptocamp) 17 | Copyright 2011-2016 Arrival 3D, Regina Obe 18 | Copyright (C) 2006 Mark Leslie 19 | Copyright 2002 Thamer Alharbash 20 | -------------------------------------------------------------------------------- /lwgeom.Rproj: -------------------------------------------------------------------------------- 1 | Version: 1.0 2 | 3 | RestoreWorkspace: Default 4 | SaveWorkspace: Default 5 | AlwaysSaveHistory: Default 6 | 7 | EnableCodeIndexing: Yes 8 | UseSpacesForTab: Yes 9 | NumSpacesForTab: 2 10 | Encoding: UTF-8 11 | 12 | RnwWeave: knitr 13 | LaTeX: pdfLaTeX 14 | 15 | AutoAppendNewline: Yes 16 | 17 | BuildType: Package 18 | PackageUseDevtools: Yes 19 | PackageInstallArgs: --no-multiarch --with-keep.source 20 | PackageRoxygenize: rd,collate,namespace 21 | -------------------------------------------------------------------------------- /man/bounding_circle.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/bounding_circle.R 3 | \name{bounding_circle} 4 | \alias{bounding_circle} 5 | \alias{st_minimum_bounding_circle} 6 | \title{Generate the minimum bounding circle} 7 | \usage{ 8 | st_minimum_bounding_circle(x, nQuadSegs = 30) 9 | } 10 | \arguments{ 11 | \item{x}{object of class \code{sfg}, \code{sfg} or \code{sf}} 12 | 13 | \item{nQuadSegs}{number of segments per quadrant (passed to \code{st_buffer})} 14 | } 15 | \value{ 16 | Object of the same class as \code{x} 17 | } 18 | \description{ 19 | Generate the minimum bounding circle 20 | } 21 | \details{ 22 | \code{st_minimum_bounding_circle} uses the \code{lwgeom_calculate_mbc} method also used by the PostGIS command \code{ST_MinimumBoundingCircle}. 23 | } 24 | \examples{ 25 | library(sf) 26 | 27 | x = st_multipoint(matrix(c(0,1,0,1),2,2)) 28 | y = st_multipoint(matrix(c(0,0,1,0,1,1),3,2)) 29 | 30 | mbcx = st_minimum_bounding_circle(x) 31 | mbcy = st_minimum_bounding_circle(y) 32 | 33 | if (.Platform$OS.type != "windows") { 34 | plot(mbcx, axes=TRUE); plot(x, add=TRUE) 35 | plot(mbcy, axes=TRUE); plot(y, add=TRUE) 36 | } 37 | 38 | nc = st_read(system.file("gpkg/nc.gpkg", package="sf")) 39 | state = st_union(st_geometry(nc)) 40 | 41 | if (.Platform$OS.type != "windows") { 42 | plot(st_minimum_bounding_circle(state), asp=1) 43 | plot(state, add=TRUE) 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /man/geod.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geod.R 3 | \name{geod} 4 | \alias{geod} 5 | \alias{st_geod_area} 6 | \alias{st_geod_length} 7 | \alias{st_geod_segmentize} 8 | \alias{st_geod_covers} 9 | \alias{st_geod_covered_by} 10 | \alias{st_geod_distance} 11 | \title{liblwgeom geodetic functions} 12 | \usage{ 13 | st_geod_area(x) 14 | 15 | st_geod_length(x) 16 | 17 | st_geod_segmentize(x, max_seg_length) 18 | 19 | st_geod_covers(x, y, sparse = TRUE) 20 | 21 | st_geod_covered_by(x, y, sparse = TRUE) 22 | 23 | st_geod_distance(x, y, tolerance = 0, sparse = FALSE) 24 | } 25 | \arguments{ 26 | \item{x}{object of class \code{sf}, \code{sfc} or \code{sfg}} 27 | 28 | \item{max_seg_length}{segment length in degree, radians, or as a length unit (e.g., m)} 29 | 30 | \item{y}{object of class \code{sf}, \code{sfc} or \code{sfg}} 31 | 32 | \item{sparse}{logical; if \code{TRUE}, return a sparse matrix (object of class \code{sgbp}), otherwise, return a dense logical matrix.} 33 | 34 | \item{tolerance}{double or length \code{units} value: if positive, the first distance less than \code{tolerance} is returned, rather than the true distance} 35 | } 36 | \description{ 37 | liblwgeom geodetic functions for length, area, segmentizing, covers 38 | } 39 | \details{ 40 | \code{st_area} will give an error message when the area spans the equator and \code{lwgeom} is linked to a proj.4 version older than 4.9.0 (see \link{lwgeom_extSoftVersion}) 41 | 42 | longitude coordinates returned are rescaled to [-180,180) 43 | } 44 | \note{ 45 | this function should is used by \link[sf:geos_measures]{st_distance}, do not use it directly 46 | } 47 | \examples{ 48 | library(sf) 49 | nc = st_read(system.file("gpkg/nc.gpkg", package="sf")) 50 | st_geod_area(nc[1:3,]) 51 | # st_area(nc[1:3,]) 52 | l = st_sfc(st_linestring(rbind(c(7,52), c(8,53))), crs = 4326) 53 | st_geod_length(l) 54 | library(units) 55 | pol = st_polygon(list(rbind(c(0,0), c(0,60), c(60,60), c(0,0)))) 56 | x = st_sfc(pol, crs = 4326) 57 | seg = st_geod_segmentize(x[1], set_units(10, km)) 58 | plot(seg, graticule = TRUE, axes = TRUE) 59 | pole = st_polygon(list(rbind(c(0,80), c(120,80), c(240,80), c(0,80)))) 60 | pt = st_point(c(0,90)) 61 | x = st_sfc(pole, pt, crs = 4326) 62 | st_geod_covers(x[c(1,1,1)], x[c(2,2,2,2)]) 63 | pole = st_polygon(list(rbind(c(0,80), c(120,80), c(240,80), c(0,80)))) 64 | pt = st_point(c(30,70)) 65 | x = st_sfc(pole, pt, crs = 4326) 66 | st_geod_distance(x, x) 67 | } 68 | -------------------------------------------------------------------------------- /man/lwgeom_extSoftVersion.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/init.R 3 | \name{lwgeom_extSoftVersion} 4 | \alias{lwgeom_extSoftVersion} 5 | \title{Provide the external dependencies versions of the libraries linked to sf} 6 | \usage{ 7 | lwgeom_extSoftVersion() 8 | } 9 | \description{ 10 | Provide the external dependencies versions of the libraries linked to sf 11 | } 12 | -------------------------------------------------------------------------------- /man/lwgeom_make_valid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/valid.R 3 | \name{lwgeom_make_valid} 4 | \alias{lwgeom_make_valid} 5 | \title{Make an invalid geometry valid} 6 | \usage{ 7 | lwgeom_make_valid(x) 8 | } 9 | \arguments{ 10 | \item{x}{object of class \code{sfc}} 11 | } 12 | \description{ 13 | Make an invalid geometry valid 14 | } 15 | -------------------------------------------------------------------------------- /man/perimeter-deprecated.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/perimeter.R 3 | \name{perimeter-deprecated} 4 | \alias{perimeter-deprecated} 5 | \alias{st_perimeter} 6 | \title{compute perimeter from polygons or other geometries} 7 | \usage{ 8 | st_perimeter(x) 9 | } 10 | \arguments{ 11 | \item{x}{object of class \code{sf}, \code{sfc} or \code{sfg}} 12 | } 13 | \description{ 14 | Deprecated. 15 | Use \code{sf::st_perimeter()} or \code{st_perimeter_lwgeom()} instead. 16 | } 17 | \keyword{internal} 18 | -------------------------------------------------------------------------------- /man/perimeter.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/perimeter.R 3 | \name{perimeter} 4 | \alias{perimeter} 5 | \alias{st_perimeter_lwgeom} 6 | \alias{st_perimeter_2d} 7 | \title{Compute perimeter from polygons or other geometries} 8 | \usage{ 9 | st_perimeter_lwgeom(x) 10 | 11 | st_perimeter_2d(x) 12 | } 13 | \arguments{ 14 | \item{x}{object of class \code{sf}, \code{sfc} or \code{sfg}} 15 | } 16 | \value{ 17 | numerical vector with perimeter for each feature (geometry), with unit of measure when possible 18 | } 19 | \description{ 20 | Compute perimeter from polygons or other geometries 21 | } 22 | -------------------------------------------------------------------------------- /man/st_as_sfc.TWKB.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/twkb.R 3 | \name{st_as_sfc.TWKB} 4 | \alias{st_as_sfc.TWKB} 5 | \title{create sfc object from tiny well-known binary (twkb)} 6 | \usage{ 7 | \method{st_as_sfc}{TWKB}(x, ...) 8 | } 9 | \arguments{ 10 | \item{x}{list with raw vectors, of class \code{TWKB}} 11 | 12 | \item{...}{ignored} 13 | } 14 | \description{ 15 | create sfc object from tiny well-known binary (twkb) 16 | } 17 | \examples{ 18 | l = structure(list(as.raw(c(0x02, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08))), class = "TWKB") 19 | library(sf) # load generic 20 | st_as_sfc(l) 21 | } 22 | \seealso{ 23 | https://github.com/TWKB/Specification/blob/master/twkb.md 24 | } 25 | -------------------------------------------------------------------------------- /man/st_astext.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/wkt.R 3 | \name{st_astext} 4 | \alias{st_astext} 5 | \alias{st_asewkt} 6 | \title{Return Well-known Text representation of simple feature geometry} 7 | \usage{ 8 | st_astext(x, digits = getOption("digits"), ..., EWKT = FALSE) 9 | 10 | st_asewkt(x, digits = options("digits")) 11 | } 12 | \arguments{ 13 | \item{x}{object of class \code{sfg}, \code{sfc}, or \code{sf}} 14 | 15 | \item{digits}{integer; number of decimal digits to print} 16 | 17 | \item{...}{ignored} 18 | 19 | \item{EWKT}{logical; use PostGIS Enhanced WKT (includes srid)} 20 | } 21 | \description{ 22 | Return Well-known Text representation of simple feature geometry or coordinate reference system 23 | } 24 | \details{ 25 | The returned WKT representation of simple feature geometry conforms to the 26 | \href{https://www.ogc.org/standards/sfa/}{simple features access} specification and extensions (if \code{EWKT = TRUE}), 27 | \href{http://postgis.net/docs/using_postgis_dbmanagement.html#EWKB_EWKT}{known as EWKT}, supported by 28 | PostGIS and other simple features implementations for addition of SRID to a WKT string. 29 | 30 | \code{st_asewkt()} returns the Well-Known Text (WKT) representation of 31 | the geometry with SRID meta data. 32 | } 33 | \examples{ 34 | library(sf) 35 | pt <- st_sfc(st_point(c(1.0002,2.3030303)), crs = 4326) 36 | st_astext(pt, 3) 37 | st_asewkt(pt, 3) 38 | } 39 | -------------------------------------------------------------------------------- /man/st_force_polygon_cw.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/clockwise.R 3 | \name{st_force_polygon_cw} 4 | \alias{st_force_polygon_cw} 5 | \title{Force a POLYGON or MULTIPOLYGON to be clockwise} 6 | \usage{ 7 | st_force_polygon_cw(x) 8 | } 9 | \arguments{ 10 | \item{x}{object with polygon geometries} 11 | } 12 | \value{ 13 | object of the same class as \code{x} 14 | } 15 | \description{ 16 | Check if a POLYGON or MULTIPOLYGON is clockwise, and if not make it so. 17 | According to the 'Right-hand-rule', outer rings should be clockwise, and 18 | inner holes should be counter-clockwise 19 | } 20 | \examples{ 21 | library(sf) 22 | polys <- st_sf(cw = c(FALSE, TRUE), 23 | st_as_sfc(c('POLYGON ((0 0, 1 0, 1 1, 0 0))', 24 | 'POLYGON ((1 1, 2 2, 2 1, 1 1))'))) 25 | 26 | st_force_polygon_cw(polys) 27 | st_force_polygon_cw(st_geometry(polys)) 28 | st_force_polygon_cw(st_geometry(polys)[[1]]) 29 | } 30 | -------------------------------------------------------------------------------- /man/st_geod_azimuth.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/bearing.R 3 | \name{st_geod_azimuth} 4 | \alias{st_geod_azimuth} 5 | \title{compute azimuth between sequence of points} 6 | \usage{ 7 | st_geod_azimuth(x) 8 | } 9 | \arguments{ 10 | \item{x}{object of class \code{sf}, \code{sfc} or \code{sfg}} 11 | } 12 | \description{ 13 | compute azimuth between sequence of points 14 | } 15 | \examples{ 16 | library(sf) 17 | p = st_sfc(st_point(c(7,52)), st_point(c(8,53)), crs = 4326) 18 | st_geod_azimuth(p) 19 | } 20 | -------------------------------------------------------------------------------- /man/st_geohash.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/geohash.R 3 | \name{st_geohash} 4 | \alias{st_geohash} 5 | \alias{st_geom_from_geohash} 6 | \title{compute geohash from (average) coordinates} 7 | \usage{ 8 | st_geohash(x, precision = 0) 9 | 10 | st_geom_from_geohash( 11 | hash, 12 | precision = -1, 13 | crs = st_crs("OGC:CRS84"), 14 | raw = FALSE 15 | ) 16 | } 17 | \arguments{ 18 | \item{x}{object of class \code{sf}, \code{sfc} or \code{sfg}} 19 | 20 | \item{precision}{integer; precision (length) of geohash returned. From the liblwgeom source: ``where the precision is non-positive, a precision based on the bounds of the feature. Big features have loose precision. Small features have tight precision.''} 21 | 22 | \item{hash}{character vector with geohashes} 23 | 24 | \item{crs}{object of class `crs`} 25 | 26 | \item{raw}{logical; if `TRUE`, return a matrix with bounding box coordinates on each row} 27 | } 28 | \value{ 29 | `st_geohash` returns a character vector with geohashes; empty or full geometries result in `NA` 30 | 31 | `st_geom_from_geohash` returns a (bounding box) polygon for each geohash if `raw` is `FALSE`, if `raw` is `TRUE` a matrix is returned with bounding box coordinates on each row. 32 | } 33 | \description{ 34 | compute geohash from (average) coordinates 35 | } 36 | \details{ 37 | see \url{https://en.wikipedia.org/wiki/Geohash}. 38 | } 39 | \examples{ 40 | library(sf) 41 | lwgeom::st_geohash(st_sfc(st_point(c(1.5,3.5)), st_point(c(0,90))), 2) 42 | lwgeom::st_geohash(st_sfc(st_point(c(1.5,3.5)), st_point(c(0,90))), 10) 43 | st_geom_from_geohash(c('9qqj7nmxncgyy4d0dbxqz0', 'up'), raw = TRUE) 44 | o = options(digits = 20) # for printing purposes 45 | st_geom_from_geohash(c('9qqj7nmxncgyy4d0dbxqz0', 'u1hzz631zyd63zwsd7zt')) 46 | st_geom_from_geohash('9qqj7nmxncgyy4d0dbxqz0', 4) 47 | st_geom_from_geohash('9qqj7nmxncgyy4d0dbxqz0', 10) 48 | options(o) 49 | } 50 | -------------------------------------------------------------------------------- /man/st_is_polygon_cw.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/clockwise.R 3 | \name{st_is_polygon_cw} 4 | \alias{st_is_polygon_cw} 5 | \title{Check if a POLYGON or MULTIPOLYGON is clockwise} 6 | \usage{ 7 | st_is_polygon_cw(x) 8 | } 9 | \arguments{ 10 | \item{x}{object with polygon geometries} 11 | } 12 | \value{ 13 | logical with length the same number of features in `x` 14 | } 15 | \description{ 16 | Check if a POLYGON or MULTIPOLYGON is clockwise. According to the 17 | 'Right-hand-rule', outer rings should be clockwise, and inner holes 18 | should be counter-clockwise 19 | } 20 | \examples{ 21 | library(sf) 22 | polys <- st_sf(cw = c(FALSE, TRUE), 23 | st_as_sfc(c('POLYGON ((0 0, 1 0, 1 1, 0 0))', 24 | 'POLYGON ((1 1, 2 2, 2 1, 1 1))'))) 25 | 26 | st_is_polygon_cw(polys) 27 | st_is_polygon_cw(st_geometry(polys)) 28 | st_is_polygon_cw(st_geometry(polys)[[1]]) 29 | } 30 | -------------------------------------------------------------------------------- /man/st_linesubstring.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/split.R 3 | \name{st_linesubstring} 4 | \alias{st_linesubstring} 5 | \title{get substring from linestring} 6 | \usage{ 7 | st_linesubstring(x, from, to, tolerance, ...) 8 | } 9 | \arguments{ 10 | \item{x}{object of class \code{sfc}, \code{sf} or \code{sfg}} 11 | 12 | \item{from}{relative distance from origin (in [0,1])} 13 | 14 | \item{to}{relative distance from origin (in [0,1])} 15 | 16 | \item{tolerance}{tolerance parameter, when to snap to line node node} 17 | 18 | \item{...}{ignored} 19 | } 20 | \value{ 21 | object of class \code{sfc} 22 | } 23 | \description{ 24 | get substring from linestring 25 | } 26 | \examples{ 27 | library(sf) 28 | lines = st_sfc(st_linestring(rbind(c(0,0), c(1,2), c(2,0))), crs = 4326) 29 | spl = st_linesubstring(lines, 0.2, 0.8) # should warn 30 | plot(st_geometry(lines), col = 'red', lwd = 3) 31 | plot(spl, col = 'black', lwd = 3, add = TRUE) 32 | st_linesubstring(lines, 0.49999, 0.8) # three points 33 | st_linesubstring(lines, 0.49999, 0.8, 0.001) # two points: snap start to second node 34 | } 35 | -------------------------------------------------------------------------------- /man/st_snap_to_grid.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/snap_to_grid.R 3 | \name{st_snap_to_grid} 4 | \alias{st_snap_to_grid} 5 | \title{Snap geometries to a grid} 6 | \usage{ 7 | st_snap_to_grid(x, size, origin) 8 | } 9 | \arguments{ 10 | \item{x}{object with geometries to be snapped} 11 | 12 | \item{size}{numeric or (length) units object; grid cell size in x-, y- (and possibly z- and m-) directions} 13 | 14 | \item{origin}{numeric; origin of the grid} 15 | } 16 | \value{ 17 | object of the same class as \code{x} 18 | } 19 | \description{ 20 | Snap geometries to a grid 21 | } 22 | \examples{ 23 | # obtain data 24 | library(sf) 25 | x = st_read(system.file("gpkg/nc.gpkg", package="sf"), quiet = TRUE)[1, ] \%>\% 26 | st_geometry \%>\% 27 | st_transform(3395) 28 | 29 | # snap to a grid of 5000 m 30 | err = try(y <- st_snap_to_grid(x, 5000)) 31 | 32 | # plot data for visual comparison 33 | if (!inherits(err, "try-error")) { 34 | opar = par(mfrow = c(1, 2)) 35 | plot(x, main = "orginal data") 36 | plot(y, main = "snapped to 5000 m") 37 | par(opar) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /man/st_split.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/split.R 3 | \name{st_split} 4 | \alias{st_split} 5 | \title{Return a collection of geometries resulting by splitting a geometry} 6 | \usage{ 7 | st_split(x, y) 8 | } 9 | \arguments{ 10 | \item{x}{object with geometries to be splitted} 11 | 12 | \item{y}{object split with (blade); if \code{y} contains more than one feature geometry, the geometries are \link[sf:geos_combine]{st_combine} 'd} 13 | } 14 | \value{ 15 | object of the same class as \code{x} 16 | } 17 | \description{ 18 | Return a collection of geometries resulting by splitting a geometry 19 | } 20 | \examples{ 21 | library(sf) 22 | l = st_as_sfc('MULTILINESTRING((10 10, 190 190), (15 15, 30 30, 100 90))') 23 | pt = st_sfc(st_point(c(30,30))) 24 | st_split(l, pt) 25 | } 26 | -------------------------------------------------------------------------------- /man/st_startpoint.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/startpoint.R 3 | \name{st_startpoint} 4 | \alias{st_startpoint} 5 | \alias{st_endpoint} 6 | \title{Return the start and end points from lines} 7 | \usage{ 8 | st_startpoint(x) 9 | 10 | st_endpoint(x) 11 | } 12 | \arguments{ 13 | \item{x}{line of class \code{sf}, \code{sfc} or \code{sfg}} 14 | } 15 | \value{ 16 | \code{sf} object representing start and end points 17 | } 18 | \description{ 19 | Return the start and end points from lines 20 | } 21 | \details{ 22 | see \url{https://postgis.net/docs/ST_StartPoint.html} and \url{https://postgis.net/docs/ST_EndPoint.html}. 23 | } 24 | \examples{ 25 | library(sf) 26 | m = matrix(c(0, 1, 2, 0, 1, 4), ncol = 2) 27 | l = st_sfc(st_linestring(m)) 28 | lwgeom::st_startpoint(l) 29 | lwgeom::st_endpoint(l) 30 | l2 = st_sfc(st_linestring(m), st_linestring(m[3:1, ])) 31 | lwgeom::st_startpoint(l2) 32 | lwgeom::st_endpoint(l2) 33 | } 34 | -------------------------------------------------------------------------------- /man/st_subdivide.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/subdivide.R 3 | \name{st_subdivide} 4 | \alias{st_subdivide} 5 | \title{Return a collection of geometries resulting by subdividing a geometry} 6 | \usage{ 7 | st_subdivide(x, max_vertices) 8 | } 9 | \arguments{ 10 | \item{x}{object with geometries to be subdivided} 11 | 12 | \item{max_vertices}{integer; maximum size of the subgeometries (at least 8)} 13 | } 14 | \value{ 15 | object of the same class as \code{x} 16 | } 17 | \description{ 18 | Return a collection of geometries resulting by subdividing a geometry 19 | } 20 | \examples{ 21 | library(sf) 22 | demo(nc, ask = FALSE, echo = FALSE) 23 | x = st_subdivide(nc, 10) 24 | plot(x[1]) 25 | } 26 | -------------------------------------------------------------------------------- /man/st_transform_proj.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/transform.R 3 | \name{st_transform_proj} 4 | \alias{st_transform_proj} 5 | \alias{st_transform_proj.sfc} 6 | \alias{st_transform_proj.sf} 7 | \alias{st_transform_proj.sfg} 8 | \title{Transform or convert coordinates of simple features directly with Proj.4 (bypassing GDAL)} 9 | \usage{ 10 | st_transform_proj(x, crs, ...) 11 | 12 | \method{st_transform_proj}{sfc}(x, crs, ...) 13 | 14 | \method{st_transform_proj}{sf}(x, crs, ...) 15 | 16 | \method{st_transform_proj}{sfg}(x, crs, ...) 17 | } 18 | \arguments{ 19 | \item{x}{object of class sf, sfc or sfg} 20 | 21 | \item{crs}{character; target CRS, or, in case of a length 2 character vector, source and target CRS} 22 | 23 | \item{...}{ignored} 24 | } 25 | \description{ 26 | Transform or convert coordinates of simple features directly with Proj.4 (bypassing GDAL) 27 | } 28 | \details{ 29 | Transforms coordinates of object to new projection, using PROJ directly rather than the GDAL API used by \link[sf]{st_transform}. 30 | 31 | If \code{crs} is a single CRS, it forms the target CRS, and in that case the source CRS is obtained as \code{st_crs(x)}. Since this presumes that the source CRS is accepted by GDAL (which is not always the case), a second option is to specify the source and target CRS as two proj4strings in argument \code{crs}. In the latter case, \code{st_crs(x)} is ignored and may well be \code{NA}. 32 | 33 | The \code{st_transform_proj} method for \code{sfg} objects assumes that the CRS of the object is available as an attribute of that name. 34 | } 35 | \examples{ 36 | library(sf) 37 | p1 = st_point(c(7,52)) 38 | p2 = st_point(c(-30,20)) 39 | sfc = st_sfc(p1, p2, crs = 4326) 40 | sfc 41 | st_transform_proj(sfc, "+proj=wintri") 42 | library(sf) 43 | nc = st_read(system.file("shape/nc.shp", package="sf")) 44 | st_transform_proj(nc[1,], "+proj=wintri +over") 45 | st_transform_proj(structure(p1, proj4string = "+init=epsg:4326"), "+init=epsg:3857") 46 | } 47 | -------------------------------------------------------------------------------- /man/st_wrap_x.Rd: -------------------------------------------------------------------------------- 1 | % Generated by roxygen2: do not edit by hand 2 | % Please edit documentation in R/wrap_x.R 3 | \name{st_wrap_x} 4 | \alias{st_wrap_x} 5 | \title{Splits input geometries by a vertical line and moves components falling on 6 | one side of that line by a fixed amount} 7 | \usage{ 8 | st_wrap_x(x, wrap, move) 9 | } 10 | \arguments{ 11 | \item{x}{object with geometries to be split} 12 | 13 | \item{wrap}{x value of split line} 14 | 15 | \item{move}{amount by which geometries falling to the left of the line 16 | should be translated to the right} 17 | } 18 | \value{ 19 | object of the same class as \code{x} 20 | } 21 | \description{ 22 | Splits input geometries by a vertical line and moves components falling on 23 | one side of that line by a fixed amount 24 | } 25 | \examples{ 26 | library(sf) 27 | demo(nc, ask = FALSE, echo = FALSE) 28 | x = st_wrap_x(nc, -78, 10) 29 | plot(x[1]) 30 | } 31 | -------------------------------------------------------------------------------- /src/Makevars.in: -------------------------------------------------------------------------------- 1 | PKG_CPPFLAGS=@PKG_CPPFLAGS@ 2 | PKG_LIBS=@PKG_LIBS@ 3 | CXX_STD = CXX 4 | 5 | OBJECTS_LIBLWGEOM= \ 6 | liblwgeom/varint.o \ 7 | liblwgeom/lwout_twkb.o \ 8 | liblwgeom/lwpsurface.o \ 9 | liblwgeom/lwtriangle.o \ 10 | liblwgeom/lwmpoly.o \ 11 | liblwgeom/lookup3.o \ 12 | liblwgeom/lwin_wkt.o \ 13 | liblwgeom/gserialized1.o \ 14 | liblwgeom/lwgeom.o \ 15 | liblwgeom/gserialized2.o \ 16 | liblwgeom/lwstroke.o \ 17 | liblwgeom/lwtin.o \ 18 | liblwgeom/lwin_twkb.o \ 19 | liblwgeom/lwgeom_geos_cluster.o \ 20 | liblwgeom/lwmsurface.o \ 21 | liblwgeom/lwgeom_wrapx.o \ 22 | liblwgeom/lwiterator.o \ 23 | liblwgeom/lwgeom_geos_node.o \ 24 | liblwgeom/lwout_geojson.o \ 25 | liblwgeom/lwgeom_debug.o \ 26 | liblwgeom/lwgeom_median.o \ 27 | liblwgeom/lwmval.o \ 28 | liblwgeom/lwkmeans.o \ 29 | liblwgeom/lwgeom_geos.o \ 30 | liblwgeom/lwout_kml.o \ 31 | liblwgeom/lwutil.o \ 32 | liblwgeom/lwprint.o \ 33 | liblwgeom/lwrandom.o \ 34 | liblwgeom/lwmline.o \ 35 | liblwgeom/lwgeodetic_tree.o \ 36 | liblwgeom/lwline.o \ 37 | liblwgeom/bytebuffer.o \ 38 | liblwgeom/lwgeodetic.o \ 39 | liblwgeom/measures.o \ 40 | liblwgeom/lwgeom_api.o \ 41 | liblwgeom/lwmcurve.o \ 42 | liblwgeom/lwcollection.o \ 43 | liblwgeom/gbox.o \ 44 | liblwgeom/lwspheroid.o \ 45 | liblwgeom/lwout_svg.o \ 46 | liblwgeom/lwin_encoded_polyline.o \ 47 | liblwgeom/lwout_encoded_polyline.o \ 48 | liblwgeom/lwgeom_geos_split.o \ 49 | liblwgeom/effectivearea.o \ 50 | liblwgeom/lwboundingcircle.o \ 51 | liblwgeom/lwcurvepoly.o \ 52 | liblwgeom/lwlinearreferencing.o \ 53 | liblwgeom/lwunionfind.o \ 54 | liblwgeom/lwchaikins.o \ 55 | liblwgeom/lwalgorithm.o \ 56 | liblwgeom/lwhomogenize.o \ 57 | liblwgeom/lwgeom_geos_clean.o \ 58 | liblwgeom/measures3d.o \ 59 | liblwgeom/lwout_x3d.o \ 60 | liblwgeom/lwgeom_transform.o \ 61 | liblwgeom/lwin_wkt_lex.o \ 62 | liblwgeom/lwmpoint.o \ 63 | liblwgeom/stringbuffer.o \ 64 | liblwgeom/lwcompound.o \ 65 | liblwgeom/gserialized.o \ 66 | liblwgeom/lwout_wkt.o \ 67 | liblwgeom/lwin_wkb.o \ 68 | liblwgeom/ptarray.o \ 69 | liblwgeom/lwout_wkb.o \ 70 | liblwgeom/lwpoly.o \ 71 | liblwgeom/lwpoint.o \ 72 | liblwgeom/lwout_gml.o \ 73 | liblwgeom/lwgeom_topo.o \ 74 | liblwgeom/lwcircstring.o \ 75 | liblwgeom/lwin_wkt_parse.o 76 | 77 | OBJECTS_RCPP= \ 78 | geodetic.o \ 79 | lwgeom.o \ 80 | RcppExports.o \ 81 | proj.o \ 82 | geos.o \ 83 | io.o \ 84 | sub.o 85 | 86 | OBJECTS=@OBJECTS@ 87 | -------------------------------------------------------------------------------- /src/Makevars.ucrt: -------------------------------------------------------------------------------- 1 | STATLIB = liblwgeom/liblwgeomstatic.a 2 | 3 | OBJECTS_LIBLWGEOM= \ 4 | liblwgeom/varint.o \ 5 | liblwgeom/lwout_twkb.o \ 6 | liblwgeom/lwpsurface.o \ 7 | liblwgeom/lwtriangle.o \ 8 | liblwgeom/lwmpoly.o \ 9 | liblwgeom/lookup3.o \ 10 | liblwgeom/lwin_wkt.o \ 11 | liblwgeom/gserialized1.o \ 12 | liblwgeom/lwgeom.o \ 13 | liblwgeom/gserialized2.o \ 14 | liblwgeom/lwstroke.o \ 15 | liblwgeom/lwtin.o \ 16 | liblwgeom/lwin_twkb.o \ 17 | liblwgeom/lwgeom_geos_cluster.o \ 18 | liblwgeom/lwmsurface.o \ 19 | liblwgeom/lwgeom_wrapx.o \ 20 | liblwgeom/lwiterator.o \ 21 | liblwgeom/lwgeom_geos_node.o \ 22 | liblwgeom/lwout_geojson.o \ 23 | liblwgeom/lwgeom_debug.o \ 24 | liblwgeom/lwgeom_median.o \ 25 | liblwgeom/lwmval.o \ 26 | liblwgeom/lwkmeans.o \ 27 | liblwgeom/lwgeom_geos.o \ 28 | liblwgeom/lwout_kml.o \ 29 | liblwgeom/lwutil.o \ 30 | liblwgeom/lwprint.o \ 31 | liblwgeom/lwrandom.o \ 32 | liblwgeom/lwmline.o \ 33 | liblwgeom/lwgeodetic_tree.o \ 34 | liblwgeom/lwline.o \ 35 | liblwgeom/bytebuffer.o \ 36 | liblwgeom/lwgeodetic.o \ 37 | liblwgeom/measures.o \ 38 | liblwgeom/lwgeom_api.o \ 39 | liblwgeom/lwmcurve.o \ 40 | liblwgeom/lwcollection.o \ 41 | liblwgeom/gbox.o \ 42 | liblwgeom/lwspheroid.o \ 43 | liblwgeom/lwout_svg.o \ 44 | liblwgeom/lwin_encoded_polyline.o \ 45 | liblwgeom/lwout_encoded_polyline.o \ 46 | liblwgeom/lwgeom_geos_split.o \ 47 | liblwgeom/effectivearea.o \ 48 | liblwgeom/lwboundingcircle.o \ 49 | liblwgeom/lwcurvepoly.o \ 50 | liblwgeom/lwlinearreferencing.o \ 51 | liblwgeom/lwunionfind.o \ 52 | liblwgeom/lwchaikins.o \ 53 | liblwgeom/lwalgorithm.o \ 54 | liblwgeom/lwhomogenize.o \ 55 | liblwgeom/lwgeom_geos_clean.o \ 56 | liblwgeom/measures3d.o \ 57 | liblwgeom/lwout_x3d.o \ 58 | liblwgeom/lwgeom_transform.o \ 59 | liblwgeom/lwin_wkt_lex.o \ 60 | liblwgeom/lwmpoint.o \ 61 | liblwgeom/stringbuffer.o \ 62 | liblwgeom/lwcompound.o \ 63 | liblwgeom/gserialized.o \ 64 | liblwgeom/lwout_wkt.o \ 65 | liblwgeom/lwin_wkb.o \ 66 | liblwgeom/ptarray.o \ 67 | liblwgeom/lwout_wkb.o \ 68 | liblwgeom/lwpoly.o \ 69 | liblwgeom/lwpoint.o \ 70 | liblwgeom/lwout_gml.o \ 71 | liblwgeom/lwgeom_topo.o \ 72 | liblwgeom/lwcircstring.o \ 73 | liblwgeom/lwin_wkt_parse.o 74 | 75 | PKG_CPPFLAGS = -I./liblwgeom -DUSE_PROJ_H -DHAVE_LIBLWGEOM_INTERNAL_H 76 | PKG_LIBS = -L./liblwgeom -llwgeomstatic 77 | 78 | ifeq (,$(shell pkg-config --version 2>/dev/null)) 79 | 80 | #PKG_LIBS = \ 81 | # -L./liblwgeom -llwgeomstatic \ 82 | # -lxml2 -lgeos_c -lgeos -ljson-c -lssl -lcrypto -lcurl -lbcrypt -lrtmp -lssl -lssh2 -lidn2 \ 83 | # -lunistring -liconv -lgcrypt -lcrypto -lgpg-error -lws2_32 -lssl -lssh2 -liconv \ 84 | # -lcrypto -lws2_32 -ltiff -llzma -ljpeg -lz -lgeotiff -ltiff -lproj -lgeotiff -ltiff -lcurl \ 85 | # -lsqlite3 -lcrypt32 -lwldap32 86 | 87 | LIBSHARPYUV = $(or $(and $(wildcard $(R_TOOLS_SOFT)/lib/libsharpyuv.a),-lsharpyuv),) 88 | 89 | PKG_LIBS += \ 90 | -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 91 | else 92 | PKG_LIBS += $(shell pkg-config --libs geos proj) 93 | endif 94 | 95 | all: clean winlibs 96 | 97 | winlibs: 98 | cp postgis_config.win postgis_config.h 99 | mkdir -p ../inst 100 | cp -r "$(R_TOOLS_SOFT)/share/gdal" ../inst/ 101 | cp -r "$(R_TOOLS_SOFT)/share/proj" ../inst/ 102 | 103 | $(SHLIB): $(STATLIB) 104 | 105 | $(STATLIB): $(OBJECTS_LIBLWGEOM) 106 | 107 | $(OBJECTS_LIBLWGEOM): winlibs 108 | 109 | CXX_STD = CXX 110 | 111 | clean: 112 | rm -f $(SHLIB) $(OBJECTS) 113 | 114 | .PHONY: all winlibs clean 115 | -------------------------------------------------------------------------------- /src/Makevars.win: -------------------------------------------------------------------------------- 1 | CXX_STD = CXX 2 | STATLIB = liblwgeom/liblwgeomstatic.a 3 | OBJECTS_LIBLWGEOM= \ 4 | liblwgeom/varint.o \ 5 | liblwgeom/lwout_twkb.o \ 6 | liblwgeom/lwpsurface.o \ 7 | liblwgeom/lwtriangle.o \ 8 | liblwgeom/lwmpoly.o \ 9 | liblwgeom/lookup3.o \ 10 | liblwgeom/lwin_wkt.o \ 11 | liblwgeom/gserialized1.o \ 12 | liblwgeom/lwgeom.o \ 13 | liblwgeom/gserialized2.o \ 14 | liblwgeom/lwstroke.o \ 15 | liblwgeom/lwtin.o \ 16 | liblwgeom/lwin_twkb.o \ 17 | liblwgeom/lwgeom_geos_cluster.o \ 18 | liblwgeom/lwmsurface.o \ 19 | liblwgeom/lwgeom_wrapx.o \ 20 | liblwgeom/lwiterator.o \ 21 | liblwgeom/lwgeom_geos_node.o \ 22 | liblwgeom/lwout_geojson.o \ 23 | liblwgeom/lwgeom_debug.o \ 24 | liblwgeom/lwgeom_median.o \ 25 | liblwgeom/lwmval.o \ 26 | liblwgeom/lwkmeans.o \ 27 | liblwgeom/lwgeom_geos.o \ 28 | liblwgeom/lwout_kml.o \ 29 | liblwgeom/lwutil.o \ 30 | liblwgeom/lwprint.o \ 31 | liblwgeom/lwrandom.o \ 32 | liblwgeom/lwmline.o \ 33 | liblwgeom/lwgeodetic_tree.o \ 34 | liblwgeom/lwline.o \ 35 | liblwgeom/bytebuffer.o \ 36 | liblwgeom/lwgeodetic.o \ 37 | liblwgeom/measures.o \ 38 | liblwgeom/lwgeom_api.o \ 39 | liblwgeom/lwmcurve.o \ 40 | liblwgeom/lwcollection.o \ 41 | liblwgeom/gbox.o \ 42 | liblwgeom/lwspheroid.o \ 43 | liblwgeom/lwout_svg.o \ 44 | liblwgeom/lwin_encoded_polyline.o \ 45 | liblwgeom/lwout_encoded_polyline.o \ 46 | liblwgeom/lwgeom_geos_split.o \ 47 | liblwgeom/effectivearea.o \ 48 | liblwgeom/lwboundingcircle.o \ 49 | liblwgeom/lwcurvepoly.o \ 50 | liblwgeom/lwlinearreferencing.o \ 51 | liblwgeom/lwunionfind.o \ 52 | liblwgeom/lwchaikins.o \ 53 | liblwgeom/lwalgorithm.o \ 54 | liblwgeom/lwhomogenize.o \ 55 | liblwgeom/lwgeom_geos_clean.o \ 56 | liblwgeom/measures3d.o \ 57 | liblwgeom/lwout_x3d.o \ 58 | liblwgeom/lwgeom_transform.o \ 59 | liblwgeom/lwin_wkt_lex.o \ 60 | liblwgeom/lwmpoint.o \ 61 | liblwgeom/stringbuffer.o \ 62 | liblwgeom/lwcompound.o \ 63 | liblwgeom/gserialized.o \ 64 | liblwgeom/lwout_wkt.o \ 65 | liblwgeom/lwin_wkb.o \ 66 | liblwgeom/ptarray.o \ 67 | liblwgeom/lwout_wkb.o \ 68 | liblwgeom/lwpoly.o \ 69 | liblwgeom/lwpoint.o \ 70 | liblwgeom/lwout_gml.o \ 71 | liblwgeom/lwgeom_topo.o \ 72 | liblwgeom/lwcircstring.o \ 73 | liblwgeom/lwin_wkt_parse.o 74 | 75 | VERSION = 3.2.1 76 | RWINLIB = ../windows/gdal3-$(VERSION) 77 | TARGET = lib$(subst gcc,,$(COMPILED_BY))$(R_ARCH) 78 | 79 | PKG_CPPFLAGS = \ 80 | -I./liblwgeom \ 81 | -I$(RWINLIB)/include/geos-3.9.0 \ 82 | -I$(RWINLIB)/include/proj-7.2.1 \ 83 | -DUSE_PROJ_H \ 84 | -DHAVE_LIBLWGEOM_INTERNAL_H 85 | 86 | PKG_LIBS = \ 87 | -L./liblwgeom -llwgeomstatic \ 88 | -L$(RWINLIB)/$(TARGET) \ 89 | -L$(RWINLIB)/lib$(R_ARCH)$(CRT) \ 90 | -lproj -lgeos_c -lgeos -ljson-c -lexpat -lxml2 -liconv -lsqlite3 \ 91 | -ltiff -ljpeg -lcurl -lssh2 -lz -lssl -lcrypto -lgdi32 -lws2_32 -lcrypt32 -lwldap32 92 | 93 | all: clean winlibs 94 | 95 | $(SHLIB): $(STATLIB) 96 | 97 | $(STATLIB): $(OBJECTS_LIBLWGEOM) 98 | 99 | $(OBJECTS_LIBLWGEOM): winlibs 100 | 101 | clean: 102 | rm -f $(SHLIB) $(OBJECTS) $(STATLIB) $(OBJECTS_LIBLWGEOM) 103 | 104 | winlibs: 105 | cp postgis_config.win postgis_config.h 106 | mkdir -p ../inst 107 | "${R_HOME}/bin${R_ARCH_BIN}/Rscript.exe" --vanilla "../tools/winlibs.R" $(VERSION) 108 | # cp -r $(RWINLIB)/share/proj ../inst/ 109 | 110 | .PHONY: all winlibs clean 111 | -------------------------------------------------------------------------------- /src/README: -------------------------------------------------------------------------------- 1 | liblwgeom code obtained from from https://github.com/postgis/postgis 2 | git commit d9a98c5be3c8644699220729f11ed48488548bad 3 | configured with: 4 | ./configure --without-pgconfig --without-sfcgal --without-libiconv-prefix --without-libintl-prefix --without-json --without-protobuf --without-topology --without-raster 5 | 6 | removed: *_sfcgal.[ch] 7 | 8 | all diffs, registered with "diff -c | grep -v 'Only in'", are found in file DIFFS 9 | 10 | In addition: postgis_version.h, outcomment line 139 which defines 11 | POSTGIS_GEOS_VERSION; ./configure now does this on the command line. 12 | 13 | in addition: "%.*g" -> "%*g" in lwgeom_wkt.c 14 | -------------------------------------------------------------------------------- /src/geodetic.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | extern "C" { 6 | #include 7 | } 8 | 9 | using namespace Rcpp; 10 | 11 | #include "lwgeom.h" // sfc <--> lwgeom 12 | 13 | // [[Rcpp::export]] 14 | Rcpp::NumericVector CPL_geodetic_area(Rcpp::List sfc, double semi_major, double inv_flattening) { 15 | Rcpp::NumericVector ret(sfc.size()); 16 | std::vector lw = lwgeom_from_sfc(sfc); 17 | SPHEROID s; 18 | spheroid_init(&s, semi_major, semi_major * (1.0 - 1.0/inv_flattening)); 19 | for (size_t i = 0; i < lw.size(); i++) { 20 | ret[i] = lwgeom_area_spheroid(lw[i], &s); 21 | lwgeom_free(lw[i]); 22 | } 23 | return ret; 24 | } 25 | 26 | // [[Rcpp::export]] 27 | Rcpp::NumericVector CPL_geodetic_length(Rcpp::List sfc, double semi_major, double inv_flattening) { 28 | Rcpp::NumericVector ret(sfc.size()); 29 | std::vector lw = lwgeom_from_sfc(sfc); 30 | SPHEROID s; 31 | spheroid_init(&s, semi_major, semi_major * (1.0 - 1.0/inv_flattening)); 32 | for (size_t i = 0; i < lw.size(); i++) { 33 | ret[i] = lwgeom_length_spheroid(lw[i], &s); 34 | lwgeom_free(lw[i]); 35 | } 36 | return ret; 37 | } 38 | 39 | // [[Rcpp::export]] 40 | Rcpp::NumericVector CPL_geodetic_azimuth(Rcpp::List sfc, double semi_major, double inv_flattening) { 41 | if (sfc.size() < 1) 42 | stop("bearing needs at least 2 points"); // #nocov 43 | Rcpp::NumericVector ret(sfc.size() - 1); 44 | std::vector lw = lwgeom_from_sfc(sfc); 45 | SPHEROID s; 46 | spheroid_init(&s, semi_major, semi_major * (1.0 - 1.0/inv_flattening)); 47 | for (int i = 0; i < ret.size(); i++) { 48 | ret[i] = lwgeom_azumith_spheroid((LWPOINT*) lw[i], (LWPOINT*) lw[i+1], &s); 49 | lwgeom_free(lw[i]); 50 | } 51 | lwgeom_free(lw[ret.size()]); // last 52 | return ret; 53 | } 54 | 55 | // [[Rcpp::export]] 56 | Rcpp::List CPL_geodetic_segmentize(Rcpp::List sfc, double max_seg_length) { 57 | std::vector lw = lwgeom_from_sfc(sfc); 58 | for (size_t i = 0; i < lw.size(); i++) { 59 | LWGEOM *ret; 60 | ret = lwgeom_segmentize_sphere(lw[i], max_seg_length); 61 | lwgeom_free(lw[i]); 62 | lw[i] = ret; 63 | } 64 | return sfc_from_lwgeom(lw); 65 | } 66 | 67 | // [[Rcpp::export]] 68 | Rcpp::List CPL_geodetic_covers(Rcpp::List sfc1, Rcpp::List sfc2) { 69 | Rcpp::List ret(sfc1.size()); 70 | std::vector lw1 = lwgeom_from_sfc(sfc1); 71 | std::vector lw2 = lwgeom_from_sfc(sfc2); 72 | for (size_t i = 0; i < lw1.size(); i++) { 73 | std::vector idx; 74 | for (size_t j = 0; j < lw2.size(); j++) 75 | if (lwgeom_covers_lwgeom_sphere(lw1[i], lw2[j])) 76 | idx.push_back(j + 1); 77 | ret[i] = idx; 78 | } 79 | sfc_from_lwgeom(lw1); // free 80 | sfc_from_lwgeom(lw2); // free 81 | return ret; 82 | } 83 | 84 | // [[Rcpp::export]] 85 | Rcpp::List CPL_geodetic_distance(Rcpp::List sfc1, Rcpp::List sfc2, double semi_major, 86 | double inv_flattening, double tolerance, bool sparse, double semi_minor = -1.0) { 87 | Rcpp::List out(1); 88 | std::vector lw1 = lwgeom_from_sfc(sfc1); 89 | std::vector lw2 = lwgeom_from_sfc(sfc2); 90 | SPHEROID s; 91 | if (semi_minor > 0.0) 92 | spheroid_init(&s, semi_major, semi_minor); 93 | else 94 | spheroid_init(&s, semi_major, semi_major * (1.0 - 1.0/inv_flattening)); // #nocov FIXME 95 | if (sparse) { 96 | Rcpp::List lst(sfc1.size()); 97 | for (size_t i = 0; i < lw1.size(); i++) { 98 | Rcpp::IntegerVector iv; 99 | for (size_t j = 0; j < lw2.size(); j++) { 100 | if (lwgeom_distance_spheroid(lw1[i], lw2[j], &s, tolerance) <= tolerance) 101 | iv.push_back(j + 1); 102 | } 103 | lst(i) = iv; 104 | } 105 | out(0) = lst; 106 | } else { 107 | Rcpp::NumericMatrix mat(sfc1.size(), sfc2.size()); 108 | for (size_t i = 0; i < lw1.size(); i++) { 109 | for (size_t j = 0; j < lw2.size(); j++) { 110 | mat(i, j) = lwgeom_distance_spheroid(lw1[i], lw2[j], &s, tolerance); 111 | } 112 | Rcpp::checkUserInterrupt(); 113 | } 114 | out(0) = mat; 115 | } 116 | sfc_from_lwgeom(lw1); // free 117 | sfc_from_lwgeom(lw2); // free 118 | return out; 119 | } 120 | -------------------------------------------------------------------------------- /src/geos.cpp: -------------------------------------------------------------------------------- 1 | #define GEOS_USE_ONLY_R_API // prevents using non-thread-safe GEOSxx functions without _r extension. 2 | #include 3 | 4 | #include 5 | 6 | // [[Rcpp::export]] 7 | std::string CPL_geos_version(bool b = false) { 8 | return GEOS_VERSION; 9 | } 10 | -------------------------------------------------------------------------------- /src/io.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | extern "C" { 4 | #include 5 | } 6 | 7 | 8 | #define LW_MSG_MAXLEN 256 9 | 10 | // #nocov start 11 | static void io_notice(const char *fmt, va_list ap) 12 | { 13 | char msg[LW_MSG_MAXLEN+1]; 14 | vsnprintf (msg, LW_MSG_MAXLEN, fmt, ap); 15 | msg[LW_MSG_MAXLEN]='\0'; 16 | Rprintf("%s\n", msg); 17 | } 18 | 19 | static void io_debug(int level, const char *fmt, va_list ap) 20 | { 21 | } 22 | 23 | 24 | static void io_error(const char *fmt, va_list ap) 25 | { 26 | char msg[LW_MSG_MAXLEN+1]; 27 | vsnprintf (msg, LW_MSG_MAXLEN, fmt, ap); 28 | msg[LW_MSG_MAXLEN]='\0'; 29 | Rprintf("%s\n", msg); 30 | Rcpp::stop("lwgeom error"); 31 | } 32 | // #nocov end 33 | 34 | // [[Rcpp::export]] 35 | Rcpp::List CPL_init_lwgeom(Rcpp::List l) { 36 | lwgeom_set_debuglogger(io_debug); 37 | lwgeom_set_handlers(NULL, NULL, NULL, io_error, io_notice); 38 | return l; 39 | } 40 | -------------------------------------------------------------------------------- /src/liblwgeom/DIFFS: -------------------------------------------------------------------------------- 1 | Tue Jan 28 09:42:00 CET 2020 2 | source from https://download.osgeo.org/postgis/source/postgis-3.0.0.tar.gz 3 | 4 | removed files lwgeom_sfcgal.* 5 | 6 | lwutil.c: remove fprintf(), exit(), stderr 7 | lwin_wkt_lex: remove exit(); remove stderr, stdout 8 | lwgeodetic_tree.c: circ_tree_print: outcommented 9 | -------------------------------------------------------------------------------- /src/liblwgeom/bytebuffer.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright 2015 Nicklas Avén 22 | * 23 | **********************************************************************/ 24 | 25 | 26 | #ifndef _BYTEBUFFER_H 27 | #define _BYTEBUFFER_H 1 28 | 29 | #include 30 | #include 31 | #include 32 | #include "varint.h" 33 | 34 | #include "lwgeom_log.h" 35 | #define BYTEBUFFER_STARTSIZE 512 36 | #define BYTEBUFFER_STATICSIZE 1024 37 | 38 | typedef struct 39 | { 40 | size_t capacity; 41 | uint8_t *buf_start; 42 | uint8_t *writecursor; 43 | uint8_t *readcursor; 44 | uint8_t buf_static[BYTEBUFFER_STATICSIZE]; 45 | } 46 | bytebuffer_t; 47 | 48 | void bytebuffer_init_with_size(bytebuffer_t *b, size_t size); 49 | void bytebuffer_destroy_buffer(bytebuffer_t *s); 50 | void bytebuffer_append_byte(bytebuffer_t *s, const uint8_t val); 51 | void bytebuffer_append_bytebuffer(bytebuffer_t *write_to, bytebuffer_t *write_from); 52 | void bytebuffer_append_varint(bytebuffer_t *s, const int64_t val); 53 | void bytebuffer_append_uvarint(bytebuffer_t *s, const uint64_t val); 54 | size_t bytebuffer_getlength(const bytebuffer_t *s); 55 | uint8_t* bytebuffer_get_buffer_copy(const bytebuffer_t *s, size_t *buffer_length); 56 | const uint8_t* bytebuffer_get_buffer(const bytebuffer_t *s, size_t *buffer_length); 57 | 58 | /* Unused functions */ 59 | #if 0 60 | void bytebuffer_destroy(bytebuffer_t *s); 61 | bytebuffer_t *bytebuffer_create_with_size(size_t size); 62 | bytebuffer_t *bytebuffer_create(void); 63 | void bytebuffer_clear(bytebuffer_t *s); 64 | uint64_t bytebuffer_read_uvarint(bytebuffer_t *s); 65 | int64_t bytebuffer_read_varint(bytebuffer_t *s); 66 | bytebuffer_t* bytebuffer_merge(bytebuffer_t **buff_array, int nbuffers); 67 | void bytebuffer_reset_reading(bytebuffer_t *s); 68 | void bytebuffer_append_bytebuffer(bytebuffer_t *write_to,bytebuffer_t *write_from); 69 | void bytebuffer_append_bulk(bytebuffer_t *s, void * start, size_t size); 70 | void bytebuffer_append_int(bytebuffer_t *buf, const int val, int swap); 71 | void bytebuffer_append_double(bytebuffer_t *buf, const double val, int swap); 72 | #endif 73 | 74 | #endif /* _BYTEBUFFER_H */ 75 | -------------------------------------------------------------------------------- /src/liblwgeom/effectivearea.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright 2014 Nicklas Avén 22 | * 23 | **********************************************************************/ 24 | 25 | #ifndef _EFFECTIVEAREA_H 26 | #define _EFFECTIVEAREA_H 1 27 | 28 | 29 | #include "liblwgeom_internal.h" 30 | #include "lwgeom_log.h" 31 | 32 | 33 | /** 34 | 35 | This structure is placed in an array with one member per point. 36 | It has links into the minheap rtee and keeps track of eliminated points 37 | */ 38 | typedef struct 39 | { 40 | double area; 41 | int treeindex; 42 | int prev; 43 | int next; 44 | } areanode; 45 | 46 | 47 | /** 48 | 49 | This structure holds a minheap tree that is used to keep track of what points that has the smallest effective area. 50 | When eliminating points the neighbor points has its effective area affected and the minheap helps to resort efficient. 51 | */ 52 | typedef struct 53 | { 54 | int maxSize; 55 | int usedSize; 56 | areanode **key_array; 57 | } MINHEAP; 58 | 59 | 60 | /** 61 | 62 | Structure to hold pointarray and its arealist 63 | */ 64 | typedef struct 65 | { 66 | const POINTARRAY *inpts; 67 | areanode *initial_arealist; 68 | double *res_arealist; 69 | } EFFECTIVE_AREAS; 70 | 71 | 72 | EFFECTIVE_AREAS* initiate_effectivearea(const POINTARRAY *inpts); 73 | 74 | void destroy_effectivearea(EFFECTIVE_AREAS *ea); 75 | 76 | void ptarray_calc_areas(EFFECTIVE_AREAS *ea,int avoid_collaps, int set_area, double trshld); 77 | 78 | #endif /* _EFFECTIVEAREA_H */ 79 | -------------------------------------------------------------------------------- /src/liblwgeom/liblwgeom_topo_internal.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright (C) 2015 Sandro Santilli 22 | * 23 | **********************************************************************/ 24 | 25 | 26 | #ifndef LIBLWGEOM_TOPO_INTERNAL_H 27 | #define LIBLWGEOM_TOPO_INTERNAL_H 1 28 | 29 | #include "../postgis_config.h" 30 | 31 | #include "liblwgeom.h" 32 | #include "liblwgeom_topo.h" 33 | 34 | /************************************************************************ 35 | * 36 | * Generic SQL handler 37 | * 38 | ************************************************************************/ 39 | 40 | struct LWT_BE_IFACE_T 41 | { 42 | const LWT_BE_DATA *data; 43 | const LWT_BE_CALLBACKS *cb; 44 | }; 45 | 46 | const char* lwt_be_lastErrorMessage(const LWT_BE_IFACE* be); 47 | 48 | LWT_BE_TOPOLOGY * lwt_be_loadTopologyByName(LWT_BE_IFACE *be, const char *name); 49 | 50 | int lwt_be_freeTopology(LWT_TOPOLOGY *topo); 51 | 52 | LWT_ISO_NODE *lwt_be_getNodeWithinDistance2D(LWT_TOPOLOGY *topo, 53 | LWPOINT *pt, 54 | double dist, 55 | uint64_t *numelems, 56 | int fields, 57 | int64_t limit); 58 | 59 | LWT_ISO_NODE *lwt_be_getNodeById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, uint64_t *numelems, int fields); 60 | 61 | int lwt_be_ExistsCoincidentNode(LWT_TOPOLOGY* topo, LWPOINT* pt); 62 | int lwt_be_insertNodes(LWT_TOPOLOGY *topo, LWT_ISO_NODE *node, uint64_t numelems); 63 | 64 | int lwt_be_ExistsEdgeIntersectingPoint(LWT_TOPOLOGY* topo, LWPOINT* pt); 65 | 66 | LWT_ELEMID lwt_be_getNextEdgeId(LWT_TOPOLOGY* topo); 67 | LWT_ISO_EDGE *lwt_be_getEdgeById(LWT_TOPOLOGY *topo, const LWT_ELEMID *ids, uint64_t *numelems, int fields); 68 | LWT_ISO_EDGE *lwt_be_getEdgeWithinDistance2D(LWT_TOPOLOGY *topo, 69 | LWPOINT *pt, 70 | double dist, 71 | uint64_t *numelems, 72 | int fields, 73 | int64_t limit); 74 | int lwt_be_insertEdges(LWT_TOPOLOGY *topo, LWT_ISO_EDGE *edge, uint64_t numelems); 75 | int 76 | lwt_be_updateEdges(LWT_TOPOLOGY* topo, const LWT_ISO_EDGE* sel_edge, int sel_fields, const LWT_ISO_EDGE* upd_edge, int upd_fields, const LWT_ISO_EDGE* exc_edge, int exc_fields); 77 | int 78 | lwt_be_deleteEdges(LWT_TOPOLOGY* topo, const LWT_ISO_EDGE* sel_edge, int sel_fields); 79 | 80 | LWT_ELEMID lwt_be_getFaceContainingPoint(LWT_TOPOLOGY* topo, LWPOINT* pt); 81 | 82 | int lwt_be_updateTopoGeomEdgeSplit(LWT_TOPOLOGY* topo, LWT_ELEMID split_edge, LWT_ELEMID new_edge1, LWT_ELEMID new_edge2); 83 | 84 | 85 | /************************************************************************ 86 | * 87 | * Internal objects 88 | * 89 | ************************************************************************/ 90 | 91 | struct LWT_TOPOLOGY_T 92 | { 93 | const LWT_BE_IFACE *be_iface; 94 | LWT_BE_TOPOLOGY *be_topo; 95 | int32_t srid; 96 | double precision; 97 | int hasZ; 98 | }; 99 | 100 | #endif /* LIBLWGEOM_TOPO_INTERNAL_H */ 101 | -------------------------------------------------------------------------------- /src/liblwgeom/lwcurvepoly.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright (C) 2001-2006 Refractions Research Inc. 22 | * 23 | **********************************************************************/ 24 | 25 | 26 | /* basic LWCURVEPOLY manipulation */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include "liblwgeom_internal.h" 32 | #include "lwgeom_log.h" 33 | 34 | LWCURVEPOLY * 35 | lwcurvepoly_construct_empty(int32_t srid, char hasz, char hasm) 36 | { 37 | LWCURVEPOLY *ret; 38 | 39 | ret = lwalloc(sizeof(LWCURVEPOLY)); 40 | ret->type = CURVEPOLYTYPE; 41 | ret->flags = lwflags(hasz, hasm, 0); 42 | ret->srid = srid; 43 | ret->nrings = 0; 44 | ret->maxrings = 1; /* Allocate room for sub-members, just in case. */ 45 | ret->rings = lwalloc(ret->maxrings * sizeof(LWGEOM*)); 46 | ret->bbox = NULL; 47 | 48 | return ret; 49 | } 50 | 51 | LWCURVEPOLY * 52 | lwcurvepoly_construct_from_lwpoly(LWPOLY *lwpoly) 53 | { 54 | LWCURVEPOLY *ret; 55 | uint32_t i; 56 | ret = lwalloc(sizeof(LWCURVEPOLY)); 57 | ret->type = CURVEPOLYTYPE; 58 | ret->flags = lwpoly->flags; 59 | ret->srid = lwpoly->srid; 60 | ret->nrings = lwpoly->nrings; 61 | ret->maxrings = lwpoly->nrings; /* Allocate room for sub-members, just in case. */ 62 | ret->rings = lwalloc(ret->maxrings * sizeof(LWGEOM*)); 63 | ret->bbox = lwpoly->bbox ? gbox_clone(lwpoly->bbox) : NULL; 64 | for ( i = 0; i < ret->nrings; i++ ) 65 | { 66 | ret->rings[i] = lwline_as_lwgeom(lwline_construct(ret->srid, NULL, ptarray_clone_deep(lwpoly->rings[i]))); 67 | } 68 | return ret; 69 | } 70 | 71 | int lwcurvepoly_add_ring(LWCURVEPOLY *poly, LWGEOM *ring) 72 | { 73 | uint32_t i; 74 | 75 | /* Can't do anything with NULLs */ 76 | if( ! poly || ! ring ) 77 | { 78 | LWDEBUG(4,"NULL inputs!!! quitting"); 79 | return LW_FAILURE; 80 | } 81 | 82 | /* Check that we're not working with garbage */ 83 | if ( poly->rings == NULL && (poly->nrings || poly->maxrings) ) 84 | { 85 | LWDEBUG(4,"mismatched nrings/maxrings"); 86 | lwerror("Curvepolygon is in inconsistent state. Null memory but non-zero collection counts."); 87 | return LW_FAILURE; 88 | } 89 | 90 | /* Check that we're adding an allowed ring type */ 91 | if ( ! ( ring->type == LINETYPE || ring->type == CIRCSTRINGTYPE || ring->type == COMPOUNDTYPE ) ) 92 | { 93 | LWDEBUGF(4,"got incorrect ring type: %s",lwtype_name(ring->type)); 94 | return LW_FAILURE; 95 | } 96 | 97 | 98 | /* In case this is a truly empty, make some initial space */ 99 | if ( poly->rings == NULL ) 100 | { 101 | poly->maxrings = 2; 102 | poly->nrings = 0; 103 | poly->rings = lwalloc(poly->maxrings * sizeof(LWGEOM*)); 104 | } 105 | 106 | /* Allocate more space if we need it */ 107 | if ( poly->nrings == poly->maxrings ) 108 | { 109 | poly->maxrings *= 2; 110 | poly->rings = lwrealloc(poly->rings, sizeof(LWGEOM*) * poly->maxrings); 111 | } 112 | 113 | /* Make sure we don't already have a reference to this geom */ 114 | for ( i = 0; i < poly->nrings; i++ ) 115 | { 116 | if ( poly->rings[i] == ring ) 117 | { 118 | LWDEBUGF(4, "Found duplicate geometry in collection %p == %p", poly->rings[i], ring); 119 | return LW_SUCCESS; 120 | } 121 | } 122 | 123 | /* Add the ring and increment the ring count */ 124 | poly->rings[poly->nrings] = (LWGEOM*)ring; 125 | poly->nrings++; 126 | return LW_SUCCESS; 127 | } 128 | 129 | /** 130 | * This should be rewritten to make use of the curve itself. 131 | */ 132 | double 133 | lwcurvepoly_area(const LWCURVEPOLY *curvepoly) 134 | { 135 | double area = 0.0; 136 | LWPOLY *poly; 137 | if( lwgeom_is_empty((LWGEOM*)curvepoly) ) 138 | return 0.0; 139 | poly = lwcurvepoly_stroke(curvepoly, 32); 140 | area = lwpoly_area(poly); 141 | lwpoly_free(poly); 142 | return area; 143 | } 144 | 145 | 146 | double 147 | lwcurvepoly_perimeter(const LWCURVEPOLY *poly) 148 | { 149 | double result=0.0; 150 | uint32_t i; 151 | 152 | for (i=0; inrings; i++) 153 | result += lwgeom_length(poly->rings[i]); 154 | 155 | return result; 156 | } 157 | 158 | double 159 | lwcurvepoly_perimeter_2d(const LWCURVEPOLY *poly) 160 | { 161 | double result=0.0; 162 | uint32_t i; 163 | 164 | for (i=0; inrings; i++) 165 | result += lwgeom_length_2d(poly->rings[i]); 166 | 167 | return result; 168 | } 169 | -------------------------------------------------------------------------------- /src/liblwgeom/lwgeodetic_tree.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright (C) 2012-2015 Paul Ramsey 22 | * 23 | **********************************************************************/ 24 | 25 | 26 | #ifndef _LWGEODETIC_TREE_H 27 | #define _LWGEODETIC_TREE_H 1 28 | 29 | #include "lwgeodetic.h" 30 | 31 | #define CIRC_NODE_SIZE 8 32 | 33 | /** 34 | * Note that p1 and p2 are pointers into an independent POINTARRAY, do not free them. 35 | */ 36 | typedef struct circ_node 37 | { 38 | GEOGRAPHIC_POINT center; 39 | double radius; 40 | uint32_t num_nodes; 41 | struct circ_node** nodes; 42 | int edge_num; 43 | uint32_t geom_type; 44 | double d; 45 | POINT2D pt_outside; 46 | POINT2D* p1; 47 | POINT2D* p2; 48 | } CIRC_NODE; 49 | 50 | void circ_tree_print(const CIRC_NODE* node, int depth); 51 | CIRC_NODE* circ_tree_new(const POINTARRAY* pa); 52 | void circ_tree_free(CIRC_NODE* node); 53 | int circ_tree_contains_point(const CIRC_NODE* node, const POINT2D* pt, const POINT2D* pt_outside, int level, int* on_boundary); 54 | double circ_tree_distance_tree(const CIRC_NODE* n1, const CIRC_NODE* n2, const SPHEROID *spheroid, double threshold); 55 | CIRC_NODE* lwgeom_calculate_circ_tree(const LWGEOM* lwgeom); 56 | int circ_tree_get_point(const CIRC_NODE* node, POINT2D* pt); 57 | int circ_tree_get_point_outside(const CIRC_NODE* node, POINT2D* pt); 58 | 59 | #endif /* _LWGEODETIC_TREE_H */ 60 | 61 | 62 | -------------------------------------------------------------------------------- /src/liblwgeom/lwgeom_debug.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright (C) 2004 Refractions Research Inc. 22 | * 23 | **********************************************************************/ 24 | 25 | 26 | #include "lwgeom_log.h" 27 | #include "liblwgeom.h" 28 | 29 | #include 30 | #include 31 | 32 | /* Place to hold the ZM string used in other summaries */ 33 | static char tflags[6]; 34 | 35 | static char * 36 | lwgeom_flagchars(LWGEOM *lwg) 37 | { 38 | int flagno = 0; 39 | if ( FLAGS_GET_Z(lwg->flags) ) tflags[flagno++] = 'Z'; 40 | if ( FLAGS_GET_M(lwg->flags) ) tflags[flagno++] = 'M'; 41 | if ( FLAGS_GET_BBOX(lwg->flags) ) tflags[flagno++] = 'B'; 42 | if ( FLAGS_GET_GEODETIC(lwg->flags) ) tflags[flagno++] = 'G'; 43 | if ( lwg->srid != SRID_UNKNOWN ) tflags[flagno++] = 'S'; 44 | tflags[flagno] = '\0'; 45 | 46 | LWDEBUGF(4, "Flags: %s - returning %p", lwg->flags, tflags); 47 | 48 | return tflags; 49 | } 50 | 51 | /* 52 | * Returns an alloced string containing summary for the LWGEOM object 53 | */ 54 | static char * 55 | lwpoint_summary(LWPOINT *point, int offset) 56 | { 57 | char *result; 58 | char *pad=""; 59 | char *zmflags = lwgeom_flagchars((LWGEOM*)point); 60 | 61 | result = (char *)lwalloc(128+offset); 62 | 63 | snprintf(result, strlen(result), "%*.s%s[%s]", 64 | offset, pad, lwtype_name(point->type), 65 | zmflags); 66 | return result; 67 | } 68 | 69 | static char * 70 | lwline_summary(LWLINE *line, int offset) 71 | { 72 | char *result; 73 | char *pad=""; 74 | char *zmflags = lwgeom_flagchars((LWGEOM*)line); 75 | 76 | result = (char *)lwalloc(128+offset); 77 | 78 | snprintf(result, strlen(result), "%*.s%s[%s] with %d points", 79 | offset, pad, lwtype_name(line->type), 80 | zmflags, 81 | line->points->npoints); 82 | return result; 83 | } 84 | 85 | 86 | static char * 87 | lwcollection_summary(LWCOLLECTION *col, int offset) 88 | { 89 | size_t size = 128; 90 | char *result; 91 | char *tmp; 92 | uint32_t i; 93 | static char *nl = "\n"; 94 | char *pad=""; 95 | char *zmflags = lwgeom_flagchars((LWGEOM*)col); 96 | 97 | LWDEBUG(2, "lwcollection_summary called"); 98 | 99 | result = (char *)lwalloc(size); 100 | 101 | snprintf(result, strlen(result), "%*.s%s[%s] with %d element%s", 102 | offset, pad, lwtype_name(col->type), 103 | zmflags, 104 | col->ngeoms, 105 | col->ngeoms ? 106 | ( col->ngeoms > 1 ? "s:\n" : ":\n") 107 | : "s"); 108 | 109 | for (i=0; ingeoms; i++) 110 | { 111 | tmp = lwgeom_summary(col->geoms[i], offset+2); 112 | size += strlen(tmp)+1; 113 | result = lwrealloc(result, size); 114 | 115 | LWDEBUGF(4, "Reallocated %d bytes for result", size); 116 | if ( i > 0 ) strcat(result,nl); 117 | 118 | strcat(result, tmp); 119 | lwfree(tmp); 120 | } 121 | 122 | LWDEBUG(3, "lwcollection_summary returning"); 123 | 124 | return result; 125 | } 126 | 127 | static char * 128 | lwpoly_summary(LWPOLY *poly, int offset) 129 | { 130 | char tmp[256]; 131 | size_t size = 64*(poly->nrings+1)+128; 132 | char *result; 133 | uint32_t i; 134 | char *pad=""; 135 | static char *nl = "\n"; 136 | char *zmflags = lwgeom_flagchars((LWGEOM*)poly); 137 | 138 | LWDEBUG(2, "lwpoly_summary called"); 139 | 140 | result = (char *)lwalloc(size); 141 | 142 | snprintf(result, strlen(result), "%*.s%s[%s] with %i ring%s", 143 | offset, pad, lwtype_name(poly->type), 144 | zmflags, 145 | poly->nrings, 146 | poly->nrings ? 147 | ( poly->nrings > 1 ? "s:\n" : ":\n") 148 | : "s"); 149 | 150 | for (i=0; inrings; i++) 151 | { 152 | snprintf(tmp, strlen(tmp), "%s ring %i has %i points", 153 | pad, i, poly->rings[i]->npoints); 154 | if ( i > 0 ) strcat(result,nl); 155 | strcat(result,tmp); 156 | } 157 | 158 | LWDEBUG(3, "lwpoly_summary returning"); 159 | 160 | return result; 161 | } 162 | 163 | char * 164 | lwgeom_summary(const LWGEOM *lwgeom, int offset) 165 | { 166 | char *result; 167 | 168 | switch (lwgeom->type) 169 | { 170 | case POINTTYPE: 171 | return lwpoint_summary((LWPOINT *)lwgeom, offset); 172 | 173 | case CIRCSTRINGTYPE: 174 | case TRIANGLETYPE: 175 | case LINETYPE: 176 | return lwline_summary((LWLINE *)lwgeom, offset); 177 | 178 | case POLYGONTYPE: 179 | return lwpoly_summary((LWPOLY *)lwgeom, offset); 180 | 181 | case TINTYPE: 182 | case MULTISURFACETYPE: 183 | case MULTICURVETYPE: 184 | case CURVEPOLYTYPE: 185 | case COMPOUNDTYPE: 186 | case MULTIPOINTTYPE: 187 | case MULTILINETYPE: 188 | case MULTIPOLYGONTYPE: 189 | case COLLECTIONTYPE: 190 | return lwcollection_summary((LWCOLLECTION *)lwgeom, offset); 191 | default: 192 | result = (char *)lwalloc(256); 193 | snprintf(result, strlen(result), "Object is of unknown type: %d", 194 | lwgeom->type); 195 | return result; 196 | } 197 | 198 | return NULL; 199 | } 200 | -------------------------------------------------------------------------------- /src/liblwgeom/lwgeom_geos.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright 2011 Sandro Santilli 22 | * Copyright 2018 Darafei Praliaskouski 23 | * 24 | **********************************************************************/ 25 | 26 | #include "geos_c.h" 27 | 28 | #include "liblwgeom.h" 29 | #include "lwunionfind.h" 30 | 31 | /* 32 | ** Public prototypes for GEOS utility functions. 33 | */ 34 | LWGEOM* GEOS2LWGEOM(const GEOSGeometry* geom, uint8_t want3d); 35 | GEOSGeometry* LWGEOM2GEOS(const LWGEOM* g, uint8_t autofix); 36 | GEOSGeometry* GBOX2GEOS(const GBOX* g); 37 | #if POSTGIS_GEOS_VERSION < 38 38 | GEOSGeometry* LWGEOM_GEOS_buildArea(const GEOSGeometry* geom_in); 39 | GEOSGeometry* LWGEOM_GEOS_makeValid(const GEOSGeometry*); 40 | #endif 41 | 42 | GEOSGeometry* make_geos_point(double x, double y); 43 | GEOSGeometry* make_geos_segment(double x1, double y1, double x2, double y2); 44 | 45 | int cluster_intersecting(GEOSGeometry **geoms, uint32_t num_geoms, GEOSGeometry ***clusterGeoms, uint32_t *num_clusters); 46 | int cluster_within_distance(LWGEOM **geoms, uint32_t num_geoms, double tolerance, LWGEOM ***clusterGeoms, uint32_t *num_clusters); 47 | int union_dbscan(LWGEOM **geoms, uint32_t num_geoms, UNIONFIND *uf, double eps, uint32_t min_points, char **is_in_cluster_ret); 48 | 49 | POINTARRAY* ptarray_from_GEOSCoordSeq(const GEOSCoordSequence* cs, uint8_t want3d); 50 | 51 | extern char lwgeom_geos_errmsg[]; 52 | extern void lwgeom_geos_error(const char* fmt, ...); 53 | -------------------------------------------------------------------------------- /src/liblwgeom/lwgeom_log.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright 2011 Sandro Santilli 22 | * Copyright 2008 Paul Ramsey 23 | * Copyright 2007-2008 Mark Cave-Ayland 24 | * Copyright 2001-2006 Refractions Research Inc. 25 | * 26 | **********************************************************************/ 27 | 28 | 29 | #ifndef LWGEOM_LOG_H 30 | #define LWGEOM_LOG_H 1 31 | 32 | #include 33 | 34 | /* 35 | * Debug macros 36 | */ 37 | #if POSTGIS_DEBUG_LEVEL > 0 38 | 39 | /* Display a notice at the given debug level */ 40 | #define LWDEBUG(level, msg) \ 41 | do { \ 42 | if (POSTGIS_DEBUG_LEVEL >= level) \ 43 | lwdebug(level, "[%s:%s:%d] " msg, __FILE__, __func__, __LINE__); \ 44 | } while (0); 45 | 46 | /* Display a formatted notice at the given debug level 47 | * (like printf, with variadic arguments) */ 48 | #define LWDEBUGF(level, msg, ...) \ 49 | do { \ 50 | if (POSTGIS_DEBUG_LEVEL >= level) \ 51 | lwdebug(level, "[%s:%s:%d] " msg, \ 52 | __FILE__, __func__, __LINE__, __VA_ARGS__); \ 53 | } while (0); 54 | 55 | /* Display a notice and a WKT representation of a geometry 56 | * at the given debug level */ 57 | #define LWDEBUGG(level, geom, msg) \ 58 | if (POSTGIS_DEBUG_LEVEL >= level) \ 59 | do { \ 60 | size_t sz; \ 61 | char *wkt = lwgeom_to_wkt(geom, WKT_EXTENDED, 15, &sz); \ 62 | /* char *wkt = lwgeom_to_hexwkb(geom, WKT_EXTENDED, &sz); */ \ 63 | LWDEBUGF(level, msg ": %s", wkt); \ 64 | lwfree(wkt); \ 65 | } while (0); 66 | 67 | /* Display a formatted notice and a WKT representation of a geometry 68 | * at the given debug level */ 69 | #define LWDEBUGGF(level, geom, fmt, ...) \ 70 | if (POSTGIS_DEBUG_LEVEL >= level) \ 71 | do { \ 72 | size_t sz; \ 73 | char *wkt = lwgeom_to_wkt(geom, WKT_EXTENDED, 15, &sz); \ 74 | /* char *wkt = lwgeom_to_hexwkb(geom, WKT_EXTENDED, &sz); */ \ 75 | LWDEBUGF(level, fmt ": %s", __VA_ARGS__, wkt); \ 76 | lwfree(wkt); \ 77 | } while (0); 78 | 79 | #else /* POSTGIS_DEBUG_LEVEL <= 0 */ 80 | 81 | /* Empty prototype that can be optimised away by the compiler 82 | * for non-debug builds */ 83 | #define LWDEBUG(level, msg) \ 84 | ((void) 0) 85 | 86 | /* Empty prototype that can be optimised away by the compiler 87 | * for non-debug builds */ 88 | #define LWDEBUGF(level, msg, ...) \ 89 | ((void) 0) 90 | 91 | /* Empty prototype that can be optimised away by the compiler 92 | * for non-debug builds */ 93 | #define LWDEBUGG(level, geom, msg) \ 94 | ((void) 0) 95 | 96 | /* Empty prototype that can be optimised away by the compiler 97 | * for non-debug builds */ 98 | #define LWDEBUGGF(level, geom, fmt, ...) \ 99 | ((void) 0) 100 | 101 | #endif /* POSTGIS_DEBUG_LEVEL <= 0 */ 102 | 103 | /** 104 | * Write a notice out to the notice handler. 105 | * 106 | * Uses standard printf() substitutions. 107 | * Use for messages you always want output. 108 | * For debugging, use LWDEBUG() or LWDEBUGF(). 109 | * @ingroup logging 110 | */ 111 | void lwnotice(const char *fmt, ...); 112 | 113 | /** 114 | * Write a notice out to the error handler. 115 | * 116 | * Uses standard printf() substitutions. 117 | * Use for errors you always want output. 118 | * For debugging, use LWDEBUG() or LWDEBUGF(). 119 | * @ingroup logging 120 | */ 121 | void lwerror(const char *fmt, ...); 122 | 123 | /** 124 | * Write a debug message out. 125 | * Don't call this function directly, use the 126 | * macros, LWDEBUG() or LWDEBUGF(), for 127 | * efficiency. 128 | * @ingroup logging 129 | */ 130 | void lwdebug(int level, const char *fmt, ...); 131 | 132 | 133 | 134 | #endif /* LWGEOM_LOG_H */ 135 | -------------------------------------------------------------------------------- /src/liblwgeom/lwin_encoded_polyline.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright 2014 Kashif Rasul and 22 | * 23 | **********************************************************************/ 24 | 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "liblwgeom.h" 31 | #include "../postgis_config.h" 32 | 33 | LWGEOM* 34 | lwgeom_from_encoded_polyline(const char *encodedpolyline, int precision) 35 | { 36 | LWGEOM *geom = NULL; 37 | POINTARRAY *pa = NULL; 38 | int length = strlen(encodedpolyline); 39 | int idx = 0; 40 | double scale = pow(10,precision); 41 | 42 | float latitude = 0.0f; 43 | float longitude = 0.0f; 44 | 45 | pa = ptarray_construct_empty(LW_FALSE, LW_FALSE, 1); 46 | 47 | while (idx < length) { 48 | POINT4D pt; 49 | char byte = 0; 50 | 51 | int res = 0; 52 | char shift = 0; 53 | do { 54 | byte = encodedpolyline[idx++] - 63; 55 | res |= (byte & 0x1F) << shift; 56 | shift += 5; 57 | } while (byte >= 0x20); 58 | float deltaLat = ((res & 1) ? ~(res >> 1) : (res >> 1)); 59 | latitude += deltaLat; 60 | 61 | shift = 0; 62 | res = 0; 63 | do { 64 | byte = encodedpolyline[idx++] - 63; 65 | res |= (byte & 0x1F) << shift; 66 | shift += 5; 67 | } while (byte >= 0x20); 68 | float deltaLon = ((res & 1) ? ~(res >> 1) : (res >> 1)); 69 | longitude += deltaLon; 70 | 71 | pt.x = longitude/scale; 72 | pt.y = latitude/scale; 73 | pt.m = pt.z = 0.0; 74 | ptarray_append_point(pa, &pt, LW_FALSE); 75 | } 76 | 77 | geom = (LWGEOM *)lwline_construct(4326, NULL, pa); 78 | lwgeom_add_bbox(geom); 79 | 80 | return geom; 81 | } 82 | -------------------------------------------------------------------------------- /src/liblwgeom/lwin_wkt.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright (C) 2010-2015 Paul Ramsey 22 | * Copyright (C) 2011 Sandro Santilli 23 | * 24 | **********************************************************************/ 25 | 26 | #include "liblwgeom_internal.h" 27 | 28 | /* 29 | * Coordinate object to hold information about last coordinate temporarily. 30 | * We need to know how many dimensions there are at any given time. 31 | */ 32 | typedef struct 33 | { 34 | lwflags_t flags; 35 | double x; 36 | double y; 37 | double z; 38 | double m; 39 | } 40 | POINT; 41 | 42 | /* 43 | * Global that holds the final output geometry for the WKT parser. 44 | */ 45 | extern LWGEOM_PARSER_RESULT global_parser_result; 46 | extern const char *parser_error_messages[]; 47 | 48 | /* 49 | * Prototypes for the lexer 50 | */ 51 | extern void wkt_lexer_init(char *str); 52 | extern void wkt_lexer_close(void); 53 | extern int wkt_yylex_destroy(void); 54 | 55 | 56 | /* 57 | * Functions called from within the bison parser to construct geometries. 58 | */ 59 | int32_t wkt_lexer_read_srid(char *str); 60 | POINT wkt_parser_coord_2(double c1, double c2); 61 | POINT wkt_parser_coord_3(double c1, double c2, double c3); 62 | POINT wkt_parser_coord_4(double c1, double c2, double c3, double c4); 63 | POINTARRAY* wkt_parser_ptarray_add_coord(POINTARRAY *pa, POINT p); 64 | POINTARRAY* wkt_parser_ptarray_new(POINT p); 65 | LWGEOM* wkt_parser_point_new(POINTARRAY *pa, char *dimensionality); 66 | LWGEOM* wkt_parser_linestring_new(POINTARRAY *pa, char *dimensionality); 67 | LWGEOM* wkt_parser_circularstring_new(POINTARRAY *pa, char *dimensionality); 68 | LWGEOM* wkt_parser_triangle_new(POINTARRAY *pa, char *dimensionality); 69 | LWGEOM* wkt_parser_polygon_new(POINTARRAY *pa, char dimcheck); 70 | LWGEOM* wkt_parser_polygon_add_ring(LWGEOM *poly, POINTARRAY *pa, char dimcheck); 71 | LWGEOM* wkt_parser_polygon_finalize(LWGEOM *poly, char *dimensionality); 72 | LWGEOM* wkt_parser_curvepolygon_new(LWGEOM *ring); 73 | LWGEOM* wkt_parser_curvepolygon_add_ring(LWGEOM *poly, LWGEOM *ring); 74 | LWGEOM* wkt_parser_curvepolygon_finalize(LWGEOM *poly, char *dimensionality); 75 | LWGEOM* wkt_parser_compound_new(LWGEOM *element); 76 | LWGEOM* wkt_parser_compound_add_geom(LWGEOM *col, LWGEOM *geom); 77 | LWGEOM* wkt_parser_collection_new(LWGEOM *geom); 78 | LWGEOM* wkt_parser_collection_add_geom(LWGEOM *col, LWGEOM *geom); 79 | LWGEOM* wkt_parser_collection_finalize(int lwtype, LWGEOM *col, char *dimensionality); 80 | void wkt_parser_geometry_new(LWGEOM *geom, int32_t srid); 81 | -------------------------------------------------------------------------------- /src/liblwgeom/lwin_wkt_parse.h: -------------------------------------------------------------------------------- 1 | /* A Bison parser, made by GNU Bison 3.4. */ 2 | 3 | /* Bison interface for Yacc-like parsers in C 4 | 5 | Copyright (C) 1984, 1989-1990, 2000-2015, 2018-2019 Free Software Foundation, 6 | Inc. 7 | 8 | This program is free software: you can redistribute it and/or modify 9 | it under the terms of the GNU General Public License as published by 10 | the Free Software Foundation, either version 3 of the License, or 11 | (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program. If not, see . */ 20 | 21 | /* As a special exception, you may create a larger work that contains 22 | part or all of the Bison parser skeleton and distribute that work 23 | under terms of your choice, so long as that work isn't itself a 24 | parser generator using the skeleton or a modified version thereof 25 | as a parser skeleton. Alternatively, if you modify or redistribute 26 | the parser skeleton itself, you may (at your option) remove this 27 | special exception, which will cause the skeleton and the resulting 28 | Bison output files to be licensed under the GNU General Public 29 | License without this special exception. 30 | 31 | This special exception was added by the Free Software Foundation in 32 | version 2.2 of Bison. */ 33 | 34 | /* Undocumented macros, especially those whose name start with YY_, 35 | are private implementation details. Do not rely on them. */ 36 | 37 | #ifndef YY_WKT_YY_LWIN_WKT_PARSE_H_INCLUDED 38 | # define YY_WKT_YY_LWIN_WKT_PARSE_H_INCLUDED 39 | /* Debug traces. */ 40 | #ifndef YYDEBUG 41 | # define YYDEBUG 0 42 | #endif 43 | #if YYDEBUG 44 | extern int wkt_yydebug; 45 | #endif 46 | 47 | /* Token type. */ 48 | #ifndef YYTOKENTYPE 49 | # define YYTOKENTYPE 50 | enum yytokentype 51 | { 52 | POINT_TOK = 258, 53 | LINESTRING_TOK = 259, 54 | POLYGON_TOK = 260, 55 | MPOINT_TOK = 261, 56 | MLINESTRING_TOK = 262, 57 | MPOLYGON_TOK = 263, 58 | MSURFACE_TOK = 264, 59 | MCURVE_TOK = 265, 60 | CURVEPOLYGON_TOK = 266, 61 | COMPOUNDCURVE_TOK = 267, 62 | CIRCULARSTRING_TOK = 268, 63 | COLLECTION_TOK = 269, 64 | RBRACKET_TOK = 270, 65 | LBRACKET_TOK = 271, 66 | COMMA_TOK = 272, 67 | EMPTY_TOK = 273, 68 | SEMICOLON_TOK = 274, 69 | TRIANGLE_TOK = 275, 70 | TIN_TOK = 276, 71 | POLYHEDRALSURFACE_TOK = 277, 72 | DOUBLE_TOK = 278, 73 | DIMENSIONALITY_TOK = 279, 74 | SRID_TOK = 280 75 | }; 76 | #endif 77 | /* Tokens. */ 78 | #define POINT_TOK 258 79 | #define LINESTRING_TOK 259 80 | #define POLYGON_TOK 260 81 | #define MPOINT_TOK 261 82 | #define MLINESTRING_TOK 262 83 | #define MPOLYGON_TOK 263 84 | #define MSURFACE_TOK 264 85 | #define MCURVE_TOK 265 86 | #define CURVEPOLYGON_TOK 266 87 | #define COMPOUNDCURVE_TOK 267 88 | #define CIRCULARSTRING_TOK 268 89 | #define COLLECTION_TOK 269 90 | #define RBRACKET_TOK 270 91 | #define LBRACKET_TOK 271 92 | #define COMMA_TOK 272 93 | #define EMPTY_TOK 273 94 | #define SEMICOLON_TOK 274 95 | #define TRIANGLE_TOK 275 96 | #define TIN_TOK 276 97 | #define POLYHEDRALSURFACE_TOK 277 98 | #define DOUBLE_TOK 278 99 | #define DIMENSIONALITY_TOK 279 100 | #define SRID_TOK 280 101 | 102 | /* Value type. */ 103 | #if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED 104 | union YYSTYPE 105 | { 106 | #line 112 "lwin_wkt_parse.y" 107 | 108 | int integervalue; 109 | double doublevalue; 110 | char *stringvalue; 111 | LWGEOM *geometryvalue; 112 | POINT coordinatevalue; 113 | POINTARRAY *ptarrayvalue; 114 | 115 | #line 116 "lwin_wkt_parse.h" 116 | 117 | }; 118 | typedef union YYSTYPE YYSTYPE; 119 | # define YYSTYPE_IS_TRIVIAL 1 120 | # define YYSTYPE_IS_DECLARED 1 121 | #endif 122 | 123 | /* Location type. */ 124 | #if ! defined YYLTYPE && ! defined YYLTYPE_IS_DECLARED 125 | typedef struct YYLTYPE YYLTYPE; 126 | struct YYLTYPE 127 | { 128 | int first_line; 129 | int first_column; 130 | int last_line; 131 | int last_column; 132 | }; 133 | # define YYLTYPE_IS_DECLARED 1 134 | # define YYLTYPE_IS_TRIVIAL 1 135 | #endif 136 | 137 | 138 | extern YYSTYPE wkt_yylval; 139 | extern YYLTYPE wkt_yylloc; 140 | int wkt_yyparse (void); 141 | 142 | #endif /* !YY_WKT_YY_LWIN_WKT_PARSE_H_INCLUDED */ 143 | -------------------------------------------------------------------------------- /src/liblwgeom/lwmcurve.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright 2001-2006 Refractions Research Inc. 22 | * 23 | **********************************************************************/ 24 | 25 | 26 | #include 27 | #include 28 | #include 29 | #include "liblwgeom_internal.h" 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/liblwgeom/lwmline.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright 2001-2006 Refractions Research Inc. 22 | * 23 | **********************************************************************/ 24 | 25 | 26 | #include 27 | #include 28 | #include 29 | #include "liblwgeom_internal.h" 30 | 31 | void 32 | lwmline_release(LWMLINE *lwmline) 33 | { 34 | lwgeom_release(lwmline_as_lwgeom(lwmline)); 35 | } 36 | 37 | LWMLINE * 38 | lwmline_construct_empty(int32_t srid, char hasz, char hasm) 39 | { 40 | LWMLINE *ret = (LWMLINE*)lwcollection_construct_empty(MULTILINETYPE, srid, hasz, hasm); 41 | return ret; 42 | } 43 | 44 | 45 | 46 | LWMLINE* lwmline_add_lwline(LWMLINE *mobj, const LWLINE *obj) 47 | { 48 | return (LWMLINE*)lwcollection_add_lwgeom((LWCOLLECTION*)mobj, (LWGEOM*)obj); 49 | } 50 | 51 | /** 52 | * Re-write the measure ordinate (or add one, if it isn't already there) interpolating 53 | * the measure between the supplied start and end values. 54 | */ 55 | LWMLINE* 56 | lwmline_measured_from_lwmline(const LWMLINE *lwmline, double m_start, double m_end) 57 | { 58 | uint32_t i = 0; 59 | int hasm = 0, hasz = 0; 60 | double length = 0.0, length_so_far = 0.0; 61 | double m_range = m_end - m_start; 62 | LWGEOM **geoms = NULL; 63 | 64 | if ( lwmline->type != MULTILINETYPE ) 65 | { 66 | lwerror("lwmline_measured_from_lmwline: only multiline types supported"); 67 | return NULL; 68 | } 69 | 70 | hasz = FLAGS_GET_Z(lwmline->flags); 71 | hasm = 1; 72 | 73 | /* Calculate the total length of the mline */ 74 | for ( i = 0; i < lwmline->ngeoms; i++ ) 75 | { 76 | LWLINE *lwline = (LWLINE*)lwmline->geoms[i]; 77 | if ( lwline->points && lwline->points->npoints > 1 ) 78 | { 79 | length += ptarray_length_2d(lwline->points); 80 | } 81 | } 82 | 83 | if ( lwgeom_is_empty((LWGEOM*)lwmline) ) 84 | { 85 | return (LWMLINE*)lwcollection_construct_empty(MULTILINETYPE, lwmline->srid, hasz, hasm); 86 | } 87 | 88 | geoms = lwalloc(sizeof(LWGEOM*) * lwmline->ngeoms); 89 | 90 | for ( i = 0; i < lwmline->ngeoms; i++ ) 91 | { 92 | double sub_m_start, sub_m_end; 93 | double sub_length = 0.0; 94 | LWLINE *lwline = (LWLINE*)lwmline->geoms[i]; 95 | 96 | if ( lwline->points && lwline->points->npoints > 1 ) 97 | { 98 | sub_length = ptarray_length_2d(lwline->points); 99 | } 100 | 101 | sub_m_start = (m_start + m_range * length_so_far / length); 102 | sub_m_end = (m_start + m_range * (length_so_far + sub_length) / length); 103 | 104 | geoms[i] = (LWGEOM*)lwline_measured_from_lwline(lwline, sub_m_start, sub_m_end); 105 | 106 | length_so_far += sub_length; 107 | } 108 | 109 | return (LWMLINE*)lwcollection_construct(lwmline->type, lwmline->srid, NULL, lwmline->ngeoms, geoms); 110 | } 111 | 112 | void lwmline_free(LWMLINE *mline) 113 | { 114 | if (!mline) 115 | return; 116 | 117 | if (mline->bbox) 118 | lwfree(mline->bbox); 119 | 120 | if (mline->geoms) 121 | { 122 | for (uint32_t i = 0; i < mline->ngeoms; i++) 123 | if (mline->geoms[i]) 124 | lwline_free(mline->geoms[i]); 125 | lwfree(mline->geoms); 126 | } 127 | 128 | lwfree(mline); 129 | } 130 | -------------------------------------------------------------------------------- /src/liblwgeom/lwmpoint.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright (C) 2001-2006 Refractions Research Inc. 22 | * 23 | **********************************************************************/ 24 | 25 | 26 | #include 27 | #include 28 | #include 29 | #include "liblwgeom_internal.h" 30 | #include "lwgeom_log.h" 31 | 32 | void 33 | lwmpoint_release(LWMPOINT *lwmpoint) 34 | { 35 | lwgeom_release(lwmpoint_as_lwgeom(lwmpoint)); 36 | } 37 | 38 | LWMPOINT * 39 | lwmpoint_construct_empty(int32_t srid, char hasz, char hasm) 40 | { 41 | LWMPOINT *ret = (LWMPOINT*)lwcollection_construct_empty(MULTIPOINTTYPE, srid, hasz, hasm); 42 | return ret; 43 | } 44 | 45 | LWMPOINT* lwmpoint_add_lwpoint(LWMPOINT *mobj, const LWPOINT *obj) 46 | { 47 | LWDEBUG(4, "Called"); 48 | return (LWMPOINT*)lwcollection_add_lwgeom((LWCOLLECTION*)mobj, (LWGEOM*)obj); 49 | } 50 | 51 | LWMPOINT * 52 | lwmpoint_construct(int32_t srid, const POINTARRAY *pa) 53 | { 54 | uint32_t i; 55 | int hasz = ptarray_has_z(pa); 56 | int hasm = ptarray_has_m(pa); 57 | LWMPOINT *ret = (LWMPOINT*)lwcollection_construct_empty(MULTIPOINTTYPE, srid, hasz, hasm); 58 | 59 | for ( i = 0; i < pa->npoints; i++ ) 60 | { 61 | LWPOINT *lwp; 62 | POINT4D p; 63 | getPoint4d_p(pa, i, &p); 64 | lwp = lwpoint_make(srid, hasz, hasm, &p); 65 | lwmpoint_add_lwpoint(ret, lwp); 66 | } 67 | 68 | return ret; 69 | } 70 | 71 | 72 | void lwmpoint_free(LWMPOINT *mpt) 73 | { 74 | uint32_t i; 75 | 76 | if ( ! mpt ) return; 77 | 78 | if ( mpt->bbox ) 79 | lwfree(mpt->bbox); 80 | 81 | for ( i = 0; i < mpt->ngeoms; i++ ) 82 | if ( mpt->geoms && mpt->geoms[i] ) 83 | lwpoint_free(mpt->geoms[i]); 84 | 85 | if ( mpt->geoms ) 86 | lwfree(mpt->geoms); 87 | 88 | lwfree(mpt); 89 | } 90 | 91 | 92 | LWMPOINT* 93 | lwmpoint_from_lwgeom(const LWGEOM *g) 94 | { 95 | LWPOINTITERATOR* it = lwpointiterator_create(g); 96 | int has_z = lwgeom_has_z(g); 97 | int has_m = lwgeom_has_m(g); 98 | LWMPOINT* result = lwmpoint_construct_empty(g->srid, has_z, has_m); 99 | POINT4D p; 100 | 101 | while(lwpointiterator_next(it, &p)) { 102 | LWPOINT* lwp = lwpoint_make(g->srid, has_z, has_m, &p); 103 | lwmpoint_add_lwpoint(result, lwp); 104 | } 105 | 106 | lwpointiterator_destroy(it); 107 | return result; 108 | } 109 | -------------------------------------------------------------------------------- /src/liblwgeom/lwmpoly.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright (C) 2001-2006 Refractions Research Inc. 22 | * 23 | **********************************************************************/ 24 | 25 | 26 | #include 27 | #include 28 | #include 29 | #include "liblwgeom_internal.h" 30 | #include "lwgeom_log.h" 31 | 32 | 33 | void 34 | lwmpoly_release(LWMPOLY *lwmpoly) 35 | { 36 | lwgeom_release(lwmpoly_as_lwgeom(lwmpoly)); 37 | } 38 | 39 | LWMPOLY * 40 | lwmpoly_construct_empty(int32_t srid, char hasz, char hasm) 41 | { 42 | LWMPOLY *ret = (LWMPOLY*)lwcollection_construct_empty(MULTIPOLYGONTYPE, srid, hasz, hasm); 43 | return ret; 44 | } 45 | 46 | 47 | LWMPOLY* lwmpoly_add_lwpoly(LWMPOLY *mobj, const LWPOLY *obj) 48 | { 49 | return (LWMPOLY*)lwcollection_add_lwgeom((LWCOLLECTION*)mobj, (LWGEOM*)obj); 50 | } 51 | 52 | 53 | void lwmpoly_free(LWMPOLY *mpoly) 54 | { 55 | uint32_t i; 56 | if ( ! mpoly ) return; 57 | if ( mpoly->bbox ) 58 | lwfree(mpoly->bbox); 59 | 60 | for ( i = 0; i < mpoly->ngeoms; i++ ) 61 | if ( mpoly->geoms && mpoly->geoms[i] ) 62 | lwpoly_free(mpoly->geoms[i]); 63 | 64 | if ( mpoly->geoms ) 65 | lwfree(mpoly->geoms); 66 | 67 | lwfree(mpoly); 68 | } 69 | 70 | -------------------------------------------------------------------------------- /src/liblwgeom/lwmsurface.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright (C) 2001-2006 Refractions Research Inc. 22 | * 23 | **********************************************************************/ 24 | 25 | 26 | #include 27 | #include 28 | #include 29 | #include "liblwgeom_internal.h" 30 | #include "lwgeom_log.h" 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/liblwgeom/lwout_encoded_polyline.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright 2014 Kashif Rasul and 22 | * Shoaib Burq 23 | * 24 | **********************************************************************/ 25 | 26 | #include "stringbuffer.h" 27 | #include "liblwgeom_internal.h" 28 | 29 | static char* lwline_to_encoded_polyline(const LWLINE*, int precision); 30 | static char* lwmmpoint_to_encoded_polyline(const LWMPOINT*, int precision); 31 | static char* pointarray_to_encoded_polyline(const POINTARRAY*, int precision); 32 | 33 | /* takes a GEOMETRY and returns an Encoded Polyline representation */ 34 | extern char* 35 | lwgeom_to_encoded_polyline(const LWGEOM* geom, int precision) 36 | { 37 | int type = geom->type; 38 | switch (type) 39 | { 40 | case LINETYPE: 41 | return lwline_to_encoded_polyline((LWLINE*)geom, precision); 42 | case MULTIPOINTTYPE: 43 | return lwmmpoint_to_encoded_polyline((LWMPOINT*)geom, precision); 44 | default: 45 | lwerror("lwgeom_to_encoded_polyline: '%s' geometry type not supported", 46 | lwtype_name(type)); 47 | return NULL; 48 | } 49 | } 50 | 51 | static char* 52 | lwline_to_encoded_polyline(const LWLINE* line, int precision) 53 | { 54 | return pointarray_to_encoded_polyline(line->points, precision); 55 | } 56 | 57 | static char* 58 | lwmmpoint_to_encoded_polyline(const LWMPOINT* mpoint, int precision) 59 | { 60 | LWLINE* line = lwline_from_lwmpoint(mpoint->srid, mpoint); 61 | char* encoded_polyline = lwline_to_encoded_polyline(line, precision); 62 | 63 | lwline_free(line); 64 | return encoded_polyline; 65 | } 66 | 67 | static char* 68 | pointarray_to_encoded_polyline(const POINTARRAY* pa, int precision) 69 | { 70 | uint32_t i; 71 | const POINT2D* prevPoint; 72 | int* delta; 73 | char* encoded_polyline = NULL; 74 | stringbuffer_t* sb; 75 | double scale = pow(10, precision); 76 | 77 | /* Empty input is empty string */ 78 | if (pa->npoints == 0) { 79 | encoded_polyline = lwalloc(1 * sizeof(char)); 80 | encoded_polyline[0] = 0; 81 | return encoded_polyline; 82 | } 83 | 84 | delta = lwalloc(2 * sizeof(int) * pa->npoints); 85 | 86 | /* Take the double value and multiply it by 1x10^precision, rounding the 87 | * result */ 88 | prevPoint = getPoint2d_cp(pa, 0); 89 | delta[0] = round(prevPoint->y * scale); 90 | delta[1] = round(prevPoint->x * scale); 91 | 92 | /* Points only include the offset from the previous point */ 93 | for (i = 1; i < pa->npoints; i++) 94 | { 95 | const POINT2D* point = getPoint2d_cp(pa, i); 96 | delta[2 * i] = round(point->y * scale) - round(prevPoint->y * scale); 97 | delta[(2 * i) + 1] = 98 | round(point->x * scale) - round(prevPoint->x * scale); 99 | prevPoint = point; 100 | } 101 | 102 | /* value to binary: a negative value must be calculated using its two's 103 | * complement */ 104 | for (i = 0; i < pa->npoints * 2; i++) 105 | { 106 | /* Multiply by 2 for a signed left shift */ 107 | delta[i] *= 2; 108 | /* if value is negative, invert this encoding */ 109 | if (delta[i] < 0) { 110 | delta[i] = ~(delta[i]); 111 | } 112 | } 113 | 114 | sb = stringbuffer_create(); 115 | for (i = 0; i < pa->npoints * 2; i++) 116 | { 117 | int numberToEncode = delta[i]; 118 | 119 | while (numberToEncode >= 0x20) 120 | { 121 | /* Place the 5-bit chunks into reverse order or 122 | each value with 0x20 if another bit chunk follows and add 63*/ 123 | int nextValue = (0x20 | (numberToEncode & 0x1f)) + 63; 124 | stringbuffer_aprintf(sb, "%c", (char)nextValue); 125 | 126 | /* Break the binary value out into 5-bit chunks */ 127 | numberToEncode >>= 5; 128 | } 129 | 130 | numberToEncode += 63; 131 | stringbuffer_aprintf(sb, "%c", (char)numberToEncode); 132 | } 133 | 134 | lwfree(delta); 135 | encoded_polyline = stringbuffer_getstringcopy(sb); 136 | stringbuffer_destroy(sb); 137 | 138 | return encoded_polyline; 139 | } 140 | -------------------------------------------------------------------------------- /src/liblwgeom/lwout_twkb.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright 2013 Nicklas Avén 22 | * 23 | **********************************************************************/ 24 | 25 | 26 | /********************************************************************** 27 | * 28 | * PostGIS - Spatial Types for PostgreSQL 29 | * http://postgis.net 30 | * Copyright 2013 Nicklas Avén 31 | * 32 | * This is free software; you can redistribute and/or modify it under 33 | * the terms of the GNU General Public Licence. See the COPYING file. 34 | * 35 | **********************************************************************/ 36 | 37 | #include "liblwgeom_internal.h" 38 | #include "lwgeom_log.h" 39 | #include 40 | #include "bytebuffer.h" 41 | 42 | /* Maximum number of geometry dimmensions that internal arrays can hold */ 43 | #define MAX_N_DIMS 4 44 | 45 | #define MAX_BBOX_SIZE 64 46 | #define MAX_SIZE_SIZE 8 47 | 48 | 49 | /** 50 | * Header true/false flags 51 | */ 52 | 53 | #define FIRST_BYTE_SET_BBOXES(flag, bool) ((flag) = ((bool) ? (flag) | 0x01 : (flag) & (~0x01))) 54 | #define FIRST_BYTE_SET_SIZES(flag, bool) ((flag) = ((bool) ? (flag) | 0x02 : (flag) & (~0x02))) 55 | #define FIRST_BYTE_SET_IDLIST(flag, bool) ((flag) = ((bool) ? (flag) | 0x04 : (flag) & (~0x04))) 56 | #define FIRST_BYTE_SET_EXTENDED(flag, bool) ((flag) = ((bool) ? (flag) | 0x08 : (flag) & (~0x08))) 57 | #define FIRST_BYTE_SET_EMPTY(flag, bool) ((flag) = ((bool) ? (flag) | 0x10 : (flag) & (~0x10))) 58 | 59 | 60 | /** 61 | * Macros for manipulating the 'type_precision' int. An int8_t used as follows: 62 | * Type 4 bits 63 | * Precision 4 bits 64 | */ 65 | 66 | #define TYPE_PREC_SET_TYPE(flag, type) ((flag) = ((flag) & 0xF0) | (((type) & 0x0F))) 67 | #define TYPE_PREC_SET_PREC(flag, prec) ((flag) = ((flag) & 0x0F) | (((prec) & 0x0F) << 4)) 68 | 69 | #define HIGHER_DIM_SET_HASZ(flag, bool) ((flag) = ((bool) ? (flag) | 0x01 : (flag) & (~0x01))) 70 | #define HIGHER_DIM_SET_HASM(flag, bool) ((flag) = ((bool) ? (flag) | 0x02 : (flag) & (~0x02))) 71 | 72 | #define HIGHER_DIM_SET_PRECZ(flag, prec) ((flag) = ((flag) & 0xE3) | (((prec) & 0x07) << 2)) 73 | #define HIGHER_DIM_SET_PRECM(flag, prec) ((flag) = ((flag) & 0x1F) | (((prec) & 0x07) << 5)) 74 | 75 | typedef struct 76 | { 77 | /* Options defined at start */ 78 | uint8_t variant; 79 | int8_t prec_xy; 80 | int8_t prec_z; 81 | int8_t prec_m; 82 | float factor[4]; /*What factor to multiply the coordiinates with to get the requested precision*/ 83 | } TWKB_GLOBALS; 84 | 85 | typedef struct 86 | { 87 | uint8_t variant; /*options that change at runtime*/ 88 | bytebuffer_t *header_buf; 89 | bytebuffer_t *geom_buf; 90 | int hasz; 91 | int hasm; 92 | const int64_t *idlist; 93 | int64_t bbox_min[MAX_N_DIMS]; 94 | int64_t bbox_max[MAX_N_DIMS]; 95 | int64_t accum_rels[MAX_N_DIMS]; /*Holds the acculmulated relative values*/ 96 | } TWKB_STATE; 97 | 98 | static int lwgeom_to_twkb_buf(const LWGEOM *geom, TWKB_GLOBALS *global_values, TWKB_STATE *ts); 99 | 100 | static int lwpoint_to_twkb_buf(const LWPOINT *line, TWKB_GLOBALS *global_values, TWKB_STATE *ts); 101 | static int lwline_to_twkb_buf(const LWLINE *line, TWKB_GLOBALS *global_values, TWKB_STATE *ts); 102 | static int lwpoly_to_twkb_buf(const LWPOLY *poly, TWKB_GLOBALS *global_values, TWKB_STATE *ts); 103 | static int lwcollection_to_twkb_buf(const LWCOLLECTION *col, TWKB_GLOBALS *global_values, TWKB_STATE *ts); 104 | static int lwgeom_write_to_buffer(const LWGEOM *geom, TWKB_GLOBALS *global_values, TWKB_STATE *parent_state); 105 | 106 | -------------------------------------------------------------------------------- /src/liblwgeom/lwout_x3d.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright 2011-2017 Arrival 3D, Regina Obe 22 | * 23 | **********************************************************************/ 24 | 25 | /** 26 | * @file X3D output routines. 27 | * 28 | **********************************************************************/ 29 | #include 30 | #include "liblwgeom_internal.h" 31 | #include "stringbuffer.h" 32 | 33 | /** defid is the id of the coordinate can be used to hold other elements DEF='abc' transform='' etc. **/ 34 | static int lwgeom_to_x3d3_sb(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb); 35 | 36 | static int asx3d3_point_sb(const LWPOINT *point, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb); 37 | static int asx3d3_line_sb(const LWLINE *line, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb); 38 | 39 | static int asx3d3_triangle_sb(const LWTRIANGLE *triangle, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb); 40 | 41 | static int asx3d3_multi_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb); 42 | static int asx3d3_psurface_sb(const LWPSURFACE *psur, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb); 43 | static int asx3d3_tin_sb(const LWTIN *tin, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb); 44 | 45 | static int asx3d3_collection_sb(const LWCOLLECTION *col, char *srs, int precision, int opts, const char *defid, stringbuffer_t *sb); 46 | static int ptarray_to_x3d3_sb(POINTARRAY *pa, int precision, int opts, int is_closed, stringbuffer_t *sb ); 47 | -------------------------------------------------------------------------------- /src/liblwgeom/lwpsurface.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright (C) 2001-2006 Refractions Research Inc. 22 | * 23 | **********************************************************************/ 24 | 25 | 26 | #include 27 | #include 28 | #include 29 | #include "liblwgeom_internal.h" 30 | #include "lwgeom_log.h" 31 | 32 | 33 | LWPSURFACE* lwpsurface_add_lwpoly(LWPSURFACE *mobj, const LWPOLY *obj) 34 | { 35 | return (LWPSURFACE*)lwcollection_add_lwgeom((LWCOLLECTION*)mobj, (LWGEOM*)obj); 36 | } 37 | 38 | 39 | void lwpsurface_free(LWPSURFACE *psurf) 40 | { 41 | uint32_t i; 42 | if ( ! psurf ) return; 43 | if ( psurf->bbox ) 44 | lwfree(psurf->bbox); 45 | 46 | for ( i = 0; i < psurf->ngeoms; i++ ) 47 | if ( psurf->geoms && psurf->geoms[i] ) 48 | lwpoly_free(psurf->geoms[i]); 49 | 50 | if ( psurf->geoms ) 51 | lwfree(psurf->geoms); 52 | 53 | lwfree(psurf); 54 | } 55 | 56 | 57 | void printLWPSURFACE(LWPSURFACE *psurf) 58 | { 59 | uint32_t i, j; 60 | LWPOLY *patch; 61 | 62 | if (psurf->type != POLYHEDRALSURFACETYPE) 63 | lwerror("printLWPSURFACE called with something else than a POLYHEDRALSURFACE"); 64 | 65 | lwnotice("LWPSURFACE {"); 66 | lwnotice(" ndims = %i", (int)FLAGS_NDIMS(psurf->flags)); 67 | lwnotice(" SRID = %i", (int)psurf->srid); 68 | lwnotice(" ngeoms = %i", (int)psurf->ngeoms); 69 | 70 | for (i=0; ingeoms; i++) 71 | { 72 | patch = (LWPOLY *) psurf->geoms[i]; 73 | for (j=0; jnrings; j++) 74 | { 75 | lwnotice(" RING # %i :",j); 76 | printPA(patch->rings[j]); 77 | } 78 | } 79 | lwnotice("}"); 80 | } 81 | 82 | 83 | 84 | 85 | /* 86 | * TODO rewrite all this stuff to be based on a truly topological model 87 | */ 88 | 89 | struct struct_psurface_arcs 90 | { 91 | double ax, ay, az; 92 | double bx, by, bz; 93 | uint32_t cnt, face; 94 | }; 95 | typedef struct struct_psurface_arcs *psurface_arcs; 96 | 97 | /* We supposed that the geometry is valid 98 | we could have wrong result if not */ 99 | int lwpsurface_is_closed(const LWPSURFACE *psurface) 100 | { 101 | uint32_t i, j, k; 102 | uint32_t narcs, carc; 103 | int found; 104 | psurface_arcs arcs; 105 | POINT4D pa, pb; 106 | LWPOLY *patch; 107 | 108 | /* If surface is not 3D, it's can't be closed */ 109 | if (!FLAGS_GET_Z(psurface->flags)) return 0; 110 | 111 | /* If surface is less than 4 faces hard to be closed too */ 112 | if (psurface->ngeoms < 4) return 0; 113 | 114 | /* Max theoretical arcs number if no one is shared ... */ 115 | for (i=0, narcs=0 ; i < psurface->ngeoms ; i++) 116 | { 117 | patch = (LWPOLY *) psurface->geoms[i]; 118 | narcs += patch->rings[0]->npoints - 1; 119 | } 120 | 121 | arcs = lwalloc(sizeof(struct struct_psurface_arcs) * narcs); 122 | for (i=0, carc=0; i < psurface->ngeoms ; i++) 123 | { 124 | 125 | patch = (LWPOLY *) psurface->geoms[i]; 126 | for (j=0; j < patch->rings[0]->npoints - 1; j++) 127 | { 128 | 129 | getPoint4d_p(patch->rings[0], j, &pa); 130 | getPoint4d_p(patch->rings[0], j+1, &pb); 131 | 132 | /* remove redundant points if any */ 133 | if (pa.x == pb.x && pa.y == pb.y && pa.z == pb.z) continue; 134 | 135 | /* Make sure to order the 'lower' point first */ 136 | if ( (pa.x > pb.x) || 137 | (pa.x == pb.x && pa.y > pb.y) || 138 | (pa.x == pb.x && pa.y == pb.y && pa.z > pb.z) ) 139 | { 140 | pa = pb; 141 | getPoint4d_p(patch->rings[0], j, &pb); 142 | } 143 | 144 | for (found=0, k=0; k < carc ; k++) 145 | { 146 | 147 | if ( ( arcs[k].ax == pa.x && arcs[k].ay == pa.y && 148 | arcs[k].az == pa.z && arcs[k].bx == pb.x && 149 | arcs[k].by == pb.y && arcs[k].bz == pb.z && 150 | arcs[k].face != i) ) 151 | { 152 | arcs[k].cnt++; 153 | found = 1; 154 | 155 | /* Look like an invalid PolyhedralSurface 156 | anyway not a closed one */ 157 | if (arcs[k].cnt > 2) 158 | { 159 | lwfree(arcs); 160 | return 0; 161 | } 162 | } 163 | } 164 | 165 | if (!found) 166 | { 167 | arcs[carc].cnt=1; 168 | arcs[carc].face=i; 169 | arcs[carc].ax = pa.x; 170 | arcs[carc].ay = pa.y; 171 | arcs[carc].az = pa.z; 172 | arcs[carc].bx = pb.x; 173 | arcs[carc].by = pb.y; 174 | arcs[carc].bz = pb.z; 175 | carc++; 176 | 177 | /* Look like an invalid PolyhedralSurface 178 | anyway not a closed one */ 179 | if (carc > narcs) 180 | { 181 | lwfree(arcs); 182 | return 0; 183 | } 184 | } 185 | } 186 | } 187 | 188 | /* A polyhedron is closed if each edge 189 | is shared by exactly 2 faces */ 190 | for (k=0; k < carc ; k++) 191 | { 192 | if (arcs[k].cnt != 2) 193 | { 194 | lwfree(arcs); 195 | return 0; 196 | } 197 | } 198 | lwfree(arcs); 199 | 200 | /* Invalid Polyhedral case */ 201 | if (carc < psurface->ngeoms) return 0; 202 | 203 | return 1; 204 | } 205 | -------------------------------------------------------------------------------- /src/liblwgeom/lwrandom.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright 2019 Mike Taves 22 | * 23 | **********************************************************************/ 24 | 25 | #include "lwrandom.h" 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #ifdef _WIN32 33 | #include 34 | #define getpid _getpid 35 | #else 36 | #include 37 | #endif 38 | 39 | static unsigned char _lwrandom_seed_set = 0; 40 | static int32_t _lwrandom_seed[3] = {0x330e, 0xabcd, 0x1234}; 41 | 42 | /* 43 | * Set seed for a random number generator. 44 | * Repeatable numbers are generated with seed values >= 1. 45 | * When seed is zero and has not previously been set, it is based on 46 | * Unix time (seconds) and process ID. */ 47 | void 48 | lwrandom_set_seed(int32_t seed) 49 | { 50 | if (seed == 0) 51 | { 52 | if (_lwrandom_seed_set == 0) 53 | seed = (unsigned int)time(NULL) + (unsigned int)getpid() - 0xbadd; 54 | else 55 | return; 56 | } 57 | /* s1 value between 1 and 2147483562 */ 58 | _lwrandom_seed[1] = (((int64_t)seed + 0xfeed) % 2147483562) + 1; 59 | /* s2 value between 1 and 2147483398 */ 60 | _lwrandom_seed[2] = ((((int64_t)seed + 0xdefeb) << 5) % 2147483398) + 1; 61 | _lwrandom_seed_set = 1; 62 | } 63 | 64 | /* for low-level external debugging */ 65 | void 66 | _lwrandom_set_seeds(int32_t s1, int32_t s2) 67 | { 68 | /* _lwrandom_seed[0] not used */ 69 | _lwrandom_seed[1] = s1; 70 | _lwrandom_seed[2] = s2; 71 | _lwrandom_seed_set = 1; 72 | } 73 | int32_t 74 | _lwrandom_get_seed(size_t idx) 75 | { 76 | return _lwrandom_seed[idx]; 77 | } 78 | 79 | /* 80 | * Generate a random floating-point value. 81 | * Values are uniformly distributed between 0 and 1. 82 | * 83 | * Authors: 84 | * Pierre L'Ecuyer (1988), see source code in Figure 3. 85 | * C version by John Burkardt, modified by Mike Taves. 86 | * 87 | * Reference: 88 | * Pierre L'Ecuyer, 89 | * Efficient and Portable Combined Random Number Generators, 90 | * Communications of the ACM, Volume 31, Number 6, June 1988, 91 | * pages 742-751. doi:10.1145/62959.62969 92 | */ 93 | double 94 | lwrandom_uniform(void) 95 | { 96 | double value; 97 | int32_t k; 98 | int32_t z; 99 | int32_t *s1 = &_lwrandom_seed[1]; 100 | int32_t *s2 = &_lwrandom_seed[2]; 101 | 102 | k = *s1 / 53668; 103 | *s1 = 40014 * (*s1 - k * 53668) - k * 12211; 104 | if (*s1 < 0) 105 | *s1 += 2147483563; 106 | 107 | k = *s2 / 52774; 108 | *s2 = 40692 * (*s2 - k * 52774) - k * 3791; 109 | if (*s2 < 0) 110 | *s2 += 2147483399; 111 | 112 | z = *s1 - *s2; 113 | if (z < 1) 114 | z += 2147483562; 115 | 116 | value = (double)(z) / 2147483563.0; 117 | 118 | return value; 119 | } 120 | -------------------------------------------------------------------------------- /src/liblwgeom/lwrandom.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright 2019 Mike Taves 22 | * 23 | **********************************************************************/ 24 | 25 | #include 26 | #include 27 | 28 | void lwrandom_set_seed(int32_t seed); 29 | double lwrandom_uniform(void); 30 | 31 | /* for low-level external debugging */ 32 | void _lwrandom_set_seeds(int32_t s1, int32_t s2); 33 | int32_t _lwrandom_get_seed(size_t idx); 34 | -------------------------------------------------------------------------------- /src/liblwgeom/lwtin.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright (C) 2001-2006 Refractions Research Inc. 22 | * 23 | **********************************************************************/ 24 | 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | #include "liblwgeom_internal.h" 31 | #include "lwgeom_log.h" 32 | 33 | 34 | LWTIN* lwtin_add_lwtriangle(LWTIN *mobj, const LWTRIANGLE *obj) 35 | { 36 | return (LWTIN*)lwcollection_add_lwgeom((LWCOLLECTION*)mobj, (LWGEOM*)obj); 37 | } 38 | 39 | void lwtin_free(LWTIN *tin) 40 | { 41 | uint32_t i; 42 | if ( ! tin ) return; 43 | if ( tin->bbox ) 44 | lwfree(tin->bbox); 45 | 46 | for ( i = 0; i < tin->ngeoms; i++ ) 47 | if ( tin->geoms && tin->geoms[i] ) 48 | lwtriangle_free(tin->geoms[i]); 49 | 50 | if ( tin->geoms ) 51 | lwfree(tin->geoms); 52 | 53 | lwfree(tin); 54 | } 55 | 56 | 57 | void printLWTIN(LWTIN *tin) 58 | { 59 | uint32_t i; 60 | LWTRIANGLE *triangle; 61 | 62 | if (tin->type != TINTYPE) 63 | lwerror("printLWTIN called with something else than a TIN"); 64 | 65 | lwnotice("LWTIN {"); 66 | lwnotice(" ndims = %i", (int)FLAGS_NDIMS(tin->flags)); 67 | lwnotice(" SRID = %i", (int)tin->srid); 68 | lwnotice(" ngeoms = %i", (int)tin->ngeoms); 69 | 70 | for (i=0; ingeoms; i++) 71 | { 72 | triangle = (LWTRIANGLE *) tin->geoms[i]; 73 | printPA(triangle->points); 74 | } 75 | lwnotice("}"); 76 | } 77 | 78 | 79 | /* 80 | * TODO rewrite all this stuff to be based on a truly topological model 81 | */ 82 | 83 | struct struct_tin_arcs 84 | { 85 | double ax, ay, az; 86 | double bx, by, bz; 87 | uint32_t cnt, face; 88 | }; 89 | typedef struct struct_tin_arcs *tin_arcs; 90 | 91 | /* We supposed that the geometry is valid 92 | we could have wrong result if not */ 93 | int lwtin_is_closed(const LWTIN *tin) 94 | { 95 | uint32_t i, j, k; 96 | uint32_t narcs, carc; 97 | int found; 98 | tin_arcs arcs; 99 | POINT4D pa, pb; 100 | LWTRIANGLE *patch; 101 | 102 | /* If surface is not 3D, it's can't be closed */ 103 | if (!FLAGS_GET_Z(tin->flags)) return 0; 104 | 105 | /* Max theoretical arcs number if no one is shared ... */ 106 | narcs = 3 * tin->ngeoms; 107 | 108 | arcs = lwalloc(sizeof(struct struct_tin_arcs) * narcs); 109 | for (i=0, carc=0; i < tin->ngeoms ; i++) 110 | { 111 | 112 | patch = (LWTRIANGLE *) tin->geoms[i]; 113 | for (j=0; j < 3 ; j++) 114 | { 115 | 116 | getPoint4d_p(patch->points, j, &pa); 117 | getPoint4d_p(patch->points, j+1, &pb); 118 | 119 | /* Make sure to order the 'lower' point first */ 120 | if ( (pa.x > pb.x) || 121 | (pa.x == pb.x && pa.y > pb.y) || 122 | (pa.x == pb.x && pa.y == pb.y && pa.z > pb.z) ) 123 | { 124 | pa = pb; 125 | getPoint4d_p(patch->points, j, &pb); 126 | } 127 | 128 | for (found=0, k=0; k < carc ; k++) 129 | { 130 | 131 | if ( ( arcs[k].ax == pa.x && arcs[k].ay == pa.y && 132 | arcs[k].az == pa.z && arcs[k].bx == pb.x && 133 | arcs[k].by == pb.y && arcs[k].bz == pb.z && 134 | arcs[k].face != i) ) 135 | { 136 | arcs[k].cnt++; 137 | found = 1; 138 | 139 | /* Look like an invalid TIN 140 | anyway not a closed one */ 141 | if (arcs[k].cnt > 2) 142 | { 143 | lwfree(arcs); 144 | return 0; 145 | } 146 | } 147 | } 148 | 149 | if (!found) 150 | { 151 | arcs[carc].cnt=1; 152 | arcs[carc].face=i; 153 | arcs[carc].ax = pa.x; 154 | arcs[carc].ay = pa.y; 155 | arcs[carc].az = pa.z; 156 | arcs[carc].bx = pb.x; 157 | arcs[carc].by = pb.y; 158 | arcs[carc].bz = pb.z; 159 | carc++; 160 | 161 | /* Look like an invalid TIN 162 | anyway not a closed one */ 163 | if (carc > narcs) 164 | { 165 | lwfree(arcs); 166 | return 0; 167 | } 168 | } 169 | } 170 | } 171 | 172 | /* A TIN is closed if each edge 173 | is shared by exactly 2 faces */ 174 | for (k=0; k < carc ; k++) 175 | { 176 | if (arcs[k].cnt != 2) 177 | { 178 | lwfree(arcs); 179 | return 0; 180 | } 181 | } 182 | lwfree(arcs); 183 | 184 | /* Invalid TIN case */ 185 | if (carc < tin->ngeoms) return 0; 186 | 187 | return 1; 188 | } 189 | -------------------------------------------------------------------------------- /src/liblwgeom/lwunionfind.c: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright 2015 Daniel Baston 22 | * 23 | **********************************************************************/ 24 | 25 | 26 | #include "liblwgeom.h" 27 | #include "lwunionfind.h" 28 | #include 29 | #include 30 | 31 | static int cmp_int(const void *a, const void *b); 32 | static int cmp_int_ptr(const void *a, const void *b); 33 | 34 | UNIONFIND* 35 | UF_create(uint32_t N) 36 | { 37 | size_t i; 38 | UNIONFIND* uf = lwalloc(sizeof(UNIONFIND)); 39 | uf->N = N; 40 | uf->num_clusters = N; 41 | uf->clusters = lwalloc(N * sizeof(uint32_t)); 42 | uf->cluster_sizes = lwalloc(N * sizeof(uint32_t)); 43 | 44 | for (i = 0; i < N; i++) 45 | { 46 | uf->clusters[i] = i; 47 | uf->cluster_sizes[i] = 1; 48 | } 49 | 50 | return uf; 51 | } 52 | 53 | void 54 | UF_destroy(UNIONFIND* uf) 55 | { 56 | lwfree(uf->clusters); 57 | lwfree(uf->cluster_sizes); 58 | lwfree(uf); 59 | } 60 | 61 | uint32_t 62 | UF_find (UNIONFIND* uf, uint32_t i) 63 | { 64 | uint32_t base = i; 65 | while (uf->clusters[base] != base) { 66 | base = uf->clusters[base]; 67 | } 68 | 69 | while (i != base) { 70 | uint32_t next = uf->clusters[i]; 71 | uf->clusters[i] = base; 72 | i = next; 73 | } 74 | 75 | return i; 76 | } 77 | 78 | uint32_t 79 | UF_size (UNIONFIND* uf, uint32_t i) 80 | { 81 | return uf->cluster_sizes[UF_find(uf, i)]; 82 | } 83 | 84 | void 85 | UF_union(UNIONFIND* uf, uint32_t i, uint32_t j) 86 | { 87 | uint32_t a = UF_find(uf, i); 88 | uint32_t b = UF_find(uf, j); 89 | 90 | if (a == b) 91 | { 92 | return; 93 | } 94 | 95 | if (uf->cluster_sizes[a] < uf->cluster_sizes[b] || 96 | (uf->cluster_sizes[a] == uf->cluster_sizes[b] && a > b)) 97 | { 98 | uf->clusters[a] = uf->clusters[b]; 99 | uf->cluster_sizes[b] += uf->cluster_sizes[a]; 100 | uf->cluster_sizes[a] = 0; 101 | } 102 | else 103 | { 104 | uf->clusters[b] = uf->clusters[a]; 105 | uf->cluster_sizes[a] += uf->cluster_sizes[b]; 106 | uf->cluster_sizes[b] = 0; 107 | } 108 | 109 | uf->num_clusters--; 110 | } 111 | 112 | uint32_t* 113 | UF_ordered_by_cluster(UNIONFIND* uf) 114 | { 115 | size_t i; 116 | uint32_t** cluster_id_ptr_by_elem_id = lwalloc(uf->N * sizeof (uint32_t*)); 117 | uint32_t* ordered_ids = lwalloc(uf->N * sizeof (uint32_t)); 118 | 119 | for (i = 0; i < uf->N; i++) 120 | { 121 | /* Make sure each value in uf->clusters is pointing to the 122 | * root of the cluster. 123 | * */ 124 | UF_find(uf, i); 125 | cluster_id_ptr_by_elem_id[i] = &(uf->clusters[i]); 126 | } 127 | 128 | /* Sort the array of cluster id pointers, so that pointers to the 129 | * same cluster id are grouped together. 130 | * */ 131 | qsort(cluster_id_ptr_by_elem_id, uf->N, sizeof (uint32_t*), &cmp_int_ptr); 132 | 133 | /* Recover the input element ids from the cluster id pointers, so 134 | * we can return element ids grouped by cluster id. 135 | * */ 136 | for (i = 0; i < uf-> N; i++) 137 | { 138 | ordered_ids[i] = (cluster_id_ptr_by_elem_id[i] - uf->clusters); 139 | } 140 | 141 | lwfree(cluster_id_ptr_by_elem_id); 142 | return ordered_ids; 143 | } 144 | 145 | uint32_t* 146 | UF_get_collapsed_cluster_ids(UNIONFIND* uf, const char* is_in_cluster) 147 | { 148 | uint32_t* ordered_components = UF_ordered_by_cluster(uf); 149 | uint32_t* new_ids = lwalloc(uf->N * sizeof(uint32_t)); 150 | uint32_t last_old_id, current_new_id, i; 151 | char encountered_cluster = LW_FALSE; 152 | 153 | current_new_id = 0; last_old_id = 0; 154 | for (i = 0; i < uf->N; i++) 155 | { 156 | uint32_t j = ordered_components[i]; 157 | if (!is_in_cluster || is_in_cluster[j]) 158 | { 159 | uint32_t current_old_id = UF_find(uf, j); 160 | if (!encountered_cluster) 161 | { 162 | encountered_cluster = LW_TRUE; 163 | last_old_id = current_old_id; 164 | } 165 | 166 | if (current_old_id != last_old_id) 167 | current_new_id++; 168 | 169 | new_ids[j] = current_new_id; 170 | last_old_id = current_old_id; 171 | } 172 | } 173 | 174 | lwfree(ordered_components); 175 | 176 | return new_ids; 177 | } 178 | 179 | static int 180 | cmp_int(const void *a, const void *b) 181 | { 182 | if (*((uint32_t*) a) > *((uint32_t*) b)) 183 | { 184 | return 1; 185 | } 186 | else if (*((uint32_t*) a) < *((uint32_t*) b)) 187 | { 188 | return -1; 189 | } 190 | else 191 | { 192 | return 0; 193 | } 194 | } 195 | 196 | static int 197 | cmp_int_ptr(const void *a, const void *b) 198 | { 199 | int val_cmp = cmp_int(*((uint32_t**) a), *((uint32_t**) b)); 200 | if (val_cmp != 0) 201 | { 202 | return val_cmp; 203 | } 204 | if (a > b) 205 | { 206 | return 1; 207 | } 208 | if (a < b) 209 | { 210 | return -1; 211 | } 212 | return 0; 213 | } 214 | -------------------------------------------------------------------------------- /src/liblwgeom/lwunionfind.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright 2015 Daniel Baston 22 | * 23 | **********************************************************************/ 24 | 25 | 26 | #ifndef _LWUNIONFIND 27 | #define _LWUNIONFIND 1 28 | 29 | #include "liblwgeom.h" 30 | 31 | typedef struct 32 | { 33 | uint32_t* clusters; 34 | uint32_t* cluster_sizes; 35 | uint32_t num_clusters; 36 | uint32_t N; 37 | } UNIONFIND; 38 | 39 | /* Allocate a UNIONFIND structure of capacity N */ 40 | UNIONFIND* UF_create(uint32_t N); 41 | 42 | /* Release memory associated with UNIONFIND structure */ 43 | void UF_destroy(UNIONFIND* uf); 44 | 45 | /* Identify the cluster id associated with specified component id */ 46 | uint32_t UF_find(UNIONFIND* uf, uint32_t i); 47 | 48 | /* Get the size of the cluster associated with the specified component id */ 49 | uint32_t UF_size(UNIONFIND* uf, uint32_t i); 50 | 51 | /* Merge the clusters that contain the two specified component ids */ 52 | void UF_union(UNIONFIND* uf, uint32_t i, uint32_t j); 53 | 54 | /* Return an array of component ids, where components that are in the 55 | * same cluster are contiguous in the array */ 56 | uint32_t* UF_ordered_by_cluster(UNIONFIND* uf); 57 | 58 | /* Replace the cluster ids in a UNIONFIND with sequential ids starting at one. 59 | * If is_in_cluster array is provided, it will be used to skip any indexes 60 | * that are not in a cluster. 61 | * */ 62 | uint32_t* UF_get_collapsed_cluster_ids(UNIONFIND* uf, const char* is_in_cluster); 63 | 64 | #endif 65 | -------------------------------------------------------------------------------- /src/liblwgeom/measures3d.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright 2011 Nicklas Avén 22 | * Copyright 2019 Darafei Praliaskouski 23 | * 24 | **********************************************************************/ 25 | 26 | #ifndef _MEASURES3D_H 27 | #define _MEASURES3D_H 1 28 | #include 29 | #include "measures.h" 30 | 31 | #define DOT(u, v) ((u).x * (v).x + (u).y * (v).y + (u).z * (v).z) 32 | #define VECTORLENGTH(v) sqrt(((v).x * (v).x) + ((v).y * (v).y) + ((v).z * (v).z)) 33 | 34 | /** 35 | 36 | Structure used in distance-calculations 37 | */ 38 | typedef struct 39 | { 40 | double distance; /*the distance between p1 and p2*/ 41 | POINT3DZ p1; 42 | POINT3DZ p2; 43 | int mode; /*the direction of looking, if thedir = -1 then we look for 3dmaxdistance and if it is 1 then we look 44 | for 3dmindistance*/ 45 | int twisted; /*To preserve the order of incoming points to match the first and second point in 3dshortest and 46 | 3dlongest line*/ 47 | double tolerance; /*the tolerance for 3ddwithin and 3ddfullywithin*/ 48 | } DISTPTS3D; 49 | 50 | typedef struct 51 | { 52 | double x, y, z; 53 | } VECTOR3D; 54 | 55 | typedef struct 56 | { 57 | POINT3DZ pop; /*Point On Plane*/ 58 | VECTOR3D pv; /*Perpendicular normal vector*/ 59 | } PLANE3D; 60 | 61 | /* 62 | Geometry returning functions 63 | */ 64 | LWGEOM *lw_dist3d_distancepoint(const LWGEOM *lw1, const LWGEOM *lw2, int32_t srid, int mode); 65 | LWGEOM *lw_dist3d_distanceline(const LWGEOM *lw1, const LWGEOM *lw2, int32_t srid, int mode); 66 | 67 | /* 68 | Preprocessing functions 69 | */ 70 | int lw_dist3d_distribute_bruteforce(const LWGEOM *lwg1, const LWGEOM *lwg2, DISTPTS3D *dl); 71 | int lw_dist3d_recursive(const LWGEOM *lwg1, const LWGEOM *lwg2, DISTPTS3D *dl); 72 | int lw_dist3d_distribute_fast(const LWGEOM *lwg1, const LWGEOM *lwg2, DISTPTS3D *dl); 73 | 74 | /* 75 | Brute force functions 76 | */ 77 | int lw_dist3d_pt_ptarray(POINT3DZ *p, POINTARRAY *pa, DISTPTS3D *dl); 78 | int lw_dist3d_point_point(LWPOINT *point1, LWPOINT *point2, DISTPTS3D *dl); 79 | int lw_dist3d_point_line(LWPOINT *point, LWLINE *line, DISTPTS3D *dl); 80 | int lw_dist3d_point_poly(LWPOINT *point, LWPOLY *poly, DISTPTS3D *dl); 81 | int lw_dist3d_point_tri(LWPOINT *point, LWTRIANGLE *tri, DISTPTS3D *dl); 82 | 83 | int lw_dist3d_line_line(LWLINE *line1, LWLINE *line2, DISTPTS3D *dl); 84 | int lw_dist3d_line_poly(LWLINE *line, LWPOLY *poly, DISTPTS3D *dl); 85 | int lw_dist3d_line_tri(LWLINE *line, LWTRIANGLE *tri, DISTPTS3D *dl); 86 | 87 | int lw_dist3d_poly_poly(LWPOLY *poly1, LWPOLY *poly2, DISTPTS3D *dl); 88 | int lw_dist3d_poly_tri(LWPOLY *poly, LWTRIANGLE *tri, DISTPTS3D *dl); 89 | 90 | int lw_dist3d_tri_tri(LWTRIANGLE *tri1, LWTRIANGLE *tri2, DISTPTS3D *dl); 91 | 92 | int lw_dist3d_pt_pt(POINT3DZ *p1, POINT3DZ *p2, DISTPTS3D *dl); 93 | int lw_dist3d_pt_seg(POINT3DZ *p, POINT3DZ *A, POINT3DZ *B, DISTPTS3D *dl); 94 | int lw_dist3d_pt_poly(POINT3DZ *p, LWPOLY *poly, PLANE3D *plane, POINT3DZ *projp, DISTPTS3D *dl); 95 | int lw_dist3d_pt_tri(POINT3DZ *p, LWTRIANGLE *tri, PLANE3D *plane, POINT3DZ *projp, DISTPTS3D *dl); 96 | 97 | int lw_dist3d_seg_seg(POINT3DZ *A, POINT3DZ *B, POINT3DZ *C, POINT3DZ *D, DISTPTS3D *dl); 98 | 99 | int lw_dist3d_ptarray_ptarray(POINTARRAY *l1, POINTARRAY *l2, DISTPTS3D *dl); 100 | int lw_dist3d_ptarray_poly(POINTARRAY *pa, LWPOLY *poly, PLANE3D *plane, DISTPTS3D *dl); 101 | int lw_dist3d_ptarray_tri(POINTARRAY *pa, LWTRIANGLE *tri, PLANE3D *plane, DISTPTS3D *dl); 102 | 103 | double project_point_on_plane(POINT3DZ *p, PLANE3D *pl, POINT3DZ *p0); 104 | int define_plane(POINTARRAY *pa, PLANE3D *pl); 105 | int pt_in_ring_3d(const POINT3DZ *p, const POINTARRAY *ring, PLANE3D *plane); 106 | 107 | /* 108 | Helper functions 109 | */ 110 | 111 | #endif /* !defined _MEASURES3D_H */ 112 | -------------------------------------------------------------------------------- /src/liblwgeom/stringbuffer.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright 2002 Thamer Alharbash 22 | * Copyright 2009 Paul Ramsey 23 | * 24 | **********************************************************************/ 25 | 26 | 27 | #ifndef _STRINGBUFFER_H 28 | #define _STRINGBUFFER_H 1 29 | 30 | #include "liblwgeom_internal.h" 31 | 32 | #include 33 | #include 34 | #include 35 | #include 36 | 37 | #define STRINGBUFFER_STARTSIZE 128 38 | 39 | typedef struct 40 | { 41 | size_t capacity; 42 | char *str_end; 43 | char *str_start; 44 | } 45 | stringbuffer_t; 46 | 47 | extern stringbuffer_t *stringbuffer_create_with_size(size_t size); 48 | extern stringbuffer_t *stringbuffer_create(void); 49 | extern void stringbuffer_init(stringbuffer_t *s); 50 | extern void stringbuffer_release(stringbuffer_t *s); 51 | extern void stringbuffer_destroy(stringbuffer_t *sb); 52 | extern void stringbuffer_clear(stringbuffer_t *sb); 53 | void stringbuffer_set(stringbuffer_t *sb, const char *s); 54 | void stringbuffer_copy(stringbuffer_t *sb, stringbuffer_t *src); 55 | extern int stringbuffer_aprintf(stringbuffer_t *sb, const char *fmt, ...); 56 | extern const char *stringbuffer_getstring(stringbuffer_t *sb); 57 | extern char *stringbuffer_getstringcopy(stringbuffer_t *sb); 58 | extern int stringbuffer_getlength(stringbuffer_t *sb); 59 | extern char stringbuffer_lastchar(stringbuffer_t *s); 60 | extern int stringbuffer_trim_trailing_white(stringbuffer_t *s); 61 | extern int stringbuffer_trim_trailing_zeroes(stringbuffer_t *s); 62 | 63 | /** 64 | * If necessary, expand the stringbuffer_t internal buffer to accommodate the 65 | * specified additional size. 66 | */ 67 | static inline void 68 | stringbuffer_makeroom(stringbuffer_t *s, size_t size_to_add) 69 | { 70 | size_t current_size = (s->str_end - s->str_start); 71 | size_t capacity = s->capacity; 72 | size_t required_size = current_size + size_to_add; 73 | 74 | while (capacity < required_size) 75 | capacity *= 2; 76 | 77 | if (capacity > s->capacity) 78 | { 79 | s->str_start = lwrealloc(s->str_start, capacity); 80 | s->capacity = capacity; 81 | s->str_end = s->str_start + current_size; 82 | } 83 | } 84 | /** 85 | * Append the specified string to the stringbuffer_t. 86 | */ 87 | inline static void 88 | stringbuffer_append(stringbuffer_t *s, const char *a) 89 | { 90 | int alen = strlen(a); /* Length of string to append */ 91 | int alen0 = alen + 1; /* Length including null terminator */ 92 | stringbuffer_makeroom(s, alen0); 93 | memcpy(s->str_end, a, alen0); 94 | s->str_end += alen; 95 | } 96 | #endif /* _STRINGBUFFER_H */ 97 | -------------------------------------------------------------------------------- /src/liblwgeom/varint.h: -------------------------------------------------------------------------------- 1 | /********************************************************************** 2 | * 3 | * PostGIS - Spatial Types for PostgreSQL 4 | * http://postgis.net 5 | * 6 | * PostGIS is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 2 of the License, or 9 | * (at your option) any later version. 10 | * 11 | * PostGIS is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with PostGIS. If not, see . 18 | * 19 | ********************************************************************** 20 | * 21 | * Copyright (C) 2014 Sandro Santilli 22 | * Copyright (C) 2013 Nicklas Avén 23 | * 24 | **********************************************************************/ 25 | 26 | 27 | #ifndef _LIBLWGEOM_VARINT_H 28 | #define _LIBLWGEOM_VARINT_H 1 29 | 30 | #include 31 | #include 32 | 33 | 34 | /* NEW SIGNATURES */ 35 | 36 | size_t varint_u32_encode_buf(uint32_t val, uint8_t *buf); 37 | size_t varint_s32_encode_buf(int32_t val, uint8_t *buf); 38 | size_t varint_u64_encode_buf(uint64_t val, uint8_t *buf); 39 | size_t varint_s64_encode_buf(int64_t val, uint8_t *buf); 40 | int64_t varint_s64_decode(const uint8_t *the_start, const uint8_t *the_end, size_t *size); 41 | uint64_t varint_u64_decode(const uint8_t *the_start, const uint8_t *the_end, size_t *size); 42 | 43 | size_t varint_size(const uint8_t *the_start, const uint8_t *the_end); 44 | 45 | /* Support from -INT{8,32,64}_MAX to INT{8,32,64}_MAX), 46 | * e.g INT8_MIN is not supported in zigzag8 */ 47 | uint64_t zigzag64(int64_t val); 48 | uint32_t zigzag32(int32_t val); 49 | uint8_t zigzag8(int8_t val); 50 | int64_t unzigzag64(uint64_t val); 51 | int32_t unzigzag32(uint32_t val); 52 | int8_t unzigzag8(uint8_t val); 53 | 54 | #endif /* !defined _LIBLWGEOM_VARINT_H */ 55 | 56 | -------------------------------------------------------------------------------- /src/lwgeom.h: -------------------------------------------------------------------------------- 1 | std::vector lwgeom_from_sfc(Rcpp::List sfc); 2 | Rcpp::List sfc_from_lwgeom(std::vector lwgeom_v); 3 | -------------------------------------------------------------------------------- /src/postgis_config.h: -------------------------------------------------------------------------------- 1 | /* src/postgis_config.h. Generated from postgis_config.h.in by configure. */ 2 | /* postgis_config.h. Generated from postgis_config.h.in by configure. */ 3 | #ifndef POSTGIS_CONFIG_H 4 | #define POSTGIS_CONFIG_H 1 5 | 6 | #include "postgis_svn_revision.h" 7 | 8 | /* Manually manipulate the POSTGIS_DEBUG_LEVEL, it is not affected by the 9 | configure process */ 10 | #define POSTGIS_DEBUG_LEVEL 0 11 | 12 | /* Define to 1 to enable memory checks in pointarray management. */ 13 | #define PARANOIA_LEVEL 0 14 | 15 | /* Define to 1 if translation of program messages to the user's native 16 | language is requested. */ 17 | #define ENABLE_NLS 1 18 | 19 | /* Define for some functions we are interested in */ 20 | #define HAVE_FSEEKO 1 21 | 22 | /* Define if the GNU gettext() function is already present or preinstalled. */ 23 | #define HAVE_GETTEXT 1 24 | 25 | /* Define if the build is big endian */ 26 | /* #undef WORDS_BIGENDIAN */ 27 | 28 | /* Define if you have the iconv() function and it works. */ 29 | #define HAVE_ICONV 1 30 | 31 | /* Define to 1 if you have the `iconvctl' function. */ 32 | /* #undef HAVE_ICONVCTL */ 33 | 34 | /* ieeefp.h header */ 35 | #define HAVE_IEEEFP_H 0 36 | 37 | /* Define to 1 if you have the `geos_c' library (-lgeos_c). */ 38 | #define HAVE_LIBGEOS_C 1 39 | 40 | /* Define to 1 if you have the `libiconvctl' function. */ 41 | /* #undef HAVE_LIBICONVCTL */ 42 | 43 | /* Define to 1 if libprotobuf-c is present */ 44 | /* #undef HAVE_LIBPROTOBUF */ 45 | 46 | /* Define to 1 if protobuf_c_version() is present */ 47 | /* #undef HAVE_PROTOBUF_C_VERSION */ 48 | 49 | /* Numeric version number for libprotobuf */ 50 | /* #undef LIBPROTOBUF_VERSION */ 51 | 52 | /* Define to 1 if libprotobuf-c is >= version 1.1 */ 53 | /* #undef HAVE_GEOBUF */ 54 | 55 | /* Define to 1 if libjson is present */ 56 | #define HAVE_LIBJSON 1 57 | 58 | /* Define to 1 if you have the `pq' library (-lpq). */ 59 | #define HAVE_LIBPQ 1 60 | 61 | /* Define to 1 if you have the `proj' library (-lproj). */ 62 | #define HAVE_LIBPROJ 1 63 | 64 | /* Define to 1 if you have the `xml2' library (-lxml2). */ 65 | #define HAVE_LIBXML2 1 66 | 67 | /* Define to 1 if you have the header file. */ 68 | #define HAVE_LIBXML_PARSER_H 1 69 | 70 | /* Define to 1 if you have the header file. */ 71 | #define HAVE_LIBXML_TREE_H 1 72 | 73 | /* Define to 1 if you have the header file. */ 74 | #define HAVE_LIBXML_XPATHINTERNALS_H 1 75 | 76 | /* Define to 1 if you have the header file. */ 77 | #define HAVE_LIBXML_XPATH_H 1 78 | 79 | /* Define to 1 if you have the header file. */ 80 | #define HAVE_UNISTD_H 1 81 | 82 | /* Define to 1 if wagyu is being built */ 83 | #define HAVE_WAGYU 1 84 | 85 | /* Define to 1 if sfcgal is being built */ 86 | /* #undef HAVE_SFCGAL */ 87 | 88 | /* Define to the sub-directory in which libtool stores uninstalled libraries. */ 89 | #define LT_OBJDIR ".libs/" 90 | 91 | /* Location of PostgreSQL locale directory */ 92 | #define PGSQL_LOCALEDIR "/usr/share/locale" 93 | 94 | /* PostGIS build date */ 95 | #define POSTGIS_BUILD_DATE "2020-01-28 17:06:21" 96 | 97 | /* SFCGAL library version at buil time */ 98 | /* #undef POSTGIS_SFCGAL_VERSION */ 99 | 100 | /* GDAL library version */ 101 | /* #undef POSTGIS_GDAL_VERSION */ 102 | 103 | /* GEOS library version */ 104 | /* #define POSTGIS_GEOS_VERSION 38 */ 105 | 106 | /* PostGIS libxml2 version */ 107 | #define POSTGIS_LIBXML2_VERSION "2.9.4" 108 | 109 | /* PostGIS library version */ 110 | #define POSTGIS_LIB_VERSION "3.0.0" 111 | 112 | /* PostGIS major version */ 113 | #define POSTGIS_MAJOR_VERSION "3" 114 | 115 | /* PostGIS minor version */ 116 | #define POSTGIS_MINOR_VERSION "0" 117 | 118 | /* PostGIS micro version */ 119 | #define POSTGIS_MICRO_VERSION "0" 120 | 121 | /* PostgreSQL server version */ 122 | #define POSTGIS_PGSQL_VERSION 100 123 | 124 | /* PROJ library version */ 125 | /* #undef POSTGIS_PROJ_VERSION */ 126 | 127 | /* PostGIS Raster build date */ 128 | /* #undef POSTGIS_RASTER_BUILD_DATE */ 129 | 130 | /* PostGIS Raster library version */ 131 | /* #undef POSTGIS_RASTER_LIB_VERSION */ 132 | 133 | /* PostGIS Raster major version */ 134 | /* #undef POSTGIS_RASTER_MAJOR_VERSION */ 135 | 136 | /* PostGIS Raster micro version */ 137 | /* #undef POSTGIS_RASTER_MICRO_VERSION */ 138 | 139 | /* PostGIS Raster minor version */ 140 | /* #undef POSTGIS_RASTER_MINOR_VERSION */ 141 | 142 | /* PostGIS Raster scripts version */ 143 | /* #undef POSTGIS_RASTER_SCRIPTS_VERSION */ 144 | 145 | /* PostGIS Raster version */ 146 | /* #undef POSTGIS_RASTER_VERSION */ 147 | 148 | /* Define to 1 if a warning is outputted every time a double is truncated */ 149 | /* #undef POSTGIS_RASTER_WARN_ON_TRUNCATION */ 150 | 151 | /* PostGIS scripts version */ 152 | #define POSTGIS_SCRIPTS_VERSION "3.0.0" 153 | 154 | 155 | /* PostGIS version */ 156 | #define POSTGIS_VERSION "3.0 USE_GEOS=1 USE_PROJ=1 USE_STATS=1" 157 | 158 | /* Define to 1 if you have the ANSI C header files. */ 159 | #define STDC_HEADERS 1 160 | 161 | /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a 162 | `char[]'. */ 163 | #define YYTEXT_POINTER 1 164 | 165 | #endif /* POSTGIS_CONFIG_H */ 166 | -------------------------------------------------------------------------------- /src/postgis_config.h.in: -------------------------------------------------------------------------------- 1 | /* postgis_config.h. Generated from postgis_config.h.in by configure. */ 2 | #ifndef POSTGIS_CONFIG_H 3 | #define POSTGIS_CONFIG_H 1 4 | 5 | #include "postgis_svn_revision.h" 6 | 7 | /* Manually manipulate the POSTGIS_DEBUG_LEVEL, it is not affected by the 8 | configure process */ 9 | #define POSTGIS_DEBUG_LEVEL 0 10 | 11 | /* Define to 1 to enable memory checks in pointarray management. */ 12 | #define PARANOIA_LEVEL 0 13 | 14 | /* Define to 1 if translation of program messages to the user's native 15 | language is requested. */ 16 | #define ENABLE_NLS 1 17 | 18 | /* Define for some functions we are interested in */ 19 | #define HAVE_FSEEKO 1 20 | 21 | /* Define if the GNU gettext() function is already present or preinstalled. */ 22 | #define HAVE_GETTEXT 1 23 | 24 | /* Define if the build is big endian */ 25 | #undef WORDS_BIGENDIAN 26 | 27 | /* Define if you have the iconv() function and it works. */ 28 | #define HAVE_ICONV 1 29 | 30 | /* Define to 1 if you have the `iconvctl' function. */ 31 | /* #undef HAVE_ICONVCTL */ 32 | 33 | /* ieeefp.h header */ 34 | #define HAVE_IEEEFP_H 0 35 | 36 | /* Define to 1 if you have the `geos_c' library (-lgeos_c). */ 37 | #define HAVE_LIBGEOS_C 1 38 | 39 | /* Define to 1 if you have the `libiconvctl' function. */ 40 | /* #undef HAVE_LIBICONVCTL */ 41 | 42 | /* Define to 1 if libprotobuf-c is present */ 43 | /* #undef HAVE_LIBPROTOBUF */ 44 | 45 | /* Define to 1 if protobuf_c_version() is present */ 46 | /* #undef HAVE_PROTOBUF_C_VERSION */ 47 | 48 | /* Numeric version number for libprotobuf */ 49 | /* #undef LIBPROTOBUF_VERSION */ 50 | 51 | /* Define to 1 if libprotobuf-c is >= version 1.1 */ 52 | /* #undef HAVE_GEOBUF */ 53 | 54 | /* Define to 1 if libjson is present */ 55 | #define HAVE_LIBJSON 1 56 | 57 | /* Define to 1 if you have the `pq' library (-lpq). */ 58 | #define HAVE_LIBPQ 1 59 | 60 | /* Define to 1 if you have the `proj' library (-lproj). */ 61 | #define HAVE_LIBPROJ 1 62 | 63 | /* Define to 1 if you have the `xml2' library (-lxml2). */ 64 | #define HAVE_LIBXML2 1 65 | 66 | /* Define to 1 if you have the header file. */ 67 | #define HAVE_LIBXML_PARSER_H 1 68 | 69 | /* Define to 1 if you have the header file. */ 70 | #define HAVE_LIBXML_TREE_H 1 71 | 72 | /* Define to 1 if you have the header file. */ 73 | #define HAVE_LIBXML_XPATHINTERNALS_H 1 74 | 75 | /* Define to 1 if you have the header file. */ 76 | #define HAVE_LIBXML_XPATH_H 1 77 | 78 | /* Define to 1 if you have the header file. */ 79 | #define HAVE_UNISTD_H 1 80 | 81 | /* Define to 1 if wagyu is being built */ 82 | #define HAVE_WAGYU 1 83 | 84 | /* Define to 1 if sfcgal is being built */ 85 | /* #undef HAVE_SFCGAL */ 86 | 87 | /* Define to the sub-directory in which libtool stores uninstalled libraries. */ 88 | #define LT_OBJDIR ".libs/" 89 | 90 | /* Location of PostgreSQL locale directory */ 91 | #define PGSQL_LOCALEDIR "/usr/share/locale" 92 | 93 | /* PostGIS build date */ 94 | #define POSTGIS_BUILD_DATE "2020-01-28 17:06:21" 95 | 96 | /* SFCGAL library version at buil time */ 97 | /* #undef POSTGIS_SFCGAL_VERSION */ 98 | 99 | /* GDAL library version */ 100 | /* #undef POSTGIS_GDAL_VERSION */ 101 | 102 | /* GEOS library version */ 103 | /* #define POSTGIS_GEOS_VERSION 38 */ 104 | 105 | /* PostGIS libxml2 version */ 106 | #define POSTGIS_LIBXML2_VERSION "2.9.4" 107 | 108 | /* PostGIS library version */ 109 | #define POSTGIS_LIB_VERSION "3.0.0" 110 | 111 | /* PostGIS major version */ 112 | #define POSTGIS_MAJOR_VERSION "3" 113 | 114 | /* PostGIS minor version */ 115 | #define POSTGIS_MINOR_VERSION "0" 116 | 117 | /* PostGIS micro version */ 118 | #define POSTGIS_MICRO_VERSION "0" 119 | 120 | /* PostgreSQL server version */ 121 | #define POSTGIS_PGSQL_VERSION 100 122 | 123 | /* PROJ library version */ 124 | /* #undef POSTGIS_PROJ_VERSION */ 125 | 126 | /* PostGIS Raster build date */ 127 | /* #undef POSTGIS_RASTER_BUILD_DATE */ 128 | 129 | /* PostGIS Raster library version */ 130 | /* #undef POSTGIS_RASTER_LIB_VERSION */ 131 | 132 | /* PostGIS Raster major version */ 133 | /* #undef POSTGIS_RASTER_MAJOR_VERSION */ 134 | 135 | /* PostGIS Raster micro version */ 136 | /* #undef POSTGIS_RASTER_MICRO_VERSION */ 137 | 138 | /* PostGIS Raster minor version */ 139 | /* #undef POSTGIS_RASTER_MINOR_VERSION */ 140 | 141 | /* PostGIS Raster scripts version */ 142 | /* #undef POSTGIS_RASTER_SCRIPTS_VERSION */ 143 | 144 | /* PostGIS Raster version */ 145 | /* #undef POSTGIS_RASTER_VERSION */ 146 | 147 | /* Define to 1 if a warning is outputted every time a double is truncated */ 148 | /* #undef POSTGIS_RASTER_WARN_ON_TRUNCATION */ 149 | 150 | /* PostGIS scripts version */ 151 | #define POSTGIS_SCRIPTS_VERSION "3.0.0" 152 | 153 | 154 | /* PostGIS version */ 155 | #define POSTGIS_VERSION "3.0 USE_GEOS=1 USE_PROJ=1 USE_STATS=1" 156 | 157 | /* Define to 1 if you have the ANSI C header files. */ 158 | #define STDC_HEADERS 1 159 | 160 | /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a 161 | `char[]'. */ 162 | #define YYTEXT_POINTER 1 163 | 164 | #endif /* POSTGIS_CONFIG_H */ 165 | -------------------------------------------------------------------------------- /src/postgis_config.win: -------------------------------------------------------------------------------- 1 | /* postgis_config.h. Generated from postgis_config.h.in by configure. */ 2 | #ifndef POSTGIS_CONFIG_H 3 | #define POSTGIS_CONFIG_H 1 4 | 5 | #include "postgis_svn_revision.h" 6 | 7 | /* Manually manipulate the POSTGIS_DEBUG_LEVEL, it is not affected by the 8 | configure process */ 9 | #define POSTGIS_DEBUG_LEVEL 0 10 | 11 | /* Define to 1 to enable memory checks in pointarray management. */ 12 | #define PARANOIA_LEVEL 0 13 | 14 | /* Define to 1 if translation of program messages to the user's native 15 | language is requested. */ 16 | #define ENABLE_NLS 1 17 | 18 | /* Define for some functions we are interested in */ 19 | #define HAVE_FSEEKO 1 20 | 21 | /* Define if the GNU gettext() function is already present or preinstalled. */ 22 | #define HAVE_GETTEXT 1 23 | 24 | /* Define if the build is big endian */ 25 | /* #undef WORDS_BIGENDIAN */ 26 | 27 | /* Define if you have the iconv() function and it works. */ 28 | #define HAVE_ICONV 1 29 | 30 | /* Define to 1 if you have the `iconvctl' function. */ 31 | /* #undef HAVE_ICONVCTL */ 32 | 33 | /* ieeefp.h header */ 34 | #define HAVE_IEEEFP_H 0 35 | 36 | /* Define to 1 if you have the `geos_c' library (-lgeos_c). */ 37 | #define HAVE_LIBGEOS_C 1 38 | 39 | /* Define to 1 if you have the `libiconvctl' function. */ 40 | /* #undef HAVE_LIBICONVCTL */ 41 | 42 | /* Define to 1 if libprotobuf-c is present */ 43 | /* #undef HAVE_LIBPROTOBUF */ 44 | 45 | /* Define to 1 if protobuf_c_version() is present */ 46 | /* #undef HAVE_PROTOBUF_C_VERSION */ 47 | 48 | /* Numeric version number for libprotobuf */ 49 | /* #undef LIBPROTOBUF_VERSION */ 50 | 51 | /* Define to 1 if libprotobuf-c is >= version 1.1 */ 52 | /* #undef HAVE_GEOBUF */ 53 | 54 | /* Define to 1 if libjson is present */ 55 | #define HAVE_LIBJSON 1 56 | 57 | /* Define to 1 if you have the `pq' library (-lpq). */ 58 | #define HAVE_LIBPQ 1 59 | 60 | /* Define to 1 if you have the `proj' library (-lproj). */ 61 | #define HAVE_LIBPROJ 1 62 | 63 | /* Define to 1 if you have the `xml2' library (-lxml2). */ 64 | #define HAVE_LIBXML2 1 65 | 66 | /* Define to 1 if you have the header file. */ 67 | #define HAVE_LIBXML_PARSER_H 1 68 | 69 | /* Define to 1 if you have the header file. */ 70 | #define HAVE_LIBXML_TREE_H 1 71 | 72 | /* Define to 1 if you have the header file. */ 73 | #define HAVE_LIBXML_XPATHINTERNALS_H 1 74 | 75 | /* Define to 1 if you have the header file. */ 76 | #define HAVE_LIBXML_XPATH_H 1 77 | 78 | /* Define to 1 if you have the header file. */ 79 | #define HAVE_UNISTD_H 1 80 | 81 | /* Define to 1 if wagyu is being built */ 82 | #define HAVE_WAGYU 1 83 | 84 | /* Define to 1 if sfcgal is being built */ 85 | /* #undef HAVE_SFCGAL */ 86 | 87 | /* Define to the sub-directory in which libtool stores uninstalled libraries. */ 88 | #define LT_OBJDIR ".libs/" 89 | 90 | /* Location of PostgreSQL locale directory */ 91 | #define PGSQL_LOCALEDIR "/usr/share/locale" 92 | 93 | /* PostGIS build date */ 94 | #define POSTGIS_BUILD_DATE "2020-01-28 17:06:21" 95 | 96 | /* SFCGAL library version at buil time */ 97 | /* #undef POSTGIS_SFCGAL_VERSION */ 98 | 99 | /* GDAL library version */ 100 | /* #undef POSTGIS_GDAL_VERSION */ 101 | 102 | /* GEOS library version */ 103 | #define POSTGIS_GEOS_VERSION 38 104 | 105 | /* PostGIS libxml2 version */ 106 | #define POSTGIS_LIBXML2_VERSION "2.9.4" 107 | 108 | /* PostGIS library version */ 109 | #define POSTGIS_LIB_VERSION "3.0.0" 110 | 111 | /* PostGIS major version */ 112 | #define POSTGIS_MAJOR_VERSION "3" 113 | 114 | /* PostGIS minor version */ 115 | #define POSTGIS_MINOR_VERSION "0" 116 | 117 | /* PostGIS micro version */ 118 | #define POSTGIS_MICRO_VERSION "0" 119 | 120 | /* PostgreSQL server version */ 121 | #define POSTGIS_PGSQL_VERSION 100 122 | 123 | /* PROJ library version */ 124 | #define POSTGIS_PROJ_VERSION 63 125 | 126 | /* PostGIS Raster build date */ 127 | /* #undef POSTGIS_RASTER_BUILD_DATE */ 128 | 129 | /* PostGIS Raster library version */ 130 | /* #undef POSTGIS_RASTER_LIB_VERSION */ 131 | 132 | /* PostGIS Raster major version */ 133 | /* #undef POSTGIS_RASTER_MAJOR_VERSION */ 134 | 135 | /* PostGIS Raster micro version */ 136 | /* #undef POSTGIS_RASTER_MICRO_VERSION */ 137 | 138 | /* PostGIS Raster minor version */ 139 | /* #undef POSTGIS_RASTER_MINOR_VERSION */ 140 | 141 | /* PostGIS Raster scripts version */ 142 | /* #undef POSTGIS_RASTER_SCRIPTS_VERSION */ 143 | 144 | /* PostGIS Raster version */ 145 | /* #undef POSTGIS_RASTER_VERSION */ 146 | 147 | /* Define to 1 if a warning is outputted every time a double is truncated */ 148 | /* #undef POSTGIS_RASTER_WARN_ON_TRUNCATION */ 149 | 150 | /* PostGIS scripts version */ 151 | #define POSTGIS_SCRIPTS_VERSION "3.0.0" 152 | 153 | 154 | /* PostGIS version */ 155 | #define POSTGIS_VERSION "3.0 USE_GEOS=1 USE_PROJ=1 USE_STATS=1" 156 | 157 | /* Define to 1 if you have the ANSI C header files. */ 158 | #define STDC_HEADERS 1 159 | 160 | /* Define to 1 if `lex' declares `yytext' as a `char *' by default, not a 161 | `char[]'. */ 162 | #define YYTEXT_POINTER 1 163 | 164 | #endif /* POSTGIS_CONFIG_H */ 165 | -------------------------------------------------------------------------------- /src/postgis_svn_revision.h: -------------------------------------------------------------------------------- 1 | #define POSTGIS_SVN_REVISION 16016 2 | -------------------------------------------------------------------------------- /src/proj.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "Rcpp.h" 3 | #ifdef USE_PROJ_H 4 | 5 | #include 6 | std::string CPL_proj_version(bool b = false) { 7 | std::stringstream buffer; 8 | buffer << PROJ_VERSION_MAJOR << "." << PROJ_VERSION_MINOR << "." << PROJ_VERSION_PATCH; 9 | return buffer.str(); 10 | } 11 | 12 | Rcpp::LogicalVector CPL_use_proj4_init_rules(Rcpp::IntegerVector v) { 13 | proj_context_use_proj4_init_rules(PJ_DEFAULT_CTX, v[0]); 14 | return true; 15 | } 16 | 17 | Rcpp::LogicalVector CPL_set_data_dir(std::string data_dir) { 18 | const char *cp = data_dir.c_str(); 19 | proj_context_set_search_paths(PJ_DEFAULT_CTX, 1, &cp); 20 | return true; 21 | } 22 | 23 | #else 24 | 25 | #include 26 | // [[Rcpp::export]] 27 | std::string CPL_proj_version(bool b = false) { 28 | int v = PJ_VERSION; 29 | std::stringstream buffer; 30 | buffer << v / 100 << "." << (v / 10) % 10 << "." << v % 10; 31 | return buffer.str(); 32 | } 33 | 34 | // [[Rcpp::export]] 35 | Rcpp::LogicalVector CPL_use_proj4_init_rules(Rcpp::IntegerVector v) { 36 | return false; 37 | } 38 | 39 | // [[Rcpp::export]] 40 | Rcpp::LogicalVector CPL_set_data_dir(std::string data_dir) { // #nocov start 41 | return false; 42 | } 43 | 44 | #endif 45 | 46 | -------------------------------------------------------------------------------- /src/sub.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | 5 | extern "C" { 6 | #include 7 | } 8 | 9 | using namespace Rcpp; 10 | 11 | #include "lwgeom.h" // sfc <--> lwgeom 12 | 13 | // [[Rcpp::export]] 14 | Rcpp::List CPL_linesubstring(Rcpp::List sfc, double from, double to, double tolerance = 0.0) { 15 | std::vector lw = lwgeom_from_sfc(sfc); 16 | std::vector out(sfc.size()); 17 | for (size_t i = 0; i < lw.size(); i++) { 18 | // LWLINE *iline = lwgeom_as_lwline(lw[i]); 19 | if ( lw[i]->type == LINETYPE ) { 20 | POINTARRAY *opa; 21 | opa = ptarray_substring(((LWLINE*)lw[i])->points, from, to, tolerance); 22 | if ( opa->npoints == 1 ) /* Point returned */ 23 | out[i] = (LWGEOM *)lwpoint_construct(lw[i]->srid, NULL, opa); // #nocov 24 | else 25 | out[i] = (LWGEOM *)lwline_construct(lw[i]->srid, NULL, opa); 26 | } else 27 | stop("geometry should be of LINE type"); // #nocov 28 | lwgeom_free(lw[i]); 29 | } 30 | return sfc_from_lwgeom(out); 31 | } 32 | -------------------------------------------------------------------------------- /tests/azimuth.R: -------------------------------------------------------------------------------- 1 | suppressPackageStartupMessages(library(sf)) 2 | suppressPackageStartupMessages(library(lwgeom)) 3 | p = st_sfc(st_point(c(7,52)), st_point(c(8,53)), crs = 4326) 4 | st_geod_azimuth(p) 5 | -------------------------------------------------------------------------------- /tests/azimuth.Rout.save: -------------------------------------------------------------------------------- 1 | 2 | R version 3.6.2 (2019-12-12) -- "Dark and Stormy Night" 3 | Copyright (C) 2019 The R Foundation for Statistical Computing 4 | Platform: x86_64-pc-linux-gnu (64-bit) 5 | 6 | R is free software and comes with ABSOLUTELY NO WARRANTY. 7 | You are welcome to redistribute it under certain conditions. 8 | Type 'license()' or 'licence()' for distribution details. 9 | 10 | R is a collaborative project with many contributors. 11 | Type 'contributors()' for more information and 12 | 'citation()' on how to cite R or R packages in publications. 13 | 14 | Type 'demo()' for some demos, 'help()' for on-line help, or 15 | 'help.start()' for an HTML browser interface to help. 16 | Type 'q()' to quit R. 17 | 18 | > suppressPackageStartupMessages(library(sf)) 19 | > suppressPackageStartupMessages(library(lwgeom)) 20 | > p = st_sfc(st_point(c(7,52)), st_point(c(8,53)), crs = 4326) 21 | > st_geod_azimuth(p) 22 | 0.5410385 [rad] 23 | > 24 | > proc.time() 25 | user system elapsed 26 | 0.372 0.015 0.378 27 | -------------------------------------------------------------------------------- /tests/dist.R: -------------------------------------------------------------------------------- 1 | suppressPackageStartupMessages(library(sf)) 2 | library(sp) 3 | suppressPackageStartupMessages(library(units)) 4 | library(geosphere) 5 | 6 | x = st_sfc( 7 | st_point(c(0,0)), 8 | st_point(c(1,0)), 9 | st_point(c(2,0)), 10 | st_point(c(3,0)), 11 | crs = 4326 12 | ) 13 | 14 | y = st_sfc( 15 | st_point(c(0,10)), 16 | st_point(c(1,0)), 17 | st_point(c(2,0)), 18 | st_point(c(3,0)), 19 | st_point(c(4,0)), 20 | crs = 4326 21 | ) 22 | 23 | st_crs(y) = 4326 24 | st_crs(x) = 4326 25 | sf_use_s2(FALSE) 26 | (d.sf = st_distance(x, y)) 27 | -------------------------------------------------------------------------------- /tests/dist.Rout.save: -------------------------------------------------------------------------------- 1 | 2 | R version 4.1.0 (2021-05-18) -- "Camp Pontanezen" 3 | Copyright (C) 2021 The R Foundation for Statistical Computing 4 | Platform: x86_64-pc-linux-gnu (64-bit) 5 | 6 | R is free software and comes with ABSOLUTELY NO WARRANTY. 7 | You are welcome to redistribute it under certain conditions. 8 | Type 'license()' or 'licence()' for distribution details. 9 | 10 | R is a collaborative project with many contributors. 11 | Type 'contributors()' for more information and 12 | 'citation()' on how to cite R or R packages in publications. 13 | 14 | Type 'demo()' for some demos, 'help()' for on-line help, or 15 | 'help.start()' for an HTML browser interface to help. 16 | Type 'q()' to quit R. 17 | 18 | > suppressPackageStartupMessages(library(sf)) 19 | > library(sp) 20 | > suppressPackageStartupMessages(library(units)) 21 | > library(geosphere) 22 | > 23 | > x = st_sfc( 24 | + st_point(c(0,0)), 25 | + st_point(c(1,0)), 26 | + st_point(c(2,0)), 27 | + st_point(c(3,0)), 28 | + crs = 4326 29 | + ) 30 | > 31 | > y = st_sfc( 32 | + st_point(c(0,10)), 33 | + st_point(c(1,0)), 34 | + st_point(c(2,0)), 35 | + st_point(c(3,0)), 36 | + st_point(c(4,0)), 37 | + crs = 4326 38 | + ) 39 | > 40 | > st_crs(y) = 4326 41 | > st_crs(x) = 4326 42 | > sf_use_s2(FALSE) 43 | Spherical geometry (s2) switched off 44 | > (d.sf = st_distance(x, y)) 45 | Units: [m] 46 | [,1] [,2] [,3] [,4] [,5] 47 | [1,] 1105855 111319.5 222639.0 333958.5 445278.0 48 | [2,] 1111387 0.0 111319.5 222639.0 333958.5 49 | [3,] 1127822 111319.5 0.0 111319.5 222639.0 50 | [4,] 1154693 222639.0 111319.5 0.0 111319.5 51 | > 52 | > proc.time() 53 | user system elapsed 54 | 0.542 0.047 0.581 55 | -------------------------------------------------------------------------------- /tests/geod.R: -------------------------------------------------------------------------------- 1 | ### Name: lw_geodetic 2 | ### Title: geodetic length, area, and predicates 3 | ### Aliases: lw_geodetic st_geod_area lw_geodetic st_geod_length 4 | ### lw_geodetic st_geod_segmentize lw_geodetic st_geod_covers 5 | 6 | ### ** Examples 7 | 8 | suppressPackageStartupMessages(library(sf)) 9 | suppressPackageStartupMessages(library(lwgeom)) 10 | suppressPackageStartupMessages(library(units)) 11 | nc = st_read(system.file("gpkg/nc.gpkg", package="sf"), quiet = TRUE) 12 | st_geod_area(nc[1:3,]) 13 | # st_area(nc[1:3,]) 14 | l = st_sfc(st_linestring(rbind(c(7,52), c(8,53))), crs = 4326) 15 | st_geod_length(l) 16 | pol = st_polygon(list(rbind(c(0,0), c(0,60), c(60,60), c(0,0)))) 17 | x = st_sfc(pol, crs = 4326) 18 | seg = st_geod_segmentize(x[1], set_units(10, km)) 19 | plot(seg, graticule = TRUE, axes = TRUE) 20 | pole = st_polygon(list(rbind(c(0,80), c(120,80), c(240,80), c(0,80)))) 21 | pt = st_point(c(0,90)) 22 | x = st_sfc(pole, pt, crs = 4326) 23 | st_geod_covers(x[c(1,1,1)], x[c(2,2,2,2)]) 24 | st_geod_covered_by(x[c(2,2)], x[c(1,1,1)]) 25 | st_geod_covers(x[c(1,1,1)], x[c(2,2,2,2)], sparse = FALSE) 26 | st_geod_covered_by(x[c(2,2)], x[c(1,1,1)], sparse = FALSE) 27 | 28 | # box crossing the dateline: 29 | #box = st_polygon(list(rbind(c(179.5,0), c(179.5,1), c(-179.5,1), c(-179.5,0), c(179.5,0)))) 30 | box = st_polygon(list(rbind(c(179.5,0.1), c(179.5,1), c(-179.5,1), c(-179.5,0.1), c(179.5,0.1)))) 31 | b = st_sfc(box, crs = 4326) 32 | units::set_units(st_geod_area(b), km^2) # approx 111^2 33 | 34 | pt = st_point(c(30, 70)) 35 | x = st_sfc(pole, pt, pt, crs = 4326) 36 | # st_geod_distance(x, x) 37 | # st_geod_distance(x, x, sparse = TRUE) 38 | st_geod_distance(x, x, tolerance = 1, sparse = TRUE) 39 | -------------------------------------------------------------------------------- /tests/geod.Rout.save: -------------------------------------------------------------------------------- 1 | 2 | R version 4.3.2 (2023-10-31) -- "Eye Holes" 3 | Copyright (C) 2023 The R Foundation for Statistical Computing 4 | Platform: x86_64-pc-linux-gnu (64-bit) 5 | 6 | R is free software and comes with ABSOLUTELY NO WARRANTY. 7 | You are welcome to redistribute it under certain conditions. 8 | Type 'license()' or 'licence()' for distribution details. 9 | 10 | R is a collaborative project with many contributors. 11 | Type 'contributors()' for more information and 12 | 'citation()' on how to cite R or R packages in publications. 13 | 14 | Type 'demo()' for some demos, 'help()' for on-line help, or 15 | 'help.start()' for an HTML browser interface to help. 16 | Type 'q()' to quit R. 17 | 18 | > ### Name: lw_geodetic 19 | > ### Title: geodetic length, area, and predicates 20 | > ### Aliases: lw_geodetic st_geod_area lw_geodetic st_geod_length 21 | > ### lw_geodetic st_geod_segmentize lw_geodetic st_geod_covers 22 | > 23 | > ### ** Examples 24 | > 25 | > suppressPackageStartupMessages(library(sf)) 26 | > suppressPackageStartupMessages(library(lwgeom)) 27 | > suppressPackageStartupMessages(library(units)) 28 | > nc = st_read(system.file("gpkg/nc.gpkg", package="sf"), quiet = TRUE) 29 | > st_geod_area(nc[1:3,]) 30 | Units: [m^2] 31 | [1] 1137388604 611077263 1423489919 32 | > # st_area(nc[1:3,]) 33 | > l = st_sfc(st_linestring(rbind(c(7,52), c(8,53))), crs = 4326) 34 | > st_geod_length(l) 35 | 130359.3 [m] 36 | > pol = st_polygon(list(rbind(c(0,0), c(0,60), c(60,60), c(0,0)))) 37 | > x = st_sfc(pol, crs = 4326) 38 | > seg = st_geod_segmentize(x[1], set_units(10, km)) 39 | > plot(seg, graticule = TRUE, axes = TRUE) 40 | > pole = st_polygon(list(rbind(c(0,80), c(120,80), c(240,80), c(0,80)))) 41 | > pt = st_point(c(0,90)) 42 | > x = st_sfc(pole, pt, crs = 4326) 43 | > st_geod_covers(x[c(1,1,1)], x[c(2,2,2,2)]) 44 | Sparse geometry binary predicate list of length 3, where the predicate 45 | was `covers' 46 | 1: 1, 2, 3, 4 47 | 2: 1, 2, 3, 4 48 | 3: 1, 2, 3, 4 49 | > st_geod_covered_by(x[c(2,2)], x[c(1,1,1)]) 50 | Sparse geometry binary predicate list of length 2, where the predicate 51 | was `covered_by' 52 | 1: 1, 2, 3 53 | 2: 1, 2, 3 54 | > st_geod_covers(x[c(1,1,1)], x[c(2,2,2,2)], sparse = FALSE) 55 | [,1] [,2] [,3] [,4] 56 | [1,] TRUE TRUE TRUE TRUE 57 | [2,] TRUE TRUE TRUE TRUE 58 | [3,] TRUE TRUE TRUE TRUE 59 | > st_geod_covered_by(x[c(2,2)], x[c(1,1,1)], sparse = FALSE) 60 | [,1] [,2] [,3] 61 | [1,] TRUE TRUE TRUE 62 | [2,] TRUE TRUE TRUE 63 | > 64 | > # box crossing the dateline: 65 | > #box = st_polygon(list(rbind(c(179.5,0), c(179.5,1), c(-179.5,1), c(-179.5,0), c(179.5,0)))) 66 | > box = st_polygon(list(rbind(c(179.5,0.1), c(179.5,1), c(-179.5,1), c(-179.5,0.1), c(179.5,0.1)))) 67 | > b = st_sfc(box, crs = 4326) 68 | > units::set_units(st_geod_area(b), km^2) # approx 111^2 69 | 11077.84 [km^2] 70 | > 71 | > pt = st_point(c(30, 70)) 72 | > x = st_sfc(pole, pt, pt, crs = 4326) 73 | > # st_geod_distance(x, x) 74 | > # st_geod_distance(x, x, sparse = TRUE) 75 | > st_geod_distance(x, x, tolerance = 1, sparse = TRUE) 76 | Sparse geometry binary predicate list of length 3, where the predicate 77 | was `st_is_within_distance' 78 | 1: 1 79 | 2: 2, 3 80 | 3: 2, 3 81 | > 82 | > proc.time() 83 | user system elapsed 84 | 0.708 1.257 0.473 85 | -------------------------------------------------------------------------------- /tests/perimeter.R: -------------------------------------------------------------------------------- 1 | suppressPackageStartupMessages(library(lwgeom)) 2 | suppressPackageStartupMessages(library(sf)) 3 | nc = st_read(system.file("gpkg/nc.gpkg", package="sf"), quiet = TRUE) 4 | nc = st_transform(nc, 3857) 5 | st_perimeter_lwgeom(nc)[1:5] 6 | st_perimeter_2d(nc)[1:5] 7 | -------------------------------------------------------------------------------- /tests/perimeter.Rout.save: -------------------------------------------------------------------------------- 1 | 2 | R version 4.3.2 (2023-10-31) -- "Eye Holes" 3 | Copyright (C) 2023 The R Foundation for Statistical Computing 4 | Platform: x86_64-pc-linux-gnu (64-bit) 5 | 6 | R is free software and comes with ABSOLUTELY NO WARRANTY. 7 | You are welcome to redistribute it under certain conditions. 8 | Type 'license()' or 'licence()' for distribution details. 9 | 10 | R is a collaborative project with many contributors. 11 | Type 'contributors()' for more information and 12 | 'citation()' on how to cite R or R packages in publications. 13 | 14 | Type 'demo()' for some demos, 'help()' for on-line help, or 15 | 'help.start()' for an HTML browser interface to help. 16 | Type 'q()' to quit R. 17 | 18 | > suppressPackageStartupMessages(library(lwgeom)) 19 | > suppressPackageStartupMessages(library(sf)) 20 | > nc = st_read(system.file("gpkg/nc.gpkg", package="sf"), quiet = TRUE) 21 | > nc = st_transform(nc, 3857) 22 | > st_perimeter_lwgeom(nc)[1:5] 23 | Units: [m] 24 | [1] 176214.9 149265.4 199586.8 375137.8 263512.6 25 | > st_perimeter_2d(nc)[1:5] 26 | Units: [m] 27 | [1] 176214.9 149265.4 199586.8 375137.8 263512.6 28 | > 29 | > proc.time() 30 | user system elapsed 31 | 0.729 1.208 0.434 32 | -------------------------------------------------------------------------------- /tests/testthat.R: -------------------------------------------------------------------------------- 1 | library(testthat) 2 | suppressPackageStartupMessages(library(sf)) 3 | suppressPackageStartupMessages(library(lwgeom)) 4 | 5 | test_check("lwgeom") 6 | -------------------------------------------------------------------------------- /tests/testthat.Rout.save: -------------------------------------------------------------------------------- 1 | 2 | R version 4.3.2 (2023-10-31) -- "Eye Holes" 3 | Copyright (C) 2023 The R Foundation for Statistical Computing 4 | Platform: x86_64-pc-linux-gnu (64-bit) 5 | 6 | R is free software and comes with ABSOLUTELY NO WARRANTY. 7 | You are welcome to redistribute it under certain conditions. 8 | Type 'license()' or 'licence()' for distribution details. 9 | 10 | R is a collaborative project with many contributors. 11 | Type 'contributors()' for more information and 12 | 'citation()' on how to cite R or R packages in publications. 13 | 14 | Type 'demo()' for some demos, 'help()' for on-line help, or 15 | 'help.start()' for an HTML browser interface to help. 16 | Type 'q()' to quit R. 17 | 18 | > library(testthat) 19 | > suppressPackageStartupMessages(library(sf)) 20 | > suppressPackageStartupMessages(library(lwgeom)) 21 | > 22 | > test_check("lwgeom") 23 | [ FAIL 0 | WARN 0 | SKIP 0 | PASS 61 ] 24 | > 25 | > proc.time() 26 | user system elapsed 27 | 1.110 1.293 0.896 28 | -------------------------------------------------------------------------------- /tests/testthat/test-as_text.R: -------------------------------------------------------------------------------- 1 | context("test-as_text.R") 2 | library(sf) 3 | 4 | test_that("Prints Points", { 5 | pt <- st_sfc(st_point(c(1.0002,2.3030303)), crs = 4326) 6 | expect_equal(st_asewkt(pt, 1), "SRID=4326;POINT(1 2.3)") 7 | expect_equal(st_astext(pt, 2, EWKT = FALSE), "POINT(1 2.3)") 8 | expect_equal(st_astext(pt, 3, EWKT = FALSE), "POINT(1 2.303)") 9 | expect_equal(st_astext(pt, 10, EWKT = FALSE), "POINT(1.0002 2.3030303)") 10 | }) 11 | 12 | test_that("Prints Polygons and Lines", { 13 | pol <- st_sfc(st_polygon(list( 14 | 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)) 15 | ))) 16 | txt <- "POLYGON((0 0,0.5 0,0.5 0.5,0.5 0,1 0,1 1,0 1,0 0))" 17 | expect_equal(st_astext(pol), txt) 18 | ln <- st_cast(pol, "LINESTRING") 19 | txt <- "LINESTRING(0 0,0.5 0,0.5 0.5,0.5 0,1 0,1 1,0 1,0 0)" 20 | expect_equal(st_astext(ln), txt) 21 | }) 22 | -------------------------------------------------------------------------------- /tests/testthat/test-clockwise.R: -------------------------------------------------------------------------------- 1 | context("test-clockwise.R") 2 | 3 | library(sf) 4 | 5 | polys <- st_sf(cw = c(FALSE, TRUE), 6 | st_as_sfc(c('POLYGON ((0 0, 1 0, 1 1, 0 0))', 7 | 'POLYGON ((1 1, 2 2, 2 1, 1 1))'))) 8 | 9 | test_that("st_is_polygon_cw works on all classes", { 10 | expect_equal(c(FALSE, TRUE), st_is_polygon_cw(polys)) 11 | expect_equal(c(FALSE, TRUE), st_is_polygon_cw(st_geometry(polys))) 12 | expect_false(st_is_polygon_cw(st_geometry(polys)[[1]])) 13 | }) 14 | 15 | test_that("st_force_polygon_cw works on all classes", { 16 | 17 | out_sf <- st_force_polygon_cw(polys) 18 | out_sfc <- st_force_polygon_cw(st_geometry(polys)) 19 | out_sfg <- st_force_polygon_cw(st_geometry(polys)[[1]]) 20 | 21 | expect_true(all(st_is_polygon_cw(out_sf))) 22 | expect_true(all(st_is_polygon_cw(out_sfc))) 23 | expect_true(all(st_is_polygon_cw(out_sfg))) 24 | }) 25 | 26 | test_that("st_force_polygon_cw preserves crs", { 27 | st_crs(polys) <- 4326 28 | expect_equal(st_crs(st_force_polygon_cw(polys)), 29 | st_crs(polys)) 30 | expect_equal(st_crs(st_force_polygon_cw(st_geometry(polys))), 31 | st_crs(polys)) 32 | }) 33 | 34 | test_that("st_force_polyfon_cw works with Single polygon, ccw exterior ring only", { 35 | obj <- st_as_sfc('POLYGON ((0 0, 1 0, 1 1, 0 0))') 36 | expect_false(st_is_polygon_cw(obj)) 37 | ret <- st_force_polygon_cw(obj) 38 | expect_true(all(st_is_polygon_cw(ret))) 39 | }) 40 | 41 | test_that("st_force_polyfon_cw works with Single polygon, cw exterior ring only", { 42 | obj <- st_as_sfc('POLYGON ((0 0, 1 1, 1 0, 0 0))') 43 | expect_true(st_is_polygon_cw(obj)) 44 | ret <- st_force_polygon_cw(obj) 45 | expect_true(all(st_is_polygon_cw(ret))) 46 | }) 47 | 48 | test_that("st_force_polyfon_cw works with Single polygon, ccw exterior ring, cw interior rings", { 49 | obj <- st_as_sfc('POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 1 2, 2 2, 1 1), (5 5, 5 7, 7 7, 5 5))') 50 | expect_false(st_is_polygon_cw(obj)) 51 | ret <- st_force_polygon_cw(obj) 52 | expect_true(all(st_is_polygon_cw(ret))) 53 | }) 54 | 55 | test_that("st_force_polyfon_cw works with Single polygon, cw exterior ring, ccw interior rings", { 56 | obj <- st_as_sfc('POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0), (1 1, 2 2, 1 2, 1 1), (5 5, 7 7, 5 7, 5 5))') 57 | expect_true(st_is_polygon_cw(obj)) 58 | ret <- st_force_polygon_cw(obj) 59 | expect_true(all(st_is_polygon_cw(ret))) 60 | }) 61 | 62 | test_that("st_force_polyfon_cw works with Single polygon, ccw exterior ring, mixed interior rings", { 63 | obj <- st_as_sfc('POLYGON ((0 0, 10 0, 10 10, 0 10, 0 0), (1 1, 1 2, 2 2, 1 1), (5 5, 7 7, 5 7, 5 5))') 64 | expect_false(st_is_polygon_cw(obj)) 65 | ret <- st_force_polygon_cw(obj) 66 | expect_true(all(st_is_polygon_cw(ret))) 67 | }) 68 | 69 | test_that("st_force_polyfon_cw works with Single polygon, cw exterior ring, mixed interior rings", { 70 | obj <- st_as_sfc('POLYGON ((0 0, 0 10, 10 10, 10 0, 0 0), (1 1, 2 2, 1 2, 1 1), (5 5, 5 7, 7 7, 5 5))') 71 | expect_false(st_is_polygon_cw(obj)) 72 | ret <- st_force_polygon_cw(obj) 73 | expect_true(all(st_is_polygon_cw(ret))) 74 | }) 75 | 76 | test_that("st_force_polyfon_cw works with MultiPolygon, ccw exterior rings only", { 77 | obj <- st_as_sfc('MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((100 0, 101 0, 101 1, 100 0)))') 78 | expect_false(st_is_polygon_cw(obj)) 79 | ret <- st_force_polygon_cw(obj) 80 | expect_true(all(st_is_polygon_cw(ret))) 81 | }) 82 | 83 | test_that("st_force_polyfon_cw works with MultiPolygon, cw exterior rings only", { 84 | obj <- st_as_sfc('MULTIPOLYGON (((0 0, 1 1, 1 0, 0 0)), ((100 0, 101 1, 101 0, 100 0)))') 85 | expect_true(st_is_polygon_cw(obj)) 86 | ret <- st_force_polygon_cw(obj) 87 | expect_true(all(st_is_polygon_cw(ret))) 88 | }) 89 | 90 | test_that("st_force_polyfon_cw works with MultiPolygon, mixed exterior rings", { 91 | obj <- st_as_sfc('MULTIPOLYGON (((0 0, 1 0, 1 1, 0 0)), ((100 0, 101 1, 101 0, 100 0)))') 92 | expect_false(st_is_polygon_cw(obj)) 93 | ret <- st_force_polygon_cw(obj) 94 | expect_true(all(st_is_polygon_cw(ret))) 95 | }) 96 | -------------------------------------------------------------------------------- /tests/twkb.R: -------------------------------------------------------------------------------- 1 | l = structure(list(as.raw(c(0x02, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08))), class = "TWKB") 2 | suppressPackageStartupMessages(library(sf)) 3 | suppressPackageStartupMessages(library(lwgeom)) 4 | st_as_sfc(l) 5 | st_as_sfc(structure(list(l[[1]], l[[1]]), class = "TWKB")) 6 | -------------------------------------------------------------------------------- /tests/twkb.Rout.save: -------------------------------------------------------------------------------- 1 | 2 | R version 4.0.4 (2021-02-15) -- "Lost Library Book" 3 | Copyright (C) 2021 The R Foundation for Statistical Computing 4 | Platform: x86_64-pc-linux-gnu (64-bit) 5 | 6 | R is free software and comes with ABSOLUTELY NO WARRANTY. 7 | You are welcome to redistribute it under certain conditions. 8 | Type 'license()' or 'licence()' for distribution details. 9 | 10 | R is a collaborative project with many contributors. 11 | Type 'contributors()' for more information and 12 | 'citation()' on how to cite R or R packages in publications. 13 | 14 | Type 'demo()' for some demos, 'help()' for on-line help, or 15 | 'help.start()' for an HTML browser interface to help. 16 | Type 'q()' to quit R. 17 | 18 | > l = structure(list(as.raw(c(0x02, 0x00, 0x02, 0x02, 0x02, 0x08, 0x08))), class = "TWKB") 19 | > suppressPackageStartupMessages(library(sf)) 20 | > suppressPackageStartupMessages(library(lwgeom)) 21 | > st_as_sfc(l) 22 | Geometry set for 1 feature 23 | Geometry type: LINESTRING 24 | Dimension: XY 25 | Bounding box: xmin: 1 ymin: 1 xmax: 5 ymax: 5 26 | CRS: NA 27 | LINESTRING (1 1, 5 5) 28 | > st_as_sfc(structure(list(l[[1]], l[[1]]), class = "TWKB")) 29 | Geometry set for 2 features 30 | Geometry type: LINESTRING 31 | Dimension: XY 32 | Bounding box: xmin: 1 ymin: 1 xmax: 5 ymax: 5 33 | CRS: NA 34 | LINESTRING (1 1, 5 5) 35 | LINESTRING (1 1, 5 5) 36 | > 37 | > proc.time() 38 | user system elapsed 39 | 0.355 0.040 0.389 40 | -------------------------------------------------------------------------------- /tic.R: -------------------------------------------------------------------------------- 1 | # installs dependencies, runs R CMD check, runs covr::codecov() 2 | do_package_checks() 3 | 4 | if (ci_on_ghactions() && ci_has_env("BUILD_PKGDOWN")) { 5 | # creates pkgdown site and pushes to gh-pages branch 6 | # only for the runner with the "BUILD_PKGDOWN" env var set 7 | do_pkgdown() 8 | } 9 | -------------------------------------------------------------------------------- /tools/winlibs.R: -------------------------------------------------------------------------------- 1 | if(getRversion() < "3.3.0") { 2 | stop("Your version of R is too old. This package requires R-3.3.0 or newer on Windows.") 3 | } 4 | 5 | # For details see: https://github.com/rwinlib/gdal3 6 | VERSION <- commandArgs(TRUE) 7 | # wrong path: if(!file.exists(sprintf("../windows/gdal3-%s/include/gdal/gdal.h", VERSION))){ 8 | testfile <- sprintf("../windows/gdal3-%s/include/gdal-%s/gdal.h", VERSION, VERSION) 9 | if(!file.exists(testfile)){ 10 | if(getRversion() < "3.3.0") setInternet2() 11 | download.file(sprintf("https://github.com/rwinlib/gdal3/archive/v%s.zip", VERSION), "lib.zip", quiet = TRUE) 12 | dir.create("../windows", showWarnings = FALSE) 13 | unzip("lib.zip", exdir = "../windows") 14 | unlink("lib.zip") 15 | } 16 | --------------------------------------------------------------------------------