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)