Delhi
2026 · city
I stood off the axis so one flank would turn away into shade and the arch would stop being a cut-out. Forty-two metres of Bharatpur sandstone, a nine-metre slot, and the flame under it the only warm mark I allowed.
india gate from kartavya path, a little left of the axis, the empty chhatri small behind it
painted by Claude Opus 5p5 2.3.2 · brush 2.2.2 · 2026-08-30
// composition: India Gate from Kartavya Path, standing a little LEFT of the axis so the monument's
// west flank turns away in shade and the arch is not a symmetrical cut-out; the empty Lutyens chhatri
// sits small and pale behind it to the right. The arch stands left of the print's centre; the lawn and
// the two ornamental water channels converge to its foot. Above and around, bare paper — no sky.
// four facts: (1) PROPORTION — 42 m tall, ~25 m wide, and the opening is only 9.1 m by 22.6 m, so the
// two piers are nearly as broad as the void and the void is a tall slot, not a hole; (2) ORDERING —
// stepped base, plain pier, round-headed arch, plain moulded band, heavy projecting cornice, plain
// attic, then a SHALLOW wide bowl on top (a saucer, not a hemisphere); (3) MATERIAL — Bharatpur
// sandstone: the lit front face a sand half-plate, the shaded flank a sand plate under an ink
// over-plate; (4) SITE — it stands on lawn between the two water channels of Kartavya Path, and
// nothing stands behind it but air.
// counts drawn: 1 arch, 2 piers, 2 ruled recessed panels each with 1 shallow niche, 2 rules with the
// inscription band left as bare paper (NO letterforms), 1 bowl-dome, 1 chhatri on 4 columns,
// 2 water channels, 26 visitor ticks, 1 ice-cream cart, 1 gilt flame.
// layering: paper flecks, the chhatri, lawn and channels, the stepped base, the lit front face, the
// flank in shade, the arch reveal and soffit, cornice / attic / bowl, ruled ink and niches, the
// visitors and the cart, then the last darks and the one gilt mark.
const PALETTE = [
"#efe6d2", // paper — warm cream sheet
"#2f3a44", // ink — slate-navy line and shadow plate
"#d4b483", // sand — Bharatpur sandstone
"#7a8c6a", // moss — the lawns of Kartavya Path
"#5d7f88", // verdigris — the two ornamental water channels
"#c9a24a", // gilt — the Amar Jawan Jyoti, the one warm accent
];
const GY = 638; // ground: top of the stepped base
const AX0 = 220, AX1 = 445; // the front face, 225px = ~25 m
const OX0 = 292, OX1 = 373; // the opening, 81px = 9.1 m
const OCX = 332.5, OR = 40.5, SPRING = 477; // the round arch springs here
const CROWN = 436; // 202px above ground = 22.6 m
const FACE_TOP = 368; // underside of the heavy cornice
const CORN_T = 344, ATT_T = 300, PAR_T = 291, DRUM = 283, BOWL_T = 259;
const FX = 198; // the back edge of the shaded west flank
const g = (m, sd, lo, hi) => constrain(randomGaussian(m, sd), lo, hi);
const shift = (pts, dx, dy) => pts.map((p) => [p[0] + dx, p[1] + dy]);
const box = (x, y, w, h) => [[x, y], [x + w, y], [x + w, y + h], [x, y + h]];
// a solid grainy plate — the letterpress solid. noStroke: a plate never carries the last pen's outline.
const plate = (pts, col, w, dist, ang, rnd) => {
brush.noStroke();
brush.noFill();
brush.hatchStyle("charcoal", col, w);
brush.hatch(dist, ang, { rand: rnd, continuous: false, gradient: 0 });
brush.polygon(pts);
brush.noHatch();
};
// a half-tone plate — two crossed cpencil passes, paper breathing through
const halfPlate = (pts, col, w, dist, ang) => {
brush.noStroke();
brush.noFill();
brush.hatchStyle("cpencil", col, w);
brush.hatch(dist, ang, { rand: 0.25, continuous: false, gradient: 0 });
brush.polygon(pts);
brush.hatch(dist * 1.12, ang - 84, { rand: 0.25, continuous: false, gradient: 0 });
brush.polygon(pts);
brush.noHatch();
};
// a fading plate — dense at one edge, open at the other
const fadePlate = (pts, col, w, dist, ang, grad) => {
brush.noStroke();
brush.noFill();
brush.hatchStyle("charcoal", col, w);
brush.hatch(dist, ang, { rand: 0.3, continuous: false, gradient: grad });
brush.polygon(pts);
brush.noHatch();
};
const ink = (x1, y1, x2, y2, w, name, col) => {
brush.noFill();
brush.set(name || "rotring", col || PALETTE[1], w || 1.0);
brush.line(x1, y1, x2, y2);
};
// a dark niche / opening slot
const slot = (x, y, w, h) => plate(box(x, y, w, h), PALETTE[1], 1.1, 1.5, 90, 0.2);
// every quad of the west flank gets the same two passes, so the shaded side reads as one plane
const westFace = (pts) => {
plate(pts, PALETTE[2], 1.5, 2.2, 90, 0.3);
plate(shift(pts, 1.5, 1), PALETTE[1], 1.15, 2.7, 94, 0.3);
};
// a shallow saucer profile — flat at the crown, steep at the springing: the India Gate bowl
const saucer = (cx, baseY, hw, h, t0, t1) => {
const pts = [];
for (let i = 0; i <= 14; i++) {
const u = (t0 + (t1 - t0) * (i / 14)) * 2 - 1;
pts.push([cx + u * hw, baseY - h * Math.sqrt(Math.max(0, 1 - u * u))]);
}
pts.push([cx + (t1 * 2 - 1) * hw, baseY], [cx + (t0 * 2 - 1) * hw, baseY]);
return pts;
};
function setup() {
createCanvas(800, 800, WEBGL);
angleMode(DEGREES);
brush.scaleBrushes(2.4);
noLoop();
}
function draw() {
translate(-width / 2, -height / 2);
background(PALETTE[0]);
// 0 — paper flecks: faint warm specks so the sheet is not dead, never dark
for (let i = 0; i < 220; i++) {
const x = random(10, 790), y = random(10, 790);
ink(x, y, x + g(1.4, 0.5, 0.5, 2.6), y + g(0, 0.4, -1, 1), g(0.45, 0.1, 0.3, 0.6), "2H", random() < 0.7 ? "#bfb39a" : PALETTE[2]);
}
// 1 — the back plane: Lutyens' empty chhatri, small and pale, behind the arch and to the RIGHT
// (standing left of the axis pushes the distant canopy off to that side)
const KX = 496, KB = 612, KT = 576;
halfPlate(box(KX + 2, KT, 44, KB - KT), PALETTE[2], 1.0, 3.0, 66);
for (let i = 0; i < 4; i++) ink(KX + 4 + i * 13, KT + 2, KX + 4 + i * 13, KB - 1, 0.9, "pen");
plate(box(KX - 4, KT - 9, 56, 9), PALETTE[2], 1.2, 2.0, 0, 0.25); // the canopy entablature
ink(KX - 5, KT - 9, KX + 53, KT - 9, 1.0);
const kDome = saucer(KX + 24, KT - 9, 21, 15, 0, 1);
halfPlate(kDome, PALETTE[2], 1.1, 2.4, 58);
plate(shift(kDome.slice(0, 5), 1, 1), PALETTE[1], 0.95, 4.2, 40, 0.3); // its shaded left cheek
ink(KX + 24, KT - 24, KX + 24, KT - 29, 1.2, "charcoal"); // the finial
halfPlate(box(KX - 12, 606, 84, 10), PALETTE[3], 1.0, 3.2, 42); // the grass it stands on
// 2 — the ground: one lawn strip the print stands on, then the two water channels converging
halfPlate(box(168, 640, 498, 18), PALETTE[3], 1.25, 2.5, 34);
halfPlate(box(430, 641, 232, 11), PALETTE[3], 1.1, 3.0, 52); // the lawn running away to the right
for (let i = 0; i < 22; i++) {
const x0 = 164 + i * 23 + g(0, 2, -5, 5);
ink(x0, 640 + g(0, 0.6, -1.4, 1.4), x0 + g(13, 4, 5, 22), 640 + g(0, 0.6, -1.4, 1.4), g(0.85, 0.2, 0.5, 1.2), "pen", PALETTE[3]);
}
// the two ornamental channels: ruled lengthwise, converging on the foot of the arch
const chan = [[152, 196, 686, 262, 274, 651], [656, 598, 686, 412, 400, 651]];
for (let c = 0; c < chan.length; c++) {
const q = chan[c];
const quad = [[q[3], q[5]], [q[4], q[5]], [q[1], q[2]], [q[0], q[2]]];
fadePlate(quad, PALETTE[4], 1.3, 2.8, 0, 0.55);
for (let i = 0; i < 8; i++) {
const s = 0.05 + i * 0.13;
const nx = q[0] + (q[1] - q[0]) * s, fx = q[3] + (q[4] - q[3]) * s;
const cut = g(0.2, 0.12, 0, 0.42); // the ruling breaks before it reaches the far end
ink(nx + g(0, 1.2, -3, 3), q[2] + g(0, 0.7, -1.6, 1.6), nx + (fx - nx) * (1 - cut), q[2] + (q[5] - q[2]) * (1 - cut),
g(1.15, 0.3, 0.65, 1.75), random() < 0.6 ? "2B" : "cpencil", random() < 0.8 ? PALETTE[4] : PALETTE[1]);
}
ink(q[0], q[2] - 1, q[3], q[5], 1.05, "pen");
ink(q[1], q[2] - 1, q[4], q[5], 0.9, "pen");
}
// 3 — the low stepped base, wider than the piers, with its own sliver of flank
plate(box(212, GY, 241, 7), PALETTE[2], 1.3, 1.8, 0, 0.25);
plate(box(204, GY + 7, 257, 8), PALETTE[2], 1.25, 2.0, 0, 0.28);
westFace([[212, GY], [190, GY - 2], [190, GY + 5], [212, GY + 7]]);
westFace([[204, GY + 7], [182, GY + 5], [182, GY + 12], [204, GY + 15]]);
ink(202, GY + 15, 462, GY + 15, 1.3);
ink(182, GY + 12, 204, GY + 15, 1.0);
// 4 — the lit front face: two broad piers and the masonry over the arch, all one sandstone plane
const leftPier = box(AX0, FACE_TOP, OX0 - AX0, GY - FACE_TOP);
const rightPier = box(OX1, FACE_TOP, AX1 - OX1, GY - FACE_TOP);
const crownBlock = box(OX0, FACE_TOP, OX1 - OX0, CROWN - FACE_TOP);
const spandrelL = [[OX0, CROWN], [OCX, CROWN]];
const spandrelR = [[OX1, CROWN], [OCX, CROWN]];
for (let i = 7; i <= 14; i++) {
const a = (i / 14) * Math.PI;
spandrelL.push([OCX + Math.cos(a) * OR, SPRING - Math.sin(a) * OR]);
}
for (let i = 7; i >= 0; i--) {
const a = (i / 14) * Math.PI;
spandrelR.push([OCX + Math.cos(a) * OR, SPRING - Math.sin(a) * OR]);
}
const litFaces = [leftPier, rightPier, crownBlock, spandrelL, spandrelR];
const litAng = [72, 68, 76, 64, 70];
for (let i = 0; i < litFaces.length; i++) {
halfPlate(litFaces[i], PALETTE[2], 1.4, 2.2, litAng[i]);
plate(litFaces[i], PALETTE[2], 1.25, 3.1, 90, 0.3); // a thin second pass so the stone reads solid
}
// 5 — the west flank, turned away from the sun: sandstone under an open ink over-plate
westFace([[AX0, FACE_TOP], [FX, 382], [FX, 636], [AX0, GY]]);
ink(AX0, FACE_TOP, FX, 382, 1.0);
// 6 — the arch: a tall slot. The soffit and the far inner reveal are the only darks inside it,
// and the opening beyond stays bare paper.
const soffit = [];
for (let i = 0; i <= 12; i++) {
const a = (i / 12) * Math.PI;
soffit.push([OCX + Math.cos(a) * OR, SPRING - Math.sin(a) * OR]);
}
for (let i = 12; i >= 0; i--) {
const a = (i / 12) * Math.PI;
soffit.push([OCX + Math.cos(a) * (OR - 13), SPRING - Math.sin(a) * (OR - 13)]);
}
fadePlate(soffit, PALETTE[1], 1.15, 2.8, 12, 0.55);
plate(box(OX1 - 14, SPRING - 6, 14, GY - SPRING + 6), PALETTE[1], 1.25, 2.6, 88, 0.3); // the far reveal
plate(box(OX0, SPRING - 2, 6, GY - SPRING + 2), PALETTE[1], 1.0, 3.6, 92, 0.3); // a nick on the near jamb
for (let i = 0; i < 12; i++) {
const a = (i / 11) * Math.PI;
const x = OCX + Math.cos(a) * OR, y = SPRING - Math.sin(a) * OR;
const a2 = ((i + 1) / 11) * Math.PI;
ink(x, y, OCX + Math.cos(a2) * OR, SPRING - Math.sin(a2) * OR, 0.85, "pen"); // the intrados, ruled
}
ink(OX0 - 5, SPRING, OX0 + 9, SPRING, 1.1); // the impost blocks
ink(OX1 - 9, SPRING, OX1 + 5, SPRING, 1.1);
// 7 — the plain moulded band (LEFT AS BARE PAPER — no letterforms), then the heavy cornice
ink(AX0 - 1, 414, AX1 + 1, 414, 1.3);
ink(AX0 - 1, 396, AX1 + 1, 396, 1.3);
ink(AX0 - 1, 411, AX1 + 1, 411, 0.7, "pen");
ink(AX0 + 3, FACE_TOP + 16, AX0 + 3, 418, 0.7, "pen"); // faint pier arris
ink(AX1 - 3, FACE_TOP + 16, AX1 - 3, 418, 0.7, "pen");
const cornice = box(212, CORN_T, 241, FACE_TOP - CORN_T);
halfPlate(cornice, PALETTE[2], 1.35, 2.0, 58);
plate(cornice, PALETTE[2], 1.2, 3.1, 90, 0.3);
halfPlate([[212, CORN_T], [232, CORN_T], [214, 362], [194, 362]], PALETTE[2], 1.15, 2.4, 20); // its top surface
westFace([[212, CORN_T], [194, 362], [194, 382], [212, FACE_TOP]]);
ink(212, FACE_TOP, 194, 382, 1.1); // the soffit it throws, ruled rather than plated
fadePlate(box(AX0, FACE_TOP, AX1 - AX0, 12), PALETTE[1], 1.0, 3.4, 0, 0.6); // shadow the cornice throws
ink(210, CORN_T, 455, CORN_T, 1.4);
ink(210, FACE_TOP, 455, FACE_TOP, 1.3);
ink(212, CORN_T + 12, 453, CORN_T + 12, 0.75, "pen");
// 8 — the plain attic, its parapet, and the shallow bowl-dome: a low saucer, never a hemisphere
const attic = box(232, ATT_T, 201, CORN_T - ATT_T);
halfPlate(attic, PALETTE[2], 1.35, 2.2, 74);
plate(attic, PALETTE[2], 1.2, 3.1, 88, 0.3);
westFace([[232, ATT_T], [214, 318], [214, 362], [232, CORN_T]]);
ink(230, ATT_T, 435, ATT_T, 1.2);
ink(232, CORN_T, 433, CORN_T, 0.8, "pen");
plate(box(226, PAR_T, 213, ATT_T - PAR_T), PALETTE[2], 1.4, 1.9, 0, 0.25);
westFace([[226, PAR_T], [211, 309], [211, 318], [226, ATT_T]]);
ink(224, PAR_T, 441, PAR_T, 1.3);
// the bowl: a drum ring, then a SHALLOW saucer — 104 wide and only 24 deep
plate(box(OCX - 57, DRUM, 114, PAR_T - DRUM), PALETTE[2], 1.35, 1.9, 0, 0.25);
ink(OCX - 58, DRUM, OCX + 58, DRUM, 1.15);
const rise = (u) => DRUM - (DRUM - BOWL_T) * Math.sqrt(Math.max(0, 1 - u * u));
const bowlL = saucer(OCX, DRUM, 52, DRUM - BOWL_T, 0, 0.46);
const bowlR = saucer(OCX, DRUM, 52, DRUM - BOWL_T, 0.4, 1);
halfPlate(bowlR, PALETTE[2], 1.35, 2.0, 62);
plate(bowlL, PALETTE[2], 1.45, 2.1, 96, 0.3);
plate(shift(bowlL, 1.5, 1), PALETTE[1], 0.9, 4.6, 100, 0.3);
for (let i = 0; i < 12; i++) {
const u0 = -1 + i / 6, u1 = -1 + (i + 1) / 6;
ink(OCX + u0 * 52, rise(u0), OCX + u1 * 52, rise(u1), 0.95); // the saucer ruled, so it reads drawn
}
for (let i = 0; i < 3; i++) {
const u = -0.52 + i * 0.52;
ink(OCX + u * 52, rise(u), OCX + u * 15, BOWL_T + 2, 0.7, "pen");
}
// 9 — the four shallow niches on the piers, and the low plinth mould
const pierC = [256, 409];
for (let p = 0; p < 2; p++) {
const c = pierC[p];
ink(c - 27, 474, c + 27, 474, 0.8, "pen"); // the shallow recessed panel, ruled and left bare
ink(c - 27, 590, c + 27, 590, 0.8, "pen");
ink(c - 27, 474, c - 27, 590, 0.75, "pen");
ink(c + 27, 474, c + 27, 590, 0.75, "pen");
const nx = c - 3.5 + g(0, 0.4, -1, 1);
plate(box(nx, 490, 7, 16), PALETTE[1], 1.15, 2.3, 90, 0.25); // one shallow niche, high on the panel
ink(nx - 2, 488, nx + 9, 488, 0.8, "pen");
ink(c - 20, 566, c + 20, 566, 0.7, "pen"); // and a moulding low across it
}
ink(AX0 - 1, 600, AX1 + 1, 600, 1.0);
ink(FX, 602, AX0, 600, 0.8, "pen");
// 10 — the visitors: charcoal ticks along the lawn, a few nearer and taller on the path
const near = [232, 241, 250, 269, 301, 317, 349, 361, 389, 401, 419, 437, 453, 471, 487, 513, 541, 597, 625, 649];
for (let i = 0; i < near.length; i++) {
const x = near[i], h = g(7.5, 1, 6, 9.5);
ink(x, 656, x + g(0, 0.5, -1.1, 1.1), 656 - h, g(1.6, 0.15, 1.35, 1.9), "charcoal");
}
const front = [259, 271, 344, 356, 368, 505];
for (let i = 0; i < front.length; i++) {
const x = front[i], h = g(11.5, 1.2, 9.5, 14);
ink(x, 681, x + g(0, 0.6, -1.4, 1.4), 681 - h, g(1.9, 0.2, 1.55, 2.25), "charcoal");
}
// one ice-cream cart out on the paved path, its parasol a bar of ink
halfPlate(box(424, 664, 30, 13), PALETTE[2], 1.3, 1.9, 52);
ink(422, 664, 456, 664, 1.2);
ink(424, 677, 452, 677, 0.9, "pen");
ink(429, 677, 429, 683, 2.0, "charcoal");
ink(448, 677, 448, 683, 2.0, "charcoal");
ink(439, 663, 439, 645, 1.0, "pen");
ink(424, 645, 455, 645, 1.9, "charcoal");
// 11 — last darks: the crisp ends of the mass, the shade pooling at the pier feet
fadePlate(box(AX0 - 1, GY - 32, OX0 - AX0 + 1, 32), PALETTE[1], 0.95, 3.8, 0, 0.7);
fadePlate(box(OX1, GY - 32, AX1 - OX1 + 1, 32), PALETTE[1], 0.95, 3.8, 0, 0.7);
ink(AX0, FACE_TOP, AX0, GY, 1.0);
ink(AX1 + 1, FACE_TOP, AX1 + 1, GY, 1.45);
ink(FX, 382, FX, 636, 1.15);
ink(OX0 - 1, SPRING, OX0 - 1, GY, 1.05);
ink(OX1 + 1, SPRING, OX1 + 1, GY, 1.25);
ink(AX1 + 1, GY, 462, GY + 4, 1.0);
// 12 — the Amar Jawan Jyoti under the arch: a black plinth and the one gilt mark on the sheet
plate(box(325, 622, 15, 16), PALETTE[1], 1.35, 1.6, 90, 0.2);
ink(332.5, 621, 332.5, 610, 2.4, "charcoal", PALETTE[5]);
ink(329, 615, 336, 615, 1.6, "charcoal", PALETTE[5]);
}