@genart-dev/illustration
v0.3.0
Published
Stroke outline generation, branch junctions, and mark-making for genart.dev
Maintainers
Readme
@genart-dev/illustration
Stroke outline generation, branch junctions, and mark-making for genart.dev.
Transforms centerline geometry into production-quality illustrated output — smooth outlines, clean branch junctions, and medium-specific mark strategies (ink, pencil, engraving, woodcut, brush).
Install
npm install @genart-dev/illustrationQuick Start
import {
segmentToProfile,
generateStrokeOutline,
inkMark,
} from "@genart-dev/illustration";
// 1. Convert geometry to a stroke profile
const profile = segmentToProfile({ x1: 0, y1: 0, x2: 200, y2: 0, width: 10 });
// 2. Generate the outline polygon
const outline = generateStrokeOutline(profile);
// 3. Apply a mark strategy
const marks = inkMark.generateMarks(outline, profile, { density: 1, weight: 1 }, Math.random);
// → Mark[] — polylines with width and opacity, ready for your rendererAPI
Stroke Outlines
Convert a centerline with per-point widths into a closed polygon (left/right edges + caps).
generateStrokeOutline(profile, options?)— full outline with left, right, startCap, endCapgenerateStrokePolygon(profile, options?)— flattened polygon (single Point2D[])taperScale(t, taper)— width multiplier at position t given a TaperSpecgenerateCap(center, tangent, halfWidth, style)— cap geometry
Adapters
Convert from common formats to StrokeProfile:
segmentToProfile(segment)— single TurtleSegment (x1/y1/x2/y2/width)segmentsToProfiles(segments)— batch conversionalgorithmPathToProfile(path)— algorithm stroke paths with per-point data
Branch Junctions
Merge branching outlines into smooth, continuous forms — eliminating the arrowhead artifacts that plague naive stroke rendering.
mergeYJunction(parent, child, attachment)— merge two outlines at a forkmergeSegmentTree(segments, options?)— merge an entire segment treeenforceG1AtJunctions(points, junctions)— tangent continuity at joinssmoothAtIndex(points, index, radius?)— local smoothingsubdivideSharpCorners(points, maxAngle?)— break up acute angles
Mark Strategies
Each strategy implements MarkStrategy.generateMarks(outline, profile, config, rng) → Mark[]:
| Strategy | Character | Reference |
|----------|-----------|-----------|
| technicalMark | Uniform weight, no variation — CAD/architectural | Technical pen |
| inkMark | Pressure-based width, endpoint pooling | Bamboo & Rock (Deng Yu) |
| pencilMark | Multi-pass offset strokes, cross-hatching | Graphite landscape |
| engravingMark | Contour outline + clipped parallel hatching | Copper-plate engraving |
| woodcutMark | Bold fill + carved gouge marks | Block print |
| brushMark | Thick→thin taper, dry-brush filaments, wet pooling | Sumi-e ink painting |
Fill Strategies
Each implements FillStrategy.generateMarks(polygon, config, rng) → Mark[]:
hatchFill— parallel lines at configurable angle and densitycrosshatchFill— two perpendicular hatch layersstippleFill— quasi-random dot distribution
Utilities
Vector math, arc-length parameterization, Catmull-Rom interpolation, and polygon operations (point-in-polygon, area, bounds, offset, outline flattening).
Design
- Zero dependencies on
@genart-dev/format— uses structural typing throughout - Declarative output — strategies return
Mark[]data; rendering to canvas/SVG is the consumer's job - Composable — adapters → outlines → junctions → marks, mix and match at each stage
Quality Bars
See QUALITY.md for the 24 visual quality bars that define "done" for each phase.
License
MIT
