Skip to content

wkpool

0.4.0Package record

Vertex Pool Topology for Well-Known Geometry

0packages depend
3Kdownloads / year
92.1%test coverage
13/13flavors OK

Overview

About

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.

Changes in 0.4.0
  • New vignette "Triangulation": ear cutting with pool_triangulate(), the PSLG route (as_pslg() with pool_holes()) to RTriangle, and taking its triangles back onto a vertex pool with new_wkpool_tri(), on silicate's inlandwaters. The other vignettes now cover periodic x, wkpool(vertices, segments) and triangle pools, and point to it.
  • pool_holes() returns a point inside each hole even when the hole is not convex: the centroid of an ear of the hole ring, clear of every pool vertex, instead of the mean of the ring's vertices, which could fall outside the hole and make RTriangle erase the polygon around it (on inlandwaters this lost most of the area). Holes filled exactly by another polygon of the pool (enclaves) are no longer returned, since they are not holes of the coverage.
Show all changes in 0.4.0Hide the rest of the changes in 0.4.0
  • plot() for wkpool_tri accepts xlab and ylab, and sets the plot extent from the triangles drawn rather than the whole vertex pool, so a subset is drawn at its own extent.
  • New plot() method for wkpool_tri: one polygon() call indexing the vertex pool, filled by feature (40,000 triangles draw in about 0.4 s to png, where casting to wk polygons and plotting those took over a minute).

Triangles (experimental)

  • New, experimental wkpool_tri class: a vector of triangles (.vx0, .vx1, .vx2, .feature, .part) on the same kind of vertex pool as a wkpool. pool_triangulate(x, engine = "decido") ear-cuts each polygon of a pool using its path provenance; ear cutting creates no vertices, so the vertex table is passed through unchanged. merge_coincident() accepts a wkpool_tri (triangulate first, merge later gives the same result as merging first). pool_triangles() and tri_segments() give the triangle table and the triangle edges as a wkpool; wk_handle() presents one POLYGON per triangle, with crs and geodesic carried. 'decido' is suggested.
  • wkpool_tri is experimental and may change in a later release. In particular the part is stored as a .part field on each triangle (the simplest option); the alternative is a .path field pointing at the outer ring's path, recovering feature and part from pool_paths() as segments do.

