Treesloth is an add-on to McNeel’s Grasshopper visual scripting interface for Rhinoceros. As a 3D CAD software suite, Rhino+Grasshopper is, at its core, a means to create, transform and manage data. Grasshopper’s explicit visual scripting interface structures these operations through the use of Data Trees. Treesloth first emerged as a series of tools that I have mostly developed for use in my own professional and research practices to help me better negotiate complex data relationships within and between Grasshopper definitions (although some of the components derive from other users’ wish lists and input ideas as well).
An earlier version of Treesloth has been available through the Milkbox Group on www.grasshopper3d.com. There is now also a dedicated user group for Treesloth. The release here fixes or enhances a few minor issues with some of the components available there, and adds several more. You can download the most current version on Food4Rhino or simply get it here:
Drag the GHA file into your Grashopper components folder. Be sure to remove any earlier versions of Treesloth first, although you should probably keep them just in case. I haven’t found any bugs yet in this version, but it hasn’t been extensively tested. Please contact me through the grasshopper3d.com forum with any questions or concerns.
The most significant addition to this release are the Pack Data and Unpack Data components. Using a binary file writer and various conversion methods available in both Rhinocommon and the Grasshopper SDK, these facilitate a robust interoperability-oriented workflow between multiple grasshopper definitions, allowing for users to quickly save any number of data or geometric elements into a relatively small .DAT file, and quickly reload them elsewhere. The default is for files to over-write existing versions, but there is also the option to “incrementally save,” which adds new files each time the save function is activated (Files are numbered according to the file count in the specified directory).
Data structures are maintained for all inputs, and mixed types are also acceptable. Data types supported include: strings, doubles, integers, booleans, date/times, domains, UV domains, colors, guids, and all rhino geometry managed through the Geometry Base class, which includes (at least) points, vectors, lines, curves, surfaces, breps and meshes. 3rd party classes (like Plankton Meshes) are not directly supported, but if you can break them down first into any of the types above, then you can save it and reload it, without relying on Rhino or having to internalize a bunch of parameters.
Other new components include Clone Structure, Sort Branches, Stack Trees and Shift Safely.
Clone structure behaves like a graft, with items from a flat list being assigned a new path. Here, though, it is possible to assign specific data paths directly. Users can use lists of integers, strings or data paths to achieve this, or they can simply attach another tree that has an equal number of paths as there are items in the list that should be placed in the new data tree.
Sort Branches allows for the synchronous renumbering of branches sorted either in ascending or descending order according to a set value for each branch. It allows for the user to select the minimum, maximum or average value in a given branch to sort (if only one item is given per branch, then each of these settings will produce the same result). Like the native component Sort List, it allows for attaching as many trees for synchronous sorting as desired (so long as they have the same number of paths as the sort keys). It also lets the user set the target depth for the sort. So, for example, if it is desirable for all branches at the first index to be tested against each other, it will sort the branches at that level.
Stack Trees is akin to both the Merge and Entwine native components, except that it attaches multiple trees to each other with sequential renumbering. The user can choose to either fully renumber all lists (reducing them to a single index path structure) or simplify to the lists to the minimum complexity required to capture the lowest level of unique structure for each tree.
Shift Safely is virtually identical to the native Shift Paths component, with the crucial difference that it doesn’t break when the offset setting is either greater or less than the number of indices in the inputs data paths. In any such instance where the number of indices to be offset is surpassed, it simply returns a flat list.
Data trees can be incredibly powerful, especially managing multiple, complex geometric or data-driven elements in a Grasshopper definition. Many of the components here have been borne directly from practice or research project-based needs to simplify or streamline workflow. A fuller list of visual examples describing each component is here. The three that really drove the initial development of this modest toolbox to begin with were Propagate Ancestors, List Compare, and Filter Unmatched. Although these have been around a while, I’d like to outline them once more.
Propagate Ancestors was developed because I regularly found myself trying to figure out how to match data sets that were related to each other, but had different path lengths. To do this, I was shifting paths from one list, getting list lengths, grafting and using list lengths to repeat data in others. And I found myself doing it quite often, especially when it came time to do detailing, where child objects had to be related back to the objects that made them. Propagate Ancestors takes care of this issue, making copies of “ancestor” data elements for easier matching to “child” elements.
I developed List Compare to make it easier to do circle packing of variable radius using Kangaroo, but have found its application useful on many occasions. Any time you have a list of items, and you want to compare each one against all the others (but not itself) in a given list, this component allows for that. It gives you the option to choose whether to simply include all unique pairs, or to get each individual item, and all other items in the list in a tree of minimal required complexity.
Filter Unmatched has been instrumental for me on a number of occasions. I understand why Grasshopper renumbers data trees that don’t match in components that take multiple inputs, but I often want to rely on the data path itself to ensure that matching between lists is correct and consistent. Sometimes, in the course of a definition, certain paths are removed from one tree that remain in another, but I want to match them up later to perform another action. As it is now, when two mis-matched data trees enter the same component in Grasshopper it renumbers one, or both of them. Filter Unmatched allows for as many data trees that pass through it for only those specific paths that are identical to each other for all inputs to remain in the output. This allows for meaningful number retention, and crucially, for complex relationships to be maintained. (Its sibling component is Unique Paths, which identifies any paths between multiple data sets that aren’t shared).