Scaling Objects in Fractal Shape Generation (Script Broken)


#1

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.AddLayer("Algorithm Tester")
	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
	advanceBy = Array(0, 0, 10)
	'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 
	pentagon = Rhino.addPolygon(arrPlane, 5, 5)
	'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.MoveObject rotatedPentagon, originPoint, advanceBy
			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  'normal
		'Rhino.AddLoftSrf arrCurves, , , 1  'loose
		'Rhino.AddLoftSrf arrCurves, , , 2  'tight
  
	Next


End Sub

Rhino.EnableRedraw False
Call makeGrowingTree
Rhino.EnableRedraw True

(Dale Fugier) #2

I’m not sure I understand how you want this scaled. But I’ve tweaked the original script a little. At least it work. :wink:

tree1.rvb (3.1 KB)


#3

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!


(Dale Fugier) #4

Hi Ryan,

Why do you need a solid?

– Dale


#5

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


#6

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

'Script copyright 06-09-2008 Giulio Piacentino
'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,
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
advanceBy = Array(0, 0, 10)
 '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
pentagon = Rhino.addPolygon(arrPlane, 5, 5)
 '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.MoveObject rotatedPentagon, originPoint, advanceBy
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  'normal
 'Rhino.AddLoftSrf arrCurves, , , 1  'loose
'Rhino.AddLoftSrf arrCurves, , , 2  'tight

Next

End Sub



Rhino.EnableRedraw False
Call makeGrowingTree
Rhino.EnableRedraw True