Periodic x (antimeridian)

  • merge_coincident() and topology_report() gain period_x (default NULL, behaviour unchanged). With period_x = 360, vertices are keyed on x %% 360, so the two copies of a +-180 seam fuse (and 0 to 360 data fuses at 0 and 360); after merging, the seam is an ordinary shared boundary for find_shared_edges(), find_internal_boundaries() and quotient arcs. The period is never inferred from the crs. Coordinates are not moved, so geometry emitted from a fused pool jumps by one period across the seam. With a tolerance, x is wrapped, snapped, then wrapped again (#3).

Constructors and naming

  • wkpool(vertices, segments) is now exported and documented: the user-level constructor from a vertex table and a segment table, as returned by pool_vertices() and pool_segments() (#2).
  • New pool_holes(), the same function as hole_points() under a name that matches the other pool_*() accessors. hole_points() is kept (#1).

Performance

  • cycles_to_wkb() / cycles_to_wkt() build all polygons in one wk::wk_polygon() call and all multipolygons in one wk::wk_collection() call, instead of looping over features and parts (10,000 hexagons: 5.7 s to 0.16 s). The fallback for pools without path provenance matches cycle edges to segments with one vctrs::vec_match() instead of a scan per cycle. Output is unchanged.
  • establish_topology() and merge_coincident() no longer build hash tables to look up vertex ids: pools they mint have .vx = 1..n, where an id is its own position, so validation in new_wkpool() and the segment remap use it directly (other pools fall back to match()). On 1M line coordinates merge_coincident() drops from 0.35 s to 0.12 s, and the vertex pipeline is now faster than silicate's PATH0() on every benchmark input (see bench/README.md).
  • find_cycles(), classify_cycles(), hole_points() and find_neighbours() no longer scale quadratically: on 10,000 hexagons find_neighbours(type = "edge") drops from 19 s (13 GB allocated) to 0.03 s and classify_cycles() from 8.3 s to 0.23 s. find_shared_edges(), find_internal_boundaries() and topology_report() key edges with vctrs instead of paste(). Results are unchanged, except that find_neighbours() output no longer carries a stray out.attrs attribute and the features column of find_shared_edges() is a plain named list.
  • bench/ holds a benchmark against silicate (not part of the built package).

Quotient boundary semantics

  • vertex_degree(), find_nodes(), find_arcs(), as_arcs(), arc_node_summary(), arcs_to_wkt() and arcs_to_wkb() gain a quotient argument (default FALSE, behaviour unchanged). In the quotient graph, duplicated shared boundaries - the same undirected vertex pair carried by more than one feature - count once: the first occurrence keeps its direction, multiplicity is discarded whatever its count. A vertex interior to a shared boundary has quotient degree 2 (the degree-2 invariant holds at this level, including for vertices minted by densification), true junctions remain nodes, and find_arcs(x, quotient = TRUE) yields the TopoJSON-style arc decomposition of a polygon layer: each shared border once, not once per feature.
  • Characterization guards pin the default duplicated-boundary and antimeridian-seam semantics as explicit contracts: boundary-interior vertices are degree-4 by default, seams of a +-180 split stay distinct through merge, and merge keys are exact coordinates with no wrapping of any kind.

Compiled arc kernel (first src/)

  • find_arcs() now runs on a cpp11 kernel (wkpool's first compiled code, LinkingTo: cpp11 only, no system requirements). The algorithm, adjacency ordering, node ordering and output are identical to the pure-R implementation, which is retained as the executable specification (find_arcs_walk_r, internal) and pinned to the kernel by conformance tests across nodes, loops, open lines, holes, grids, subsets and shuffled pools.
  • Scale: the pathological all-nodes grid at 2.56 million segments runs in about 1 second (was ~10x that in R after the linear rewrite, and unboundedly worse before it); 2 million segments of long arcs walk in under a second, with remaining time dominated by the R-side dense-id mapping. Real-world effect: the CGAZ world admin boundaries (~10M segments) drop from ~44s to a few seconds.

Exact coordinate identity and linear internals

  • merge_coincident() now groups vertices on the double-precision bit pattern (via vctrs::vec_group_id()) instead of formatted text keys. This fixes a silent correctness bug: the old keys went through as.character() at ~15 significant digits, so distinct doubles differing only beyond printable precision merged even at tolerance = 0. Exact now means exact.
  • When the pool carries z, vertices are keyed on all coordinate columns: equal x/y with different z no longer merge silently. Tolerance is documented honestly as a snap grid (cell size tolerance), not a distance guarantee, and canonical vertices keep their original coordinates.
  • topology_report() computes its counts directly from vertex groups instead of performing a full internal merge_coincident() plus find_shared_edges().
  • The quadratic idioms are gone: find_arcs() uses dense integer adjacency with amortized cursors and a preallocated walk buffer (was: character-keyed lists grown with c() in loops); pool_combine() remaps by position with per-input offsets (was: character-named lookup tables and growing vectors); as_arcs() and vertex_degree() are vectorized. On a 160x160 grid of squares (102400 segments) find_arcs() drops from minutes to under half a second, and all core verbs now scale linearly.
  • pool_compact() remap corrected for pools whose segment order does not follow pool order (latent indexing assumption).

Path provenance (.path)

  • establish_topology() now mints a .path id per segment - one id per input ring or linestring - with a sidecar paths table (.path, .feature, .part, .ring, captured from wk::wk_coords() identifiers). Provenance survives subsetting, merge_coincident(), pool_compact() and pool_combine() (which offsets path ids to keep them unique), and is exposed via the new accessors pool_path() and pool_paths(). new_wkpool() gains path and paths arguments.
  • find_cycles() uses provenance when present: a cycle is a path whose segment chain closes. Rings are recovered exactly, in input order and input winding, robust to segment reordering (chains are rebuilt by connectivity), and a broken ring after subsetting is dropped rather than mis-walked. The result carries a path attribute mapping cycles to path ids. Pools without provenance keep the legacy storage-order walk.
  • The winding-convention issue is resolved structurally: with provenance, ring roles are known (the first ring of each part is the exterior, later rings are its holes), so classify_cycles() and hole_points() no longer guess from winding and the convention argument is only consulted for provenance-free pools. hole_points() on a simple polygon now returns NULL as intended.
  • cycles_to_wkb(feature = TRUE) reconstructs original feature structure exactly when provenance is present: rings grouped into their original part (exterior first, then that part's own holes), parts grouped into POLYGON or MULTIPOLYGON features. This replaces the heuristics (all holes with the first outer; holes dropped for multi-part features) for established pools; provenance-free pools keep the old behaviour.

Native emitters

  • All round-trip emitters (arcs_to_*(), cycles_to_*(), segments_to_*()) are rebuilt on wk's C-level construction filters (wk::wk_linestring(), wk::wk_polygon(), wk::wk_collection()). WKB is now the primary product and WKT is derived from it; no coordinate text is assembled anywhere in wkpool.
  • Consequences: WKB output preserves coordinates at full double precision (previously text formatting perturbed doubles at around the 15th significant digit); z vertex values are carried through all emitters (previously dropped); rings are closed by wk; crs and geodesic ride along by construction. WKT output uses wk's writer (16 significant digits, trimmed) - use the WKB emitters when bit-exact coordinates matter.
  • Behaviour is otherwise unchanged. (The documented simplifications in cycles_to_wkb(feature = TRUE) were retained at this stage and have since been superseded by path provenance for established pools - see above; they still describe the provenance-free fallback.)

wk_handle: a wkpool is wk-handleable

  • wk::wk_handle() is implemented for wkpool: a pool presents as one LINESTRING per segment (length preserved), with crs and geodesic attached. The wk ecosystem's generic conversions now work directly on a pool: wk::as_wkb(), wk::as_wkt(), wk::wk_coords(), wk::wk_meta(), geos::as_geos_geometry(), and anything else built on wk_handle(). Arcs and cycles remain explicit conversions.
  • The handled path is built natively from the pool (wk::xy() indexed by the segment table, through wk's C-level linestring filter): no text round trip, coordinates at full double precision, XYZ when the pool carries z.

CRS round trip

  • A wkpool now participates in wk's CRS propagation model. The CRS and geodesic flag of the input are captured by establish_topology() (via wk::wk_crs() and wk::wk_is_geodesic()), carried through subsetting, merge_coincident(), pool_compact(), as_arcs() and pool_combine(), and restored onto the output of segments_to_wkt(), arcs_to_wkt(), cycles_to_wkt() and their WKB counterparts.
  • Methods for wk::wk_crs(), wk::wk_set_crs(), wk::wk_is_geodesic() and wk::wk_set_geodesic() are provided for wkpool objects. The CRS is opaque and carried, never interpreted, per wk convention.
  • pool_combine() resolves the CRS across inputs with wk::wk_crs_output(): inherit values give way to concrete values, and combining pools with unequal concrete CRS is an error.
  • new_wkpool() is now exported, so downstream packages that construct pools directly (e.g. bigcurve) can do so through a supported constructor that checks invariants and carries crs/geodesic.

From NEWS.md in the release

Install

Health

CRAN checks
13OK
Slowest check: 3.2 min · r-devel-windows-x86_64
Status changes
  • OK13 OK2026-08-04
  • NOTE12 OK, 1 NOTE2026-08-01
  • OK13 OK2026-03-10
Advisories

none known

Documentation

In release 0.4.0
READMEYes · 672 wordsVignettesYes · 3 · evaluation depends on the environmentNEWSYes · 100% structured · mentions 0.4.0Citation fileNo
Help pages
34 (1 internal)includes a package overview page
Examples that run
100%32 run in a plain check
Exported functions with examples
100%
Documented parameters
98%
Return-value docs
100%
Help pages citing references
0%

Downloads

3K
CRAN downloads in the past year
Rank #13,812 · ~8/day · ~252/mo
Daily download trend is not available in this view yet.
34730 days
83290 days
3K1 year
Compare downloads with other packages →
Also on45 r2u5 autocran

Repository

6Stars
0Forks
0Open issues
0Open PRs
0Releases
64Commits
2Commit identities
64 commits · Last activity 2026-10-12 · 0% stars, 30d
Responsiveness
How these are sampled
PRs merged (all time)
100%
Median days to close, 50 most recently updated closed issues
64
Median days to close, 50 most recently updated closed PRs
0

Stars over time

2025-12-23 · 22026-07-07 · 6
PracticesBeta

9 development-tooling and community-health practices detected across 6 families in the upstream repository

Checks run against github.com/hypertidy/wkpool on 2026-10-11.

Continuous integration (2)
GitHub ActionsR CMD check workflow

The R CMD check workflow runs on Linux, macOS and Windows, and on R-devel

Governance and community (1)
Code of conduct
Docs source (3)
README.Rmd

GitHub Pages site last deployed 2026-10-08 · The repository has a site deploy workflow

Reproducibility and dev environment (1)
data-raw/
Show all practicesHide 2 practices
CRAN release process (1)
cran-comments.md
Lint, format, editor (1)
RStudio project
How this is detected·Detection ruleset v3 (2026-09-26)
AI coding toolsBeta

This repository shows signs of AI coding tools.

  • Claude Codefirst seen 2026-08-07
    Pull request it wrote: opened by a project member
    Commits: 2 by its own account · at least 17 crediting it in the message
Models named in its commits
  • Claude Opus 5.59 commits · Oct 2026
  • Claude Fable 58 commits · Aug 2026
Counts are commits, not lines of code. Commits by a tool's accounts count once across all of its accounts. Commits crediting it are the largest count among its credit lines, a minimum.How this is detected·Detection ruleset v4 (updated 2026-09-27)

Dependencies

Declared dependencies
11 external dependencies (excludes base and recommended)

Installing wkpool adds 7 packages (5 with compiled code, 3.9 MB of source tarballs). Heaviest: vctrs 1.0 MB, wk 1.0 MB, rlang 766 KB.

Depends (0)
none
Imports (2)
LinkingTo (1)
Enhances (0)
none
Reverse dependencies
0direct
0indirect

Nothing depends on this yet.

People & History

People (1)
Author, Maintainer since 0.3.0 (2026), Copyright holder
Releases (2)

Pick two releases to compare their code metrics.

  • 0.4.0Latest
    record
    2026-10-12 · current release · diff ↗ ·
    added 9 exports
    new_wkpool, new_wkpool_tri, pool_holes, pool_path, pool_paths, pool_triangles, pool_triangulate, tri_segments, wkpool
  • R
    R 4.6.0 released · 2026-04-24
  • 0.3.0
    record
    2026-03-05
  • R
    R 4.5.0 released · 2025-04-11

Package metadata

First published
2026-03-05
Total releases
2 / 1 yrs
License
MIT + file LICENSE OSI
Download size
610 KB

Cite

Cite this package

Run in R for the authors' preferred citation:

citation("wkpool")
Sumner, M. (2026). wkpool: Vertex Pool Topology for Well-Known Geometry (Version 0.4.0) [Computer software]. https://doi.org/10.32614/CRAN.package.wkpool

This package has no citation file, so citation() returns this entry built from DESCRIPTION.

Cite the R Observatory

For a number measured here: a download total, a coverage figure, an archival date.

APA

Balamuta, J. J. (2026). R Observatory: Metrics for wkpool version 0.4.0 [Data set]. HJJB, LLC. Data release v2026-10-18. https://doi.org/10.5281/zenodo.21843040

From data release v2026-10-18, which the citation names so these numbers can be found later. More on citing and the projects behind them.

Report a problem with this page →

Privacy choices

These apply to this browser and are stored on this device only. Nothing about your choice is sent to us.

Read the privacy policy