COMPO · 3.05 · SHAPE TRANSFORM ADAPTER

Трансформации
формы.

Shape-side применение canonical ObjectTransform: position, rotation, scale, reflection и skew через deterministic affine matrix. 3.05 вычисляет world-space view, inverse mapping, bounds и orientation parity, но не становится вторым владельцем универсального ObjectTransform и не превращает transform magnitude в aesthetic score.

ModuleCompo 3.05
Scopeshape transform adapter
ObjectTransformCORE OWNER
Metricsnone
Topic3 · SHAPE
Next3.06

Transform adapter, не второй Core

00 / module api

3.05 применяет внешний canonical transform к форме и отдаёт world-space view. Сами поля универсального ObjectTransform должны принадлежать Core.

SCOPE

Affine local→world application, inverse mapping, world bounds, parity и dirty-recompute routing для Shape.

BOUNDARY

ObjectTransform schema → Core; local geometry → 3.01/3.02/3.04; shape scoring → 3.06.

FINALITY

SHAPE TRANSFORM ADAPTER ONLY.

НЕ ДУБЛИРУЕМ OBJECTTRANSFORM. 3.05 не объявляет position/rotation/scale/reflection/skew своей универсальной schema. Для shape-side вычислений authoritative input — deterministic affine matrix от Core adapter.

ObjectTransformView

01 / canonical adapter

Пока Core migration не опубликована, 3.05 требует минимальный adapter-view. Это позволяет не зависеть от того, как UI или Core сериализует decomposition.

Required view

ObjectTransformView {
  transformRef,
  localToWorld: [
    a,b,c,d,tx,ty
  ],
  worldToLocal?,
  decomposition?,   // Core-owned
  exactness,
  confidence,
  provenance
}

Affine matrix

| a  c  tx |
| b  d  ty |
| 0  0   1 |

x' = a·x + c·y + tx
y' = b·x + d·y + ty

det = a·d - b·c
MATRIX AUTHORITATIVE. Decomposition position/rotation/scale/reflection/skew может быть полезна UI и audit, но shape geometry должна трансформироваться по canonical matrix.

Points, vectors, tangents

02 / geometry mapping

Translation действует только на points; direction/tangent vectors используют linear part матрицы.

POINT: p_world = [a c; b d] · p_local + [tx,ty] VECTOR / TANGENT: v_world = [a c; b d] · v_local normalized tangent: normalize(v_world) if |v_world|≈0 → N/A NORMAL: transform by inverse-transpose when inverse exists DO NOT: apply translation to vectors normalize before anisotropic/skew transform

World → local

03 / inverse mapping

Inverse нужен hit-testing, semantic anchors и world-space correction projection. Singular matrix его не имеет.

Inverse

det = a·d - b·c if |det| > EPS: L⁻¹ = 1/det · | d -c | | -b a | p_local = L⁻¹ · (p_world - t)

Singular

|det| ≤ EPS

isInvertible = false
worldToLocal = N/A
orientationParity = DEGENERATE

Examples:
  scaleX = 0
  scaleY = 0
  dependent axes after transform

Never fake inverse.

Reflection и orientation parity

04 / reflection

Универсальный и устойчивый способ определить ориентацию после transform — знак determinant, а не конкретный UI checkbox.

det > 0 → orientationParity = PRESERVED det < 0 → orientationParity = FLIPPED |det| ≤ EPS → orientationParity = DEGENERATE Consequences: winding direction flips iff det < 0 convexity class preserved for invertible affine transform holes/fill nesting topology preserved local geometry unchanged
REFLECTION ≠ NEGATIVE-SCALE GUESS. Если Core хранит reflection отдельными flags или через signed scale — это его serialization concern. 3.05 доверяет матрице и determinant.

Что сохраняется, а что нужно пересчитать

05 / transform classes

Не все affine transforms одинаковы. Topology значительно устойчивее Euclidean measurements.

TransformPreservesChanges / dirty evidence
translationlengths, angles, topology, convexity, parityworld position/bounds, scene relations
rotationlengths, angles, topology, convexity, parityworld bounds/direction
uniform + scaleangles, topology, convexitylength/feature scale, bounds, mass/occupancy downstream
reflectionlengths, angles, topology, convexitywinding/orientation parity
anisotropic scaleaffine topology, convexityangles, local aspect, feature scale, curvature-like evidence
skewaffine topology, convexityangles, lengths, feature scale, curvature-like evidence
singular—dimension collapse; topology may cease to be valid

