๐ TikZ layout scaffolds¶
One known-good starting file per layout metaphor in
docs/TIKZ-STYLE.md. That document tells an
author to commit to a metaphor before placing a node; these are what the
choice hands you, so a figure starts from a file rather than from an
empty tikzpicture.
| File | Metaphor | Reach for it when |
|---|---|---|
pipeline.tex |
Pipeline | the thing is a sequence and the question is "what happens next" |
map.tex |
Map | the point is how things compare on two named axes, not how they connect |
layered-stack.tex |
Layered stack | the question is what is allowed to depend on what |
control-loop.tex |
Control loop | the whole claim is that the cycle closes |
branching-tree.tex |
Branching tree | one thing divides into cases and no case rejoins another |
hub-and-spoke-network.tex |
Hub-and-spoke network | everything going through one place is the claim |
zoned-spine.tex |
Zoned spine | one storyline, with parallel commentaries on points along it |
state-machine.tex |
State machine | it is in one state at a time, and a state can recur, stay put or be sent back |
comparison.tex |
Comparison | two things made of the same parts, and the point is the part that differs |
sequence.tex |
Sequence | parties exchange messages and the order of the exchanges is the claim |
timeline.tex |
Timeline | when things happen, and how far apart, is the claim |
Two more things live here that are not scaffolds:
cg-figstyle.texis the house figure style: the palette plus node roles, zone cards, edges, tags, badges, a legend swatch and a two-step label ramp. Every scaffold carries a verbatim copy of it, so you never copy it by hand; see below.exemplars/holds seven figures drawn with that block, at a wider page (the render's 453pt) than the scaffolds: three from one paper redrawn, and a comparison, a Markov chain, a sequence and a timeline drawn for this project. They show what the vocabulary is for: zone cards, step badges, a legend, the housepics, lettered panels, an accented state, lifelines and eras placed in time.pump-markov-chain.texis the reference book's pump as a Markov chain, the state-machine layout with an accented state and no initial or accepting one. Read them; start from a scaffold.
๐ Using one¶
Start a figure from it beside the draft that needs it, then re-label
the nodes. figure new copies the scaffold, syncs its house block and
never overwrites a figure that exists:
1 | |
Its first line, % cg-layout: pipeline, names the layout, and
chitragupta figure check reads it to print the figure's size and
counts beside that layout's reference ranges, and to skip the connector
rules that layout exempts (a hub's diagonal spokes, say). Keep it, and
change it if you change the layout.
๐จ The house style comes with the file¶
Every scaffold carries the house figure-style block
(cg-figstyle.tex, described in
TIKZ-STYLE.md) between two marker comments,
and draws with it: \begin{tikzpicture}[cg], then cgbox, cgkey,
cgedge and the rest, so a copied file is already in house colours,
weights and corners and you re-label rather than re-decide. Keep the
block inside the figure when you edit it: the renderer injects only
\usepackage{tikz}, and a thesis-chapter-writer fragment is \input
into the user's own thesis, which has never heard of this project. A
figure depending on a style defined elsewhere compiles here and fails
there.
Do not edit inside the markers. Every figure in a book carries the
same copy, and an edited one forks the house style without anyone
noticing. A style only your figure needs goes in the picture's own
options. Repeating the block in every figure of one document is safe:
it is all \tikzset and \providecommand, so a second copy re-defines
the same keys to the same values.
The colour roles, in one line each: cgInk borders and labels, cgFlow
the primary path, cgAccent the one thing the figure is about, cgAlt
a second class, cgAux what happens off to the side, cgWarm and
cgRose a third and fourth zone. Fills are tints of the palette name;
strokes and coloured text take its darker shade, cg<Hue>Line or
cg<Hue>Text (draw=cgAltLine, text=cgAccentText), which clear WCAG
contrast where the light hues do not. docs/TIKZ-STYLE.md has the table,
and figure check's k1-stroke and k2-text report a figure that
draws or writes in a light hue instead.
Labels are set at the body size, all of them. Node names and zone
titles are \normalsize\bfseries and everything else is \normalsize,
which [cg] sets explicitly. Each scaffold is laid out to fit the article class's
text width at that size, so \input it bare: a \resizebox around it
prints the type at whatever the scale factor happens to be.
Then write the ASCII twin at figures/<name>.txt and reference the pair
from the draft with a single marker line. docs/WRITING-STANDARDS.md
ยง10 owns that contract, and your genre skill's figure step spells the
marker for your draft's language. Every scaffold and exemplar here ships
as such a pair: copy its .txt beside the .tex and edit both.
chitragupta figure check reports a twin that is missing or that lacks a
name, tag or panel letter the TikZ has (twin-missing, t1-labels,
t2-tags, t3-panels), and tests/test_tikz_scaffolds.py holds every
pair here clean under those rules. A twin is the clearest 7-bit form
of what the figure says, not necessarily a tracing of it:
state-machine.txt is a transition table, because a self-loop and a
curved pair draw badly in characters and the table is more precise.
A panelled figure is still one file. Copy the same scaffold once per
panel into a single tikzpicture (or two different ones, if the
panels are different shapes), and give each panel a (<letter>) <short
title> label node, lettered by its position in reading order: (a)
first, (b) next, on through the alphabet. docs/TIKZ-STYLE.md's
"Panels in one figure" section has the worked example and the rule for a
row that stops fitting. These files carry no figure float, so the
float and the \caption are added to your copy, not found in it.
Each file carries its own \usetikzlibrary line at the top. Keep it:
the renderer collects those lines across a draft's figures and loads the
union in the preamble (#781), so the line is a no-op in a rendered draft
-- but it is what makes the file compile on its own, which is how you are
told to check one, and what thesis-chapter-writer's fragment needs
inside a thesis this pipeline never sees. A picture that reaches for
below=4mm of store with no load anywhere fails the whole render, with
a message naming neither the library nor the figure.
Do not add anything else about loading: no clearing of
\tikz@library@...@loaded, no saving or restoring of
\tikz@node@reset@hook. Inside a figure float those workarounds
multiply every node's placement shift, silently. See
docs/TIKZ-STYLE.md.
โ What "known-good" means here¶
Every scaffold compiles on its own and reports no finding from
figure check:
1 | |
The tests hold parts of that on every run, so a scaffold cannot quietly
rot. tests/test_tikz_scaffolds.py checks that no scaffold has a node
overlap, a protrusion or node text past 15 words, and reads the metaphor
table in docs/TIKZ-STYLE.md, so adding a row there without adding a
file here fails. tests/test_figure_check.py checks that each scaffold
compiles, accents one node, sets no stray space and fits the width.
What each rule means is in
docs/figure-checks/README.md.
tests/test_tikz_scaffolds.py also checks four more things, for the
scaffolds and the exemplars alike:
- every copy of the block is byte-identical to
cg-figstyle.tex. After editing that file, bump thev<N>in its first line, add the new version's digest tocg-figstyle.versions.toml, and runpython -m chitragupta figure sync assets/tikz/*.tex assets/tikz/exemplars/*.texto refresh every scaffold and exemplar instead of copying the block by hand; \inputof the file sets nothing but its picture: the block, the\usetikzlibraryline and the picture's last line all end in%;- no glyph prints below the body size, read back out of the compiled PDF (a subscript or exponent may go to TeX's own script size, and no further);
- each scaffold fits the
articletext width unscaled.
Every node is named, and that matters. A finding names a node by
its (name), and an unnamed node only by its centre in millimetres. A
picture that names no node at all is reported as nothing-measurable.
Keep the names when you re-label.
โ Editing one without breaking it¶
The scaffolds place every node relative to another node. None of them
places a node at a coordinate in millimetres, and that is the property
to preserve (the block's pics are the one exception, and
docs/TIKZ-STYLE.md says why):
a figure laid out in hand-computed absolute millimetres cannot express
"do not collide", so changing one label's length re-opens every
adjacency in the picture at once.
Three limits worth knowing before you edit:
- Gaps are bounded by the protrusion check. A tall empty horizontal
band (more than a third of the figure's height with no node in it)
is reported as
content-protrusion, because LaTeX sets a figure as a rectangular box and one element stranded above the rest wastes every inch beside it. Spreading a two-row layout out generously is the usual way to trip this. - A containing box is not a collision.
layered-stack.texrelies on it: afitlayer wholly enclosing its members is grouping, whichnode-overlapexempts, whereas two layers partially overlapping is a finding. - A tree reports no edges.
branching-tree.texuseschild, which draws its edges internally rather than as\drawstatements, so the edge list andbudget-edgescome back empty for it. The connector rules still measure the lines it drew. Confirm a tree's structure from the source's own nesting.