generative_pioneers · mohr_line_arrangement
Line Arrangements (Mohr)
Manfred Mohr's 1969 plotter 'Line Arrangements': a fixed grid of columns and rows, each carrying a small set of nearly-parallel lines whose exact positions are random within the cell, overlaid with a layer of 45° diagonals whose length, position and orientation are independently random. The piece reads as a structural score — vertical and horizontal scaffolding first, then a tilted second voice — that establishes the same 'abstract text' Mohr described in his P-021 family of algorithmic drawings at Vincennes in 1969/70.
Original: https://emohr.com/sc69-73/vfile_random69.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
For each of n_columns grid cells we drop h_lines_per_col vertical segments inside the cell with a uniform random horizontal offset jitter·cell_width and random vertical trim; symmetrically for n_rows. A second pass draws d_lines_total segments at ±45° with uniformly random centers and uniformly random lengths in [0.04·dim, 0.42·dim].
Parameters
| Name | Type | Default | Range | Description |
|---|---|---|---|---|
dim | int | 512 | 200–1200 | Square canvas side length |
n_columns | int | 12 | 4–32 | Number of vertical grid columns |
n_rows | int | 12 | 4–32 | Number of horizontal grid rows |
h_lines_per_col | int | 3 | 1–8 | Vertical strokes per column |
v_lines_per_row | int | 3 | 1–8 | Horizontal strokes per row |
d_lines_total | int | 24 | 0–200 | Number of 45° diagonal strokes |
jitter | float | 0.35 | 0–1 | Within-cell random offset (fraction of cell size) |
thickness | float | 1.2 | 0.5–3 | Effective ink line thickness |
bg_color | tuple | 245,240,230 | null–null | Background RGB |
line_color | tuple | 15,15,20 | null–null | Ink line RGB |
seed | int | null | 0–999999 | RNG seed |
Reference
First 60 lines of reference.py. Full source:
library_external/generative_pioneers/mohr_line_arrangement/reference.py
from __future__ import annotations
from typing import ClassVar
import imageio.v2 as imageio
import numpy as np
class MohrLineArrangement:
family: ClassVar[str] = "generative_pioneers"
sketch: ClassVar[str] = "mohr_line_arrangement"
def __init__(
self,
dim: int = 512,
n_columns: int = 12,
n_rows: int = 12,
h_lines_per_col: int = 3,
v_lines_per_row: int = 3,
d_lines_total: int = 24,
jitter: float = 0.35,
thickness: float = 1.2,
bg_color: tuple[int, int, int] = (245, 240, 230),
line_color: tuple[int, int, int] = (15, 15, 20),
seed: int | None = None,
) -> None:
self.dim = dim
self.n_columns = n_columns
self.n_rows = n_rows
self.h_lines_per_col = h_lines_per_col
self.v_lines_per_row = v_lines_per_row
self.d_lines_total = d_lines_total
self.jitter = jitter
self.thickness = thickness
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.time = 0
self._dirty = True
def reset(self, seed: int | None = None) -> None:
if seed is not None:
self._seed = seed
self.rng = np.random.default_rng(self._seed)
self.canvas = np.full((self.dim, self.dim, 3), self.bg_color, dtype=np.uint8)
self.time = 0
self._dirty = True
def _draw_segment(
self,
x0: float,
y0: float,
x1: float,
y1: float,
color: np.ndarray,
thickness: float,
) -> None:
d = float(np.hypot(x1 - x0, y1 - y0)) Try running it locally
The reference implementation is self-contained Python with numpy. Install the package and run:
python library_external/generative_pioneers/mohr_line_arrangement/reference.py Need help? See Learn for the standard environment setup, or Playground for an in-browser sketchbook.
More from generative pioneers
Interruptions (Molnár)
generative_pioneers · molnar_interruptions
Vera Molnár's 1968 'Interruptions' series: a regular grid of rectangle cells where each cell's four border edges are drawn independently, each with its own random probability of being omitted.
Paint by Numbers (Haeberli)
generative_pioneers · haeberli_painterly
Paul Haeberli's 1990 SIGGRAPH 'Paint by Numbers' — the founding paper of stroke-based rendering.
Plotter Trajectories (Hébert)
generative_pioneers · hebert_plotter_trajectory
Jean-Pierre Hébert's plotter-trajectory idiom — parametric Lissajous-like curves drawn over multiple passes, each pass slightly phase-shifted, each segment modulated by the local velocity of the pen so that slow regions lay down heavier pigment and fast regions trace a ghost line.
Walk-through-Raster (Nake)
generative_pioneers · nake_walk_sequence
Frieder Nake's 1966 'Walk-through-Raster' program (Algol 60 on a Telefunken TR4, plotted on a ZUSE Graphomat Z64): a repertoire of six signs — empty, vshort, vlong, hshort, hlong, dot — is sampled into a Markov chain whose transition probabilities vary with chain position so that 'vertical strokes are high at the chain's middle, empties dominate at the ends'.