Derived world-space bounds

06 / world bounds

World bounds всегда производны от local geometry + matrix. Они не становятся новой local geometry и не равны visual occupancy.

POLYGON / POLYLINE: transform all exact vertices worldBounds = min/max transformed points ANALYTIC CURVE: preferred: transform curve representation then solve world-space extrema exactly fallback: bounded flattening + errorBound + confidence worldBounds = DERIVED(shape.geometry, ObjectTransform) NEVER: localBounds = worldBounds
WORLD BOUNDS ≠ VISUAL MASS. Topic 4 может потреблять transformed region, но 3.05 не вычисляет occupancy/density/perceived weight.

BakeTransform — отдельная миграция

07 / explicit bake

Иногда transform действительно нужно запечь в geometry, например при export. Это не обычное применение transform и требует новой geometry revision.

ORDINARY APPLY

Derived view

local geometry unchanged
transformRef unchanged
worldGeometry = derive(...)
no new geometry owner state
EXPLICIT BAKE

Migration

new local geometry =
  apply(transform, old geometry)

new geometry.version
new provenance
transform reset/identity
only through geometry owner
NO SILENT BAKE. Moving/rotating/scaling a shape must not silently rewrite Bézier control points or primitive dimensions in canonical local geometry.

Recompute routing

08 / dirty graph

Transform change не означает «пересчитать всё». 3.05 формирует dirty plan по типу transform и downstream dependence.

ALWAYS

World view

world geometry, world bounds, inverse/parity descriptors.

CONDITIONAL

3.03 / 3.04

Topology may reuse under invertible affine transform; world-scale readability evidence may need recompute.

DOWNSTREAM

4 / 5 / global

Visual mass, occupancy, free-space and scene relations become dirty when occupied world region changes.

TransformDirtyPlan {
  recomputeWorldGeometry: true,
  recomputeWorldBounds: true,
  flipWinding: det < 0,
  localTopologyReusable: invertible,
  readabilityWorldScaleDirty: dependsOnTarget,
  topic4MassDirty: renderedRegionChanged,
  topic5SpaceDirty: occupiedRegionChanged,
  globalRelationsDirty: true
}

Почему 3.05 не имеет transform score

09 / descriptor only

MAIN требует базовые трансформации объекта, но не задаёт отдельную transform-aesthetic dimension. Поэтому модуль не изобретает `rotationFit` или `scaleBeauty`.

OWNS_METRICS = []. Rotation, scale, reflection и skew здесь — state/geometry descriptors. Их уместность будет оцениваться конкретными owners: hierarchy, alignment, visual mass, responsive layout, style consistency или shape scorer при наличии явной причины.
rotationRad = descriptor scaleX/scaleY = descriptor determinant = descriptor hasSkew = descriptor NOT: more rotation = better less skew = better uniform scale = better reflection = penalty transformBeautyScore

Reference test adapter

10 / reference decomposition

Для executable tests нужен один deterministic способ собрать матрицу. Он указан только как fixture и не объявляется Core schema.

ReferenceTransformParams {
  position: {x,y},
  rotationRad,
  scaleX > 0,
  scaleY > 0,
  reflectX: boolean,
  reflectY: boolean,
  skewXRad,
  skewYRad
}

REFERENCE ORDER:
  point
    → scale
    → reflection
    → skew
    → rotation
    → translation

Production:
  consume Core matrix directly.
WHY. Affine decomposition не единственна. Поэтому test decomposition — средство проверки matrix math, а не новый canonical serialization contract.

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

11 / visual lab

Одна локальная форма под разными transform classes. Форма локально не меняется.

LOCAL SOURCE ROTATION ANISOTROPIC SCALE REFLECTION · det<0 winding flips · topology survives SKEW angles/lengths change SINGULAR det≈0 · no inverse same local geometry · different derived world views · no transform quality score

Affine transform tests

12 / deterministic tests

Проверяем composition, inverse, determinant parity, topology-preserving classes, local immutability и отсутствие score ownership.

