home processing download documents tutorial python tutorial gallery source about
 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 :
            pos2 = self.pos.dup().add(self.dir)
            
            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),\
                       meshPt2.cp().add(widthDir),\
                       meshPt1.cp().add(widthDir),\
                       meshPt1.cp().sub(widthDir).add(0,0,z1),\
                       meshPt2.cp().sub(widthDir).add(0,0,z2),\
                       meshPt2.cp().add(widthDir).add(0,0,z2),\
                       meshPt1.cp().add(widthDir).add(0,0,z1)).clr(self.clr())
            
            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 
        
            pos2 = self.pos.dup().add(self.dir)
            #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)

HOME
FOR PROCESSING
DOWNLOAD
DOCUMENTS
TUTORIALS (Java / Python)
GALLERY
SOURCE CODE(GitHub)
ABOUT