Documentation
¶
Overview ¶
Package layout7 is the v7 layout engine: an implementation of the nine layout principles specified in gl:docs/dev/layout-gen/layout-principles.md (v7P1–v7P9).
The layout is derived from GROUPS and RELATIVE rules; absolute positions are the LAST step, and growth is symmetric by construction (orbit variables — one shared pitch per fork fan, computed closed-form before placement). Every exported and internal step cites the principle it implements; a change that cannot name its principle does not belong in this package.
Principle → file map:
v7P1 components separate along event structure membership.go
v7P2 central component first, tied ring, 16:9 wrap components.go
v7P3 event skeleton (leads-to down, part-of right,
forks spread symmetrically, join affinity) skeleton.go
v7P4 aux groups (row/above/diagonal grammar,
subgroup order, affinity, bracket, span) groups.go
v7P5 same-kind ties (draw / order / onion layer) membership.go, groups.go
v7P6 flow corridor: skeleton never yields,
space does (symmetric fan growth) skeleton.go (pitch), place.go
v7P7 shared nodes anchor at their deepest user membership.go
v7P8 spacing: minimums, symmetric growth, grid size.go, place.go (constants, solve)
v7P9 edge routing: kind budget, hide order, stubs route.go
The pipeline (generate.go) is:
normalize → membership (P1/P7) → groups (P4/P5) → skeleton (P3/P6) → place (P8: rows/columns, per-row separation solve) → assemble (P2) → route (P9) → emit (pkg/layout Graph, version 26.07-v7)
Output is the shared ipm-simple-graph structure (pkg/layout.Graph), with every edge carrying an explicit Route and Visibility, so all downstream consumers (layout-test-runner, ipmsvg-gen, layout-gen --edges) work unchanged.
Development documentation: gl:docs/dev/layout-gen/layout7-engine.md. Acceptance gate: the eight `## v7 acceptance targets` cases in gl:docs/dev/layout-gen/layout-alg-ext.md (run via `make layout-test-v7`).
Index ¶
Constants ¶
const ( GridStep = 20 NodeW = 120 // standard node 120×60 NodeH = 60 BoundarySize = 40 // S/E boundary nodes RowGap = 60 // vertical gap between event rows (base minimum) ColGap = 60 // horizontal gap between adjacent columns (base minimum) NearGap = 100 // near-to satellite stand-off (v7P5): visibly MORE than // an attached column gap — near-to is adjacency, not attachment // ("more than partof/express gap", ~90 gridded up) BoundaryGap = 40 // S/E to the adjacent event (v7P8 proven constant) StackGap = 40 // vertical gap inside an aux stack (clearance) Clearance = 40 // generic aux clearance (v7P8 "clearance 40") CompGap = 120 // gap between components (v7P2 tiles / wrap rows) Margin = 40 // canvas margin // ColPitch is the centre-to-centre distance of adjacent standard // columns: NodeW + ColGap. Derived, not tunable separately. ColPitch = NodeW + ColGap // 180 // RowPitch is the base centre distance of adjacent event rows. RowPitch = NodeH + RowGap // 120 // MaxFanAngleDeg caps how flat a wide fork fan may get (v7P3/P8): past // it the fan row drops instead of only widening. MaxFanAngleDeg = 150 // TargetAspect is the 16:9 canvas budget every arrangement aims for // (v7P2); the single global valve of the spec's decision log. TargetAspectW = 16.0 TargetAspectH = 9.0 )
v7P8 — spacing: gaps are minimums, growth is symmetric, the grid is exact. "Every constant a multiple of the grid step, so the solver works in grid units and snapping is exact by construction." Grid step is 20 per the spec; every constant below is a multiple of it.
const TraceAvailable = traceEnabled
TraceAvailable reports whether this build carries the trace emit sites (false under `-tags l7notrace`) — consumers like pkg/l7report check it to fail loudly instead of returning an empty report.
const Version = "26.07-v7"
Version identifies graphs produced by this engine.
Variables ¶
This section is empty.
Functions ¶
func Generate ¶
Generate lays out an IPM graph by the v7 principles and returns the shared ipm-simple-graph structure (pkg/layout.Graph) — every edge carries an explicit route and visibility, so downstream consumers need no engine awareness.
Pipeline (see doc.go for the principle map):
normalize → membership (v7P1/P7) → groups (v7P4/P5) → skeleton (v7P3/P6) → place (v7P8/P6) → assemble (v7P2) → route (v7P9) → emit
func GenerateTraced ¶
GenerateTraced is Generate with a decision trace. Generate(doc) == GenerateTraced(doc, nil).
Types ¶
type Kind ¶
type Kind int
Kind is a node's layout kind. Unresolved input nodes act as their primary candidate (Candidates[0]) for every layout decision but keep their input type in the emitted graph.
type Options ¶
type Options struct {
// Containers makes a composite event's part-of sub-grid claim its
// vertical band EXCLUSIVELY: the spine neighbours above and below the
// composite are pushed clear of the grid's full span instead of tucking
// beside it in the spine column.
//
// OFF (default) is the compact flat layout: v7P8 grows a row gap only
// where the two neighbourhoods x-OVERLAP, so a sub-grid hanging in its
// own column costs the spine nothing. That is right for a flat diagram
// and wrong for one drawn with container SHELLS — a shell is the bbox of
// {composite ∪ its part-of subtree}, so whatever tucked in beside the
// grid ends up enclosed by a container it is not a member of.
//
// ON is the "reserve shell margin when spacing a composite" rule. It costs
// vertical space in exact proportion to the sub-grid's height — that
// room is what makes the shell exclusive.
Containers bool
}
Options tune the engine for a consumer's needs. The zero value is the plain flat layout every renderer got before options existed.
type Rel ¶
type Rel int
Rel is an edge's relation kind. The kind hierarchy L > P > X > N governs membership (v7P1), layer order (v7P5) and visibility (v7P9) alike — the extracted pattern of the spec's decision log.
type Trace ¶
type Trace interface {
Emit(e TraceEvent)
}
Trace receives structured events during GenerateTraced. It is the engine's ONLY debug surface (docs/dev/layout-gen/layout-debug.md): all narration lives outside (pkg/l7report); the engine just states facts. A nil trace costs one pointer check per site; a `-tags l7notrace` build compiles the sites away entirely.
type TraceEvent ¶
type TraceEvent struct {
Stage string // membership | groups | skeleton | floors | pull | place | assemble | route
Kind string // component | election | anchor | satellite | unanchored | demote |
// band | subrows | positions | candidate | chosen | stubbed | tile | tile-candidate
Data map[string]any
}
TraceEvent is one engine decision or snapshot. Data holds small, stage-specific payloads with STABLE keys — consumers grep and diff these; keys are API.