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

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
Næste skridt, omskrive til Python (2021);
# 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)