2014-06-25

Swarm Python Component

Swarm in Grasshopper using GH_Python component. Testing swarm behaviour in Rhino is in this post: Rhino.Python Swarm Bridge

For more discussion please visit my post in grasshopper example forum.

GH_Python Code:

### --Written by Gene Ting-Chun Kao-- ###
ghenv.Component.Message = "written by +GENEATCG"
 
import rhinoscriptsyntax as rs 
import Rhino as rc
from random import *
 
rectX = 600
rectY = 600
 
class Runner:
    def __init__(self, p, v):
        self.p = p
        self.v = v
        self.a = rs.VectorCreate( (0,0,0),(0,0,0) )
         
    def ptRun(self):
        self.v = rs.VectorAdd(self.v, self.a)
        v = rs.VectorLength(self.v)
        if v > 2:
            self.v = rs.VectorScale(rs.VectorUnitize(self.v), 2)
        self.p = rs.VectorAdd(self.p, self.v)
         
        self.a = rs.VectorCreate( (0,0,0),(0,0,0) )
     
    def reflect(self):
        if self.p[0] >= rectX or self.p[0] < 0:
            self.v[0] *= -1.2
        if self.p[1] >= rectY or self.p[1] < 0:
            self.v[1] *= -1.2
     
    def door(self):
        if self.p[0] >= rectX:
            self.p[0] -= rectX
        if self.p[0] <= 0:
            self.p[0] += rectX
        if self.p[1] >= rectY:
            self.p[1] -= rectY
        if self.p[1] <= 0:
            self.p[1] += rectY
         
     
    def flock(self):
        self.separate(ms)
        self.cohesion(mc)
        self.align(ma)
     
    def align(self, mag):
         
        steer = rs.VectorCreate( (0,0,0) , (0,0,0) )
        count = 0
         
        for i in pts:
            distance = rs.Distance(i.p, self.p)
            if distance > 0 and distance < 40:
                steer = rs.VectorAdd(steer, i.v)
                count += 1
         
        if count>0:
            steer = rs.VectorScale(steer, 1.0/count)
         
        steer = rs.VectorScale(steer, mag)
        self.a = rs.VectorAdd(self.a, steer)
     
    def cohesion(self, mag):
         
        sum = rs.VectorCreate( (0,0,0) , (0,0,0) )
        count = 0
         
        for i in pts:
            distance = rs.Distance(i.p, self.p)
            if distance > 0 and distance < 60:
                sum = rs.VectorAdd(sum, i.p)
                count += 1
         
        if count>0:
            sum = rs.VectorScale(sum, 1.0/count)
         
        steer = rs.VectorSubtract(sum, self.p)
        steer = rs.VectorScale(steer, mag)
        self.a = rs.VectorAdd(self.a, steer)
        #print(self.a)
     
    def separate(self, mag):
         
        steer = rs.VectorCreate( (0,0,0) , (0,0,0) )
        count = 0
         
        for i in pts:
            distance = rs.Distance(i.p, self.p)
            if distance > 0 and distance < 30:
                diff = rs.VectorSubtract(self.p, i.p)
                diff = rs.VectorUnitize(diff)
                diff = rs.VectorScale(diff, 1.0/distance)
                 
                steer = rs.VectorAdd(steer , diff)
                count += 1
         
        if count>0:
            steer = rs.VectorScale(steer, 1.0/count)
         
        steer = rs.VectorScale(steer, mag)
         
        self.a = rs.VectorAdd(self.a, steer)
        #print(self.a)
     
    def drawPt(self):
        pt = rc.Geometry.Point3d(self.p[0], self.p[1], self.p[2])
        return pt
 
if reset:
    pts = []
    for i in range(20):
        p = rs.VectorCreate(   rs.AddPoint( randint(1,rectX-1),  randint(1,rectY-1),0  )  ,  rs.AddPoint(0,0,0)    )
        v = rs.VectorCreate(   rs.AddPoint( randint(1,3) ,  randint(1,3),0   )  ,  rs.AddPoint(0,0,0)    )
        run1 = Runner(p, v)
        pts.append(run1)
else:
    pos = []
    vec = []
     
    if not stop:
        for i in pts:
            pos.append(i.drawPt())
            vec.append(i.v)
        for i in pts:
            if bound:
                i.reflect()
            else:
                i.door()
            #i.separate(magnitude)
            i.flock()
            i.ptRun()
         
    else:
        for i in pts:
            pos.append(i.drawPt())
            vec.append(i.v)
 
 
plane = rs.WorldXYPlane()
 
rect = rs.AddRectangle(plane, rectX, rectY)