Skip to content

Refactor: improve enclosed tessellation fallback handling#184

Closed
yu-ta-sato wants to merge 8 commits into
c2g-dev:mainfrom
yu-ta-sato:fix/null-barrier-geometries
Closed

Refactor: improve enclosed tessellation fallback handling#184
yu-ta-sato wants to merge 8 commits into
c2g-dev:mainfrom
yu-ta-sato:fix/null-barrier-geometries

Conversation

@yu-ta-sato

@yu-ta-sato yu-ta-sato commented Jul 5, 2026

Copy link
Copy Markdown
Collaborator

Description

This PR improves enclosed tessellation robustness around known momepy / Shapely failure modes and makes fallback behavior more consistent.

  • Adds a retry ladder for enclosed tessellation failures, including GEOS topology errors, coverage_simplify geometry-type errors, and No objects to concatenate failures.
  • Uses a consistent empty enclosed-tessellation schema: geometry, enclosure_index, and tess_id.
  • Drops null or empty barrier geometries from tessellation barriers while keeping those rows as movement segments.
  • Unifies building-footprint fallback cell generation for full tessellation fallback and unenclosed-building fallback.
  • Ensures fallback cells match their source buildings exactly when keep_buildings=True, avoiding duplicate or incorrect spatial-join matches.
  • Adds regression coverage for retry/degradation paths, fallback metadata handling, null barrier geometries, and empty fallback schemas.
  • Clarifies documentation around when suppress_empty_error applies.

Related Issues

N/A

Checklist

  • I have read the Contributing Guide.
  • I have updated the documentation, if necessary.
  • I have added tests to cover my changes.
  • All new and existing tests passed.
  • Pre-commit checks passed locally.

yu-ta-sato and others added 8 commits July 5, 2026 01:00
The retry ladder in _run_tessellation_with_retries handled terminal
failures asymmetrically: a GEOSException after the coarser-grid retry
degraded the unit to an empty tessellation, but the same exception
raised during the TypeError-initiated retry, a ValueError ("No objects
to concatenate") raised on any retry call, or any known failure with
caller-pinned simplify/grid_size options propagated and aborted the
whole run.

Every known failure (coverage_simplify TypeError, GEOSException, momepy
concat ValueError) now ends in a warning plus an empty tessellation at
whichever rung it occurs; only unknown errors propagate. Caller-pinned
options are still never overridden — a pinned grid_size or simplify now
degrades to empty instead of raising once the remaining options are
exhausted. The overlap-repair retry likewise keeps the original cells
and drops the broken enclosures when its own retry fails, instead of
raising away the good ones.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Empty enclosed-tessellation outputs previously carried a tess_id column
on some paths (momepy concat failure) but not others (retry-ladder
degradation, empty enclosures, empty input), while non-empty outputs
always have both tess_id and enclosure_index. Every empty enclosed
result now uses the same [geometry, enclosure_index, tess_id] schema
via _create_empty_tessellation, and the include_tess_id plumbing is
removed. The empty-input early return in create_tessellation reuses the
helper instead of building the frame inline; the no-barrier
(morphological) empty schema is unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the nested try/except ladder in _run_tessellation_with_retries
with a single retry loop: _classify_tessellation_failure names the known
failure kinds (concat ValueError, coverage_simplify TypeError,
GEOSException) and _next_retry_overrides picks the next rung (coarser
grid first, then simplify=False) while never overriding caller-pinned
options. The rung order and all log substrings are unchanged; the full
tessellation test suite passes without any expectation changes.

_repair_or_drop_degenerate_enclosures now reuses the same runner
(seeded with the coarser grid_size and a repair-specific exhaustion
warning) instead of duplicating the TypeError handling, and the interim
helpers _run_final_tessellation_attempt, _retry_at_coarser_grid and
_is_known_tessellation_error are absorbed. The coarse precision 1e-3
moves into the _COARSE_GRID_SIZE constant.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The whole-tessellation fallback (_fallback_tessellation_without_
enclosures) and the unenclosed-building fallback (_include_unenclosed_
building_tessellation) built their cells with separate inline code, and
only the latter recorded the source building index. Whole-tessellation
fallback cells therefore relied on the representative-point spatial
join in _add_building_info, which duplicates rows and mis-assigns
buildings when one footprint contains several representative points —
the same failure mode already fixed for the unenclosed path.

Both paths now build their cells through a shared
_building_fallback_cells helper that always records the source index,
so the exact-match logic applies uniformly. The whole-tessellation
fallback's empty returns also gain the proper place schema instead of
echoing raw building columns, and the internal source-index column no
longer leaks into the place nodes when keep_buildings=False.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Pure extraction of the fallback deduplication and exact-match block
into _match_fallback_cells_to_source_buildings, keeping the positional
masking that tolerates sjoin-duplicated index labels. No behavior
change; no test changes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
With barriers present, create_tessellation degrades the momepy concat
failure to an empty tessellation internally, so the ValueError
conversion in _create_enclosed_tessellation only fires on the
barrier-free morphological path; the enclosed path reaches the
footprint fallback through the empty-tessellation check instead.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@yu-ta-sato yu-ta-sato changed the title fix: ignore null barrier geometries in tessellation Refactor: improve enclosed tessellation fallback handling Jul 5, 2026
@yu-ta-sato yu-ta-sato closed this Jul 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant