Truchet
one tile per grid cell, turned by a seeded choice, with both built-in tiles sharing the canvas: quarter arcs weave meandering loops on the left, corner-to-corner diagonals cut maze corridors on the right, and a flow field sweeps hue along both (truchet)
- Run
swift run --package-path Examples Example-Patterns-Truchet- Source
- Examples/Patterns/Truchet/Sketch.swift
import Ollin
/// Truchet tiling: one tile design on every cell of a grid, each spun to a
/// random orientation. Both built-in tiles share the canvas: on the left, the
/// `.arcs` tile joins the cell's edge midpoints with two quarter-circles, so
/// the arcs meet across cell borders and a wall of random spins reads as
/// smooth, meandering loops; on the right, the `.diagonals` tile draws one
/// corner-to-corner stroke per cell, and the same random spins read as a maze
/// of corridors.
///
/// The tilings are pure functions of the seed, so they're computed once and
/// held; what moves is a flow field that shifts each contour's color, so waves
/// of hue travel along the connected curves and corridors alike. Each piece is
/// an ordinary `Contour`, so the same line-work would stroke, hatch, or export
/// to SVG for a pen plotter.
@main
final class TruchetTiles: Sketch {
private var pieces: [Contour] = []
override func draw() {
if pieces.isEmpty {
seed(3)
let left = Rectangle(x: 0, y: 0, width: width / 2, height: height)
let right = Rectangle(x: width / 2, y: 0, width: width / 2, height: height)
pieces = truchet(in: left, columns: 6, rows: 12, tile: .arcs)
+ truchet(in: right, columns: 6, rows: 12, tile: .diagonals)
}
background(Color(hex: 0x0E1116))
noFill()
strokeCap(.round)
strokeWeight(11 * scale)
let a = Color(hex: 0x2EC4B6) // teal
let b = Color(hex: 0xF6511D) // ember
for piece in pieces {
// A flow through the field shifts each piece's color; since the
// marks connect across cells, the hue sweeps along the loops and
// corridors as waves.
let mid = piece.points[piece.points.count / 2]
let flow = signedNoise(mid.x * 0.003, mid.y * 0.003, time * 0.9)
stroke(Color.mix(a, b, (flow + 1) * 0.5))
drawPolyline(piece.points, closed: false)
}
}
}