Python Tutorials | (back to the list of tutorials) |
To 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
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)
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())