COMPO · 5.02 · EMPTY REGIONS / CLEARANCE / BREATHING ROOM

Empty regions,
clearance &
breathing room.

Connected-component и distance-field слой Topic 5: EmptyRegion[], region-specific area shares, Euclidean clearance to free-region boundary, largest inscribed empty radius и local breathing-room queries. Все outputs остаются геометрическими descriptors — figure-ground/corridor semantics и whitespace target fit ещё не принадлежат 5.02.

ModuleCompo 5.02
Scopeempty regions / clearance
Ownsregion geometry
Relationsdeferred 5.03
Topic5 · SPACE
Next5.03

Free mask → regions → clearance

00 / module api

5.02 принимает уже готовый FreeMask 5.01. Его задача — понять, из скольких связных пустых областей он состоит и какой локальный геометрический запас есть внутри каждой.

SCOPE

Connected EmptyRegion[], Euclidean clearance field, maximum inscribed radius и local breathing-room query.

DOES NOT OWN

Occupied/free mask, figure-ground relations, corridor semantics, whitespace score.

FINALITY

CONNECTED FREE-REGION / CLEARANCE GEOMETRY ONLY.

DO NOT REBUILD THE MASK. 5.02 не имеет второго определения «что считается пустым». Единственный spatial source — FreeMask 5.01 + его domain/policy provenance.

EmptyRegion[]

01 / connected components

Каждая связная компонента free mask становится отдельным EmptyRegion.

EmptyRegion

{
  regionId,
  freeMaskRef,
  domainRef,
  componentIndex,

  areaPx2,
  areaFractionOfFreeSpace,
  areaFractionOfDomain,

  touchesDomainBoundary,
  isInteriorPocket,

  boundaryRefs[],
  distanceFieldRef,
  maxClearance,

  exactness,
  confidence,
  provenance
}

Area identities

Σ regionArea = 5.01 freeArea ± tolerance regionShareOfFree = regionArea / freeArea regionShareOfDomain = regionArea / domainArea
INTERIOR POCKET ≠ GOOD/BAD. `isInteriorPocket=true` означает только, что free component не касается domain boundary. Интерпретация enclosure появляется в 5.03.

4/8 connectivity нельзя угадывать

02 / raster topology

В vector topology вопрос естественный. В raster fallback диагональное касание требует явной digital-topology policy.

Dual pair A

freeConnectivity = 4
occupiedConnectivity = 8

diagonal free cells
→ disconnected

Dual pair B

freeConnectivity = 8
occupiedConnectivity = 4

diagonal free cells
→ connected
NO 4/4 OR 8/8 DEFAULT BY ACCIDENT. Для raster topology policy должна быть explicit и dual, иначе foreground/background могут одновременно получить противоречивую diagonal connectivity.

FreeSpaceDistanceField

03 / clearance field

Clearance определяется внутри free region как расстояние до ближайшей границы именно этой свободной области.

For p ∈ EmptyRegion R: clearance_R(p) = min distance( p, ∂R ) ∂R includes: occupied-support boundary AND CompositionSpaceDomain boundary For p outside R: clearance = N/A NOT 0
EUCLIDEAN BY DEFAULT. Manhattan/Chebyshev distance допустимы только как отдельный declared backend/policy, но не могут молча подменить canonical Euclidean semantics.

Largest inscribed empty disk

04 / maximum clearance

Максимум clearance — геометрическая ёмкость одного EmptyRegion.

Maximum

r_max(R) = max over p∈R clearance_R(p) maxClearancePx = r_max maxClearanceShortN = r_max / shortSidePx

Meaning

center:
  maxClearancePoint

radius:
  maxClearancePx

disk:
  largest empty disk
  inscribed in R

NOT:
  corridor width
  whitespace score
  balance

BreathingRoomQuery

05 / local query

`Breathing room` в 5.02 — удобное имя для локального clearance query, а не эстетический verdict.

BreathingRoomQuery {
  queryId,
  point,
  freeMaskRef,
  distanceFieldRef,
  normalizationContextRef?
}

