Region topology, не новый silhouette owner
3.04 берёт closed boundaries и превращает их в filled-region structure: outer regions, holes, fill semantics, outline operation и convex/concave descriptors.
Compound region topology, fill rule, holes, outline placement, convexity/concavity descriptors и target-aware fit.
Raw contour → 3.02; silhouette readability → 3.03; transform → 3.05; scoring aggregation → 3.06.
LOCAL SHAPE REGION TOPOLOGY ONLY.
CompoundShapeGeometry
Ring, donut, буква O, несколько disconnected filled components — это не новые primitive family. Они представлены boundary set + region graph + fill rule.
Compound
CompoundShapeGeometry {
kind: "COMPOUND",
boundaryRefs[],
regionGraph,
fillRule:
"EVEN_ODD|NON_ZERO",
outerRegionRefs[],
holeRegionRefs[],
exactness,
provenance
}Region graph
RegionNestingTree {
nodes: [{
boundaryRef,
parentRef?,
nestingDepth,
windingDirection?,
resolvedRole:
"OUTER|HOLE|ISLAND|UNRESOLVED"
}]
}EVEN_ODD и NON_ZERO
Fill semantics должна быть явной. Иначе одинаковый набор contours может давать разные filled regions.
Parity
Winding sum
Outer, hole, island
Nested contours образуют дерево. При EVEN_ODD depth parity даёт alternating fill/hole/island. При NON_ZERO решающим становится winding accumulation.
| Depth | EVEN_ODD | Possible semantic role |
|---|---|---|
| 0 | filled | OUTER |
| 1 | empty | HOLE |
| 2 | filled | ISLAND |
| 3 | empty | nested HOLE |
Outline — derived band, не source mutation
Outline может идти по центру boundary, внутрь filled region или наружу. Width/style меняют derived paint region, но не исходные contour points.
No outline
Fill region only.
Centered
Band extends both sides of source boundary.
Inside
Derived band constrained toward filled side.
Outside
Derived band expands outside filled region.
OutlineOperationDescriptor {
sourceBoundaryRefs[],
placement,
width,
derivedBandGeometryRef?,
exactness,
errorBound?,
provenance
}
Convexity без area ratio
Чтобы не забирать Topic 4, convexity определяется structural geometry: sign-consistent turns/support behavior и stable reflex features, а не area(shape)/area(hull).
Polygonal exact
Smooth / curved
Reflex events и indentation depth
Concavity может описываться без заполненной площади: stable reflex event + геометрическая глубина indentation относительно convex support/hull.
ConcavityFeature {
qArc,
positionN,
reflexTurnDeg?,
indentationDepthN,
featureScaleN,
exactness,
confidence,
provenance
}
ShapeRegionTarget
Только target превращает region descriptors в fit-компоненты.
Target
ShapeRegionTarget {
allowedFillRules?,
holeCountRange?,
maxNestingDepth?,
allowedOutlineModes?,
convexityPreference?:
"CONVEX|CONCAVE|ANY",
reflexFeatureCountRange?,
indentationDepthRange?,
requiredEvidencePolicy?
}No target
holeCount → descriptor fillRule → descriptor outlinePlacement → descriptor convexityClass → descriptor concavityFeatures → descriptor holeStructureFit = N/A convexityFit = N/A localTopologyFit = N/A
Composite-first handoff → 3.06
3.04 отдаёт один composite vote. Hole count, convexity class и indentation depth напрямую в scorer не голосуют.
localTopologyFit
key: shape.region.localTopologyFit owner: Compo3.04 scoringGroup: SHAPE_REGION_TOPOLOGY composite: true componentOf: null independentVoteAllowed: false
Diagnostic by default
holeStructureFit fillRuleFit outlineModeFit convexityFit componentOf: shape.region.localTopologyFit
Validity и неоднозначность
Region topology нельзя «починить» эстетическим score.
| Case | Status | Policy |
|---|---|---|
| fill rule missing for ambiguous compound path | UNRESOLVED | caller/import owner supplies semantics |
| hole boundary lies outside claimed outer | INVALID RELATION | geometry correction request |
| two boundaries overlap/coincide | AMBIGUOUS | exact boolean resolver or correction |
| self-intersecting unresolved contour | INDETERMINATE CONVEXITY | do not force convex/concave |
| zero outline width | canonical NONE or zero-band descriptor | policy-driven normalization |
| holeCount target missing | N/A fit | not zero |
Owner исправляет своё
3.04 может изменить собственные paint/topology parameters, но contour geometry и transform остаются чужими.
Fill rule
3.04 may patch ShapePaintRef.
Outline
3.04 may derive band / change own placement.
Contour shape
→ 3.02 / 3.06 correction request.
Transform
→ Core / 3.05.
Визуальная лаборатория
Ring, nested island, convex/concave outer boundary и outline placement. Примеры не ранжируются.
Reference topology tests
Проверяем fill rules, nesting parity, convexity classification, target gate, composite metadata и no-owner-theft.
DATA FOR LAYOUT ENGINE
Machine-readable contract 3.04.
{
"module": "Compo 3.04",
"name": "shape_fill_outline_holes_convexity_concavity",
"version": "1.1-corrective",
"scope": "LOCAL_SHAPE_REGION_TOPOLOGY_PAINT_STRUCTURE_AND_CONVEXITY_INTERPRETATION",
"consumes": [
"Compo3.00.Shape",
"Compo3.02.PathShapeGeometry or compatible closed boundary adapters",
"Compo3.03.SilhouetteTopologyDescriptor?",
"Compo3.01.PrimitiveToPathResult?",
"GeometryToleranceContext?",
"ShapeRegionTarget?"
],
"provides": [
"CompoundShapeGeometry",
"ShapePaintRef",
"FillTopologyDescriptor",
"RegionNestingTree",
"HoleDescriptor[]",
"OutlineOperationDescriptor",
"ConvexityDescriptor",
"ConcavityFeature[]",
"ShapeRegionFitResult",
"MetricResult[shape.region.localTopologyFit]",
"ShapeRegionCorrectionRequest[]"
],
"owns_metrics": [
"shape.region.holeStructureFit",
"shape.region.fillRuleFit",
"shape.region.outlineModeFit",
"shape.region.convexityFit",
"shape.region.localTopologyFit",
"shape.region.confidence"
],
"descriptors_only": [
"shape.region.componentCount",
"shape.region.holeCount",
"shape.region.nestingDepth",
"shape.region.fillRule",
"shape.region.outlinePlacement",
"shape.region.convexityClass",
"shape.region.reflexFeatureCount",
"shape.region.maxIndentationDepthN",
"shape.region.concavityFeatures[]",
"shape.region.regionGraph"
],
"fill_rules": [
"EVEN_ODD",
"NON_ZERO"
],
"outline_modes": [
"NONE",
"CENTER",
"INSIDE",
"OUTSIDE"
],
"convexity_classes": [
"CONVEX",
"CONCAVE",
"DEGENERATE",
"INDETERMINATE"
],
"metric_exports": {
"primary_vote": {
"key": "shape.region.localTopologyFit",
"owner": "Compo3.04",
"scoringGroup": "SHAPE_REGION_TOPOLOGY",
"composite": true,
"componentOf": null,
"dependsOn": [
"shape.region.holeStructureFit",
"shape.region.fillRuleFit",
"shape.region.outlineModeFit",
"shape.region.convexityFit"
],
"derivedFrom": [
"shape.region.componentCount",
"shape.region.holeCount",
"shape.region.nestingDepth",
"shape.region.convexityClass",
"shape.region.reflexFeatureCount",
"shape.region.maxIndentationDepthN"
],
"independentVoteAllowed": false
},
"components": [
{
"key": "shape.region.holeStructureFit",
"componentOf": "shape.region.localTopologyFit",
"scoringGroup": "SHAPE_REGION_TOPOLOGY",
"independentVoteAllowed": false
},
{
"key": "shape.region.fillRuleFit",
"componentOf": "shape.region.localTopologyFit",
"scoringGroup": "SHAPE_REGION_TOPOLOGY",
"independentVoteAllowed": false
},
{
"key": "shape.region.outlineModeFit",
"componentOf": "shape.region.localTopologyFit",
"scoringGroup": "SHAPE_REGION_TOPOLOGY",
"independentVoteAllowed": false
},
{
"key": "shape.region.convexityFit",
"componentOf": "shape.region.localTopologyFit",
"scoringGroup": "SHAPE_REGION_TOPOLOGY",
"independentVoteAllowed": false
}
],
"diagnostic_only": [
"shape.region.componentCount",
"shape.region.holeCount",
"shape.region.nestingDepth",
"shape.region.convexityClass",
"shape.region.reflexFeatureCount",
"shape.region.maxIndentationDepthN",
"shape.region.concavityFeatures[]",
"shape.region.confidence"
]
},
"metric_policy": {
"primary_vote": "shape.region.localTopologyFit",
"components": "DIAGNOSTIC_ONLY_BY_DEFAULT_WHEN_COMPOSITE_ACTIVE",
"explicit_target_required": true,
"no_target": "RETURN_DESCRIPTORS_AND_NA_SCORE",
"convex_is_not_universally_better": true,
"fewer_holes_is_not_universally_better": true,
"outline_is_not_universally_better": true,
"fill_rule_is_semantic_not_aesthetic_by_default": true
},
"compound_geometry": {
"kind": "COMPOUND",
"boundaryRefs": "closed boundary references",
"regionGraph": "containment/nesting relations",
"fillRule": "EVEN_ODD|NON_ZERO",
"outerRegionRefs": "resolved filled outer regions",
"holeRegionRefs": "resolved hole regions",
"exactness": "EXACT|BOUNDED_APPROXIMATION",
"provenance": "object"
},
"paint_ref": {
"fillEnabled": "boolean",
"fillStyleRef": "external paint/style reference; 3.04 does not own color harmony",
"outlineEnabled": "boolean",
"outlinePlacement": "NONE|CENTER|INSIDE|OUTSIDE",
"outlineWidth": "explicit units or style preset",
"outlineStyleRef": "external paint/style reference",
"fillRule": "EVEN_ODD|NON_ZERO"
},
"convexity_policy": {
"polygonal_exact": "all non-zero turn signs consistent => CONVEX; any reflex turn => CONCAVE",
"smooth_or_curved": "use exact support/turn adapter when available; otherwise bounded polyline approximation with confidence",
"self_intersecting": "INDETERMINATE unless an explicitly resolved simple filled region adapter is supplied",
"holes": "filled region as a whole is not called convex when holes are present; boundary convexity and region convexity must be distinguished"
},
"concavity_features": {
"reflexFeatureCount": "count of stable reflex events after tolerance-aware merging",
"maxIndentationDepthN": "max normalized distance from concave boundary feature toward the convex support/hull representation",
"featureScaleN": "local normalized indentation span",
"provenance": "exact or bounded approximation"
},
"hard_constraints": [
"raw contour segment geometry remains owned by Compo3.02",
"silhouette readability/topology interpretation remains owned by Compo3.03",
"object transform remains Core/Compo3.05",
"fill rule determines filled-region semantics; winding direction alone must not be treated as hole identity",
"rings/holes are compound region topology, not primitive aliases",
"outline operation derives a new region/band and must not mutate the source contour",
"outline width or filled area must not be converted into visual mass here",
"silhouette area/occupancy/density remain Topic4",
"scene free space remains Topic5",
"global balance/hierarchy/eye-flow are not owned here",
"convexity/concavity descriptors are not universal beauty signals",
"no explicit target means localTopologyFit=N/A",
"no beautyScore"
],
"initial_heuristics": {
"reflex_turn_epsilon_deg": {
"value": 2.0,
"provenance": "INITIAL_HEURISTIC"
},
"concavity_feature_merge_arc_fraction": {
"value": 0.025,
"provenance": "INITIAL_HEURISTIC"
},
"indentation_depth_noise_shortN": {
"value": 0.0015,
"provenance": "INITIAL_HEURISTIC"
},
"outline_offset_approx_error_shortN": {
"value": 0.0005,
"provenance": "INITIAL_HEURISTIC"
}
},
"correction_policy": {
"direct_foreign_contour_mutation": "FORBIDDEN",
"invalid_outer_hole_relation": "request Compo3.02/3.06 geometry correction",
"fill_rule_mismatch": "patch ShapeRegionTarget/ShapePaintRef only",
"outline_mode_mismatch": "patch ShapePaintRef or request derived outline operation",
"convexity_target_mismatch": "request bounded contour edit via Compo3.02/3.06",
"transform_issue": "route to Compo3.05",
"color_or_paint_harmony_issue": "route to external paint/color owner"
},
"deferred_inputs": [
"Compo3.05 transformed world region",
"Compo3.06 candidate generation and local shape aggregation",
"Topic4 silhouette area/occupancy/visual mass",
"Topic5 positive/negative space",
"external paint/color harmony",
"global balance/hierarchy/eye-flow"
],
"recompute_when": [
"boundary set changes",
"boundary containment/nesting changes",
"fill rule changes",
"outline placement/width changes",
"region target changes",
"geometry tolerance/approximation policy changes"
],
"finality": "LOCAL_SHAPE_REGION_TOPOLOGY_ONLY",
"fill_rule_reference": {
"EVEN_ODD": "filled iff crossing parity is odd",
"NON_ZERO": "filled iff signed winding sum != 0",
"orientation_note": "NON_ZERO uses signed contributions; opposite windings may cancel",
"missing_fill_rule": "UNRESOLVED for ambiguous compound path"
}
}