layout7

package
v0.4.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 13, 2026 License: Apache-2.0 Imports: 7 Imported by: 0

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

View Source
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.

View Source
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.

View Source
const Version = "26.07-v7"

Version identifies graphs produced by this engine.

Variables

This section is empty.

Functions

func Generate

func Generate(doc *model.IpmGraph) (*layout.Graph, error)

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

func GenerateTraced(doc *model.IpmGraph, t Trace) (*layout.Graph, error)

GenerateTraced is Generate with a decision trace. Generate(doc) == GenerateTraced(doc, nil).

func GenerateWithOptions

func GenerateWithOptions(doc *model.IpmGraph, opts Options) (*layout.Graph, error)

GenerateWithOptions is Generate with the engine options applied.

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.

const (
	KindEvent Kind = iota
	KindThing
	KindConcept
)

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.

const (
	RelLeadsTo Rel = iota
	RelPartOf
	RelExpresses
	RelNearTo
)

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL