Sunday, April 29, 2012

Corals - Surface Dependant 3D Branching

  


Input : Surface from Rhino
Outputs: Quad Tessellated Surface with 3D Branches growing normal, of the centre of each tessellation.


3D branching depends on surface curvature, changes in size, branching levels and random range for angles of branches.




import rhinoscriptsyntax as rs
import random 
import scriptcontext
rs.EnableRedraw(False)

surface = rs.GetObject('select surface',8)

udomain = rs.SurfaceDomain(surface,0)
vdomain = rs.SurfaceDomain(surface,1)

stepu = 15
stepv = 15

divisionsu  = udomain[1] / stepu
divisionsv = vdomain[1] / stepv
surfaceptv = []

## GRID OF POINTS UV##
for u in range(0,stepu+1):
    listupt = []
    for v in rs.frange(0,vdomain[1],divisionsv):
        
        pt = rs.EvaluateSurface(surface,u*divisionsu,v)
        pt1 = rs.AddPoint(pt)
        listupt.append(pt1)
    surfaceptv.append(listupt)


##ROW MIDPOINTS##
midpoints1 = []
for i in range(0,stepu+1):
    points1 = []
    for j in range(0,stepv-1):
        a = surfaceptv[i][j]
        acoord = rs.PointCoordinates(a)
        b = surfaceptv[i][j+1]
        bcoord = rs.PointCoordinates(b)
        cX = (acoord[0]+bcoord[0])/2 
        cY = (acoord[1]+bcoord[1])/2 
        cZ = (acoord[2]+bcoord[2])/2 
        c = [cX,cY,cZ]
        points1.append(c)
    midpoints1.append(points1)

##FIND MIDPOINTS##
midpoints = []
for i in range(0,stepu):
    rows = []
    for j in range(0,stepv-1):
        
        a0 = midpoints1[0+i][j]
        a1 = midpoints1[1+i][j]
        mpX= (a0[0]+a1[0])/2
        mpY= (a0[1]+a1[1])/2
        mpZ= (a0[2]+a1[2])/2
        a = rs.AddPoint([mpX,mpY,mpZ])
        rows.append(a)
    midpoints.append(rows)

##curvature evaluation##
slope = []
for i in range(0,stepu):
    for j in range(0,stepv-1):
        
        p1 = rs.PointCoordinates(surfaceptv[0+i][0+j])
        p2 = rs.PointCoordinates(surfaceptv[0+i][1+j])
        p3 = rs.PointCoordinates(surfaceptv[1+i][1+j])
        p4 = rs.PointCoordinates(surfaceptv[1+i][0+j])
        
        p1o= p1[2]
        p2o= p2[2]
        p3o= p3[2]
        p4o= p4[2]
        po = [p1o,p2o,p3o,p4o]
        
        difference = max(po) - min(po)
        slope.append(difference)

smax =  max(slope)
smin =  min(slope)
srange = max(slope) - min(slope)
sint = srange/3
rangemid1 = smin + sint
rangemid2 = rangemid1 + sint

rad_low = 0.07
rad_mid = 0.1 
rad_high= 0.13

LineBList = []

lowslope = []
midslope = []
highslope= []