Tests not run yet.

DATA FOR LAYOUT ENGINE

13 / machine contract

Machine-readable contract 3.05.

{
  "module": "Compo 3.05",
  "name": "shape_transforms_position_rotation_scale_reflection_skew",
  "version": "1.0-canonical",
  "scope": "SHAPE_SIDE_APPLICATION_OF_CANONICAL_OBJECT_TRANSFORM",
  "consumes": [
    "Compo3.00.Shape",
    "Compo3.01.PrimitiveShapeGeometry?",
    "Compo3.02.PathShapeGeometry?",
    "Compo3.04.CompoundShapeGeometry?",
    "Compo0.ObjectTransformRef or compatible ObjectTransformView",
    "GeometryToleranceContext?"
  ],
  "provides": [
    "ObjectTransformView",
    "ShapeTransformDescriptor",
    "ShapeWorldGeometryView",
    "ShapeWorldBoundsResult",
    "TransformValidityResult",
    "TransformParityDescriptor",
    "ShapeInverseMappingAdapter",
    "TransformCorrectionRequest[]"
  ],
  "owns_contracts": [
    "shape-side transform application",
    "local-to-world matrix use for ShapeGeometry",
    "world-to-local inverse adapter",
    "world-space derived bounds",
    "reflection/orientation parity descriptor",
    "transform validity and degeneracy diagnostics",
    "shape-specific recompute routing under transform changes"
  ],
  "owns_metrics": [],
  "descriptors_only": [
    "shape.transform.determinant",
    "shape.transform.orientationParity",
    "shape.transform.isInvertible",
    "shape.transform.isSimilarity",
    "shape.transform.hasAnisotropicScale",
    "shape.transform.hasSkew",
    "shape.transform.worldBounds",
    "shape.transform.localToWorldMatrix",
    "shape.transform.worldToLocalMatrix",
    "shape.transform.exactness",
    "shape.transform.confidence"
  ],
  "canonical_owner_policy": {
    "ObjectTransform_schema_owner": "Compo0/Core target architecture",
    "Compo3.05_role": "shape-side adapter / consumer",
    "negative_scale_policy": "Core must canonicalize or explicitly define it; 3.05 must not invent a conflicting reflection convention",
    "matrix_requirement": "adapter must expose a deterministic localToWorld affine matrix",
    "decomposition_requirement": "optional; matrix is authoritative for shape-side geometry application"
  },
  "object_transform_view": {
    "transformRef": "string",
    "localToWorld": [
      "a",
      "b",
      "c",
      "d",
      "tx",
      "ty"
    ],
    "worldToLocal": "optional derived inverse",
    "decomposition": "optional Core-owned position/rotation/scale/reflection/skew fields",
    "determinant": "a*d-b*c",
    "exactness": "EXACT|APPROXIMATE",
    "confidence": "0..1",
    "provenance": "object"
  },
  "matrix_convention": {
    "point": "x'=a*x+c*y+tx; y'=b*x+d*y+ty",
    "vector": "x'=a*x+c*y; y'=b*x+d*y",
    "storage": "[a,b,c,d,tx,ty]",
    "composition": "compose(A,B) means apply B first, then A",
    "coordinate_system": "inherits scene convention; 3.05 does not redefine screen/world axes"
  },
  "reference_fixture_decomposition": {
    "status": "REFERENCE_TEST_ADAPTER_ONLY_NOT_CORE_SCHEMA",
    "fields": [
      "position{x,y}",
      "rotationRad",
      "scaleX>0",
      "scaleY>0",
      "reflectX:boolean",
      "reflectY:boolean",
      "skewXRad",
      "skewYRad"
    ],
    "composition_order": [
      "local point",
      "scale",
      "reflection",
      "skew",
      "rotation",
      "translation"
    ]
  },
  "invariance_policy": {
    "translation": "preserves distances, angles, topology, convexity and orientation parity",
    "rotation": "preserves distances, angles, topology, convexity and orientation parity",
    "uniform_positive_scale": "preserves angles/topology/convexity; scales lengths",
    "reflection": "preserves distances/angles/topology/convexity; flips orientation parity when determinant<0",
    "anisotropic_scale": "preserves affine topology/convexity but not Euclidean angles or length ratios",
    "skew": "preserves affine topology/convexity but not Euclidean angles, lengths or curvature values",
    "singular_transform": "determinant≈0; geometry collapses dimension and inverse mapping is unavailable"
  },
  "downstream_recompute_policy": {
    "topology_under_invertible_affine": "3.03/3.04 topology class can usually be reused if no tolerance-sensitive world-space contact test is involved",
    "winding_orientation": "must flip when determinant<0",
    "world_feature_scale": "must recompute under scale/skew",
    "world_bounds": "always recompute when matrix changes",
    "euclidean_angle_or_length_evidence": "recompute under non-rigid transforms as required by owner",
    "silhouette_readability": "recompute if target/evidence depends on world-space feature scale or rendering scale",
    "visual_mass_topic4": "dirty on any scale/skew/outline/world-region change relevant to rendered occupancy",
    "scene_free_space_topic5": "dirty when transformed occupied region changes"
  },
  "hard_constraints": [
    "local ShapeGeometry is immutable under ordinary transform application",
    "ObjectTransform schema is not re-owned by Compo3.05",
    "transform adapter must provide deterministic matrix semantics",
    "singular transform must not pretend to have an inverse",
    "reflection parity must follow determinant sign, not a guessed UI flag",
    "world bounds are derived data and must not overwrite local bounds",
    "bakeTransform must be explicit and produce a new geometry revision with provenance",
    "raw transform magnitude is not an aesthetic score",
    "visual mass/occupancy remain Topic4",
    "scene free space remains Topic5",
    "global balance/hierarchy/eye-flow are not owned here",
    "no beautyScore"
  ],
  "initial_heuristics": {
    "determinant_zero_epsilon": {
      "value": 1e-10,
      "provenance": "IMPLEMENTATION_HEURISTIC"
    },
    "matrix_roundtrip_epsilon": {
      "value": 1e-09,
      "provenance": "IMPLEMENTATION_HEURISTIC"
    },
    "similarity_orthogonality_epsilon": {
      "value": 1e-08,
      "provenance": "IMPLEMENTATION_HEURISTIC"
    },
    "world_bounds_curve_approx_error_shortN": {
      "value": 0.0005,
      "provenance": "INITIAL_HEURISTIC"
    }
  },
  "correction_policy": {
    "direct_local_geometry_mutation": "FORBIDDEN",
    "singular_transform": "request Core/ObjectTransform owner correction",
    "unsupported_transform_view": "request canonical matrix adapter",
    "bake_request": "explicit new geometry revision; route to geometry owner with transform provenance",
    "visual_scale_problem": "context/scorer may request transform target change but 3.05 does not aesthetic-rank it",
    "geometry_problem": "route to Compo3.01/3.02/3.04",
    "mass_or_occupancy_problem": "route to Topic4",
    "free_space_problem": "route to Topic5"
  },
  "deferred_inputs": [
    "canonical ObjectTransform Core migration",
    "Compo3.06 shape candidate generation/scoring",
    "Topic4 visual mass/occupancy",
    "Topic5 positive/negative space",
    "global balance/hierarchy/eye-flow",
    "rendering-specific pixel snapping"
  ],
  "recompute_when": [
    "ObjectTransform matrix/version changes",
    "local ShapeGeometry changes",
    "compound/outline derived geometry changes",
    "world-space tolerance or approximation policy changes"
  ],
  "finality": "SHAPE_TRANSFORM_ADAPTER_ONLY"
}
ARCHITECTURE CHECKPOINT · OBJECTTRANSFORM SCHEMA BELONGS TO COMPO0/CORE TARGET ARCHITECTURE. 3.05 OWNS ONLY SHAPE-SIDE MATRIX APPLICATION, INVERSE/PARITY/WORLD-BOUNDS DESCRIPTORS AND TRANSFORM-SPECIFIC DIRTY ROUTING. LOCAL GEOMETRY → 3.01/3.02/3.04. SCORING/GENERATOR → 3.06. VISUAL MASS/OCCUPANCY → TOPIC 4. FREE SPACE → TOPIC 5. NO TRANSFORM BEAUTYSCORE.
VISITS / ...