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