Grasshopper

algorithmic modeling for Rhino

It has been several days I have been trying to understand the ways of VB.Net coming from Bentley GC and Csharp. But still I seem to be crawling...

Can someone point out whats wrong with this code?


Private Sub RunScript(ByVal point As On3dPoint, ByRef A As Object, ByRef B As Object)

Dim yArray As New ArrayList

Dim count As Double : count = 10
Dim i As Int16

For i = 1 To count Step 1
Dim xArray As New List (Of On3dPoint)
Dim j As Int16

For j = 1 To count Step 1
Dim nPoint As New On3dPoint
nPoint.x = i
nPoint.y = j
nPoint.z = 0
xArray.Add(nPoint)

Next

yArray.Add(xArray)

Next

A = yArray


As a side point i reckon grasshopper is fantastic, not having to promote and export in and out from rhino saves hours each day! But would benefit from a more useful debugger also even simple definitions run quite slowly, is there plans of allowing people to compile definitions into rhino native plugins? That would be great!

Views: 710

Replies to This Discussion

Hi Erik,

Your code, with changes (no fixes yet):

-------------------------------------------
Dim yArray As New List(Of List(Of On3dPoint))
Dim count As Int32 = 10

For i As Int32 = 1 To count
Dim xArray As New List(Of On3dPoint)

For j As Int32 = 1 To count
Dim nPoint As New On3dPoint(i, j, 0)
xArray.Add(nPoint)
Next

yArray.Add(xArray)
Next
A = yArray
-------------------------------------------

- ArrayList is a DotNET 1.0 legacy class. You should always try to use type specific classes such as List(Of T).
- Int16 is only rarely useful. Its numeric scope is too limited for a lot of purposes. Int32 is to be preferred.
- You can declare iteration variables (i & j) inside the loop code.

The reason your code doesn't work is not because there's anything wrong with it. It's simply that Grasshopper doesn't understand lists of lists if you supply them in this fashion. Only one dimensional collections can be outputted like this. Thus, if you want to put all the points into a single list:

-------------------------------------------
Dim points As New List(Of On3dPoint)
Dim count As Int32 = 10

For i As Int32 = 1 To count
For j As Int32 = 1 To count Step 1
Dim nPoint As New On3dPoint(i, j, 0)
points.Add(nPoint)
Next
Next
A = points
-------------------------------------------

If you want to output lists of lists, you must supply it as a DataTree(Of T):

-------------------------------------------
Dim points As New Grasshopper.DataTree(Of On3dPoint)
For i As Int32 = 1 To x
For j As Int32 = 1 To y
Dim nPoint As New On3dPoint(i, j, 0)
points.Add(nPoint, New Grasshopper.Kernel.Data.GH_Path(i))
Next
Next
A = points
-------------------------------------------


--
David Rutten
david@mcneel.com
Poprad, Slovakia
Using the Grasshopper.DataTree(Of On3dPoint) works great! But now I want to access the points from within the data tree, points(x)(y) for example to create a line : this is my non-functional attempt:

Dim lArray As New List (Of OnLine)
' Dim k As Int32
'For k = 1 To 3

Dim nLine As New OnLine
nLine.from = points.Branch(x).Item(y)
nLine.To = points.Branch(x+2).Item(y)
lArray.Add(nLine)
Hi Erik,

a tree is strickly speaking not a two-dimensional array. It contains any number of branches, each of which can contain any number of items. Every branch has a unique path and every path contains a unique collection of integers. For example {0} is the simplest and most common path. If you add a dimension to this path, you can get results such as {0;0} or {0;1} or {0;25}.

In the case above, all our paths only have a single dimension, so we get: {0}, {1}, {2}, ... , {N}, depending on how many columns the grid has.

ho... breakfast time. I'll pick this up again in a bit. >>>
>>>

Since you know your data structure is constructed in such a way as to mimic a two-dimensional array, you can access it safely using indices rather than paths:

-----------------------
Dim points As New Grasshopper.DataTree(Of On3dPoint)

For i As Int32 = 0 To x
For j As Int32 = 0 To y
Dim nPoint As New On3dPoint(i, j, 0)
points.Add(nPoint, New GH_Path(i))
Next
Next

Dim lines As New List(Of OnLine)

For i As int32 = 0 To x - 2
For j As int32 = 0 To y
Dim pA As On3dPoint = points.Branches(i)(j)
Dim pB As On3dPoint = points.Branches(i + 2)(j)

lines.Add(New OnLine(pA, pB))
Next
Next

A = lines
-----------------------



--
David Rutten
david@mcneel.com
Poprad, Slovakia
Wow, seems reasonably clear now thanks for all the explanations. Am I right in thinking that creating a three leveled array (k)(j)(i) requires a structure like this:

Grasshopper.DataTree(Of Grasshopper.DataTree(Of OnLine))
Grasshopper.DataTree(Of OnLine)
OnLine
No, you'd never create a DataTree(Of DataTree(Of T)).

