Studio Matrx Monthly · Volume 1 · Issue 3 · August 2026
Amogh N P
 In loving memory of Amogh N P — Architect · Designer · Visionary 
Algorithms for FormLesson 9.3
PSD for Architecture, Planning & Urban Design/Module 9 · Generative & Parametric Scripting

Lesson 9.3 · Generative & Parametric Scripting

Algorithms for Form

Grids and tilings, attractors, cellular automata and packing - the generative approaches that turn rules into architecture

14 min Interactive lessonFree · open lessonByAmogh N P· Architect & interior designer
The hook

A grid, an attractor, a growth rule, a packing - four small ideas that generate an astonishing range of architectural form.

Once you can vary a pattern with randomness and grow one with recursion, the natural next question is: what other rules turn into form? The answer is a compact, powerful toolbox that recurs across every parametric project - and each tool is a rule you can write in a few lines.

This lesson tours four of the most useful: grids and tilings (the scaffold most generative work starts from), attractors (points of influence that reshape a field), cellular automata (patterns that grow from neighbour rules), and packing (filling space without overlap). Together they are the vocabulary of the Computational Design course, in plain Python.

Four engines: grid, attractor, cellular automaton, packing. Design the rule.

Grids and tilings - the scaffold of generative work

Almost every generative project starts from a grid: a regular arrangement of points or cells that gives you somewhere to put things. In Python a grid is just a nested loop or a list comprehension over rows and columns:

python
cols, rows, spacing = 5, 4, 3.0
points = [(c * spacing, r * spacing)
          for r in range(rows) for c in range(cols)]
print(len(points), points[:3])   # 20 points

A plain grid is only the beginning. A tiling (or tessellation) fills a surface with repeated shapes - squares, hexagons, triangles - and hexagons in particular show up constantly in facades and screens because they pack efficiently and read as organic. You get a hexagonal layout by offsetting every other row:

python
import math

size = 1.0
cells = []
for r in range(4):
    for c in range(5):
        x = c * size * 1.5
        y = r * size * math.sqrt(3) + (c % 2) * size * math.sqrt(3) / 2
        cells.append((round(x, 2), round(y, 2)))
print(cells[:4])

The grid is rarely the finished design - it is the scaffold you then perturb, populate or deform. Every technique that follows takes a grid as its starting field and changes it according to a rule. Get comfortable generating grids and tilings and you have the substrate for everything else.

It helps to notice how much design already lives on grids you did not think of as generated: a curtain-wall mullion layout, a ceiling tile module, a paving pattern, a structural column bay. Writing them as code rather than drawing them by hand buys you two things immediately. First, they become parametric - change the spacing or count in one place and the whole field updates, so exploring 'what if the bay were 300 mm wider' is instant instead of an afternoon of redrawing. Second, they become addressable - because each cell has an index (c, r), you can ask questions of the grid ('every third column', 'the cells within two metres of the corner', 'alternate rows') and act on them selectively. That indexability is what turns a dead grid into a design surface: it is the hook every later rule grabs onto.

RULES BECOME FORMa ruleif neighbourscrowded -> offelse -> onapplyread asa screen,a facade,a tilingGrids, tilings, cellular automata and packing all work this way: a small rule, applied everywhere.you design the rule; the computer draws the consequence
Zoom
Grids, tilings, cellular automata and packing all share one shape: a small rule applied across a field. You design the rule - here, a neighbour condition that turns cells on or off - and the computer draws the consequence, which you read as a screen, a facade or a tiling.

Grid = the scaffold. Everything else perturbs, populates or deforms it.

Attractors - a point of influence reshapes the field

An attractor is one of the most productive ideas in parametric design: a point (or curve, or set of points) whose influence varies across a field, so that every element responds to its distance from the attractor. Panels grow larger near it, apertures open wider, fins rotate more - all driven by one moving point. The mechanism is always the same: for each element, measure the distance to the attractor, and map that distance to a property.

python
import math

def attractor_scale(px, py, ax, ay, strength=6.0):
    dist = math.hypot(ax - px, ay - py)
    return strength / (dist + 1.0)      # bigger when closer

grid = [(c, r) for r in range(5) for c in range(5)]
sizes = [round(attractor_scale(x, y, 2, 2), 2) for (x, y) in grid]
print(max(sizes), min(sizes))

Each cell's size now depends on how close it sits to the attractor at (2, 2) - a smooth gradient of influence across the whole grid. The magic for a designer is that the attractor is a handle: move it, and the entire pattern reflows continuously. That is parametric design in miniature - one intuitive control driving hundreds of coordinated elements. Attractors are a signature move in Grasshopper (Module 6), where you drag a point and watch a facade breathe; the maths underneath is exactly this distance-to-property mapping.

The idea generalises well beyond a single point. The attractor can be a curve (map each element to its distance from a path - a circulation spine, a site boundary), several points at once (take the nearest, or sum their influences), or even a repelling force that pushes elements away rather than pulling them in. The falloff - how influence fades with distance - is itself a design choice: a sharp inverse-square falloff makes a tight, dramatic focus, while a gentle linear one spreads the effect broadly. Tuning the falloff curve is often where an attractor design goes from crude to elegant, and it is worth experimenting with deliberately rather than accepting the first formula you write.

AN ATTRACTOR SHAPES A FIELDattractorEvery point is nudged toward the attractor; the nudge is stronger nearby, gentler far away.move a point, and the whole pattern reflows - that is parametric form
Zoom
An attractor is a single point of influence: every element is nudged or scaled according to its distance from it, strongly nearby and gently far away. Move the attractor and the whole field reflows continuously - one intuitive handle driving hundreds of coordinated elements, the essence of parametric form.

Attractor = a handle. Measure distance, map to a property. Move it, all reflows.

Cellular automata - form that grows from neighbour rules

A cellular automaton is a grid of cells that update together according to a rule about each cell's neighbours. From a rule you could write on a napkin, startlingly organic patterns emerge. The simplest is a one-dimensional automaton, where each new cell depends on the three cells above it, and an 8-bit 'rule number' encodes the outcome for all eight possible neighbourhoods:

python
def step(row, rule):
    n = len(row)
    out = []
    for i in range(n):
        left, mid, right = row[(i-1) % n], row[i], row[(i+1) % n]
        pattern = (left << 2) | (mid << 1) | right
        out.append((rule >> pattern) & 1)
    return out

row = [0, 0, 0, 1, 0, 0, 0]
for _ in range(3):
    print(row)
    row = step(row, 90)

Rule 90 grows a Sierpinski triangle; rule 30 produces something that looks random. The two-dimensional cousin is Conway's Game of Life, whose rules about live neighbours generate gliders and oscillators. For designers, cellular automata are a way to grow porosity, shading patterns and screen densities that feel alive - each cell 'decides' whether to be solid or void based on its neighbourhood. You design the rule, not the pattern, and the pattern emerges from it - the defining move of generative design.

The word to sit with is emergence: complex, coherent, unplanned global behaviour arising from simple local rules that mention nothing about the big picture. No cell knows it is part of a triangle or a glider; each only looks at its neighbours and applies the rule, yet structure appears at the scale of the whole grid. This is genuinely the same principle behind a flock of birds, a termite mound, or a city's street pattern - and it is why generative design can feel almost alive. For a designer it is liberating and humbling at once: you cannot dictate the pattern directly, only shape the rule and the starting state and then discover what they produce. That is exactly why the seed and the rule number matter so much - they are your two handles on an outcome you do not draw but grow.

CA: cells update from neighbours. You design the rule; the pattern emerges.

Packing - filling space without overlap

The last staple is packing: arranging elements to fill a space without overlapping. Circle packing, Voronoi cells and box packing all answer the same design question - how do I distribute many objects efficiently across an area? The simplest honest algorithm is dart-throwing: propose a random position, accept it only if it does not collide with what is already placed, and repeat until you have enough or you give up.

python
import random, math

random.seed(3)
radius, placed, tries = 0.6, [], 0
while len(placed) < 8 and tries < 1000:
    p = (random.uniform(0, 10), random.uniform(0, 10))
    if all(math.hypot(p[0]-q[0], p[1]-q[1]) > 2 * radius for q in placed):
        placed.append(p)
    tries += 1
