Python Tutorials (back to the list of tutorials)

## Physics Simulation and Swarm Examples

### Multi-Agent 3D Example 2 (requires iGeo version 7.6.0 or higher)

The example code below takes the previous tutorial code at "Multi-Agent 2D Example 3" and adding height depending on time and creating polygon mesh geometries.

```add_library('igeo')

def setup() :
size(480, 360, IG.GL)
IG.duration(300)
# left 100%, right 4.5%
LineAgent(IG.v(0,0,0), IG.v(2,0,0), 100.0, 4.5).clr(0)

class LineAgent(IAgent) :
def __init__(self, pt, dir, pctL, pctR) :
self.pos = pt
self.dir = dir
self.pctL = pctL
self.pctR = pctR
self.isColliding=False
self.itxn = None

def interact(self, agents) :
if self.time()==0 :
for agent in agents :
if self.isColliding :
return
if isinstance(agent, LineAgent) and agent is not self :
pos2 = self.pos.cp(self.dir)
apos2 = agent.pos.cp(agent.dir)
if not apos2.eq(self.pos) and not agent.pos.eq(self.pos) : #not sharing root
self.itxn = IVec.intersectLine(agent.pos,apos2,self.pos,pos2) #keep intersection to draw line later
if self.itxn is not None : #intersecting
self.isColliding=True

def update(self) :
if self.time()==0 :

thickness = 0.3
widthDir = self.dir.dup().rot(PI/2).len(thickness/2)
z1 = sin(IG.time()*0.05)*10+15
z2 = sin((IG.time()+1)*0.05)*10+15
meshPt1 = self.pos
meshPt2 = pos2
if self.isColliding :
meshPt2 = self.itxn

IG.meshBox(meshPt1.cp().sub(widthDir),\
meshPt2.cp().sub(widthDir),\

if self.isColliding :
self.del()
return

r = self.red() + IRand.get(-0.05, 0.05)
g = self.green() + IRand.get(-0.05, 0.05)
b = self.blue() + IRand.get(-0.05, 0.05)

branchL = IRand.pct(self.pctL)
branchR = IRand.pct(self.pctR)

lenL = self.dir.len()
lenR = self.dir.len()
lenL*=0.995  #shrinking length
lenR*=0.995  #shrinking length

if branchL and branchR : #only when branching both
if IRand.pct(50.0) :
if self.pctL < self.pctR :
lenL *= 0.9
else :
lenR *= 0.9
elif IRand.pct(6.0) :
if self.pctL < self.pctR :
lenL *= 0.4
else :
lenR *= 0.4

elif IRand.pct(5.0) :
if self.pctL < self.pctR :
lenL *= 4
else :
lenR *= 4

if branchL : #bend left
dir2 = self.dir.dup()
dir2.len(lenL) #update length
dir2.rot(PI/30)

if branchR and self.pctR > self.pctL : #swap L/R% when branching both
LineAgent(pos2, dir2, self.pctR, self.pctL).clr(r,g,b)
else :
LineAgent(pos2, dir2, self.pctL, self.pctR).clr(r,g,b)

if branchR : #bend right
dir2 = self.dir.dup()
dir2.len(lenR) #update length
dir2.rot(-PI/30)

if branchL and self.pctR < self.pctL : #swap L/R% when branching both
LineAgent(pos2, dir2, self.pctR, self.pctL).clr(r,g,b)
else :
LineAgent(pos2, dir2, self.pctL, self.pctR).clr(r,g,b)

```

The example code below takes the previous tutorial code at "Multi-Agent 2D Example 3" and layering multiple agents in different z levels and interconnect them. All the branches and interconnection lines are made out of polygon mesh sticks.

```add_library('igeo')

def setup() :
size(480, 360, IG.GL)
IG.duration(80)
z = 0
for i in range(20) :
#IRand.dir() is giving a random direction with given length perpendicular to given axis
LineAgent(IRand.pt(-30,-30,z,30,30,z), IRand.dir(IG.zaxis,2),100.0,4.5).clr(0)
z += IRand.get(1,5)

class LineAgent(IAgent) :
def __init__(self, pt, dir, pctL, pctR) :
self.pos = pt
self.dir = dir
self.pctL = pctL
self.pctR = pctR
self.isColliding = False
self.itxn = None

def interact(self, agents) :
if self.time()==0 :
for agent in agents :
if self.isColliding :
return
if isinstance(agent, LineAgent) and agent is not self :
#draw interconnection in z
if not self.pos.eqZ(agent.pos)  : #z is not equal
minLen = self.dir.len()
if agent.dir.len() < minLen :
minLen = agent.dir.len()
threshold = minLen * 2.5
if self.pos.eqX(agent.pos, threshold) and\
self.pos.eqY(agent.pos, threshold)  : #x and y is equal with in given tolerance
if IRand.pct(60) :
#ICurve(self.pos,agent.pos).clr(self.clr())
IG.meshSquareStick(self.pos,agent.pos,0.3).clr(self.clr())
else :
pos2 = self.pos.cp(self.dir)
apos2 = agent.pos.cp(agent.dir)

if not apos2.eq(self.pos) and not agent.pos.eq(self.pos) : #not sharing root
self.itxn = IVec.intersectLine(agent.pos,apos2,self.pos,pos2) #keep intersection to draw line later
if self.itxn is not None : #intersecting
self.isColliding=True

def update(self) :
if self.time()==0 :
if self.isColliding :
#ICurve(self.pos, self.itxn).clr(self.clr())
IG.meshSquareStick(self.pos, self.itxn, 0.5).clr(self.clr()) #keep line to intersection
self.del()
return

#ICurve(self.pos, self.pos2).clr(self.clr())
IG.meshSquareStick(self.pos, pos2, 0.5).clr(self.clr())

r = self.red() + IRand.get(-0.05, 0.05)
g = self.green() + IRand.get(-0.05, 0.05)
b = self.blue() + IRand.get(-0.05, 0.05)

branchL = IRand.pct(self.pctL)
branchR = IRand.pct(self.pctR)

lenL = self.dir.len()
lenR = self.dir.len()
lenL*=0.995  #shrinking length
lenR*=0.995  #shrinking length

if branchL and branchR :  #only when branching both
if IRand.pct(50.0) :
if self.pctL < self.pctR :
lenL *= 0.9
else :
lenR *= 0.9
elif IRand.pct(6.0) :
if self.pctL < self.pctR :
lenL *= 0.4
else :
lenR *= 0.4
elif IRand.pct(5.0) :
if self.pctL < self.pctR :
lenL *= 1.4
else :
lenR *= 1.4

if branchL :  #bend left
dir2 = self.dir.dup()
dir2.len(lenL)  #update length
dir2.rot(PI/30)

if branchR and self.pctR > self.pctL :  #swap L/R% when branching both
LineAgent(pos2, dir2, self.pctR, self.pctL).clr(r,g,b)
else :
LineAgent(pos2, dir2, self.pctL, self.pctR).clr(r,g,b)

if branchR :  #bend right
dir2 = self.dir.dup()
dir2.len(lenR)  #update length
dir2.rot(-PI/30)

if branchL and self.pctR < self.pctL :  #swap L/R% when branching both
LineAgent(pos2, dir2, self.pctR, self.pctL).clr(r,g,b)
else :
LineAgent(pos2, dir2, self.pctL, self.pctR).clr(r,g,b)

```

(back to the list of tutorials)