RhinoScript substitution system aggregation

From KokkugiaWiki

this tutorial builds off a simple rhinoScript recursive aggregation script while adding object types and a set of conditional substitution rules.

the script requires a file with appropriately named objects which can be downloaded here

Option Explicit


Call Main()
Sub Main()

	Dim gens, sLoc, i, j, arrTemp, objArrSingle(), objArr(2), refPtsSingle(), refPts(2), sObjArr
	
	' user input - gens + start loc
	gens = Rhino.GetReal("how many generations", 10)
	sLoc = Rhino.GetPoint("select a starting location")
	
	' compile named objects into arrays
	For i = 0 To 2
		
		ReDim objArrSingle(9)
		
		For j = 0 To 9			
			arrTemp = Rhino.ObjectsByName("obj_" & CStr(i) & "_" & CStr(j) )
			If Not isarray(arrTemp) Then Exit Sub
			objArrSingle(j) = arrTemp(0)
		Next	
		
		objArr(i) = objArrSingle
		
	Next
	
	' reference points / base
	For i = 0 To 2
		
		ReDim refPtsSingle(2)
		For j = 1 To 3
			refPtsSingle(j-1) = Rhino.PointCoordinates(objArr(i)(j))
		Next
		
		refPts(i) = refPtsSingle
		
	Next
	
	' make start object - "a"
	sObjArr = Rhino.CopyObjects(objArr(0), refPts(0)(0), sLoc)
	
	' call recursive function
	substitute objArr, refPts, sObjArr, gens	
	
End Sub


Function substitute(objArr, refPts, sObj, gens)

	Dim objType, newObjArr, target, nextObj
	
	' conditional - if - gens
	If gens > 0 Then
		
		' get type
		objType = Rhino.GetObjectData(sObj(0), "section", "type")
		
		' rules based on type
		Select Case objType
			
			Case "a" ' a-b
				target = 0  '''' 0 or 1
				nextObj = 1  '''' 0 or 1 or 2 (a,b,c)
				' orient the object - use as input to a recursive function call
				newObjArr = orient(sObj, refPts(nextObj), objArr(nextObj), target)
				substitute objArr, refPts, newObjArr, gens-1
			
			Case "b" ' b-ca
				target = 0  '''' 0 or 1
				nextObj = 2  '''' 0 or 1 or 2  (a,b,c)
				newObjArr = orient(sObj, refPts(nextObj), objArr(nextObj), target)
				substitute objArr, refPts, newObjArr, gens-1
				target = 1  '''' 0 or 1
				nextObj = 0  '''' 0 or 1 or 2 (a,b,c)
				newObjArr = orient(sObj, refPts(nextObj), objArr(nextObj), target)
				substitute objArr, refPts, newObjArr, gens-1
			
			Case "c" ' c-a
				target = 1  '''' 0 or 1
				nextObj = 0  '''' 0 or 1 or 2 (a,b,c)
				newObjArr = orient(sObj, refPts(nextObj), objArr(nextObj), target)
				substitute objArr, refPts, newObjArr, gens-1		
			
		End Select	
		
	End If

End Function



Function orient(sObj, refPts, objArr, tarIndex)

	Dim tarArrPts(), i, newObjs
	
	' decides on target
	If tarIndex = 0 Then
		
		' target 1
		For i = 4 To 6
			ReDim Preserve tarArrPts(i-4)
			tarArrPts(i-4) = Rhino.PointCoordinates(sObj(i))
		Next
		
	Else
		
		' target 2
		For i = 7 To 9
			ReDim Preserve tarArrPts(i-7)
			tarArrPts(i-7) = Rhino.PointCoordinates(sObj(i))
		Next
		
	End If
	
	' orients objs
	newObjs= Rhino.OrientObjects(objArr, refPts, tarArrPts, 1)
	For i = 0 To UBound(newObjs)
		Rhino.ObjectName newObjs(i), ""
	Next
	orient = newObjs

End Function



the following script assigns names and types to the objects to run the above script



Call assignType()
Sub assignType()
	
	Dim strObject
	For i = 0 To 2
		For j = 0 To 9
			If j = 0 Then
				strObject = Rhino.GetObject("select object " & CStr(i) & " mesh")
				Select Case i
					Case 0
					 	Rhino.SetObjectData strObject, "section", "type", "a"
					Case 1
						Rhino.SetObjectData strObject, "section", "type", "b"
					Case 2
						Rhino.SetObjectData strObject, "section", "type", "c"
				End Select
			Else	
				strObject = Rhino.GetObject("select object " & CStr(i) & " point "  & CStr(j), 1)	
			End If
			
			Rhino.ObjectName strObject, "obj_" & CStr(i) & "_" & CStr(j)
		Next			
	Next
	
