I am trying to output some colored surfaces through a python function which I intend to use in a headless compute environment.
import rhinoscriptsyntax as rs
import scriptcontext
import Rhino
ghdoc = scriptcontext.doc
my_doc = Rhino.RhinoDoc.CreateHeadless(None)
my_doc.ModelUnitSystem = Rhino.UnitSystem.Meters
Rhino.RhinoDoc.ActiveDoc = my_doc
doc_object = my_doc.Objects.Find(G)
if doc_object is not None:
attributes = doc_object.Attributes
geometry = doc_object.Geometry
scriptcontext.doc = Rhino.RhinoDoc.ActiveDoc
# We add both the geometry and the attributes to the Rhino doc
rhino_brep = scriptcontext.doc.Objects.Add(geometry, attributes)
# Set print color if provided
if C:
rs.ObjectColor(rhino_brep, color=C)
scriptcontext.doc = ghdoc
a=rhino_brep
Unfortunately this doesn’t return the colored geometry.
if doc_object is not None:
attributes = doc_object.Attributes
if C:
attributes.ColorSource = Rhino.DocObjects.ObjectColorSource.ColorFromObject
attributes.ObjectColor = C
So basically the context of this is I need to colour some geometry but in a headless environment because I am using Rhino Compute to do this. That is why I’m doing this line my_doc = Rhino.RhinoDoc.CreateHeadless(None)
The other lines of code for doc manipulation are gathered from Mcneel website where there is a custom bake component for Rhino doc. Rhino - Custom GhPython Baking Component
There definitely is some flaw in my logic but since there isn’t much documentation on adding colour to geometry in a headless environment, this is the best I have come up with. Hopefully this provides a bit more clarity.
Is this Python script running in a Grasshopper definition that will eventually be evaluated by rhino.compute? If so, I don’t think you need to bake or add anything to the document at all. You just need the Brep to be returned from rhino.compute to then be used in whatever client you’re using. Usually you would do this by passing the Brep into a Context Bake Component. Then, when rhino.compute evaluates your definition, it will return the Brep back to the client.
I should also say that I’m not sure object attributes are currently serialized as part of the geometry… That is I can’t say for certain as I haven’t tried that. But, I would think you might be better off by returning your Brep and your colors separately… and then combining those however you want inside your client code. Does that help?
This is something I tried before; however, it did not work, I tried setting the object color to a surface, but it didn’t help. The documentation is a bit vague for python but here is what I did. I outputted a list of all the colors and use those colors to set the objectcolor of the breps. But when I add them to a 3dm and write it, they don’t have the corresponding colors. Am I missing something?
colors = []
for val in response_object:
paramName = val['ParamName']
if paramName == "RH_OUT:Colors":
innerTree = val['InnerTree']
for key, innerVals in innerTree.items():
for innerVal in innerVals:
if 'data' in innerVal:
data = json.loads(innerVal['data'])
colors.append(data)
for idx, val in enumerate(response_object):
paramName = val['ParamName']
if paramName == "RH_OUT:Surface":
innerTree = val['InnerTree']
for key, innerVals in innerTree.items():
for innerVal in innerVals:
if 'data' in innerVal:
data = json.loads(innerVal['data'])
geo = rh.CommonObject.Decode(data)
if idx < len(colors):
color_str = colors[idx]
r, g, b = map(int, color_str.split(','))
a = 255
att = rh.ObjectAttributes()
att.PlotColor = (r, g, b, int(a))
model.Objects.AddBrep(geo, att)
I guess I’m still confused as to what it is you’re trying to do. You shouldn’t need to add anything to the document (at all).
Can you tell me more about what your “client” looks like… meaning how are you sending the request to rhino.compute. I assume you’re wanting to use rhino.compute to solve a grasshopper definition and then get some data back. Is that correct? If that’s the case, you simply need to output a brep and a list of colors and connect those to a Context Bake component. Then, when you evaluate your definition in rhino.compute… it will look for the data connected to any of the Context Bake components in your definition and send the data back to your client as part of the response. A simplified version of what this GH definition might look like is below.
I’ve attached the ghx below, have a look, but basically, I’m doing something similar. Now my problem is after I get back those breps and colors within vscode, how do I set the color of those breps and put them into a 3dm.
Ok. I guess I’m still unclear as to what you’re trying to do. Are you trying to have rhino.compute to perform some calculation and return a result? If so, where is the resulting being returned to? Are you using Hops? Are you returning the geometry and list of colors back to Grasshopper? Or is your client some other thing (like a web site, etc.)? Again, I don’t think you want to be adding anything to any document… but without understanding what the overall goal you’re trying to achieve… it’s hard to help.
Sorry about so much confusion, here all the all the files and the steps outlined.
Read 3DM using Rhino3DM library in Python (VScode). Get the breps and get the corresponding user value. In this case its zoning curves+ its corresponding zoning value.
Send this data to Rhino Compute where the ghx is a script that turns curves into breps and outputs a list of breps + a list of colors which correspond to the brep.
Goal : Color the breps with their corresponding color somehow without turning them into meshes and using mesh colors as this is really slow and what I am currently using. I basically want the coloring process of the breps to be done automatically somehow.
End Output (Goal): A 3DM with breps which are colored. (i.e. zoning surfaces colored by their corresponding colors in the 3dm)
zoning.3dm (614.3 KB) - This is the 3DM with the curves from step 1
test.py (3.6 KB) - This is the python script from vscode from step 1. Connection to rhinocompute is here.
zoning.ghx (65.4 KB) - This is the grasshopper ghx script run on rhinocompute used in step 2(This turns the curves into surfaces and gets a corresponding color and ouputs both as two lists)
Ok. I think I understand better. I’m still not clear as to who is sending the request to rhino.compute. I’m going to assume that it’s a user who is using Hops and sending a simple grasshopper file to take the curves and extrude them to a specific height and generate the colors. This script would then pass back the list of breps and a list of colors (using the Context Bake component) to Hops and these would be output from one of the two outputs on the Hops component.
So, at this point, we just need to assign the colors to the breps and add them to a document and write out the 3dm (if I understand everything correctly). I’m going to use a C# component to do this (since this is what I use most often). The first two inputs on this component takes a list of breps and a list of colors… these would be what would be coming from the Hops component output. After that, the script basically looks like this:
if(breps.Count != colors.Count) return; //the list of breps does not match the list of colors
using (var doc = RhinoDoc.CreateHeadless(null))
{
for(int i = 0; i < breps.Count; i++)
{
var att = new Rhino.DocObjects.ObjectAttributes();
att.ColorSource = Rhino.DocObjects.ObjectColorSource.ColorFromObject;
att.ObjectColor = colors[i];
doc.Objects.Add(breps[i], att);
}
if(export && !doc.Export(filepath)){
//File could not be saved
}
}
This is very simplified code and should probably be expanded to check for edge cases. But, this should create a new set of object attributes… then assign the colors to the attributes and then add the geometry and attributes to the document. Finally, at the end it writes out the .3dm file to a path specified in one of the other inputs. Does this help (or am I still misunderstanding what you’re after)?
Thanks so much for this. This is very close to what I require. To answer your question, the user sends the compute request through a web interface, they click on a button which triggers a compute run.
Instead of saving the file within grasshopper, is there a way to return the colored objects from the component so I can basically save the file in my python script rather than inside gh? The reason being I want to run this with my AWS server, and it’s hard to return a file which gets saved locally within my EC2 instance.