NEWS.md
burn() replaces burn_scanline() as the main entry point. burn_scanline() remains as a deprecated wrapper.
burn_sparse() removed. The function is now a deprecated stub that errors with a message directing users to burn(). All GEOS-dependent code has been removed; the package no longer depends on libgeos.
Polygon boundary cells: $edges$weight renamed to $edges$fraction (done in a previous dev cycle, retained here for completeness).
extract_burn() to extract values at points
mode = c("coverage", "approx") parameter on burn(). "coverage" (default) computes exact coverage fractions for polygon boundary cells via the analytical traversal engine. "approx" uses the cell-centre rule (fasterize semantics): boundary cells are included as full run cells iff the cell centre is inside the polygon. No $edges produced in approx mode. Lines and points are unaffected by mode.
crop_burn(x, target) extracts a sub-window from a controlledburn result. Filters and clips runs/edges/lines/points to the target extent (snapped outward to cell boundaries), re-bases row/col indices. Pure R data frame filtering — no dense allocation.
Lightweight approx sweep. Approx mode uses a dedicated edge-row intersection sweep (~120 lines of C++) that bypasses the exactextract walker entirely. On CGAZ (218 countries, 10.1M vertices), this is 1.6–14.5× faster than the walker-based path and crosses over fasterize at ~134 million cells. At 537M cells, controlledburn is 6.8× faster than fasterize; at 8.6 billion cells (where fasterize runs out of memory), the sweep completes in 2.4 seconds.
Cell-for-cell fasterize parity. On NC counties at 2000×800, the lightweight sweep produces identical output to fasterize (zero discrepant cells). Boundary conventions match fasterize: left-inclusive, top-inclusive, half-open interval for horizontal edges at cell-centre y-coordinates.
C++ core (cpp/): pure C++17 library with zero external dependencies, built and tested independently via CMake/CTest. tools/sync-core.sh derives R package sources from the canonical core.
Python bindings (python/): pybind11 + scikit-build-core. burn() accepts WKB bytes and supports mode="coverage" and mode="approx". 33 pytest cases pass.
Shared parity fixtures (fixtures/): CSV files with WKT, WKB hex, grid specs, and expected results. Read by C++, R, and Python test suites for cross-language consistency.
CI for all three surfaces: C++ ctest, Python pytest, R CMD check.
libgeos (LinkingTo and Imports). The vendored exactextract subset is trimmed to 9 GEOS-free analytical geometry files.cpp11 (LinkingTo), wk (Imports).sf, fasterize) are optional and gated behind skip_if_not_installed(). NC county test fixture is bundled as serialised WKB — no sf or vapour needed at test time.Unified geometry rasterization: burn() handles polygon, line, and point input through a single entry point with type-pure output tables ($runs, $edges, $lines, $points).
process_polygon_approx(): the lightweight sweep. For each polygon edge, computes x-intercepts at each row’s y_mid, accumulates winding per row, sweeps left-to-right to emit runs. Top-inclusive half-open interval (ya, yb] matches the walker’s crossing convention.
process_polygon(): the full walker path for coverage mode. Uses the exactextract traversal engine for exact analytical coverage fractions.
Edge zoo (tests/testthat/test-edge-zoo.R) pins canonical rasterizer edge cases by category. Each test pins a convention, not just a numerical expectation.
vignette("architecture") documents the full development story: fasterize origins, exactextract integration, GEOS replacement, dual-mode engine, and scaling characteristics.
Complete rewrite of controlledburn using the exactextract algorithm (Daniel Baston, vendored from exactextractr) for exact polygon-grid coverage fractions.
burn_scanline(): O(perimeter) scanline sweep with winding-number interior classification and exact boundary coverage fractions. No dense matrix allocation — output is sparse runs + edges tables.
burn_sparse(): Reference implementation using the exactextract dense algorithm, compressed to the same sparse output format.
materialise_chunk(): Opt-in expansion to dense matrix or vector, with per-polygon-id filtering.
Default grid parameters: extent derived from geometry bbox via wk::wk_bbox(), dimension auto-fitted to 256 cells on the long axis preserving aspect ratio, or specified as resolution.
Geometry input via wk::wkb(), geos_geometry, sfc, blob, or raw WKB list (compatible with vapour/gdalraster output).
Moved from Rcpp to cpp11, using libgeos for GEOS access.
Scanline algorithm: lightweight walk using Box::crossing() directly (no Cell class allocation), winding-count interior classification, analytical single-traversal coverage via perimeter_distance().
Validated against burn_sparse across 52 test cases: simple shapes, NC counties, shared boundaries, edge cases (grid-aligned edges, slivers, extent clipping, degenerate shapes).
O(perimeter) scaling confirmed by benchmark: 17× faster than dense at 3200×3200 resolution for complex shapes. Memory: sparse output ~50 MB vs ~2 GB dense for real-world 32K×16K grids.