Cybernetic Urbanism | Form Generation #01 DLA
Contents
- DLA
- What is DLA ?
- Pipeline
- OOP in GhPython | Example
- Scheme
- Grammer
- DLA Algorithm in Grasshopper | Example
- Agent Class
- DLA Class
- Draw Functions
DLA
What is DLA ?
The following is the quotation from wikipedia “Diffusion-limited aggregation“;
Diffusion-limited aggregation (DLA) is the process whereby particles undergoing a random walk due to Brownian motion cluster together to form aggregates of such particles. This theory, proposed by T.A. Witten Jr. and L.M. Sander in 1981,[1] is applicable to aggregation in any system where diffusion is the primary means of transport in the system. DLA can be observed in many systems such as electrodeposition, Hele-Shaw flow, mineral deposits, and dielectric breakdown.
Pipeline
There are 3 processes in programing DLA;
- Random Walk
- Connection Check
- Connect Nodes
- Draw Branch
OOP in GhPython
Scheme
With OOP(Object-Oriented Programming) in GhPython, we can make some programs coding apart.
Grammer
– Constructor
import ghpythonlib.components as gh import rhinoscriptsyntax as rs import Rhino.Geometry as rg import random as rand class Agent: def __init__(self, step): self.pos = rg.Point3d(0,0,0) self.step = step self.log = [] self.log.append(self.pos) def randwalk(self): sph = gh.Sphere(gh.XYPlane([0,0,0]),self.step) randVec = gh.PopulateGeometry(sph, 1, rand.randint(0,100)) self.pos = rs.VectorAdd(self.pos,randVec) self.log.append(self.pos) a = Agent(x)
– Update Function
x.randwalk() a = x
– Draw Function
a = x.pos
a = x.log
DLA Algorithm in Grasshopper
Agent Class
class Agent:
def __init__(self, targetPt, step, r, branchLength):
sph = gh.Sphere(gh.XYPlane([0,0,0]),r)
self.pos = gh.PopulateGeometry(sph, 1, rand.randint(0,100))
self.step = step
self.tPt = targetPt
self.brLen = branchLength
self.hierarchy = 0
def randwalk(self):
targetVec = rs.VectorScale(rs.VectorUnitize(rs.VectorSubtract(self.tPt,self.pos)),self.step)
sph = gh.Sphere(gh.XYPlane([0,0,0]),self.step)
tempVec = gh.PopulateGeometry(sph, 1, rand.randint(0,100))
v = rs.VectorUnitize(rs.VectorAdd(targetVec,tempVec))
self.pos = rs.VectorAdd(self.pos,v)
def addConnection(self, index, pos, hierarchy):
self.index = index
v = rs.VectorSubtract(pos,self.pos)
d = rs.VectorSubtract(rs.VectorScale(rs.VectorUnitize(v),self.brLen),v)
self.pos = rs.VectorSubtract(self.pos,d)
self.hierarchy = hierarchy + 1
def getConnection(self):
index = self.index
return index
Center Agent Class
class centerAgent(Agent):
def __init__(self, tPt, step, r, brLen):
Agent.__init__(self, tPt, step, r, brLen)
self.pos = tPt
DLA Class
class DLA:
def __init__(self, cenPt, brLen, reso, proc):
self.agents = []
self.cenPt = cenPt
self.brLen = brLen
self.reso = reso
self.proc = proc
self.bndRad = 0
self.agents.append(centerAgent(self.cenPt,self.reso,self.brLen,self.brLen))
self.curAgent = Agent(self.cenPt,self.reso,self.brLen*2,self.brLen)
self.finished = False
def update(self):
if self.proc:
if self.finished :
self.agents.append(self.curAgent)
if gh.Distance(self.cenPt,self.curAgent.pos) > self.bndRad:
self.bndRad = gh.Distance(self.cenPt,self.curAgent.pos)
self.curAgent = Agent(self.cenPt,self.reso,self.bndRad+self.brLen,self.brLen)
self.finished = False
else:
self.val = self.checkConnection(self.curAgent)
if self.val != "False":
self.curAgent.addConnection(self.val,self.agents[self.val].pos,self.agents[self.val].hierarchy)
self.finished = True
else:
self.curAgent.randwalk();
else:
while self.finished == False:
self.val = self.checkConnection(self.curAgent)
if self.val != "False":
self.curAgent.addConnection(self.val,self.agents[self.val].pos,self.agents[self.val].hierarchy)
self.finished = True
else:
self.curAgent.randwalk();
self.agents.append(self.curAgent)
if gh.Distance(self.cenPt,self.curAgent.pos) > self.bndRad:
self.bndRad = gh.Distance(self.cenPt,self.curAgent.pos)
self.curAgent = Agent(self.cenPt,self.reso,self.bndRad+self.brLen,self.brLen)
self.finished = False
def checkConnection(self, agent):
pts = []
pts = self.getPoints()
closest = gh.ClosestPoint(self.curAgent.pos,pts)
if closest[2] < self.brLen:
return closest[1]
else:
return "False"
def getHierarchicalBranch(self, hie):
branches = []
for i in range(1,len(self.agents)):
if self.agents[i].hierarchy > hie+1:
branches.append(rs.AddLine(self.agents[i].pos, self.agents[self.agents[i].getConnection()].pos))
return branches
def getBranches(self):
branches = []
if len(self.agents)>1:
for i in range(1,len(self.agents)):
branches.append(rs.AddLine(self.agents[i].pos, self.agents[self.agents[i].getConnection()].pos))
else:
branches.append(rs.AddLine(self.agents[0].pos,self.curAgent.pos))
return branches
def getPoints(self):
points = []
for ag in self.agents:
points.append(ag.pos)
return points
def getcurAgentPos(self):
p = self.curAgent.pos
return p

