Ripple Unfold

This fabrication script presents a simple tool to evaluate a surface with a triangular pattern and unfold this pattern in a series of bands. These bands are tabbed a numbered for easy assembly. This script is the first and simplest step in a series of rhinoscripts which will attempt to provide rigid structural skins with a simple triangulation technique.

Rhino Script

Option Explicit
'Script written by <David Mans>
'Script copyrighted by <Neoarchaic Design>
'Script version Monday, May 26, 2008 1:43:26 PM

Call Main()
Sub Main()
	Dim surf
	surf = Rhino.GetObject("select surface", 8)
	If isNull(surf) Then Exit Sub
	Call reparameterize(surf)
	
	Dim arrItems, arrValues, arrResults
	arrItems = array("Colums", "Rows", "Offset", "tabHeight", "ripple", "cutTemplate", "surfaces")
	arrValues = array(20, 20, 2, 1, False, True, True)
	arrResults = Rhino.PropertyListBox(arrItems, arrValues,, "Volume Parameters")
	Dim tri
	Call Rhino.EnableRedraw(False)
	tri = TriangulateSurface(surf, CDbl(arrResults(0)), CDbl(arrResults(1)), CDbl(arrResults(2)), array(CBool(arrResults(4))))
	If CBool(arrResults(6)) = True Then
		Call SurfaceMe(tri, RGB(255, 0, 0))
	End If
	
	If CBool(arrResults(5)) = True Then
		Call UnfoldMe(tri, CDbl(arrResults(3)))
	End If
	
	Call Rhino.EnableRedraw(True)
	
End Sub
Function TriangulateSurface(surface, cols, rows, offset, arrBln)
	TriangulateSurface = Null
	Dim i,j
	Dim uDom,vDom,uStep,vStep
	uDom = Rhino.SurfaceDomain(surface, 0)(1): uStep = uDom / cols
	vDom = Rhino.SurfaceDomain(surface, 1)(1): VStep = vDom / rows
	
	ReDim uv(rows),pt(rows),uvSet(cols),ptSet(cols)
	'plot point grid
	For i = 0 To cols Step 1
		For j = 0 To rows Step 1
			uv(j) = array(i * uStep, j * vStep)
			If i Mod (2) Then
				If j Mod (2) Then				
					pt(j) = Rhino.PointAdd(Rhino.EvaluateSurface(surface, uv(j)), Rhino.VectorScale(Rhino.VectorUnitize(Rhino.SurfaceNormal(surface, uv(j))), offset))

				Else
					pt(j) = Rhino.EvaluateSurface(surface, uv(j))
				End If
			Else
				If j Mod (2) Then				
					pt(j) = Rhino.EvaluateSurface(surface, uv(j))
				Else
					If arrBln(0) = True Then
						pt(j) = Rhino.PointAdd(Rhino.EvaluateSurface(surface, uv(j)), Rhino.VectorScale(Rhino.VectorUnitize(Rhino.SurfaceNormal(surface, uv(j))), -offset))
					Else
						pt(j) = Rhino.PointAdd(Rhino.EvaluateSurface(surface, uv(j)), Rhino.VectorScale(Rhino.VectorUnitize(Rhino.SurfaceNormal(surface, uv(j))), offset))
					End If
				End If
			End If
		Next 
		uvSet(i) = uv
		ptSet(i) = pt
	Next
	TriangulateSurface = ptSet
