Silhouette python or grasshopper

Hi All,

I’m looking for a either a python example or a grasshopper component that returns a curve in the name manner as the Silhouette command - does anyone have an example?

Cheers

DK

jsut found it in c#:

it’s highly probable it will look about the same in python

Hi,
DuplicateEdgeCurves gets the output you’re looking for using RhinoCommon.
I am sure there is a component in grasshopper that does this, anyhow since you asked for either a method or a component, here you go with the method
siloutte = brepname.DuplicateEdgeCurves()

pretty sure dupEdge and silhouette are not the same thing. Imagine silhouette more like a (chinese) shadow image, while dupedge has some depth to it.

Managed to poke around with the RhinoCommon info and got this to work:

import Rhino

Board = x
Camera = cam
Sil_Type = Rhino.Geometry.SilhouetteType(16)
Sil_Tol = 0.01
Ang_Tol = 0.01

Results = Rhino.Geometry.Silhouette.Compute(Board,Sil_Type,Camera,Sil_Tol,Ang_Tol)

Output_Curves = []
for Result in Results:
    Output_Curves.append(Rhino.Geometry.Silhouette.Curve.GetValue(Result))

a = Output_Curves

Please do not judge my coding (lack of) style - this work and does exactly what I need it to do.

Cheers

DK

1 Like

haha, you would not want to look at some of my ugly codes, so don’t worry about being judged;)

1 Like

