MyNixOS website logo
Description

Vertex Pool Topology for Well-Known Geometry.

Establishes and maintains vertex pool topology for geometry handled by 'wk'. Segments are the atomic unit, vertices are shared via integer references into a pool. Topology is made discoverable via coincident vertex detection while not requiring modification of the input data. Topological data models follow principles described in Worboys and Duckham (2004, ISBN:978-0415283755). The edge-based topology geometry decomposed into vertices and directed edge pairs is a simplification of the quad-edge case in Guibas & Stolfi (1985) <doi:10.1145/282918.282923>.

R-CMD-check CRANstatus

wkpool

Vertex pool topology for geometry handled by wk.

Design philosophy

Simple features throws away topology — every polygon stores its own coordinates, shared boundaries are duplicated, and expensive operations (GEOS) are needed to rediscover this structure which is then again discarded.

wkpool takes a different approach:

  • Segments are atomic: Everything is edges (vertex pairs). Polygons, linestrings, meshes — all just segments with different grouping.
  • Vertices live in a pool: Coordinates stored once, referenced by integer ID (.vx).
  • Observe, don’t correct: establish_topology() represents the truth of your input. Snapping/fixing is a separate, explicit decision.
  • Topology is discoverable: merge_coincident() finds shared vertices. Shared boundaries, neighbour relations — they emerge from the data.
  • Feature provenance: Segments track which feature they came from (.feature), enabling adjacency and boundary queries.

Installation

From CRAN use

install.packages("wkpool")

For development version use

#install.packages("remotes")
remotes::install_github("hypertidy/wkpool")

Usage

library(wkpool)
library(wk)

# Any wk-handleable geometry
#x <- wk::as_wkb(<wk-compatible>)
x <- wk::as_wkb(c(
   paste0(
     "MULTIPOLYGON (((0 0, 0 1, 0.75 1, 1 0.8, 0.5 0.7, ",
     "0.8 0.6, 0.69 0, 0 0), (0.2 0.2, 0.5 0.2, ",
     "0.5 0.4, 0.3 0.6, 0.2 0.4, 0.2 0.2)))"),
 "MULTIPOLYGON (((0.69 0, 0.8 0.6, 1.1 0.63, 1.23 0.3, 0.69 0)))"
))

# Establish topology (no coordinate merging yet)
pool <- establish_topology(x)

# What do we have?
topology_report(pool)
#> $n_vertices_raw
#> [1] 19
#> 
#> $n_vertices_unique
#> [1] 14
#> 
#> $n_duplicate_vertices
#> [1] 5
#> 
#> $n_near_miss_vertices
#> [1] 0
#> 
#> $n_segments
#> [1] 16
#> 
#> $n_shared_edges
#> [1] 1
#> 
#> $n_features
#> [1] 2

# Merge coincident vertices (exact match)
merged <- merge_coincident(pool, tolerance = 0)

# Find shared boundaries
shared <- find_shared_edges(merged)

# Internal boundaries (edges shared by exactly 2 features)
internal <- find_internal_boundaries(merged)

# Neighbour relations
neighbours <- find_neighbours(merged, type = "edge")    # share a boundary
neighbours_v <- find_neighbours(merged, type = "vertex") # share any vertex

# Access the raw structure
pool_vertices(merged)  # data.frame: .vx, x, y
#>    .vx    x    y
#> 1    1 0.00 0.00
#> 2    2 0.00 1.00
#> 3    3 0.75 1.00
#> 4    4 1.00 0.80
#> 5    5 0.50 0.70
#> 6    6 0.80 0.60
#> 7    7 0.69 0.00
#> 9    8 0.20 0.20
#> 10   9 0.50 0.20
#> 11  10 0.50 0.40
#> 12  11 0.30 0.60
#> 13  12 0.20 0.40
#> 17  13 1.10 0.63
#> 18  14 1.23 0.30
pool_segments(merged)  # data.frame: .vx0, .vx1, .feature
#>    .vx0 .vx1 .feature
#> 1     1    2        1
#> 2     2    3        1
#> 3     3    4        1
#> 4     4    5        1
#> 5     5    6        1
#> 6     6    7        1
#> 7     7    1        1
#> 8     8    9        1
#> 9     9   10        1
#> 10   10   11        1
#> 11   11   12        1
#> 12   12    8        1
#> 13    7    6        2
#> 14    6   13        2
#> 15   13   14        2
#> 16   14    7        2

Key decisions

DecisionChoiceRationale
Pool scopePer-vector, sidecar attributeNo wk core changes needed, n-geometry ready
SnappingObserve don’t correctRepresent truth, fixing is separate
Vertex identityMinted .vx integerSurvives subset, lighter than UUID
Segment identityDerived from vertex pairNo ID to track, tuple IS identity
Primary vctrSegmentsGeometry is what you subset, vertices follow
FoundationvctrsPrincipled combine/subset, tidyverse alignment

Next steps

  • [x] wk_handle.wkpool() — round-trip back to wk geometry
  • [x] Path reconstruction — derive linestrings/rings from segment connectivity
  • [ ] Apply to production package (trip)
  • [ ] Triangulation integration (decido) — indexed triangles from same pool
  • [ ] Consider C++ once API is stable

Code of Conduct

Please note that the wkpool project is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.

Metadata

Version

0.3.0

License

Unknown

Platforms (78)

    Darwin
    FreeBSD
    Genode
    GHCJS
    Linux
    MMIXware
    NetBSD
    none
    OpenBSD
    Redox
    Solaris
    uefi
    WASI
    Windows
Show all
  • aarch64-darwin
  • aarch64-freebsd
  • aarch64-genode
  • aarch64-linux
  • aarch64-netbsd
  • aarch64-none
  • aarch64-uefi
  • aarch64-windows
  • aarch64_be-none
  • arm-none
  • armv5tel-linux
  • armv6l-linux
  • armv6l-netbsd
  • armv6l-none
  • armv7a-linux
  • armv7a-netbsd
  • armv7l-linux
  • armv7l-netbsd
  • avr-none
  • i686-cygwin
  • i686-freebsd
  • i686-genode
  • i686-linux
  • i686-netbsd
  • i686-none
  • i686-openbsd
  • i686-windows
  • javascript-ghcjs
  • loongarch64-linux
  • m68k-linux
  • m68k-netbsd
  • m68k-none
  • microblaze-linux
  • microblaze-none
  • microblazeel-linux
  • microblazeel-none
  • mips-linux
  • mips-none
  • mips64-linux
  • mips64-none
  • mips64el-linux
  • mipsel-linux
  • mipsel-netbsd
  • mmix-mmixware
  • msp430-none
  • or1k-none
  • powerpc-linux
  • powerpc-netbsd
  • powerpc-none
  • powerpc64-linux
  • powerpc64le-linux
  • powerpcle-none
  • riscv32-linux
  • riscv32-netbsd
  • riscv32-none
  • riscv64-linux
  • riscv64-netbsd
  • riscv64-none
  • rx-none
  • s390-linux
  • s390-none
  • s390x-linux
  • s390x-none
  • vc4-none
  • wasm32-wasi
  • wasm64-wasi
  • x86_64-cygwin
  • x86_64-darwin
  • x86_64-freebsd
  • x86_64-genode
  • x86_64-linux
  • x86_64-netbsd
  • x86_64-none
  • x86_64-openbsd
  • x86_64-redox
  • x86_64-solaris
  • x86_64-uefi
  • x86_64-windows