Intense Workshop, "Recursion"
Roland Snooks (Kokkugia)
Rekursion er - i denne sammenhæng - en proces hvormed gentagelsen af samme enheder fortsætter kontinuerligt på samme eller lignende facon.
Eksempelvis, når overfladerne på to spejle er nøjagtigt parallelle eller vinkelrette på hinanden, vil der i det indlejrede billeder opstå en form for uendelig rekursion. Udtrykket består bl.a. af en række tilknyttede betydninger, der er udvoksede inden for andre discipliner, bl.a. lingvistik og logik.
Den mest almindelige anvendelse af rekursion er i matematik og datalogi, hvor det referer til processen der definerer funktioner. Denne proces vil således kunne anvendes inden for sin egen funktion. Altså, funktionen påkaldes på ny, inden for sig selv. Helt konkret definerer dette et uendeligt antal forekomster, der så i nogle tilfælde kan henvise til andre forekomster, men på en sådan måde, at der ikke kan forekomme noget endegyldigt dødt loop eller uendelig referencekæde.
Udtrykket bruges også mere generelt til at beskrive en proces med gentagelse af objekter på en tilsvarende måde.
![]()
RhinoScript, første skridt (2009):
Roland Snooks (Kokkugia)
Rekursion er - i denne sammenhæng - en proces hvormed gentagelsen af samme enheder fortsætter kontinuerligt på samme eller lignende facon.
Eksempelvis, når overfladerne på to spejle er nøjagtigt parallelle eller vinkelrette på hinanden, vil der i det indlejrede billeder opstå en form for uendelig rekursion. Udtrykket består bl.a. af en række tilknyttede betydninger, der er udvoksede inden for andre discipliner, bl.a. lingvistik og logik.
Den mest almindelige anvendelse af rekursion er i matematik og datalogi, hvor det referer til processen der definerer funktioner. Denne proces vil således kunne anvendes inden for sin egen funktion. Altså, funktionen påkaldes på ny, inden for sig selv. Helt konkret definerer dette et uendeligt antal forekomster, der så i nogle tilfælde kan henvise til andre forekomster, men på en sådan måde, at der ikke kan forekomme noget endegyldigt dødt loop eller uendelig referencekæde.
Udtrykket bruges også mere generelt til at beskrive en proces med gentagelse af objekter på en tilsvarende måde.

RhinoScript, første skridt (2009):
Option Explicit
' Script written by Claus Rytter Bruun de Neergaard, clausclaus.com
' Description:
' Takes a triangle and subdivides it. The function recursively calls itself, until length criteria is reached. 
Call Recursion1()
Sub Recursion1()
 
Dim strTriangle : strTriangle = Rhino.GetObject("select a triangle", 4)
    
	Dim dblMinLength : dblMinLength = Rhino.GetReal("length criteria", 1.0, 0.1, 10.0)
	
    
	' call function and pass variables
    
	Call Rhino.EnableRedraw(False)                                                    
               SubDivTri strTriangle, dblMinLength
    
	Call Rhino.EnableRedraw(True)
	
