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])