End Function
Function SurfaceMe(ptSet, objClr)
	SurfaceMe = Null
	If Rhino.IsLayer("surfaces") = False Then
		Call Rhino.AddLayer("surfaces", RGB(0, 0, 255))
	End If
	
	Dim i,j
	Dim cols, rows
	cols = uBound(ptSet)
	rows = uBound(ptSet(0))
	
	Dim srfA(),srfB()
	ReDim srfA(rows-1),srfB(rows-1)
	ReDim s(cols-1)
	For i = 0 To cols - 1 Step 1
		For j = 0 To rows - 1 Step 1
			If i Mod (2) Then
				If j Mod (2) Then
					srfA(j) = Rhino.AddSrfPt(array(ptSet(i)(j), ptSet(i)(j + 1), ptSet(i + 1)(j)))
					srfB(j) = Rhino.AddSrfPt(array(ptSet(i + 1)(j + 1), ptSet(i)(j + 1), ptSet(i + 1)(j)))
				Else
					srfA(j) = Rhino.AddSrfPt(array(ptSet(i + 1)(j), ptSet(i + 1)(j + 1), ptSet(i)(j)))
					srfB(j) = Rhino.AddSrfPt(array(ptSet(i)(j + 1), ptSet(i + 1)(j + 1), ptSet(i)(j)))
				End If
			Else
				If j Mod (2) Then
					srfA(j) = Rhino.AddSrfPt(array(ptSet(i + 1)(j), ptSet(i + 1)(j + 1), ptSet(i)(j)))
					srfB(j) = Rhino.AddSrfPt(array(ptSet(i)(j + 1), ptSet(i + 1)(j + 1), ptSet(i)(j)))
				Else
					srfA(j) = Rhino.AddSrfPt(array(ptSet(i)(j), ptSet(i)(j + 1), ptSet(i + 1)(j)))
					srfB(j) = Rhino.AddSrfPt(array(ptSet(i + 1)(j + 1), ptSet(i)(j + 1), ptSet(i + 1)(j)))
				End If
			End If
			Call Rhino.ObjectColor(srfA(j), objClr)
			Call Rhino.ObjectColor(srfB(j), objClr)
			Call Rhino.ObjectLayer(srfA(j), "surfaces")
			Call Rhino.ObjectLayer(srfB(j), "surfaces")
		Next
		s(i) = array(srfA, srfB)
	Next
	SurfaceMe = s