print(len(placed), "circles placed")

Notice the honest limit: it might not fit all eight, so we cap the attempts - real generative code accepts that some goals are not fully reachable and stops gracefully. More sophisticated packings (relaxation, Voronoi, physics-based) produce denser, more even results, and Grasshopper plugins like Kangaroo do this with simulated forces. But the concept is the one above: propose, test against a constraint, keep or reject. That is a thread running through this whole module - and it is exactly the generate-and-test structure that the next lesson turns into optimization. Voronoi deserves a special mention, since it is the flip side of packing: given a set of points, it carves space into the region closest to each point, producing the cell patterns you see in leaf veins, cracked mud and a great deal of contemporary facade and structure work.

Packing: propose, test the constraint, keep or reject. Cap the attempts - accept it may not all fit.

Combining engines - and keeping judgement in charge

The real power of this toolbox appears when you combine the engines, because they are all just rules acting on a field. A single facade might start from a hexagonal tiling, have each cell's aperture scaled by an attractor near the entrance, and then have a cellular automaton decide which cells are solid for privacy - three rules layered into one coherent, parametric system. Because each layer is driven by a few parameters, the whole composition stays adjustable: move the attractor, change the automaton rule, retune the tiling, and the design regenerates as a family rather than a fixed drawing. This composability is why these particular techniques recur across the field - they stack cleanly.

Choosing which engine fits is a matter of matching the rule to the intent. Want a smooth gradient of a property across a surface - openings, depth, rotation? That is an attractor. Want an all-over pattern with an organic, grown quality from a local rule? That is a cellular automaton or an L-system. Want to distribute many discrete elements efficiently in a space? That is packing or Voronoi. Want a regular substrate to build any of the above on? Start with a grid or tiling. Naming the intent usually points straight at the tool.

And here is the honest caution that must accompany all of it: emergent does not mean good. These algorithms will happily generate thousands of striking patterns, most of which are not right for the building - too busy, structurally naive, or blind to program, orientation and cost. The techniques expand the space of forms you can explore and the speed of exploring it; they do not tell you which form to choose. That judgement, and the discipline of testing a generated form against real constraints, is what the final lesson formalises by turning the generate-and-test habit into optimization - and it is what keeps you, not the algorithm, the author of the design.

Stack the engines: tiling + attractor + automaton. Emergent is not the same as good.

Approaches & tools in this lesson

grid / tiling

A regular field of points or cells to build on

A nested loop or comprehension. The scaffold nearly every generative technique starts from; hexagonal tilings are a facade favourite.

attractor

A point of influence that varies a property by distance

Measure distance, map it to size/rotation/spacing. A single intuitive handle driving hundreds of elements; a Grasshopper signature move.

cellular automaton

Cells that update from a neighbour rule

Rule 90, rule 30, Conway's Life. You design the rule; complex, organic patterns emerge. Great for porosity and shading screens.

packing

Filling space with non-overlapping elements

Dart-throwing, Voronoi, relaxation (Kangaroo). Propose-test-keep; accept that not everything always fits and cap the attempts.

Hands-on workshop

Workshop - an attractor-driven facade grid

Build a grid of panels whose sizes respond to a movable attractor point, then move the attractor and watch the whole pattern reflow. This is the single most transferable generative pattern - a grid plus a distance-to-property mapping.

Python 3 (math is built in). Optional: matplotlib to visualise the grid of sized panels.

Given & goal
Goal: a parametric facade grid controlled by one attractor
Inputs: Python 3, the math module (matplotlib optional to view)
Time: ~40 minutes
  1. 1Generate a grid of (x, y) points, say 8 by 8 at unit spacing, with a list comprehension. Print how many points you have.
  2. 2Write attractor_scale(px, py, ax, ay) that returns a size based on the inverse distance to the attractor (bigger when closer), as in the lesson. Compute a size for every grid point.
  3. 3Move the attractor: run the whole thing with the attractor at (0, 0), then at (4, 4), and confirm the map of sizes changes - the field reflows around the new point.
  4. 4Add a second attractor and combine their influence (for instance, take the larger of the two scales at each point). Observe how two handles interact.
  5. 5Bonus: plot the grid with matplotlib, drawing each point as a circle whose radius is its computed size, so you actually see the facade breathe around the attractor.

