designcoding
About Table of Contents Keywords Monthly Archive
Support designcoding!

Differential Growth

June 16, 2025 | Algorithms
#grasshopper #growth #rhino-python #simulation #vector-field

Differential growth is a process where different parts of a structure grow at different rates, leading to complex forms. After watching this, I decided to try it in Grasshopper. Here, differential growth mimics this behavior by applying rules such as Repulsion to avoid crowding or overlapping, Cohesion to keep parts connected or within a range, and Insertion to add new elements when a part stretches too far. The algorithm I present here simulates a differential growth process starting from a set of points along a curve. All agents apply repulsion forces to each other if they are within a certain distance. Each agent checks its neighbors: it pushes or pulls them. Additionally, when two neighbors become too far apart, the code inserts a new (point) agent. Over time, this interaction leads to growing patterns shown below:

Differential Growth animation

I developed this Grasshopper Python code in Rhino 8 (Python 3). This means it will NOT work in Rhino 7. Crv is the initial curve for the starting agents. I is the distance threshold above which a new agent is inserted. R is the range within which global repulsion is applied. K is the scaling factor for force accumulation. Q is the damping coefficient (controls how fast they slow down). N is the maximum number of agents. When Run is triggered, it triggers one iteration of the simulation. I attached a Grasshopper Timer component to repeat it. The outputs are the points and the vectors. This implementation makes some optimizations, but it still checks every boid with every other. So it becomes very (really) slow when you increase the N value too much. Below is the Python code inside the Grasshopper definition. You can find the definition at the bottom of this page.

import rhinoscriptsyntax as rs
import math
insertDistance = I
repulsionDistance = R
k = K
q = Q
def vector_add(a, b):
	return [a[0]+b[0], a[1]+b[1], a[2]+b[2]]
def vector_subtract(a, b):
	return [a[0]-b[0], a[1]-b[1], a[2]-b[2]]
def vector_scale(v, s):
	return [v[0]*s, v[1]*s, v[2]*s]
def vector_length(v):
	return math.sqrt(v[0]**2 + v[1]**2 + v[2]**2)
def vector_unitize(v):
	length = vector_length(v)
	if length == 0:
		return [0,0,0]
	return [v[0]/length, v[1]/length, v[2]/length]
def vector_distance_sq(a, b):
	return (a[0]-b[0])**2 + (a[1]-b[1])**2 + (a[2]-b[2])**2
class Boid():
	def __init__(self, pos, vel):
		self.pos = list(pos)
		self.vel = list(vel)	
	def updateVel(self, i):
		forces = [0,0,0]
		for boid in flock:
			if boid != self:
				dis = vector_distance_sq(boid.pos, self.pos)
				if dis < repulsionDistance ** 2:
					dif = vector_subtract(boid.pos, self.pos)
					dif = vector_unitize(dif)
					dif = vector_scale(dif, -1 / dis)
					forces = vector_add(forces, dif)
		n_boid = flock[i-1]
		p_boid = flock[(i+1) % len(flock)]
		p_dis = vector_distance_sq(p_boid.pos, self.pos)
		p_dif = vector_subtract(p_boid.pos, self.pos)
		p_dif = vector_unitize(p_dif)
		p_dif = vector_scale(p_dif, 1 / p_dis)
		if p_dis < (insertDistance * 0.5) **2:
			p_dif = vector_scale(p_dif, -1)
		forces = vector_add(forces, p_dif)
		n_dis = vector_distance_sq(n_boid.pos, self.pos)
		n_dif = vector_subtract(n_boid.pos, self.pos)
		n_dif = vector_unitize(n_dif)
		n_dif = vector_scale(n_dif, 1 / n_dis)
		if n_dis < (insertDistance * 0.5) **2:
			n_dif = vector_scale(n_dif, -1)
		forces = vector_add(forces, n_dif)
		forces = vector_scale(forces, k)
		self.vel = vector_add(self.vel, forces)
	def updatePos(self):
		self.pos = vector_add(self.pos, self.vel)
		self.vel = vector_scale(self.vel, q)