for i in range(0,stepu):
    for j in range(0,stepv-1):
        pl = rs.AddPolyline([surfaceptv[0+i][0+j],surfaceptv[1+i][0+j],surfaceptv[1+i][1+j],surfaceptv[0+i][1+j],surfaceptv[0+i][0+j]])       
        points = [surfaceptv[0+i][0+j],surfaceptv[1+i][0+j],surfaceptv[1+i][1+j],surfaceptv[0+i][1+j]]
        srf = rs.AddSrfPt(points)
        uv = rs.SurfaceClosestPoint(srf, midpoints[i][j])
        pt = rs.PointCoordinates(midpoints[i][j])
        norm = rs.SurfaceNormal(srf, uv)
        
        
        p1 = rs.PointCoordinates(surfaceptv[0+i][0+j])
        p2 = rs.PointCoordinates(surfaceptv[0+i][1+j])
        p3 = rs.PointCoordinates(surfaceptv[1+i][1+j])
        p4 = rs.PointCoordinates(surfaceptv[1+i][0+j])
        p1o= p1[2]
        p2o= p2[2]
        p3o= p3[2]
        p4o= p4[2]
        po = [p1o,p2o,p3o,p4o]
        
        difference = max(po) - min(po)
        
        if (difference < rangemid1) and (difference >= smin): 
            vect0 = rs.VectorScale(norm, 0.6)
        elif (difference < rangemid2 ) and (difference > rangemid1):
            vect0 = rs.VectorScale(norm, 0.8)
        elif (difference <= smax) and (difference > rangemid2):
            vect0 = rs.VectorScale(norm, 0.4)
        
        vect = rs.VectorAdd(vect0, pt)
        
        plane = rs.PlaneFromNormal(midpoints[i][j],norm)
        
        l = rs.AddLine(midpoints[i][j],vect)
        if (difference < rangemid1) and (difference >= smin): 
            lowslope.append(l)
            circle = rs.AddCircle(plane,rad_low)
            mcircle = rs.MoveObject(circle,vect0)
        elif (difference < rangemid2 ) and (difference > rangemid1):
            midslope.append(l)
            circle = rs.AddCircle(plane,rad_mid)
            mcircle = rs.MoveObject(circle,vect0)
        elif (difference <= smax) and (difference > rangemid2):
            highslope.append(l)
            circle = rs.AddCircle(plane,rad_high)
            mcircle = rs.MoveObject(circle,vect0)
            
        loft = rs.AddLoftSrf([pl,circle])


## 3D BRANCHING##
def drawbranch1 (x, line):
    scriptcontext.escape_test()
    
    if x==0:
        return
    else:
        for i in range(0,4):
            end_pt = rs.CurveEndPoint(line)
            st_pt = rs.CurveStartPoint(line)
            rnd = random.randint(-50, 50)
            rndrot1 = random.randint(-40,40)
            rndrot2 = random.randint(-40,40)
            vect = rs.VectorCreate(end_pt, st_pt)
            vect = rs.VectorRotate(vect, rnd, [rndrot1,rndrot2,0])
            ptadd = rs.PointAdd(end_pt, vect)
            #cyl = rs.AddCylinder(st_pt,end_pt,rad_low,False)
            line = rs.AddLine(end_pt,ptadd)
            drawbranch1(x-1, line)

for i in range(len(lowslope)):
    a = drawbranch1(3, lowslope[i])



def drawbranch2 (x, line):
    scriptcontext.escape_test()
    if x==0:
        return
    else:
        for i in range(0,4):
            end_pt = rs.CurveEndPoint(line)
            st_pt = rs.CurveStartPoint(line)
            rnd = random.randint(-30, 30)
            rndrot1 = random.randint(-30,30)
            rndrot2 = random.randint(-30,30)
            vect = rs.VectorCreate(end_pt, st_pt)
            vect = rs.VectorRotate(vect, rnd, [rndrot1,rndrot2,0])
            ptadd = rs.PointAdd(end_pt, vect)
            #cyl = rs.AddCylinder(st_pt,end_pt,rad_mid,False)
            line = rs.AddLine(end_pt,ptadd)
            drawbranch2(x-1, line)

for i in range(len(midslope)):
    a = drawbranch2(3, midslope[i])



def drawbranch3 (x, line):
    scriptcontext.escape_test()
    if x==0:
        return
    else:
        for i in range(0,3):
            end_pt = rs.CurveEndPoint(line)
            st_pt = rs.CurveStartPoint(line)
            rnd = random.randint(-15, 15)
            rndrot1 = random.randint(-90,90)
            rndrot2 = random.randint(-90,90)
            vect = rs.VectorCreate(end_pt, st_pt)
            vect = rs.VectorRotate(vect, rnd, [rndrot1,rndrot2,0])
            ptadd = rs.PointAdd(end_pt, vect)
            #cyl = rs.AddCylinder(st_pt,end_pt,rad_high,False)
            line = rs.AddLine(end_pt,ptadd)
            drawbranch3(x-1, line)

for i in range(len(highslope)):
    a = drawbranch3(3, highslope[i])


No comments:

Post a Comment