Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Transforms DataTrees in Grasshopper to nestings of lists, and vice versa
def list_to_tree(input, none_and_holes=True, source=[0]):
"""Transforms nestings of lists or tuples to a Grasshopper DataTree"""
from Grasshopper import DataTree as Tree
from Grasshopper.Kernel.Data import GH_Path as Path
from System import Array
def proc(input,tree,track):
path = Path(Array[int](track))
if len(input) == 0 and none_and_holes: tree.EnsurePath(path); return
for i,item in enumerate(input):
if hasattr(item, '__iter__'): #if list or tuple
track.append(i); proc(item,tree,track); track.pop()
else:
if none_and_holes: tree.Insert(item,path,i)
elif item is not None: tree.Add(item,path)
if input is not None: t=Tree[object]();proc(input,t,source[:]);return t
# written by Giulio Piacentino, giulio@mcneel.com
def tree_to_list(input, retrieve_base = lambda x: x[0]):
"""Returns a list representation of a Grasshopper DataTree"""
def extend_at(path, index, simple_input, rest_list):
target = path[index]
if len(rest_list) <= target: rest_list.extend([None]*(target-len(rest_list)+1))
if index == path.Length - 1:
rest_list[target] = list(simple_input)
else:
if rest_list[target] is None: rest_list[target] = []
extend_at(path, index+1, simple_input, rest_list[target])
all = []
for i in range(input.BranchCount):
path = input.Path(i)
extend_at(path, 0, input.Branch(path), all)
return retrieve_base(all)
@piac

This comment has been minimized.

@piac

This comment has been minimized.

Copy link
Owner Author

@piac piac commented Feb 16, 2015

This is an extension of a sample by Benjamin Golder posted on the GH forum. The original sample worked on a single list with lists inside (2D); this sample works on arbitrarily nested lists of lists (nD).

@epignatelli

This comment has been minimized.

Copy link

@epignatelli epignatelli commented Apr 6, 2017

Hi Giulio, i would like to report an issue.
Simplifying the input breaks the code. Usually it backs up to the previous dimension of the nested array.

image

@piac

This comment has been minimized.

Copy link
Owner Author

@piac piac commented Jun 22, 2017

@epignatelli

Hi, do you see those "source"/"retrieve_base " parameters in the two functions? They refer exactly to aberrant trees that actually represent "forests". (two tree that have {1} and {2} paths actually are not one "tree", but two different "trees")

@piac

This comment has been minimized.

Copy link
Owner Author

@piac piac commented Jun 22, 2017

Also, in Rhino WIP and Rhino 6, it will be possible to use

import ghpythonlib.treehelpers as th

a_tree = th.list_to_tree(a_list)
a_list = th.tree_to_list(a_tree)

that contain improved versions of the script above.

@xarthurx

This comment has been minimized.

Copy link

@xarthurx xarthurx commented Mar 16, 2019

This function doesn't work when the tree index doesn't start on 0.
image

@laurend

This comment has been minimized.

Copy link

@laurend laurend commented Feb 25, 2020

I didn't realize this at first so I want to mention in case it helps others: it seems that in order for tree_to_list to work properly (the version included with Rhino 6) the incoming tree must have the same dimensions as your target list. For instance, I had a list with 9 branches {0}...{8} and 40 items in each branch. I had to use path mapper to remap the incoming paths as {0;0}...{0;8} to output a 9x40 list of lists.

@piac

This comment has been minimized.

Copy link
Owner Author

@piac piac commented Feb 25, 2020

@laurend I think this topic:
https://discourse.mcneel.com/t/treehelpers-with-simplify/92531/2
will explain more in detail for you.

@laurend

This comment has been minimized.

Copy link

@laurend laurend commented Feb 25, 2020

@piac yes, I wish I had found that earlier!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.