PensaGrex mark geometry

A renderer-neutral drawing specification for every mark on the map. Complete enough to reproduce the shapes in any language against any 2D API, without reading the renderer. The companion to node-visual-system (grammar and policy) and rust_port_ideas (the egui argument). Each figure below renders from the same path data as the golden masters in the canonical Markdown.

This page is the presentation sibling of mark-geometry.md, which is canonical. It shows each mark on both of the app's grounds, azure (the light default) and navy (the dark), because the two-ground colour meaning is part of the specification. The Markdown carries the formulas, the constants, and the full prose; this page carries the shapes.

Scope. The mark vocabulary only: the vector marks a card, track, junction, decorator, or marker draws. Not the layout engine that positions them (row layering, branch routing, junction placement, folding, the camera), which is a separate specification. Every position here is an input the layout supplies.

1The ground

A dot at every 40-pixel lattice point, in the low-alpha --grid ink; the subway paper. In the source a 40×40 CSS radial gradient; reproduced as a tiled texture, or a loop of small filled circles over the visible rectangle.

azure

2The station dot

Where a card attaches to its line: a filled circle of diameter 11 (radius 5.5) in --line, the same size as a status glyph.

azure

3The card silhouettes

Four shapes. Each is an outer silhouette in the node colour with the same path inset per edge and refilled in the panel colour; the band between the two fills is the outline, thin on one edge and heavy on another (the Googie tell). Every figure below is the outer path and its innerT-transformed copy, drawn on both grounds. Width is a fixed 188; the height is stated per shape.

screen — a plain task (w=188, h=56)

azure

marquee — a task carrying the "here" cursor (w=188, h=72)

A concave cushion: each edge bows inward, top and bottom by 0.14h, sides by 0.05w.

azure

hull — a project node, and its terminus (w=188, h=58)

Concave top, tapering sides, convex bottom; the curve is capped at a height of 58 so a tall card does not swallow its own label. The terminus (right) is the same hull turned a half turn, so a folded pair reads as one shape and its reflection.

azure · hull + terminus

keystone — a rounded asymmetric quadrilateral, currently unassigned (w=188, h=56)

azure

The BORDERS four-tuples (top, right, bottom, left) that set the outline weight: screen (3.5, 8, 3.5, 7); marquee (6, 8, 4, 5); hull (4, 5, 8, 8); keystone (3, 5, 9, 7). The inner transform is translate(l, t) scale((w−l−r)/w, (h−t−b)/h).

4The status glyphs

An 11-pixel circle (radius 5.5) beside the label. Filled for done and in-progress; a 2px solid ring for to-do; a 1.5px dashed ring for cancelled; a filled teal ring for a project node.

azure

Left to right: done, in-progress, to-do, cancelled, project. The ring variants draw at a smaller radius so their stroke sits inside the 11-pixel envelope.

5The orbits decorator

A flagged node wears three off-axis elliptical rings centred on the card, each carrying one electron ball, plus a core, in the node's own colour. Off-axis and irregular on purpose; drawn behind the card so the rings overflow it. Shown in the done violet; the faint rounded box represents the card the decorator sits behind; it is included here so that you can see how much the decorator overflows a card.

azure

Ring semi-axes and rotations (rx, ry, deg): (72, 12, −30), (66, 13, 40), (68, 11, 103). Ball offsets from the centre: (45.4, −34.8), (−36.6, −40.5), (−5.5, 53.7).

6The cursor mark (Atomic Starburst)

The branch cursor: ten solid rays of irregular length at irregular angles off a base of 15, each tipped with a ball, around a solid core, in --ink. The cursor draws it at 1.15× the base size.

azure

The four-plus-spoke atmosphere burst is defined in the source but not currently mounted; see the constants in the Markdown.

7The tracks, and the underpass

A track is a polyline in --line with round caps and joins: a riser (the vertical spine, width 3), and the branch and return laterals (width 2.3). Where a lateral crosses another line, it yields, cut with a gap whose ends carry caps lying parallel to the line passed under, so the cut reads as a slice of what runs on. The illustration shows a return passing behind a riser.

azure

Illustrative crossing; the exact gap and cap geometry is the breakSize computation in the Markdown (air across the crossed line, perpClear 3 plus its half-width, divided by the sine of the crossing angle). In egui the cut becomes an explicit mitred ribbon quad, since egui clips only to a rectangle.

8The junction diamond

A fork or merge is marked by an 8-pixel square turned 45° into a diamond, in --line (turning to --ink on hover); a single-branch junction also carries a transparent 13-pixel hit halo, shown faint.

azure

9The note glyph

A card with a note shows a memo-pad glyph in its bottom-right corner, on a 16×16 viewbox, in --muted (turning to --ink on hover): a rounded body, two ring ticks over the top, three ruled lines. Shown at 4×.

azure

10Colours (two grounds)

Every fill and stroke is a role token resolving to one of two values by ground. Teal marks the structure of a plan (a project and its close); violet marks a task that is done. Values from style.css.

tokenroleazurenavy
--groundcanvas#d3e6ef#0f2334
--panelcard panel (task)#f8f3e8#1a3a54
--inktext, cursor mark#173242#e8f1f6
--linetracks, dots, diamonds#365b6c#6fb6c9
--mutedtags, note glyph#5f7d8b#93b3c2
--c-todoto-do#d9a53a#f0bd55
--c-progin-progress#d75f2e#f27a44
--c-donedone (violet)#7d54a6#bd93e6
--c-cancelcancelled#8aa0ab#7590a0
--c-projectproject hull (teal)#1f8f8a#37c2ba
--c-project-tintproject/close panel#cbe6e4#356e69
--cursorHERE pill, drop hints#d75f2e#f27a44

11egui translation contract

The only renderer-specific note; the argument for egui is in rust_port_ideas. In brief: flatten each quadratic to a sampled polyline before any camera transform; draw the outline as two fills, never a stroke; tessellate the concave hull and marquee with lyon into a Shape::Mesh, since epaint fills only convex polygons; apply SVG rotate/scale as affine operations on the point list; map strokes to an epaint::Stroke; and replace the even-odd underpass clip with an explicit mitred ribbon quad, because egui clips only to an axis-aligned rectangle. Drive zoom through world coordinates and font size, or atlas-sampled text blurs while the vector marks stay crisp.

Canonical source: docs/mark-geometry.md. This page is regenerated from it; if they drift, the Markdown wins. Sources for every number: render/shapes.js, render/tracks.js, render/card.js, render/scene.js, style.css, and node-visual-system.md.