Grasshopper

algorithmic modeling for Rhino

I've been reading many discussions on datatrees in VB and I've got a hold on at least some of the basics. I have a component that's confusing me, though, and I was wondering if someone could help me out. Here's an image to see what I'm talking about:


I also attached my file.

I have a list of objects (planes) coming in on 4 different branches (0;3 through 0;6)

Just as a test I ran this code:

*From scripted component labeled (A) in image

Private Sub RunScript(ByVal x As DataTree(Of Plane), ByRef A As Object)

Dim tree1 As New datatree(Of System.Object)
Dim path1 As New GH_Path(7)

For i As Integer = 0 To x.Branch(0).count - 1
tree1.Add(x.Branch(0).item(i), path1)
Next

a = tree1

Which outputs all planes that were on branch {0;3} on new branch {7}. This works the way I expect it to.

What I'm confused about is when I add this little bit at the end:

*From scripted component labeled (B) in image

Private Sub RunScript(ByVal x As DataTree(Of Plane), ByRef A As Object)

Dim tree1 As New datatree(Of System.Object)
Dim path1 As New GH_Path(7)

For i As Integer = 0 To x.Branch(0).count - 1
tree1.Add(x.Branch(0).item(i), path1)
Next

a = tree1.Branch(path1)



The planes are now on branch {0;3;0}, but it seems (to me at least) that it should produce the same result as above since path1 was set to (7).

Ultimately I want a way of addressing each Branch on the same branch name they came in on. I can retrieve each branch easily:

*From scripted component labeled (C) in image

a = x.Branch(0)

b = x.Branch(1)

c = x.Branch(2)

d = x.Branch(3)

But each of these branches has a path of {0;3;0}

That doesn't seem right to me either... Is there something I'm missing?

By using the following code, I can basically recreate the branch structure that comes in:

*From scripted component labeled (D) in image

Private Sub RunScript(ByVal x As DataTree(Of Plane), ByRef A As Object)

Dim tree1 As New datatree(Of System.Object)

For g As Integer = 0 To x.BranchCount - 1
Dim path1 As New GH_Path(g)

For i As Integer = 0 To x.Branch(0).count - 1
tree1.Add(x.Branch(g).item(i), path1)
Next

Next

a = tree1 

but then I run into the same problem when trying to address any branch:

*From scripted component labeled (D) in image

Private Sub RunScript(ByVal x As DataTree(Of Plane), ByRef A As Object)

Dim tree1 As New datatree(Of System.Object)

For g As Integer = 0 To x.BranchCount - 1
Dim path1 As New GH_Path(g)

For i As Integer = 0 To x.Branch(0).count - 1
tree1.Add(x.Branch(g).item(i), path1)
Next

Next

a = tree1.Branch(0)

I apologize for the length of this post, but I appreciate any help I can get!

Thanks,

Brian

Views: 3839

Attachments:

Replies to This Discussion

a = tree1.Branch(path1)


A Tree is stored as two synchronized lists. The first one is a sorted list of all the paths, the second is a matching list of List(Of T), where T is the type of the Tree. So when you retrieve tree1.Branch(0), all you get is a single list filled with items that are of type T, with no path information whatsoever. The {0;3;0} now comes from the internal data matching logic.

But each of these branches has a path of {0;3;0}

That doesn't seem right to me either... Is there something I'm missing?

These branches do no have a path of {0;3;0}. They don't have a path at all, they are just List(Of T) instances. The {0;3;0} is only assigned at the very last moment, when RunScript returns and Grasshopper figures out that you've assigning a list to A. Since the input is marked as Tree Access, it simply picks the first path it comes across.

If you want to have control over the data structure of your outputs, you must output DataTree(Of T) instances, and not just the branches of a DataTree.

--

David Rutten

david@mcneel.com

Poprad, Slovakia

Thanks for the reply David,

So if I wanted to output each branch as a separate output, would I have to create 4 datatrees?

Like so:

Private Sub RunScript(ByVal x As DataTree(Of Plane), ByRef A As Object, ByRef B As Object, ByRef C As Object, ByRef D As Object)

Dim tree1, tree2, tree3, tree4 As New datatree(Of System.Object)

Dim path1 As New GH_Path(0, 3)
Dim path2 As New GH_Path(0, 4)
Dim path3 As New GH_Path(0, 5)
Dim path4 As New GH_Path(0, 6)

For i As Integer = 0 To x.Branch(0).count - 1
tree1.Add(x.Branch(0).item(i), path1)
tree2.Add(x.Branch(1).item(i), path2)
tree3.Add(x.Branch(2).item(i), path3)
tree4.Add(x.Branch(3).item(i), path4)
Next


a = tree1
b = tree2
c = tree3
d = tree4

This works I guess I'm just wondering if there is a better way.

Thanks again,

-Brian

If you want to operate on just one list at a time, why not set the input access to list? That way you won't have to worry about the paths, it's taken care of by the internal component logic.

It is in the nature of datatrees that you can never have more than one of them. A single parameter in Grasshopper only has a single datatree. When you add another datatree, the two are simply merged together into a single, larger datatree.

Dim tree As New DataTree(Of System.Object)

For i As Integer = 0 To x.Branch(0).count - 1

  tree.Add(x.Branch(0).item(i), New GH_Path(0, 3))
  tree.Add(x.Branch(1).item(i), New GH_Path(0, 4))
  tree.Add(x.Branch(2).item(i), New GH_Path(0, 5))
  tree.Add(x.Branch(3).item(i), New GH_Path(0, 6))
Next


a = tree

This is a bit of a weird example though, as it doesn't seem to do anything except copy the original tree.

--

David Rutten

david@mcneel.com

Poprad, Slovakia

I see, that makes sense. This example is a little obscure, but my intention is to input objects on multiple branches, then manipulate each branch differently within the script, and then output them with the same path structure they came in on (In this example above  I'm not doing anything to the planes before I send them off - I just wanted to make sure I could output them with the right data structure).

I guess in this case I can just address the incoming data as x.Branch(...),then manipulate those objects and then worry about the branch-management at the end of the script.

Thanks David,

Brian

It looks like list access could work for what I'm trying to do, but If I use list access and x now contains multiple lists, how do I address each list (branch) separately?

Thanks

-Brian

You don't address them separately. Or rather, your RunScript function will be called once for every branch so the iteration is no longer your responsibility. Of course the problem with using List access is that you no longer know what path each list belonged to, it's just an anonymous list.

Dealing with datatrees mostly means two nested loops, the outer one iterates over all paths/branches, the inner one iterates over all items in whatever branch is currently being handled.

--

David Rutten

david@mcneel.com

Poprad, Slovakia

Ok, after a little practice I'm going the datatree route. Thanks again David for all your help.

A skillful choice of whether setting the input as "list" input or "Tree" input for custom VB components can help make programming much easier.

For example if you are writing a component that deals with a list, picking list with free you from writing the iteration yourself.

Dim tree As New DataTree(Of System.Object)  is what I used most in your case, where the output structure matters.

RSS

About

Translate

Search

Videos

  • Add Videos
  • View All

© 2024   Created by Scott Davidson.   Powered by

Badges  |  Report an Issue  |  Terms of Service