Skip to content

fix: recover polygon area from GeometryCollection intersections in gr… - #187

Merged
prabinoid merged 1 commit into
test/aoi-related-prsfrom
pr-7319
Sep 24, 2026
Merged

prabinoid merged 1 commit into
test/aoi-related-prsfrom
pr-7319

Conversation

@prabinoid

Copy link
Copy Markdown

…id trim

Fixes hotosm#6638.

GridService.trim_grid_to_aoi() drops a partially-overlapping tile entirely whenever its intersection with the AOI comes back as anything other than a bare Polygon/MultiPolygon. But a tile touching the AOI boundary can intersect into a GeometryCollection containing a real polygon slice plus stray Point/LineString artifacts from the boundary touch - the old code discarded the whole tile in that case, losing real area and leaving gaps where the task grid should have covered the AOI.

Diagnosed by @prabinoid in the issue thread; this implements the fix they identified: for a GeometryCollection result, filter .geoms for just the Polygon/MultiPolygon members and unary_union them back into a single shape to keep using. If none of the sub-geometries carry any area (a pure boundary touch), the tile is still skipped, same as before.

Verified against a constructed reproduction (two AOI polygons - one overlapping the tile's interior, one only touching its edge - unioned together) that actually produces a GeometryCollection([Polygon, LineString]) intersection with Shapely, matching the reported bug exactly: old logic drops the tile despite 1.0 unit of real overlap area; new logic recovers it. Also verified the "no polygon in the collection" and "genuinely no overlap" paths still correctly skip the tile, unchanged from before.

Wasn't able to run the existing test_grid_service.py suite locally - importing the backend package pulls in its full dependency tree (mail clients etc.) beyond what this module itself needs, and BaseTestCase additionally requires a live Postgres instance neither of which were available in my environment. The verification above exercises the exact Shapely operations this change makes; deferring the full suite to CI.

What type of PR is this? (check all applicable)

  • 🍕 Feature
  • 🐛 Bug Fix
  • 📝 Documentation
  • 🧑‍💻 Refactor
  • ✅ Test
  • 🤖 Build or CI
  • ❓ Other (please specify)

Related Issue

Example: Fixes #123

Describe this PR

A brief description of how this solves the issue.

Screenshots

Please provide screenshots of the change.

Alternative Approaches Considered

Did you attempt any other approaches that are not documented in code?

Review Guide

Notes for the reviewer. How to test this change?

Checklist before requesting a review

[optional] What gif best describes this PR or how it makes you feel?

…id trim

Fixes hotosm#6638.

GridService.trim_grid_to_aoi() drops a partially-overlapping tile
entirely whenever its intersection with the AOI comes back as
anything other than a bare Polygon/MultiPolygon. But a tile touching
the AOI boundary can intersect into a GeometryCollection containing a
real polygon slice plus stray Point/LineString artifacts from the
boundary touch - the old code discarded the whole tile in that case,
losing real area and leaving gaps where the task grid should have
covered the AOI.

Diagnosed by @prabinoid in the issue thread; this implements the fix
they identified: for a GeometryCollection result, filter .geoms for
just the Polygon/MultiPolygon members and unary_union them back into
a single shape to keep using. If none of the sub-geometries carry any
area (a pure boundary touch), the tile is still skipped, same as
before.

Verified against a constructed reproduction (two AOI polygons - one
overlapping the tile's interior, one only touching its edge - unioned
together) that actually produces a GeometryCollection([Polygon,
LineString]) intersection with Shapely, matching the reported bug
exactly: old logic drops the tile despite 1.0 unit of real overlap
area; new logic recovers it. Also verified the "no polygon in the
collection" and "genuinely no overlap" paths still correctly skip the
tile, unchanged from before.

Wasn't able to run the existing test_grid_service.py suite locally -
importing the backend package pulls in its full dependency tree
(mail clients etc.) beyond what this module itself needs, and BaseTestCase
additionally requires a live Postgres instance neither of which were
available in my environment. The verification above exercises the
exact Shapely operations this change makes; deferring the full suite
to CI.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Brian Bergstrom <dulcetberg@gmail.com>
@prabinoid
prabinoid merged commit e9ed3f9 into test/aoi-related-prs Sep 24, 2026
2 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants