COMPO · 3.02 · ORGANIC SHAPES / PATH CONTOURS

Органические
формы и
path-контуры.

Canonical local geometry для свободных замкнутых контуров: line/quad/cubic/arc segments, continuity, closure, exact bounds, traversal и raw self-intersection evidence. Модуль описывает геометрический contour, но не присваивает ему readability, convexity, visual mass или aesthetic score.

ModuleCompo 3.02
Scopesingle contour geometry
Ownspath / closure / raw events
Metricsnone
Topic3 · SHAPE
Next3.03

Органический contour = geometry contract

00 / module api

3.02 строит и валидирует один локальный contour формы. Он не решает читаемость силуэта и не превращает геометрию кривой в aesthetic score.

SCOPE

Single-contour path: segment graph, closure, bounds, point/tangent evaluation и raw intersections.

BOUNDARY

Topology/readability → 3.03; holes/compound → 3.04; transform → 3.05; scoring → 3.06.

FINALITY

LOCAL SINGLE-CONTOUR GEOMETRY ONLY.

CURVE ≠ LINE CURVATURE OWNER. 3.02 может геометрически вычислять производную/касательную своего contour для evaluation, но не копирует line metrics 2.04/2.18 и не создаёт новый curvature/tension score.

Segment graph

01 / canonical segments

Organic contour хранится как последовательность явных segment primitives. Необязательные spline-форматы нормализуются в canonical segments с provenance.

SegmentFieldsContract
LINEp0,p1exact straight boundary segment
QUADp0,c,p1quadratic Bézier; canonical or normalized to cubic by backend
CUBICp0,c1,c2,p1canonical organic contour workhorse
ARCcenter,rx,ry,startAngle,sweepAngle,axisRotationRad?analytic elliptical arc; no implicit full ellipse alias
ContourPath = S₀ → S₁ → ... → Sₙ₋₁ for every adjacent pair: end(Sᵢ) ≈ start(Sᵢ₊₁) if closed: end(Sₙ₋₁) ≈ start(S₀) A broken chain is not repaired silently.

PathShapeGeometry

02 / path schema

Как и в 3.01, local path geometry не содержит transform. World contour вычисляется позже через 3.05.

Canonical path

PathShapeGeometry {
  kind: "PATH",
  closed: true|false,
  segments: ContourSegment[],
  localBounds,
  exactness:
    "EXACT|BOUNDED_APPROXIMATION",
  source: OrganicContourSource,
  sourcePathHash,
  version,
  provenance
}

Organic source

OrganicContourSource =
  "EXPLICIT_SEGMENTS" |
  "ANCHORS_AND_HANDLES" |
  "SMOOTHED_POLYLINE" |
  "PRIMITIVE_CONVERSION" |
  "IMPORTED_PATH"

source != quality
controlPointCount != beauty

Bézier evaluation

03 / path math

Точки и касательные — чистая geometry. Они нужны bounds, conversion, intersections и downstream topology, но не голосуют эстетически.

Quadratic

B(t) = (1-t)² P₀ + 2(1-t)t C + t² P₁ B'(t) = 2(1-t)(C-P₀) + 2t(P₁-C)

Cubic

B(t) = (1-t)³P₀ +3(1-t)²tC₁ +3(1-t)t²C₂ +t³P₁ B'(t) = 3(1-t)²(C₁-P₀) +6(1-t)t(C₂-C₁) +3t²(P₁-C₂)
TANGENT N/A. Если derivative collapse даёт нулевой вектор, tangent возвращает N/A/degenerate evidence, а не произвольное направление.

Local bounds без occupancy

04 / exact bounds

Для Bézier bounds учитывают внутренние экстремумы, а не только anchors/control box. Но bounds всё равно не становятся silhouette area или occupancy.

CUBIC coordinate derivative: a t² + b t + c = 0 for x and y independently: solve derivative roots keep t ∈ (0,1) evaluate B(t) bounds = min/max(endpoints + valid extrema) ARC: include endpoints include analytic axis-extrema angles inside sweep BOUNDED_APPROXIMATION: bounds must include declared maxErrorBound provenance
BOUNDS ≠ MASS. localBounds — geometry support box. Silhouette area/occupancy/density принадлежат теме 4.

Closure и continuity

05 / closure

Форма-region требует замкнутого contour. При этом маленький numerical gap и настоящий semantic open contour — разные состояния.

CaseStatusPolicy
exact endpoint matchCLOSEDvalid
gap ≤ owner toleranceCLOSED_WITH_TOLERANCEsnap only under explicit normalization policy; retain provenance
gap > toleranceOPEN / UNRESOLVEDdo not invent closing segment
adjacent segment breakINVALID_CHAINcorrection request
zero-length segmentDEGENERATE_SEGMENTremove only if topology unchanged and provenance retained
N/A vs invalid. Open path как intermediate imported/source geometry может быть допустимым descriptor, но он не является готовой filled Shape region. Final region request требует explicit closure.

Reversal и winding

06 / traversal descriptors

Traversal order — часть path serialization, но геометрический locus сохраняется при reversal. Winding direction нужен downstream fill/topology, а величина signed area здесь не публикуется.

SCREEN +Y DOWN. В canonical screen coordinates положительный shoelace sign соответствует визуальному CW, отрицательный — CCW. Направление нельзя копировать из math +Y-up conventions без инверсии.

Reversal

reverse(path):
  reverse segment order
  swap segment endpoints
  CUBIC: c1 ↔ c2
  ARC: sweep sign flips

geometry locus = SAME
winding = FLIPS
start semantic may change

Winding descriptor

windingDirection =
  "CW" |
  "CCW" |
  "DEGENERATE"

implementation may use
signed shoelace/integration
internally,

but area magnitude is NOT
published as 3.02 owner metric.

Self-intersection: факт, не topology verdict

07 / raw intersection evidence

3.02 может определить, где contour пересекает сам себя. Но classification вроде simple/non-simple silhouette и её readability принадлежит 3.03.

ContourIntersectionEvent {
  segmentA,
  segmentB,
  point,
  tA,
  tB,
  kind:
    "PROPER_CROSS" |
    "TANGENT_TOUCH" |
    "OVERLAP" |
    "ENDPOINT_CONTACT",
  exactness,
  confidence,
  provenance
}
3.02: detects raw event 3.03: interprets event in silhouette/topology contract 3.04: decides fill/compound consequences if applicable 3.02 MUST NOT emit: topologyScore silhouetteReadabilityScore convexityScore

Organic path → polyline

08 / bounded approximation

Renderer или intersection backend может потребовать flattening. Approximation должна быть budgeted и иметь error bound, иначе sampling density начнёт менять topology.

ERROR

Bound

Каждая flattened curve несёт maxErrorBound в локальных/нормализованных единицах.

BUDGET

Segments

Есть maxSegments; бесконечное adaptive refinement запрещено.

CONFIDENCE

Fallback

Approximate intersection/bounds evidence получает соответствующий exactness/confidence.

SEGMENTATION INVARIANCE. Геометрически одинаковый contour, разбитый на другое число collinear/compatible segments, не должен получать другое downstream качество только из-за segment count.

Когда нужен другой owner

09 / ownership routing

3.02 не должен разрастаться в universal shape engine.

RequestOwner / route
parameteric rectangle/ellipse/star3.01
single freeform contour edit3.02
silhouette readability / topology interpretation3.03
multiple contours / holes / boolean / fill rule3.04
position / rotation / scale / reflection / skewCore ObjectTransform / 3.05
candidate search / shape target score3.06
silhouette area / visual massTopic 4
scene free-space / negative spaceTopic 5

Визуальная лаборатория

10 / visual lab

Один simple organic contour, reversed traversal, self-intersecting path и bounded flattened representation. Цвет не кодирует quality.

A · SIMPLE CLOSED CUBIC CONTOUR closed · single contour · no score B · SAME LOCUS / REVERSED same geometry · winding flips C · RAW SELF-INTERSECTION EVENT 3.02 detects event · 3.03 interprets topology D · BOUNDED FLATTENING approximation carries error bound + budget

Reference contour tests

11 / deterministic tests

Проверяем continuity, Bézier endpoints, reversal, winding, closure, intersections и no-owner-theft.

Tests not run yet.

DATA FOR LAYOUT ENGINE

12 / machine contract

Machine-readable contract 3.02.

{
  "module": "Compo 3.02",
  "name": "organic_shapes_and_path_contours",
  "version": "1.1-corrective",
  "scope": "LOCAL_SINGLE_CONTOUR_PATH_GEOMETRY_FOR_SHAPES",
  "consumes": [
    "Compo3.00.Shape",
    "Compo3.00.PathShapeGeometry interface",
    "Compo3.01.PrimitiveToPathResult? as optional derived source",
    "GeometryToleranceContext?"
  ],
  "provides": [
    "PathShapeGeometry",
    "ContourSegment[]",
    "ContourPathEvaluator",
    "ContourBoundsResult",
    "ContourClosureResult",
    "ContourIntersectionEvent[]",
    "ContourWindingDirection",
    "OrganicContourSource",
    "PathGeometryCorrectionRequest[]"
  ],
  "owns_contracts": [
    "single-contour segment graph",
    "LINE|QUAD|CUBIC|ARC segment schema",
    "segment continuity and closure validation",
    "local point/tangent evaluation along contour",
    "exact or bounded local contour bounds",
    "raw self-intersection event detection",
    "winding direction descriptor without publishing area magnitude"
  ],
  "owns_metrics": [],
  "descriptors_only": [
    "closed",
    "segmentCount",
    "segmentKinds[]",
    "localBounds",
    "startPoint",
    "endPoint",
    "closureGap",
    "windingDirection",
    "intersectionEvents[]",
    "exactness",
    "approximationErrorBound",
    "sourcePathHash"
  ],
  "segment_types": {
    "LINE": {
      "exact": true
    },
    "QUAD": {
      "exact": true
    },
    "CUBIC": {
      "exact": true
    },
    "ARC": {
      "exact": true
    }
  },
  "path_schema": {
    "kind": "PATH",
    "closed": "boolean",
    "segments": "ContourSegment[]",
    "localBounds": "Rect",
    "exactness": "EXACT|BOUNDED_APPROXIMATION",
    "source": "OrganicContourSource",
    "version": "string|integer",
    "provenance": "object"
  },
  "organic_source_types": [
    "EXPLICIT_SEGMENTS",
    "ANCHORS_AND_HANDLES",
    "SMOOTHED_POLYLINE",
    "PRIMITIVE_CONVERSION",
    "IMPORTED_PATH"
  ],
  "canonicalization": {
    "adjacent_segment_endpoints": "must match within owner tolerance or be INVALID/UNRESOLVED; never silently bridge large gaps",
    "closed_path": "last endpoint must equal first endpoint within tolerance; closure is explicit",
    "phase_or_start_index": "canonical serialization may rotate start index only when semantic anchor is absent",
    "reversal": "changes traversal/winding but must preserve unordered geometric locus",
    "duplicate_zero_length_segments": "remove only when provenance is retained and topology is unchanged",
    "catmull_rom_or_spline_inputs": "normalize to canonical CUBIC segments with explicit conversion provenance"
  },
  "boundary_interface": {
    "pointAt": "(q01) -> Point; q is normalized arc-length fraction when available",
    "tangentAt": "(q01) -> Vector|N/A",
    "localBounds": "() -> Rect",
    "intersections": "() -> ContourIntersectionEvent[]",
    "windingDirection": "() -> CW|CCW|DEGENERATE",
    "toPolyline": "(errorPolicy) -> BoundedApproximation"
  },
  "hard_constraints": [
    "final filled shape contour requires closed=true; open contour is unresolved/non-region geometry unless explicitly used as an intermediate source",
    "segment chain continuity is required",
    "NaN/Infinity coordinates are invalid",
    "local geometry must not contain object position/rotation/scale/reflection/skew",
    "multiple outer contours or holes are outside 3.02 and route to 3.04",
    "raw self-intersection events may be reported here, but topology classification/readability belongs to 3.03",
    "winding direction may be exported; signed/absolute area magnitude is not a 3.02 owner metric",
    "curvature/tension scoring from line topic 2.04/2.18 must not be copied as shape-contour quality metrics",
    "visual mass / silhouette area / occupancy are not owned here",
    "no beautyScore",
    "winding direction must follow canonical screen +Y-down convention",
    "ARC endpoints are derived from analytic arc parameters; runtime must not require undeclared p0/p1 fields"
  ],
  "initial_heuristics": {
    "closure_tolerance_shortN": {
      "value": 1e-05,
      "provenance": "INITIAL_HEURISTIC"
    },
    "polyline_approx_max_error_shortN": {
      "value": 0.0005,
      "provenance": "INITIAL_HEURISTIC"
    },
    "polyline_approx_max_segments": {
      "value": 512,
      "provenance": "IMPLEMENTATION_HEURISTIC"
    },
    "derivative_zero_epsilon": {
      "value": 1e-10,
      "provenance": "IMPLEMENTATION_HEURISTIC"
    }
  },
  "correction_policy": {
    "small_closure_gap": "may propose close endpoint within declared tolerance only if caller policy allows snap",
    "large_closure_gap": "request path owner/generator correction; do not auto-close",
    "broken_chain": "request segment endpoint correction",
    "self_intersection": "report event; interpretation/correction target may involve 3.03/3.06",
    "multiple_subpaths_or_holes": "route to Compo3.04",
    "transform_change": "route to Compo3.05/Core ObjectTransform"
  },
  "deferred_inputs": [
    "Compo3.03 silhouette readability and topology interpretation",
    "Compo3.04 fill rule / holes / convexity / concavity",
    "Compo3.05 transformed world contour",
    "Compo3.06 candidate generation / local shape scoring",
    "Topic4 silhouette area / occupancy / visual mass",
    "Topic5 scene free space",
    "global balance/hierarchy/eye-flow"
  ],
  "recompute_when": [
    "segment type or control point changes",
    "closure state changes",
    "geometry tolerance changes",
    "path normalization/conversion policy changes"
  ],
  "finality": "LOCAL_SINGLE_CONTOUR_GEOMETRY_ONLY",
  "coordinate_convention": {
    "screen_axes": "+X right, +Y down",
    "winding": "positive shoelace signed area in screen coordinates => CW; negative => CCW",
    "phase": "angles follow the inherited screen-coordinate convention"
  },
  "arc_contract": {
    "fields": [
      "center",
      "rx",
      "ry",
      "startAngle",
      "sweepAngle",
      "axisRotationRad?"
    ],
    "startPoint": "derived analytically at startAngle",
    "endPoint": "derived analytically at startAngle+sweepAngle",
    "reversal": "startAngle += sweepAngle; sweepAngle = -sweepAngle; geometric locus preserved",
    "redundant_p0_p1_storage": "NOT_REQUIRED"
  }
}
ARCHITECTURE CHECKPOINT · 3.02 OWNS SINGLE-CONTOUR LOCAL PATH GEOMETRY: SEGMENT GRAPH, CONTINUITY/CLOSURE, POINT/TANGENT EVALUATION, LOCAL BOUNDS, WINDING DIRECTION AND RAW INTERSECTION EVENTS. SILHOUETTE READABILITY/TOPOLOGY → 3.03. HOLES/FILL/CONVEXITY → 3.04. TRANSFORM → CORE / 3.05. GENERATION/SCORING → 3.06. VISUAL MASS/AREA/OCCUPANCY → TOPIC 4. NEGATIVE SPACE → TOPIC 5. NO BEAUTYSCORE.
VISITS / ...