Силуэт = topology + читаемость
3.03 принимает уже построенную boundary geometry и отвечает на другой вопрос: насколько её topology и значимые contour features соответствуют явному silhouette target.
Silhouette topology class, feature-scale descriptors, simplification stability и target-aware readability.
Raw path → 3.02; holes/convexity → 3.04; transform → 3.05; aggregate/generator → 3.06.
LOCAL SILHOUETTE READABILITY ONLY.
SilhouetteBoundaryView
3.03 не копирует control points и path segments. Он получает adapter-view поверх boundary geometry, чтобы одинаково работать с primitive conversion, organic path и позже с compound boundary.
Boundary view
SilhouetteBoundaryView {
boundaryRef,
closed,
componentCount,
intersectionEvents[],
windingDirection,
sampleByArcFraction(q),
tangentByArcFraction(q),
localBounds,
exactness,
confidence
}Not owned here
segments[] // 3.02 controlPoints[] // 3.02 fillRule // 3.04 holes[] // 3.04 convexity // 3.04 ObjectTransform // Core / 3.05 silhouetteArea // Topic 4 visualMass // Topic 4
Topology class без fill semantics
Классификация silhouette boundary нужна до эстетической интерпретации. Но holes/inside-outside fill semantics не переезжают сюда из 3.04.
| Class | Condition | Meaning |
|---|---|---|
SIMPLE_CLOSED | closed, one component, no proper crossings | обычный однокомпонентный silhouette boundary |
OPEN | closure gap beyond owner tolerance | не готовая filled silhouette region |
SELF_INTERSECTING | proper crossing events > 0 | non-simple boundary; target may allow or forbid |
DEGENERATE | collapsed / insufficient geometry | неустойчивый silhouette |
MULTI_COMPONENT_EXTERNAL | componentCount > 1 from pre-resolved external/later-pass adapter | только topology fact; 3.03 не создаёт same-pass dependency на 3.04, hole semantics остаются 3.04 |
topologyClass = descriptor. topologyFit появляется только при explicit target.Значимые features, не segment count
Readability зависит не от количества Bézier segments, а от воспринимаемых изменений направления/характера boundary. Поэтому segmentation details должны подавляться.
Feature scale и различимость
Мелкие детали могут исчезать при уменьшении, но минимальная дистанция между features — всё ещё геометрический descriptor. Нужен target, чтобы решить, допустим ли такой scale.
Separation
minimumFeatureSeparationN — нормализованная дистанция между значимыми events.
Scale
Feature scale относительно local bounds/short side, без scene occupancy.
Target
ICONIC_SIMPLE может требовать крупнее features; COMPLEX_ALLOWED — нет.
Устойчивость силуэта при упрощении
Один из полезных признаков readability — сохраняется ли характер boundary при bounded simplification. Это не требует silhouette area и поэтому не забирает Topic 4.
SilhouetteReadabilityTarget
Target задаёт, какой тип silhouette нужен. FREE означает descriptors only.
Target
SilhouetteReadabilityTarget {
profile:
"ICONIC_SIMPLE" |
"ORGANIC_CLEAR" |
"SYMBOLIC" |
"COMPLEX_ALLOWED" |
"FREE",
allowedTopologyClasses[],
featureCountRange?,
featureScaleRange?,
minSimplificationStability?,
selfIntersectionPolicy?,
requiredEvidencePolicy?
}No target
topologyClass → available feature descriptors → available stability descriptors → available topologyFit = N/A featureScaleFit = N/A readabilityFit = N/A localReadabilityScore = N/A N/A != 0
Composite-first handoff → 3.06
Сразу используем зрелый contract, чтобы не повторять историю 2.15–2.18. У 3.03 есть один primary vote; компоненты при активном composite остаются diagnostics.
localReadabilityScore
key: shape.silhouette.localReadabilityScore owner: Compo3.03 scoringGroup: SILHOUETTE_READABILITY composite: true componentOf: null independentVoteAllowed: false
Diagnostic by default
topologyFit featureScaleFit simplificationStabilityFit readabilityFit componentOf: shape.silhouette.localReadabilityScore
Одинаковый факт — разные target verdicts
3.03 специально отделяет descriptor и интерпретацию.
| Descriptor fact | ICONIC_SIMPLE | COMPLEX_ALLOWED |
|---|---|---|
| 12 salient features | может снижать feature-scale/readability fit | может быть полностью допустимо |
| 1 proper self-intersection | обычно topology mismatch | допустимо, если policy=ALLOW |
| low simplification stability | может быть mismatch | не обязательно проблема |
| large clear features | часто подходит | нейтральный факт |
Correction request, а не mutation
3.03 диагностирует mismatch и формулирует желаемый effect. Геометрию меняет 3.02 или generator 3.06.
Open contour
→ 3.02: close/repair boundary under its tolerance policy.
Tiny features
→ 3.02/3.06: merge/enlarge detail within target constraints.
Self-crossing
→ 3.02/3.06 only if target forbids it.
Hole semantics
→ 3.04; never reinterpret here.
SilhouetteCorrectionRequest {
sourceShapeId,
sourceMetricKey,
targetOwner: "Compo3.02|Compo3.04|Compo3.06",
requestedEffect,
constraints[],
evidenceRefs[],
provenance: "DERIVED"
}
Визуальная лаборатория
Пять silhouette cases: simple, complex-clear, tiny-detail, self-intersecting и simplification-stable. Цвет различает examples, а не quality.
Reference readability tests
Проверяем topology classification, target gate, composite-first metadata, segmentation invariance и no-owner-theft.
DATA FOR LAYOUT ENGINE
Machine-readable contract 3.03.
{
"module": "Compo 3.03",
"name": "silhouette_contour_readability_and_topology",
"version": "1.1-corrective",
"scope": "LOCAL_SILHOUETTE_TOPOLOGY_CLASSIFICATION_AND_TARGET_AWARE_READABILITY",
"consumes": [
"Compo3.00.Shape",
"Compo3.02.PathShapeGeometry or compatible SilhouetteBoundaryView",
"Compo3.02.ContourIntersectionEvent[]",
"Compo3.02.ContourWindingDirection",
"Compo3.01.PrimitiveToPathResult? as derived boundary source",
"GeometryToleranceContext?",
"SilhouetteReadabilityTarget?",
"PreResolvedCompoundBoundaryAdapter? (external or later-pass view; not a same-pass Compo3.04 dependency)"
],
"provides": [
"SilhouetteBoundaryView",
"SilhouetteTopologyDescriptor",
"SilhouetteFeatureDescriptor",
"SilhouetteSimplificationDescriptor",
"SilhouetteReadabilityResult",
"MetricResult[shape.silhouette.localReadabilityScore]",
"SilhouetteCorrectionRequest[]"
],
"owns_metrics": [
"shape.silhouette.topologyFit",
"shape.silhouette.featureScaleFit",
"shape.silhouette.simplificationStabilityFit",
"shape.silhouette.readabilityFit",
"shape.silhouette.localReadabilityScore",
"shape.silhouette.confidence"
],
"descriptors_only": [
"shape.silhouette.topologyClass",
"shape.silhouette.salientFeatureCount",
"shape.silhouette.minimumFeatureSeparationN",
"shape.silhouette.simplificationStability",
"shape.silhouette.boundaryDistanceN",
"shape.silhouette.intersectionBurden",
"shape.silhouette.openGapN",
"shape.silhouette.readabilityStatus"
],
"topology_classes": [
"SIMPLE_CLOSED",
"OPEN",
"SELF_INTERSECTING",
"DEGENERATE",
"MULTI_COMPONENT_EXTERNAL"
],
"target_profiles": [
"ICONIC_SIMPLE",
"ORGANIC_CLEAR",
"SYMBOLIC",
"COMPLEX_ALLOWED",
"FREE"
],
"metric_exports": {
"primary_vote": {
"key": "shape.silhouette.localReadabilityScore",
"owner": "Compo3.03",
"scoringGroup": "SILHOUETTE_READABILITY",
"composite": true,
"componentOf": null,
"dependsOn": [
"shape.silhouette.topologyFit",
"shape.silhouette.featureScaleFit",
"shape.silhouette.simplificationStabilityFit",
"shape.silhouette.readabilityFit"
],
"derivedFrom": [
"Compo3.02.ContourIntersectionEvent[]",
"Compo3.02.ContourClosureResult",
"shape.silhouette.salientFeatureCount",
"shape.silhouette.minimumFeatureSeparationN",
"shape.silhouette.simplificationStability"
],
"independentVoteAllowed": false
},
"components": [
{
"key": "shape.silhouette.topologyFit",
"componentOf": "shape.silhouette.localReadabilityScore",
"scoringGroup": "SILHOUETTE_READABILITY",
"independentVoteAllowed": false
},
{
"key": "shape.silhouette.featureScaleFit",
"componentOf": "shape.silhouette.localReadabilityScore",
"scoringGroup": "SILHOUETTE_READABILITY",
"independentVoteAllowed": false
},
{
"key": "shape.silhouette.simplificationStabilityFit",
"componentOf": "shape.silhouette.localReadabilityScore",
"scoringGroup": "SILHOUETTE_READABILITY",
"independentVoteAllowed": false
},
{
"key": "shape.silhouette.readabilityFit",
"componentOf": "shape.silhouette.localReadabilityScore",
"scoringGroup": "SILHOUETTE_READABILITY",
"independentVoteAllowed": false
}
],
"diagnostic_only": [
"shape.silhouette.topologyClass",
"shape.silhouette.salientFeatureCount",
"shape.silhouette.minimumFeatureSeparationN",
"shape.silhouette.simplificationStability",
"shape.silhouette.boundaryDistanceN",
"shape.silhouette.intersectionBurden",
"shape.silhouette.openGapN",
"shape.silhouette.confidence"
]
},
"metric_policy": {
"primary_vote": "shape.silhouette.localReadabilityScore",
"components": "DIAGNOSTIC_ONLY_BY_DEFAULT_WHEN_COMPOSITE_ACTIVE",
"explicit_target_required": true,
"no_target": "RETURN_DESCRIPTORS_AND_NA_SCORE",
"raw_complexity_not_monotonic_quality": true,
"self_intersection_not_universal_penalty": true,
"simpler_not_universally_better": true
},
"silhouette_boundary_view": {
"boundaryRef": "source contour/path reference",
"closed": "boolean",
"componentCount": "integer >=1 when externally supplied",
"intersectionEvents": "refs to Compo3.02 events",
"windingDirection": "CW|CCW|DEGENERATE",
"sampleByArcFraction": "adapter function",
"tangentByArcFraction": "adapter function",
"localBounds": "geometry support box",
"exactness": "EXACT|BOUNDED_APPROXIMATION",
"confidence": "0..1"
},
"topology_policy": {
"SIMPLE_CLOSED": "closed + one component + no proper self-intersections",
"OPEN": "not closed beyond owner tolerance",
"SELF_INTERSECTING": "one or more proper self-intersections in boundary locus",
"DEGENERATE": "insufficient or collapsed boundary geometry",
"MULTI_COMPONENT_EXTERNAL": "componentCount>1 supplied by a pre-resolved external/later-pass compound-boundary adapter; 3.03 does not derive hole semantics"
},
"readability_evidence": {
"salientFeatureCount": "count of direction/curvature events after tolerance-aware suppression; descriptor only",
"minimumFeatureSeparationN": "minimum normalized arc/spatial separation between salient features; descriptor only",
"simplificationStability": "topology + normalized boundary-distance stability under bounded simplification",
"intersectionBurden": "normalized proper-crossing burden; descriptor only",
"openGapN": "normalized closure gap; descriptor only"
},
"hard_constraints": [
"raw path geometry stays owned by Compo3.02",
"holes/fill rule/convexity/concavity stay owned by Compo3.04",
"object transform stays external/Core and shape-side adapter Compo3.05",
"silhouette area/occupancy/visual mass stay owned by Topic4",
"scene free space stays owned by Topic5",
"global balance/hierarchy/eye-flow are not computed here",
"feature count or complexity is never a universal beauty rule",
"self-intersection may be allowed by explicit target; do not hard-ban aesthetically in all profiles",
"no explicit target means localReadabilityScore=N/A",
"no beautyScore",
"3.03 must not require Compo3.04 output in the same evaluation pass; compound silhouette view is external/pre-resolved or evaluated in a later pass"
],
"initial_heuristics": {
"salient_turn_threshold_deg": {
"value": 18,
"provenance": "INITIAL_HEURISTIC"
},
"feature_merge_arc_fraction": {
"value": 0.03,
"provenance": "INITIAL_HEURISTIC"
},
"small_feature_separation_shortN": {
"value": 0.015,
"provenance": "INITIAL_HEURISTIC"
},
"simplification_error_shortN": {
"value": 0.0025,
"provenance": "INITIAL_HEURISTIC"
},
"boundary_distance_tau_shortN": {
"value": 0.01,
"provenance": "INITIAL_HEURISTIC"
}
},
"correction_policy": {
"direct_foreign_geometry_mutation": "FORBIDDEN",
"open_or_broken_contour": "request Compo3.02 correction",
"feature_scale_problem": "request bounded contour edit from Compo3.02/3.06",
"holes_or_compound_topology": "route to Compo3.04",
"transform_based_visibility_issue": "route to Compo3.05",
"target_profile_change": "caller/Compo3.06"
},
"deferred_inputs": [
"Compo3.04 hole/fill topology and convexity/concavity",
"Compo3.05 transformed world silhouette",
"Compo3.06 candidate generation and local shape aggregation",
"Topic4 silhouette area/occupancy/visual mass",
"Topic5 positive/negative space",
"global hierarchy/balance/eye-flow"
],
"recompute_when": [
"source contour geometry changes",
"source intersection evidence changes",
"closure/winding changes",
"readability target changes",
"salience/simplification tolerance policy changes",
"compatible compound-boundary adapter changes component topology"
],
"finality": "LOCAL_SILHOUETTE_READABILITY_ONLY"
}