BreathingRoomQueryResult {
  queryPoint,
  regionId,
  localRadiusPx,
  localRadiusShortN?,
  status,
  confidence,
  provenance
}
RADIUS, NOT MARGIN SCORE. Даже большой localRadius не означает автоматически «достаточно воздуха». Нужный диапазон может зависеть от target/style и оценивается только в 5.04.

Край canvas — тоже граница

06 / domain boundary

Если free region касается края domain, clearance ограничивается и этим краем.

free region boundary = interfaces with OccupiedMask ∪ interfaces with outside(Domain) Therefore: a large empty corner does NOT have infinite clearance. Even an entirely empty bounded canvas: one EmptyRegion maxClearance = inradius(domain)

Per-region area ≠ total free area

07 / ownership of region area

5.01 и 5.02 делят ownership по масштабу объекта измерения.

MetricOwnerMeaning
space.mask.freeAreaPx25.01весь FreeMask
space.mask.freeFraction5.01весь FreeMask / domain
space.region.count5.02число connected free components
space.region.areaPx25.02площадь конкретного EmptyRegion
space.region.areaFractionOfFreeSpace5.02доля конкретного region внутри total free space

Sampling invariance и error bounds

08 / exact + fallback

Mean clearance намеренно не канонизирован: он легко зависит от raster resolution и measure weighting.

Preferred

VECTOR_MEDIAL
ANALYTIC

exact/controlled
distance to region boundary

Fallback

RASTER_EDT
RASTER_CENTER_SAMPLED

deterministic
declared cellSize
declared errorBound
Reference center-sampled fixture: continuous maximum location error ≤ √2 / 2 × cellSize Reported: approximate value + error bound + confidence Never hide raster resolution.

Clearance ≠ corridor width

09 / semantic boundary

Формула `2×radius` похожа на ширину только в специальных местах medial geometry.

5.02

Distance field, local radius, max inscribed radius.

5.03

Corridor/channel/enclosure relations и их region-object semantics.

5.04

Target-aware «слишком узко / достаточно / намеренно плотно».

NO WIDTH BY DOUBLING EVERYWHERE. На углах, около сложных препятствий и в открытых областях `2×clearance` не является универсальной channel-width metric.

Edge cases

10 / edge cases

Пустая область и отсутствие области — разные состояния.

CaseEmptyRegion result
FreeMask empty / domain fully occupiedregionCount=0; no zero-area pseudo-region
Domain completely freeобычно 1 boundary-touching region
two regions separated by occupied barrierregionCount=2
diagonal-only raster contactdepends explicitly on 4/8 connectivity policy
query on occupied pointbreathing room=N/A
query outside domainN/A
shortSidePx missingPx clearance valid; ShortN=N/A

Correction routing

11 / corrections

5.02 не расширяет пустоту сам.

Mask wrong

→ 5.01.

Geometry wrong

→ Topic 3.

Relation meaning

→ 5.03.

Too tight for target

→ 5.04 / future solver.

CORRECTION REQUEST != MUTATION. `maxClearance too small` не разрешает 5.02 автоматически уменьшать или раздвигать объекты.

Visual Lab

12 / visual lab

Connectedness и clearance показаны как geometry descriptors.

A · ONE CONNECTED REGION free wraps around obstacle · one component B · TWO REGIONS full barrier splits free mask into 2 C · INTERIOR POCKET does not touch domain boundary D · LOCAL BREATHING RADIUS radius = distance(query point, nearest free-region boundary) maxClearance = largest inscribed radius NOT corridor width everywhere NOT whitespace quality 5.03 interprets spatial relations

Reference region / clearance tests

13 / deterministic tests

Reference runner использует binary cell-union geometry: connected components exact for declared digital topology; clearance — deterministic center-sampled Euclidean approximation with explicit cell scale.

Tests not run yet.

DATA FOR LAYOUT ENGINE

14 / machine contract

Machine-readable contract 5.02.

