Python Tutorials | (back to the list of tutorials) |
Agents and AttractorsTo control a large number of agents, an attractor is often introduced. You define attractors to be located somewhere in the space and agents are oriented towards the location of the attractor.
![]()
![]()
![]()
![]()
add_library('igeo')
def setup() :
size(480,360,IG.GL)
IG.duration(500)
for i in range(3) :
MyAttractor(IRand.pt(0, 0, 20, 100, 100, 20))
#agents in a matrix
for i in range(10) :
for j in range(10) :
MyLineAgent(IVec(i*10,j*10,0),IVec(0,0,0.5)).clr(.5,i*0.1,j*0.1)
class MyAttractor(IAgent) :
def __init__(self, p) :
self.pos = p
self.point = IPoint(self.pos).clr(1.0,0,0)
def update(self) :
# random walk
self.pos.add(IRand.pt(-5,5))
class MyLineAgent(IAgent) :
def __init__(self, p, d) :
self.pos = p
self.dir = d
self.attractor = None
def interact(self, agents) :
#searching the closest attractor
minDist = -1
for agent in agents :
if isinstance(agent, MyAttractor) :
if agent is not self :
dist = agent.pos.dist(self.pos)
#first attractor to check
if self.attractor is None :
self.attractor = agent
minDist = dist
#if less than minimum, it's minimum
elif dist < minDist :
self.attractor = agent
minDist = dist
def update(self) :
#if any closest attractor found, attractor is not null
if self.attractor is not None :
dif = self.attractor.pos.dif(self.pos)
dif.len(self.dir.len())
self.dir = dif
#reset attractor and minDist
attractor = None
ICurve(self.pos.dup(), self.pos.dup().add(self.dir)).clr(self.clr())
self.pos.add(self.dir)
One important part of the code is
the code to find the closest attractor out of
multiple attractors in the space.
This is a typical algorithm to search data
which have a minimum or maximum value.
Each time
Simple Boundary of Agents![]()
![]()
![]()
![]()
add_library('igeo')
def setup() :
size(480, 360, IG.GL)
IG.duration(1000)
MyBoundary(-200,-200,200,200)
MyHexAgent(IVec(0,0,0), IVec(0,10,0))
class MyBoundary(IAgent) :
def __init__(self, x1, y1, x2, y2) :
self.minx = x1
self.miny = y1
self.maxx = x2
self.maxy = y2
IG.rect(IVec(x1,y1,0), x2-x1, y2-y1)
class MyHexAgent(IAgent) :
def __init__(self, p, d) :
self.pos = p
self.dir = d
self.depth = 0
self.depthInc = 0.5
self.hue = 0
def interact(self, agents) :
for agent in agents :
if isinstance(agent, MyBoundary) :
#checking if next position is out of the boundary
nextPos = self.pos.cp(self.dir)
if nextPos.x() < agent.minx :
self.dir.ref(IG.xaxis) #reflect on x-plane
elif nextPos.x() > agent.maxx :
self.dir.ref(IG.xaxis) #reflect on x-plane
if nextPos.y() < agent.miny :
self.dir.ref(IG.yaxis) #reflect on y-plane
elif nextPos.y() > agent.maxy :
self.dir.ref(IG.yaxis) #reflect on y-plane
def update(self) :
self.createHexGeometry()
self.pos.add(self.dir)
#random shift of direction
if IRand.pct(10) :
self.dir.rot(PI/3)
elif IRand.pct(10) :
self.dir.rot(-PI/3)
#random shift of height
if IRand.pct(10) :
self.depthInc *= -1
self.depth += self.depthInc
self.hue += 0.002
def createHexGeometry(self) :
#creating hexagonal extrusion
cpts = []
for i in range(6) :
cpts.append(self.dir.dup().rot(PI/3*i+PI/6).div(2).add(self.pos))
IG.extrude(cpts, 1, True, self.depth).hsb(self.hue,1,1)
Blocking Agents![]()
![]()
![]()
![]()
add_library('igeo')
def setup() :
size(480, 360, IG.GL)
IG.duration(150)
LineAgent(IVec(0,0,0), IVec(1,0,0))
for i in range(-1,2,2) : # -1, 1
for j in range(-1,2,2) :
for k in range(-1,2,2) :
LineBlockAgent(IVec(40*i,40*j,40*k), 40)
class LineBlockAgent(IAgent) :
def __init__(self, p, rad) :
self.pos = p
self.radius = rad
def interact(self, agents) :
for agent in agents :
if isinstance(agent, LineAgent) :
if agent.pt2.dist(self.pos) < self.radius :
agent.del()
def update(self) :
if self.time()==0 :
ISphere(self.pos,self.radius).clr(0,1,1,0.2)
class LineAgent(IAgent) :
length = 2
clearance = 1.99 #less than length
def __init__(self, pt, dir) :
self.pt1 = pt
self.pt2 = pt.dup().add(dir.dup().len(LineAgent.length))
self.isColliding = False
def interact(self, agents) :
for agent in agents :
if self.time() == 0 : #only in the first time
if isinstance(agent, LineAgent) :
if agent is not self :
# checking clearance of end point
if agent.pt2.dist(self.pt2) < LineAgent.clearance :
self.isColliding = True
def update(self) :
if self.isColliding :
self.del()
elif self.time() == 0 : #if not colliding
ICurve(self.pt1,self.pt2).clr(0)
dir = self.pt2.dif(self.pt1)
#rotation axis with random direction
axis = IRand.pt(-1,1).len(1)
if IRand.pct(50) : #bend
LineAgent(self.pt2, dir.dup().rot(axis,IRand.get(PI/3,PI/3*2)))
if IRand.pct(50) : #bend the other way
LineAgent(self.pt2, dir.dup().rot(axis,-IRand.get(PI/3,PI/3*2)))
if IRand.pct(90) : #straight
LineAgent(self.pt2, dir.dup())
HOME
FOR PROCESSING
DOWNLOAD
DOCUMENTS
TUTORIALS (Java /
Python)
GALLERY
SOURCE CODE(GitHub)
PRIVACY POLICY
ABOUT/CONTACT