You’ll walk away with
A script that prints (or plots) an 8x8 grid of panel sizes driven by an attractor, run for at least two attractor positions, plus a sentence on how adding a second attractor changed the field.

The worked example

Three altitudes on the same idea

Read the band that fits you — or all three.

For the architectAutomate busywork & build custom tools

These four algorithms are the working vocabulary of parametric practice. Attractor-driven facades, cellular-automata shading screens, Voronoi structural patterns and packed skylights are now routine on real projects, and understanding the plain-Python core lets you go beyond the sliders - customising the rule when an off-the-shelf Grasshopper component does not do quite what the design needs. The grid-attractor pairing alone underlies a huge share of contemporary facade work.

For the interior designerScripts for data, schedules & layouts

Generative algorithms produce bespoke pattern and layout that would be impossibly tedious by hand. Attractors drive perforated screens that open toward a view, packing arranges an artful non-repeating tile or acoustic-panel layout, and cellular automata generate feature-wall textures with an organic, grown quality. Because each is rule-driven and parametric, the pattern adapts instantly when the panel size, the room or the focal point changes.

For the studentA hireable computational skill

This lesson is the bridge from scripting into full computational design. Grids, attractors, cellular automata and packing are exactly the topics the Academy's Computational Design course develops in Grasshopper - seeing their plain-Python cores here means you will understand what those components actually do, not just wire them together. Build an attractor grid and a cellular automaton and you have two portfolio pieces and a real head start.

Misconception check

Generative design means the computer creates the design for you.

The computer never decides what is good - it only executes the rule you give it and shows you the consequence. In every technique here, the creative act is designing the rule: where the attractor sits and how sharply influence falls off, which cellular-automaton rule and seed, how tightly to pack, which tiling to deform. The algorithm faithfully turns that rule into form, often surprising you with emergent detail, but the surprise is a product of your rule, not a substitute for your judgement. Generative design widens the range of forms you can explore and the speed of exploring them; choosing which emergent result is actually good remains entirely yours. It is a collaborator that generates, not an author that decides.
Try it

Do it yourself

Think in rules and fields.

  1. 1Why is a grid described as the 'scaffold' of generative work rather than the design itself?
  2. 2In an attractor, what is measured for each element, and what is it mapped to?
  3. 3In a cellular automaton, do you design the pattern or the rule? What is the difference?
  4. 4What does the dart-throwing packing algorithm do when a proposed position collides with an existing one?
  5. 5Give one real facade or screen example for each: attractor, cellular automaton, packing.
Take this with you

The one line to carry out

Grids, attractors, cellular automata and packing are four rules-into-form engines: you design the rule - a field, a point of influence, a neighbour update, a non-overlap constraint - and the algorithm generates the consequence. The judgement is in the rule, not the output.
Take it further
References & further reading

Peer-reviewed journals & authoritative standards

  1. 01Cellular automatonWikipedia, 2026.
  2. 02Parametric designWikipedia, 2026.
  3. 03Generative designWikipedia, 2026.
  4. 04Grasshopper 3DWikipedia, 2026.
Related lessons
Recap
Most generative work starts from a grid or tiling, the scaffold you then reshape. An attractor maps each element's distance from a point to a property, giving one intuitive handle over a whole field. A cellular automaton grows organic pattern from a neighbour rule you design. Packing fills space by proposing, testing a constraint and keeping or rejecting. All four are the plain-Python core of the tools the Computational Design course develops in Grasshopper.
Carry forward →

So far the rules generate form directly. The final lesson closes the loop: instead of accepting whatever a rule produces, we score each result and let the computer search for better ones - the generate-evaluate-improve loop behind optimization and simulation.

A

The author

Amogh N P

Architect, interior designer, and creative polymath. Studio Matrx began in his notebooks — his vision of design made honest, useful, and open to everyone. Its Academy is written and taught in his memory, and free, forever.

More about Amogh →