End Sub
Function SubDivTri(strTriangle, dblMinLength)
    
	Dim dblTriLength, arrVtxPts, arrMidPt0, arrMidPt1, arrMidPt2 
    
	Dim strTriangle0, strTriangle1, strTriangle2
		
	dblTriLength = Rhino.CurveLength(strTriangle)         If dblTriLength > dblMinLength Then‘ the vtx of the triangle
        
		arrVtxPts = Rhino.PolylineVertices(strTriangle)
        
		' get the mid points of the triangle
		        arrMidPt0 = Array((arrVtxPts(0)(0) + arrVtxPts(1)(0))/2, 
			(arrVtxPts(0)(1) +                     arrVtxPts(1)(1))/2, 
			(arrVtxPts(0)(2) + arrVtxPts(1)(2))/2)
         arrMidPt1 = Array((arrVtxPts(1)(0) + arrVtxPts(2)(0))/2, 
			(arrVtxPts(1)(1) +                     arrVtxPts(2)(1))/2, 
			(arrVtxPts(1)(2) + arrVtxPts(2)(2))/2)
        
		arrMidPt2 = Array((arrVtxPts(2)(0) + arrVtxPts(0)(0))/2, 
			(arrVtxPts(2)(1) +                     arrVtxPts(0)(1))/2, 
			(arrVtxPts(2)(2) + arrVtxPts(0)(2))/2)
        
		' draw three triangles
        
		strTriangle0 = Rhino.AddPolyline
            
			(Array(arrVtxPts(0), arrMidPt0, arrMidPt2, arrVtxPts(0)))
        
		strTriangle1 = Rhino.AddPolyline
			(Array(arrMidPt0, arrVtxPts(1), 
            
arrMidPt1, arrMidPt0))
        
		strTriangle2 = Rhino.AddPolyline
			(Array(arrMidPt1, arrVtxPts(2), 
            
arrMidPt2, arrMidPt1))
        
		' recursively call this function three times
        
		SubDivTri strTriangle0, dblMinLength
		SubDivTri strTriangle1, dblMinLength
        
		SubDivTri strTriangle2, dblMinLength
    
	End If
End Function
RhinoScript, andet skridt (2009):
Option Explicit
' script written by Roland Snooks, 'Complex Formations'-workshop
' CITA and Kokkugia, 2009
‘ Tweaked by Claus Rytter Bruun de Neergaard during the workshop
' Workshop held at The Royal Academy of Fine Arts, School of Architecture
Call Recursion2()
Sub Recursion2()
 
	Dim triangle: triangle = Rhino.GetObject("sel triangle surface", 8) 
	' call the recursive function
	Rhino.EnableRedraw False	
	subdivideTriangle triangle
	Rhino.EnableRedraw True
		
End Sub
Function SubDivTri(triangle)
	Dim triangleLength, vertexPts, midPt0, midPt1, midPt2
	Dim triangle1, triangle2, triangle3, triangle4
	Dim triangleCrv, centerPt, srfPara, srfNormal
	' get the border of the triangle	
	Rhino.SelectObject triangle
	Rhino.Command("DupBorder enter")
	triangleCrv = Rhino.FirstObject
	triangleLength = Rhino.CurveLength(triangleCrv)
	If triangleLength > 8 Then
		' get the vtx (vertex is the corner points on any geometry)
		vertexPts = Rhino.PolylineVertices(triangleCrv)
		' get the center point of the triangle
		centerPt = Rhino.CurveAreaCentroid(triangleCrv)
		' get the normal at that point
		srfPara = Rhino.SurfaceClosestPoint(triangle, centerPt(0))
		srfNormal = Rhino.SurfaceNormal(triangle, srfPara)
		' get the midpoints
		midPt0 = Array((vertexPts(0)(0) + vertexPts(1)(0))/2, _
			(vertexPts(0)(1)+vertexPts(1)(1))/2, _
			(vertexPts(0)(2)+vertexPts(1)(2))/2)
		midPt1 = Array((vertexPts(1)(0) + vertexPts(2)(0))/2, _
			(vertexPts(1)(1)+vertexPts(2)(1))/2, _
			(vertexPts(1)(2)+vertexPts(2)(2))/2)
		midPt2 = Array((vertexPts(2)(0) + vertexPts(0)(0))/2, _
			(vertexPts(2)(1)+vertexPts(0)(1))/2, _
			(vertexPts(2)(2)+vertexPts(0)(2))/2)
		' scale and normalize the vector
		srfNormal = Rhino.VectorUnitize(srfNormal)
		srfNormal = Rhino.VectorScale(srfNormal, triangleLength*0.1)
		' move the midpoints by the normal
		midPt0 = Rhino.VectorAdd(midPt0, srfNormal)
		midPt1 = Rhino.VectorAdd(midPt1, srfNormal)
		midPt2 = Rhino.VectorAdd(midPt2, srfNormal)
		' draw triangles - ADD SURFACES x 4
		triangle1= Rhino.AddSrfPt(Array(vertexPts(0), midPt0, midPt2))
		triangle2= Rhino.AddSrfPt(Array(midPt0, vertexPts(1), midPt1))
		triangle3= Rhino.AddSrfPt(Array(midPt1, vertexPts(2), midPt2))
		triangle4= Rhino.AddSrfPt(Array(midPt0, midPt1, midPt2))
		' call this function with the new triangles as input x 4
		SubDivTri triangle1
		SubDivTri triangle2
		SubDivTri triangle3
		SubDivTri triangle4
		' delete the original triangle 
		Rhino.DeleteObject triangle
		Rhino.DeleteObject triangleCrv
		Rhino.DeleteObjects Array(triangle, triangleCrv)
	End If  