End Function
Function UnfoldMe(ptSet, tabHeight)
	UnfoldMe = Null
	If Rhino.IsLayer("cuts") = False Then
		Call Rhino.AddLayer("cuts", RGB(255, 0, 0))
	End If
	If Rhino.IsLayer("scores") = False Then
		Call Rhino.AddLayer("scores", RGB(0, 0, 0))
	End If
	
	Dim i,j,r
	Dim cols, rows, wrldCS
	cols = uBound(ptSet)
	rows = uBound(ptSet(0))
	wrldCS = Rhino.WorldXYPlane()
	Dim oriPt(), angX(), ptA(), ptB(), ptC(),pts(),minX(),maxX(),mn(),mx()
	ReDim oriPt(rows-1), angX(rows-1), ptA(rows-1), ptB(rows-1), ptC(rows-1),minX(rows-1),maxX(rows-1),mn(cols-1),mx(cols-1),pts(cols-1)
	
	Dim angA(),angB(),angC(),disA(),disB(),disC(),s(),a(),d()
	ReDim angA(rows-1),angB(rows-1),angC(rows-1),disA(rows-1),disB(rows-1),disC(rows-1)
	ReDim a(cols-1), d(cols-1)
	For i = 0 To cols - 1 Step 1
		For j = 0 To rows - 1 Step 1
			If i Mod (2) Then
				If j Mod (2) Then
					angA(j) = Rhino.angle2(array(ptSet(i)(j), ptSet(i + 1)(j)), array(ptSet(i)(j), ptSet(i)(j + 1)))(0)
					angB(j) = Rhino.angle2(array(ptSet(i + 1)(j), ptSet(i)(j)), array(ptSet(i + 1)(j), ptSet(i)(j + 1)))(0)
					angC(j) = Rhino.angle2(array(ptSet(i + 1)(j), ptSet(i)(j + 1)), array(ptSet(i + 1)(j), ptSet(i + 1)(j + 1)))(0)
					disA(j) = Rhino.Distance(ptSet(i)(j), ptSet(i + 1)(j))
					disB(j) = Rhino.Distance(ptSet(i)(j), ptSet(i)(j + 1))
					disC(j) = Rhino.Distance(ptSet(i + 1)(j), ptSet(i + 1)(j + 1))
				Else
					angA(j) = Rhino.angle2(array(ptSet(i + 1)(j), ptSet(i)(j)), array(ptSet(i + 1)(j), ptSet(i + 1)(j + 1)))(0)
					angB(j) = Rhino.angle2(array(ptSet(i)(j), ptSet(i + 1)(j)), array(ptSet(i)(j), ptSet(i + 1)(j + 1)))(0)
					angC(j) = Rhino.angle2(array(ptSet(i)(j), ptSet(i + 1)(j + 1)), array(ptSet(i)(j), ptSet(i)(j + 1)))(0)
					disA(j) = Rhino.Distance(ptSet(i + 1)(j), ptSet(i)(j))
					disB(j) = Rhino.Distance(ptSet(i + 1)(j), ptSet(i + 1)(j + 1))
					disC(j) = Rhino.Distance(ptSet(i)(j), ptSet(i)(j + 1))
				End If
			Else
				If j Mod (2) Then
					angA(j) = Rhino.angle2(array(ptSet(i + 1)(j), ptSet(i)(j)), array(ptSet(i + 1)(j), ptSet(i + 1)(j + 1)))(0)
					angB(j) = Rhino.angle2(array(ptSet(i)(j), ptSet(i + 1)(j)), array(ptSet(i)(j), ptSet(i + 1)(j + 1)))(0)
					angC(j) = Rhino.angle2(array(ptSet(i)(j), ptSet(i + 1)(j + 1)), array(ptSet(i)(j), ptSet(i)(j + 1)))(0)
					disA(j) = Rhino.Distance(ptSet(i + 1)(j), ptSet(i)(j))
					disB(j) = Rhino.Distance(ptSet(i + 1)(j), ptSet(i + 1)(j + 1))
					disC(j) = Rhino.Distance(ptSet(i)(j), ptSet(i)(j + 1))
				Else
					angA(j) = Rhino.angle2(array(ptSet(i)(j), ptSet(i + 1)(j)), array(ptSet(i)(j), ptSet(i)(j + 1)))(0)
					angB(j) = Rhino.angle2(array(ptSet(i + 1)(j), ptSet(i)(j)), array(ptSet(i + 1)(j), ptSet(i)(j + 1)))(0)
					angC(j) = Rhino.angle2(array(ptSet(i + 1)(j), ptSet(i)(j + 1)), array(ptSet(i + 1)(j), ptSet(i + 1)(j + 1)))(0)
					disA(j) = Rhino.Distance(ptSet(i)(j), ptSet(i + 1)(j))
					disB(j) = Rhino.Distance(ptSet(i)(j), ptSet(i)(j + 1))
					disC(j) = Rhino.Distance(ptSet(i + 1)(j), ptSet(i + 1)(j + 1))
				End If
			End If
		Next
		a(i) = array(angA, angB, angC)
		d(i) = array(disA, disB, disC)
	Next
	
	For i = 0 To cols - 1 Step 1
		r = 0
		For j = 0 To rows - 1 Step 1
			If j = 0 Then
				oriPt(j) = array(0, 0, 0)
				angX(j) = 0
			Else
				oriPt(j) = ptB(j - 1)
				If ptB(j - 1)(1) > ptC(j - 1)(1) Then
					angX(j) = -Rhino.Angle2(array(ptB(j - 1), Rhino.PointAdd(ptB(j - 1), wrldCS(1))), array(ptB(j - 1), ptC(j - 1)))(0)
				Else
					angX(j) = Rhino.Angle2(array(ptB(j - 1), Rhino.PointAdd(ptB(j - 1), wrldCS(1))), array(ptB(j - 1), ptC(j - 1)))(0)
				End If
			End If
			If i Mod (2) Then
				r = j + 1
			Else
				r = j
			End If
			If r Mod (2) Then
				ptA(j) = Rhino.PointAdd(oriPt(j), Rhino.VectorScale(Rhino.VectorRotate(wrldCS(1), angX(j), wrldCS(3)), d(i)(0)(j)))
				ptB(j) = Rhino.PointAdd(oriPt(j), Rhino.VectorScale(Rhino.VectorRotate(wrldCS(1), angX(j) + a(i)(1)(j) + a(i)(2)(j), wrldCS(3)), d(i)(2)(j)))
				ptC(j) = Rhino.PointAdd(ptA(j), Rhino.VectorScale(Rhino.VectorRotate(wrldCS(1), angX(j) + 180 - a(i)(0)(j), wrldCS(3)), d(i)(1)(j)))
			Else
				ptA(j) = Rhino.PointAdd(oriPt(j), Rhino.VectorScale(Rhino.VectorRotate(wrldCS(1), angX(j), wrldCS(3)), d(i)(0)(j)))
				ptB(j) = Rhino.PointAdd(oriPt(j), Rhino.VectorScale(Rhino.VectorRotate(wrldCS(1), angX(j) + a(i)(0)(j), wrldCS(3)), d(i)(1)(j)))
				ptC(j) = Rhino.PointAdd(ptA(j), Rhino.VectorScale(Rhino.VectorRotate(wrldCS(1), angX(j) + 180 - a(i)(1)(j) - a(i)(2)(j), wrldCS(3)), d(i)(2)(j)))
			End If
			minX(j) = Rhino.Min(array(ptA(j)(0), ptB(j)(0), ptC(j)(0)))
			maxX(j) = Rhino.Max(array(ptA(j)(0), ptB(j)(0), ptC(j)(0)))
			r = r + 1
		Next
		mn(i) = Rhino.Min(minX)
		If mn(i) > 0 Then
			mn(i) = 0
		Else
			mn(i) = abs(mn(i))
		End If
		mx(i) = abs(Rhino.Max(maxX))
		pts(i) = array(oriPt, ptA, ptB, ptC)
	Next
	Dim ptX, k
	Dim edge(),edgeA(), edgeB(), span()
	ReDim edge(cols-1),edgeA(rows-1), edgeB(rows-1), span(rows*2)
	r = 0
	For i = 0 To cols - 1 Step 1
		k = 0
		If i > 0 Then
			r = r + mx(i - 1) + mn(i) + tabHeight * 2
		End If
		For j = 0 To rows - 1 Step 1
			ptX = array(r, 0, 0)
			If j Mod (2) Then
				span(k) = Rhino.AddLine(Rhino.PointAdd(ptX, pts(i)(0)(j)), Rhino.PointAdd(ptX, pts(i)(3)(j)))
				Call Rhino.ObjectLayer(span(k), "scores")
				k = k + 1
			Else
				span(k) = Rhino.AddLine(Rhino.PointAdd(ptX, pts(i)(1)(j)), Rhino.PointAdd(ptX, pts(i)(2)(j)))
				Call Rhino.ObjectLayer(span(k), "scores")
				k = k + 1
			End If
			If j = 0 Then
				span(k) = Rhino.AddLine(Rhino.PointAdd(ptX, pts(i)(0)(j)), Rhino.PointAdd(ptX, pts(i)(1)(j)))
				Call Rhino.ObjectLayer(span(k), "cuts")
				k = k + 1
			End If
			If j = rows - 1 Then
				span(k) = Rhino.AddLine(Rhino.PointAdd(ptX, pts(i)(2)(j)), Rhino.PointAdd(ptX, pts(i)(3)(j)))
				Call Rhino.ObjectLayer(span(k), "cuts")
				k = k + 1
			Else
				span(k) = Rhino.AddLine(Rhino.PointAdd(ptX, pts(i)(2)(j)), Rhino.PointAdd(ptX, pts(i)(3)(j)))
				Call Rhino.ObjectLayer(span(k), "scores")
				k = k + 1
			End If
			edgeA(j) = Rhino.AddLine(Rhino.PointAdd(ptX, pts(i)(0)(j)), Rhino.PointAdd(ptX, pts(i)(2)(j)))
			Call Rhino.ObjectLayer(edgeA(j), "scores")
			edgeB(j) = Rhino.AddLine(Rhino.PointAdd(ptX, pts(i)(1)(j)), Rhino.PointAdd(ptX, pts(i)(3)(j)))
			Call Rhino.ObjectLayer(edgeB(j), "scores")
		Next
		edge(i) = array(edgeA, edgeB)
	Next
	
	Dim tabA(), tabB(), lblA(), lblB()
	ReDim tabA(rows-1), tabB(rows-1), lblA(rows-1), lblB(rows-1)
	For i = 0 To cols - 1 Step 1
		For j = 0 To rows - 1 Step 1
			tabA(j) = tabMaker(edge(i)(0)(j), -90, tabHeight)
			tabB(j) = tabMaker(edge(i)(1)(j), 90, tabHeight)
			Call Rhino.ObjectLayer(tabA(j), "cuts")
			Call Rhino.ObjectLayer(tabB(j), "cuts")
			
			If i = cols - 1 Then
				lblB(j) = labelMaker(edge(i)(1)(j), cols - 1 &amp; "." &amp; j, tabHeight * .25, 0, True)
			Else
				lblB(j) = labelMaker(edge(i)(1)(j), i + 1 &amp; "." &amp; j, tabHeight * .25, 0, True)
			End If
			lblA(j) = labelMaker(edge(i)(0)(j), i &amp; "." &amp; j, tabHeight * .25, 180, True)
		Next
	Next