I’ve hooked into this thread as I need similar functionality. I’m trying to reproduce the Silhouette function in keyboard Rhino to recreate the outer (and inner sometimes) boundary of a 3D-object. I use this to gain a 6mm offset for each layer (after the whole model has been split into slices) which I then use to machine a ‘blank’ slice, prior to glueing and moulding. I’ve now (thanks to the very helpful Helvetosaur) automated the layering into closed models. For each slice I need the silhouette (DupEdge has caused issues with the offset as well as making the CNC router go crazy at times. I’ve attached where I’ve got to from this thread. It sort of works on some objects. But I drew a random shape and the silhouette has some vertical (‘z’ axis parallel) lines as well as top and bottom outlines. Maybe all I need to do with this whole thing is project to the C-plane and join everything in which case I can do that. But there doesn’t seem to be a Curve Boolean function (as I used in the original manual operation) in python Rhino so not sure how I end up with a single outline curve when scripting. I guess I’m just trying to find out if I’m on the right track as I can do more testing to see the effect of things like projecting onto a plane. Suspect I’ll need proper help shortly though!

Test Silhouette.py (938 Bytes)
SW57 Test for Python Dummy model.3dm (5.2 MB)

I don’t know what you’re trying to achieve, but maybe the Mesh Shadow component could be useful for you.

1 Like

Check this out:

https://developer.rhino3d.com/api/RhinoCommon/html/M_Rhino_Geometry_Curve_CreateBooleanRegions.htm

https://developer.rhino3d.com/api/RhinoCommon/html/T_Rhino_Geometry_CurveBooleanRegions.htm

Thanks. I think that will work, but I just don’t know enough to use it - sorry! I’m pretty new to python scripts and now have to take on the RhinoCommon stuff as well which seems to require conversion between types, and I don’t know how to do that. I have a list of GUIDs (all edge curves which are projected onto a plane) and would like the Boolean function to work on these to just leave the outer (and inner in some cases though that is less important) shape. Mesh operations aren’t ‘true’ enough to the curve to not cause the offset function to get messed up (and also the CNC router which tries to follow it). So somehow I need to be able to make the GUIDs I have acceptable to the CreateBooleanRegions Method - I guess this means making it of type IEnumerable. I have no idea how to do this unfortunately. Looks like more processing might be required beyond that also to get the final curve.

I’ve uploaded a model which I manually generated the outline (I added 6mm offset to make it stand out better). In actual use I wouldn’t do an outline of a whole model, but would cut whatever model I’m making into 50mm (say) slices, then get an outline of the 50mm slice and add the 6mm offset to create a boundary for a roughing blank. I glue all the oversized blanks together (normally machining each layer first) so I can create the whole model for CNC machining. I’ve also uploaded the python script which is just to develop the silhouette part of the operation. It works as far as getting loads of outline curves projected onto the input plane.

Thanks for any help on this

Ben

Test Silhouette.py (1.3 KB)
SW57 Test for Python Dummy model Demo Version.3dm (4.0 MB)

I’ve never used Rhino.Geometry.Silhouette before, and it doesn’t do at all what I’d imagined it would. I’d thought it would return the planar object silhouette for a desired camera view - like Make2D does -, but instead it computes all sorts of tangent, crease, boundary, etc. silhouette types.
When you inspect the Rhino.Geometry.SilhouetteTypes that it returns, you’ll notice that there isn’t even a Rhino.Geometry.SilhouetteType.Boundary for your case, which is weird?

For your current amalgamation of projected curves, regional curve booleans won’t do the trick, since they require neat and tidy, closed, planar curves to evaluate.
You’d probably have to shatter your curves at intersections and self-intersections to get their individual segments. After that you’d have to implement some sort of algorithm that can sort out which connected segments make up the “real” object silhouette.

Maybe there’s an easier way, but I can’t think of one for now.

Interestingly enough, Make2D also fails to produce a clean Scene Silhouette for your object.

Oh dear. Seems a pity as all it takes in manual operation is to do a Silhouette, project to C plane, then do Boolean Curve and click anywhere outside. That works very well. The outline curve doesn’t need to be very accurate (I make it 6mm oversize just so there is roughly a min of 6mm to machine off anything). But it does need to be smooth. The offset function would get upset by the outline curve that Meshoutline produced so I’m assuming this would be the same. It also makes the machine work very hard if there are loads of tiny line segments joined together. The reason I’m automating mainly is for material estimation as I often get asked for a price using different thickness materials and manually it can take a few hours to do an estimate. I’ve automated the CAM side, driving the CNC machine, and the slicing is also automatic now, so this is the only thing remaining to take a quote from 4 hours to 4 minutes! Do you know if there’s a way to make a curve ‘smooth’ even if it isn’t as accurate? I will look at Meshoutline (for python) to see what kind of output it produces, though most of them were fine and I can’t remember which models would screw it up.

Thanks again

Ben

Thanks Martin. That does seem to produce a curve, rather than polyline so is what I need. Takes me in a different direction as now I have to figure out how to get the rest of what I’ve done into Grasshopper to integrate the whole things so I’ll set to work on that.

Regards

Ben

Here’s what I came up with trying to replicate your manual workflow with python.

import Rhino
import Rhino.Geometry as rg

tol = Rhino.RhinoDoc.ActiveDoc.ModelAbsoluteTolerance
angleTol = Rhino.RhinoDoc.ActiveDoc.ModelAngleToleranceRadians

brep.Faces.SplitFacesAtTangents()

silhouettes = rg.Silhouette.Compute(
    brep,
    rg.SilhouetteType.Boundary,
    rg.Vector3d.ZAxis,
    tol,
    angleTol)

crvs = []

for sil in silhouettes:
    crvs.append(rg.Curve.ProjectToPlane(sil.Curve, rg.Plane.WorldXY))

regions = rg.Curve.CreateBooleanRegions(
    crvs,
    rg.Plane.WorldXY,
    True,
    tol)
    
a = regions.RegionCurves(0)

This line was necessary to get the brep in your sample file to produce a silhouette.

brep.Faces.SplitFacesAtTangents()

silhouette_python.gh (1.0 MB) sample brep is internalized in this file

-Kevin

1 Like

Thanks very much Kevin. This looks very promising. I’ve coded pretty much exactly what you suggested (attached) except as a script outside of Grasshopper - so I used the ‘coercebrep’ function to convert from selected geometry. I’m not as comfortable working inside Grasshopper yet and I don’t really know how to do all the slicing and layering which I do (the attached drawing shows how a simple mould ends up in Layers 01 - 20). If I have to figure out how to do it inside Grasshopper, so be it, but I’ve tried this way first. Anyway, it doesn’t work properly for me. I’ve attached the drawing I used with some sample shapes and one of them (the extrusion) seems to work fine. The other 2 come up with the error:-

Message: Object reference not set to an instance of an object.

Traceback:
line 28, in , “C:\Users\Ben\OneDrive - Wilkinsons\Projects\Rhino Python\Test Silhouette.py”

Have I just done something stupid here, or do I have to do it inside Grasshopper like you did?

SW57 Test for Python Dummy model.3dm (6.4 MB)
Test Silhouette.py (1.7 KB)

Your file seems to work here with all 3 objects in your test file - adds silhouette curves to current layer and can see output from print statements - not seeing any errors.

Not necessary to do this in grasshopper, I did it that way because of the title of your thread (and it’s where I work most often).

-Kevin

I’ve looked into this in more detail now. I have 2 computers with Rhino on them and both show repeatable failures for 2 of my models. When I stopped the program after the silhouettes array is formed, you can see that the program fails when the ‘curve’ at a particular instance doesn’t have any Curve information. The one that works has Curve info for all indicis. I’ve uploaded a copy of the debugger output for this. I did notice this in my original script as I did a test for a valid GUID before adding to the array and quite a few elements were omitted this way. Maybe that’s what I need to do - test if the Silhouette output element is valid or not. Does that make sense? Is Silhouette supposed to create non-valid curves (if that’s what they are)?

Thanks

Ben

Tried your code again and it worked with all 3 objects. I usually work on MacOS so decided to try your file on my Windows PC and reproduced the error you are seeing.

Not sure why this behaves differently on Windows and MacOs but this modified code works on both:
Test Silhouette.py (1.7 KB)

These are the only changes I made to your code:

  • Added line 28 to make sure there is a Curve in the current silhouette result.
  • Changed indent level on line 29.

-Kevin