Space Frame From Surface

'SpaceframeFromSurface.rvb 'This script produces a spaceframe with a constant depth 'In: Surface, U and V divisions, height, grid size 'Out: Folded Tiles on Surface and unfolded curves on XY plane, labelled, and ready to be laser cut

Option Explicit

Sub SpaceFrameFromSurface

Dim sourceSurface, uDiv, vDiv, height, grid Dim uStep, vStep Dim uVal, vVal Dim i, j   Dim tilePoints(3) Dim apexData, apexPoint

'Prompt user for input data sourceSurface = Rhino.GetObject("Select a surface to populate with spaceframe", 8)

uDiv = Rhino.GetInteger("Enter the number of divisions in the U direction", 10, 1)

vDiv = Rhino.GetInteger("Enter the number of divisions in the V direction", 10, 1)

height = Rhino.GetReal("Enter a height for the spaceframe") 'End input data

'To simplify the script, the surface is reparameterized to go from 0 to 1 in both directions Rhino.SelectObject sourceSurface Rhino.Command "Reparameterize 0 1 0 1 "

'Redimension the arrays that will hold all the values of U and V to the number of tiles in each direction Redim uVal(uDiv) Redim vVal(vDiv) ReDim apexPoint ((uDiv-1),(vDiv-1))

'Find the step value, i.e. the distance between tiles in each direction. (note: this is not the euclidian distance, it is the distance measured in UV space) uStep = 1/uDiv vStep = 1/vDiv

'Fill the arrays with the actual values of U and V at each step For i = 0 To uDiv uVal(i) = i * uStep Rhino.Print "uVal(" & i & "):" & uVal(i) Next

For i = 0 To vDiv vVal(i) = i * vStep Rhino.Print "vVal(" & i & "):" & vVal(i) Next

'Disable Rhino from redrawing the views during the tile construction to speed things up   Rhino.EnableRedraw vbFalse Rhino.Print "Constructing spaceframe..."

'Start looping through each u and v division and create the tile within For i = 0 to uDiv-1 For j = 0 to vDiv-1 'Find the 3D coordinate for each of the 4 corners of the tile using the UV coordinates as input tilePoints(0) = Rhino.EvaluateSurface(sourceSurface, array(uVal(i), vVal(j))) tilePoints(1) = Rhino.EvaluateSurface(sourceSurface, array(uVal(i+1), vVal(j))) tilePoints(2) = Rhino.EvaluateSurface(sourceSurface, array(uVal(i+1), vVal(j+1))) tilePoints(3) = Rhino.EvaluateSurface(sourceSurface, array(uVal(i), vVal(j+1)))

'Find the 3D coordinate normal to the specified UV coordinate for the given height apexData = Rhino.SurfaceCurvature(sourceSurface, array(uVal(i)+(uVal(1)/2), vVal(j)+(vVal(1)/2))) apexPoint(i,j) = offsetCalc(apexData, height)

'Add two top struts Rhino.AddLine tilePoints(0), tilePoints(1) Rhino.AddLine tilePoints(0), tilePoints(3)

'If in the last u row then add another strut If (i = uDiv-1) Then Rhino.AddLine tilePoints(1), tilePoints(2) End If

'If in the last v row then add another strut If (j = vDiv-1) Then Rhino.AddLine tilePoints(3), tilePoints(2) End If

'Add 4 diagonal struts Rhino.AddLine tilePoints(0), apexPoint(i,j) Rhino.AddLine tilePoints(1), apexPoint(i,j) Rhino.AddLine tilePoints(2), apexPoint(i,j) Rhino.AddLine tilePoints(3), apexPoint(i,j)

'If not in the first u row then add a bottom strut If (i > 0) Then Rhino.AddLine apexPoint(i,j), apexPoint(i-1,j) End If

'If not in the first v row then add a bottom strut If (j > 0) Then Rhino.AddLine apexPoint(i,j), apexPoint(i,j-1) End If

Next Next

'Re-enable the redraw so that we can see the result of the tile construction Rhino.EnableRedraw vbTrue

End Sub

'Call the sub SpaceFrameFromSurface

''' 'This fucntion finds the coordinate of a point normal to, and at a from, a point on the surface Function offsetCalc(oData, height) Dim vscaled vscaled = VectorScale(oData(1),height) offsetCalc = VectorAdd(vscaled,oData(0)) End Function

'' 'function by RMA, "vectors.rvb" Function VectorAdd(v1, v2)

VectorAdd = Null If Not IsArray(v1) Or (UBound(v1) <> 2) Then Exit Function If Not IsArray(v2) Or (UBound(v2) <> 2) Then Exit Function VectorAdd = Array(v1(0) + v2(0), v1(1) + v2(1), v1(2) + v2(2))

End Function

'' 'function by RMA, "vectors.rvb" Function VectorScale(v, d)

VectorScale = Null If Not IsArray(v) Or (UBound(v) <> 2) Then Exit Function If Not IsNumeric(d) Then Exit Function VectorScale = Array(v(0) * d, v(1) * d, v(2) * d)

End Function

' 'This function checks if the current layer is and if it isn't, makes it so. If the layer doesn't '    exist then it creates it with the name. Function CheckLayer(layername) If Rhino.IsLayer(layername) Then Rhino.CurrentLayer(layername) Else Rhino.AddLayer(layername) Rhino.CurrentLayer(layername) End If End Function