Transform adapter, не второй Core
3.05 применяет внешний canonical transform к форме и отдаёт world-space view. Сами поля универсального ObjectTransform должны принадлежать Core.
Affine local→world application, inverse mapping, world bounds, parity и dirty-recompute routing для Shape.
ObjectTransform schema → Core; local geometry → 3.01/3.02/3.04; shape scoring → 3.06.
SHAPE TRANSFORM ADAPTER ONLY.
ObjectTransformView
Пока 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
Points, vectors, tangents
Translation действует только на points; direction/tangent vectors используют linear part матрицы.
World → local
Inverse нужен hit-testing, semantic anchors и world-space correction projection. Singular matrix его не имеет.
Inverse
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
Универсальный и устойчивый способ определить ориентацию после transform — знак determinant, а не конкретный UI checkbox.
Что сохраняется, а что нужно пересчитать
Не все affine transforms одинаковы. Topology значительно устойчивее Euclidean measurements.
| Transform | Preserves | Changes / dirty evidence |
|---|---|---|
| translation | lengths, angles, topology, convexity, parity | world position/bounds, scene relations |
| rotation | lengths, angles, topology, convexity, parity | world bounds/direction |
| uniform + scale | angles, topology, convexity | length/feature scale, bounds, mass/occupancy downstream |
| reflection | lengths, angles, topology, convexity | winding/orientation parity |
| anisotropic scale | affine topology, convexity | angles, local aspect, feature scale, curvature-like evidence |
| skew | affine topology, convexity | angles, lengths, feature scale, curvature-like evidence |
| singular | — | dimension collapse; topology may cease to be valid |
Derived world-space bounds
World bounds всегда производны от local geometry + matrix. Они не становятся новой local geometry и не равны visual occupancy.
BakeTransform — отдельная миграция
Иногда transform действительно нужно запечь в geometry, например при export. Это не обычное применение transform и требует новой geometry revision.
Derived view
local geometry unchanged transformRef unchanged worldGeometry = derive(...) no new geometry owner state
Migration
new local geometry = apply(transform, old geometry) new geometry.version new provenance transform reset/identity only through geometry owner
Recompute routing
Transform change не означает «пересчитать всё». 3.05 формирует dirty plan по типу transform и downstream dependence.
World view
world geometry, world bounds, inverse/parity descriptors.
3.03 / 3.04
Topology may reuse under invertible affine transform; world-scale readability evidence may need recompute.
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
MAIN требует базовые трансформации объекта, но не задаёт отдельную transform-aesthetic dimension. Поэтому модуль не изобретает `rotationFit` или `scaleBeauty`.
Reference test adapter
Для 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.
Визуальная лаборатория
Одна локальная форма под разными transform classes. Форма локально не меняется.
Affine transform tests
Проверяем composition, inverse, determinant parity, topology-preserving classes, local immutability и отсутствие score ownership.
DATA FOR LAYOUT ENGINE
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"
}