openprocessing_p5js · HyperbolicTiling
Poincaré Disk Hyperbolic Tessellation
Escher-style regular hyperbolic tessellation in the Poincaré disk. Builds the {p, q} tiling where p-sided regular polygons meet q at every vertex, valid only when (p-2)(q-2) > 4. Implemented as recursive Möbius reflection: start with a central p-gon, draw it, then for each edge reflect the central polygon across the geodesic that edge subtends, recursing depth times.
Original: https://github.com/looeee/hyperbolic-tiling
▶ Try the live demo (JS port) ▶ Run reference.py via Pyodide 10 formulas have instant JS ports. The Pyodide path runs the actual Python in your browser — first load is ~6 MB, then instant.
Math essence
Reflection across a geodesic whose endpoints on the unit circle are (a, b): R(z) = (c*conj(z) + (a-b)*a) / (conj(c)*z + conj((a-b)*a)) where c = (a-b) / (1 - conj(a)*b). Central polygon radius: cosh(rho) = cos(pi/q) / sin(pi/p). Schlafli deficit: (p-2)(q-2) > 4 required for hyperbolic geometry.
Parameters
| Name | Type | Default | Range | Description |
|---|---|---|---|---|
dim | int | 512 | 200–1200 | Square canvas side length. |
p | int | 7 | 3–24 | Polygon sides per cell. |
q | int | 3 | 3–24 | Cells meeting at each vertex. |
depth | int | 4 | 1–8 | Reflection recursion depth. |
line_alpha | float | 0.85 | 0.05–1 | Edge opacity per stamp. |
bg_color | tuple | 245,240,230 | — | Background canvas color. |
ink_color | tuple | 24,28,56 | — | Edge color. |
max_polys | int | 3500 | 100–20000 | Polygons cap (truncates BFS if exceeded). |
seed | int | null | 0–999999 |
Reference
First 60 lines of reference.py. Full source:
library_external/openprocessing_p5js/HyperbolicTiling/reference.py
from __future__ import annotations
from typing import ClassVar
import numpy as np
def _mobius_reflect_point(z: complex, a: complex, b: complex) -> complex:
"""Reflect complex point ``z`` across the geodesic line through points
``a`` and ``b`` (inside the unit disk).
A Poincaré-disk geodesic is a Euclidean circle orthogonal to the unit
circle. Given two interior points a, b, the unique such circle passing
through them has center ``c`` on the perpendicular bisector of ab with
the orthogonality constraint ``|c|^2 = |c - a|^2 + 1``. Solving:
Re(conj(a) c) = (|a|^2 + 1) / 2
Re(conj(b) c) = (|b|^2 + 1) / 2
Im(conj(a) c - conj(b) c) free
This is a 2×2 linear system in the real and imaginary parts of c. The
reflection is then inversion in that circle:
R(z) = c + |c - a|^2 / conj(z - c)
Used by Joyce's Hyperbolic Tessellations applet (1995), b5strbal/Escher
(2020), and Beardon, *The Geometry of Discrete Groups*, §3.
"""
if abs(a - b) < 1e-12:
return z
aa = abs(a) ** 2
bb = abs(b) ** 2
rhs_a = (aa + 1.0) * 0.5
rhs_b = (bb + 1.0) * 0.5
A = np.array(
[
[a.real, -a.imag],
[b.real, -b.imag],
],
dtype=np.float64,
)
rhs = np.array([rhs_a, rhs_b], dtype=np.float64)
try:
sol = np.linalg.solve(A, rhs)
except np.linalg.LinAlgError:
return z
c = complex(sol[0], sol[1])
rho2 = abs(c - a) ** 2
dz = z - c
if abs(dz) < 1e-12:
return z
return c + rho2 / np.conj(dz)
class HyperbolicTiling:
"""Escher-style regular hyperbolic tessellation in the Poincaré disk.
Builds the ``{p, q}`` tiling where ``p``-sided regular polygons meet
``q`` at every vertex, valid only when the Schlafli angle deficit
``(p - 2)(q - 2) > 4``. Implemented as a recursive reflection scheme in Try running it locally
The reference implementation is self-contained Python with numpy. Install the package and run:
python library_external/openprocessing_p5js/HyperbolicTiling/reference.py Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.
More from openprocessing · p5.js
Additive Synthesis Waveform Visualisation
openprocessing_p5js · SoundWaveform
Visualisation of additive synthesis: y(t) = A * sum_{i=0..N-1} a_i * sin(2π f_i t + phi_i).
Inverse-distance Attractor Network
openprocessing_p5js · AttractorNetwork
A population of point-agents, each carrying a position and a velocity, mutually attracted by an inverse-distance force F = G / max(d, d_min)^alpha along the displacement vector.
Kaleidoscope Mirror Mandala
openprocessing_p5js · KaleidoscopeMirror
Draws a single wandering line and reflects it across N rotational mirrors around the canvas centre.
Mathematical Rose (Rhodonea) Patterns
openprocessing_p5js · PolarCurves
Overlay of multiple rose (rhodonea) curves in the canonical polar form r = a * cos((n/d) * theta + phase), parametrised by the rational multiplier k = n/d.
Tron Lightcycle Trails
openprocessing_p5js · TronLightcycle
Tron-style lightcycle trails.