Skip to content

Rasterize LinearRing as a line; warn on dropped geometries - #3063

Merged
brendancol merged 1 commit into
mainfrom
issue-3055
Jun 9, 2026
Merged

Rasterize LinearRing as a line; warn on dropped geometries#3063
brendancol merged 1 commit into
mainfrom
issue-3055

Conversation

@brendancol

Copy link
Copy Markdown
Contributor

Closes #3055

_classify_geometries sorts inputs into polygon / line / point buckets. The line bucket matched only LineString (1) and MultiLineString (5), so a non-empty LinearRing (shapely type id 2) fell through every bucket and disappeared. rasterize then returned an all-fill raster with no error or warning.

  • Add type id 2 to the fast-path line bucket and the 'LinearRing' name to the slow-path (GeometryCollection) line branch, so a LinearRing rasterizes as its closed boundary.
  • Warn, naming the type, whenever a non-empty geometry matches no bucket, so data is never dropped silently. None / empty geometries stay silent (None reports as non-empty with type id -1, so it is now treated as empty to match the slow path's existing guard).
  • Update the rasterize docstring to list LinearRing and the new drop-with-warning behavior.

_classify_geometries is the single classifier shared by every backend path, so the fix applies to numpy, cupy, dask+numpy, and dask+cupy.

Test plan

  • LinearRing routes to the line bucket on both the fast path and the GeometryCollection slow path
  • End-to-end rasterize burns a LinearRing boundary and matches the equivalent closed LineString (numpy, dask, cupy, dask+cupy)
  • Non-empty unsupported type ids warn; None and empty geometries stay silent
  • Full existing rasterize suite passes (586 passed, 2 skipped); flake8 clean

_classify_geometries dropped non-empty LinearRings (shapely type id 2)
because the line bucket only matched LineString and MultiLineString. A
LinearRing came back in all three empty buckets, so rasterize returned an
all-fill raster with no error or warning.

Add type id 2 (and the 'LinearRing' name on the GeometryCollection slow
path) to the line bucket, and warn naming the type whenever a non-empty
geometry matches no bucket. None / empty inputs stay silent. The classifier
is shared by all four backends, so the fix covers numpy, cupy, dask+numpy,
and dask+cupy.
@github-actions github-actions Bot added the performance PR touches performance-sensitive code label Jun 9, 2026

@brendancol brendancol left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR Review: Rasterize LinearRing as a line; warn on dropped geometries

Blockers (must fix before merge)

  • None.

Suggestions (should fix, not blocking)

  • None blocking. The else branch in _classify_one (slow path, rasterize.py:366) is effectively unreachable through the public API, since shapely won't build a GeometryCollection that holds an unsupported member. It is reasonable as defense-in-depth, and the helper itself is unit-tested, so I would keep it.

Nits (optional improvements)

  • _warn_dropped_geometries warns with the default UserWarning. That matches the rest of the module (no explicit warning category is used anywhere in rasterize.py), so no change is needed. Noting it only so the choice is visible.

What looks good

  • LinearRing now routes to the line bucket on both the vectorized fast path (rasterize.py:308) and the GeometryCollection slow path (rasterize.py:363), and the tests confirm a ring burns the same pixels as the equivalent closed LineString.
  • The None case is handled correctly: valid = ~empty & (type_ids >= 0) (rasterize.py:300) drops type id -1, so a None geometry is skipped silently, matching the slow path's existing geom is None guard instead of warning on it.
  • The drop warning fires once per batch with the unique offending types, not once per geometry, so it will not spam.
  • Backend coverage is real: _classify_geometries is the single classifier shared by numpy, cupy, dask+numpy, and dask+cupy, and the tests exercise all four end to end.

Checklist

  • Algorithm matches intended behavior (LinearRing = closed line)
  • All implemented backends produce consistent results
  • NaN / None / empty handling is correct
  • Edge cases covered (None, empty, unsupported type id, GC slow path)
  • Dask chunk boundaries handled (shared classifier; ragged chunks tested)
  • No premature materialization or unnecessary copies
  • Benchmark not needed (classification-only bug fix)
  • README feature matrix unchanged (no new function, no backend change)
  • Docstrings present and updated

@brendancol
brendancol merged commit d5d7a19 into main Jun 9, 2026
9 checks passed
@brendancol
brendancol deleted the issue-3055 branch June 25, 2026 12:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

performance PR touches performance-sensitive code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

rasterize: non-empty LinearRing and other unsupported geometries are silently dropped

1 participant