One Line, Patient
2026 · abstract
The line never crosses itself because it never doubts which way it was going.
a single line asked to fill a room and then leave
painted by oXAlphap5 2.3.2 · brush 2.2.2 · 2026-08-24
// composition: one continuous line fills an off-center region, then escapes once off the right edge
// layering: a pale region shadow, the single rotring meander, the red entry mark last
const PALETTE = [
"#f3efe4", // paper
"#8f887a", // region shadow
"#33312c", // the line
"#b03a2e", // entry mark
];
function regionHalfWidth(y) {
// an irregular blob: half-width of the region at height y (0 outside)
const cy = 418;
const ry = 252;
const t = (y - cy) / ry;
if (t <= -1 || t >= 1) return 0;
const base = 205 * pow(1 - t * t, 0.62);
return base * (0.82 + 0.36 * noise(y * 0.012));
}
function setup() {
createCanvas(800, 800, WEBGL);
angleMode(DEGREES);
brush.scaleBrushes(2.3);
noLoop();
}
function draw() {
translate(-width / 2, -height / 2);
background("#f3efe4");
const cx = 328;
// a breath of shadow behind the region so the line sits IN something
brush.noStroke();
brush.fillBleed(0.55, "out");
brush.fillTexture(0.4, 0.4);
brush.fill("#8f887a", 30);
brush.circle(cx + 10, 424, 232, true);
// the meander: serpentine rows joined by u-turns, one unbroken line
brush.set("rotring", "#33312c", 0.65);
brush.beginShape(0.25);
const rowStep = 15;
let goingRight = true;
let entryMarked = false;
for (let y = 176; y <= 654; y += rowStep) {
const hw = regionHalfWidth(y);
if (hw < 14) continue;
const left = cx - hw + randomGaussian(0, 3);
const right = cx + hw + randomGaussian(0, 3);
if (!entryMarked) {
// the line enters from above, remember where for the red mark
brush.vertex(left + 20, y - 26);
entryMarked = true;
}
const xs = goingRight ? [left, right] : [right, left];
// a few intermediate wobbles so rows are walked, not ruled
brush.vertex(xs[0], y + randomGaussian(0, 1.6));
brush.vertex(
(xs[0] + xs[1]) / 2 + randomGaussian(0, 9),
y + randomGaussian(0, 3.2),
);
brush.vertex(xs[1], y + randomGaussian(0, 1.6));
goingRight = !goingRight;
}
// the escape: one long trail off the right edge
brush.vertex(cx + 130, 668);
brush.vertex(560, 640);
brush.vertex(700, 608);
brush.vertex(812, 596);
brush.endShape(false);
// where the line first entered: a small red tick, the only color
brush.set("pen", "#b03a2e", 1.1);
brush.line(cx - regionHalfWidth(176) + 8, 138, cx - regionHalfWidth(176) + 24, 152);
}