End Sub



this script assigns a type to the objects as object data

Call assignType()
Sub assignType()
	
	Dim strObject
	
	strObject = Rhino.GetObject("select object a")
	Rhino.SetObjectData strObject, "section", "type", "a"
	strObject = Rhino.GetObject("select object b")
	Rhino.SetObjectData strObject, "section", "type", "b"
	strObject = Rhino.GetObject("select object c")
	Rhino.SetObjectData strObject, "section", "type", "c"

End Sub


this script prints object data

Call printType()
Sub printType()
	
	Dim strObject
	
	strObject = Rhino.GetObject("select object to test type")
	Rhino.Print Rhino.GetObjectData(strObject, "section", "type")
	
	
End Sub


......another version of the code

Option Explicit

Call Main()

Sub Main()
	
	Dim gens, arrObjs(2), arrObjSingle(9), i, j, basePoint, startObjs, startPos, arrObjTemp
	
	' user input: gens, 1 mesh, 9 points - into a single array
	gens = Rhino.GetReal("how many generations", 7)
	startPos = Rhino.GetPoint("select a starting position")
	
	' arrObjs( (mesh, pt1, pt2, pt3.....pt9), (mesh, pt1, pt2, pt3.....pt9), (mesh, pt1, pt2, pt3.....pt9) )
	' arrObjSingle(mesh, pt1, pt2, pt3.....pt9)
	For j = 0 To 2
		For i = 0 To 9
			arrObjTemp = Rhino.ObjectsByName("obj_" & j & "_" & i)
			arrObjSingle(i) = arrObjTemp(0)
		Next
		arrObjs(j) = arrObjSingle		
	Next
	
	' get object 1 base point
	basePoint = Rhino.PointCoordinates(arrObjs(0)(1))
	
	' copy the first object
	startObjs = Rhino.CopyObjects(arrObjs(0), basePoint, startPos)
	
	' call the recursive function
	Call substitute(arrObjs, gens, startObjs)
	
End Sub



Function substitute(arrObjs, gens, currentObjs)

	Dim objType, newArrObjs
	
	' conditional statement
	If gens > 1 Then
		
		objType = Rhino.GetObjectData(currentObjs(0), "section", "type")
		
		' rule sets - call aggregate function - 
		Select Case objType
			
			Case "a" ' a - b
				' call the aggregate function
				newArrObjs = aggregate(currentObjs, arrObjs(1), 1)		
				' call substitute function - RECURSIVE
				Call substitute(arrObjs, gens-1, newArrObjs)
			
			Case "b" ' b - c
				newArrObjs = aggregate(currentObjs, arrObjs(2), 1)	
				Call substitute(arrObjs, gens-1, newArrObjs)
			
				newArrObjs = aggregate(currentObjs, arrObjs(1), 2)	
				Call substitute(arrObjs, gens-1, newArrObjs)
			
			Case "c" ' c - ac
				newArrObjs = aggregate(currentObjs, arrObjs(0), 2)	
				Call substitute(arrObjs, gens-1, newArrObjs)
			
				newArrObjs = aggregate(currentObjs, arrObjs(2), 1)	
				Call substitute(arrObjs, gens-1, newArrObjs)			
			
		End Select	
	
	End If
	

End Function



Function aggregate(arrCurrentObjs, arrNewObjs, target)

	Dim arrRefPts(2), arrTarPts(2)
	
	' compile an array of refPoints + targetPoints (x2)
	arrRefPts(0) = Rhino.PointCoordinates(arrNewObjs(1))
	arrRefPts(1) = Rhino.PointCoordinates(arrNewObjs(2))
	arrRefPts(2) = Rhino.PointCoordinates(arrNewObjs(3))
	
	If target = 1 Then
		arrTarPts(0) = Rhino.PointCoordinates(arrCurrentObjs(4))		
		arrTarPts(1) = Rhino.PointCoordinates(arrCurrentObjs(5))
		arrTarPts(2) = Rhino.PointCoordinates(arrCurrentObjs(6))		
	Else	
		arrTarPts(0) = Rhino.PointCoordinates(arrCurrentObjs(7))		
		arrTarPts(1) = Rhino.PointCoordinates(arrCurrentObjs(8))	
		arrTarPts(2) = Rhino.PointCoordinates(arrCurrentObjs(9))			
	End If
	
	' orient objects
	aggregate = Rhino.OrientObjects(arrNewObjs, arrRefPts, arrTarPts, 1)

End Function





Views