Geometry before interpretation
Only explicit diagonal candidate geometry is canonical here.
How a diagonal candidate is represented
Пояснительная графика показывает именно геометрический слой, без скрытой оценки композиции.
Rising diagonal
Canonical direction points to +x. Positive dy gives the RISING geometry class. This is a descriptor only.
Falling diagonal
Canonical direction still points to +x. Negative dy gives FALLING. No reading-order or tension assumption is attached.
Caller requests exact axisRef values. No all-lines scan and no geometry-driven discovery.
Owner-qualified anchor + direction evidence is validated. Missing/conflicting evidence stays N_A.
1..256 candidates. Exact duplicate geometry across refs produces N_A instead of multiple pseudo-votes.
24.00 stops at candidate geometry. It does not decide which diagonal is “main”, whether objects follow it, how mass projects onto it, or whether the scene has desirable tension.
One owner for candidate identity
24.00 владеет геометрией candidate identity, но не её композиционной интерпретацией.
Frame + evidence + candidate set
2D frame binding, explicit axis evidence, resolution, exact line equivalence, rising/falling orientation descriptor, bounded candidate set and immutable root seed.
Alignment + mass + tension + score
Object orientation is 24.01, mass distribution is 24.02, counter-diagonal/tension is 24.03, scoring/candidate generation is 24.04.
Coordinate frame is explicit
The same axis numbers are meaningless without exact frame lineage.
Evidence is owner-qualified
Each requested axisRef resolves from exact anchor + direction declarations.
One point on the line
{x,y} in the exact coordinate frame. No viewport-center or object-centroid inference is allowed.
Non-zero vector
{dx,dy} must be finite and both components non-zero for a diagonal candidate.
No confidence winner
Multiple declarations for one axisRef must be exactly line-equivalent. Contradiction → N_A; confidence is diagnostic only.
Exact line equivalence, no epsilon
Scaled/reversed directions can still denote the same infinite line.
Same infinite line
Direction reversal or scale does not create a new geometric axis. Exact line equivalence is tested algebraically, without tolerance.
Near-parallel is still different
No hidden angle epsilon. If cross products are not exactly equal, the declarations are different candidates until a downstream policy says otherwise.
Diagonal means mathematically non-axis-aligned
No hidden “looks diagonal enough” threshold is introduced at 24.00.
Valid candidate
Both direction components are non-zero. Even a very shallow slope remains diagonal unless an explicit downstream threshold is provided.
Axis-aligned firewall
Exact horizontal and vertical directions are not diagonal candidates. The module rejects them rather than inventing a near-diagonal tolerance.
Bounded explicit candidate set
No full line search and no duplicate-equivalent geometry inflation.
DiagonalAxisCandidate {
axisRef,
scopeRef, snapshotRef,
coordinateFrameRef,
anchor: {x,y},
direction: {dx,dy},
orientationClass: RISING | FALLING,
evidenceRefs[],
objectOrientationAttachmentRef: null,
massDistributionAttachmentRef: null,
tensionProfileAttachmentRef: null,
scoreRef: null,
status,
mutationAllowed: false
}Immutable root seed
Downstream modules attach results without mutating 24.00 records.
Downstream ownership stays explicit
Execution order does not collapse ownership boundaries.
| Module | Owns next | 24.00 explicitly does not do it |
|---|---|---|
| 24.01 | Object orientation vs diagonal | No angle/alignment between object orientation and candidate axis. |
| 24.02 | Mass distribution along diagonal | No projection coordinate, density, centroid-along-axis or side mass. |
| 24.03 | Counter-diagonal and tension profiles | No main/counter role assignment, angular tension or controlled tension profile. |
| 24.04 | Scoring, candidates and tests | No MetricResult, target fit, independent vote or repair generator. |
Descriptor ≠ score
These separations are normative and testable.
Being declared does not make an axis the primary compositional diagonal.
RISING/FALLING are exact orientation descriptors only.
Near-parallel or near-collinear axes remain distinct without explicit tolerance.
24.00 owns zero MetricResult records and zero independent numeric votes.
CANON → LAB → DATA → IDEAS
Canonical geometry can later feed perceptual studies without turning hypotheses into laws.
24.00 regression suite
Tests cover exact frame lineage, axis evidence validity, conflict preservation, exact line equivalence, axis-aligned rejection, bounded explicit candidate selection, duplicate-equivalent handling, immutable seed, zero metrics and strict 24.01–24.04 / Topic21–23/25 firewalls.
DATA FOR LAYOUT ENGINE
Machine-readable contract for integration and cross-module audit.
{
"module": "Compo 24.00",
"name": "diagonal_axis_candidates",
"version": "1.0-canonical",
"canonical_main_title": "Diagonal axis candidates",
"topic": "24_ДИАГОНАЛЬНАЯ_КОМПОЗИЦИЯ",
"scope": "EXPLICIT_OWNER_QUALIFIED_2D_DIAGONAL_AXIS_EVIDENCE_EXACT_GEOMETRIC_CANDIDATE_RESOLUTION_BOUNDED_CANDIDATE_SET_AND_IMMUTABLE_ROOT_SEED_ONLY_WITHOUT_OBJECT_ORIENTATION_MASS_PROJECTION_COUNTER_DIAGONAL_TENSION_OR_SCORING",
"main_topic_contract": {
"topic_title": "Диагональная композиция",
"topic_goal": "Описывает диагональную структуру всей сцены: main diagonal, counter-diagonal, проекции масс на ось и controlled diagonal tension.",
"expected_output": "DiagonalCompositionDescriptor, main/counter axes, projection distribution",
"planned_files": [
"24.00 Diagonal axis candidates",
"24.01 Object orientation vs diagonal",
"24.02 Mass distribution along diagonal",
"24.03 Counter-diagonal and tension profiles",
"24.04 Scoring, candidates and tests"
]
},
"ownership": {
"owner": "Compo24.00",
"owns": [
"DiagonalCoordinateFrameBinding",
"DiagonalAxisEvidence",
"DiagonalAxisEvidenceResolution",
"DiagonalAxisCandidate",
"DiagonalAxisOrientationClass taxonomy",
"DiagonalAxisCandidateSetPolicy",
"DiagonalAxisCandidateSet",
"DiagonalCompositionSeed root identity",
"exact geometric line-equivalence test without tolerance",
"explicit-only bounded diagonal candidate selection",
"identity/status/provenance rules for Topic24 root axis-candidate layer",
"non-mutating correction request for frame/axis-evidence/candidate-set errors"
],
"does_not_own": [
"raw object geometry or raw line extraction — upstream geometry owners",
"automatic diagonal discovery from scene pixels/objects — deferred / foreign owner",
"object orientation relative to a diagonal — Compo24.01",
"mass projection or distribution along diagonal — Compo24.02",
"main-vs-counter diagonal relationship and controlled tension — Compo24.03",
"target profile, MetricResult, candidate generator or final scoring — Compo24.04",
"flow-template diagonal path matching — Topic25",
"radial axes / rings / sectors — Topic23",
"symmetric mirror axis semantics — Topic21",
"asymmetric centroid/moment semantics — Topic22",
"dominance / hierarchy / beautyScore / final-layout ranking",
"foreign geometry/style/semantic mutation"
]
},
"consumes": [
"explicit scope and snapshot identity",
"one explicit owner-qualified 2D coordinate frame",
"explicit requested diagonal axis refs",
"owner-qualified axis evidence with anchor point and non-axis-aligned direction vector",
"optional source/provenance/confidence metadata"
],
"provides": [
"DiagonalCoordinateFrameBinding",
"DiagonalAxisEvidenceResolution[]",
"DiagonalAxisCandidate[]",
"DiagonalAxisCandidateSet",
"DiagonalCompositionSeed"
],
"owns_metrics": [],
"independent_numeric_votes": 0,
"status_semantics": {
"OK": "valid exact explicit geometry lineage",
"N_A": "missing/conflicting/duplicate-equivalent/overflow evidence; never numeric zero",
"INVALID": "malformed or impossible record; never numeric zero"
},
"orientation_semantics": {
"RISING": "canonical direction has dx > 0 and dy > 0",
"FALLING": "canonical direction has dx > 0 and dy < 0",
"HORIZONTAL": "not a valid diagonal candidate",
"VERTICAL": "not a valid diagonal candidate",
"note": "RISING/FALLING are geometric orientation descriptors, not quality, reading direction or tension."
},
"exact_equivalence": {
"parallel": "dx1 * dy2 === dy1 * dx2",
"same_infinite_line": "parallel AND (x2-x1)*dy1 === (y2-y1)*dx1",
"tolerance": null,
"near_parallel_is_equal": false
},
"policy": {
"selectionMode": "EXPLICIT_CANDIDATES_ONLY",
"maxCandidates": [
1,
256
],
"overflow": "N_A_WITHOUT_TRUNCATION",
"duplicateEquivalentGeometry": "N_A_NO_WINNER",
"autoAxisDiscovery": false,
"autoMainAxisSelection": false,
"autoCounterAxisSelection": false,
"autoScoring": false
},
"root_seed_contract": {
"axisCandidateSetRef": "exact",
"objectOrientationAttachmentRef": null,
"massDistributionAttachmentRef": null,
"tensionProfileAttachmentRef": null,
"scoringAttachmentRef": null,
"metricResultRefs": [],
"mutationAllowed": false
},
"firewalls": [
"axis candidate != selected main diagonal",
"axis candidate != counter-diagonal",
"diagonal orientation != movement direction",
"rising/falling != good/bad",
"near-horizontal nonzero direction != horizontal by hidden threshold",
"near-parallel != exact parallel",
"duplicate equivalent axis declarations != extra evidence votes",
"candidate count != compositional strength",
"axis geometry != object orientation",
"axis geometry != mass distribution",
"axis geometry != tension",
"N_A != 0",
"INVALID != 0",
"descriptor != score",
"local != global"
],
"visual_explanation": {
"diagrams": [
"anatomy of rising/falling diagonals",
"same infinite line under reversed/scaled direction",
"valid diagonal vs horizontal/vertical firewall",
"explicit bounded candidate-set pipeline"
]
},
"ideas_data_hooks": {
"IDEAS_REFS": [
"perceived diagonal strength vs exact geometric slope",
"scene-dependent main diagonal selection",
"counter-diagonal tension perception",
"mass projection profile experiments",
"diagonal direction and reading-order interactions",
"near-axis-aligned perceptual thresholds",
"multiple-diagonal competition"
],
"DATA_CAPTURE": [
"scope/snapshot/frame lineage",
"axis refs",
"anchor and direction evidence",
"evidence conflicts",
"exact-equivalence collisions",
"rising/falling orientation class",
"candidate-set status"
],
"DEFERRED_SEMANTIC_INPUTS": [
"main diagonal choice",
"counter-diagonal role",
"controlled tension target",
"desirability of rising/falling direction"
],
"HUMAN_FEEDBACK_HOOKS": [
"correct axis anchor/direction",
"merge duplicate equivalent axes",
"withdraw a candidate",
"declare missing candidate evidence"
],
"CONFLICT_PRIORITY_ASSUMPTIONS": [
"confidence cannot resolve contradictory geometry",
"lexical axisRef order is not priority",
"candidate request order is not strength ranking"
],
"LAB_HOOKS": [
"exact vs perceived diagonal threshold",
"main/counter diagonal perceptual studies",
"tension response to angular separation",
"projection-density perception"
]
},
"topic24ProgressAfterThisModule": "1/5 local",
"next_module": "Compo 24.01 — Object orientation vs diagonal",
"hard_stop": "No 24.01–24.04 implementation in this file"
}