End Function
Function tabMaker(curve, rotVal, scale)
	tabMaker = Null
	Dim tabLN(1), tabPT(2),crvDom, wrldCS, i
	crvDom = Rhino.CurveDomain(curve)
	wrldCS = Rhino.WorldXYPlane()
	tabPT(0) = Rhino.CurveStartPoint(curve)
	tabPT(2) = Rhino.CurveEndPoint(curve)
	tabPT(1) = Rhino.PointAdd(Rhino.EvaluateCurve(curve, crvDom(1) * .5),Rhino.VectorScale(Rhino.VectorUnitize(Rhino.VectorRotate(Rhino.VectorCreate(Rhino.EvaluateCurve(curve, crvDom(1) * .4),tabPT(2)),rotVal, wrldCS(3))),scale))
	For i = 0 To 1 Step 1
		tabLN(i) = Rhino.AddLine(tabPT(i), tabPT(i + 1))
	Next
	tabMaker = tabLN
End Function
Function labelMaker(curve, title, size, angle, blnAlign)
	labelMaker = Null
	Dim txt, wrldCS
	If Rhino.IsLayer("numbering") = False Then
		Call Rhino.AddLayer("numbering", RGB(0, 255, 0))
	End If
	wrldCS = Rhino.WorldXYPlane()
	txt = Rhino.AddText(title, Rhino.CurveMidPoint(curve), size)
	If blnAlign = True Then
		Call Rhino.TextObjectPlane(txt, array(Rhino.CurveMidPoint(curve), Rhino.VectorCreate(Rhino.CurveMidPoint(curve), Rhino.CurveEndPoint(curve)), Rhino.VectorRotate(Rhino.VectorCreate(Rhino.CurveMidPoint(curve), Rhino.CurveEndPoint(curve)), 90, wrldCS(3)), wrldCS(3)))
		Call Rhino.RotateObject(txt, Rhino.CurveMidPoint(curve), angle, wrldCS(3))
	End If
	Call Rhino.ObjectLayer(txt, "numbering")
	labelMaker = txt
End Function
Function reparameterize(strObjectID)
	If Rhino.IsCurve(strObjectID) = True Then
		Call rhino.SelectObject(strObjectID)
		Call rhino.Command("reparameterize 0 1")
		Call rhino.UnselectAllObjects()
	End If
	If Rhino.IsSurface(strObjectID) = True Then
		Call rhino.SelectObject(strObjectID)
		Call rhino.Command("reparameterize 0 1 0 1")
		Call rhino.UnselectAllObjects()
	End If		
End Function