Design IX: Digital Methods, Python Coding

  • 2D/3D GEOMETRY STUDIES
  • import rhinoscriptsyntax as rs
    import math
    #Defining dimensions of the box
    pt1=(0,0,0)
    pt2=(1,0,0)
    pt3=(1,1,0)
    pt4=(0,1,0)
    pt5=(0,0,1)
    pt6=(1,0,1)
    pt7=(1,1,1)
    pt8=(0,1,1)
    corners=(pt1,pt2,pt3,pt4,pt5,pt6,pt7,pt8)
    #Defing the ammount of points the curve is broken into
    def main():
        curve_id = rs.GetObject("Select a curve to sample", 4, True, True)
        if not curve_id: return
        rs.EnableRedraw(False)
        t = 0
        while t<=1.0:
            addpointat_r1_parameter(curve_id,t)
            t=0.005
        rs.EnableRedraw(True)
    #Defing curve and location of boxes on curve
    def addpointat_r1_parameter(curve_id, parameter):
        domain = rs.CurveDomain(curve_id)
        r1_param = domain[0] + parameter*(domain[1]-domain[0])
        r3point = rs.EvaluateCurve(curve_id, r1_param)
        if r3point:
            point_id = rs.AddPoint(r3point)
            box = rs.AddBox(corners)
            a = rs.MoveObject(box,point_id)
            rs.RotateObjects(a,point_id,r1_param)
            rs.ScaleObjects(a,point_id,[3,3,3])
    #execute main() function
    main()
  • An extended version of the code above, with the addition of classes in order to call and embed functions.
  •      import rhinoscriptsyntax as rs
         import math

         class CrvDiv:
              def __init__ (self, crv1, NumDiv, SclObj):
                self.crv1 = crv1
                self.NumDiv = NumDiv
                self.SclObj = SclObj
                self.pt1=(0,0,0)
                self.pt2=(1,0,0)
                self.pt3=(1,1,0)
                self.pt4=(0,1,0)
                self.pt5=(0,0,1)
                self.pt6=(1,0,1)
                self.pt7=(1,1,1)
                self.pt8=(0,1,1)
                self.corners=(self.pt1,self.pt2,self.pt3,self.pt4,self.pt5,self.pt6,self.pt7,self.pt8)
            
            #Add, Move Box to Line, and Scale Based on User Input
            def DivideCrv(self):
                PtList1 = rs.DivideCurve(self.crv1, self.NumDiv, True, True)
              
                for i in range (len(PtList1)):
                
                     box = rs.AddBox(self.corners)
                      rs.MoveObject(box,PtList1[i])
                     print(PtList1[i]) 
                     #rs.RotateObjects(box,PtList1,20)
                     rs.ScaleObjects(box,PtList1[i], [self.SclObj, self.SclObj, self.SclObj])

       #User Select Curve, Divide Curve by User Input, and Scale Boxes Based on User Input
       SelectCrv1 = rs.GetObject("Select a Curve",4)
       SelectDiv = rs.GetReal("Input Number of Divisions on Curve", None, 3, None)
       SelectScl = rs.GetReal("Input Scale of Object",None,1,None)

       obj01 = CrvDiv(SelectCrv1,SelectDiv, SelectScl)
       obj01.DivideCrv()
         
  • Creating a group of objects whose heights change based upon a defined Cosine curve. Where the objects below the x,y plane are deleted. Using user defined amounts and sizes.
  • import math
    import rhinoscriptsyntax as rs
    #Define box
    corners=([0,0,0],[1,0,0],[1,1,0],[0,1,0],[0,0,1],[1,0,1],[1,1,1],[0,1,1])
    #Range Parameters
    dblA = 0.
    dblB = 100.
    dblStep = 4.
    #Cosine function to allow cubes to start at maximum altitude and decrease
    for x in rs.frange(dblA,dblB,dblStep):
        for y in rs.frange (dblA,dblB,dblStep):
            box=rs.AddBox (corners)
            z = 50*math.cos(math.radians(x+y))
            rs.ScaleObject(box,[0,0,0],[4,4,z])
    #rotate around origin point to create "pyramid" shape
            quad1= rs.MoveObject(box,[x,y,0])
            quad2 = rs.RotateObject(quad1,[0,0,0],90,None,True)
            quad3 = rs.RotateObject(quad2,[0,0,0],90,None,True)
            quad4 = rs.RotateObject(quad3,[0,0,0],90,None,True)
    #Delete every object below z = 0
            if z <= 0: 
                rs.DeleteObjects([box,quad2,quad3,quad4])
  •   import math
      import rhinoscriptsyntax as rs
      

      class Pyramid:
       
         #Define box
         def __init__ (self, dblA, dblB, dblStep):
             self.dblA = dblA
             self.dblB = dblB
             self.dblStep = dblStep
             self.pt1=(0,0,0)
             self.pt2=(1,0,0)
             self.pt3=(1,1,0)
             self.pt4=(0,1,0)
             self.pt5=(0,0,1)
             self.pt6=(1,0,1)
             self.pt7=(1,1,1)
             self.pt8=(0,1,1)
             self.corners=(self.pt1,self.pt2,self.pt3,self.pt4,self.pt5,self.pt6,self.pt7,self.pt8)
            
            
        def CosineScale (self):
            #Cosine function to allow cubes to start at maximum altitude and decrease
            for x in rs.frange(self.dblA,self.dblB,self.dblStep):
                for y in rs.frange (self.dblA,self.dblB,self.dblStep):
                    box=rs.AddBox (self.corners)
                    z = ((self.dblB/2)*math.cos(math.radians(x+y)))
                    rs.ScaleObject(box,[0,0,0],[self.dblStep,self.dblStep,z])
                    #rotate around origin point to create "pyramid" shape
                    quad1= rs.MoveObject(box,[x,y,0])
                    quad2 = rs.RotateObject(quad1,[0,0,0],90,None,True)
                    quad3 = rs.RotateObject(quad2,[0,0,0],90,None,True)
                    quad4 = rs.RotateObject(quad3,[0,0,0],90,None,True)
                    #Delete every object below z = 0

                    if z <= 0: 
                        rs.DeleteObjects([box,quad2,quad3,quad4])  

      #Range Parameters With Defaults of a Height of 100 and a Scale of 4
      InputAmmount = rs.GetReal("Input Height to be divided in Half", 100, 2, None)
      InputScale = rs.GetReal("Input Scale of box", 4, 1, None)

      obj01 = Pyramid(0,InputAmmount,InputScale)
      obj01.CosineScale()
     
  • RECURSION
  • Random growth patterns, at random origin points. These patterns grow to a set amount determined by the code, and then go through a recursion process a set number of times.
  • import rhinoscriptsyntax as rs
    import random
    import math
    rs.EnableRedraw(False)
    class Rec:
        
        def __init__(self, _border):
            self.border =_border
        def outline(self):
            self.pt1 = [0,0,0]
            self.pt2 = [self.border,0,0]
            self.pt3 = [self.border,self.border,0]
            self.pt4 = [0,self.border,0]
            rs.AddCurve((self.pt1,self.pt2,self.pt3,self.pt4,self.pt1),1)
    obj1 = Rec(120)
    obj1.outline()
    CircList = []
    def placePt(x_range,y_range,z_range):
        x = random.uniform(0,x_range)
        y = random.uniform(0,y_range)
        z = random.uniform(0,z_range)
        pt = [x,y,z]
        return pt
    for j in range(0,10):
        ZeroX = random.uniform(j,120)
        ZeroY = random.uniform (j,120)
        ptZero = [ZeroX,ZeroY,0]
        pts = []
        pts.append(ptZero)
        circleZero = rs.AddCircle(ptZero,.5)
        for i in range(0,(random.randint(10,100))):
            pt = rs.AddPoint(placePt(100,100,0))
            index = rs.PointArrayClosestPoint(pts,pt)
            cp = pts[index]
            vect = rs.VectorCreate(cp,pt)
            unitVect = rs.VectorUnitize(vect)
            subVect = vect - unitVect
            newPt = rs.MoveObject(pt,subVect)
            Ptcoor = rs.PointCoordinates(newPt)
            NewCirc = rs.AddCircle(newPt,.5)
            pts.append(newPt)
            CircList.append(NewCirc)
    def RecScale(num,CircList):
        if (num <=1):
            return 1
        else:
            a1 = rs.ScaleObject(CircList,Ptcoor,[ 10*(1/num),10*(1/num),0], True )
            return RecScale(num-1,CircList)
    num = 10
    for k in range(0,10):
        RecScale(num, CircList)
  • A square grid plotted and ran through a recursion definition, that says to scale down and rotate by a random angle around the center point of each square. Below the variations show different rotation ranges and differing amounts of recursions.
  • import rhinoscriptsyntax as rs
    import math
    import random 
        
    class Rec:
        
        def __init__(self, _num,_i, _j, _border):
            self.i = _i
            self.j = _j
            self.num = _num
            self.border =_border
             self.plane = rs.WorldXYPlane()
            self.a = rs.AddRectangle(self.plane,12,12)
            self.a1 = rs.MoveObject(self.a,[self.i,self.j,0])
            self.Cent = rs.CurveAreaCentroid(self.a1)
            self.CentPt = rs.AddPoint(self.Cent[0])
        def outline(self):
            self.pt1 = [0,0,0]
            self.pt2 = [self.border,0,0]
            self.pt3 = [self.border,self.border,0]
            self.pt4 = [0,self.border,0]
            rs.AddCurve((self.pt1,self.pt2,self.pt3,self.pt4,self.pt1),1)
            
        def RecScale(self, num):
            if (num <=1):
                return 1
            else:
        
                self.a1 = rs.ScaleObject(self.a1,self.CentPt,[(1/self.num)*2,(1/self.num)*2,0], True )
                Rota1 = rs.RotateObject(self.a1,self.CentPt,random.randint(1,360))
                return self.RecScale(num-.5)
    num=3
    for i in rs.frange (0,116,12):
        for j in rs.frange (0,116,12):
            obj1 = Rec(num,i,j, 120)
            obj1.RecScale(num)
    obj1.outline()
  • A plot of circles rotated by a sine curve, cosine curve, and tangent curve. The curves are then run through a user determined ammount of recursion loops. The premise of this experiment was to apply a recursive function  on certain areas of  plotted objects.
  • import rhinoscriptsyntax as rs
    import math
    import random 
    rs.EnableRedraw(False)
    class Base:    
        def __init__(self,i,Mfun,num,Angle):
            self.i = i
            self.Mfun = Mfun
            self.num = num
            self.Angle = Angle       
            self.RoCirc = None
            self.Ro2Circ = None
            self.Center = None
            self.Center2 = None        
            self.pt1 = (-self.i/2,-self.i/2,0)
            self.pt2 = (self.i/2,-self.i/2,0)
            self.pt3 = (self.i/2,self.i/2,0)
            self.pt4 = (-self.i/2,self.i/2,0)
            self.Border = rs.AddCurve([self.pt1,self.pt2,self.pt3,self.pt4,self.pt1],1)       
            self.PtList = []
            self.RecList = []
            self.CircList = []
            self.CoordList = []
            self.Circle = rs.AddCircle([0,0,0],40)
                          
        def Crv (self):
            for r in range (0,150):
                Circ = rs.AddCircle((0,0,0),1)
                rs.MoveObject(Circ, (r/2,r/2,0))
                if (self.Mfun == 1):
                    x = math.sin(2*r)
                elif (self.Mfun == 2):
                    x = math.cos(2*r)
                elif (self.Mfun == 3):
                    x = math.tan(r)
                
                self.RoCirc = rs.RotateObject(Circ,(0,0,0),self.Angle*x,None)
                self.Center = rs.CircleCenterPoint(self.RoCirc)
                CentPoint = rs.AddPoint(self.Center)
                self.Ro2Circ = rs.RotateObject(self.RoCirc,(0,0,0),180,None,True)
                self.Center2 = rs.CircleCenterPoint(self.Ro2Circ)
                CentPoint2 = rs.AddPoint(self.Center2)
                self.CircList.append([self.RoCirc,self.Ro2Circ])
                self.PtList.append(CentPoint)
                self.PtList.append(CentPoint2)
                Del1 = rs.PointInPlanarClosedCurve(CentPoint,self.Circle)
                Del2 = rs.PointInPlanarClosedCurve(CentPoint2,self.Circle)
                self.RecList.append([Del1,Del2])
                self.CoordList.append([self.Center,self.Center2])
                
                if (Del1 == 0):
                    self.Recursion(num)          
            rs.DeleteObject(self.Circle)
        def Recursion(self, num):
                if (num <= 1):
                    return 1
                else:
                    rs.ScaleObjects(self.RoCirc, self.Center ,(self.num,self.num,0), True)
                    rs.ScaleObjects(self.Ro2Circ, self.Center2 ,(self.num,self.num,0), True)
                    return self.Recursion (num - 1)
            
    Mfun = rs.GetInteger("Choose 1 for sine curve. Choose 2 for cosine curve. Choose 3 for tangent curve.")
    Angle = rs.GetInteger("Enter angle of rotation",15,1,180) 
    num = rs.GetInteger("Enter number of recursions",3,2,5)
    obj01 = Base(144, Mfun,num, Angle)
    obj01.Crv()
    obj01.Recursion(num)
  • A generation of random sided shapes at random sizes. These generated shapes are then put through a recursion process, of which the user determined the amount of recursions. The user can input the interger  value to determine the degree of the curve to determine its smoothness.
  • import rhinoscriptsyntax as rs
    import math
    import random 
    rs.EnableRedraw(False)
    class Rec:
        
        def __init__(self,i,_num, putin):
            self.i = i
            self.num = _num
            self.putin = putin
            self.Ngon = None
            self.PtList = None
            self.pt1 = (-self.i/2,-self.i/2,0)
            self.pt2 = (self.i/2,-self.i/2,0)
            self.pt3 = (self.i/2,self.i/2,0)
            self.pt4 = (-self.i/2,self.i/2,0)
            self.Border = rs.AddCurve([self.pt1,self.pt2,self.pt3,self.pt4,self.pt1],1)       
            
        def PointField(self):
            x = random.uniform(-self.i/2,self.i/2)
            y = random.uniform(-self.i/2,self.i/2)
            pt = rs.AddPoint(x,y,0)
            self.PtList = rs.PointCoordinates(pt)       
            I = random.randint(3,5)        
            self.NgonList = []
            
            if (I == 3):
                ThreePt1 = rs.AddPoint((random.randint(0,4)), (random.randint(0,4)), 0)
                ThreePt2 = rs.AddPoint((random.randint(-4,0)), (random.randint(-4,4)), 0)
                ThreePt3 = rs.AddPoint((random.randint(0,4)), (random.randint(-4,0)), 0)
                Shape = rs.AddCurve([ThreePt1,ThreePt2,ThreePt3,ThreePt1], self.putin)
                self.Ngon = rs.MoveObject(Shape,self.PtList)
                self.NgonList.append(self.Ngon)
                self.RecScale(num)
            elif (I == 4):
                FourPt1 = rs.AddPoint((random.randint(0,4)), (random.randint(0,4)), 0)
                FourPt2 = rs.AddPoint((random.randint(-4,0)), (random.randint(0,4)), 0)
                FourPt3 = rs.AddPoint((random.randint(-4,0)), (random.randint(-4,0)), 0)
                FourPt4 = rs.AddPoint((random.randint(0,4)), (random.randint(-4,0)), 0) 
                Shape = rs.AddCurve([FourPt1,FourPt2,FourPt3,FourPt4,FourPt1], self.putin)
                self.Ngon = rs.MoveObject(Shape,self.PtList)
                self.NgonList.append(self.Ngon)
                self.RecScale(num)
            elif (I == 5):
                FivePt1 = rs.AddPoint((random.randint(-2,2)), (random.randint(2,4)), 0)
                FivePt2 = rs.AddPoint((random.randint(-4,-2)), (random.randint(2,4)), 0)
                FivePt3 = rs.AddPoint((random.randint(-4,0)), (random.randint(-4,0)), 0)
                FivePt4 = rs.AddPoint((random.randint(0,4)), (random.randint(-4,0)), 0) 
                FivePt5 = rs.AddPoint((random.randint(2,4)), (random.randint(2,4)), 0)
                Shape = rs.AddCurve([FivePt1,FivePt2,FivePt3,FivePt4,FivePt5,FivePt1], self.putin)
                self.Ngon = rs.MoveObject(Shape,self.PtList)
                self.NgonList.append(self.Ngon)
                self.RecScale(num)
            
        def RecScale(self, num):
            if (num <=1):
                return 1
            else:
                rs.ScaleObject(self.Ngon,self.PtList,[self.num*1,self.num*1,0], True )
                return self.RecScale(num-1)
                    
    num = 3
    put = rs.GetInteger("Input Curve Degrees",1,1,4)
    obj01 = Rec(144,num,put)
    for i in range(0,100):
        obj01.PointField()
    obj01.RecScale(num)
  • FRACTAL
  • An experiment in fractals and recursion. A user drawn line that can have a fractal begin to substitute for the line. The top line is the fractal and the bottom group is a second generation fractal line put through five recursions
  • import rhinoscriptsyntax as rs
    import math
    import random
    randptList = []
    bList =[]

    def RandPoints (Cap):
        for i in range (random.randint(2,Cap)):
            X = random.randrange(-100,100)
            Y = random.randrange(-100,100)
            Z = 0
            pt = [X,Y,Z]
            rs.AddPoint(pt)
            randptList.append (pt)
           
    def RandLines(number):
        
        for i in rs.frange (0,number,1):
            
            base = rs.AddPolyline(randptList)
            rs.MoveObject(base,[0,i**2,0])
            bList.append(base)
        
    number = rs.GetInteger("input number of starting points",3,1,10)
    Cap = rs.GetInteger("input range cap for random lines",3,1,10)
    RandPoints(Cap)
    RandLines(number)
    # 2D fractal script selecting a generator curve and base curve
    def Frac (gen, base, steps, step):
        newbase = []
        
        baseList = rs.CurvePoints(base)
               
        #Base object replaces each segment with generator curve
        for i in range (len(baseList)-1):
            newbase.append(Replace(baseList[i], baseList[i+1], gen, i))
        #old base curve is deleted and new replacement curves are joined        
        if (len(baseList)) != 1:
            rs.DeleteObjects(base)
            base = rs.JoinCurves(newbase[:])
            
            rs.DeleteObjects(newbase[:])
        if step < steps:
            Frac(gen, base, steps, step+1)
                
    #Replace function            
    def Replace (Pt_Start, Pt_End, genCrv, i):
        origin = [0,0,0]
        vecStart = rs.VectorCreate (Pt_Start, origin)
        vecEnd = rs.VectorCreate (Pt_End, origin)
        genStart = rs.CurveStartPoint (genCrv)
        genEnd = rs.CurveEndPoint(genCrv)
        vecGenStart = rs.VectorCreate (genStart, origin)
        vecGenEnd = rs.VectorCreate (genEnd, origin)
        temp_end = rs.VectorSubtract (vecEnd, vecStart)
        temp_Gen_end = rs.VectorSubtract (vecGenEnd, vecGenStart)
        mag = rs.VectorLength (temp_end)
        amag = rs.VectorLength (temp_Gen_end)
        scale_factor = mag / amag
        
        CpyGen = rs.CopyObject (genCrv)
        rs.ScaleObject (CpyGen, genStart, [scale_factor, scale_factor, scale_factor])
        anglex = math.atan2 (temp_end[1], temp_end [0])
        anglex = math.degrees(anglex)
        angle_gen_x = math.atan2(temp_Gen_end[1], temp_Gen_end[0])
        angle_gen_x = math.degrees(angle_gen_x)
        if angle_gen_x != 0:
            rs.RotateObject(CpyGen, genStart, anglex - angle_gen_x)
        else:
            rs.RotateObject(CpyGen, genStart, anglex)        
            if i%2 is 0:
                rs.MirrorObject(CpyGen, rs.CurveStartPoint(CpyGen), rs.CurveEndPoint(CpyGen))
        translation = rs.VectorCreate(vecStart, genStart)
        newBase = rs.MoveObject(CpyGen, translation)
        return newBase
    gen = rs.GetObject("generator", 4, True)
    #base = [rs.GetObject("base", 4, True)]
    steps = rs.GetInteger("number of stops", 3, 1, 15)
    for k in range(0,number):
        base = bList[k]
        Frac (gen, base, steps, 3)
        if k == number:
            base = bList[k+1]
            rs.DeleteObject(base)
  • An experimentation in sponge coding. This is similar to the fractal type code above but rahther than a 2d line this code replaces a solid with a fractal geometry, by placing this fractal at the corners, and midpoints of the edges of a solid. 
  • import rhinoscriptsyntax as rs
    import random
    corners=[0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,1,1,1,1,0,1,1]
    random.seed (1) # optional, in order to repeat randomness
     
    arrObject =[]
    arrBoolObject =[]
    object=rs.AddBox (corners)
    eObject=rs.ScaleObject (object, [0,0,0], [8,8,50])
    arrBoolObject.append(eObject)
    # Create boolean difference tower to use as base for sponge
    for i in range (50):
        xPos=random.randrange(0,6)
        yPos=random.randrange(0,6)
        zPos=random.randrange(0,45)
        object=rs.AddBox (corners)
        position=[xPos,yPos,zPos]
        mObject=rs.MoveObject (object,position)
        sObject=rs.ScaleObject (mObject, position, [random.uniform(4,6),random.uniform(4,6),random.uniform(4,6)])
        arrObject.append(sObject)
        zoneObject=rs.BooleanDifference(arrBoolObject[i],arrObject[i])
        arrBoolObject.append(zoneObject)
    def Main():
        obj = []
        obj.append(rs.GetObject("Set base object:", 16))
        step = 1
        obj02 = []
        obj02.append(rs.GetObject("Set modular object:",16))
        endstep = rs.GetInteger("How many steps?", 3,1,8)
        rs.EnableRedraw(False)
        Sponge(obj, obj02, step, endstep)
        
    # Each step a base object is replaced
    def Sponge(obj, obj02, step, endstep):
        #Getting edge curves of the base object
        
        edge = rs.DuplicateEdgeCurves(obj)
        end = []
        mid = []
        scale = []
        # End and mid point for every edge curve
        
        for i in range(len(edge)):
            end.append(rs.CurveEndPoint(edge[i]))
            mid.append(rs.CurveMidPoint(edge[i]))
        #Deleting duplicates
        rs.DeleteObjects(edge)
        #end = list(set(end))
        #Scaling base object and placing it in every corner
        for i in range(len(end)):
            scale.append(rs.ScaleObject(obj02, end[i], (1/4,1/4,1/4), True))
        #Scaling base object and placing it to the middle of every edge
        for i in range(len(mid)):
            scale.append(rs.ScaleObject(obj02, mid[i],(1/4, 1/4, 1/4), True))
        #Deleting base ojb
        rs.DeleteObject(obj)
      
        #Recursion
        if step < endstep:
            for i in range(len(scale)):
                Sponge(scale[i],step+1, endstep)
        
        #print scale
        Union = rs.BooleanUnion(scale)
        print Union
                
    Main()
  • Stochastic search box. Tis code introduces a stochastic search within a defined area adding color to even and odd boxes.
  • import rhinoscriptsyntax as rs
    import random
    corners=[0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,1,1,1,1,0,1,1]
            
    arrX=[]        
    arrY=[]
    arrZ=[]
     
    oddList = []
    evenList = []
    # Stochastic search for loop
    for i in range (500):
        sv=0
        
        while True:
            rx=random.randint(0,10)
            ry=random.randint(0,10)
            rz=random.randint(0,10)
            
            overlap = False
            for j in range (i):
                diffx=abs(arrX[j]-rx)
                diffy=abs(arrY[j]-ry)
                diffz=abs(arrZ[j]-rz)       
                if(diffx<1 and diffy<1 and diffz<1):
                    overlap=True        
            if overlap==False:
                arrX.append(rx)
                arrY.append(ry)
                arrZ.append(rz)
                cube=rs.AddBox(corners)
                rs.MoveObject(cube,[arrX[i],arrY[i],arrZ[i]])
                # Modulus of 2 to place objects into 2 different lists
                if i%2 == 0:
                    evenList.append(cube)
                else:
                    oddList.append(cube)
                break    
       
            if sv>1000:
                print "not found"
                break
            sv=sv+1

    # Color definition
    def parametercolor(parameter):
        red = parameter
        if red<0: red=0
        if red>255: red=255
        return (red,150,255-red)
        
    # Calling the even and odd lists to have them colored
    rs.ObjectColor(evenList,parametercolor(50))
    rs.ObjectColor(oddList,parametercolor(250))
     
  • The above two images show a stochastic search bridge that also uses color to change boxes. This begins to represent the use of python to start identifying spaces and relationships for master planning.
  • import rhinoscriptsyntax as rs
    import random
    corners=[0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,1,1,1,1,0,1,1]
            
    arrX=[]        
    arrY=[]
    arrZ=[]
    ZList = []
    OList = []
    TList = []
    # Stochastic search for loop
    for i in range (1500):
            
        sv=0
        
        while True:
            rx=random.randint(0,50)
            ry=random.randint(0,10)
            rz=random.randint(0,30)
            
            overlap = False
            for j in range (i):
                diffx=abs(arrX[j]-rx)
                diffy=abs(arrY[j]-ry)
                diffz=abs(arrZ[j]-rz)
                
                if(diffx<1 and diffy<1 and diffz<1):
                    overlap=True
                    
            if overlap==False:
                arrX.append(rx)
                arrY.append(ry)
                arrZ.append(rz)
                cube=rs.AddBox(corners)
                rs.MoveObject(cube,[arrX[i],arrY[i],arrZ[i]])
                rs.ScaleObject(cube,[0,0,0],[8,4,1])
    # Modulus of 3 to place objects into 3 different lists
                if i%3 == 0:
                    ZList.append(cube)
                elif i%3 == 1:
                    OList.append(cube)
                elif i%3 == 2:
                    TList.append(cube)
                break
            
            if sv>10000:
                print "not found"
                break
            sv=sv+1
    # Color and scale according to lists
    rs.ObjectColor(OList,[0,200,0])
    rs.ObjectColor(TList,[0,0,150])
    rs.ScaleObject(ZList,[0,0,0],[2,3,1])
    rs.MoveObject(ZList,[-200,-45,0])
    # Delete 3/4 of objects in TList
    for k in range (500):
        obj = TList[k]
        if k%4 == 0:
            rs.DeleteObject(obj)
        elif k%4 == 1:
            rs.ScaleObject(obj,[0,0,0],[2,3,1])
            rs.MoveObject(obj,[-200,-45,0])
        if k%4 == 2:
            rs.DeleteObject(obj)
        if k%4 == 3:
            rs.DeleteObject(obj)
    # Delete 1/2 of objects in OList        
    for l in range (500):
        obj = OList[l]
        if l%2 == 0:
            rs.DeleteObject(obj)
        elif l%2 == 1:
            rs.ScaleObject(obj,[0,0,0],[2,3,1])
            rs.MoveObject(obj,[-200,-45,0])
  • This was an experimentation on an automated boolean difference. The user can input a plane and extrude it by a drawn line to custom create an object within a bounding frame (which is what can be seen on the right). The result of the boolean difference is on the left with spheres randomly removed from the user created solid. 
  • import rhinoscriptsyntax as rs
    import random
    corners=[0,0,0,1,0,0,1,1,0,0,1,0,0,0,1,1,0,1,1,1,1,0,1,1]
    pt1=[0,0,0]
    pt2=[100,0,0]
    pt3=[100,100,0]
    pt4=[0,100,0]
    pt5=[0,0,100]
    pt6=[100,0,100]
    pt7=[100,100,100]
    pt8=[0,100,100]
    arrObject =[]
    arrBoolObject =[]
    backupList = []
    # Create Bounding Box
    BndBox = rs.AddCurve([pt1,pt2,pt3,pt4,pt1,pt5,pt6,pt2,pt6,pt7,pt3,pt7,pt8,pt4,pt8,pt5],1)
    # User Inputs, Asking to draw an Object within the Bounding Box
    surf = rs.GetObject("Draw or select surface to be extruded",8)
    curve = rs.GetObject("Draw or select curve to be extruded along", 4)
    object = rs.ExtrudeSurface(surf,curve,True)
    arrBoolObject.append(object)
    Range = rs.GetInteger("Input max range for random boolean")
    S1Range = rs.GetInteger("Input min scale range for boolean objects")
    S2Range = rs.GetInteger("Input max scale range for boolean objects")
     
    # Boolean Difference definition
    def Boolean(sv,R,S1,S2):
        
        for i in range (sv,R):
            xPos=random.uniform(5,90)
            yPos=random.uniform(5,90)
            zPos=random.randrange(5,90)
            object=rs.AddSphere([0,0,0],2)
            position=[xPos,yPos,zPos]
            mObject=rs.MoveObject (object,position)
            sObject=rs.ScaleObject (mObject, position,                      [random.randrange(S1,S2),random.randrange(S1,S2),random.randrange(S1,S2)])
            arrObject.append(sObject)
            backupList.append(arrBoolObject[i])
            zoneObject=rs.BooleanDifference(arrBoolObject[i],arrObject[i])
            
            print i
            print sv
            print arrBoolObject [i]
            print zoneObject
            
    # Failsafe: If ZoneObject outputs NONE, return to the definition (BETA)
            if zoneObject == []:
                print "none"
                arrBoolObject.append(backupList[i])
                sv = sv+1
                return Boolean(sv,R,S1,S2)
            
            else:
                arrBoolObject.append(zoneObject)
                sv = sv+1       
            
    # Executing definition 
    sv = 0
    Boolean(sv,Range,S1Range,S2Range)
    rs.DeleteObjects([surf,curve,BndBox])
     
  • This is an experimentation on an automated boolean union. The user is allowed to create a srface that is then extruded, moved and then finally booleaned together. 
  • import rhinoscriptsyntax as rs
    import random
    randList=[]
    def randPoint ():
        pt1 =[random.randrange(1,100),random.randrange(1,100),0]
        pt2 =[random.randrange(-100,-1),random.randrange(1,100),0]
        pt3 =[random.randrange(-100,-1),random.randrange(-100,-1),0]
        pt4 =[random.randrange(1,100),random.randrange(-100,-1),0]
        randList.append(pt1)
        randList.append(pt2)
        randList.append(pt3)
        randList.append(pt4)
        randList.append(pt1)

    arrObject =[]
    arrBoolObject =[]
    #Random object creation for loop
    for i in range (20):
        rPos=random.uniform(-.5,.5)
        rScale=random.uniform (2.5,3.5)
        randPoint()
        baseCrv = rs.AddCurve(randList,1)
        srf = rs.AddPlanarSrf(baseCrv)
        line = rs.AddLine([0,0,0],[0,0,10])
        object = rs.ExtrudeSurface(srf, line)
        rs.DeleteObject(line)
        #Move the objects in a random X,Y direction as well as 
        #Moving the objects first up then done in order to create a 
        #Grouping of objects that appears more random
        position=[rPos,rPos,-i+3]
        mObject=rs.MoveObject (object,position)
        sObject=rs.ScaleObject (mObject, position, [rScale,rScale,1])
        arrObject.append(sObject)
            
    #Union the first two objects
    initBoolObject=rs.BooleanUnion ([arrObject[0],arrObject[1]]) 
    arrBoolObject.append(initBoolObject)
    #Boolean union for loop
    for j in range (2,20):
        
        #Union the next object with the previous boolean object
        resultObject=rs.BooleanUnion ([arrBoolObject[j-2],arrObject[j]])
        
        #Append the boolean object to the boolean array
        arrBoolObject.append(resultObject) 
  • FLOCKING
  • import random
    import math
    import rhinoscriptsyntax as rs
     
    class Bird():
        def __init__(self):
            self.X = random.randint(0, 50)
            self.Y = random.randint(0, 50)
            self.Z = random.randint(0, 100)
            self.VelocityX = random.randint(1,20) / 10.0
            self.VelocityY  = random.randint(1,20) / 10.0
            self.VelocityZ = random.randint(1,20) / 10.0
            self.MaxVelocity = 5
            self.rand = None

        def drawBird(self):
            point = [self.X, self.Y, self.Z]
            pts = rs.AddPoint(point)
            rs.MoveObject(self.randomShape(),pts) 
        def randomShape(self):
            self.rand = random.randint(1,3)
            if self.rand == 1:
                sphere = rs.AddSphere((0,0,0),2)
                randNum = random.randint(1,4)
                sSphere = rs.ScaleObject(sphere,(0,0,0),
        (randNum,randNum,randNum))
                return sSphere
            if self.rand == 2:
                box = rs.AddBox([0,0,0,2,0,0,2,2,0,0,2,0,0,0,
        2,2,0,2,2,2,2,0,2,2])
                sBox = rs.ScaleObject(box,(0,0,0),
        (random.randint(1,4),random.randint(1,4),
        random.randint(1,4))) 
                return sBox
            if self.rand == 3:
                cone = rs.AddCone((0,0,0),3,2)
                sCone = rs.ScaleObject(cone,(0,0,0),
        (random.randint(1,4),random.randint(1,4),
        random.randint(1,4)))
                return sCone
        def getDistance(self, otherBird):
            distX = self.X - otherBird.X
            distY = self.Y - otherBird.Y
            distZ = self.Z - otherBird.Z
            result = math.sqrt(distX * distX + distY * distY + distZ * distZ) 
            return result      
        def stayClose(self, nearBirds):
            diff_X = 0
            diff_Y = 0
            diff_Z = 0
            avgX = 0
            avgY = 0
            avgZ = 0
            for otherBird in nearBirds:
                diff_X = diff_X + (self.X - otherBird.X)
                diff_Y = diff_Y + (self.Y - otherBird.Y)
                diff_Z = diff_Z + (self.Z - otherBird.Z)
            avgX = diff_X/ len(nearBirds)
            avgY = diff_Y/ len(nearBirds)
            avgZ = diff_Z/ len(nearBirds)
            self.VelocityX = self.VelocityX - (avgX / 100)
            self.VelocityY = self.VelocityY - (avgY / 100)
            self.VelocityZ = self.VelocityZ - (avgZ / 100)         
        def matchVelocity(self, nearBirds):
            diff_X = 0
            diff_Y = 0
            diff_Z = 0
            avgX = 0
            avgY = 0
            avgZ = 0
            for otherBird in nearBirds:
                diff_X = diff_X + otherBird.VelocityX
                diff_Y = diff_Y + otherBird.VelocityY
                diff_Z = diff_Z + otherBird.VelocityZ
            avgX = diff_X / len(nearBirds)
            avgY = diff_Y / len(nearBirds)
            avgZ = diff_Z / len(nearBirds)
            self.VelocityX = self.VelocityX + (avgX / 40)
            self.VelocityY = self.VelocityY + (avgY / 40)
            self.VelocityZ = self.VelocityZ + (avgZ / 40)

        def avoidCollision(self, nearBirds):
            distanceX = 0
            distanceY = 0
            distanceZ = 0
            minDistance = 30
            for otherBird in nearBirds:
                distance = self.getDistance(otherBird)
                if  distance < minDistance:
                    diff_X = (self.X - otherBird.X) 
                    if diff_X >= 0: 
                        diff_X = math.sqrt(minDistance) - diff_X
                    else:
                        diff_X = -math.sqrt(minDistance) - diff_X   
                    distanceX = distanceX + diff_X                  
                    diff_Y = (self.Y - otherBird.Y)               
                    if diff_Y >= 0: 
                        diff_Y = math.sqrt(minDistance) - diff_Y
                    else:
                        diff_Y = -math.sqrt(minDistance) - diff_Y   
                    distanceY = distanceY + diff_Y 
                    diff_Z = (self.Z - otherBird.Z)
                    if diff_Z >= 0:
                        diff_Z = math.sqrt(minDistance) - diff_Z
                    else:
                        diff_Z = -math.sqrt(minDistance) - diff_Z
                    distanceZ = distanceZ + diff_Z
            self.VelocityX = self.VelocityX - (distanceX / 5)
            self.VelocityY = self.VelocityY - (distanceY / 5)
            self.VelocityZ = self.VelocityZ - (distanceZ / 5)
        def updatePosition(self):
            self.X = self.X + self.VelocityX
            self.Y = self.Y + self.VelocityY
            self.Z = self.Z + self.VelocityZ
            pos = rs.AddPoint(self.X, self.Y, self.Z)
            return pos
        def checkMaxVelocity(self):
            velocityConditionX = abs(self.VelocityX) > self.MaxVelocity
            velocityConditionY = abs(self.VelocityY) > self.MaxVelocity
            velocityConditionZ = abs(self.VelocityZ) > self.MaxVelocity
            if velocityConditionX or velocityConditionY or velocityConditionZ:
                maxValue = max(abs(self.VelocityX), abs(self.VelocityY), abs(self.VelocityZ))
                scaleFactor = self.MaxVelocity / maxValue
                self.VelocityX = self.VelocityX * scaleFactor
                self.VelocityY = self.VelocityY * scaleFactor
                self.VelocityZ = self.VelocityZ * scaleFactor       
        def checkBounds(self):
            boundX = 50
            boundY = 50
            boundZ = 100
            if self.X < 0 and self.VelocityX < 0:
                self.VelocityX = -self.VelocityX
            if self.X > boundX and self.VelocityX > 0:
                self.VelocityX = -self.VelocityX
            if self.Y < 0 and self.VelocityY < 0:
                self.VelocityY = -self.VelocityY
            if self.Y > boundY and self.VelocityY > 0:
                self.VelocityY = -self.VelocityY
            if self.Z < 0 and self.VelocityZ < 0:
                self.VelocityZ = -self.VelocityZ
            if self.Z > boundZ and self.VelocityZ > 0:
                self.VelocityZ = -self.VelocityZ

        def updateBird(self, NearBirds):
            self.stayClose(NearBirds)
            self.matchVelocity(NearBirds)
            self.avoidCollision(NearBirds)
            self.checkBounds();
            self.checkMaxVelocity()
            point = self.updatePosition()
            self.drawBird()
            return point
             
    class Flock():
        def __init__(self):
            self.AllBirds = []
            self.NearBirds = []
            self.NumBirds = 5
            self.Repeat = 50 
        def generateInitialBirds(self):
            for i in range(self.NumBirds):
                b = Bird()
                self.AllBirds.append(b)
     
        def runFlocking(self):
                
            for bird in self.AllBirds:
                BirdPath = []
                for i in range(self.Repeat):
                    self.findNearBirds(bird)
                    pathPoint = bird.updateBird(self.NearBirds)
                    BirdPath.append(pathPoint)
                    
                Path = rs.AddCurve(BirdPath,2)
                rs.AddPipe(Path,0,.5,1,2)
        def findNearBirds(self, bird):
            self.NearBirds = []
            for newBird in self.AllBirds:
                if bird == newBird:
                    pass
                else:
                    distance = bird.getDistance(newBird)
                    if distance < 600:
                        self.NearBirds.append(newBird)
                    else:
                        pass
        def main(self):
            self.generateInitialBirds()
            self.runFlocking()
             
    f = Flock()
    f.main()

                 
  • import random
    import math
    import rhinoscriptsyntax as rs
     
    class Bird():
        def __init__(self):
            self.X = random.randint(0, 50)
            self.Y = random.randint(0, 50)
            self.Z = random.randint(0, 100)
            self.VelocityX = random.randint(1,20) / 10.0
            self.VelocityY  = random.randint(1,20) / 10.0
            self.VelocityZ = random.randint(1,20) / 10.0
            self.MaxVelocity = 5
             
        def drawBird(self):
            point = [self.X, self.Y, self.Z]
            rs.AddPoint(point)
             
        def getDistance(self, otherBird):
            distX = self.X - otherBird.X
            distY = self.Y - otherBird.Y
            distZ = self.Z - otherBird.Z
            result = math.sqrt(distX * distX + distY * distY + distZ * distZ)
            
            return result
             
        def stayClose(self, nearBirds):
            diff_X = 0
            diff_Y = 0
            diff_Z = 0
            avgX = 0
            avgY = 0
            avgZ = 0
            for otherBird in nearBirds:
                diff_X = diff_X + (self.X - otherBird.X)
                diff_Y = diff_Y + (self.Y - otherBird.Y)
                diff_Z = diff_Z + (self.Z - otherBird.Z)
            avgX = diff_X/ len(nearBirds)
            avgY = diff_Y/ len(nearBirds)
            avgZ = diff_Z/ len(nearBirds)
            self.VelocityX = self.VelocityX - (avgX / 100)
            self.VelocityY = self.VelocityY - (avgY / 100)
            self.VelocityZ = self.VelocityZ - (avgZ / 100)
             
        def matchVelocity(self, nearBirds):
            diff_X = 0
            diff_Y = 0
            diff_Z = 0
            avgX = 0
            avgY = 0
            avgZ = 0
            for otherBird in nearBirds:
                diff_X = diff_X + otherBird.VelocityX
                diff_Y = diff_Y + otherBird.VelocityY
                diff_Z = diff_Z + otherBird.VelocityZ
            avgX = diff_X / len(nearBirds)
            avgY = diff_Y / len(nearBirds)
            avgZ = diff_Z / len(nearBirds)
            self.VelocityX = self.VelocityX + (avgX / 40)
            self.VelocityY = self.VelocityY + (avgY / 40)
            self.VelocityZ = self.VelocityZ + (avgZ / 40)        
     
        def avoidCollision(self, nearBirds):
            distanceX = 0
            distanceY = 0
            distanceZ = 0
            minDistance = 30
            for otherBird in nearBirds:
                distance = self.getDistance(otherBird)
                if  distance < minDistance:
                    diff_X = (self.X - otherBird.X) 
                    if diff_X >= 0: 
                        diff_X = math.sqrt(minDistance) - diff_X
                    else:
                        diff_X = -math.sqrt(minDistance) - diff_X   
                    distanceX = distanceX + diff_X                  
                 
                    diff_Y = (self.Y - otherBird.Y)               
                    if diff_Y >= 0: 
                        diff_Y = math.sqrt(minDistance) - diff_Y
                    else:
                        diff_Y = -math.sqrt(minDistance) - diff_Y   
                    distanceY = distanceY + diff_Y 
                    
                    diff_Z = (self.Z - otherBird.Z)
                    if diff_Z >= 0:
                        diff_Z = math.sqrt(minDistance) - diff_Z
                    else:
                        diff_Z = -math.sqrt(minDistance) - diff_Z
                    distanceZ = distanceZ + diff_Z
            self.VelocityX = self.VelocityX - (distanceX / 5)
            self.VelocityY = self.VelocityY - (distanceY / 5)
            self.VelocityZ = self.VelocityZ - (distanceZ / 5)
        def updatePosition(self):
            self.X = self.X + self.VelocityX
            self.Y = self.Y + self.VelocityY
            self.Z = self.Z + self.VelocityZ
            pos = rs.AddPoint(self.X, self.Y, self.Z)
            return pos
        def checkMaxVelocity(self):
            velocityConditionX = abs(self.VelocityX) > self.MaxVelocity
            velocityConditionY = abs(self.VelocityY) > self.MaxVelocity
            velocityConditionZ = abs(self.VelocityZ) > self.MaxVelocity
            if velocityConditionX or velocityConditionY or velocityConditionZ:
                maxValue = max(abs(self.VelocityX), abs(self.VelocityY), abs(self.VelocityZ))
                scaleFactor = self.MaxVelocity / maxValue
                self.VelocityX = self.VelocityX * scaleFactor
                self.VelocityY = self.VelocityY * scaleFactor
                self.VelocityZ = self.VelocityZ * scaleFactor
        def checkBounds(self):
            boundX = 50
            boundY = 50
            boundZ = 100
            if self.X < 0 and self.VelocityX < 0:
                self.VelocityX = -self.VelocityX
            if self.X > boundX and self.VelocityX > 0:
                self.VelocityX = -self.VelocityX
            if self.Y < 0 and self.VelocityY < 0:
                self.VelocityY = -self.VelocityY
            if self.Y > boundY and self.VelocityY > 0:
                self.VelocityY = -self.VelocityY
            if self.Z < 0 and self.VelocityZ < 0:
                self.VelocityZ = -self.VelocityZ
            if self.Z > boundZ and self.VelocityZ > 0:
                self.VelocityZ = -self.VelocityZ
                 

        def updateBird(self, NearBirds):
            self.stayClose(NearBirds)
            self.matchVelocity(NearBirds)
            self.avoidCollision(NearBirds)
            self.checkBounds();
            self.checkMaxVelocity()
            point = self.updatePosition()
            self.drawBird()
            return point
             
    class Flock():
        def __init__(self):
            self.AllBirds = []
            self.NearBirds = []
            self.NumBirds = 10
            self.Repeat = 100
             
        def generateInitialBirds(self):
            for i in range(self.NumBirds):
                b = Bird()
                self.AllBirds.append(b)
     
        def runFlocking(self):
                
            for bird in self.AllBirds:
                BirdPath = []
                for i in range(self.Repeat):
                    self.findNearBirds(bird)
                    
                    pathPoint = bird.updateBird(self.NearBirds)
                    BirdPath.append(pathPoint)
                    
                Path = rs.AddCurve(BirdPath)
                randSize = random.uniform(.25,2)
                pipe = rs.AddPipe(Path,0,randSize,1,2)
                r = random.randint(0,255)
                g = random.randint(0,255)
                b = random.randint(0,255)
                rs.ObjectColor(pipe, (r,g,b))
        def findNearBirds(self, bird):
            self.NearBirds = []
            for newBird in self.AllBirds:
                if bird == newBird:
                    pass
                else:
                    distance = bird.getDistance(newBird)
                    if distance < 600:
                        self.NearBirds.append(newBird)
                    else:
                        pass
        def main(self):
            self.generateInitialBirds()
            self.runFlocking()
             
    f = Flock()
    f.main()
  • import random
    import math
    import rhinoscriptsyntax as rs
    random.seed(1)
    class Bird():
        def __init__(self):
            self.X = random.randint(0, 50)
            self.Y = random.randint(0, 50)
            self.Z = random.randint(0, 100)
            self.VelocityX = random.randint(1,20) / 10.0
            self.VelocityY  = random.randint(1,20) / 10.0
            self.VelocityZ = random.randint(1,20) / 10.0
            self.MaxVelocity = 5
        def drawBird(self):
            point = [self.X, self.Y, self.Z]
            pts = rs.AddPoint(point)
            
            
        def getDistance(self, otherBird):
            distX = self.X - otherBird.X
            distY = self.Y - otherBird.Y
            distZ = self.Z - otherBird.Z
            result = math.sqrt(distX * distX + distY * distY + distZ * distZ)
            
            return result
             
        def stayClose(self, nearBirds):
            diff_X = 0
            diff_Y = 0
            diff_Z = 0
            avgX = 0
            avgY = 0
            avgZ = 0
            for otherBird in nearBirds:
                diff_X = diff_X + (self.X - otherBird.X)
                diff_Y = diff_Y + (self.Y - otherBird.Y)
                diff_Z = diff_Z + (self.Z - otherBird.Z)
            avgX = diff_X/ len(nearBirds)
            avgY = diff_Y/ len(nearBirds)
            avgZ = diff_Z/ len(nearBirds)
            self.VelocityX = self.VelocityX - (avgX / 100)
            self.VelocityY = self.VelocityY - (avgY / 100)
            self.VelocityZ = self.VelocityZ - (avgZ / 100)
             
        def matchVelocity(self, nearBirds):
            diff_X = 0
            diff_Y = 0
            diff_Z = 0
            avgX = 0
            avgY = 0
            avgZ = 0
            for otherBird in nearBirds:
                diff_X = diff_X + otherBird.VelocityX
                diff_Y = diff_Y + otherBird.VelocityY
                diff_Z = diff_Z + otherBird.VelocityZ
            avgX = diff_X / len(nearBirds)
            avgY = diff_Y / len(nearBirds)
            avgZ = diff_Z / len(nearBirds)
            self.VelocityX = self.VelocityX + (avgX / 40)
            self.VelocityY = self.VelocityY + (avgY / 40)
            self.VelocityZ = self.VelocityZ + (avgZ / 40)
        def avoidCollision(self, nearBirds):
            distanceX = 0
            distanceY = 0
            distanceZ = 0
            minDistance = 30
            for otherBird in nearBirds:
                distance = self.getDistance(otherBird)
                if  distance < minDistance:
                    diff_X = (self.X - otherBird.X) 
                    if diff_X >= 0: 
                        diff_X = math.sqrt(minDistance) - diff_X
                    else:
                        diff_X = -math.sqrt(minDistance) - diff_X   
                    distanceX = distanceX + diff_X                  
                 
                    diff_Y = (self.Y - otherBird.Y)               
                    if diff_Y >= 0: 
                        diff_Y = math.sqrt(minDistance) - diff_Y
                    else:
                        diff_Y = -math.sqrt(minDistance) - diff_Y   
                    distanceY = distanceY + diff_Y 
                    
                    diff_Z = (self.Z - otherBird.Z)
                    if diff_Z >= 0:
                        diff_Z = math.sqrt(minDistance) - diff_Z
                    else:
                        diff_Z = -math.sqrt(minDistance) - diff_Z
                    distanceZ = distanceZ + diff_Z
             
            self.VelocityX = self.VelocityX - (distanceX / 5)
            self.VelocityY = self.VelocityY - (distanceY / 5)
            self.VelocityZ = self.VelocityZ - (distanceZ / 5)
        def updatePosition(self):
            self.X = self.X + self.VelocityX
            self.Y = self.Y + self.VelocityY
            self.Z = self.Z + self.VelocityZ
            pos = rs.AddPoint(self.X, self.Y, self.Z)
            return pos
        def checkMaxVelocity(self):
            velocityConditionX = abs(self.VelocityX) > self.MaxVelocity
            velocityConditionY = abs(self.VelocityY) > self.MaxVelocity
            velocityConditionZ = abs(self.VelocityZ) > self.MaxVelocity
            if velocityConditionX or velocityConditionY or velocityConditionZ:
                maxValue = max(abs(self.VelocityX), abs(self.VelocityY), abs(self.VelocityZ))
                scaleFactor = self.MaxVelocity / maxValue
                self.VelocityX = self.VelocityX * scaleFactor
                self.VelocityY = self.VelocityY * scaleFactor
                self.VelocityZ = self.VelocityZ * scaleFactor      
        def checkBounds(self):
            boundX = 10
            boundY = 10
            boundZ = 50
            if self.X < 0 and self.VelocityX < 0:
                self.VelocityX = -self.VelocityX
            if self.X > boundX and self.VelocityX > 0:
                self.VelocityX = -self.VelocityX
            if self.Y < 0 and self.VelocityY < 0:
                self.VelocityY = -self.VelocityY
            if self.Y > boundY and self.VelocityY > 0:
                self.VelocityY = -self.VelocityY
            if self.Z < 0 and self.VelocityZ < 0:
                self.VelocityZ = -self.VelocityZ
            if self.Z > boundZ and self.VelocityZ > 0:
                self.VelocityZ = -self.VelocityZ
        def updateBird(self, NearBirds):
            self.stayClose(NearBirds)
            self.matchVelocity(NearBirds)
            self.avoidCollision(NearBirds)
            self.checkBounds();
            self.checkMaxVelocity()
            point = self.updatePosition()
            self.drawBird()
            return point
    class Flock():
        def __init__(self, input):
            self.AllBirds = []
            self.NearBirds = []
            self.NumBirds = input
            self.Repeat = 50
            self.crvList = []
        def generateInitialBirds(self):
            for i in range(self.NumBirds):
                b = Bird()
                self.AllBirds.append(b)
        def runFlocking(self):
            for bird in self.AllBirds:
                BirdPath = []
                for i in range(self.Repeat):
                    self.findNearBirds(bird)
                    pathPoint = bird.updateBird(self.NearBirds)
                    BirdPath.append(pathPoint)
                Path = rs.AddCurve(BirdPath)
                self.crvList.append(Path)
        def findNearBirds(self, bird):
            self.NearBirds = []
            for newBird in self.AllBirds:
                if bird == newBird:
                    pass
                else:
                    distance = bird.getDistance(newBird)
                    if distance < 600:
                        self.NearBirds.append(newBird)
                    else:
                        pass
        def main(self):
            self.generateInitialBirds()
            self.runFlocking()
        
    input = rs.GetInteger("input number of curves")
    f = Flock(input)
    f.main()
    obj1 = rs.GetObjects("select curves")
    rs.AddLoftSrf(obj1)

  • import random
    import math
    import rhinoscriptsyntax as rs
     
    class Bird():
        def __init__(self):
            self.X = random.randint(0, 50)
            self.Y = random.randint(0, 50)
            self.Z = random.randint(0, 100)
            self.VelocityX = random.randint(1,20) / 10.0
            self.VelocityY  = random.randint(1,20) / 10.0
            self.VelocityZ = random.randint(1,20) / 10.0
            self.MaxVelocity = 5
             
        def drawBird(self):
            point = [self.X, self.Y, self.Z]
            pts = rs.AddPoint(point)
            rs.AddSphere(pts,1)
             
        def getDistance(self, otherBird):
            distX = self.X - otherBird.X
            distY = self.Y - otherBird.Y
            distZ = self.Z - otherBird.Z
            result = math.sqrt(distX * distX + distY * 
                distY + distZ * distZ)
            return result
             
        def stayClose(self, nearBirds):
            diff_X = 0
            diff_Y = 0
            diff_Z = 0
            avgX = 0
            avgY = 0
            avgZ = 0
            for otherBird in nearBirds:
                diff_X = diff_X + (self.X - otherBird.X)
                diff_Y = diff_Y + (self.Y - otherBird.Y)
                diff_Z = diff_Z + (self.Z - otherBird.Z)
            avgX = diff_X/ len(nearBirds)
            avgY = diff_Y/ len(nearBirds)
            avgZ = diff_Z/ len(nearBirds)
            self.VelocityX = self.VelocityX - (avgX / 100)
            self.VelocityY = self.VelocityY - (avgY / 100)
            self.VelocityZ = self.VelocityZ - (avgZ / 100)
             
        def matchVelocity(self, nearBirds):
            diff_X = 0
            diff_Y = 0
            diff_Z = 0
            avgX = 0
            avgY = 0
            avgZ = 0
            for otherBird in nearBirds:
                diff_X = diff_X + otherBird.VelocityX
                diff_Y = diff_Y + otherBird.VelocityY
                diff_Z = diff_Z + otherBird.VelocityZ
            avgX = diff_X / len(nearBirds)
            avgY = diff_Y / len(nearBirds)
            avgZ = diff_Z / len(nearBirds)
            self.VelocityX = self.VelocityX + (avgX / 40)
            self.VelocityY = self.VelocityY + (avgY / 40)
            self.VelocityZ = self.VelocityZ + (avgZ / 40)
             
     
        def avoidCollision(self, nearBirds):
            distanceX = 0
            distanceY = 0
            distanceZ = 0
            minDistance = 30
            for otherBird in nearBirds:
                distance = self.getDistance(otherBird)
                if  distance < minDistance:
                    diff_X = (self.X - otherBird.X) 
                    if diff_X >= 0: 
                        diff_X = math.sqrt(minDistance) - diff_X
                    else:
                        diff_X = -math.sqrt(minDistance) - diff_X   
                    distanceX = distanceX + diff_X                  
                 
                    diff_Y = (self.Y - otherBird.Y)               
                    if diff_Y >= 0: 
                        diff_Y = math.sqrt(minDistance) - diff_Y
                    else:
                        diff_Y = -math.sqrt(minDistance) - diff_Y   
                    distanceY = distanceY + diff_Y 
                    
                    diff_Z = (self.Z - otherBird.Z)
                    if diff_Z >= 0:
                        diff_Z = math.sqrt(minDistance) - diff_Z
                    else:
                        diff_Z  = -math.sqrt(minDistance) - diff_Z
                    distanceZ = distanceZ + diff_Z
             
            self.VelocityX = self.VelocityX - (distanceX / 5)
            self.VelocityY = self.VelocityY - (distanceY / 5)
            self.VelocityZ = self.VelocityZ - (distanceZ / 5)
            
        def updatePosition(self):
            self.X = self.X + self.VelocityX
            self.Y = self.Y + self.VelocityY
            self.Z = self.Z + self.VelocityZ
            pos = rs.AddPoint(self.X, self.Y, self.Z)
            return pos
             
       
        def checkMaxVelocity(self):
            velocityConditionX = abs(self.VelocityX) > self.MaxVelocity
            velocityConditionY = abs(self.VelocityY) > self.MaxVelocity
            velocityConditionZ = abs(self.VelocityZ) > self.MaxVelocity
            if velocityConditionX or velocityConditionY or velocityConditionZ:
                maxValue = max(abs(self.VelocityX), 
        abs(self.VelocityY), abs(self.VelocityZ))
                scaleFactor = self.MaxVelocity / maxValue
                self.VelocityX = self.VelocityX * scaleFactor
                self.VelocityY = self.VelocityY * scaleFactor
                self.VelocityZ = self.VelocityZ * scaleFactor
                 
        def checkBounds(self):
            boundX = 50
            boundY = 50
            boundZ = 100
            if self.X < 0 and self.VelocityX < 0:
                self.VelocityX = -self.VelocityX
            if self.X > boundX and self.VelocityX > 0:
                self.VelocityX = -self.VelocityX
            if self.Y < 0 and self.VelocityY < 0:
                self.VelocityY = -self.VelocityY
            if self.Y > boundY and self.VelocityY > 0:
                self.VelocityY = -self.VelocityY
            if self.Z < 0 and self.VelocityZ < 0:
                self.VelocityZ = -self.VelocityZ
            if self.Z > boundZ and self.VelocityZ > 0:
                self.VelocityZ = -self.VelocityZ
                 
        def updateBird(self, NearBirds):
            self.stayClose(NearBirds)
            self.matchVelocity(NearBirds)
            self.avoidCollision(NearBirds)
            self.checkBounds();
            self.checkMaxVelocity()
            point = self.updatePosition()
            self.drawBird()
            return point
             
    class Flock():
        def __init__(self):
            self.AllBirds = []
            self.NearBirds = []
            self.NumBirds = 15
            self.Repeat = 50
             
        def generateInitialBirds(self):
            for i in range(self.NumBirds):
                b = Bird()
                self.AllBirds.append(b)
     
        def runFlocking(self):
                
            for bird in self.AllBirds:
                BirdPath = []
                for i in range(self.Repeat):
                    self.findNearBirds(bird)
                    
                    pathPoint = bird.updateBird(self.NearBirds)
                    BirdPath.append(pathPoint)
                    
                Path = rs.AddCurve(BirdPath,2)
                rs.AddPipe(Path,0,.5,1,2)
                 
        def findNearBirds(self, bird):
            self.NearBirds = []
            for newBird in self.AllBirds:
                if bird == newBird:
                    pass
                else:
                    distance = bird.getDistance(newBird)
                    if distance < 600:
                        self.NearBirds.append(newBird)
                    else:
                        pass
        def main(self):
            self.generateInitialBirds()
            self.runFlocking()
             
    f = Flock()
    f.main()
         
  • import random
    import math
    import rhinoscriptsyntax as rs
     
    class Bird():
        def __init__(self):
            self.X = random.randint(0, 50)
            self.Y = random.randint(0, 50)
            self.Z = random.randint(0, 100)
            self.VelocityX = random.randint(1,20) / 10.0
            self.VelocityY  = random.randint(1,20) / 10.0
            self.VelocityZ = random.randint(1,20) / 10.0
            self.MaxVelocity = 5
             
        def drawBird(self):
            point = [self.X, self.Y, self.Z]
            rs.AddPoint(point)
             
        def getDistance(self, otherBird):
            distX = self.X - otherBird.X
            distY = self.Y - otherBird.Y
            distZ = self.Z - otherBird.Z
            result = math.sqrt(distX * distX + distY * distY + distZ * distZ)
            
            return result
             
        def stayClose(self, nearBirds):
            diff_X = 0
            diff_Y = 0
            diff_Z = 0
            avgX = 0
            avgY = 0
            avgZ = 0
            for otherBird in nearBirds:
                diff_X = diff_X + (self.X - otherBird.X)
                diff_Y = diff_Y + (self.Y - otherBird.Y)
                diff_Z = diff_Z + (self.Z - otherBird.Z)
            avgX = diff_X/ len(nearBirds)
            avgY = diff_Y/ len(nearBirds)
            avgZ = diff_Z/ len(nearBirds)
            self.VelocityX = self.VelocityX - (avgX / 100)
            self.VelocityY = self.VelocityY - (avgY / 100)
            self.VelocityZ = self.VelocityZ - (avgZ / 100)
             
        def matchVelocity(self, nearBirds):
            diff_X = 0
            diff_Y = 0
            diff_Z = 0
            avgX = 0
            avgY = 0
            avgZ = 0
            for otherBird in nearBirds:
                diff_X = diff_X + otherBird.VelocityX
                diff_Y = diff_Y + otherBird.VelocityY
                diff_Z = diff_Z + otherBird.VelocityZ
            avgX = diff_X / len(nearBirds)
            avgY = diff_Y / len(nearBirds)
            avgZ = diff_Z / len(nearBirds)
            self.VelocityX = self.VelocityX + (avgX / 40)
            self.VelocityY = self.VelocityY + (avgY / 40)
            self.VelocityZ = self.VelocityZ + (avgZ / 40)
     
        def avoidCollision(self, nearBirds):
            distanceX = 0
            distanceY = 0
            distanceZ = 0
            minDistance = 30
            for otherBird in nearBirds:
                distance = self.getDistance(otherBird)
                if  distance < minDistance:
                    diff_X = (self.X - otherBird.X) 
                    if diff_X >= 0: 
                        diff_X = math.sqrt(minDistance) - diff_X
                    else:
                        diff_X = -math.sqrt(minDistance) - diff_X   
                    distanceX = distanceX + diff_X                  
                 
                    diff_Y = (self.Y - otherBird.Y)               
                    if diff_Y >= 0: 
                        diff_Y = math.sqrt(minDistance) - diff_Y
                    else:
                        diff_Y = -math.sqrt(minDistance) - diff_Y   
                    distanceY = distanceY + diff_Y 
                    
                    diff_Z = (self.Z - otherBird.Z)
                    if diff_Z >= 0:
                        diff_Z = math.sqrt(minDistance) - diff_Z
                    else:
                        diff_Z = -math.sqrt(minDistance) - diff_Z
                    distanceZ = distanceZ + diff_Z
             
            self.VelocityX = self.VelocityX - (distanceX / 5)
            self.VelocityY = self.VelocityY - (distanceY / 5)
            self.VelocityZ = self.VelocityZ - (distanceZ / 5)
            
        def updatePosition(self):
            self.X = self.X + self.VelocityX
            self.Y = self.Y + self.VelocityY
            self.Z = self.Z + self.VelocityZ
            pos = rs.AddPoint(self.X, self.Y, self.Z)
            return pos
        def checkMaxVelocity(self):
            velocityConditionX = abs(self.VelocityX) > self.MaxVelocity
            velocityConditionY = abs(self.VelocityY) > self.MaxVelocity
            velocityConditionZ = abs(self.VelocityZ) > self.MaxVelocity
            if velocityConditionX or velocityConditionY or velocityConditionZ:
                maxValue = max(abs(self.VelocityX), abs(self.VelocityY), abs(self.VelocityZ))
                scaleFactor = self.MaxVelocity / maxValue
                self.VelocityX = self.VelocityX * scaleFactor
                self.VelocityY = self.VelocityY * scaleFactor
                self.VelocityZ = self.VelocityZ * scaleFactor
                 
      
       def checkBounds(self):
            boundX = 50
            boundY = 50
            boundZ = 100
            if self.X < 0 and self.VelocityX < 0:
                self.VelocityX = -self.VelocityX
            if self.X > boundX and self.VelocityX > 0:
                self.VelocityX = -self.VelocityX
            if self.Y < 0 and self.VelocityY < 0:
                self.VelocityY = -self.VelocityY
            if self.Y > boundY and self.VelocityY > 0:
                self.VelocityY = -self.VelocityY
            if self.Z < 0 and self.VelocityZ < 0:
                self.VelocityZ = -self.VelocityZ
            if self.Z > boundZ and self.VelocityZ > 0:
                self.VelocityZ = -self.VelocityZ
                 
        def updateBird(self, NearBirds):
            self.stayClose(NearBirds)
            self.matchVelocity(NearBirds)
            self.avoidCollision(NearBirds)
            self.checkBounds();
            self.checkMaxVelocity()
            point = self.updatePosition()
            self.drawBird()
            return point
             
    class Flock():
        def __init__(self):
            self.AllBirds = []
            self.NearBirds = []
            self.NumBirds = 10
            self.Repeat = 100
            
            self.eList = []
            self.oList = []
            self.zList = []
            self.yList = []
        def generateInitialBirds(self):
            for i in range(self.NumBirds):
                b = Bird()
                self.AllBirds.append(b)
     
        def runFlocking(self):
                
            for bird in self.AllBirds:
                BirdPath = []
                for i in range(self.Repeat):
                    self.findNearBirds(bird)
                    
                    pathPoint = bird.updateBird(self.NearBirds)
                    BirdPath.append(pathPoint)
                   
                for k in range(i):
                    pt = BirdPath[k]
                    if k%4 == 0:
                        self.eList.append(pt)
                    if k%4 == 1:
                        self.oList.append(pt)
                    if k%4 == 2:
                        self.zList.append(pt)
                    if k%4 == 3:
                        self.yList.append(pt)
                eCrv = rs.AddCurve(self.eList)
                rs.AddPipe(eCrv,0,.25,0,2)
                
                oCrv = rs.AddCurve(self.oList)
                rs.AddPipe(oCrv,0,.25,0,2)
                
                zCrv = rs.AddCurve(self.zList)
                rs.AddPipe(zCrv,0,.25,0,2)
                
                yCrv = rs.AddCurve(self.zList)
                rs.AddPipe(yCrv,0,.25,0,2)
                
        def findNearBirds(self, bird):
            self.NearBirds = []
            for newBird in self.AllBirds:
                if bird == newBird:
                    pass
                else:
                    distance = bird.getDistance(newBird)
                    if distance < 600:
                        self.NearBirds.append(newBird)
                    else:
                        pass
        def main(self):
            self.generateInitialBirds()
            self.runFlocking()
             
    f = Flock()
    f.main()

    rs.AddSphere([0,0,5], 10)
    rs.AddSphere([40,0,5], 10)
    rs.AddSphere([40,40,5], 10)
    rs.AddSphere([0,40,5], 10)
    rs.AddSphere([0,0,95], 10)
    rs.AddSphere([40,0,95], 10)
    rs.AddSphere([40,40,95], 10)
    rs.AddSphere([0,40,95], 10)