 # Scaling Objects in Fractal Shape Generation (Script Broken)

Hi guys,

I’m new this semester both to Rhino and programming–I am making my way through David Rutten’s Rhino101 and finally decided to edit my script for a final project in a class I am taking. Unfortunately, the script that I edited that once worked is now broken, and I’m literally breaking it more trying to debug it.

The script is designed to make a set of rotated pentagons that branch each generation into 2 more pentagons. The original (working) script is here so you can see how I’ve broken it:
http://www.giuliopiacentino.com/tree-and-lake/

The idea was to:

1. Change the shapes to pentagons
2. Scale each object by a random amount (between .9 and 1.1) so that the final shapes could be booleaned together (this is where a lot of the trouble comes).

I would be really grateful for any help–since additional work I do seems to make the problem worse, rather than better.

Thanks again!
Ryan

``````    Sub makeGrowingTree
Rhino.CurrentLayer("AlgorithmTester")
Dim originPoint, arrPlane, arrPentagonOrigin, arr3dX, arr3dY, arr3dZ, advanceBy
'Shapes changed from circles to Pentagons, but any shape may be used
Dim pentagon, rotatedPentagon
'Declaring variables with the name of the shape helps understand, make sure to change these
Dim angleX:angleX = 15
Dim angleZ:angleZ = 25
'Sets Rotation Angle, in this case only rotating in the X and Z axis
originPoint = Array(0, 0, 0)
'Sets the origin
'Number of units you will increase in each generation.  This is fixed
Dim generations:generations = 3
'Number of times the script will run
Dim listGenerations()
ReDim listGenerations(generations,4^generations-1)
'Each time you are increasing the number of times you run the script by 4^n-1
Dim cumulativeRotations()
ReDim cumulativeRotations(4^generations-1)

Dim generationNum, childNum, colsToFill, startToFill, fillingChild

'draw the pentagon
arrPentagonOrigin = Array(0, 0, 0)
arr3dX = Array(1, 0, 0)
arr3dY = Array(0, 1, 0)
arr3dZ = Array(0, 0, 1)
arrPlane = Array(arrPentagonOrigin, arr3dX, arr3dY, arr3dZ)
'dimension of the pentagon
'Change the number of sides and size of the polygon.  First 5 is the radius, the second 5 is the number of sides
For childNum = 0 To 2 ^ generations - 1
cumulativeRotations(childNum) = 0
listGenerations(0, childNum) = pentagon
Next

For generationNum = 1 To generations
For childNum = 0 To 4 ^ generationNum - 1

colsToFill = 4 ^ (generations - generationNum)
startToFill = childNum * colsToFill

For fillingChild=0 To colsToFill - 1
If (childNum Mod 2) = 0 Then
cumulativeRotations(fillingChild + startToFill) = cumulativeRotations(fillingChild + startToFill) + angleX
Else
cumulativeRotations(fillingChild + startToFill) = cumulativeRotations(fillingChild + startToFill) - angleX
End If
Next

Dim dblLow:dblLow = 0.90
Dim dblHigh:dblHigh = 1.10
Randomize
Dim Random:Random = Rnd * (dblHigh - dblLow) + dblLow
Dim arrRand:arrRand = (Random,Random, Random)
arrPentagonOrigin = Rhino.CurveMidPoint(listGenerations(generationNum - 1, startToFill))
'CurveMidPoint replace Circle Center
'MsgBox generationNum

'the new circle is copied and repositioned
rotatedPentagon = Rhino.scaleObject(listGenerations(generationNum - 1, startToFill), arrPentagonOrigin, Array(0.8, 0.8, 0.8), True)
Rhino.RotateObject rotatedPentagon, originPoint, cumulativeRotations(startToFill), arr3dX, False
Rhino.RotateObject rotatedPentagon, originPoint, angleZ * Sqr(generationNum), arr3dZ, False
Rhino.ScaleObject(rotatedPentagon, arrPentagonOrigin, arrRand, False)

'MsgBox "Generation is " & generationNum & "." & Chr(13) & "Columns to fill are " & colsToFill & ". Start filling at " & startToFill & "."

For fillingChild=0 To colsToFill - 1
listGenerations(generationNum, fillingChild + startToFill) = rotatedPentagon
Next
Next
Next

'Prepare the 2-dimension array to a 1-dimension and loft
Dim arrCurves(), i
ReDim arrCurves(UBound(listGenerations,1))

For childNum=0 To UBound(listGenerations, 2)

For i=0 To UBound(listGenerations, 1)
arrCurves(i) = listGenerations(i, childNum)
Next

'Rhino.AddLoftSrf arrCurves, , , 1  'loose
'Rhino.AddLoftSrf arrCurves, , , 2  'tight

Next

End Sub

Rhino.EnableRedraw False
Call makeGrowingTree
Rhino.EnableRedraw True
``````

I’m not sure I understand how you want this scaled. But I’ve tweaked the original script a little. At least it work. tree1.rvb (3.1 KB)

