Geometric Tessellation
About This Sketch
A grid of diamonds rotates in synchronized waves, creating mesmerizing geometric patterns. The position-based rotation offset makes the pattern flow across the canvas like a visual wave.
Tessellation is fundamental to art and mathematicsโfrom Islamic geometric patterns to Escher's impossible tilings. This sketch combines classic tessellation with modern animation to create an ever-evolving kaleidoscope.
Algorithm
A tessellating pattern of rotating diamonds that creates a hypnotic kaleidoscope effect. Each cell rotates at a slightly different rate based on its position in the grid.
**Key Concepts:**
- **Tessellation**: Repeating pattern that tiles a plane without gaps
- **Transformation Matrix**: Translate to cell center, then rotate
- **Position-Based Variation**: Rotation offset depends on grid coordinates
- **Nested Shapes**: Concentric diamonds create depth
- **Spatial Color Mapping**: Color determined by position in grid
**How it works:**
1. Divide canvas into regular grid of cells
2. For each cell, translate to its center point
3. Calculate rotation based on base angle + position offset
4. This creates wave-like rotation propagation across grid
5. Draw outer diamond shape
6. Draw inner diamond for visual richness
7. Choose color based on cell's position in grid
8. Increment base rotation each frame
Pseudocode
SETUP:
rotation = 0
gridSize = 40
DRAW (every frame):
CLEAR background
FOR x = 0 to canvas_width STEP gridSize:
FOR y = 0 to canvas_height STEP gridSize:
SAVE transformation
MOVE to (x + gridSize/2, y + gridSize/2)
cell_rotation = rotation + (x + y) ร 0.01
ROTATE by cell_rotation
position_sum = x + y
color = gradient based on position_sum
DRAW outer diamond shape
DRAW inner diamond shape
RESTORE transformation
rotation = rotation + 0.01
Source Code
let sketch = function(p) {
let rotation = 0;
p.setup = function() {
p.createCanvas(400, 300);
p.colorMode(p.RGB);
};
p.draw = function() {
const colors = getThemeColors();
p.background(...colors.bg);
let gridSize = 40;
for (let x = 0; x < p.width; x += gridSize) {
for (let y = 0; y < p.height; y += gridSize) {
p.push();
p.translate(x + gridSize/2, y + gridSize/2);
// Different rotation based on position
let cellRotation = rotation + (x + y) * 0.01;
p.rotate(cellRotation);
// Color based on position
let t = p.map(x + y, 0, p.width + p.height, 0, 1);
let col = t < 0.33 ? colors.accent1 :
t < 0.66 ? colors.accent2 : colors.accent3;
p.noFill();
p.stroke(...col);
p.strokeWeight(2);
// Draw diamond
p.beginShape();
p.vertex(0, -gridSize/2.5);
p.vertex(gridSize/2.5, 0);
p.vertex(0, gridSize/2.5);
p.vertex(-gridSize/2.5, 0);
p.endShape(p.CLOSE);
// Inner diamond
p.beginShape();
p.vertex(0, -gridSize/5);
p.vertex(gridSize/5, 0);
p.vertex(0, gridSize/5);
p.vertex(-gridSize/5, 0);
p.endShape(p.CLOSE);
p.pop();
}
}
rotation += 0.003;
};
};