Is it possible to invoke sub-object selection through a Python script? For example, if I have a polysurface and I want to select one face. Or would I have to extract the face and deal with it that way? That’s what I am assuming I will need to do but I thought it’s worth asking.
You can get sub-objects - that is one of the strengths of Python, but you will have to go through RhinoCommon - as the subobject doesn’t really exist as an object with an ID in the document, so you have to first extract its geometry, then you can add that back to the document if you want it to exist in the document independently.
However, you can also just work with it as (virtual) geometry without adding it to the document - that is also one of the great strengths of Python/RhinoCommon. Unfortunately, at that point, as most rhinoscriptsyntax methods are based on ID’s - that is to say they only recognize objects that are in the document - if you want to continue working with your virtual geometry, you will need to do most of your succeeding operations in RhinoCommon as well. So things can get complicated pretty quick.
Following is a snippet that allows you to select a sub-surface and offset it by a given value. Note that the selection is not restricted to subsurfaces, it will also select surfaces (I don’t know yet how to restrict it to just Brep faces).
import rhinoscriptsyntax as rs
import scriptcontext as sc
import Rhino
def TestOffsetSubSrf():
msg="Select a surface or Brep face to offset"
srf_filter=Rhino.DocObjects.ObjectType.Surface
rc,objref=Rhino.Input.RhinoGet.GetOneObject(msg,False,srf_filter)
if rc!=Rhino.Commands.Result.Success: return
offset=rs.GetReal("Offset value")
if offset==None: return
face=objref.Face()
subSrf=face.ToNurbsSurface()
oSrf=subSrf.Offset(offset,sc.doc.ModelAbsoluteTolerance)
sc.doc.Objects.AddSurface(oSrf)
sc.doc.Views.Redraw()
TestOffsetSubSrf()
What I am trying to do is extract information from an object, specifically hole information from an imported Solidworks detail. Ideally I would like to select the cylindrical face that represents the hole, then have the diameter, depth and location fed back to the command line, or whatever else I need to do with it. I have a tool that provides this information currently, but it’s not as automated as I would like.
Thanks Mitch and Clement for your code samples. I will study these closely tomorrow.
All of these examples are very informative and helpful. I think I have more reading to do, especially with regard to RhinoCommon and how to use it. For example, TryGetCylinder is unknown to me, but looks like exactly what I need.
But 8+16 is surface or polysurface, and I’m holding shift+control during selection while using the script and I get no sub-object highlights with the script running in V8.
Pre-selecting the sub-objects I want also doesn’t work because the script just de-selects them and asks for 2 objects, despite preselect=True.
That’s correct, surfaces and polysurfaces are single objects allowed in the rs.GetObjects() method,
but this function does not have a subobjects argument like rs.GetObject()
You could write a function that allows you to select multiple faces in a loop using rs.GetObject()
I was lazy and asked chatGPT to write it, and with the second question it actually produced this working example, using the GetObject function (so RhinoCommon directly instead of the rhinoscriptsyntax method)
import rhinoscriptsyntax as rs
import Rhino
def select_multiple_subobjects():
# Initialize an empty list to store selected sub-object indices
selected_subobjects = []
# Prompt the user to select sub-objects (with sub-object selection enabled)
go = Rhino.Input.Custom.GetObject()
go.SetCommandPrompt("Select multiple sub-objects (faces, edges, vertices) from a polysurface")
go.SubObjectSelect = True # Enable sub-object selection
go.GetMultiple(1, 0) # Allow multiple selections
if go.CommandResult() != Rhino.Commands.Result.Success:
print("No sub-objects were selected.")
return
# Loop through the selected sub-objects
for obj_ref in go.Objects():
# Get the geometry of the selected sub-object
subobject_index = obj_ref.GeometryComponentIndex.Index
# Get the sub-object type
subobject_type = obj_ref.GeometryComponentIndex.ComponentIndexType
if subobject_type == Rhino.Geometry.ComponentIndexType.BrepFace:
# Store only face sub-object indices
selected_subobjects.append(subobject_index)
print(f"Face with index {subobject_index} selected.")
elif subobject_type == Rhino.Geometry.ComponentIndexType.BrepEdge:
print(f"Edge with index {subobject_index} selected.")
elif subobject_type == Rhino.Geometry.ComponentIndexType.BrepVertex:
print(f"Vertex with index {subobject_index} selected.")
# Display the result
if selected_subobjects:
print(f"Selected face indices: {selected_subobjects}")
else:
print("No faces were selected.")
# Run the function
select_multiple_subobjects()
Since the pages I posted are the top results when I searched, perhaps it would be good to put a warning on the top of those pages (if the referrer is Gogle) with a link to the better source you posted?