.
This commit is contained in:
parent
909e241907
commit
1ee796b282
29 changed files with 250 additions and 126 deletions
|
|
@ -120,7 +120,7 @@ def _is_pointlike(geom_bng) -> bool:
|
|||
def _rescue_footprint(geom_bng) -> dict | None:
|
||||
"""Fatten a degenerate BNG geometry into a representable footprint and snap.
|
||||
|
||||
A POINTLIKE input (a point, or a near-zero-area/short-perimeter polygon — the
|
||||
A POINTLIKE input (a point, or a near-zero-area/short-perimeter polygon, the
|
||||
signature of a tower-block postcode whose UPRNs all share one coordinate)
|
||||
gets a building-scale buffer so it is not reduced to an invisible sub-metre
|
||||
dot; thin slivers that still carry length keep the minimal buffer.
|
||||
|
|
@ -263,7 +263,7 @@ def merge_fragments(
|
|||
# Close tiny gaps between adjacent OA boundary edges (float mismatches).
|
||||
# The closing can erode a tiny MultiPolygon (e.g. a postcode with only a
|
||||
# sliver fragment) to nothing, which would leave the postcode with no
|
||||
# geometry at all — keep the un-closed shape if that happens.
|
||||
# geometry at all. Keep the un-closed shape if that happens.
|
||||
if combined.geom_type == "MultiPolygon":
|
||||
closed = combined.buffer(5.0).buffer(-5.0)
|
||||
if not closed.is_valid:
|
||||
|
|
@ -308,7 +308,7 @@ def _polygonal(geom):
|
|||
return None
|
||||
# Both callers run on WGS84-degree output geometry, so the robustness
|
||||
# fallback snaps on the 1e-6° grid (~0.11 m), not geometry.py's metre
|
||||
# default — a coarse metre grid would obliterate a degree-scale shape.
|
||||
# default. A coarse metre grid would obliterate a degree-scale shape.
|
||||
merged = safe_union(polys, grid=_OUTPUT_PRECISION_DEG)
|
||||
return merged if not merged.is_empty else None
|
||||
return None
|
||||
|
|
@ -324,7 +324,7 @@ def _resolve_overlaps(
|
|||
containment (a postcode fully enclosed by another). Each postcode is trimmed
|
||||
by the union of its higher-priority overlapping neighbours, where **priority =
|
||||
ascending area**: a smaller postcode wins contested ground. That single rule
|
||||
handles both cases correctly — an enclosed postcode is always smaller than its
|
||||
handles both cases correctly: an enclosed postcode is always smaller than its
|
||||
container, so it keeps its area while the container gets a hole (a `overlaps`
|
||||
query alone would miss containment entirely). Run last, on the final output
|
||||
geometries, so nothing re-introduces overlap afterwards. A postcode that would
|
||||
|
|
@ -348,7 +348,7 @@ def _resolve_overlaps(
|
|||
arr = np.array(geoms, dtype=object)
|
||||
pairs: set[tuple[int, int]] = set()
|
||||
# "overlaps" gives partial overlaps; "contains" gives containment (which
|
||||
# "overlaps" excludes) — together they cover every 2-D overlap without the
|
||||
# "overlaps" excludes). Together they cover every 2-D overlap without the
|
||||
# edge-touch explosion a plain "intersects" query would add.
|
||||
for predicate in ("overlaps", "contains"):
|
||||
qsrc, qtgt = tree.query(arr, predicate=predicate)
|
||||
|
|
@ -577,7 +577,7 @@ def _grid_footprint(geom):
|
|||
pass can shave a small (e.g. co-located, non-geographic) postcode down to a
|
||||
sub-grid sliver that disappears when snapped to output precision. Rather than
|
||||
drop it, place a minimal valid footprint at its location. The tiny overlap
|
||||
this re-creates with the neighbour that trimmed it is harmless — the output
|
||||
this re-creates with the neighbour that trimmed it is harmless: the output
|
||||
partition is best-effort, a missing boundary is a hard validation failure.
|
||||
"""
|
||||
try:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue