complexification_net · boundaries
Boundaries
Boundaries traces gradient-magnitude contours on a fractal Brownian motion noise substrate. An 'edge_field' holds per-pixel ink weight; on each step the field decays everywhere, then re-ignites at every pixel where the gradient of the noise exceeds a threshold. This produces line-art that maps the contours of the noise terrain — soft meandering boundaries like topographic contour lines, or like ink seeping through the high-curvature folds of paper. The piece evokes the same family as Tarbell's 'substrate' (where recursive vein growth lives on a noisy substrate) and 'stitches' (where stitches are pinned along a substrate's contours).
Original: https://web.archive.org/web/20041223174832/http://www.levitated.net/daily/levMainVein.html
▶ 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
Build a 2D fBm value-noise field F(x,y) of dim×dim pixels at `noise_octaves` octaves with persistence p. Compute gradient (gx, gy) = ∇F. Maintain edge field E(x,y). Each step: E *= edge_decay; E[i,j] = 1 if |∇F[i,j]| > edge_threshold and E[i,j] < 0.05; render E onto canvas as semi-transparent ink.
Parameters
| Name | Type | Default | Range | Description |
|---|---|---|---|---|
dim | int | 500 | 150–1000 | Square canvas side length |
noise_scale | float | 0.018 | 0.002–0.1 | Base spatial frequency of noise |
noise_octaves | int | 5 | 1–8 | Number of fBm octaves |
noise_persistence | float | 0.55 | 0.1–0.9 | Amplitude multiplier per octave |
edge_threshold | float | 0.012 | 0.001–0.1 | Gradient magnitude above which a pixel becomes an edge |
edge_decay | float | 0.9 | 0.5–0.999 | Per-step multiplicative decay of edge ink |
edge_init_density | float | 0.001 | 0–0.05 | Initial fraction of pixels with edge ink |
bg_color | tuple | 240,235,225 | null–null | Background RGB |
line_color | tuple | 35,25,45 | null–null | Edge ink RGB |
seed | int | null | 0–999999 | RNG seed |
Reference
First 60 lines of reference.py. Full source:
library_external/complexification_net/boundaries/reference.py
from __future__ import annotations
from typing import ClassVar
import imageio.v2 as imageio
import numpy as np
class Boundaries:
family: ClassVar[str] = "complexification_net"
sketch: ClassVar[str] = "boundaries"
def __init__(
self,
dim: int = 500,
noise_scale: float = 0.018,
noise_octaves: int = 5,
noise_persistence: float = 0.55,
edge_threshold: float = 0.012,
edge_decay: float = 0.90,
edge_init_density: float = 0.001,
bg_color: tuple[int, int, int] = (240, 235, 225),
line_color: tuple[int, int, int] = (35, 25, 45),
seed: int | None = None,
) -> None:
self.dim = dim
self.noise_scale = float(noise_scale)
self.noise_octaves = int(noise_octaves)
self.noise_persistence = float(noise_persistence)
self.edge_threshold = float(edge_threshold)
self.edge_decay = float(edge_decay)
self.edge_init_density = float(edge_init_density)
self.bg_color = np.array(bg_color, dtype=np.uint8)
self.line_color = np.array(line_color, dtype=np.uint8)
self._seed = seed
self.rng = np.random.default_rng(seed)
self.canvas = np.full((dim, dim, 3), self.bg_color, dtype=np.uint8)
self.field: np.ndarray = np.zeros((dim, dim), dtype=np.float32)
self.edge_field: np.ndarray = np.zeros((dim, dim), dtype=np.float32)
self._grad_x: np.ndarray = np.zeros((dim, dim), dtype=np.float32)
self._grad_y: np.ndarray = np.zeros((dim, dim), dtype=np.float32)
self.time = 0
self._build_noise()
self.reset()
def _build_noise(self) -> None:
rng = np.random.default_rng(self._seed if self._seed is not None else 0)
d = self.dim
big = d * 4
self._perm = rng.integers(0, 256, size=big * big, dtype=np.int32)
self._noise_period = big
@staticmethod
def _fade(t: np.ndarray) -> np.ndarray:
return t * t * t * (t * (t * 6 - 15) + 10)
@staticmethod
def _lerp(a: np.ndarray, b: np.ndarray, t: np.ndarray) -> np.ndarray:
return a + t * (b - a)
Try running it locally
The reference implementation is self-contained Python with numpy. Install the package and run:
python library_external/complexification_net/boundaries/reference.py Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.
More from complexification.net
Cellular Automata Worm
complexification_net · cellularAutomataWorm
The CA Worm is an expanding construction of a one-dimensional cellular automaton.
Cyclic Cellular Automaton
complexification_net · cyclicCellularAutomaton
A Greenberg-Hastings / Rock-Paper-Scissors style cyclic cellular automaton on a 2D torus.
Diffusion Limited Aggregation
complexification_net · diffusionLimitedAggregation
DLA is a simulated growth process: a sticky seed sits in a 2D field, wandering particles spawn along an outer circle, take unit-length random-walk steps, and stick to the cluster whenever they touch it.
Fibers (curling brush)
complexification_net · fibers
A field of curling fibers grown from random seeds scattered across the canvas.
Main Vein
complexification_net · mainVein
A single, meandering recursive vein grows from the center of a dark substrate.
Reaction Diffusion (Gray-Scott)
complexification_net · reactionDiffusion
Gray-Scott reaction-diffusion on a torus: two virtual chemicals U (substrate) and V (catalyst) react and diffuse on a 2D grid.