{
  "module": "Compo 5.02",
  "name": "connected_empty_regions_clearance_and_breathing_room",
  "version": "1.1-corrective",
  "scope": "CONNECTED_FREE_SPACE_REGIONS_DISTANCE_TO_FREE_BOUNDARY_AND_LOCAL_BREATHING_ROOM",
  "consumes": [
    "Compo5.01.SpaceMaskPairResult",
    "Compo5.01.FreeSpaceMaskResult",
    "Compo5.00.CompositionSpaceDomain",
    "SpaceRegionTopologyPolicy",
    "DistanceMetricPolicy",
    "CanvasNormalizationContext.shortSidePx? from external owner",
    "vector/raster mask representation adapter"
  ],
  "provides": [
    "EmptyRegion",
    "EmptyRegionSet",
    "FreeSpaceDistanceField",
    "ClearanceMaximumDescriptor",
    "BreathingRoomQuery",
    "BreathingRoomQueryResult",
    "MetricResult[space.region.count]",
    "MetricResult[space.region.areaPx2]",
    "MetricResult[space.region.areaFractionOfFreeSpace]",
    "MetricResult[space.region.areaFractionOfDomain]",
    "MetricResult[space.region.maxClearancePx]",
    "MetricResult[space.region.maxClearanceShortN]",
    "MetricResult[space.region.confidence]",
    "SpaceRegionCorrectionRequest[]"
  ],
  "owns_metrics": [
    "space.region.count",
    "space.region.areaPx2",
    "space.region.areaFractionOfFreeSpace",
    "space.region.areaFractionOfDomain",
    "space.region.maxClearancePx",
    "space.region.maxClearanceShortN",
    "space.region.confidence"
  ],
  "descriptors_only": [
    "space.region.regionId",
    "space.region.componentIndex",
    "space.region.touchesDomainBoundary",
    "space.region.isInteriorPocket",
    "space.region.boundaryRefs[]",
    "space.region.maxClearancePoint",
    "space.region.distanceFieldRef",
    "space.region.exactness",
    "space.region.approximationErrorBoundPx",
    "space.region.status",
    "space.breathingRoom.localRadiusPx",
    "space.breathingRoom.localRadiusShortN",
    "space.breathingRoom.queryPoint",
    "space.breathingRoom.status",
    "space.region.setStatus"
  ],
  "empty_region_schema": {
    "regionId": "stable deterministic id inside mask/version",
    "freeMaskRef": "Compo5.01 ref",
    "domainRef": "same CompositionSpaceDomain",
    "componentIndex": "integer >=0",
    "areaPx2": "region-specific area; sum across regions equals 5.01 freeAreaPx2 within tolerance",
    "areaFractionOfFreeSpace": "regionArea / totalFreeArea",
    "areaFractionOfDomain": "regionArea / domainArea",
    "touchesDomainBoundary": "boolean geometric descriptor",
    "isInteriorPocket": "!touchesDomainBoundary descriptor only; not a quality judgment",
    "boundaryRefs": "resolved free-region boundary refs[]",
    "distanceFieldRef": "FreeSpaceDistanceField ref",
    "maxClearance": "ClearanceMaximumDescriptor",
    "exactness": "EXACT|BOUNDED_APPROXIMATION",
    "confidence": "0..1",
    "provenance": "object"
  },
  "distance_field_schema": {
    "fieldRef": "string",
    "regionId": "EmptyRegion ref",
    "metric": "EUCLIDEAN_TO_FREE_REGION_BOUNDARY",
    "definition": "for p inside region, distance to nearest point on boundary of the same free region; boundary includes occupied-support boundary and CompositionSpaceDomain boundary",
    "representation": "ANALYTIC|VECTOR_MEDIAL|RASTER_EDT|RASTER_CENTER_SAMPLED|CUSTOM",
    "queryDomain": "inside the free region only",
    "outsideOrOccupied": "N_A, not zero",
    "errorBoundPx": "required for approximation",
    "confidence": "0..1",
    "provenance": "object"
  },
  "clearance_semantics": {
    "localClearance": "distance from a free-space point to nearest boundary of its free region",
    "maxClearancePx": "maximum localClearance over one EmptyRegion; radius of a largest inscribed empty disk under the declared geometry/approximation",
    "maxClearanceShortN": "maxClearancePx / shortSidePx when normalization context is valid",
    "breathingRoom": "query-level alias/consumer-facing descriptor for localClearance at an explicit point; not an aesthetic score",
    "diameter_note": "clearance is a radius. A local empty corridor width may be approximately 2*radius only in specific medial/channel geometry; corridor width semantics are deferred to 5.03"
  },
  "region_topology_policy": {
    "vector": "connected components of FreeMask under continuous planar topology",
    "raster": "connectivity must be explicit",
    "raster_allowed_pairs": [
      {
        "freeConnectivity": 4,
        "occupiedConnectivity": 8
      },
      {
        "freeConnectivity": 8,
        "occupiedConnectivity": 4
      }
    ],
    "dual_connectivity_reason": "avoid ambiguous diagonal foreground/background connectivity in digital topology",
    "default_reference_fixture": {
      "freeConnectivity": 4,
      "occupiedConnectivity": 8,
      "provenance": "STYLE_PRESET"
    }
  },
  "area_policy": {
    "region_area": "measure each connected free component",
    "sum_identity": "sum(region.areaPx2) = Compo5.01.freeAreaPx2 within mask exactness/error tolerance",
    "areaFractionOfFreeSpace": "regionArea/freeArea; N/A when freeArea=0 because there are no EmptyRegion records",
    "areaFractionOfDomain": "regionArea/domainArea",
    "ordering": "canonical serialization by area descending, then stable geometry/signature id; ordering is not quality"
  },
  "clearance_policy": {
    "preferred_metric": "Euclidean distance",
    "domain_boundary": "counts as free-region boundary",
    "occupied_boundary": "counts as free-region boundary",
    "other_free_regions": "not directly relevant because distinct components are separated by non-free boundary",
    "exact_vector": "analytic/medial-axis adapter when robust",
    "raster_fallback": "deterministic Euclidean distance transform / center-sampled bounded approximation",
    "sampling_error": "must be declared; reference center-sampling error <= sqrt(2)/2 cellSize for locating continuous maximum on a cell-union region",
    "mean_clearance": "not canonical in 5.02 because sampling/measure weighting policy would need a separate explicit integration contract"
  },
  "breathing_room_query_schema": {
    "queryId": "string",
    "point": "domain-coordinate point",
    "freeMaskRef": "5.01 ref",
    "distanceFieldRef": "5.02 ref",
    "normalizationContextRef": "optional",
    "returns": "localRadiusPx/localRadiusShortN/status/confidence/provenance"
  },
  "metric_policy": {
    "regionCount": "topological descriptor only",
    "regionArea": "region-specific geometry descriptor; total free area remains owned by 5.01",
    "maxClearance": "geometric capacity descriptor only",
    "breathingRoom": "local query descriptor only",
    "direct_scoring": "FORBIDDEN in 5.02",
    "more_regions_is_better": "FORBIDDEN",
    "larger_clearance_is_better": "FORBIDDEN",
    "larger_region_is_better": "FORBIDDEN",
    "target_interpretation": "deferred to Compo5.04"
  },
  "hard_constraints": [
    "one metric = one owner",
    "5.02 consumes the canonical FreeMask from 5.01 and must not rebuild occupied/free masks under new names",
    "sum of EmptyRegion areas must reconcile with 5.01 freeArea within declared tolerance",
    "raster connectivity policy must be explicit; 4/8 diagonal ambiguity must not be guessed",
    "FreeSpaceDistanceField is defined only inside free space; occupied/outside query is N/A, not zero breathing room",
    "CompositionSpaceDomain boundary participates in free-region boundary distance",
    "maxClearance is a radius, not corridor width",
    "mean clearance is not published without an explicit measure/integration policy",
    "isInteriorPocket is a topology descriptor only and not enclosure/figure-ground interpretation",
    "region-object ownership/enclosure/channel/corridor relations remain Compo5.03",
    "5.01 total freeArea/freeFraction ownership is retained; 5.02 owns only per-region area descriptors and region count",
    "4.01 hullOccupancy remains unrelated object-internal metric",
    "visual mass remains Topic4",
    "canvas short-side normalization is consumed from external owner, not owned",
    "more clearance or more free regions is not universally better",
    "zero free area yields zero EmptyRegions, not one zero-area region",
    "explicit full-free domain may yield one boundary-touching EmptyRegion",
    "N/A != 0",
    "no local whitespace quality score in 5.02",
    "global balance/hierarchy/eye-flow remain future owners",
    "no beautyScore",
    "EmptyRegionSet must carry status so an explicit zero-region result is distinguishable from missing region evidence",
    "5.04 must consume EmptyRegionSet.status; undefined/missing regions must never be interpreted as regionCount=0"
  ],
  "initial_heuristics": {
    "region_area_reconciliation_tolerance_px2": {
      "value": 1e-06,
      "provenance": "IMPLEMENTATION_HEURISTIC"
    },
    "distance_epsilon_px": {
      "value": 1e-09,
      "provenance": "IMPLEMENTATION_HEURISTIC"
    },
    "reference_raster_connectivity": {
      "value": {
        "freeConnectivity": 4,
        "occupiedConnectivity": 8
      },
      "provenance": "STYLE_PRESET"
    }
  },
  "correction_policy": {
    "foreign_mask_mutation": "FORBIDDEN",
    "mask_inconsistency": "route to Compo5.01",
    "domain_issue": "route to canvas/domain owner",
    "distance_backend_failure": "request exact/fallback distance-field adapter with explicit error bound",
    "connectivity_policy_missing": "request explicit SpaceRegionTopologyPolicy",
    "region_object_relation_issue": "route to Compo5.03",
    "whitespace_target_issue": "route to Compo5.04",
    "object_geometry_issue": "route to Topic3 owner"
  },
  "deferred_inputs": [
    "Compo5.03 figure-ground / enclosure / corridor / channel relations",
    "Compo5.04 target-aware scoring/corrections/regression",
    "Topic6 canonical canvas/format normalization",
    "future global balance/hierarchy/eye-flow"
  ],
  "recompute_when": [
    "5.01 FreeMask changes",
    "CompositionSpaceDomain changes",
    "raster/vector connectivity/topology policy changes",
    "distance metric/backend changes",
    "normalization shortSidePx changes",
    "mask approximation/error policy changes"
  ],
  "finality": "CONNECTED_FREE_REGION_AND_CLEARANCE_GEOMETRY_ONLY",
  "empty_region_set_schema": {
    "freeMaskRef": "Compo5.01 ref",
    "status": "OK|PARTIAL|N_A|INVALID",
    "regions": "EmptyRegion[]",
    "regionCount": "integer >=0 only when status=OK",
    "freeAreaPx2": "copied/reference value from 5.01 for reconciliation only; ownership stays 5.01",
    "topologyPolicyRef": "explicit vector/raster connectivity policy",
    "confidence": "0..1",
    "provenance": "object",
    "zero_vs_missing": "status=OK + regions=[] means valid zero free regions; status=N_A/PARTIAL is missing/incomplete evidence"
  }
}
ARCHITECTURE CHECKPOINT · 5.02 OWNS CONNECTED EMPTY REGIONS, PER-REGION AREA DESCRIPTORS, EUCLIDEAN FREE-REGION DISTANCE FIELD, MAX CLEARANCE RADIUS AND LOCAL BREATHING-ROOM QUERY. 5.01 RETAINS OCCUPIED/FREE MASK AND TOTAL FREE AREA/FRACTION OWNERSHIP. RASTER CONNECTIVITY MUST BE EXPLICIT AND DUAL. DOMAIN BOUNDARY PARTICIPATES IN CLEARANCE. MAXCLEARANCE IS A RADIUS, NOT UNIVERSAL CORRIDOR WIDTH OR WHITESPACE QUALITY. REGION↔OBJECT / ENCLOSURE / CHANNEL RELATIONS → 5.03; TARGET SCORING → 5.04. NO BEAUTYSCORE.
VISITS / ...