### Build example pages Source: https://github.com/wheresryan22/anatomy/blob/main/CONTRIBUTING.md Each framework-free example is one script that writes standalone pages next to itself. The built pages are committed. The --light flag builds the light variant of an example. ```sh node examples/dial-indicator/build.mjs node examples/dial-indicator/build.mjs --light node examples/desk-computer/build.mjs node examples/desk-computer/build.mjs --light node examples/arcade-cabinet/build.mjs node examples/arcade-cabinet/build.mjs --light ``` -------------------------------- ### capture.mjs command-line examples Source: https://github.com/wheresryan22/anatomy/blob/main/references/verify.md Shows various invocations of scripts/capture.mjs with different options for capturing screenshots of a page. Options include --out, --width, --hover, --times, --key, --zoom, --reduced, and --select. The script starts its own headless Chrome and clips to the first .iso-plate by default. ```sh node scripts/capture.mjs page.html --out shots/desk.png # desktop 1440, dpr 2 node scripts/capture.mjs page.html --out shots/phone.png --width 390 # phone node scripts/capture.mjs page.html --out shots/hover.png --hover 0.7,0.5 # pointer at 70% across node scripts/capture.mjs page.html --out shots/tour.png --times 1200,2400,3600 # motion: extra shots over time node scripts/capture.mjs page.html --out shots/keys.png --key ArrowRight,ArrowRight node scripts/capture.mjs page.html --out shots/joint.png --zoom 200,80,220,170 # close-up at 4x, in card px node scripts/capture.mjs page.html --out shots/still.png --reduced # reduced motion node scripts/capture.mjs http://localhost:3000/docs --select "figure:nth-of-type(3) .iso-plate" # one figure on a dev-server page ``` -------------------------------- ### Install Anatomy as an Agent Skill Source: https://github.com/wheresryan22/anatomy/blob/main/README.md Installation command for the Anatomy Agent Skill. Run this to add the skill to your environment. ```bash npm install anatomy ``` -------------------------------- ### TURN.mount(stage, data, options) Source: https://github.com/wheresryan22/anatomy/blob/main/references/3d.md Binds every live layer in the stage, renders the rest pose, and installs window.__isoTurn. The options include onHold, onFrame, and follow callbacks. ```APIDOC ## TURN.mount(stage, data, { onHold, onFrame, follow }) ### Description Binds every live layer in `stage`, renders the rest pose, and installs `window.__isoTurn`. `follow(values)` maps figure values to group values on every `set` (one input drives coupled groups). `onFrame(controller)` runs after each render (draw shaders here). `onHold()` runs when a tool calls the hook. ### Parameters - `stage` (unknown) - Required - The stage to bind. - `data` (unknown) - Required - The data for the figure. - `options` (object) - Optional - Options object. - `onHold` (function) - Optional - Callback when a tool calls the hook. - `onFrame` (function) - Optional - Callback after each render. - `follow` (function) - Optional - Maps figure values to group values on every set. ### Returns - `controller` (object) - The controller object. ``` -------------------------------- ### Generate state files for --states Source: https://github.com/wheresryan22/anatomy/blob/main/references/3d.md This JavaScript example writes clip.json and tilt-path.json using the build module's follow and nodAt functions. clip.json is for --order, tilt-path.json is for --pops. The states list must be a continuous path in steps of about 0.02°. ```js import { writeFileSync } from "node:fs"; import { follow, nodAt } from "./build.mjs"; const at = (t) => follow({ yaw: 20 + 30 * t, tilt: nodAt(t) }); writeFileSync("clip.json", JSON.stringify(Array.from({ length: 241 }, (_, i) => at(i / 60)))); writeFileSync("tilt-path.json", JSON.stringify(Array.from({ length: 1201 }, (_, i) => follow({ yaw: 30, tilt: -12 + i * 0.02 })))); ``` -------------------------------- ### Construct a Minimal WebGL Page in build.mjs Source: https://github.com/wheresryan22/anatomy/blob/main/references/webgl.md Example of setting up a projection, defining data, and generating the HTML structure for a page containing both SVG and WebGL layers. ```js const P = k.fitProjection(points, W, H, { pad: 28, azimuth: 40 }); const DECK = { x: -90, y: -90, w: 180, d: 180, r: 8 }; const DATA = { W, H, camera: glCamera(P), plateR: 40, deck: [DECK.w / 2, DECK.r] }; const backSvg = k.figureSvg({ width: W, height: H, label: LABEL, body: back }); const frontSvg = ``; const stage = `
${backSvg}${frontSvg}
`; const page = k.pageHtml({ title, theme, body: `${k.plateHtml({ ...card, body: stage })}`, script: kitScript() + glScript() + LIVE.replace("__DATA__", JSON.stringify(DATA)) }); ``` -------------------------------- ### More prompts from the skill's evals Source: https://github.com/wheresryan22/anatomy/blob/main/README.md Additional example prompts from the skill's evals. These cover a Next.js database connection pooling figure, a CDN edge cache isometric SVG, a Bunsen burner with WebGL flame, and a heat-exchanger espresso machine with water flow animation. ```text /anatomy a figure for our Next.js docs on database connection pooling: a pool of 10 connections, requests borrow one and give it back, and when all 10 are busy new requests wait in a queue. A React component plus a static HTML preview, dark theme. ``` ```text /anatomy an isometric SVG explaining how a CDN edge cache works, cache hit vs miss, TTL of 60 s, for a dark landing page. Just the SVG file and a PNG preview. ``` ```text /anatomy a Bunsen burner on a lab bench: opening the air collar turns the lazy yellow flame into a roaring blue cone. WebGL for the flame, one HTML file, dark theme. ``` ```text /anatomy a heat-exchanger espresso machine with the side panel off: boiler, heat-exchanger tube, group head, pump, steam wand and gauge. Show the water flowing when you pull a shot. Standalone HTML, light theme. ``` -------------------------------- ### Drive script usage examples Source: https://github.com/wheresryan22/anatomy/blob/main/references/verify.md Shows various invocations of scripts/drive.mjs with different options for actions, dimensions, reduced mode, no-WebGL fallback, and preloading. ```sh node scripts/drive.mjs page.html '[["wait",1500],["move",".rt-stage",0.7,0.4],["wait",600],["shot","shots/hover.png"]]' node scripts/drive.mjs page.html --actions steps.json --height 1300 node scripts/drive.mjs page.html --actions steps.json --width 390 node scripts/drive.mjs page-light.html --actions steps.json --reduced node scripts/drive.mjs page.html --actions steps.json --no-webgl node scripts/drive.mjs page-light.html --actions steps.json --preload slow.js ``` -------------------------------- ### window.__isoTurn Source: https://github.com/wheresryan22/anatomy/blob/main/references/3d.md Global object with controller, set, get, order, events, stats, and layers. Every call holds the figure. ```APIDOC ## window.__isoTurn ### Description `{ controller, set, get, order, events, stats, layers }`; every call holds the figure (`onHold`). `set` takes a number or a values object. ### Properties - `controller` (object) - The controller. - `set` (function) - Sets values. - `get` (function) - Gets values. - `order` (function) - Gets order. - `events` (function) - Gets events. - `stats` (function) - Gets stats. - `layers` (array) - Layers. ``` -------------------------------- ### supports(solids, tubes, { ground, touch = 0.15, sunk = 0.5 }) Source: https://github.com/wheresryan22/anatomy/blob/main/references/kit.md Builds a contact graph of solids and rigid tubes and lists every solid not connected to the ground (default: names starting stand.), plus every pair of solids sunk more than sunk into each other unless they share an owner or one is seated on the other. hanging lists rigid tubes that connect to nothing held, and fails too. ```APIDOC ## supports(solids, tubes, { ground, touch = 0.15, sunk = 0.5 }) ### Description Builds a contact graph of solids and rigid tubes and lists every solid not connected to the ground (default: names starting stand.), plus every pair of solids sunk more than sunk into each other unless they share an owner or one is seated on the other. hanging lists rigid tubes that connect to nothing held, and fails too. ### Parameters - **solids** - The solids to check. - **tubes** - The tubes to check. - **ground** - Optional - Names of ground solids (default: names starting stand.). - **touch** (number, default 0.15) - Optional - Contact threshold. - **sunk** (number, default 0.5) - Optional - Sink threshold. ### Returns A list of solids not connected to ground and pairs of solids sunk more than sunk into each other, plus hanging rigid tubes. ``` -------------------------------- ### Browser check commands Source: https://github.com/wheresryan22/anatomy/blob/main/references/3d.md Run these Node.js commands to verify the turning-dial example. The --fidelity flag checks prisms, rounds, lathes, and tubes against kit functions; --order checks WebGL z-buffer against DOM painter fills; --pops detects visual differences; --states loads a JSON file of value objects; --perf measures performance. Controls are provided for each check. ```sh node examples/turning-dial/build.mjs --light --verify # writes turning-dial-verify-light.html node scripts/turn-check.mjs examples/turning-dial/build.mjs --fidelity node scripts/turn-check.mjs page-verify.html --order --step 1 node scripts/turn-check.mjs page-verify.html --order --states clip.json node scripts/turn-check.mjs page.html --pops --no-webgl --step 1 --out shots/pops node scripts/turn-check.mjs page.html --lines # and the dark page node scripts/turn-check.mjs page.html --perf --width 1440 node scripts/turn-check.mjs page.html --perf --width 390 --throttle 4 node scripts/turn-bench.mjs examples/turning-dial/build.mjs node scripts/drive.mjs page.html '[["turn", 37], ["shot", "a.png"], ["orbit", "orbit.png", 0, 345, 15]]' ``` -------------------------------- ### lines.mjs output showing floating line ends Source: https://github.com/wheresryan22/anatomy/blob/main/references/verify.md Example output from scripts/lines.mjs. It reports the count of floating ends and, for each, the end distance in card px, the card coordinates, the line length, and the start of the d path so you can find it in the build. Use --out to ring them on a 2× shot of the card. ```text line ends: 3 of 1148 ends on 295 lines float iso-line faint in it k -0.080 end 7.25 px from anything at card 507.4,407.2 length 75.7 d M392.1 381.7L507.4 407.2… ``` -------------------------------- ### Wait for cold engine with until action Source: https://github.com/wheresryan22/anatomy/blob/main/references/verify.md Wait for the engine to be cold before starting a slowed transition. Use this after pressing Escape and before the key that starts the transition, so the sheet films an opening rather than a close. ```json ["until", "document.querySelector('[data-readout]').textContent.includes('cold')"] ``` -------------------------------- ### T.build({ statics, poses, verify = false, strict = true }) Source: https://github.com/wheresryan22/anatomy/blob/main/references/3d.md Solves every pair, proves every static item's layer, packs the page data. Throws a readable error on any pair with no separating plane, any static that can't be proved, any non-convex part. ```APIDOC ## T.build({ statics, poses, verify = false, strict = true }) ### Description Solves every pair, proves every static item's layer, packs the page data. Throws a readable error on any pair with no separating plane, any static that can't be proved, any non-convex part. ### Parameters - **statics** - Required - Static items. - **poses** - Required - The figure's reachable states (a list or a function returning one): every motion clip, sampled. - **verify** (boolean) - Optional - Default: false. - **strict** (boolean) - Optional - Default: true. If false, keeps interlocked pairs. ### Returns Returns `out = { svg, data, css, report, layerSvg(name, { width, height }), verify }`. ``` -------------------------------- ### saddleOf(F, a, start, s1, P, { steps }) Source: https://github.com/wheresryan22/anatomy/blob/main/references/kit.md A saddle pad: a cylinder of radius `a` along `F.a` from a curved host surface to a flat face at `s1`. `start(angle)` is where each generator leaves the host (find it by bisecting the host's `sdf`), or a number `R` for a host cylinder perpendicular to `F.a` (then `saddleStart(R, a, angle)` gives each generator's start). ```APIDOC ## saddleOf(F, a, start, s1, P, { steps }) ### Description A saddle pad: a cylinder of radius `a` along `F.a` from a curved host surface to a flat face at `s1`. `start(angle)` is where each generator leaves the host (find it by bisecting the host's `sdf`), or a number `R` for a host cylinder perpendicular to `F.a` (then `saddleStart(R, a, angle)` gives each generator's start). The fill is the union of its visible facets and face, the outline its two side generators, the visible part of the saddle curve and the face rim, so it meets the host along the true intersection. Seat flanges on it wherever a flat flange on a curved body would leave a rim gap. ### Parameters - **F** (Frame) - Required - The frame defining the axis. - **a** (number) - Required - Radius of the cylinder. - **start** (function or number) - Required - Function `start(angle)` or a number `R` for a host cylinder. - **s1** (number) - Required - End `s` value. - **P** (Projection) - Required - The projection context. - **options** (object) - Optional - Options: `steps`. ``` -------------------------------- ### Install the anatomy skill with npx Source: https://github.com/wheresryan22/anatomy/blob/main/README.md Run this command to add the wheresryan22/anatomy skill to your environment with the claude-code agent. No API keys or npm install are required; the kit uses only Node's built-in modules. ```sh npx skills add wheresryan22/anatomy -g -a claude-code ``` -------------------------------- ### clearances(tubes, solids, { ratio = 0.5, least = 0.2, state, only, mounts }) Source: https://github.com/wheresryan22/anatomy/blob/main/references/kit.md Samples every tube and lists every place it comes closer than max(least, ratio * r) to a solid or another tube. Near a run's flat end it measures the end ring, not a sphere that would overhang the cut. Only an end's own mount, that mount's pipe, and the fittings of a line that shares the mount or lands on this tube are excused, and only within r + gap + 1 of the end; near an end anything else may still not be entered by more than 0.1. Pass state to pose everything and only: "through" to list penetrations alone. ```APIDOC ## clearances(tubes, solids, { ratio = 0.5, least = 0.2, state, only, mounts }) ### Description Samples every tube and lists every place it comes closer than max(least, ratio * r) to a solid or another tube. Near a run's flat end it measures the end ring, not a sphere that would overhang the cut. Only an end's own mount, that mount's pipe, and the fittings of a line that shares the mount or lands on this tube are excused, and only within r + gap + 1 of the end; near an end anything else may still not be entered by more than 0.1. Pass state to pose everything and only: "through" to list penetrations alone. ### Parameters - **tubes** - The tubes to check. - **solids** - The solids to check against. - **ratio** (number, default 0.5) - Optional - Multiplier for the tube radius to determine clearance threshold. - **least** (number, default 0.2) - Optional - Minimum clearance threshold. - **state** - Optional - Pose state to apply before checking. - **only** (string) - Optional - If "through", list only penetrations. - **mounts** - Optional - Mount information for excusing certain fittings. ### Returns A list of every place where a tube comes closer than the threshold to a solid or another tube. ``` -------------------------------- ### Run the audit with node examples/raptor-engine/build.mjs --audit Source: https://github.com/wheresryan22/anatomy/blob/main/references/verify.md Run the audit from the command line after wiring kit/audit.mjs into the build. The output lists each audit category with a count of problems; a clean run reports 0 problems for every check except free ends apart, which reports 35 items marked free (not failing). ```sh node examples/raptor-engine/build.mjs --audit ``` ```text clearance: 0 problems clearance apart: 0 problems terminals: 0 ends not on a mount loose ends: 0 screen folds: 0 support: 0 unsupported solids · 0 hanging tubes · 0 sunk pairs depth order: 0 problems through in mid-flight: 0 pairs self-overlap: 0 chunks whose outline crosses itself on screen wobble: 0 smoothed profiles whose slope turns between its ends saddles off their host apart: 0 stand-in shapes: 0 items whose recorded shape covers too little of what it draws crowding: 0 pairs where a bend or end touches another line on screen free ends apart (marked free, not failing): 35 audit · 80 tubes · 267 solids · 478 items · 1119 depth order ``` -------------------------------- ### Define Trunnion and Arm Components Source: https://github.com/wheresryan22/anatomy/blob/main/references/3d.md Example of defining round components for a trunnion and arm assembly, ensuring proper spacing for joint clearance. ```js T.round({ name: "yaw.arm+", group: yaw, layer, F: VERT(0, 11.7), s0: 40, s1: 61, r: 1 }); T.round({ name: "head.can", group: tilt, layer, F: frameOf([0, 0, 56], [1, 0, 0], [0, 0, 1]), s0: -12, s1: 8, r: 9 }); T.round({ name: "head.trunnion+", group: tilt, layer, F: frameOf([0, 9, 56], [0, 1, 0], [0, 0, 1]), s0: 0, s1: 1.7, r: 4.5 }); ``` -------------------------------- ### ISO_CSS Source: https://github.com/wheresryan22/anatomy/blob/main/references/kit.md All the styles. kit/iso.css is the same text. ```APIDOC ## ISO_CSS ### Description All the styles. kit/iso.css is the same text. ### Returns CSS string. ``` -------------------------------- ### Link working copy as Claude skill Source: https://github.com/wheresryan22/anatomy/blob/main/CONTRIBUTING.md Symlink the working copy into the personal skills folder so the skill can be used while it is being changed. Move any installed copy out of the way first. ```sh ln -s "$PWD" ~/.claude/skills/anatomy ``` -------------------------------- ### turning(P, { recorder, scale = 1 }) Source: https://github.com/wheresryan22/anatomy/blob/main/references/3d.md The builder T. Pass the kit recorder so every live shape is recorded for the kit audit too. ```APIDOC ## turning(P, { recorder, scale = 1 }) ### Description The builder T. Pass the kit recorder so every live shape is recorded for the kit audit too. ### Parameters - **P** - Required - The scene or part to turn. - **recorder** - Required - The kit recorder. - **scale** (number) - Optional - Default: 1. Scale factor. ``` -------------------------------- ### moved(shape, offset), sdf(shape, p), boundsOf(shape) Source: https://github.com/wheresryan22/anatomy/blob/main/references/kit.md Helper functions: translate a shape, compute signed distance (negative inside), and get world bounds. ```APIDOC ## moved(shape, offset) ### Description Translates a shape by the given offset. ### Parameters - **shape** (Shape) - Required - The shape to translate. - **offset** (Array) - Required - Translation offset [x, y, z]. ### Returns - **Shape** - The translated shape. ## sdf(shape, p) ### Description Computes the signed distance from point p to the shape (negative inside). ### Parameters - **shape** (Shape) - Required - The shape. - **p** (Array) - Required - Point coordinates [x, y, z]. ### Returns - **Number** - Signed distance. ## boundsOf(shape) ### Description Returns the world bounds of the shape. ### Parameters - **shape** (Shape) - Required - The shape. ### Returns - **Bounds** - The world bounds. ``` -------------------------------- ### Invoke the anatomy skill in Claude Code Source: https://github.com/wheresryan22/anatomy/blob/main/README.md After adding the skill, run this command inside Claude Code to explain a topic interactively. The example asks for an interactive explanation of a token bucket rate limiter. ```text /anatomy explain how a token bucket rate limiter works, interactive ``` -------------------------------- ### solidClearances(solids, { state, sunk = 0.5 }) Source: https://github.com/wheresryan22/anatomy/blob/main/references/kit.md Poses the solids and, for every pair that sits at a different offset in that state, tests each one's surface points against the other's sdf; anything more than sunk inside fails. Run it at state 1 and in every replayed and prefix state. ```APIDOC ## solidClearances(solids, { state, sunk = 0.5 }) ### Description Poses the solids and, for every pair that sits at a different offset in that state, tests each one's surface points against the other's sdf; anything more than sunk inside fails. Run it at state 1 and in every replayed and prefix state. ### Parameters - **solids** - The solids to check. - **state** - Optional - Pose state to apply. - **sunk** (number, default 0.5) - Optional - Sink threshold. ### Returns A list of solid pairs that are sunk more than sunk into each other. ``` -------------------------------- ### fadeLineSvg(points, options) Source: https://github.com/wheresryan22/anatomy/blob/main/references/kit.md One line (screen points) that fades out over its first start and last end px instead of stopping. Each ramp is stroked with a userSpaceOnUse linear gradient along its own chord, and the middle is a plain lineSvg. ```APIDOC ## fadeLineSvg(points, options) ### Description One line (screen points) that fades out over its first start and last end px instead of stopping. Each ramp is stroked with a userSpaceOnUse linear gradient along its own chord, and the middle is a plain lineSvg. ### Parameters - **points** (array) - Required - Array of screen points. - **options** (object) - Optional - Configuration options. - **fade** (array) - Optional - Default [start, end]. The fade range in pixels. - **tone** (string) - Optional - Default 'lo'. The tone of the line. - **className** (string) - Optional - Additional CSS class. - **stops** (number) - Optional - Default 6. Number of gradient stops. ### Returns - **string** - SVG string. ``` -------------------------------- ### TURN (runtime) Source: https://github.com/wheresryan22/anatomy/blob/main/references/kit.md The TURN runtime controller provides methods for mounting a stage, controlling the scene, and managing poses, cameras, and layers. It also includes utility functions for rotations, materials, and CSS. ```APIDOC ## TURN (runtime) ### Description The TURN runtime controller provides methods for mounting a stage, controlling the scene, and managing poses, cameras, and layers. It also includes utility functions for rotations, materials, and CSS. ### Methods - **TURN.mount(stage, data, { onHold, onFrame, follow })** - The controller. Returns an object with methods: `set(values | θ, { detail })`, `render()`, `angleAt(x, y, z, group)`, `values`, `pose(name)`, `detach(name)`, `anchor(group, restPoint, restDir?)`, `cover(names, options)`, `order(layer)`, `orderIndex(layer)`, `events()`, `stats()`, `frames()`, `cams()`, `scene()`, `destroy()`. Installs `window.__isoTurn`. - **TURN.cover(controller, names | [names…], { polygons = 6, edges = 10, pad = 0.3, layers })** - Returns `{ uCoverEdge, uCoverCount, dropped, parts }` for `coverOf`. - **TURN.poseUniforms(controller, group, prefix = "uGroup")** - Returns four `vec3` for `GLSL_TURN` or `glslPose`. - **TURN.anchor(scene, cams, group, point, dir)** - Anchors outside a controller. - **TURN.floorOf(scene, group, R)** - Returns the lowest z of a group under a rotation. - **TURN.rotation(axis, deg)** - Returns a rotation as `[9]`. - **TURN.quat(q)** - Returns a rotation as `[9]`. - **TURN.compose(A, B)** - Returns a rotation as `[9]`. - **TURN.materials** - Material names. - **TURN.materialCss()** - Returns the CSS for materials. - **TURN.css()** - Returns the CSS. - **TURN_CSS** - The CSS. - **TURN.camera**, **TURN.poses**, **TURN.cams**, **TURN.prepare**, **TURN.emit**, **TURN.order**, **TURN.frame**, **TURN.gjk**, **TURN.disjoint**, **TURN.q**, **TURN.levels** - The pipeline, for tools: cameras per group, a prepared scene, one part's frame, a layer's order. ```