End Function# script (re)written in Python from VBScript, 
# by Claus Rytter Bruun de Neergaard, clausclaus.com, 2021
# original script written with Roland Snooks at workshop 
# “Complex Formations"-workshop, CITA, 2009
import rhinoscriptsyntax as rs
# function(s)
def subDivisionTriangle(triangle):
 
    triangleCurve = rs.DuplicateSurfaceBorder(triangle)
    triangleLength = rs.CurveLength(triangleCurve)
    if (triangleLength > 5):
        # get the vertex (the corner points of any geometry)
        vertexPts = rs.PolylineVertices(triangleCurve)
        # get the center point of the triangle
        centerPt = rs.CurveAreaCentroid(triangleCurve)
        # get the normal at center point
        surfaceParameter = rs.SurfaceClosestPoint(triangle, centerPt[0])
        surfaceNormal = rs.SurfaceNormal(triangle, surfaceParameter)
        surfaceNormal = surfaceNormal * -1
        # insert point at center point (just to test it out)
        pt = rs.AddPoint(centerPt[0][0], centerPt[0][1], centerPt[0][2])
        # get the mid-points
        individualCurves = rs.ExplodeCurves(triangleCurve)
        midPt0 = rs.CurveMidPoint(individualCurves[0])
        midPt1 = rs.CurveMidPoint(individualCurves[1])
        midPt2 = rs.CurveMidPoint(individualCurves[2]
        # scale and normalize the vector
        surfaceNormal = rs.VectorUnitize(surfaceNormal)
        surfaceNormal = rs.VectorScale(surfaceNormal, triangleLength * 0.1)
        # move the midpoints by / along the normal
        midPt0 = rs.VectorAdd(midPt0, surfaceNormal)
        midPt1 = rs.VectorAdd(midPt1, surfaceNormal)
        midPt2 = rs.VectorAdd(midPt2, surfaceNormal)
        # draw triangles / add surfaces x 4
        arr = [vertexPts[0], midPt0, midPt2]
        triangle1 = rs.AddSrfPt(arr)
        arr = [midPt0, vertexPts[1], midPt1]
        triangle2 = rs.AddSrfPt(arr)
        arr = [midPt1, vertexPts[2], midPt2]
        triangle3 = rs.AddSrfPt(arr)
        arr = [midPt0, midPt1, midPt2]
        triangle4 = rs.AddSrfPt(arr)
        # call the function with the new triangles as input x 4
        subDivisionTriangle(triangle1)
        subDivisionTriangle(triangle2)
        subDivisionTriangle(triangle3)
        subDivisionTriangle(triangle4)
        # delete the original triangle
        rs.DeleteObjects(triangle)
        rs.DeleteObjects(triangleCurve)
        rs.DeleteObjects([triangle, triangleCurve])
        rs.DeleteObject(pt)
    # clean up the workspace
    rs.DeleteObject(triangleCurve)
# variables
triangle = rs.GetObject("Select triangle surface", 8)
# call the recursive function
rs.EnableRedraw(False)
subDivisionTriangle(triangle)
rs.EnableRedraw(True)

