DEV Community

stepinto.dev
stepinto.dev

Posted on Edited on Originally published at stepinto.dev

Cut Tile and Poured Cement

It was all broken by me really, or built like a clumsy caveman

Trying to have something right afterwards

The two tile walls I wrote up last time are painted: a brush drifts, a wash pools, an ink line goes on top. These two aren't painted at all. Alicatado is cut: every piece is chipped out of a fired, glazed tile with a hammer and bedded in lime next to its neighbours, the way the dados of the Alhambra were made. Hidráulico is pressed: pigmented cement poured into a brass divider, lifted, pressed and left to cure, never fired, the way every hallway in Spain was floored between 1880 and 1960.

I keep asking the same question from different sides. The first two pages were about what a rule looks like once a hand has painted it, and these are about what it looks like once a material has been through it.

A wall of eight-point stars in blue, black, honey and purple glazed tile, with white crosses and small green squares between, every piece edged by pale mortar

The mexuar preset. Octagons and squares underneath, θ at 45 degrees, and every region a piece.

The geometry is borrowed

Alicatado draws nothing new. The pattern comes straight from Çini, which puts a contact point on every edge of a hidden tiling, fires two rays from each at an angle θ, and draws the pattern where the rays collide. Walk the faces of that line web and you have a list of polygons, which Çini colours by class and calls a mosaic.

That was the bit I kept coming back to. Çini's mosaic mode already insets every face a little and calls the gap grout, and its Alhambra palette already cycles glazes by position. It was most of the way to cut tile without ever treating a face as a thing you could pick up. So the new page uses the same polygons, and all the work is in what happens to each one afterwards.

The cutter

A piece on a real alicatado wall is cut by hand to a drawing, and it misses the drawing in four ways. It's set a fraction off where it should be, and turned a fraction. Its corners are nicked. Its long edges bow, because a hammer doesn't cut straight. So every face gets a shift, a turn, a jitter on each vertex and a bow on any edge longer than half a unit, all scaled by a slider called cut, and all drawn from a random generator seeded by the face's position, so the same piece is wrong the same way every time you pan back to it.

Then there's the mortar. Çini shrinks a face towards its centroid to make the joint, which is fine for a square and wrong for a star. Scaling a star towards its centre moves the points a long way and the inner corners hardly at all, so the mortar is wide at the tips and thin in the notches. A real joint is the same width everywhere. The fix is a mitred offset: at each vertex, move inward along the bisector of the two edge normals by the joint width over the cosine of the half angle, clamped so a very sharp point can't shoot off to infinity.

function offsetPoly(poly, d) {
  const n = poly.length, out = [];
  for (let i = 0; i < n; i++) {
    const p = poly[(i + n - 1) % n], v = poly[i], q = poly[(i + 1) % n];
    // unit edge directions, then their inward normals (the polygon is CCW)
    let e1x = v[0] - p[0], e1y = v[1] - p[1], l1 = Math.hypot(e1x, e1y) || 1;
    let e2x = q[0] - v[0], e2y = q[1] - v[1], l2 = Math.hypot(e2x, e2y) || 1;
    e1x /= l1; e1y /= l1; e2x /= l2; e2y /= l2;
    const n1x = -e1y, n1y = e1x, n2x = -e2y, n2y = e2x;
    let bx = n1x + n2x, by = n1y + n2y, bl = Math.hypot(bx, by);
    if (bl < 1e-6) { bx = n1x; by = n1y; bl = 1; }
    bx /= bl; by /= bl;
    const cosHalf = bx * n1x + by * n1y;
    const m = Math.min(d / Math.max(cosHalf, 0.2), Math.min(l1, l2) * 0.49);
    out.push([v[0] + bx * m, v[1] + by * m]);
  }
  return out;
}
Enter fullscreen mode Exit fullscreen mode

That's the whole cutter, twenty lines, and it's what makes a twelve-point wheel look set into a wall rather than drawn on one.

Each piece came from a different tile

The pieces of a cut-tile wall were chipped from many tiles, fired in many batches, so no two are quite the same colour. Every piece shifts its hue, saturation and lightness a touch from its class colour. On top of that goes a mottle, a soft radial cloud of the same glaze darker or lighter where it ran thick. Then the lustre: a glazed surface is glossy, so each piece gets a small highlight on the side nearer the light, with the light's direction on a slider.

The pieces also stand proud of the mortar, and the edges are what sell that. For each side of the inset polygon, take its outward normal and dot it with the light direction. Facing the light, stroke a thin pale line; facing away, a thin dark one, with the alpha scaled by the dot product. Nothing is actually raised, but at reading distance the wall has relief, and if you drag the light slider round the relief moves the way it should.

A close view of cut tile: white crosses with green centres, blue and black stars, fine crazing in the white glaze, and one piece missing to show the combed mortar bed beneath

Close, with wear on. The crazing is in the white glaze, where it shows. The missing piece shows the bed, combed by a trowel, with a shadow cast onto it by the pieces still standing.

Wear is the last layer, and I got it wrong the first time. A missing piece was a flat patch of mortar colour and a repaired piece was a random glaze from the palette, and both read as mistakes rather than history. Now a missing piece is sunk: darker, grainy, combed, with a shadow along the edges that face the light. A repair keeps its own colour and just looks newer, a touch brighter and glassier, with no crazing. The crazing itself only goes on about a third of the pieces, which is enough.

