Skip to content

core

The backend-agnostic scene model: a retained Scene that records vector geometry through a PathContext, flattens curves, groups rings, tessellates fills, expands strokes, and packs everything into GPU-ready buffers with per-drawable color/flag side-tables. HitIndex provides CPU hit-testing over the same data.

import { Scene } from "@mapequation/d3gl";
const scene = new Scene(0.5);
scene.group("shapes", (g) => g.drawable("a", (ctx) => { ctx.rect(0, 0, 10, 10); }));
scene.setFill("shapes", "a", "#3366cc");
const buffers = scene.buffers("shapes"); // GPU-ready typed arrays
ClassDescription
HitIndex-
PathRecorderRecords PathContext drawing calls into flattened polylines (subpaths). This is the retained-mode capture used by GPU backends: call a d3 generator into a PathRecorder once, then hand the subpaths to the tessellator.
Scene-
InterfaceDescription
BackendA renderer for a Scene, implemented per target (WebGL / Canvas / SVG).
DeclutterScratchReusable grid scratch so a per-frame caller (geo declutter runs on every zoom) allocates nothing.
DrawableOpts-
DrawableRangeContiguous slice a drawable occupies within a group’s shared buffers.
DrawableVector-
DrawBatchGeneralized transient pass-through payload (built per repaint, discarded).
FillGeometry-
GroupBufferDeltaBuffers for an appended TAIL of a group (see Scene.appendedBuffers). Same arrays as GroupBuffers but each holds only the newly-appended data; index values are group-absolute. drawableCount is the total after the append, fromDrawable the index where the new range begins. Point count = pointCenters/4.
GroupBuffersGPU-ready typed arrays for one group. Vertices are [x, y, drawableId].
GroupBuilder-
InstancedArrowsDataSoA for a batch of instanced triangle arrowheads (directed-link tips).
InstancedCirclesDataSoA for a batch of instanced circles (e.g. network nodes). Plain typed arrays.
InstancedHalfArrowsDataSoA for a batch of instanced half-arrow links (#104 N6) — the “map of networks” directed-link glyph: one filled shape per link, pinched to the source centre and ending in a barbed arrowhead on the target boundary, bowed around a shared centre curve (see network/half-link.ts). All world units.
InstancedHighlightShader-driven highlight state for an instanced layer (#162). Passed to Backend.styleInstancedLayer, it maps to vertex-shader uniforms so hover/selection restyle costs no geometry rebuild: - hoverGroup — the hovered node’s group id (matched against each instance’s groups); -1 = none. - dimActive / dimOpacity — fade every non-highlighted instance’s alpha by dimOpacity when active. - recolor — RGB (0..1) a highlighted instance is tinted toward, preserving luminance (so a weight- encoded link keeps its weight); null/absent ⇒ highlighted instances keep their colour (e.g. nodes). - selected — optional per-instance flag buffer (0/1) to upload in place (a selection change), instead of re-emitting the layer. Length must equal the layer’s instance count.
InstancedLinesDataSoA for a batch of instanced lines (e.g. network links); straight, or bent via bends.
InstancedPieDataSoA for a batch of instanced pie wedges (#171) — the physical-view glyph for a state network’s overlapping module membership. One instance per wedge (not per pie): a wedge is an angular [startFrac, endFrac] sector of a disc, so a physical node spanning w modules contributes w wedge instances sharing a centre/radius. Reuses the circle’s quad+SDF-disc positioning; the fragment discards outside the disc and outside the wedge’s angular range, so there is no per-fragment loop and no wedge texture — it draws in one instanced call and updates in place like InstancedCirclesData. (Single-module physical nodes stay on the InstancedCirclesData lane as solid discs.)
PassThroughLayerIdentifies a pass-through layer to a backend (no retained geometry).
PathContextPathContext is the seam of d3gl: the subset of CanvasRenderingContext2D’s path API that d3 path-emitting generators (d3-geo geoPath, d3-shape, d3-chord, d3-hierarchy links) actually call. Implement this once per backend and any of those generators can render to that backend unchanged.
PointBatchTransient, GPU/Canvas-ready point data. Owned by no one — built per repaint and discarded.
ProjectedPathOne projected path feature, ready to draw. Canvas draws natively; WebGL tessellates per frame.
RenderDeltaAn incremental append for one layer: only the drawables added at/after buffers.fromDrawable. buffers are the delta GPU buffers (for WebGL), drawables the matching new vector views (for Canvas/SVG draw-on-top). Index values in buffers are group-absolute, so a backend whose buffers mirror the group appends verbatim. clipTo/sizeMode mirror the layer’s current settings.
RenderLayerOne named layer handed to a backend: GPU buffers + the vector view + optional clip.
RingGroupOne filled polygon: an outer ring plus zero or more hole rings.
StrokeGeometry-
StrokeOptions-
StyleTablesJust the per-drawable style tables (colors + flags), for styles-only backend updates — never the O(total-vertices) Scene.buffers rebuild: geometry hasn’t changed, only how it’s painted. LIVE views of the Scene’s typed storage (#207) — zero copies/allocation per call; see Scene.styleTables.
SubpathA flattened subpath: a polyline plus whether it was closed.
TextDataOne backend-rendered text label (#105 N7b-2). Positioned in screen pixels (the caller projects the world anchor and applies the view transform) and drawn at a constant pixel font, so labels stay readable at any zoom — re-pushed each setTransform, like the HTML overlay it mirrors. Drawn live by the SVG (<text>) and Canvas (fillText) backends; the WebGL backend keeps the HTML overlay on screen (GPU/MSDF text is #69) but retains the set for export (#219), so labels survive toSVG()/toPNG() on all three backends.
ViewTransformView transform applied on top of project-once geometry: scale k, translate (x, y).
Type AliasDescription
DrawItemWhat a PassThroughSpec yields per datum (generalizes the point-only project()).
InstancedLayerA named GPU-instanced primitive layer — the network rendering lane (#100).
LineCapOpen-subpath end-cap style.
LineJoinStroke join style.
VariableDescription
DEFAULT_MITER_LIMITDefaults match the Canvas 2D defaults and are pinned identically on Canvas/SVG so the three backends agree. (SVG’s own default miter limit is 4, so it must be set explicitly.)
versionThe d3gl package version, injected at build time from package.json.
FunctionDescription
declutterMembersEnumerate the glyphs a kept survivor represents from a declutterScreen winners array: every glyph mapped to kept (including kept itself, which maps to itself). O(count) inverse scan — run lazily on a hit (members()), never per frame. Returns indices in source order.
declutterScratchA fresh, empty scratch (grown lazily on first use). Hold one per engine and pass it in to reuse it.
declutterScreenGreedy screen-space declutter. Visits glyphs in order (importance descending; omitted ⇒ index order) and keeps each unless its centre is within spacing·(rᵢ + rⱼ) of an already-kept glyph — so the drawn circles don’t overlap and the most important glyph in a cluster survives. A glyph whose centre is off-screen is always kept and never occludes others (so panning never culls what’s barely out of view). O(n) via a uniform grid sized to the largest exclusion radius, so any overlapping pair falls in the 3×3 cell neighbourhood.
expandStrokeExpand a polyline into fill triangles for a stroke of the given width.
flattenArcCircular arc, matching CanvasRenderingContext2D.arc semantics.
flattenCubicCubic bezier from (x0,y0) to (x3,y3) with control points (x1,y1),(x2,y2).
flattenQuadraticQuadratic bezier: elevate to cubic and reuse the cubic flattener.
groupRingsGroup a flat list of closed rings into filled polygons with holes.
pointInRingRay-casting point-in-polygon test against a ring (interleaved x,y).
signedAreaShoelace signed area of a ring (interleaved x,y). Positive for counter-clockwise winding, negative for clockwise. Magnitude is the area.
tessellateFillTriangulate filled (closed) subpaths into triangles via earcut.