Four examples this time around, showing how to take all that sexy VB.NET stuff we covered last time and stick it in grasshopper. First up, a super-simple example of how you can write your own version of the standard line component.

Using the code:

Private Sub RunScript(ByVal P1 As Point3d, ByVal P2 As Point3d, ByRef A As Object)
'This subroutine is the one that will be run whenever the component is updated.
'Note that the names and data types we set up outside the code are here as subroutine arguments
'The last one is our output - it is 'ByRef' so that changes we make here are not merely local</p>
Dim L As Line 'This declares that we are going to be using a line called 'L'
L = New Line(P1, P2) 'This creates a line using one of the built in constructors that takes two points
A = L 'This sets the line we have created as our output object A.
End Sub

You can download the example here: http://www.vitruality.com/Teaching/Example3.ghx (Right click, save as…)

That example will follow the same basic rules on data-matching as most other components; namely if you input a list or a tree it will be run once matching the first item in both lists, again with the second and so on. If you want, however, you can take control of how that works by bringing in lists of objects as inputs instead. This can be set up by right clicking on an input and selecting ‘List Access’:

This script will take two lists of points and draw a zig-zag between them.

Private Sub RunScript(ByVal P1 As List(Of Point3d), ByVal P2 As List(Of Point3d), ByRef A As Object)</p>
Dim i As Integer
'We calculate the maximum index we're going to go to.
'This is the minimum of the highest indices of the two lists
Dim maxi As Integer = math.Min(P1.Count, P2.Count) - 1
Dim OutList As New List(Of Line) 'This is to store our output lines
'Here we loop through both lists
For i = 0 To maxi
'We take the ith point from P1 and the ith point from P2 and draw a line between them
Dim fromPt As Point3d = P1(i)
Dim toPt As Point3d = P2(i)
Dim L As New Line(fromPt, toPt)
'We add our line to the output list
OutList.Add(L)
'If there is another point still to go in P2...
If i < P2.Count - 1 Then
'...we do the same to the ith point from P1 and the (i+1)th point from P2
Dim ToPt2 As Point3d = P2(i + 1)
Dim L2 As New Line(fromPt, toPt2)
OutList.Add(L2)
End If
Next
A = OutList 'This will set the output of the component
End Sub

Aaaaand you can download it here: http://www.vitruality.com/Teaching/Example3a.ghx (Right click, save as…)

Now things get a little more interesting. All of the above could be done in grasshopper just using the built-in components, but there are a few things that are impossible in grasshopper normally but that we can do via code. One of these things is recursion, which you might recall is the tool we use for creating fractals.

So, the next example uses this principle to create a fractal branching structure. Here’s some I made earlier:

Which were made with this script:

Private Sub RunScript(ByVal startLine As Line, ByVal Factor As Double, ByVal Angle As Double, ByVal Axis As Vector3d, ByVal Iterations As Integer, ByRef branches As Object)
Dim OutList As New List(Of Line)</p>
'Start the branching
Branch(startLine, factor, angle, axis, iterations, outlist)
branches = OutList
End Sub
'<Custom additional code>
'Branch() is a separate subroutine so that we can call it recursively from within itself
Private Sub Branch(ByVal startLine As line, ByVal factor As Double, ByVal angle As Double, _
ByVal axis As vector3d, ByVal iterations As Integer, ByRef outList As List(Of Line))
'We pass in everything we need to calculate the new lines. Note that outList is ByRef so we can change
'the original rather than just create a copy
If iterations > 0 Then
'Vectors have 'operators' defined, meaning that we can use them in mathematical equations like numbers
'Operators are things like + - * / etc.
'This is vector subtraction, i.e. |A| - |B| = (A.x - B.x, A.y - B.y, A.z - B.z)
Dim VectorA As Vector3d = startLine.To - startLine.From
VectorA *= factor 'This scales our vector by a factor
'We want two branches, so we create a copy of vector A:
Dim VectorB As New Vector3d(VectorA.X, VectorA.Y, VectorA.Z)
'Then we rotate them in opposite directions:
'Vector3d has a built-in 'Rotate' sub we can use for this.
VectorA.Rotate(angle, Axis)
VectorB.Rotate(-angle, Axis)
Dim LineA As Line
Dim LineB As Line
'The endpoint of our new lines will be the end of our starting line plus our vectors
Dim EndPointA As Point3d = startLine.To + VectorA
Dim EndPointB As Point3d = startLine.To + VectorB
'We now draw lines from the end of our old line to the points we just found
LineA = New Line(startLine.To, EndPointA)
LineB = New Line(startLine.To, EndPointB)
'We add the lines to our output lists
outlist.Add(LineA)
outlist.Add(LineB)
'Now we use recursion (calling a function from within itself) to branch further
'Note that we subtract one from the iterations. This lets us 'count down' branchings and stop.
Branch(LineA, factor, angle, axis, iterations - 1, outList)
Branch(LineB, factor, angle, axis, iterations - 1, outList)
End If
End Sub

Get the definition here: http://www.vitruality.com/Teaching/Example4.ghx (Right click, save as)

And finally, here’s a tweaked version of the Branch() subroutine that does the same thing in 3d:

Private Sub Branch(ByVal startLine As line, ByVal factor As Double, ByVal angle As Double, _
ByVal axis As vector3d, ByVal iterations As Integer, ByRef outList As List(Of Line))</p>
If iterations > 0 Then
Dim VectorA As Vector3d = startLine.To - startLine.From
VectorA *= factor
Dim VectorB As New Vector3d(VectorA.X, VectorA.Y, VectorA.Z)
'======================================================================================
'This is the only bit that's changed: we now rotate twice, once about our given axis and
'again using the line itself as an axis (we copy vector A again to use as this axis)
Dim NewAxis As New Vector3d(VectorA.X, VectorA.Y, VectorA.Z)
VectorA.Rotate(angle, Axis)
VectorA.Rotate(math.PI / 2, NewAxis)
VectorB.Rotate(-angle, Axis)
VectorB.Rotate(math.PI / 2, NewAxis)
'The key thing is that by rotating it the second time, we are changing the plane that
'the branches are in. We thus need to rotate the first rotation axis as well
Axis.Rotate(math.PI / 2, NewAxis)
'=====================================================================================
Dim LineA As Line
Dim LineB As Line
Dim EndPointA As Point3d = startLine.To + VectorA
Dim EndPointB As Point3d = startLine.To + VectorB
LineA = New Line(startLine.To, EndPointA)
LineB = New Line(startLine.To, EndPointB)
outlist.Add(LineA)
outlist.Add(LineB)
Branch(LineA, factor, angle, axis, iterations - 1, outList)
Branch(LineB, factor, angle, axis, iterations - 1, outList)
End If
End Sub

Which you can download here: http://www.vitruality.com/Teaching/Example4a.ghx (Right cl- oh, you know the drill by now)