GHPython: Construct Multiple Layered Data Tree by Filtering

Hi everyone,

I’ve looked very hard to try and solve my challenge, and found a lot of good posts. But I cannot find this issue or tips to solve it.

I want to build a data tree with about 4 layers. In the ghpython component, there are 4 inputs, each one is part of a branch layer hierarchy, example:
Devs = {0}
Plots = {0,0}
Buildings = {0,0,0}
Massing = {0,0,0,0}

The goal is to be able to see what items are contained below each higher-order element. The tree can then be used for calculations of (# items, M2, GFA, etc.)

I want to organize the items on each lower (successive) layer underneath the item which contains them. example:
Dev[1] contains Plots[3,4,5] contains Buildings[10,11,15] contains Massing[90,91,92]

Problems:
My problem is that the data is duplicating and not filtering

  • I might be using the wrong filtering techniques (ex. Curve.Contain might be bad method)
  • I might be structuring the for loops incorrectly
  • I might be constructing the dataTree incorrectly

MassDataMaker_0.4_SentOut.gh (31.3 KB)

I’ve already read through these important posts, and more

Hi @D.Ronald,

I am wondering why the need for a single tree rather than 4 separate trees that you can operate on concurrently?

@christopher.ho

I wanted to export one full report to CSV, Excel, or to JSON or to database. The full report would show a hierarchy of ‘ownership’ of all the geometries within other geometries - a literal hierarchy tree.

Another reason is that I want to build a tree that clearly shows the relationship between all the geometries. I need structured data which shows what geometry is inside the others, spatially. From this you can do all your calculations such as densities.

Thanks. Darrel

Found your the problem.

branchData = dTree.Branch(i)

Because you add the path {0,0} that becomes the second path with three items rather than the path {1} which you were originally looking for.
I don’t know if we can assume that there are no buildings that exist outside of a plot?

import Rhino as rc
import Grasshopper as gh
import Grasshopper.Kernel.Data.GH_Path as GH_Path
import ghpythonlib.treehelpers as th


#--------------------------------------------------------
# FUNCTIONS

def rcCentroid(c):
    """ Get CENTROID from CURVE """
    rcCentroids = rc.Geometry.AreaMassProperties.Compute(c)
    return rcCentroids.Centroid
    
def dataTreeGenerator(dataTree, data):
    """ 
    Create DATA TREE from data
    Args: dataTree, data
    """
    dLength = len(data)
    for i in range(dLength):
        path = GH_Path(i)
        dataTree.Add(data[i], path)
    return dataTree

def rcCurveInside(curve, points):
    """Tests if POINTS (p) are inside CURVES (c) """
    results = []
    for p in points:
        result = rc.Geometry.Curve.Contains(curve, p)
        results.append(result)
    return results


#--------------------------------------------------------
# EXECUTION

# construct Empty Data Tree
dTree = gh.DataTree[object]()

plotCentroids = []
for c in plots:
    plotCentroids.append(rcCentroid(c))
buildingsCentroids = []
for c in buildings:
    buildingsCentroids.append(rcCentroid(c))
massingCentroids = []
for c in massing:
    massingCentroids.append(rcCentroid(c))


# Construct DATATREE from DEVS
dTree = dataTreeGenerator(dTree, devs)
print dTree
#print type(dTree)
#print dTree.Path(0)
print dTree.Branch(1)
#print dTree.BranchCount

# Iterate the first layer of branches
for i in range(dTree.BranchCount):
    branchData = dTree.Branch(GH_Path(i))
    branchPath = dTree.Path
    # get the curves in each branch
    for j in branchData:
        # get both items of PLOT CURVE and PLOT CENTROID
        for plot, centroid in zip(plots, plotCentroids):
            
            # test inclusions
            result = rc.Geometry.Curve.Contains(j, centroid)
            print result
            print i
            # filter by inclusion to create tree
            if result == rc.Geometry.PointContainment.Inside:
                dTree.Add(plot, GH_Path(i,0))
                
                for building, centroid2 in zip(buildings, buildingsCentroids):
                    result = rc.Geometry.Curve.Contains(plot, centroid2)
                    if result == rc.Geometry.PointContainment.Inside:
                        dTree.Add(building, GH_Path(i,len(dTree.Branch(GH_Path(i,0)))-1,0))
                        
                        for mass, centroid3 in zip(massing, massingCentroids):
                            result = rc.Geometry.Curve.Contains(building, centroid3)
                            if result == rc.Geometry.PointContainment.Inside:
                                dTree.Add(mass, GH_Path(i,len(dTree.Branch(GH_Path(i,0)))-1,len(dTree.Branch(GH_Path(i,len(dTree.Branch(GH_Path(i,0)))-1,0)))-1,0))

Maybe see if the above code is what you are looking for.