python/ghutil

This module contains low-level RhinoPython and GHPython utility functions.

RhinoDoc Database Access

Normal GHPython operates on temporary objects within the Grasshopper document. This module provides functions to query the persistent geometric model contained in the Rhino database, accessible via the Rhino API, a wrapper around the core C# and C++ object in Rhino.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# ghrhinodoc.py - utility functions for manipulating the RhinoDoc database from within Grasshopper

import Rhino
import System.Guid

#================================================================
def fetch_or_create_layer_index(name):
    """Given a layer name, return the integer layer index value.  If the layer doesn't exist, create it."""
    layers = Rhino.RhinoDoc.ActiveDoc.Layers
    existing = layers.Find(name, True) # flag: ignore deleted layers

    if existing == -1:
        # create a new layer in the active document
        new_layer = Rhino.DocObjects.Layer()
        new_layer.Name = name
        return layers.Add(new_layer)
    else:
        return existing
#================================================================
def add_geometry(geometry, layer_index = None, name = None):
    """Add the general geometry object (type GeometryBase) to the document,
    optionally on the given layer, and optionally with the given object name.
    Returns the GUID of the new DocObject wrapping the geometry object.
    This GUID is only valid within the RhinoDoc database.
    """

    attributes = Rhino.DocObjects.ObjectAttributes()
    if layer_index is not None:
        attributes.LayerIndex = layer_index
    if name is not None:
        attributes.Name = name
    return Rhino.RhinoDoc.ActiveDoc.Objects.Add(geometry, attributes)

#================================================================
def all_doc_objects(layer):
    """Return a list of all DocObjects on the given layer, specified by layer name."""
    return Rhino.RhinoDoc.ActiveDoc.Objects.FindByLayer(layer)

#================================================================
def find_ghdoc_geometry(ghdoc, gobj):
    """Find the Rhino.Geometry object identified by the given script input.  If an
    input has a 'ghdoc' type hint supplied, it will be supplied as a GUID
    identifying an object in the ghdoc document, and this function looks up the
    object.  Otherwise, it may be supplied as a Rhino.Geometry object which is
    simply returned.
    """
    
    if type(gobj) is System.Guid:
        # print "Looking up object GUID in Grasshopper document."
        # Find() returns an AttributedGeometry object with properties Geometry and ObjectAttributes
        item = ghdoc.Objects.Find(gobj)
        # print "Item is", item, type(item)
        return item.Geometry
    
    else:
        # print "Geometry was directly supplied."
        return gobj
    
#================================================================

GHPython Tree Operators

GHPython will automatically convert simple lists of objects to and from Grasshopper tree objects when calling Python code and returning values, but more complex data strutures are not handled automatically. This module provides some useful primitives for accessing more complex tree data from within GHPython blocks.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
"""\
ghutil.trees

Utility functions related to creating Data Trees in Grasshopper.
"""

# import the Grasshopper Data Tree API
import Grasshopper as gh

#================================================================
# from https://gist.github.com/piac/ef91ac83cb5ee92a1294
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

#================================================================
def vectors_to_data_tree(vector_list):
    """Convert a list of Python tuples of floats to a GH datatree."""
    dataTree = gh.DataTree[float]()
    for i,vec in enumerate(vector_list):
        for value in vec:
            dataTree.Add(value,gh.Kernel.Data.GH_Path(i))
    return dataTree

#================================================================
# from https://gist.github.com/piac/ef91ac83cb5ee92a1294
# 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)
#================================================================