API Reference

Auto-generated from source metadata. Functions marked Provisional may have API changes in future releases.

eido.core

Rendering and export — the main entry point for Eido. Use `render` for one-stop rendering of scenes and animations to images, SVG, GIF, or polyline data. Specialized functions (`render-to-file`, `render-to-svg`, etc.) are also available for direct use.

*validate*
Controls whether scene validation runs before compilation.
Defaults to true. Bind to false in REPL/watch workflows for faster
re-renders. The show and watch-* dev helpers automatically skip
validation after the first successful render.
(explain scene)
Validates a scene and prints human-readable errors to *out*.
Returns the error vector, or nil if valid.
(format-errors errors)
Formats validation errors as a human-readable string.
Takes a vector of error maps as returned by validate.
(read-scene path)
Reads an EDN file and returns the scene map.
(render input)
(render input opts)
Renders a scene or animation.

Single scene:
(render scene) → BufferedImage
(render scene {:output "out.png"}) → writes file, returns path
(render scene {:format :svg}) → SVG string
(render scene {:format :dxf}) → DXF R12 string
(render scene {:format :gcode}) → GRBL G-code string
(render scene {:format :hpgl}) → HPGL plotter string
(render scene {:format :polylines}) → {:polylines [...] :bounds [w h]}

Animation (sequence of scenes):
(render frames {:output "a.gif" :fps 30}) → animated GIF
(render frames {:output "a.svg" :fps 30}) → animated SVG file
(render frames {:output "dir/" :fps 30}) → PNG sequence
(render frames {:format :svg :fps 30}) → animated SVG string

Common opts: :scale, :transparent-background, :quality (JPEG), :dpi (PNG/TIFF),
:tiff/compression (:lzw :deflate :none),
:loop (GIF, default true), :prefix (frame sequence).

Validation: scenes are validated before compilation by default. Bind
*validate* to false for faster REPL iteration, or set :eido/validate
false on the scene map.
(render-animation scenes dir)
(render-animation scenes dir opts)
Renders a sequence of scenes to numbered PNG files in a directory.
Returns a vector of written file paths.
Opts: :scale, :transparent-background, :prefix (default "frame-").
(render-batch jobs)
(render-batch generate-fn n)
Renders a sequence of export jobs to files. Each job is a map with
:scene, :path, and optional :opts. Returns a vector of written paths.
With a generator fn and count, calls (f i) for each index.
(render-file path)
Reads an EDN scene file and renders it to a BufferedImage.
(render-from-manifest path)
(render-from-manifest path override-opts)
Reads a manifest EDN file and re-renders the scene using stored options.
Override keys in opts to change output path, format, etc.
(render-to-animated-svg scenes path opts)
Renders a sequence of scenes to an animated SVG file.
Opts: :fps (required), :scale, :transparent-background.
(render-to-animated-svg-str scenes opts)
Renders a sequence of scenes to an animated SVG string using SMIL.
Opts: :fps (required), :scale, :transparent-background.
(render-to-file scene path)
(render-to-file scene path opts)
Renders a scene and writes to file. Format detected from extension.
Supported formats: PNG, JPEG, GIF, BMP, TIFF, SVG, DXF, G-code, HPGL.
Opts: :format, :quality (JPEG), :scale, :transparent-background,
:dpi (PNG/TIFF), :tiff/compression (:lzw :deflate :none),
:emit-manifest? (write EDN sidecar for reproducibility).
DXF/G-code/HPGL also accept :flatness, :segments, :optimize-travel,
and any writer-specific keys (see eido.io.dxf, eido.io.gcode,
eido.io.hpgl).
(render-to-gif scenes path opts)
Renders a sequence of scenes to an animated GIF.
Opts: :fps (required), :scale, :transparent-background, :loop (default true).
(render-to-svg scene)
(render-to-svg scene opts)
Renders a scene to an SVG XML string.
Opts: :scale, :transparent-background, :stroke-only, :group-by-stroke,
:deduplicate, :optimize-travel.
(validate scene)
Validates a scene map against the Eido scene spec.
Returns nil if valid, or a vector of error maps with
:path, :pred, :message, and :value.

eido.path

Path operations: boolean ops (union, intersection, difference, xor) plus re-exports from sub-namespaces: eido.path.stroke — stroke profiles & expansion eido.path.distort — noise/wave distortion eido.path.warp — twist/fisheye/bend/bulge eido.path.morph — path interpolation eido.path.decorate — path decoration

(chaikin-commands commands opts)
Chaikin corner-cutting smoothing on path commands.
Produces rounder, more uniform curves than Catmull-Rom.
opts: :iterations (3), :retain-ends (true).
(contains-point? polygon [px py])
Tests whether a point [px py] is inside a polygon [[x y] ...].
Uses the ray-casting algorithm (count horizontal ray crossings).
(dash-commands commands opts)
Breaks path commands into dashed segments.
opts: :dash [on-length off-length] — required
:offset (0.0) — shift the pattern start
Returns a vector of path-command vectors, one per dash.
(decorate-path path-cmds shape opts)
Places copies of shape at intervals along path-cmds.
opts: :spacing (required), :rotate? (default false).
Returns a vector of group nodes with transforms.
(difference cmds-a cmds-b)
Returns path commands for shape A minus shape B.
(distort-commands commands opts)
Distorts path commands using the specified method.
opts keys: :type (:noise, :wave, :roughen, :jitter)
For :noise:amplitude, :frequency, :seed
For :wave:axis (:x or :y), :amplitude, :wavelength
For :roughen/:jitter:amount, :seed
(ink-preset seed)
Returns stylize steps for ink-stroke aesthetics.
Moderate Chaikin smoothing with organic jitter.
(inset polygon d)
Shrinks a closed polygon inward by distance d.
Returns a vector of [[x y] ...] points.
Works correctly for convex polygons; concave polygons may produce
self-intersecting results.
(interpolate commands-a commands-b t)
Blends between two paths at parameter t (0-1).
Both paths must have the same number and type of commands.
Returns blended path commands.
(intersection cmds-a cmds-b)
Returns path commands for the intersection of two shapes.
(jittered-commands commands opts)
Adds organic jitter to path commands.
Resamples for uniform point density, then applies jitter distortion.
opts: :amount (3.0), :density (1.0) — approximate spacing between points,
:seed (0)
(morph commands-a commands-b t)
Interpolates between two path command sequences at parameter t (0-1).
Both must have the same number of commands and matching types.
(morph-auto commands-a commands-b t)
Resamples both paths to matching point counts, then morphs at t.
Works with any two closed or open paths.
(outline-commands path-cmds profile max-width)
Generates path commands for a variable-width stroke outline.
path-cmds: scene-format path commands ([:move-to [x y]] ...)
profile: keyword or [[t width-factor] ...] pairs
max-width: the maximum stroke width (profile scales this)
(pencil-preset seed)
Returns stylize steps for pencil-line aesthetics.
Light smoothing, fine jitter, short dashes for sketch feel.
(resample commands n)
Resamples path commands to exactly n evenly-spaced points.
Flattens curves to line segments first.
(resolve-profile profile)
Resolves a profile keyword to a vector of [t width-factor] pairs,
or passes through a vector.
(shape->path-commands node)
Converts a primitive shape node to path commands.
(simplify points epsilon)
Douglas-Peucker path simplification on [[x y] ...] point vectors.
Removes points that contribute less than epsilon to the shape.
(simplify-commands commands epsilon)
Douglas-Peucker simplification on path commands.
Wraps simplify on the extracted points and rebuilds commands.
(smooth-commands commands opts)
Smooths path commands by resampling and fitting Catmull-Rom curves.
opts: :samples (32) — resample count before fitting.
(split-at-length commands segment-length)
Splits path commands into segments of approximately equal arc-length.
Returns a vector of path-command vectors, one per segment.
Helper
Wraps smooth-commands
(stylize commands steps)
Applies path aesthetic transforms described as data.
Wraps smooth-commands, jittered-commands, dash-commands, chaikin-commands.
steps: vector of {:op :smooth/:jitter/:dash/:chaikin, ...opts}.
Example: (stylize cmds [{:op :chaikin :iterations 3} {:op :dash :dash [10 5]}])
(trim-to-bounds commands bounds)
Clips path commands to a bounding rectangle.
bounds: [x y w h] clipping region.
Returns a vector of path-command vectors (one per visible segment).
Flattens curves to line segments before clipping.
(union cmds-a cmds-b)
Returns path commands for the union of two shapes.
(warp-commands commands spec)
Applies a warp transformation to path commands.
(warp-node node spec)
Recursively warps a node tree. Converts primitives to paths, then warps.
(watercolor-preset seed)
Returns stylize steps for watercolor-edge aesthetics.
Heavy Chaikin smoothing with pronounced jitter for bleeding edges.
(width-at profile t)
Linearly interpolates width from a profile at parameter t (0..1).
Profile is a vector of [t width] pairs, sorted by t.
(xor cmds-a cmds-b)
Returns path commands for the symmetric difference of two shapes.

eido.scene

Declarative scene construction helpers. Functions for building scene nodes: text, shapes, grids, radial layouts, and paper presets. Returns plain maps that compose with the scene data format — no special types or wrappers.

Helper
(circle-node center radius)
(circle-node center radius fill)
Creates a circle node. Shorthand for the {:node/type :shape/circle ...} map.
Example: (circle-node [200 200] 50 [:color/name "red"])
(distribute n [x1 y1] [x2 y2] f)
Generates n nodes distributed evenly along a line from p1 to p2.
f receives (x y t) where t is the normalized parameter [0.0, 1.0].
For n=1, places at the midpoint. For n>1, includes both endpoints.
(grid cols rows f)
Generates a vector of nodes by calling f for each cell in a cols x rows grid.
f receives (col row) and must return a node map (or nil to skip).
Cells are visited row-major: (0,0) (1,0) (2,0) ... (0,1) (1,1) ...
Helper
(line-node from to)
(line-node from to stroke)
Creates a line node. Shorthand for the {:node/type :shape/line ...} map.
stroke is a map with :color and :width keys.
Example: (line-node [0 0] [100 100] {:color [:color/name "black"] :width 2})
(paper size & {:keys [landscape dpi], :or {landscape false, dpi 300}})
Returns a base scene map for a named paper size.
Keyword args: :landscape (false), :dpi (300).
The returned map includes :image/size, :image/units, and :image/dpi
pass through with-units before rendering.

