Package 'controlledburn'

Title: Sparse Polygon Rasterization with Exact Coverage Fractions
Description: Rasterize polygons without materializing any pixel values. Computes exact coverage fractions for polygon-grid intersections and returns results in a sparse two-table format: run-length encoded interior cells and individually weighted boundary cells. The scanline algorithm is O(perimeter) in both time and memory. Uses the exactextract algorithm by Daniel Baston, vendored from the 'exactextractr' package. Derived from the 'fasterize' package by Noam Ross.
Authors: Michael Sumner [aut, cre] (ORCID: <https://orcid.org/0000-0002-2471-7511>), Noam Ross [aut] (ORCID: <https://orcid.org/0000-0002-2136-0000>), EcoHealth Alliance [cph] (Original fasterize scanline logic), Jim Hester [ctb] (Wrote CollectorList.h for early version), Daniel Baston [cph] (exactextract C++ algorithm (vendored)), ISciences, LLC [cph] (exactextract C++ algorithm (vendored))
Maintainer: Michael Sumner <[email protected]>
License: Apache License (>= 2)
Version: 0.1.3
Built: 2026-05-12 00:06:27 UTC
Source: https://github.com/hypertidy/controlledburn

Help Index


Sparse rasterization of polygon, line, and point geometry

Description

Rasterizes geometry into a sparse output schema, with one type-pure table per geometry kind. Polygons produce run-length-encoded interior cells (⁠$runs⁠) and weighted boundary cells (⁠$edges⁠, with a coverage fraction in ⁠[0, 1]⁠). Lines produce one record per touched cell with the absolute length of line within the cell, in CRS units (⁠$lines⁠). Points produce one record per touched cell, with no measure column (⁠$points⁠). See the unified geometry rasterization design doc in ⁠inst/docs-design/⁠.

Usage

burn_scanline(x, extent = NULL, dimension = NULL, resolution = NULL)

Arguments

x

geometry input, one of:

  • an sfc geometry column (from sf)

  • a geos_geometry vector (from geos)

  • a list of raw vectors containing WKB

extent

numeric vector c(xmin, xmax, ymin, ymax) defining the raster extent. If NULL (default), derived from the bounding box of x.

dimension

integer vector c(ncol, nrow) defining the grid dimensions. If NULL (default), fitted to the extent with at most 256 cells along the longer axis, preserving aspect ratio. Mutually exclusive with resolution.

resolution

numeric, cell size (scalar for square cells, or c(dx, dy)). If supplied, dimension is computed from extent / resolution. Mutually exclusive with dimension.

Details

Mixed geometry-kind input (e.g. a vector containing both polygons and lines) is permitted and produces tables populated for whichever kinds are present. Each table's measure column means exactly one thing — polygon ⁠$edges$fraction⁠ is dimensionless, ⁠$lines$length⁠ is in CRS units, points have no measure — so combining them in a single materialized matrix would silently mix units. materialize_chunk() therefore refuses mixed-kind input; filter to one kind via ⁠id =⁠ first, or run separate burns for each kind.

GeometryCollection input warns and is skipped. Curved types (CircularString, CompoundCurve, etc.) must be linearised by the caller before calling.

Memory usage is O(perimeter) rather than O(bounding-box area), so no tile_size parameter is required (in contrast to burn_sparse(), which is polygon-only and tile-bounded).

Value

A list with class "controlledburn" containing:

runs

data.frame with columns row, col_start, col_end, id — run-length encoded polygon interior cells (always full coverage). Empty for line/point input.

edges

data.frame with columns row, col, fraction, id — polygon boundary cells with partial coverage; fraction is in (0, 1). Empty for line/point input.

lines

data.frame with columns row, col, length, id — line cells; length is the absolute length of the line within the cell, in CRS units. Empty for polygon/point input.

points

data.frame with columns row, col, id — point cells; no measure column (a point is either in a cell or it isn't). Empty for polygon/line input.

extent

the raster extent (c(xmin, xmax, ymin, ymax))

dimension

the grid dimensions (c(ncol, nrow))

Row and column indices are 1-based. Row 1 is the top (ymax) row. The id column is a 1-based index into the input geometry vector.

The measure is computed in the CRS the geometry and grid are specified in — not the geodesic measure on the Earth. Geometry in degrees produces area in square degrees and length in degrees. For geodesic measures, project to an appropriate CRS first.

Examples

if (requireNamespace("geos", quietly = TRUE)) {
  library(geos)

  # Polygon: produces $runs (interior) and $edges (fraction in [0, 1])
  poly <- as_geos_geometry("POLYGON ((0.5 0.5, 2.5 0.5, 2.5 2.5, 0.5 2.5, 0.5 0.5))")
  r <- burn_scanline(poly, extent = c(0, 3, 0, 3), dimension = c(3, 3))

  # Line: produces $lines with absolute length in CRS units
  line <- as_geos_geometry("LINESTRING (0.5 0.5, 2.5 2.5)")
  r <- burn_scanline(line, extent = c(0, 3, 0, 3), dimension = c(3, 3))

  # Point: produces $points with row/col only (no measure column)
  pt <- as_geos_geometry("POINT (1.5 1.5)")
  r <- burn_scanline(pt, extent = c(0, 3, 0, 3), dimension = c(3, 3))

  # Defaults: extent from bbox, 256-cell fitted grid
  r <- burn_scanline(poly)

  # By resolution
  r <- burn_scanline(poly, resolution = 0.01)
}

Sparse polygon rasterization with exact coverage fractions

Description

Computes exact coverage fractions for polygon-grid intersections via an exactextract-style flood-fill, returning sparse two-table output: run-length-encoded interior cells and individually weighted boundary cells.

Usage

burn_sparse(
  x,
  extent = NULL,
  dimension = NULL,
  resolution = NULL,
  tile_size = 4096L
)

Arguments

x

geometry input, one of:

  • an sfc geometry column (from sf)

  • a geos_geometry vector (from geos)

  • a list of raw vectors containing WKB

extent

numeric vector c(xmin, xmax, ymin, ymax) defining the raster extent. If NULL (default), derived from the bounding box of x.

dimension

integer vector c(ncol, nrow) defining the grid dimensions. If NULL (default), fitted to the extent with at most 256 cells along the longer axis, preserving aspect ratio. Mutually exclusive with resolution.

resolution

numeric, cell size (scalar for square cells, or c(dx, dy)). If supplied, dimension is computed from extent / resolution. Mutually exclusive with dimension.

tile_size

integer, maximum tile dimension (default 4096). The grid is processed in tiles of at most ⁠tile_size x tile_size⁠ cells to bound memory usage. Set to Inf to disable tiling. (Not relevant on burn_scanline(), whose memory cost is O(perimeter).)

Details

Polygon-only. Line and point input are rejected with an error directing the caller to burn_scanline(), which produces the unified (polygon / line / point) output schema.

Compared to burn_scanline(), this function is older and uses a bounding-box-bounded dense intermediate (hence the tile_size parameter). For polygon input the two functions produce numerically identical results; burn_scanline() is preferred for new code.

controlledburn does not validate input geometry. It rasterizes what you pass it, valid or not, and trusts you to judge the result.

Value

A list with class "controlledburn" containing:

runs

data.frame with columns row, col_start, col_end, id — run-length encoded interior cells (full coverage)

edges

data.frame with columns row, col, fraction, id — boundary cells with partial coverage, fraction in (0, 1)

extent

the raster extent

dimension

the grid dimensions

Row and column indices are 1-based. Row 1 is the top (ymax) row. The id column is a 1-based index into the input geometry vector.

Examples

if (requireNamespace("geos", quietly = TRUE)) {
  library(geos)
  poly <- as_geos_geometry("POLYGON ((0.5 0.5, 2.5 0.5, 2.5 2.5, 0.5 2.5, 0.5 0.5))")

  # Explicit extent and dimension
  result <- burn_sparse(poly, extent = c(0, 3, 0, 3), dimension = c(3, 3))

  # Defaults: extent from bbox, 256-cell fitted grid
  result <- burn_sparse(poly)

  # Specify resolution (cell size)
  result <- burn_sparse(poly, resolution = 0.1)
}

Materialize a controlledburn result to a dense matrix or vector

Description

Expands a sparse burn_sparse() / burn_scanline() result into a dense matrix, optionally over a subwindow of the parent grid. The matrix's values depend on which kind of geometry produced the result:

Usage

materialize_chunk(
  x,
  target = NULL,
  id = NULL,
  type = c("matrix", "vector"),
  max_cells = 1e+08
)

materialise_chunk(
  x,
  target = NULL,
  id = NULL,
  type = c("matrix", "vector"),
  max_cells = 1e+08
)

Arguments

x

a "controlledburn" object from burn_sparse() or burn_scanline()

target

numeric extent c(xmin, xmax, ymin, ymax) to materialize, or NULL (default) for the full grid. The target extent is snapped outward to cell boundaries of the source grid and clamped to the source extent.

id

integer geometry id (or vector of ids) to materialize, or NULL (default) for all. Useful for filtering a mixed-kind result down to a single kind before materialising.

type

character, one of "matrix" (default) or "vector"

max_cells

maximum number of cells to allocate (default 1e8). Set to Inf to disable the safety check.

Details

  • Polygon (⁠$runs⁠ + ⁠$edges⁠): coverage fraction in ⁠[0, 1]⁠. Interior cells are 1; boundary cells are the partial fraction.

  • Line (⁠$lines⁠): absolute length within each cell, in CRS units. Multiple lines crossing the same cell sum.

  • Point (⁠$points⁠): integer count of points landing in each cell. Multiple points in one cell sum.

If a result holds tables for more than one geometry kind (which can happen when a single burn was given a mixed-kind input vector), materialize_chunk() errors rather than silently combining different units in one matrix. Filter with ⁠id =⁠ to one kind first, or run separate burns for each kind.

Value

A numeric matrix (nrow × ncol) or vector (length nrow*ncol). The cell unit depends on geometry kind (see Description). When target is specified, the matrix dimensions correspond to the snapped subwindow. The snapped extent is available as attr(result, "extent").