You make a specific data layout (or 'topology' if you like) by providing different paths for different branches.

So, if you want to mimic a three dimensional array, you'll just have to create paths that contain multiple dimensions:

{0;0;0}
{0;0;1}
{0;0;2}
{0;1;0}
{0;1;1}
{0;1;2}
{1;0;0}
{1;0;1}
{1;0;2}
{1;1;0}
{1;1;1}
{1;1;2}

The above paths describe a tree structure which is akin to a three-dimensional array with a size of 3 in the first dimension and a size of 2 in the second and third dimensions.

--
David Rutten
david@mcneel.com
Poprad, Slovakia
Hey, David, I'm trying to figure out the actual syntax of multiple dimension data tree. Your explanation is very helpful. However, what on earth is the third dimension of the 3d array like {0;2;1}?What's the relationship between path, branch and item? Is that "DataTree.Path.Branch.Item"?

And these two lines are very confusing:

points.Add(nPoint, New GH_Path(i))
points.Branches(i)(j)

What is brach and what is path?


Thanks
Hi Jinge,

a branch is a list of data. A path is a list of integers (indices) that identify a unique branch. For example {0;0;2}. Every Branch has a Path associated with it. Thus, a DataTree contains two lists of equal length, one with GH_Path and one with List(Of T).

An item is a single element in some branch.

When accessing branches, you can use both GH_Paths and indices to retrieve them. Whichever method you choose depends on whatever makes the most sense in any given scenario.

The lines of code that confused you work like this:

point.Add(nPoint, New GH_Path(i))

Two things happen on this line. First we create a new GH_Path with a single index (namely {i}) and then we add a new item to the tree at the given path. If there already is a branch with the path {i}, the point will be appended to that branch. If there is no such branch yet, a new branch will be created.

points.Branches(i)(j)

In the above line, you use two indexers to retrieve a specific item from the DataTree. First we access the list of Branches at index i, then we access the items in that branch with the index j. The above is synonymous with:

Dim branch As List(Of On3dPoint) = points.Branches(i)
Dim pA As On3dPoint = branch(j)


--
David Rutten
david@mcneel.com
Poprad, Slovakia
Thanks, David.

Your explanation is pretty clear for 2d array, but I think I'm still not sure about 3d array. It seems a point from a 3d array data tree will like this: points.Branches(i)(j)(k),right? Than how to define a datatree like this?



Dim points As New Grasshopper.DataTree(Of On3dPoint)

For i As Int32 = 0 To x
For j As Int32 = 0 To y
For k As Int32 =0 To x

Dim nPoint As New On3dPoint(i, j, k)
points.Add(nPoint, New GH_Path(i)(j))
' or "Path(i,j)"? or "Path(i,j,k)"? "Path(i;j;k)"?

Next
Next
Next
Hi Jinge,

(can no longer reply to your message, it's nested too deep).

Accessing items from a DataTree always looks like this:

tree.Branch(i)(j)

Where i is either the index of the branch or the path of the branch. Thus:

tree.Branch(0)(2)

will give you the third item in the first branch (no matter what the path for that branch is). While:

tree.Branch(New GH_Path(0, 2, 5))(2)

will give you the third item in the branch that is associated with the path {0;2;5}

Note: the DataTree.Branch() method has three overloads, and it's a bit confusing.:

DataTree(Of T).Branch(ByVal index As Integer) As List(Of T)
DataTree(Of T).Branch(ByVal path As GH_Path) As List(Of T)
DataTree(Of T).Branch(ByVal ParamArray path As Int32()) As List(Of T)

The third one allows you to specify a bunch of integers without wrapping them up in a single path. Like so:

tree.Branch(0, 2, 5)(2)

This is the same as before. But if you only supply a single integer, it counts as a branch index.

This is probably something I need to make more consistent.

--
David Rutten
david@mcneel.com
Poprad, Slovakia
"even simple definitions run quite slowly"

Some operations take a lot longer to complete than others. Some components can probably be sped up, but most of the slow ones involve complicated geometric operations which are already running quite fast, all things considered.

Compiling things into native rhino plugins (what's an unnative Rhino plugin?) won't speed things up in the slightest. Grasshopper is a native Rhino plugin and is using the exact same functions any other plugin would use to accomplish the same ends.

--
David Rutten
david@mcneel.com
Poprad, Slovakia
Thank's for the scripting explanation David,

Obviously I am not completely sure how the conversions happen from components functions to grasshopper engine to rhino but I was just wondering if once a definition is finished it can be compiled out into a plugin. Therefore running directly within rhino without having to pass through grasshopper therefore saving conversion time. But maybe this time is negligible...

RSS

About

Translate

Search

Photos

  • Add Photos
  • View All

Videos

  • Add Videos
  • View All

© 2024   Created by Scott Davidson.   Powered by

Badges  |  Report an Issue  |  Terms of Service