Example:
(paper :a4) ;=> {:image/size [21.0 29.7] :image/units :cm :image/dpi 300}
(paper :letter :landscape true) ;=> {:image/size [11.0 8.5] :image/units :in :image/dpi 300}
paper-sizes
Standard paper sizes as [width height unit] triples.
Width and height are in the specified unit.
Helper
(points->path points)
(points->path points closed?)
Converts [x y] points to path commands.
Convenience for (into [[:move-to p0]] (mapv (fn [p] [:line-to p]) rest)).
Helper
Wraps radial
(polar->xy [cx cy] radius angle)
Converts polar coordinates to [x y].
Wraps the trig: (+ cx (* r (cos a))), (+ cy (* r (sin a))).
(polygon points)
Creates a closed path node from a sequence of [x y] points.
(radial n [cx cy] radius f)
Generates n nodes distributed evenly around a circle.
f receives (x y angle) where angle is in radians [0, 2*pi).
Angles start from the top (12 o'clock) and proceed clockwise.
Helper
(rect-node xy size)
(rect-node xy size fill)
Creates a rect node. Shorthand for the {:node/type :shape/rect ...} map.
Example: (rect-node [10 10] [100 50] [:color/name "blue"])
(regular-polygon [cx cy] radius n)
Creates a closed regular n-sided polygon path node centered at [cx cy]
with the given radius. First vertex is at the top (12 o'clock).
Helper
Wraps radial
(ring n [cx cy] radius shape)
Places n copies of shape in a circle. Returns a vector of translated nodes.
Convenience for (radial n [cx cy] radius (fn [x y _] shape-with-translate)).
(smooth-path points)
Creates a smooth path through a sequence of [x y] points using
Catmull-Rom to cubic bezier conversion. Returns a path node.
(star [cx cy] outer-radius inner-radius n)
Creates a closed star path node with n points centered at [cx cy].
outer-radius is the distance to the tips, inner-radius to the inner vertices.
(text content origin font-spec)
Creates a text node rendered as vector paths.
(text-clip content [ox oy] font-spec children)
Creates a group clipped to text outlines. Children are clipped to the
text shape — anything inside the letters shows through.
(text-glyphs content origin font-spec glyph-overrides)
Creates a per-glyph text node. glyph-overrides is a vector of maps,
each with :glyph/index and optional :style/fill, :style/stroke,
:node/transform, :node/opacity.
(text-on-path content path-commands font-spec)
Creates text that follows a path. path-commands uses the same format
as :shape/path — [[:move-to [x y]] [:curve-to ...] ...].
(text-outline content [ox oy] font-spec)
Returns text as a path node — the vector outline of the glyphs.
Useful as a clip mask, for boolean ops, or as a standalone shape.
(text-stack content origin font-spec layers)
Creates layered text (e.g. shadow + outline + fill).
layers is a vector of style maps applied to copies of the same text.
Earlier layers render behind later ones.
(triangle p1 p2 p3)
Creates a triangle path node from three [x y] points.
(with-margin scene margin)
Wraps a scene's nodes in a group clipped to an inset rectangle.
Margin is the distance in pixels from each edge.
Uses existing :group/clip infrastructure — no new rendering machinery.
(with-units scene)
Converts a scene described in real-world units to pixel coordinates.
Reads :image/units (:cm, :mm, or :in) and :image/dpi from the scene,
walks the scene tree scaling all spatial values by the conversion factor.
Strips :image/units from the result; retains :image/dpi for metadata embedding.
The core rendering pipeline remains pixel-based — this is a preprocessing step.

Example:
(-> (paper :a4)
(assoc :image/background :white
:image/nodes [...])
with-units)

eido.text

Text-to-path conversion for artistic typography. Converts text nodes into standard Eido path nodes via Java 2D font APIs. No external dependencies — uses JDK built-in Font, GlyphVector, PathIterator.

(flatten-commands commands)
(flatten-commands commands flatness)
Approximates curves as line segments. flatness controls subdivision.
(glyph-contours commands)
Splits path commands into separate closed contours.
Returns [[cmd ...] [cmd ...] ...], one vector per contour.
(path-length commands)
Returns total arc length of path commands.
(point-at commands distance)
Returns {:point [x y] :angle rad} at a given distance along path commands.
resolve-font
Resolves a font-spec map to a java.awt.Font. Memoized.
(text->glyph-paths content font-spec)
Converts a string + font-spec to per-glyph path data.
Returns [{:commands [...] :position [x y]} ...], one entry per glyph.
Commands are relative to each glyph's own origin (not layout position).
:position gives the glyph's layout position within the string.
(text->path-commands content font-spec)
Converts a string + font-spec to Eido path commands for the entire text.
Returns at the origin [0 0]; caller positions via :text/origin.
(text-advance content font-spec)
Returns the total advance width of text rendered with the given font-spec.
(text-glyphs-node->group node)
Expands a :shape/text-glyphs node into a :group with one :shape/path per glyph.
(text-node->group node)
Expands a :shape/text node into a :group with a single :shape/path child.
(text-on-path-node->group node)
Expands a :shape/text-on-path node into a :group with glyphs along a path.

eido.path.stroke

Stroke profiles and variable-width path expansion. Apply named or custom width profiles to convert open paths into filled outlines.

(outline-commands path-cmds profile max-width)
Generates path commands for a variable-width stroke outline.
path-cmds: scene-format path commands ([:move-to [x y]] ...)
profile: keyword or [[t width-factor] ...] pairs
max-width: the maximum stroke width (profile scales this)
(resolve-profile profile)
Resolves a profile keyword to a vector of [t width-factor] pairs,
or passes through a vector.
(width-at profile t)
Linearly interpolates width from a profile at parameter t (0..1).
Profile is a vector of [t width] pairs, sorted by t.

eido.path.distort

Point-level path distortion using noise, waves, roughening, and jitter. Each distortion displaces individual points without changing path topology.

(distort-commands commands opts)
Distorts path commands using the specified method.
opts keys: :type (:noise, :wave, :roughen, :jitter)
For :noise:amplitude, :frequency, :seed
For :wave:axis (:x or :y), :amplitude, :wavelength
For :roughen/:jitter:amount, :seed

eido.path.warp

Geometric coordinate warps: twist, fisheye, bulge, bend, and wave. Each warp remaps point positions through a spatial transformation.

(shape->path-commands node)
Converts a primitive shape node to path commands.
(warp-commands commands spec)
Applies a warp transformation to path commands.
(warp-node node spec)
Recursively warps a node tree. Converts primitives to paths, then warps.

eido.path.morph

Path interpolation and shape morphing. Blends between two paths by resampling them to equal point counts and interpolating positions.

(morph commands-a commands-b t)
Interpolates between two path command sequences at parameter t (0-1).
Both must have the same number of commands and matching types.
(morph-auto commands-a commands-b t)
Resamples both paths to matching point counts, then morphs at t.
Works with any two closed or open paths.
(resample commands n)
Resamples path commands to exactly n evenly-spaced points.
Flattens curves to line segments first.

eido.path.decorate

Place copies of a shape at regular intervals along a path, optionally rotating each copy to follow the path tangent.

(decorate-path path-cmds shape opts)
Places copies of shape at intervals along path-cmds.
opts: :spacing (required), :rotate? (default false).
Returns a vector of group nodes with transforms.

eido.path.aesthetic

High-level path aesthetic helpers: smoothing, jitter, and dashing. Operates on path commands and returns path commands.

(chaikin-commands commands opts)
Chaikin corner-cutting smoothing on path commands.
Produces rounder, more uniform curves than Catmull-Rom.
opts: :iterations (3), :retain-ends (true).
(dash-commands commands opts)
Breaks path commands into dashed segments.
opts: :dash [on-length off-length] — required
:offset (0.0) — shift the pattern start
Returns a vector of path-command vectors, one per dash.
(ink-preset seed)
Returns stylize steps for ink-stroke aesthetics.
Moderate Chaikin smoothing with organic jitter.
(jittered-commands commands opts)
Adds organic jitter to path commands.
Resamples for uniform point density, then applies jitter distortion.
opts: :amount (3.0), :density (1.0) — approximate spacing between points,
:seed (0)
(pencil-preset seed)
Returns stylize steps for pencil-line aesthetics.
Light smoothing, fine jitter, short dashes for sketch feel.
(smooth-commands commands opts)
Smooths path commands by resampling and fitting Catmull-Rom curves.
opts: :samples (32) — resample count before fitting.
Helper
Wraps smooth-commands
(stylize commands steps)
Applies path aesthetic transforms described as data.
Wraps smooth-commands, jittered-commands, dash-commands, chaikin-commands.
steps: vector of {:op :smooth/:jitter/:dash/:chaikin, ...opts}.
Example: (stylize cmds [{:op :chaikin :iterations 3} {:op :dash :dash [10 5]}])
(watercolor-preset seed)
Returns stylize steps for watercolor-edge aesthetics.
Heavy Chaikin smoothing with pronounced jitter for bleeding edges.

eido.color

Color parsing, conversion, and manipulation. See also eido.color.palette for color harmonies & gradients.

(contrast color-a color-b)
WCAG 2.0 luminance contrast ratio between two colors.
Returns a double >= 1.0 (1 = identical, 21 = black/white).
Accepts any color form (vectors, keywords, maps).
(darken color amount)
Decreases lightness by amount (0-1). Accepts color vectors or maps.
(desaturate color amount)
Decreases saturation by amount (0-1). Accepts color vectors or maps.
Helper
(hsl h s l)
Shorthand for [:color/hsl h s l]. Wraps hue with mod 360.
(lerp color-a color-b t)
(lerp color-a color-b t opts)
Linearly interpolates between two colors. t in [0, 1].
Accepts color vectors or maps; returns a color vector.
Optional opts map: {:space :oklab} for perceptually uniform interpolation.
Helper
Wraps lerp
(lerp-oklab color-a color-b t)
Interpolates between two colors in OKLAB space. t in [0, 1].
Wraps (lerp color-a color-b t {:space :oklab}).
(lighten color amount)
Increases lightness by amount (0-1). Accepts color vectors or maps.
(mix-subtractive color-a color-b t)
Mixes two colors subtractively, simulating how real paint pigments blend.
Blue + yellow = green, red + blue = purple, etc.

color-a, color-b: [r g b] in linear RGB [0..1] float space.
t: mix ratio (0.0 = all color-a, 1.0 = all color-b).

Uses a reflectance multiplication model: pigments absorb light,
so mixing pigments multiplies their reflectance spectra. Approximated
by geometric mean: result_ch = a_ch^(1-t) * b_ch^t.

named-colors
CSS Color Level 4 named colors mapped to [r g b] values.
Helper
(oklab L a b)
Shorthand for [:color/oklab L a b].
Helper
(oklch L C h)
Shorthand for [:color/oklch L C h].
(perceptual-distance color-a color-b)
OKLAB deltaE — Euclidean distance in OKLAB perceptual color space.
Returns a double >= 0.0 (0 = identical colors).
More perceptually meaningful than RGB distance.
Accepts any color form (vectors, keywords, maps).
(resolve-color color)
Resolves a color value to a map with :r :g :b :a keys.
Accepts tagged vectors ([:color/rgb 255 0 0], [:color/name "red"])
or bare keywords (:red, :cornflowerblue) as shorthand for named colors.
Helper
(rgb r g b)
Shorthand for [:color/rgb r g b].
(rgb->hsl r g b)
Converts RGB (0-255 each) to [h s l] where h: 0-360, s: 0-1, l: 0-1.
(rgb->oklab r g b)
Converts sRGB (0-255 each) to OKLAB [L a b].
L: 0-1 (lightness), a: ~-0.4 to 0.4, b: ~-0.4 to 0.4.
(rgb->oklch r g b)
Converts sRGB (0-255 each) to OKLCH [L C h].
L: 0-1, C: 0-0.4+, h: 0-360 degrees.
(rotate-hue color degrees)
Shifts hue by degrees (can be negative). Accepts color vectors or maps.
(saturate color amount)
Increases saturation by amount (0-1). Accepts color vectors or maps.

eido.color.palette

Color harmony algorithms and palette generation. Provides complementary, analogous, triadic, and other schemes plus palette manipulation utilities.

Helper
(adjust palette opts)
Applies multiple palette adjustments in one call.
Wraps warmer/cooler/muted/vivid/darker/lighter.
opts keys: :warmer, :cooler, :muted, :vivid, :darker, :lighter.
(analogous c n)
Returns n colors spread evenly across a 60-degree arc centered on c.
(complementary c)
Returns the complementary color (180 degrees opposite).
(cooler palette amount)
Rotates all hues toward cool (negative degrees). Typical: 5-15.
(darker palette amount)
Darkens all colors by amount (0-1).
(from-image img k)
(from-image img k opts)
Extracts a palette of k dominant colors from an image using k-means
clustering in OKLAB perceptual color space. Returns a palette vector
sorted from dark to light.
img: BufferedImage or file path string.
opts: :samples (1000), :seed (0), :max-iter (20).
(gradient-map stops t)
(gradient-map stops t opts)
Interpolates through color stops at parameter t (0-1).
stops: [[pos color] ...] sorted ascending by pos.
Optional opts: {:easing fn} applies an easing function to t before lookup.
Returns a color vector.
(gradient-palette start end n)
Returns n colors evenly interpolated between start and end.
(lighter palette amount)
Lightens all colors by amount (0-1).
Helper
(min-contrast palette)
Returns the minimum pairwise WCAG contrast ratio in a palette.
Wraps (color/contrast) over all pairs. Useful for checking readability.
(monochromatic c n)
Returns n colors with the same hue, varying lightness from dark to light.
(muted palette amount)
Desaturates all colors by amount (0-1).
palettes
Named palettes as vectors of color vectors.
(shuffle-palette palette seed)
Returns a deterministically shuffled palette.
Helper
(sort-by-lightness palette)
Sorts a palette from dark to light using OKLAB perceptual lightness.
Wraps (sort-by (fn [c] (first (color/rgb->oklab ...))) palette).
(split-complementary c)
Returns the base color plus two colors flanking its complement (±30°).
(swatch palette)
(swatch palette opts)
Returns a BufferedImage showing color bars for a palette.
Useful with show at the REPL for quick visual feedback.
opts: :width (400), :height (60).
(tetradic c)
Returns 4 colors at 90-degree intervals (rectangle/square scheme).
(triadic c)
Returns 3 colors evenly spaced at 120-degree intervals.
(vivid palette amount)
Saturates all colors by amount (0-1).
(warmer palette amount)
Rotates all hues toward warm (positive degrees). Typical: 5-15.
(weighted-gradient palette weights)
Creates gradient stops where each color occupies proportional space.
Returns stops [[pos color] ...] suitable for gradient-map.
palette and weights must have the same length.
(weighted-pick palette weights seed)
Picks one color from palette biased by weights.
palette: vector of color vectors.
weights: vector of positive numbers (same length as palette).
seed: long for deterministic selection.
(weighted-sample palette weights n seed)
Samples n colors from palette with replacement, biased by weights.
Helper
(with-roles roles palette)
Attaches role names to a palette for readable access.
Wraps (zipmap roles palette).
Example: (with-roles [:bg :primary :accent] pal) => {:bg c1 :primary c2 :accent c3}

eido.gen.noise

Noise generators: Perlin, simplex, value noise, FBM, turbulence, and ridge. Building blocks for organic textures, flow fields, and terrain-like forms.

(fbm noise-fn x y)
(fbm noise-fn x y opts)
Fractal Brownian motion — layers of noise at increasing frequency.
noise-fn must accept (x y) or (x y opts) and return a double.
Options: :octaves (4), :lacunarity (2.0), :gain (0.5), :seed.
(perlin2d x y)
(perlin2d x y opts)
2D Perlin noise. Returns a double in [-1, 1].
Optionally accepts {:seed n} for a seeded permutation table.
(perlin3d x y z)
(perlin3d x y z opts)
3D Perlin noise. Returns a double in [-1, 1].
Useful for animating noise (use time as z).
Optionally accepts {:seed n}.
(perlin4d x y z w)
(perlin4d x y z w opts)
4D Perlin noise. Returns a double in [-1, 1].
Essential for seamlessly looping animated noise.
Looping trick: (perlin4d x y (* r (cos t)) (* r (sin t))).
Optionally accepts {:seed n}.
(preview noise-fn)
(preview noise-fn opts)
Renders a noise function as a grayscale BufferedImage.
noise-fn: (fn [x y] -> double), expected range [-1, 1].
Useful with show at the REPL for tuning noise parameters.
opts: :width (256), :height (256), :scale (0.02).
(ridge noise-fn x y)
(ridge noise-fn x y opts)
Ridged multifractal noise — inverts absolute value for sharp ridges.
Same options as fbm, plus :offset (1.0).
(simplex2d x y)
(simplex2d x y opts)
2D OpenSimplex2S noise. Returns a double in [-1, 1].
Fewer directional artifacts than Perlin noise.
Optionally accepts {:seed n}.
(simplex3d x y z)
(simplex3d x y z opts)
3D OpenSimplex2S noise. Returns a double in [-1, 1].
Optionally accepts {:seed n}.
(simplex4d x y z w)
(simplex4d x y z w opts)
4D OpenSimplex2S noise. Returns a double in [-1, 1].
Essential for seamlessly looping animated noise.
Looping trick: (simplex4d x y (* r (cos t)) (* r (sin t))).
Optionally accepts {:seed n}.
(turbulence noise-fn x y)
(turbulence noise-fn x y opts)
Turbulence — fbm using absolute values of noise.
Returns non-negative values. Same options as fbm.

eido.gen.flow

Flow field path generation from noise-based vector fields. Traces streamlines with optional collision avoidance for even spacing.

(flow-field bounds opts)
Generates path nodes from a noise-based flow field within bounds.
bounds: [x y w h] region.
Returns a vector of :shape/path nodes (streamlines).
opts: :density (20), :step-length (2.0), :steps (50),
:noise-scale (0.005), :seed (0), :min-length (3),
:collision-distance (nil — set to enforce minimum spacing between streamlines).

eido.gen.contour

Marching squares contour extraction from scalar fields. Produces connected iso-lines at specified thresholds for topographic effects.

(contour-lines noise-fn bounds opts)
Generates contour paths at iso-thresholds of a scalar field.
noise-fn: (fn [x y opts] -> double). bounds: [x y w h].
Returns a vector of :shape/path nodes.
opts: :thresholds ([0.0]), :resolution (5), :noise-scale (0.01), :seed (0).

eido.gen.scatter

Point distribution algorithms: regular grids, Poisson disk sampling, and noise-biased placement. Includes jitter and node expansion.

(grid bounds cols rows)
Generates a regular grid of [x y] positions within bounds.
bounds: [x y w h].
(jitter points opts)
Displaces each point by a Gaussian offset scaled by amount.
Returns [[x' y'] ...]. opts: :amount (required), :seed (default 0).
Amount controls displacement magnitude: 0 = no change, higher = more
disorder. Uses Gaussian for natural feel.
(noise-field bounds opts)
Generates up to n positions biased by noise density.
bounds: [x y w h]. opts: :n (required), :seed (default 0).
Points are placed where noise value exceeds a threshold.
(poisson-disk bounds opts)
Generates well-distributed points via Poisson disk sampling.
bounds: [x y w h]. opts: :min-dist (required), :seed (default 0).
Delegates to eido.gen.stipple/poisson-disk.
(scatter->nodes shape positions jitter)
Creates positioned group nodes from a shape and positions.
jitter: nil or {:x dx :y dy :seed s} for random displacement.

eido.gen.voronoi

Voronoi diagram and Delaunay triangulation from seed points. Produces cell polygons and dual-graph edges for territorial partitions.

(delaunay-edges points bounds)
Generates Delaunay triangulation edges as line nodes.
bounds: [x y w h] clipping region.
Derived from Voronoi: two seeds are neighbors if their cells share an edge.
(voronoi-cells points bounds)
Generates Voronoi cell polygons from seed points.
bounds: [x y w h] clipping region.
Returns a vector of :shape/path nodes (closed polygons), one per point.
Uses half-plane intersection: O(n^2) per cell.

eido.gen.lsystem

Lindenmayer systems: string rewriting and turtle-graphics interpretation. Generates branching, fractal, and botanical structures from simple rules. Rules can be plain strings (classic L-system) or vectors of alternatives (constrained L-system). When alternatives are provided with :bounds, the system searches for rule choices that keep growth within the canvas. Symbols: F=draw, G=move, +=turn right, -=turn left, [=push, ]=pop, |=reverse.

bush
Bushy plant with symmetric branching.
coral
Dense branching coral structure.
(expand-string axiom rules iterations)
Rewrites axiom by applying rules for n iterations.
Characters not in rules pass through unchanged.
Rules can be strings (classic) or vectors of strings (uses first alternative).
fern
Asymmetric fern with curving fronds.
(interpret expanded opts)
Interprets an L-system string via turtle graphics.
Returns scene-format path commands.
opts: :angle (degrees), :length, :origin [x y], :heading (degrees).
lightning
Jagged branching lightning bolt.
(lsystem->path-cmds axiom rules opts)
Full pipeline: expand axiom with rules, then interpret via turtle.
Returns path commands.

opts:
:iterations — number of expansion steps (default 3)
:angle — turn angle in degrees
:length — step length
:origin — [x y] start position (default [0 0])
:heading — initial direction in degrees (default 0)

When rules contain vector alternatives (e.g. {"F" ["FF+F" "F" ""]}):
:bounds [x y w h] — canvas constraint; growth stays within.
Result is scaled to fill the bounds.
:seed (42) — controls which rule choices are made when
the full expansion overflows bounds.
seaweed
Swaying organic tendrils.
tree
Classic branching tree with taper.

eido.gen.particle

Particle systems with emitters, forces, and over-lifetime curves. Supports 2D and 3D simulation with built-in presets for fire, snow, and more.

Provisional
confetti
Confetti burst: colorful rectangles falling with gravity.
Note: uses per-particle random colors from :particle/colors palette.
Provisional
fire
Fire effect: upward flames with orange-to-red color shift.
Provisional
fountain
Fountain: upward spray arcing back down under gravity.
Provisional
(render-frame state config)
(render-frame state config opts)
Renders a simulation state to a vector of Eido node maps.
Optionally override the projection for this frame (useful for orbiting cameras).

state: a simulation state from states
config: the particle system configuration map
opts: optional {:projection proj} to override :particle/projection for this frame
Provisional
(simulate config n opts)
Runs a particle simulation and returns a lazy seq of node-vectors.
Each element is a vector of Eido node maps ready for :image/nodes.

config: particle system configuration map
n: number of frames to produce
opts: {:fps 30} — frames per second (determines time step)

Returns a lazy seq of n vectors. Use vec to realize for indexed access.
Provisional
smoke
Smoke: slow-rising, expanding, fading gray clouds.
Provisional
snow
Snowfall: gentle drift downward from a line emitter.
Provisional
sparks
Sparks burst: bright, fast, short-lived points.
Provisional
(states config n opts)
Runs a particle simulation and returns a lazy seq of raw simulation states.
Each state contains :particles (internal particle maps with :pos, :vel, :age, etc.).

Use this when you need per-frame control over rendering, e.g. orbiting cameras
for 3D particles. Pair with render-frame to convert states to nodes.

config: particle system configuration map
n: number of frames to produce
opts: {:fps 30} — frames per second (determines time step)

Returns a lazy seq of n state maps.
Provisional
(with-position config pos)
Returns config with the emitter repositioned.
Provisional
(with-seed config seed)
Returns config with a different seed.

eido.gen.stipple

Poisson disk sampling and stipple fills. Generates well-distributed dot patterns for shading and texture.

(poisson-disk bounds opts)
Generates well-distributed points via Poisson disk sampling.
bounds: [x y w h] region. opts: :min-dist (required), :seed (default 0).
Returns a vector of [x y] within the bounds.
(stipple-fill->nodes bounds spec)
Generates circle nodes for a stipple fill within bounds.
bounds: [x y w h] region.
spec: :stipple/density (0-1), :stipple/radius, :stipple/seed,
:stipple/color.

eido.gen.hatch

Cross-hatch line patterns for pen-plotter-style fills. Generates parallel lines at arbitrary angles with multi-layer support.

(hatch-fill->nodes bounds spec)
Converts a hatch fill spec to scene path nodes (lines).
bounds: [x y w h]. Each line becomes a path node with the specified stroke.
Spec keys: :hatch/angle, :hatch/spacing, :hatch/stroke-width,
:hatch/color, :hatch/layers [{:angle :spacing} ...].
(hatch-lines bounds {:keys [angle spacing], :or {angle 45, spacing 5}})
Generates hatch line segments [x1 y1 x2 y2] within a bounding box.
bounds: [x y w h]. opts: :angle (45), :spacing (5).

eido.gen.vary

Per-item style variation: color, opacity, and transform overrides driven by index, position, noise, or gradient interpolation.

(apply-overrides children overrides)
Merges overrides onto a vector of child group nodes.
Each override map is merged onto the first child of the group at index i.
Wraps via mod when overrides is shorter than children.
(by-gradient n stops)
Generates n fill overrides interpolated through gradient stops.
stops: [[pos color] ...] for palette/gradient-map.
(by-index n f)
Generates n overrides by calling (f i) for each index 0..n-1.
f should return a map of node attribute overrides.
(by-noise positions f opts)
Generates overrides from Perlin noise sampled at each position.
Calls (f noise-value) where noise-value is in [-1, 1].
opts: :noise-scale (required), :seed (default 0).
Helper
Wraps by-noise
(by-noise-palette positions palette opts)
Generates fill overrides by mapping noise to palette colors.
opts: :noise-scale (required), :seed (default 0).
Wraps (by-noise positions f opts).
Helper
Wraps by-index
(by-palette n palette)
(by-palette n palette opts)
Generates n fill overrides from a palette with optional weights.
opts: :seed (default 0), :weights (optional weight vector).
Wraps (by-index n (fn [i] {:style/fill ...})).
(by-position positions f)
Generates overrides by calling (f x y) for each [x y] position.
f should return a map of node attribute overrides.

eido.gen.prob

Seeded probability distributions and sampling utilities. All functions take an explicit seed (long) for deterministic, reproducible results. No global RNG state is used.

(coin p seed)
Returns true with probability p (0.0 to 1.0).
(gaussian n mean sd seed)
Returns a vector of n Gaussian-distributed doubles with given mean and sd.
(in-circle radius seed)
(in-circle radius [cx cy] seed)
Returns a point [x y] uniformly distributed inside a disc.
Uses the sqrt trick for uniform area distribution.
(in-sphere radius seed)
(in-sphere radius [cx cy cz] seed)
Returns a point [x y z] uniformly distributed inside a sphere volume.
Uses the Gaussian method + cbrt trick for uniform volume distribution.
(make-rng seed)
Creates a java.util.Random from a seed.
Helper
(mixture sources mix-weights n seed)
Samples n values from a mix of source vectors, weighted by mix-weights.
Wraps weighted-choice to select which source to draw from.
Example: (mixture [(uniform 100 1 5 s1) (gaussian 100 20 3 s2)] [3 1] 50 seed)
(on-circle radius seed)
(on-circle radius [cx cy] seed)
Returns a point [x y] on the circumference of a circle.
Uniformly distributed angle.
(on-sphere radius seed)
(on-sphere radius [cx cy cz] seed)
Returns a point [x y z] uniformly distributed on a sphere surface.
Uses the Gaussian method to avoid polar clustering.
Helper
(pareto n alpha min-val seed)
Returns a vector of n Pareto-distributed doubles.
Wraps (sample-n {:type :pareto ...}).
(pick coll seed)
Picks one element from coll uniformly at random.
Returns nil if coll is empty.
(pick-weighted items weights seed)
Picks one element from items using corresponding weights.
Returns nil if items is empty.
(sample spec seed)
Samples a single value from a distribution spec.
Spec is a plain map with :type and type-specific keys:
{:type :uniform :lo 0.0 :hi 1.0}
{:type :gaussian :mean 0.0 :sd 1.0}
{:type :choice :options [:a :b :c]}
{:type :weighted-choice :options [:a :b] :weights [3 1]}
{:type :boolean :probability 0.5}
{:type :pareto :alpha 2.0 :min 1.0} ;; optional :max
{:type :triangular :min 0 :max 1 :mode 0.5}
{:type :eased :easing fn :lo 0 :hi 1}
Same spec format used by eido.gen.series/series-params.
(sample-n spec n seed)
Samples n values from a distribution spec.
Each value gets a deterministic sub-seed derived from the base seed
and its index, ensuring independent samples.
Helper
Wraps in-circle
(scatter-in-circle n radius center seed)
Returns a vector of n points uniformly distributed inside a disc.
Wraps repeated in-circle calls with independent sub-seeds.
Helper
Wraps on-circle
(scatter-on-circle n radius center seed)
Returns a vector of n points on a circle.
Wraps repeated on-circle calls with independent sub-seeds.
(shuffle-seeded coll seed)
Returns a deterministically shuffled vector of coll (Fisher-Yates).
Helper
(triangular n min-val max-val mode seed)
Returns a vector of n triangular-distributed doubles in [min-val, max-val].
Wraps (sample-n {:type :triangular ...}).
(uniform n lo hi seed)
Returns a vector of n uniform doubles in [lo, hi).
(weighted-choice weights seed)
Returns a single index chosen from weights (vector of positive numbers).
(weighted-sample n weights seed)
Returns a vector of n indices sampled from weights (with replacement).

eido.gen.circle

Circle packing: variable-radius non-overlapping circle placement. Uses greedy rejection sampling with spatial grid acceleration.

(circle-pack bounds opts)
Packs circles within a rectangular region.
Returns a vector of {:center [x y] :radius r} maps.
opts:
:min-radius (2.0) — smallest circle
:max-radius (40.0) — largest circle
:padding (1.0) — gap between circles
:attempts (500) — max failed attempts before stopping
:max-circles (1000) — cap on total circles
:seed (42)
:bounds-fn — optional (fn [x y] -> boolean) for non-rectangular containment
(circle-pack-in-path path-commands opts)
Packs circles within an arbitrary closed path.
Uses java.awt.geom.Area for containment testing.
Helper
Wraps pack->nodes
(pack->colored-nodes circles palette)
(pack->colored-nodes circles palette opts)
Circle pack to styled nodes with palette colors.
opts: :seed (default 0), :weights (optional), :style (optional base style map).
Wraps (pack->nodes circles) + (palette/weighted-sample palette).
(pack->nodes circles opts)
Converts circle-pack output to scene nodes.
opts: :style (base style map applied to each circle)

eido.gen.subdivide

Recursive rectangular subdivision for compositional layouts. Produces Mondrian-style grids and binary space partitions.

(subdivide bounds opts)
Recursively subdivides a rectangle into smaller rectangles.
Returns a vector of {:rect [x y w h] :depth n} maps.
opts:
:depth (4) — max recursion depth
:min-size (20.0) — stop splitting below this dimension
:split-range [0.3 0.7] — random split ratio range
:h-bias (0.5) — probability of horizontal split (vs vertical)
:padding (0.0) — gap between sub-rects
:seed (42)
(subdivide->nodes rects color-fn)
Converts subdivision output to rect scene nodes.
color-fn: (fn [{:rect [x y w h] :depth n}] -> color).
Helper
Wraps subdivide->nodes
(subdivide->palette-nodes rects palette)
(subdivide->palette-nodes rects palette opts)
Subdivision rects to styled nodes with palette colors.
opts: :seed (default 0), :style (optional base style map).
Wraps (subdivide->nodes rects (fn [...] (prob/pick palette seed))).

eido.gen.series

Long-form generative series utilities. Deterministic seed derivation and parameter sampling for numbered editions (Art Blocks / fxhash style workflows).

Helper
Wraps series-params
(derive-traits params buckets)
Categorizes continuous parameter values into named labels.
Wraps a simple threshold lookup over a params map.
buckets: {:param [[threshold label] ...]}
Example: (derive-traits {:density 42} {:density [[20 "sparse"] [40 "medium"] [100 "dense"]]})
(edition-seed master-seed edition-number)
Derives a deterministic, uncorrelated seed for an edition number
from a master seed. Uses murmur3-style mixing so nearby editions
produce independent seeds.
(export-edition-package {:keys [spec master-seed start end scene-fn output-dir format render-opts traits contact-sheet? contact-cols thumb-size], :or {contact-sheet? true, contact-cols 5, thumb-size [160 160]}})
Renders a complete edition package: images, manifests, and optional contact sheet.
opts: same as render-editions, plus:
:contact-sheet? — generate a grid thumbnail image (default true)
:contact-cols — columns in contact sheet (default 5)
:thumb-size — per-thumbnail size (default [160 160])
Returns {:editions [...] :contact-sheet path-or-nil}.
(load-seeds path)
Reads all seed bookmarks from an EDN log file.
Returns a vector of maps in append order, or [] if the file does not exist.
(param-grid {:keys [base-params row-param col-param seed scene-fn thumb-size]})
Renders a parameter sweep as a single BufferedImage for REPL exploration.
Varies one param across rows, optionally another across columns.
Pass the result to show at the REPL.
opts:
:base-params — base parameter map
:row-param — {:key :param-name :values [v1 v2 ...]}
:col-param — {:key :param-name :values [v1 v2 ...]} (optional, default 1 col)
:seed — seed for scene generation
:scene-fn — (fn [params] scene-map) — takes merged params, returns scene
:thumb-size — [width height] per thumbnail (default [160 160])
(render-editions {:keys [spec master-seed start end scene-fn output-dir format render-opts traits emit-manifest?]})
Renders a batch of editions from a series spec.
opts:
:spec — parameter spec map (as for series-params)
:master-seed — master seed for the series
:start — first edition number (inclusive)
:end — last edition number (exclusive)
:scene-fn — (fn [params edition-number] scene-map)
:output-dir — directory to write files into
:format:png (default) or :svg
:render-opts — optional map passed to eido.core/render (e.g. {:scale 2})
:traits — optional trait buckets for derive-traits
:emit-manifest? — write per-edition .edn sidecar manifests (default false)
Returns a vector of {:edition n :params params :traits traits :file path}.
(save-seed! path entry)
Appends a seed bookmark to an EDN log file.
entry should contain at least :seed; :params and :note are optional.
Adds :timestamp automatically. Accumulates one EDN form per line.
(seed-grid {:keys [spec master-seed start end seeds scene-fn cols thumb-size]})
Renders a grid of editions as a single BufferedImage for REPL exploration.
Each cell shows a different seed; pass the result to show at the REPL.
opts:
:spec — parameter spec map
:master-seed — master seed for the series
:start — first edition number (inclusive, default 0)
:end — last edition number (exclusive)
:seeds — explicit list of edition numbers (overrides start/end)
:scene-fn — (fn [params edition-number] scene-map)
:cols — number of columns (default 5)
:thumb-size — [width height] per thumbnail (default [160 160])
(series-params spec master-seed edition-number)
Generates a parameter map for one edition in a series.
spec: map of {:param-name {:type :uniform/:gaussian/:choice/:weighted-choice/:boolean, ...}}
Each parameter gets a deterministic sub-seed derived from the edition seed
and a hash of the parameter name.
(series-range spec master-seed start end)
Returns a vector of parameter maps for editions start (inclusive) to end (exclusive).
(trait-summary spec master-seed n-editions trait-buckets)
Computes trait frequencies across n editions of a series.
Returns {:trait-name {"label" count ...} ...} — pure data for REPL inspection.
Useful for verifying that rare traits are actually rare before releasing.

eido.gen.ca

Cellular automata and Gray-Scott reaction-diffusion simulation. Grid-based evolution systems for organic pattern generation.

(ca->nodes {:keys [grid w h]} cell-size alive-style)
Renders a CA grid as scene nodes. Only alive cells produce nodes.
alive-style: style map for alive cells (e.g., {:style/fill color}).
cell-size: pixel size per cell.
(ca-grid w h init seed)
Creates an initial CA grid.
init: :random (seeded), :empty, or :center (single live cell).
Returns {:grid boolean-array :w w :h h}.
(ca-run grid-map rule n)
Runs CA for n steps. Returns the final grid.
(ca-step {:keys [grid w h]} rule)
Advances a CA grid by one generation.
rule: :life, :highlife, or {:birth #{...} :survive #{...}}.
(rd->nodes {:keys [a b w h]} cell-size color-fn)
Renders an RD state as scene nodes. One rect per cell.
color-fn: (fn [a-val b-val] -> color-vector).
(rd-grid w h init seed)
Creates initial reaction-diffusion concentration grids.
init: :center (circle of B in center), :random (scattered seeds).
Returns {:a double-array :b double-array :w w :h h}.
rd-presets
Named parameter sets for Gray-Scott reaction-diffusion.
All produce visible patterns within 500-2000 steps on 100x100+ grids.
(rd-run rd-map params n)
Runs reaction-diffusion for n steps. Returns the final grid.
(rd-step {:keys [a b w h]} params)
Advances reaction-diffusion by one time step.
params: {:feed f :kill k :da da :db db :dt dt}.

eido.gen.boids

Boids flocking simulation with steering behaviors. Separation, alignment, cohesion, plus optional seek/flee/wander. Uses spatial grid for efficient neighbor lookup.

(alignment boid neighbors radius strength)
Computes steering force toward average heading of neighbors.
classic
Classic boids — balanced separation/alignment/cohesion.
(cohesion boid neighbors radius strength)
Computes steering force toward centroid of neighbors.
(flee boid target flee-radius strength)
Computes steering force away from a point within flee-radius.
(flock->nodes {:keys [boids]} opts)
Renders a flock state as scene nodes.
opts: :shape (:triangle or :circle), :size (6), :style (style map).
(init-flock opts)
Creates initial flock state.
opts: :count (50), :bounds [bx by bw bh], :max-speed (2.0), :seed (42).
Returns {:boids [...] :tick 0}.
murmuration
Starling murmuration — tight cohesion, wide alignment.
(seek boid target max-speed strength)
Computes steering force toward a target point.
(separation boid neighbors radius strength)
Computes steering force away from nearby boids.
(simulate-flock config n opts)
Returns a vector of n flock states.
(step-flock {:keys [boids tick]} config)
Advances flock by one tick. config contains behavior parameters.

eido.gen.coloring

Graph coloring via constraint satisfaction. Assigns colors to regions (Voronoi cells, subdivision rects, or any indexed set with adjacency) such that no two adjacent regions share a color. Uses core.logic CLP(FD) for the constraint solver. Primary function: `color-regions` — takes scene nodes, adjacency, and a palette, returns nodes with :style/fill applied. The solver guarantees no two adjacent regions share a color. Creative control: :seed — different seeds produce different valid colorings :pin — fix specific regions to specific colors; the solver completes the rest consistently

(cells-adjacency cells)
Computes adjacency from path-based regions (Voronoi cells, polygons).
Two regions are adjacent if they share 2+ vertices (within epsilon).
Returns a set of [i j] pairs (i < j).
(color-regions nodes adjacency palette)
(color-regions nodes adjacency palette opts)
Applies graph coloring to scene nodes.
nodes: vector of scene nodes
adjacency: collection of [i j] pairs
palette: vector of colors
opts:
:seed (0) — shuffles palette assignment for variety
:pin {idx color} — fix specific regions to specific colors;
the solver completes the rest consistently
Returns nodes with :style/fill applied, or nil if no valid coloring exists.
(rects-adjacency rects)
Computes adjacency from subdivision rects.
Two rects are adjacent if they share an edge.
rects: vector of {:rect [x y w h]} maps.
Returns a set of [i j] pairs (i < j).

eido.texture

Texture and material helpers for organic rendering effects. These helpers produce scene nodes (groups with deformed, layered copies) for simulating translucent media like watercolor, ink wash, and gouache.

Provisional
(layered shape-node opts)
Returns a group node with n deformed copies of shape at low opacity.
Simulates watercolor, ink wash, and other translucent media.
opts: :layers (required), :opacity (required), :deform-fn (required),
:seed (default 0).
deform-fn: (fn [shape-node layer-index seed] -> shape-node).
Each layer gets a unique sub-seed derived from the base seed.
Provisional
(watercolor path-node opts)
Convenience: layered rendering with jitter deformation.
Returns a group node simulating watercolor wash.
opts: :layers (30), :opacity (0.04), :amount (3.0), :seed (0).

eido.paint

Procedural paint engine for Eido. Provides declarative brush specifications, stroke constructors, and paint surface configuration. Integrates with the standard Eido rendering pipeline — paint surfaces appear as scene nodes alongside shapes, groups, and generators. Three entry points: 1. Standalone paint surface — {:node/type :paint/surface ...} 2. Paint parameters on paths — {:paint/brush :chalk ...} on any path 3. Group modifier — {:paint/surface {...}} on a group for shared surfaces

Provisional
(auto-pressure points)
(auto-pressure points opts)
Derives a pressure curve from path geometry.
points: [[x y] ...] — point sequence.
opts: {:mode :taper (default), :start 0.3, :end 0.2}
Returns [[t pressure] ...] suitable for :paint/pressure.
Provisional
(brush spec)
(brush preset overrides)
Returns a brush spec, optionally merging overrides onto a preset.
(brush :chalk)
(brush :chalk {:brush/paint {:paint/opacity 0.2}})
(brush {:brush/type :brush/dab ...})
Provisional
(circle-points center)
(circle-points center opts)
Generates stroke points around a circle or arc.
center: [cx cy].
opts: {:radius 50, :n 20, :start 0.0, :end (* 2 PI), :pressure 0.8}
Returns [[x y pressure 0 0 0] ...] suitable for :paint/points.
Provisional
(compose surface)
Composites a painted surface to a BufferedImage.
Provisional
(fill-ellipse center)
(fill-ellipse center opts)
Generates stroke descriptors to fill an elliptical area with paint.
center: [cx cy].
opts: {:rx 50, :ry 30, :brush :oil, :color [...], :radius 8.0,
:density 12, :seed 0}
Returns a vector of stroke descriptors for :paint/strokes.
Provisional
(fill-rect bounds)
(fill-rect bounds opts)
Generates stroke descriptors to fill a rectangular area with paint.
bounds: [x y w h].
opts: {:brush :chalk, :color [...], :radius 8.0, :density 15, :seed 0}
Returns a vector of stroke descriptors for :paint/strokes.
Provisional
(line-points from)
(line-points from opts)
Generates stroke points along a straight line.
from: [x0 y0].
opts: {:to [x1 y1], :n 15, :pressure 0.8}
Returns [[x y pressure 0 0 0] ...].
Provisional
(make-surface config)
Creates a paint surface from a surface config or size vector.
Accepts [w h], {:paint/size [w h]}, or {:size [w h]}.
Provisional
(paint-group children)
(paint-group children opts)
Creates a group with a shared paint surface.
children: painted path nodes or generators with paint params.
opts: {:substrate {:substrate/tooth 0.4}}
Provisional
(paint-surface strokes)
(paint-surface strokes opts)
Creates a paint surface node.
strokes: vector of stroke descriptors.
opts: {:size [w h], :substrate {:substrate/tooth 0.4}, :children [nodes]}
Provisional
(painted-path points opts)
Creates a path node with paint parameters.
points: [[x y] ...] — auto-smoothed via Catmull-Rom, or path commands.
opts: {:brush :ink, :color [...], :radius 8.0, :pressure [[t p] ...], :opacity 0.5}
Provisional
presets
Named brush presets. Each is a brush spec map.
Provisional
(render-stroke! surface stroke-desc)
(render-stroke! surface stroke-desc substrate-spec)
Renders a single stroke onto a surface.
stroke-desc: {:stroke/brush :stroke/color :stroke/points :stroke/seed}
or path-based: {:paint/brush :paint/color :path/commands :paint/pressure}
Returns nil (mutates surface).
substrate-spec: optional substrate from the surface config.
Provisional
(render-strokes! surface strokes)
(render-strokes! surface strokes substrate-spec)
Renders all strokes onto a surface. Returns the surface.
Provisional
(resolve-brush brush)
Resolves a brush reference to a full brush spec.
Accepts a keyword (preset name), a spec map, or nil (returns default).
Provisional
(stroke points opts)
Creates a stroke descriptor for use in :paint/strokes.
points: [[x y pressure speed tilt-x tilt-y] ...]
opts: {:brush :chalk, :color [...], :radius 12.0, :seed 42}
Provisional
(stroke-from-path path-commands opts)
Creates a stroke descriptor from path commands with auto-derived
pressure. Convenience for composing paths with paint.
path-commands: [[:move-to [x y]] [:line-to [x y]] ...]
opts: {:brush :chalk, :color [...], :radius 12.0,
:pressure :taper (or :curvature, or explicit curve), :seed 42}
Provisional
(wave-points from)
(wave-points from opts)
Generates stroke points along a wavy line.
from: [x0 y0].
opts: {:to [x1 y1], :amplitude 15, :frequency 0.15, :n 20, :pressure 0.7}
Returns [[x y pressure 0 0 0] ...].

eido.animate

Easing, interpolation, and timing functions for animation. Easing functions take a normalized t in [0,1] and return a shaped t. Compose with `lerp` for value interpolation, or use `frames`, `stagger`, and `cycle-n` for sequencing multi-frame animations.

(cycle-n n t)
Returns progress for n full cycles within [0, 1].
E.g., (cycle-n 2 0.5) completes one full cycle by midpoint.
(ease-in t)
Quadratic ease in: slow start, fast end. t in [0, 1].
(ease-in-back t)
Back ease in (overshoots then returns). t in [0, 1].
(ease-in-bounce t)
Bounce ease in. t in [0, 1].
(ease-in-circ t)
Circular ease in. t in [0, 1].
(ease-in-cubic t)
Cubic ease in. t in [0, 1].
(ease-in-elastic t)
Elastic ease in. t in [0, 1].
(ease-in-expo t)
Exponential ease in. t in [0, 1].
(ease-in-out t)
Quadratic ease in-out: slow start and end. t in [0, 1].
(ease-in-out-back t)
Back ease in-out. t in [0, 1].
(ease-in-out-bounce t)
Bounce ease in-out. t in [0, 1].
(ease-in-out-circ t)
Circular ease in-out. t in [0, 1].
(ease-in-out-cubic t)
Cubic ease in-out. t in [0, 1].
(ease-in-out-elastic t)
Elastic ease in-out. t in [0, 1].
(ease-in-out-expo t)
Exponential ease in-out. t in [0, 1].
(ease-in-out-quart t)
Quartic ease in-out. t in [0, 1].
(ease-in-quart t)
Quartic ease in. t in [0, 1].
(ease-out t)
Quadratic ease out: fast start, slow end. t in [0, 1].
(ease-out-back t)
Back ease out (overshoots then settles). t in [0, 1].
(ease-out-bounce t)
Bounce ease out. t in [0, 1].
(ease-out-circ t)
Circular ease out. t in [0, 1].
(ease-out-cubic t)
Cubic ease out. t in [0, 1].
(ease-out-elastic t)
Elastic ease out. t in [0, 1].
(ease-out-expo t)
Exponential ease out. t in [0, 1].
(ease-out-quart t)
Quartic ease out. t in [0, 1].
Helper
(fade-in t)
Quadratic fade-in. Wraps (* t t) clamped to [0, 1].
Helper
(fade-linear t)
Linear fade: 1.0 at t=0, 0.0 at t=1. Wraps (- 1.0 t).
Helper
Wraps fade-linear
(fade-out t)
Quadratic fade-out (softer tail). Wraps (* (fade-linear t) (fade-linear t)).
(frames n f)
Builds a vector of n frames by calling (f t) for each frame,
where t is normalized progress [0.0, 1.0].
(lerp a b t)
Linearly interpolates between a and b. t in [0, 1].
(ping-pong t)
Converts linear progress to a value that goes 0 -> 1 -> 0.
t in [0, 1], returns [0, 1].
(progress frame total)
Returns normalized progress [0.0, 1.0] for frame within total frames.
Frame 0 returns 0.0, last frame returns 1.0.
Helper
(pulse t)
(pulse t frequency)
Sine oscillation: returns a value in [0, 1] that pulses over time.
Wraps (/ (+ 1 (sin (* t 2 PI frequency))) 2).
(stagger i n t overlap)
Returns per-element progress for staggered animations.
i: element index (0-based), n: total elements, t: global progress [0, 1],
overlap: how much elements overlap (0 = sequential, 1 = all simultaneous).
Returns local progress for element i, clamped to [0, 1].

eido.scene3d

3D scene construction: mesh generation, transforms, and projection to 2D. This namespace re-exports all public vars from: eido.scene3d.camera — projections & camera positioning eido.scene3d.mesh — mesh constructors (primitives, platonics, parametric) eido.scene3d.transform — translate, rotate, scale, deform, mirror eido.scene3d.topology — subdivision, auto-smooth, adjacency, normals eido.scene3d.surface — UV projection, coloring, painting, material maps eido.scene3d.modeling — extrude/inset/bevel faces, L-system, instancing eido.scene3d.render — shading, render-mesh, depth-sort, convenience, text eido.scene3d.util — make-face, mesh-bounds, mesh-center, merge-meshes, palette-color, lerp-color Users can require this namespace for the full API, or require sub-namespaces directly for finer-grained imports.

(auto-smooth-edges mesh opts)
Returns a set of hard edge keys where adjacent faces meet at more than
the given angle. Use with subdivide's :hard-edges option.
opts:
:angle - threshold angle in radians (edges sharper than this are hard)
(axis-component axis [x y z])
Extracts the component of a 3D vector along the given axis (:x, :y, or :z).
(axis-range axis mesh)
Returns [min max] of the given axis across all vertices in a mesh.
(bevel-faces mesh opts)
Insets selected faces then extrudes the inner faces, creating a beveled edge.
Composes inset-faces and extrude-faces in one step.
opts:
:select/* - face selector (defaults to :all)
:bevel/inset - how far to shrink inward (0-1)
:bevel/depth - extrusion distance (positive = outward, negative = inward)
(build-face-adjacency mesh)
Builds adjacency maps from a mesh.
Returns {:edge-faces {edge-key → [face-index ...]}
:vert-faces {vertex → [face-index ...]}
:face-data [{:vertices [...] :style ... :normal ... :point ...} ...]}
(color-mesh mesh opts)
Colors each face based on a descriptor.
When :select/type is present, only selected faces are colored; others pass through.
opts:
:color/type - :field, :axis-gradient, or :normal-map
:color/palette - vector of [:color/rgb r g b] colors
:color/field - field descriptor (for :field type)
:color/axis - :x, :y, or :z (for :axis-gradient type)
:select/* - optional face selector (defaults to all faces)
(compute-vertex-normals face-data vert-faces)
Computes smooth vertex normals by averaging adjacent face normals.
Returns {vertex → normalized-average-normal}.
(cone projection position opts)
Creates a 3D cone projected into 2D.
opts: :radius, :height, :segments, :style, :light, :cull-back.
(cone-mesh radius height)
(cone-mesh radius height opts)
Returns a mesh approximating a cone at the origin.
Base circle in the XZ plane at y=0, apex at [0 height 0].
Opts: :segments (default 16) — number of sides.
(cube projection position opts)
Creates a 3D cube projected into 2D, returned as a :group node.
opts: :size (1), :style, :light, :cull-back.
(cube-mesh)
(cube-mesh position size)
Returns a mesh of 6 quad faces for a unit cube at the origin,
or a cube at position [x y z] with given size.
(cylinder projection position opts)
Creates a 3D cylinder projected into 2D.
opts: :radius, :height, :segments, :style, :light, :cull-back.
(cylinder-mesh radius height)
(cylinder-mesh radius height opts)
Returns a mesh approximating a cylinder centered at the origin.
Opts: :segments (default 16) — number of sides for the circular cross-section.
(deform-mesh mesh descriptor)
Applies a deformation to a mesh, returning a new mesh.
descriptor: map with :deform/type and type-specific options.
Types: :twist, :taper, :bend, :inflate, :crumple, :displace.
(depth-sort & node-colls)
Sorts a mixed collection of nodes by :node/depth for correct 3D occlusion.
Accepts any number of node collections — vectors of nodes, individual group
nodes (from render-mesh), or single nodes.

Groups are flattened into their children before sorting. All nodes are
sorted smallest-depth-first (farthest from camera drawn first — painter's
algorithm). Nodes without :node/depth are placed at the back.

Returns a vector of sorted nodes ready for :image/nodes.
(detail-faces mesh opts)
Adds procedural surface detail by insetting then noise-extruding faces.
Creates mechanical/sci-fi panel detail. Composes inset + field-driven extrude.
opts:
:select/* - face selector (defaults to :all)
:detail/field - noise field for per-face extrusion depth
:detail/inset - inset amount (default 0.1)
:detail/depth-range - [min-depth max-depth] range for extrusion
(edge-key a b)
Returns a canonical key for an edge between two 3D points.
Sorts the endpoints so edge [a b] and [b a] produce the same key.
(extrude-faces mesh opts)
Extrudes selected faces along their normals.
opts:
:select/* - face selector (see make-face-selector)
:extrude/amount - distance to push faces
:extrude/scale - optional scale factor toward centroid (default 1.0)
(extrude-mesh path-points direction)
Extrudes a 2D polygon along a 3D vector.
path-points: seq of [x y] (treated as [x, 0, y] in 3D space).
direction: [dx dy dz] extrusion vector.
(fov->distance fov half-width)
Converts a horizontal field-of-view angle (radians) to a perspective
:distance value. half-width is half the viewport width in world-space
units (typically screen-half-width / scale).
(heightfield-mesh {:keys [field bounds grid height]})
Creates a mesh from a 2D field sampled on a grid.
opts:
:field - field descriptor (noise, constant, distance)
:bounds - [x z width depth] defining the sampling area
:grid - [cols rows] number of sample points
:height - maximum Y displacement
(inset-faces mesh opts)
Insets selected faces, creating a smaller inner face and border quads.
opts:
:select/* - face selector
:inset/amount - how far to shrink inward (0-1 fraction of distance to centroid)
(instance-mesh mesh opts)
Places copies of a mesh at multiple positions.
Bridges 2D scatter distributions to 3D mesh placement.
opts:
:positions - vector of [x y z] positions
:jitter - {:amount n :seed s} random positional jitter
:rotate-y - {:range [min max] :seed s} random Y-axis rotation per instance
(isometric opts)
Creates an isometric projection map.
opts: :scale (default 1.0), :origin [x y] (default [0 0]).
(lerp-color [_t1 r1 g1 b1] [_t2 r2 g2 b2] t)
Linear interpolation between two RGB colors.
(look-at base-projection eye target)
(look-at base-projection eye target up)
Returns a projection map oriented so the camera looks from eye toward target.
Derives :yaw, :pitch, and :roll from the geometry. Preserves :type, :scale,
:origin, and :distance from base-projection.
up: world up vector (default [0 1 0]).
(lsystem-mesh {:keys [axiom rules iterations angle length profile segments taper]})
Generates a 3D mesh from an L-system by sweeping a profile along branches.
Composes L-system string expansion + 3D turtle interpretation + sweep-mesh.
opts:
:axiom - starting string
:rules - rewrite rules {"F" "FF[+F][-F]"}
:iterations - number of rewriting iterations
:angle - turn angle in degrees
:length - distance per F step
:profile - 2D cross-section [[x y] ...] for sweep
:segments - sweep segments per branch (default 4)
:taper - profile scale factor per branch depth (default 1.0, < 1 = thinner)
(make-face vertices)
(make-face vertices style)
Creates a face map from a sequence of 3D vertices.
Computes the normal automatically from the first three vertices.
(make-face-selector opts)
Builds a predicate fn from a selector descriptor.
Returns (fn [face centroid normal] -> boolean).
(merge-meshes & meshes)
Combines multiple meshes into a single mesh (vector of faces).
Each argument is either a bare mesh (vector of faces) or a
[mesh style] pair, where style is applied to every face in that mesh.
(mesh-bounds mesh)
Returns the axis-aligned bounding box of a mesh as {:min [x y z] :max [x y z]}.
(mesh-center mesh)
Returns the center point of a mesh's bounding box.
(mirror-mesh mesh opts)
Reflects a mesh across an axis plane through the origin.
opts:
:mirror/axis - :x, :y, or :z (which axis plane to reflect across)
:mirror/merge - if true, return original + reflection combined (default false)
(normal-map-mesh mesh opts)
Perturbs vertex normals using a field sampled at UV coordinates.
Creates visible surface detail under lighting without adding geometry.
Requires :face/texture-coords on faces (from uv-project or OBJ import).
opts:
:normal-map/field - field descriptor
:normal-map/strength - perturbation strength (default 1.0)
:select/* - optional face selector
(orbit base-projection target opts)
Returns a projection with the camera orbiting target at the given radius.
opts: :radius, :yaw (radians), :pitch (radians).
At yaw=0 pitch=0, camera is at +Z relative to target (consistent with
the default camera convention).
(orthographic opts)
Creates an orthographic projection map.
opts: :scale, :origin, :yaw (radians), :pitch (radians).
(paint-mesh mesh opts)
Assigns per-vertex colors by sampling a field at vertex positions.
When :color/source is :uv, samples at vertex UV coordinates instead of
3D positions — this is the bridge from Eido's 2D procedural system to 3D.
opts:
:color/type - :field, :axis-gradient, or :normal-map
:color/source - :position (default) or :uv (requires :face/texture-coords)
:color/palette - vector of [:color/rgb r g b] colors
:color/field - field descriptor (for :field type)
:color/axis - :x, :y, or :z (for :axis-gradient type)
:select/* - optional face selector
(palette-color palette t)
Maps a [0,1] value to a color from a palette via linear interpolation.
(perspective opts)
Creates a perspective projection map.
opts: :scale, :origin, :yaw, :pitch, :distance.
(platonic-mesh type radius)
Returns a platonic solid inscribed in a sphere of the given radius.
type: :tetrahedron, :octahedron, :dodecahedron, or :icosahedron.
(prism projection position opts)
Creates a 3D prism projected into 2D.
opts: :base-points, :height, :style, :light, :cull-back.
(prism-mesh base-points height)
Returns a mesh for a prism: a 2D polygon base extruded along the Y axis.
base-points: seq of [x y] for the base (in the XZ plane).
height: extrusion distance along the Y axis.
(render-mesh projection mesh opts)
Projects a mesh and returns a :group node with faces sorted back-to-front.
Each face becomes a :shape/path node.

opts:
:style - default style {:style/fill [...] :style/stroke {...}}
:light - single light map (backward compatible)
:lights - vector of light maps (multi-light)
:cull-back - if true, omit back-facing polygons (default true)
:wireframe - if true, render edges only (no fill, no shading)
:shading - :flat (default) or :smooth (vertex normal averaging)
(revolve-mesh {:keys [profile segments]})
Creates a mesh by revolving a 2D profile around the Y axis.
opts:
:profile - vector of [radius height] pairs defining the cross-section
:segments - number of rotation steps around the axis
(rotate-mesh mesh axis angle)
Rotates all vertices and normals in a mesh around the given axis.
axis: :x, :y, or :z. angle: radians.
(scale-mesh mesh factor)
Scales all vertices in a mesh. factor is a number (uniform) or [sx sy sz].
(specular-map-mesh mesh opts)
Varies specular intensity per vertex using a field sampled at UV coordinates.
Requires :face/texture-coords on faces. The material's specular value is
overridden per sub-triangle during rendering.
opts:
:specular-map/field - field descriptor
:specular-map/range - [min-spec max-spec] (default [0.0 1.0])
:select/* - optional face selector
(sphere projection position opts)
Creates a 3D sphere projected into 2D.
opts: :radius, :segments, :rings, :style, :light, :cull-back.
(sphere-mesh radius)
(sphere-mesh radius opts)
Returns a mesh approximating a sphere at the origin.
Opts: :segments (default 16) — longitude slices,
:rings (default 12) — latitude bands.
(subdivide mesh opts)
Applies Catmull-Clark subdivision to a mesh.
opts:
:iterations - number of subdivision passes (each 4× face count)
:hard-edges - optional set of edge keys to preserve as creases
Returns a new mesh of quad faces.
(sweep-mesh {:keys [profile path segments closed]})
Creates a mesh by sweeping a 2D profile along a 3D path.
opts:
:profile - vector of [x y] pairs defining the cross-section
:path - vector of [x y z] waypoints defining the sweep path
:segments - number of steps along the path
:closed - if true, connect last ring back to first (default false)
(text-3d projection content font-spec opts)
Creates 3D extruded text projected into 2D, returned as a :group node.
projection: projection map. content: string. font-spec: font map.
opts: :depth (extrusion depth), :flatness, :style, :light, :cull-back.
The mesh is centered at the origin for natural rotation.
Front/back caps use even-odd fill to correctly render letter holes.
(text-mesh content font-spec depth opts)
Creates side-wall faces for extruded text (no caps).
content: string. font-spec: font map. depth: extrusion depth along Y axis.
opts: :flatness (curve approximation, default 1.0).
(torus projection position opts)
Creates a 3D torus projected into 2D.
opts: :major-radius, :minor-radius, :ring-segments, :tube-segments,
:style, :light, :cull-back.
(torus-mesh R r)
(torus-mesh R r opts)
Returns a mesh approximating a torus at the origin.
R: major radius (center of tube to center of torus).
r: minor radius (tube cross-section).
Opts: :ring-segments (default 24) — divisions around the ring,
:tube-segments (default 12) — divisions around the tube.
(translate-mesh mesh offset)
Translates all vertices in a mesh by offset [dx dy dz].
(uv-project mesh opts)
Assigns texture coordinates to mesh faces via projection.
opts:
:uv/type - :box, :spherical, :cylindrical, or :planar
:uv/axis - axis for :cylindrical/:planar (default :y)
:uv/scale - UV scale factor (default 1.0)
:uv/offset - [u-offset v-offset] (default [0 0])
:select/* - optional face selector

eido.scene3d.camera

Projection constructors and camera utilities.

(fov->distance fov half-width)
Converts a horizontal field-of-view angle (radians) to a perspective
:distance value. half-width is half the viewport width in world-space
units (typically screen-half-width / scale).
(isometric opts)
Creates an isometric projection map.
opts: :scale (default 1.0), :origin [x y] (default [0 0]).
(look-at base-projection eye target)
(look-at base-projection eye target up)
Returns a projection map oriented so the camera looks from eye toward target.
Derives :yaw, :pitch, and :roll from the geometry. Preserves :type, :scale,
:origin, and :distance from base-projection.
up: world up vector (default [0 1 0]).
(orbit base-projection target opts)
Returns a projection with the camera orbiting target at the given radius.
opts: :radius, :yaw (radians), :pitch (radians).
At yaw=0 pitch=0, camera is at +Z relative to target (consistent with
the default camera convention).
(orthographic opts)
Creates an orthographic projection map.
opts: :scale, :origin, :yaw (radians), :pitch (radians).
(perspective opts)
Creates a perspective projection map.
opts: :scale, :origin, :yaw, :pitch, :distance.

eido.scene3d.mesh

Mesh constructors: primitives, platonic solids, and parametric generators.

(cone-mesh radius height)
(cone-mesh radius height opts)
Returns a mesh approximating a cone at the origin.
Base circle in the XZ plane at y=0, apex at [0 height 0].
Opts: :segments (default 16) — number of sides.
(cube-mesh)
(cube-mesh position size)
Returns a mesh of 6 quad faces for a unit cube at the origin,
or a cube at position [x y z] with given size.
(cylinder-mesh radius height)
(cylinder-mesh radius height opts)
Returns a mesh approximating a cylinder centered at the origin.
Opts: :segments (default 16) — number of sides for the circular cross-section.
(extrude-mesh path-points direction)
Extrudes a 2D polygon along a 3D vector.
path-points: seq of [x y] (treated as [x, 0, y] in 3D space).
direction: [dx dy dz] extrusion vector.
(heightfield-mesh {:keys [field bounds grid height]})
Creates a mesh from a 2D field sampled on a grid.
opts:
:field - field descriptor (noise, constant, distance)
:bounds - [x z width depth] defining the sampling area
:grid - [cols rows] number of sample points
:height - maximum Y displacement
(platonic-mesh type radius)
Returns a platonic solid inscribed in a sphere of the given radius.
type: :tetrahedron, :octahedron, :dodecahedron, or :icosahedron.
(prism-mesh base-points height)
Returns a mesh for a prism: a 2D polygon base extruded along the Y axis.
base-points: seq of [x y] for the base (in the XZ plane).
height: extrusion distance along the Y axis.
(revolve-mesh {:keys [profile segments]})
Creates a mesh by revolving a 2D profile around the Y axis.
opts:
:profile - vector of [radius height] pairs defining the cross-section
:segments - number of rotation steps around the axis
(sphere-mesh radius)
(sphere-mesh radius opts)
Returns a mesh approximating a sphere at the origin.
Opts: :segments (default 16) — longitude slices,
:rings (default 12) — latitude bands.
(sweep-mesh {:keys [profile path segments closed]})
Creates a mesh by sweeping a 2D profile along a 3D path.
opts:
:profile - vector of [x y] pairs defining the cross-section
:path - vector of [x y z] waypoints defining the sweep path
:segments - number of steps along the path
:closed - if true, connect last ring back to first (default false)
(torus-mesh R r)
(torus-mesh R r opts)
Returns a mesh approximating a torus at the origin.
R: major radius (center of tube to center of torus).
r: minor radius (tube cross-section).
Opts: :ring-segments (default 24) — divisions around the ring,
:tube-segments (default 12) — divisions around the tube.

eido.scene3d.transform

Mesh transforms, deformations, and mirror operations.

(deform-mesh mesh descriptor)
Applies a deformation to a mesh, returning a new mesh.
descriptor: map with :deform/type and type-specific options.
Types: :twist, :taper, :bend, :inflate, :crumple, :displace.
(mirror-mesh mesh opts)
Reflects a mesh across an axis plane through the origin.
opts:
:mirror/axis - :x, :y, or :z (which axis plane to reflect across)
:mirror/merge - if true, return original + reflection combined (default false)
(rotate-mesh mesh axis angle)
Rotates all vertices and normals in a mesh around the given axis.
axis: :x, :y, or :z. angle: radians.
(scale-mesh mesh factor)
Scales all vertices in a mesh. factor is a number (uniform) or [sx sy sz].
(translate-mesh mesh offset)
Translates all vertices in a mesh by offset [dx dy dz].

eido.scene3d.topology

Mesh topology: adjacency, subdivision, and auto-smoothing.

(auto-smooth-edges mesh opts)
Returns a set of hard edge keys where adjacent faces meet at more than
the given angle. Use with subdivide's :hard-edges option.
opts:
:angle - threshold angle in radians (edges sharper than this are hard)
(build-face-adjacency mesh)
Builds adjacency maps from a mesh.
Returns {:edge-faces {edge-key → [face-index ...]}
:vert-faces {vertex → [face-index ...]}
:face-data [{:vertices [...] :style ... :normal ... :point ...} ...]}
(compute-vertex-normals face-data vert-faces)
Computes smooth vertex normals by averaging adjacent face normals.
Returns {vertex → normalized-average-normal}.
(subdivide mesh opts)
Applies Catmull-Clark subdivision to a mesh.
opts:
:iterations - number of subdivision passes (each 4× face count)
:hard-edges - optional set of edge keys to preserve as creases
Returns a new mesh of quad faces.

eido.scene3d.surface

UV projection, face coloring, vertex painting, and material maps.

(color-mesh mesh opts)
Colors each face based on a descriptor.
When :select/type is present, only selected faces are colored; others pass through.
opts:
:color/type - :field, :axis-gradient, or :normal-map
:color/palette - vector of [:color/rgb r g b] colors
:color/field - field descriptor (for :field type)
:color/axis - :x, :y, or :z (for :axis-gradient type)
:select/* - optional face selector (defaults to all faces)
(normal-map-mesh mesh opts)
Perturbs vertex normals using a field sampled at UV coordinates.
Creates visible surface detail under lighting without adding geometry.
Requires :face/texture-coords on faces (from uv-project or OBJ import).
opts:
:normal-map/field - field descriptor
:normal-map/strength - perturbation strength (default 1.0)
:select/* - optional face selector
(paint-mesh mesh opts)
Assigns per-vertex colors by sampling a field at vertex positions.
When :color/source is :uv, samples at vertex UV coordinates instead of
3D positions — this is the bridge from Eido's 2D procedural system to 3D.
opts:
:color/type - :field, :axis-gradient, or :normal-map
:color/source - :position (default) or :uv (requires :face/texture-coords)
:color/palette - vector of [:color/rgb r g b] colors
:color/field - field descriptor (for :field type)
:color/axis - :x, :y, or :z (for :axis-gradient type)
:select/* - optional face selector
(specular-map-mesh mesh opts)
Varies specular intensity per vertex using a field sampled at UV coordinates.
Requires :face/texture-coords on faces. The material's specular value is
overridden per sub-triangle during rendering.
opts:
:specular-map/field - field descriptor
:specular-map/range - [min-spec max-spec] (default [0.0 1.0])
:select/* - optional face selector
(uv-project mesh opts)
Assigns texture coordinates to mesh faces via projection.
opts:
:uv/type - :box, :spherical, :cylindrical, or :planar
:uv/axis - axis for :cylindrical/:planar (default :y)
:uv/scale - UV scale factor (default 1.0)
:uv/offset - [u-offset v-offset] (default [0 0])
:select/* - optional face selector

eido.scene3d.modeling

Polygonal modeling operations: extrude, inset, bevel, detail, L-system, instancing.

(bevel-faces mesh opts)
Insets selected faces then extrudes the inner faces, creating a beveled edge.
Composes inset-faces and extrude-faces in one step.
opts:
:select/* - face selector (defaults to :all)
:bevel/inset - how far to shrink inward (0-1)
:bevel/depth - extrusion distance (positive = outward, negative = inward)
(detail-faces mesh opts)
Adds procedural surface detail by insetting then noise-extruding faces.
Creates mechanical/sci-fi panel detail. Composes inset + field-driven extrude.
opts:
:select/* - face selector (defaults to :all)
:detail/field - noise field for per-face extrusion depth
:detail/inset - inset amount (default 0.1)
:detail/depth-range - [min-depth max-depth] range for extrusion
(extrude-faces mesh opts)
Extrudes selected faces along their normals.
opts:
:select/* - face selector (see make-face-selector)
:extrude/amount - distance to push faces
:extrude/scale - optional scale factor toward centroid (default 1.0)
(inset-faces mesh opts)
Insets selected faces, creating a smaller inner face and border quads.
opts:
:select/* - face selector
:inset/amount - how far to shrink inward (0-1 fraction of distance to centroid)
(instance-mesh mesh opts)
Places copies of a mesh at multiple positions.
Bridges 2D scatter distributions to 3D mesh placement.
opts:
:positions - vector of [x y z] positions
:jitter - {:amount n :seed s} random positional jitter
:rotate-y - {:range [min max] :seed s} random Y-axis rotation per instance
(lsystem-mesh {:keys [axiom rules iterations angle length profile segments taper]})
Generates a 3D mesh from an L-system by sweeping a profile along branches.
Composes L-system string expansion + 3D turtle interpretation + sweep-mesh.
opts:
:axiom - starting string
:rules - rewrite rules {"F" "FF[+F][-F]"}
:iterations - number of rewriting iterations
:angle - turn angle in degrees
:length - distance per F step
:profile - 2D cross-section [[x y] ...] for sweep
:segments - sweep segments per branch (default 4)
:taper - profile scale factor per branch depth (default 1.0, < 1 = thinner)

eido.scene3d.render

3D rendering: shading, NPR, mesh projection, depth sorting, convenience wrappers, and text mesh.

(cone projection position opts)
Creates a 3D cone projected into 2D.
opts: :radius, :height, :segments, :style, :light, :cull-back.
(cube projection position opts)
Creates a 3D cube projected into 2D, returned as a :group node.
opts: :size (1), :style, :light, :cull-back.
(cylinder projection position opts)
Creates a 3D cylinder projected into 2D.
opts: :radius, :height, :segments, :style, :light, :cull-back.
(depth-sort & node-colls)
Sorts a mixed collection of nodes by :node/depth for correct 3D occlusion.
Accepts any number of node collections — vectors of nodes, individual group
nodes (from render-mesh), or single nodes.

Groups are flattened into their children before sorting. All nodes are
sorted smallest-depth-first (farthest from camera drawn first — painter's
algorithm). Nodes without :node/depth are placed at the back.

Returns a vector of sorted nodes ready for :image/nodes.
(prism projection position opts)
Creates a 3D prism projected into 2D.
opts: :base-points, :height, :style, :light, :cull-back.
(render-mesh projection mesh opts)
Projects a mesh and returns a :group node with faces sorted back-to-front.
Each face becomes a :shape/path node.

opts:
:style - default style {:style/fill [...] :style/stroke {...}}
:light - single light map (backward compatible)
:lights - vector of light maps (multi-light)
:cull-back - if true, omit back-facing polygons (default true)
:wireframe - if true, render edges only (no fill, no shading)
:shading - :flat (default) or :smooth (vertex normal averaging)
(sphere projection position opts)
Creates a 3D sphere projected into 2D.
opts: :radius, :segments, :rings, :style, :light, :cull-back.
(text-3d projection content font-spec opts)
Creates 3D extruded text projected into 2D, returned as a :group node.
projection: projection map. content: string. font-spec: font map.
opts: :depth (extrusion depth), :flatness, :style, :light, :cull-back.
The mesh is centered at the origin for natural rotation.
Front/back caps use even-odd fill to correctly render letter holes.
(text-mesh content font-spec depth opts)
Creates side-wall faces for extruded text (no caps).
content: string. font-spec: font map. depth: extrusion depth along Y axis.
opts: :flatness (curve approximation, default 1.0).
(torus projection position opts)
Creates a 3D torus projected into 2D.
opts: :major-radius, :minor-radius, :ring-segments, :tube-segments,
:style, :light, :cull-back.

eido.io.obj

Wavefront OBJ and MTL parser. Pure functions: string in, mesh data out.

(parse-mtl text)
Parses MTL text into a map of material-name to style map.
Returns e.g. {"wood" {:style/fill [:color/rgb 139 90 43] :node/opacity 1.0}}

Supported directives: newmtl, Kd, d. All others are ignored.
(parse-obj text opts)
Parses OBJ text into a mesh (vector of face maps).

opts:
:materials - map from material name to style (from parse-mtl)
:default-style - style for faces with no material assignment

Supported directives: v, vn, vt, f, usemtl,
g (group name → :face/group), s (smooth group → :face/smooth-group),
o (object name, ignored). All others are silently skipped.

Texture coordinates (vt) are stored as :face/texture-coords when present.
(write-mtl materials)
Generates MTL text from a map of material-name to style map.
Inverse of parse-mtl.
(write-obj mesh)
(write-obj mesh opts)
Generates OBJ text from a mesh (vector of face maps).
Exports texture coordinates when :face/texture-coords is present.
opts:
:name - object name (default "mesh")
:mtl - if true, includes material references; returns {:obj str :mtl str}
if false (default), returns the OBJ string directly

eido.io.polyline

Extracts polyline data from compiled IR for CNC/plotter/laser export. Converts all geometry to sequences of [x y] points.

Provisional
(extract-grouped-polylines ir)
(extract-grouped-polylines ir opts)
Extracts polylines from compiled IR, grouped by stroke color.

Returns {:groups [{:stroke
:polylines [[[x y] ...] ...]} ...]
:bounds [w h]}.

Stroke colors are resolved maps like {:r R :g G :b B :a A}, or nil
for ops without a stroke. Groups appear in the order their stroke
color was first seen. Leaf ops inside :buffer containers are
flattened before grouping.

Options:
:flatness — curve subdivision tolerance (default 0.5)
:segments — number of segments for circle/ellipse/arc (default 64)
(extract-polylines ir)
(extract-polylines ir opts)
Extracts all polyline data from compiled IR.
Returns {:polylines [[[x1 y1] [x2 y2] ...] ...] :bounds [w h]
:dropped {:fills N ...} (only when non-empty)}.

The optional :dropped map summarizes visual features (fills,
gradients, patterns, hatch, stipple, effects) that the polyline
pipeline cannot represent — a scene that looks filled on screen
exports as outlines only, and :dropped flags how much got lost.

Options:
:flatness — curve subdivision tolerance (default 0.5)
:segments — number of segments for circle/ellipse/arc approximation (default 64)
Provisional
(optimize-travel-polylines polylines)
Reorders polylines to minimize pen-up travel between them.
Greedy nearest-neighbor starting from [0 0], picking the polyline
whose first point is closest to the current position each step.

Polylines with no first point (empty/nil) are dropped, since they
produce no motion and can't anchor the nearest-neighbor search.

Input and output are both vectors of polylines:
[[[x y] ...] ...].
(polylines->edn data)
Serializes polyline data to an EDN string.
Provisional
(summarize-drops ir)
Returns a map of silently-dropped visual features for a compiled IR.
Counts what the polyline pipeline can't represent — fills (solid,
gradient, pattern, hatch, stipple) — so callers can warn or log
when an export would lose visible information.

Returns {} when nothing is dropped.

eido.math

Shared math utilities: 3D vector operations, interpolation, smoothstep, rotations, and other numeric helpers used across Eido.

(camera-direction projection)
Returns the unit vector pointing from the scene toward the camera.
Used for back-face culling and depth sorting.
Convention: yaw=0 pitch=0 means camera looks along -Z (camera at +Z).
(cross [x1 y1 z1] [x2 y2 z2])
Cross product of two 3D vectors.
(dot [x1 y1 z1] [x2 y2 z2])
Dot product of two 3D vectors.
(face-centroid vertices)
Returns the centroid (average position) of a set of 3D points.
(face-normal [v0 v1 v2 & _])
Computes the normal vector of a face from its first three vertices.
The direction follows the right-hand rule (counter-clockwise winding).
(face-tangent-bitangent [v0 v1 v2] [uv0 uv1 uv2])
Computes tangent and bitangent vectors for a face given its first three
vertices and their UV coordinates. Returns [tangent bitangent] as
normalized 3D vectors, or nil if the UV triangle is degenerate.
(lerp [ax ay az] [bx by bz] t)
Linear interpolation between two 3D vectors.
t=0 returns a, t=1 returns b.
(magnitude [x y z])
Length of a 3D vector.
(make-projector projection)
Returns a function that projects 3D points to 2D screen coordinates.
Precomputes trig values and projection parameters once, avoiding
per-vertex map lookups, trig calls, and intermediate vector allocations.
(normalize v)
Returns a unit vector in the same direction, or [0 0 0] for zero vector.
(project projection point)
Projects a 3D point to 2D screen coordinates using the given projection.
(rotate [x y z] axis angle)
Rotates a point around the given axis (:x, :y, or :z) by angle (radians).
(smoothstep edge0 edge1 x)
Hermite interpolation between edge0 and edge1.
Returns 0 when x <= edge0, 1 when x >= edge1, smooth curve between.
(v* [x y z] s)
Multiplies a 3D vector by a scalar.
(v+ [x1 y1 z1] [x2 y2 z2])
Adds two 3D vectors.
(v- [x1 y1 z1] [x2 y2 z2])
Subtracts second 3D vector from first.
(view-transform projection point)
Transforms a 3D point into view space (rotated by camera angles).
Used for perspective projection depth calculation.

eido.ir

Eido's intermediate representation. Two levels: 1. Semantic IR — containers, draw items, fill/effect descriptors. Preserves artist intent (hatch fills, effects, fields) as data. 2. Concrete ops — leaf records consumed by render.clj and svg.clj. Low-level drawing instructions (RectOp, PathOp, BufferOp). The pipeline flows: scene map → semantic IR → lower → concrete ops → render. See eido.ir.lower for the lowering step.

(->ArcOp op cx cy rx ry start extent mode fill stroke-color stroke-width opacity stroke-cap stroke-join stroke-dash transforms clip)
(->BufferOp op composite filter opacity transforms clip ops)
(->CircleOp op cx cy r fill stroke-color stroke-width opacity stroke-cap stroke-join stroke-dash transforms clip)
(->EllipseOp op cx cy rx ry fill stroke-color stroke-width opacity stroke-cap stroke-join stroke-dash transforms clip)
(->LineOp op x1 y1 x2 y2 fill stroke-color stroke-width opacity stroke-cap stroke-join stroke-dash transforms clip)
(->PathOp op commands fill-rule fill stroke-color stroke-width opacity stroke-cap stroke-join stroke-dash transforms clip)
(->RectOp op x y w h corner-radius fill stroke-color stroke-width opacity stroke-cap stroke-join stroke-dash transforms clip)
(arc-geometry center rx ry start extent & {:keys [mode]})
(circle-geometry center radius)
(compile-command command)
Flattens a scene path command to concrete IR format.
[:move-to [x y]] → [:move-to x y]
(container size background items)
(container size background items extra-resources)
Creates a semantic IR container from size, background, and draw items.
Optionally accepts additional resources to merge with the default framebuffer.
(draw-item geometry & {:keys [fill stroke opacity transforms clip effects pre-transforms]})
Creates a semantic draw item from geometry and optional style properties.
(effect-pass id effect & {:keys [input target], :or {input :framebuffer, target :framebuffer}})
Creates an effect pass that applies a filter to a resource.
(ellipse-geometry center rx ry)
(generator-item generator-map)
Creates a semantic draw item from a generator descriptor map.
The generator-map should have :item/generator with :generator/type.
(geometry-bounds geom)
Returns [x y w h] bounding box for an IR geometry map.
(line-geometry from to)
(path-geometry commands & {:keys [fill-rule]})
(pipeline size background passes)
(pipeline size background passes {:keys [resources outputs]})
Creates a multi-pass IR container.
passes: vector of pass maps (draw-geometry, effect-pass, program-pass).
Optionally accepts additional resources and outputs.
(program-pass id program & {:keys [input target], :or {input :framebuffer, target :framebuffer}})
Creates a program pass that evaluates a program over a resource.
(rect-geometry xy size & {:keys [corner-radius]})

eido.ir.domain

Domain descriptors — the space over which something is evaluated. A domain describes what coordinate system and bindings are available when evaluating a program, field, or generator. Domain kinds: :image-grid — pixel grid with :uv [0..1, 0..1], :px, :py, :size :shape-local — shape-local UV space with :uv [0..1, 0..1] :world-2d — world coordinates with :pos [x y] :path-param — path parameter with :t [0..1], :pos [x y] :mesh-faces — per-face with :normal, :centroid :mesh-vertices — per-vertex with :pos [x y z] :points — point set with :pos [x y], :index :particles — particle collection with :pos, :vel, :age, :life :timeline — animation time with :t [0..1], :frame, :fps

(bindings-for domain-kind)
Returns the set of binding keywords available for a domain kind.
Useful for documentation and validation.
(image-grid size)
Domain over a pixel grid.
(mesh-faces mesh)
Domain over mesh faces.
(particles source)
Domain over a particle collection.
(path-param path-commands)
Domain over a path's parameter space [0..1].
(points point-set)
Domain over a point set.
(shape-local)
Domain over a shape's local UV space.
(timeline & {:keys [fps frames]})
Domain over animation time.
(world-2d bounds)
Domain over 2D world coordinates within bounds.

eido.ir.resource

Named resources for multi-pass rendering. A resource is an explicit input/output object used by passes. Resources are declared in the IR container and referenced by name. Resource kinds: :image — raster image buffer (the main framebuffer) :mask — single-channel mask :geometry — vector geometry (paths, shapes) :points — point set :field — evaluated scalar/vector field :particle-state — particle simulation state :parameter-block — named parameter values

(field-resource name field-desc)
Declares a field resource.
(geometry name)
Declares a geometry resource.
(image name size & {:keys [color-space], :or {color-space :srgb}})
Declares an image resource.
(mask name size)
Declares a mask resource.
(merge-resources & resource-maps)
Merges multiple resource declarations into one map.
(parameter-block name params)
Declares a parameter block resource.
(particle-state name schema)
Declares a particle state resource.
(point-set name points)
Declares a point set resource.
(validate-pass-resources pass resources)
Validates that all resources referenced by a pass exist in the
resource map. Returns nil if valid, or a vector of error strings.
(validate-pipeline-resources ir-container)
Validates all passes in a pipeline reference declared resources.
Returns nil if valid, or a vector of error strings.

eido.ir.fill

Semantic fill descriptors and lowering to concrete ops. Fill types: :fill/solid — solid color :fill/gradient — linear or radial gradient :fill/pattern — tiled pattern :fill/hatch — hatched line pattern :fill/stipple — dot distribution pattern Hatch and stipple fills preserve their semantic identity in the IR and are expanded to concrete geometry during lowering.

(evaluate-procedural-fill fill-spec w h)
Evaluates a procedural fill over a bounding box, producing a BufferedImage.
The program receives :uv as normalized [0..1, 0..1] coordinates.
(gradient type stops & {:keys [from to center radius]})
(hatch opts)
(lower-hatch item)
Lowers a draw item with a hatch fill to concrete ops.
Calls hatch/hatch-fill->nodes directly and converts to concrete ops.
(lower-procedural item)
Lowers a draw item with a procedural fill to concrete ops.
Evaluates the program over the item's bounds and creates an image fill.
(lower-stipple item)
Lowers a draw item with a stipple fill to concrete ops.
Calls stipple/stipple-fill->nodes directly and converts to concrete ops.
(procedural program)
Creates a procedural fill descriptor.
program is a program map with :program/body and optional :program/inputs.
The program is evaluated per-pixel with :uv bound to normalized [0-1] coords.
(semantic-fill? fill)
Returns true if a fill descriptor requires semantic lowering
(as opposed to direct resolution to a color/gradient).
(solid color)
(stipple opts)

eido.ir.effect

Semantic effect descriptors and lowering to concrete ops. Effect types: :effect/shadow — drop shadow with offset, blur, color :effect/glow — glow (shadow with no offset) :effect/blur — gaussian blur :effect/grain — film grain :effect/posterize — color quantization :effect/duotone — two-color mapping :effect/halftone — dot-screen halftone Effects are stored as descriptors in draw items and expanded to BufferOp wrappers during lowering.

(blur & {:keys [radius], :or {radius 5}})
(duotone & {:keys [color-a color-b]})
(glow & {:keys [blur color opacity], :or {blur 8, opacity 0.7}})
(grain & {:keys [amount seed], :or {amount 30}})
(halftone & {:keys [dot-size angle], :or {dot-size 6, angle 45}})
(lower-effects item)
Lowers a draw item with effects to concrete ops.
Builds BufferOp wrappers directly for shadow/glow and filter effects.
(posterize & {:keys [levels], :or {levels 4}})
(shadow & {:keys [dx dy blur color opacity], :or {dx 3, dy 3, blur 5, opacity 0.5}})

eido.ir.field

Field descriptors and evaluation. A field is a function over a 2D domain that yields a scalar or vector value. Fields are reusable descriptors that can be consumed by fills, generators, transforms, and programs. Field types: :field/noise — Perlin noise (raw, fbm, turbulence, ridge) :field/constant — uniform value everywhere :field/distance — distance from a point

(constant-field value)
Creates a field that returns the same value everywhere.
(distance-field center)
Creates a field that returns the distance from a point.
(evaluate field x y)
Evaluates a field descriptor at position (x, y).
Returns a double.
(evaluate-3d field x y z)
Evaluates a field descriptor at 3D position (x, y, z).
Noise fields use 3D Perlin noise. Distance fields use x and y only.
Returns a double.
(noise-field & {:keys [scale variant octaves lacunarity gain seed offset], :or {scale 1.0, variant :fbm}})
Creates a noise field descriptor.
Options: :noise-type (:perlin), :variant (:raw | :fbm | :turbulence | :ridge),
:scale (1.0), :octaves (4), :lacunarity (2.0), :gain (0.5),
:seed (nil), :offset (1.0, ridge only).

eido.ir.program

Minimal expression evaluator for vector-form programs. Programs are pure data: nested vectors describing computations. They are evaluated over a domain (e.g. image grid) with named bindings. Expression forms: Literals: 42, 0.5, [1 2 3] References: :uv, :time, :seed (keywords resolve in env) Arithmetic: [:+ a b], [:- a b], [:* a b], [:/ a b] Math: [:abs x], [:sqrt x], [:pow x n], [:mod x n] [:sin x], [:cos x], [:floor x], [:ceil x] Vector: [:vec2 x y], [:vec3 x y z], [:vec4 x y z w] Access: [:x v], [:y v] (first/second of a vector) Interpolate: [:mix a b t], [:clamp x lo hi] Conditional: [:select pred a b] Fields: [:field/noise {field-desc} pos-expr] Color: [:color/rgb r g b]

(evaluate env expr)
Evaluates an expression in the given environment.
env is a map of keyword → value (e.g. {:uv [0.5 0.5] :time 0.0}).
(run program env)
Evaluates a program map over a single point.
program: {:program/inputs {:uv :vec2 ...}
:program/domain {:domain/kind :image-grid ...} ;; optional
:program/body }
env: {:uv [0.5 0.5] :time 0.0 ...}

If the program has a :program/domain, validates that the env contains
the expected bindings for that domain kind.

eido.ir.transform

Semantic transform descriptors and lowering. Transform types: :transform/distort — noise/wave/roughen/jitter displacement on paths :transform/warp — wave/twist/fisheye/bulge/bend coordinate warp :transform/morph — interpolation between two path command sets Transforms are stored on draw items as :item/pre-transforms and applied to geometry before coordinate transforms during lowering.

(apply-pre-transform commands transform)
Applies a single pre-transform to path commands.
(apply-pre-transforms geom pre-transforms)
Applies a sequence of pre-transforms to a geometry map.
Returns a modified geometry map (always :path type after transforms).
(distortion method opts)
Creates a distort transform descriptor.
method: :noise | :wave | :roughen | :jitter
opts: method-specific params (see eido.path.distort).
(morph-transform target t)
Creates a morph transform descriptor.
target: path commands to morph toward.
t: interpolation parameter (0.0 = source, 1.0 = target).
(warp-transform method params)
Creates a warp transform descriptor.
method: :wave | :twist | :fisheye | :bulge | :bend
params: method-specific params (see eido.path.warp).

eido.ir.generator

Generator descriptors and lowering. A generator is a draw item that produces multiple concrete ops by calling existing feature module functions. Generators use :item/generator instead of :item/geometry. Generator types: :generator/flow-field — streamlines from noise field :generator/contour — iso-contour lines from scalar field :generator/scatter — distributed copies of a shape :generator/voronoi — Voronoi tessellation from seed points :generator/delaunay — Delaunay triangulation edges :generator/decorator — shapes placed along a path

(contour bounds & {:keys [field opts style]})
Creates a contour generator descriptor.
field: a field descriptor (or nil for default Perlin noise).
(decorator-gen path-commands shape & {:keys [spacing rotate? overrides], :or {spacing 20, rotate? true}})
Creates a decorator generator descriptor.
(delaunay-gen points bounds & {:keys [style]})
Creates a Delaunay edge generator descriptor.
(expand-generator gen-desc)
Expands a generator descriptor to concrete ops by calling
existing feature module functions and compiling the results.
(flow-field bounds & {:keys [opts style overrides]})
Creates a flow field generator descriptor.
(particle-gen config frame n)
Creates a particle system generator descriptor.
config: particle system config map (emitter, forces, lifetime, etc.)
frame: which frame to render (0-indexed)
n: total frames to simulate.
(scatter-gen shape positions & {:keys [jitter overrides]})
Creates a scatter generator descriptor.
(voronoi-gen points bounds & {:keys [style overrides]})
Creates a Voronoi generator descriptor.

eido.ir.vary

Vary descriptors for per-item style variation. Vary descriptors generate override vectors that modify generated items (fill, stroke, opacity, transforms). Vary types: :vary/by-index — override function called with index :vary/by-position — override function called with position :vary/by-noise — noise-sampled at each position :vary/by-gradient — interpolated color gradient

(by-gradient n stops)
Creates a vary descriptor that interpolates fill through gradient stops.
(by-index n f)
Creates a vary descriptor that generates overrides by index.
(by-noise positions f opts)
Creates a vary descriptor that generates overrides from noise.
opts: :noise-scale (required), :seed (default 0).
(by-position positions f)
Creates a vary descriptor that generates overrides by position.
(resolve-overrides vary-desc)
Evaluates a vary descriptor into an override vector.
If the input is already a vector, returns it as-is.

eido.ir.material

Material descriptors and multi-light shading for 3D rendering. Materials describe how surfaces respond to light using Blinn-Phong. Light types: :directional — parallel rays from a direction (default, existing) :omni — radiates in all directions from a position :spot — cone of light from a position with hotspot/falloff :hemisphere — sky/ground ambient blend by normal direction Standard light types for 3D scene illumination.

(directional direction & {:keys [color multiplier ambient], :or {multiplier 1.0, ambient 0.0}})
Creates a directional light (parallel rays).
(hemisphere sky-color ground-color & {:keys [up multiplier], :or {up [0 1 0], multiplier 0.3}})
Creates a hemisphere (sky) light with sky and ground colors.
(omni position & {:keys [color multiplier decay decay-start], :or {multiplier 1.0, decay :none, decay-start 0.0}})
Creates an omni (point) light that radiates in all directions.
(phong & {:keys [ambient diffuse specular shininess color], :or {ambient 0.3, diffuse 0.7, specular 0.0, shininess 32.0}})
Creates a Blinn-Phong material descriptor.
(shade-face style normal light-dir cam-dir light material)
(shade-face style normal light-dir cam-dir light material lights face-centroid)
Shades a face style using a material and lights.
Supports single light or lights vector.
(shade-multi-light normal cam-dir face-centroid material lights)
Shades a face using multiple lights and a Blinn-Phong material.
Returns [:color/rgb r g b].
(shade-phong normal light-dir cam-dir light material)
Computes Blinn-Phong shading for a face with a single directional light.
(spot position direction & {:keys [color multiplier hotspot falloff decay decay-start], :or {multiplier 1.0, hotspot 43.0, falloff 45.0, decay :none, decay-start 0.0}})
Creates a spot light with a cone defined by hotspot and falloff angles.

eido.ir.lower

Lowers semantic IR containers to concrete ops. Input: {:ir/version 1 :ir/size [w h] :ir/background bg :ir/passes [{:pass/items [...]}]} Output: {:ir/size [w h] :ir/background bg :ir/ops [RectOp ...]}

(lower ir-container)
Lowers a semantic IR container to the concrete format
consumed by eido.engine.render and eido.engine.svg.
(lower-scene-node node)
Converts a simple scene node (path, circle, rect, etc.) to a concrete op.
Handles scene-level fill/stroke resolution. For use by IR modules that
receive scene nodes from feature modules (hatch, stipple, flow, etc.).
(lower-scene-nodes nodes)
Converts a vector of simple scene nodes to a flat vector of concrete ops.
(resolve-fill f)
Resolves a semantic fill descriptor to the format concrete ops expect.