Thanks Dale! Basically I want to be able to boolean the end lofts
together–Rhino was previously failing because the pentagons on each level
were the exact same size. My instructor told me to make each pentagon a
little bigger or smaller and then it would work. I figured this would be
possible in the script by just added a random scaling factor before each
pentagon is constructed. Is that something that shouldn’t work, or is
there a better way to get the end result to form a solid?

Thanks again!

Hi Ryan,

Why do you need a solid?

– Dale

This is a component in designs I’m making to print. In this case, it’s the
centerpiece of a table. I would like to have a solid so I can export to STL
and print it.

Thanks!
Ryan

Dale, I think I fixed the script based on looking at yours (I had changed
for some idiotic reason the generations to 4 in some spots). I think now I
have changed the pentagon size, but I expect the problem is that the origin
pentagon is the same. Is there any way I could move these or loft them in
a different way? Given the number of iterations, it would be a pain to do
this manually, but if there’s no other options, I suppose I’l have to…

``````Option Explicit
'Script written by <insert name>
'Script copyrighted by <insert company name>
'Script version Thursday, April 17, 2014 12:25:22 PM

'Edits and annotations 04-29-2014 by Ryan Borker + Dale Fugier (5-8-2014)
Rhino.DeleteObjects Rhino.AllObjects
Sub makeGrowingTree
Dim originPoint, arrPlane, arrPentagonOrigin, arr3dX, arr3dY, arr3dZ,
'Shapes changed from circles to Pentagons, but any shape may be used
Dim pentagon, rotatedPentagon
'Declaring variables with the name of the shape helps understand, make sure
to change these
Dim angleX:angleX = 15
Dim angleZ:angleZ = 25
'Sets Rotation Angle, in this case only rotating in the X and Z axis
originPoint = Array(0, 0, 0)
'Sets the origin
'Number of units you will increase in each generation.  This is fixed
Dim generations:generations = 3
'Number of times the script will run
Dim listGenerations()
ReDim listGenerations(generations,2^generations-1)
'Each time you are increasing the number of times you run the script by
2^n-1
Dim cumulativeRotations()
ReDim cumulativeRotations(2^generations-1)
Randomize

Dim generationNum, childNum, colsToFill, startToFill, fillingChild
'draw the pentagon
arrPentagonOrigin = Array(0, 0, 0)
arr3dX = Array(1, 0, 0)
arr3dY = Array(0, 1, 0)
arr3dZ = Array(0, 0, 1)
arrPlane = Array(arrPentagonOrigin, arr3dX, arr3dY, arr3dZ)
'dimension of the pentagon
'Change the number of sides and size of the polygon.  First 5 is the
radius, the second 5 is the number of sides
For childNum = 0 To 2 ^ generations - 1
cumulativeRotations(childNum) = 0
listGenerations(0, childNum) = pentagon
Next

For generationNum = 1 To generations
For childNum = 0 To 2 ^ generationNum - 1

colsToFill = 2 ^ (generations - generationNum)
startToFill = childNum * colsToFill

For fillingChild=0 To colsToFill - 1
If (childNum Mod 2) = 0 Then
cumulativeRotations(fillingChild + startToFill) =
cumulativeRotations(fillingChild + startToFill) + angleX
Else
cumulativeRotations(fillingChild + startToFill) =
cumulativeRotations(fillingChild + startToFill) - angleX
End If
Next

Dim dblLow:dblLow = 0.90
Dim dblHigh:dblHigh = 1.10
Dim random1:random1 = Rnd * (dblHigh - dblLow) + dblLow
Dim random2:random2 = Rnd * (dblHigh - dblLow) + dblLow
Dim random3:random3 = Rnd * (dblHigh - dblLow) + dblLow
Dim arrRand:arrRand = Array(random1, random2, random3)
arrPentagonOrigin = Rhino.CurveMidPoint(listGenerations(generationNum - 1,
startToFill))
'CurveMidPoint replace Circle Center
'MsgBox generationNum

'the new circle is copied and repositioned
rotatedPentagon = Rhino.scaleObject(listGenerations(generationNum - 1,
startToFill), arrPentagonOrigin, Array(0.8, 0.8, 0.8), True)
Rhino.RotateObject rotatedPentagon, originPoint,
cumulativeRotations(startToFill), arr3dX, False
Rhino.RotateObject rotatedPentagon, originPoint, angleZ *
Sqr(generationNum), arr3dZ, False
Rhino.ScaleObject rotatedPentagon, arrPentagonOrigin, arrRand, False

'MsgBox "Generation is " & generationNum & "." & Chr(13) & "Columns to fill
are " & colsToFill & ". Start filling at " & startToFill & "."

For fillingChild=0 To colsToFill - 1
listGenerations(generationNum, fillingChild + startToFill) =
rotatedPentagon
Next
Next
Next

'Prepare the 2-dimension array to a 1-dimension and loft
Dim arrCurves(), i
ReDim arrCurves(UBound(listGenerations,1))

For childNum=0 To UBound(listGenerations, 2)

For i=0 To UBound(listGenerations, 1)
arrCurves(i) = listGenerations(i, childNum)
Next