I'm a beginner in Python and have a question about converting data structure, for using it in Grasshopper.
As an output from my python code, I have a grid of cubes (GUID's), layered up in what I call 'generations'. Besides that, it outputs a grid of data, which contains the information about what color each cube should get.
For example: for j=5 in i=3, in generation=5, I have a cube. In the other list, for j=5 in i=3 , in generation=5, I have 'green' as a string. In grasshopper, I want to link this 'green' value to a swatch, and then color the right cube with it.
The problem is that Python outputs a three-dimensional array, while Grasshopper works in trees. So, I have to convert my outputs to a tree structure in which the first level is 'generations', the second level is 'i' and the third is 'j'.
A friend sent me this piece of code, so I guess that is how to begin:
import clr clr.AddReference("Grasshopper") from Grasshopper.Kernel.Data import GH_Path from Grasshopper import DataTree
I hope you guys can help! Tessa
This is my mainfunction:
def Main():
intLength = input1
intWidth = input2
intGen = input3
arrValues = randomizeArray01(intLength,intWidth)
arrDensity = densityfunction(arrValues)
arrMeshes = render(arrValues,-1)
for k in range(intGen):
arrValues = applyGOL(arrValues,arrDensity)
arrDensity = densityfunction(arrValues)
genC = colorObject(arrValues)
colorList.append(genC)
genR = render(arrValues,k)
renderList.append(genR)
In which this is the renderfunction:
def render(arrValues, z):
rs.EnableRedraw(False)
arrMeshes = []
for i in range(len(arrValues)):
arrRow = []
for j in range(len(arrValues[i])):
box = addMeshBox([(i-0.5),(len(arrValues[i])-j-0.5),z-0.5], [(i+0.5),(len(arrValues[i])-j+0.5),z+0.5])
arrRow.append(box)
arrMeshes.append(arrRow)
rs.EnableRedraw(True)
return arrMeshes
And this is the colorfunction:
def colorObject(arrValues):
arrColor = []
for i in range(len(arrValues)):
rowColor= []
for j in range(len(arrValues[i])):
if arrValues[i][j] == 0:
color = green
rowColor.append(color)
elif arrValues[i][j] ==1:
color = residential
rowColor.append(color)
elif arrValues[i][j] ==100:
color = retail
rowColor.append(color)
elif arrValues[i][j] ==1000:
color = road
rowColor.append(color)
arrColor.append(rowColor)
return arrColor
And in the end, this is what I output to Grasshopper:
a = renderList
b = colorList
In grasshopper, this gives me a list of 'Iron.Python.Runtime.List'.
I don't have a working version of grasshopper to hand, but my code for doing this is:
import rhinoscriptsyntax as rs
import Rhino.Geometry as rg
from clr import AddReference as addr
addr("Grasshopper")
from System import Object
from Grasshopper import DataTree
from Grasshopper.Kernel.Data import GH_Path
def raggedListToDataTree(raggedList):
rl = raggedList
result = DataTree[object]()
for i in range(len(rl)):
temp = []
for j in range(len(rl[i])):
temp.append(rl[i][j])
#print i, " - ",temp
path = GH_Path(i)
result.AddRange(temp, path)
return result
There is a gist of this here that also has a function that turns trees into lists.
There's still quite a lot wrong with this, no recursion, no error checking, no branch magic, but it does the job in most cases. I'd love to see it improved!
In your case you can just pipe the output that would otherwise give you a runtime list into the raggedListToDataTree
function.