Ollin

Girih

Islamic star patterns by the polygons-in-contact method: a honeycomb's strapwork changes shape as the contact angle sweeps, under a girih-tile medallion of a decagon and pentagons at the classic 54 degrees (girihPattern, Girih.Tile)

Run
swift run --package-path Examples Example-Patterns-Girih
Source
Examples/Patterns/Girih/Sketch.swift
import Ollin

/// Islamic star patterns by the polygons-in-contact method: every tile edge
/// midpoint sprouts a pair of rays at the contact angle, and where rays meet,
/// the strapwork is born. The background sweeps the contact angle over a
/// honeycomb, morphing the same tiling from spiky stars to a woven lattice;
/// the medallion is the girih-tile flower (a decagon ringed by ten pentagons)
/// at the classic 54 degrees.
@main
final class GirihStars: Sketch {
    private let period = 12.0
    override var loopDuration: Double? { period }

    private var hexes: [[Vector2]] = []
    private var flower: [[Vector2]] = []

    override func setup() {
        // A honeycomb over an expanded rectangle, so cells cover the whole
        // canvas instead of letterboxing inside it.
        let expanded = Rectangle(center: center,
                                 width: width * 1.3, height: height * 1.3)
        hexes = HexGrid(in: expanded, columns: 13, rows: 12).cells.map(\.corners)

        // The flower: a decagon with a pentagon laid on each edge. Girih
        // tiles share one edge length, so walking each decagon edge backward
        // lands a pentagon snug against it, on the outside.
        let edge = width * 0.052
        let decagon = Girih.Tile.decagon.points(edge: edge, at: center)
        flower = [decagon]
        for i in decagon.indices {
            let p = decagon[i], q = decagon[(i + 1) % decagon.count]
            flower.append(Girih.Tile.pentagon.points(onEdge: q, p))
        }
    }

    override func draw() {
        background(Color(hex: 0x101418))

        // The honeycomb strapwork, contact angle swinging over the loop.
        let angle = 35 + pingPong(over: period) * 35   // 35...70 degrees
        noFill()
        stroke(Color(hex: 0x2EC4B6).withAlpha(0.8))
        strokeWeight(2.5 * scale)
        strokeCap(.round)
        drawGirih(over: hexes, angle: angle)

        // The girih-tile medallion at the classic angle.
        fill(Color(hex: 0x101418).withAlpha(0.85))
        noStroke()
        for tile in flower { drawPolygon(tile) }
        noFill()
        stroke(Color(hex: 0xFCA311))
        strokeWeight(3.5 * scale)
        drawGirih(over: flower, angle: 54)
    }
}

↑↓ move ↩ open