The pajarita

The Alhambra's most famous alicatado isn't a star pattern at all. It's the pajarita, the wall of birds, hexagons and stars in the p3 symmetry group with no mirrors, so every bird is the same hand. Çini draws it directly, with one S-shaped Bézier curve splitting every rhombus into two crescents. For Alicatado I sample each curve into ten points, so a crescent is a polygon like everything else and goes through the same cutter. The hexagons and stars sit over the birds, so they paint their own mortar first: a wide stroke of lime around the piece, then the inset fill on top.

Interlocking bird shapes in cream, black, honey, green and blue around white hexagons and small stars in purple, black and green

Pajaritos. Every curve is a polygon now, and every bird a piece.

Then cement

Hidráulico is the opposite kind of page. Alicatado used none of the azulejeria engine and Hidráulico uses all of it, exactly as Azulejería and Jerez do. The only thing that changes is what the tile is made of.

A cement tile isn't painted, so there's no wash and no ink line. The pigment goes into a brass divider and comes out flat, matte, and butted straight against the next colour with no outline between them. The divider is metal, so edges are straight. The only hand in it is the bleed: a fraction of a millimetre where one pigment crept under the divider before it lifted. The surface is cement, so it has grain and cures a little unevenly. It doesn't craze, but it wears, and it wears where people walk.

So the engine now takes a material, an object of optional hooks that change what the tile is made of without touching what is drawn on it:

const material = {
  ampOf: hand => 0.0015 * hand,            // the mould is brass; the hand is only bleed
  shape(g, pts, col, b) {                  // flat fill, then the pigment that crept under
    trace(g, pts, true);
    g.fillStyle = col; g.fill();
    const bleed = b.amp * 7;
    if (bleed > 0.0005) {
      g.strokeStyle = col; g.lineWidth = bleed * (0.6 + 0.8 * b.rng());
      g.globalAlpha = 0.35; g.stroke(); g.globalAlpha = 1;
    }
  },
  surface(g, S, pal, rng) { /* grain, and the cast of an uneven cure */ },
  plain(g, S, pal, rng) { /* a checker's plain tile is solid pigment */ },
  lay: { shift: 0.004, turn: 0.003 },      // laid tight, machine square
  gapOf: S => Math.max(0.8, S * 0.01),     // a hairline joint
  age(ctx, t) {                            // the pigment dulls along the line people walk
    const walk = Math.exp(-((t.cy / (t.S * 2.6)) ** 2));
    const w = 0.05 + 0.85 * walk + (t.rng() - 0.5) * 0.12;
    ctx.fillStyle = hexA(t.pal.glaze, Math.min(0.6, w * 0.6));
    ctx.fillRect(-t.s / 2, -t.s / 2, t.s, t.s);
    // then scuffs, the odd crack, a corner chipped to the grey beneath
  },
};
Enter fullscreen mode Exit fullscreen mode

shape, line and dot replace the brush's strokes. surface lays the ground, plain paints the tile a checker alternates with, lay is how far a tile strays from its cell, gapOf is the joint, and age is drawn over each tile in its own frame when age is on, with the tile's world position passed in so wear can follow a line through the floor rather than a line through the screen. Without a material, every hook falls back to the glazed behaviour.

A floor of burgundy cement tiles on cream: octagonal frames around four-petal flowers, concentric rings at the corners, a grid of burgundy lines through every join

The zaguán preset. Flat burgundy and grey, straight edges, and a joint you can barely see.

A grey cement floor of nested squares, paler and scuffed along a band through the middle where it has been walked, with a few cracks

Bodega, with wear on. The paler band through the middle is the walked line.

The design never finds out. None of the hooks read the design's random generator, so a material can't move a motif, and the old walls are untouched by construction. I checked anyway: I hashed the canvas bytes of every Azulejería and Jerez preset, two query-string walls with age and checker on, and every thumbnail in every panel, before and after the change, and all twenty-two were identical. The package is at 1.1.0 and the README has the hooks.

Cream cement tiles each carrying an eight-point star in ochre inside a green diamond and a brown ring, with brown stars where four tiles meet

Casino. Every tile whole, the star at its centre, and a second star made by four corners.

What the two pages taught the engine

Alicatado is the more interesting of the two for the package, because it doesn't use it and still ended up rewriting half of it. Not the tile half: the drag, the pinch, the wheel, the double tap, the buffered repaint that lets you pan without recomputing the world, the panel with its tabs and thumbnails, the query string, the seeded random and the colour helpers. All of that is the same on every page, and Alicatado has its own copy because the engine only offers it bundled with a grid of square tiles.

So the next version of the engine draws its line somewhere else. A viewer: a canvas you paint a world into, with all the interaction and the panel. And on top of it, a tile wall, which is one paint function and the materials. Alicatado becomes the viewer plus its own paint function. So would a trencadís page, or a Roman mosaic, which is where the cutter would get reused. That's a breaking change, so I waited until there were three materials to design it against instead of one.

A dense zellige of small cut pieces on a near-black ground: stars in gold, turquoise, terracotta and green, with pale mortar between

The fez preset. Small pieces, dark ground, the mortar doing most of the drawing.

Top comments (0)