Null And Empty Geometry Semantics

Null geometries and empty geometries are distinct states in vibeSpatial.

Intent

Define the runtime and kernel contract for missing versus empty geometries before owned geometry buffers and kernels expand.

Request Signals

  • null geometry

  • empty geometry

  • missing geometry

  • validity bitmap

  • null propagation

  • empty semantics

Open First

  • docs/architecture/nulls.md

  • src/vibespatial/runtime/nulls.py

  • docs/architecture/runtime.md

  • docs/decisions/0003-null-empty-geometry-contract.md

Verify

  • uv run pytest tests/test_null_policy.py

  • uv run python scripts/check_docs.py --check

Risks

  • Treating null and empty as the same state breaks GeoPandas and Shapely semantics.

  • Scalar branching for null or empty cases can create avoidable warp divergence.

  • Buffer layouts that omit validity information will force slow-path recovery later.

Canonical States

Every geometry slot is in exactly one of these states:

  • null: missing geometry value

  • empty: valid geometry object with zero coordinates

  • value: non-empty geometry

Buffers must represent both missingness and emptiness:

  • nulls use a validity bitmap

  • empties use valid rows with zero-length coordinate or offset spans

Core Rules

  • Null handling follows Arrow semantics.

  • Unary operations propagate nulls.

  • Binary predicates propagate nulls.

  • Joins and aggregations exclude null geometries from candidate generation.

  • Empty geometries are valid inputs, not missing data.

Empty Geometry Rules

  • bounds of empty geometries are NaN

  • area and length of empty geometries are 0

  • predicates involving an empty geometry return defined boolean results

  • empties must never be rewritten to nulls

For the current default contract:

  • empty.intersects(X) -> false

  • empty.within(X) -> false

  • empty.contains(X) -> false

Kernel-specific docs may extend this table, but they must not collapse empty and null into the same result state.

Batch Execution Rules

  • Null and empty handling should use predicated execution or mask-and-fill patterns.

  • Warp-wide scalar fallback branches are not the default mechanism.

  • Output buffers must preserve the distinction between propagated nulls and defined empty-derived values.

Buffer Implications

o17.2.1 and later work should assume:

  • validity is orthogonal to geometry family tags

  • zero-length spans are meaningful and must survive partitioning or permutation

  • restoration of row order cannot lose null or empty state