def check_insert_particles(flock):
	i = 0
	while i < len(flock):
		boidA = flock[i]
		boidB = flock[(i + 1) % len(flock)]
		dis = vector_distance_sq(boidA.pos, boidB.pos)
		if dis > insertDistance**2:
			pos = vector_scale(vector_add(boidA.pos, boidB.pos), 0.5)
			vel = vector_scale(vector_add(boidA.vel, boidB.vel), 0.5)
			flock.insert(i+1, Boid(pos, vel))
		else:
			i += 1
def reset_flock():
	points = rs.CurvePoints(Crv)
	points = rs.CullDuplicatePoints(points)
	center = rs.CurveAreaCentroid(Crv)[0]
	for point in points:
		vel = vector_subtract(point, center)
		vel = vector_unitize(vel)
		boid = Boid(point, vel)
		flock.append(boid)
if "ready" not in globals() or Reset:
	ready = True
	flock = []
	reset_flock()
if ready and Run:
	if len(flock) < N:	
		check_insert_particles(flock)
	for i, boid in enumerate(flock):
		boid.updateVel(i)
	for boid in flock:
		boid.updatePos()
pos = [rs.CreatePoint(*boid.pos) for boid in flock]
vel = [rs.CreateVector(*boid.vel) for boid in flock]
Differential Growth Grasshopper file, including the Python componentDownload

Cite this post

Yazar, T. (2025, June 16). Differential Growth. designcoding. Retrieved August 18, 2026, from https://www.designcoding.net/differential-growth/

Related Posts

Wandering Simulator

March 9, 2024

In 1986, Craig Reynolds developed an algorithm aiming to model the flocking behavior of birds, which remains a cult method used in flock simulations today. In my initial study, the bird-oids (boids) have no rules or limitations, just chilling randomly on the screen. I call this initial version Wandering Simulator. There are several reasons why this fundamental simulation is difficult in Grasshopper and Python, our parametric design interface. In Grasshopper (data flow modeling), pushing the back doors a bit is…

Solar Position

May 6, 2012

Experimenting with various plug-ins for solar calculations, I found Daniel Da Rocha’s robust implementation of the solar position algorithm in vb.net. It calculates the solar angle of any place and time. Although it’s written in the old vb.net component, it still works great. I’m trying to create a fast and easy workflow to optimize Grasshopper models based on solar directions. This is done by projecting faces to the solar planes and checking how much of their area is included in…

Wind Tunnel in Vasari

April 13, 2012

When I was a student, 3D modeling and rendering on the computer was an advanced skill. I only managed to create my first rendering in the 4th-year project.  Then, it became a special talent for designers, even opening a freelance business. However, that came to an end when that technology expanded, reaching everybody. Ten years ago, different ecological analysis methods on geometric designs were also another specialized field that everybody doesn’t have access to. Now it seems those technical skills…

Parametric Bricks

January 17, 2024

In 2016, archi-union architects and fab-union intelligent engineering completed the renovation of the art gallery in Shanghai, China. The distinctive feature of the building was the robotic masonry fabrication of the brick facades. The undulating and waving parametric bricks were increasingly becoming popular after the introduction of parametric design tools such as Grasshopper and the works of Gramazio & Kohler at ETH Zurich since 2008, I guess. I made two Grasshopper experiments in 2012 and 2013 to generate such structures….

Vector Fields Exercise

April 4, 2023

Fields is a native group of components available since the very early version of Grasshopper. In today’s Design Computing class, we studied it again with the first-year design students. I studied these interesting and beautiful shapes earlier here, here, here, and here. The one you see below is a short in-class exercise about vector fields. The exercise aims to show the Grasshopper’s capabilities in form-finding studies via Field Lines. The definition starts with the generation of a set of random…

  • Chapters

    • Algorithms
    • Discourses
    • Fabrications
    • Studios
  • Explore

    • All Keywords
    • Table of Contents
    • Monthly Archive
    • #polyhedra
    • #tessellation
    • #tutorial
    • #parametric-surface
    • #robot
    • #dome
    • #parametric-curve
    • #design-object
    • #image-sampler
    • #linear-algebra
    • #terrain
    • #kuka-prc
    • #sandblasting
    • #stone
    • #animation
    • #cycloid
    • #art
    • #aperiodic
    • #tiling
    • #dodecahedron
  • Search

  • Support designcoding!

  • Would you like to help me maintain designcoding? You can donate via Patreon. Thank you!

  • copyright 2026 designcoding.net | about | privacy policy | end user license agreement