Also Dale, can you think of a way to go from a SubDEdge Id, back to component index within it’s parent subd, to enable selection? I think I need to use an ObjRef in some way, although I thought an ObjRef only applies to a unique parent object, not a sub object such as an edge.
I’m also not sure how to then use methods for this selecting. I am trying to switch a selection of edge loop/s into the edge rings shared between them.
EDIT: I had a little bit of luck with this, actually. Done just for fun, to try and practice with manipulating subd types a little bit.
What I would like to build is an ‘ExtractIsocurve’ tool for subds interactively, using isocurves that go along a faceloop. This is my slow progress hack job, where next I would probably . I can see from my practice so far that it is not trivial, since the subd objects don’t necessarily have an ‘order’. The restriction is you need a nice quad face loop. I think I might be repeating myself a bit in the code below, switching around from Ids to Component Indexes and so on.
# Convert Loop to Ring Selection
import Rhino
import Rhino.Geometry as rg
import scriptcontext as sc
def GetSubDEdge():
#select a subd edge, return edge ids of selection
go = Rhino.Input.Custom.GetObject()
go.GeometryFilter = Rhino.DocObjects.ObjectType.MeshEdge
go.SetCommandPrompt('Select edge ')
go.GetMultiple(1,0) # could be optional depending on inputs, add cmd line op?
objrefs = go.Objects()
subdref = go.Objects() [0].SubD()
edge_ids = [ objref.GeometryComponentIndex.Index for objref in objrefs ]
return edge_ids, subdref, objrefs
#global vars
selected_edge_id, subdref, subdobjref = GetSubDEdge() #returns selected edge ids
ring_edges = []
guid = subdobjref [0].ObjectId # guid of top level object, NEEDS ERROR CHECKING
#returns the faces related to edge selection
edge_obj = [subdref.Edges.Find( selected ) for selected in selected_edge_id ]
faceids = []
for edge in edge_obj:
count = edge.FaceCount
for i in range(count):
faceref = edge.FaceAt(i)
faceids.append(faceref.Id) if faceref not in faceids else next #
facedict = dict ( zip ( faceids, [ faceids.count(face) for face in faceids ])) #collect counter
shared_faces_ids = [ i for i in facedict if facedict.get(i) > 1 ] # Return SubDFace Id / Component Index
shared_faces_objs = [ subdref.Faces.Find(faceid) for faceid in shared_faces_ids ] # Return SubDFace Type
for faceobj in shared_faces_objs:
for i in range(faceobj.EdgeCount):
if faceobj.EdgeAt(i).Id not in selected_edge_id:
ring_edge_index = faceobj.EdgeAt(i).Id
ring_edges.append(ring_edge_index) if ring_edge_index not in ring_edges else next
ring_edge_objs = [ subdref.Edges.Find( edge ).Id for edge in ring_edges ] # return the ring edges, SubDEdge Type
component_indices = [ rg.ComponentIndex (rg.ComponentIndexType.SubdEdge, obj) for obj in ring_edge_objs ] # create ComponentIndex Types
#component index and ring edge index are same number - is this duplication ?
objrefs = [Rhino.DocObjects.ObjRef(guid, index) for index in component_indices] # create ObjRef type, does it just accept an integer for index?
rhino_objects = [ ref.Object() for ref in objrefs ] # create RhinoObject Type
sc.doc.Objects.UnselectAll() #Remove current selection
# Do the ring selecting
for enum, obj in enumerate ( rhino_objects ):
obj.SelectSubObject( component_indices [ enum ], True, True, True ) # best overload ?
print "Selected Edge Index", obj
### from the vertices of selected edges, find vert ids that only appear once
## i.e. they will be an end point
# if closed, index of every vert will appear exactly twice
print "selected edge indices:", selected_edge_id
print "associated face indices:", faceids
print "shared face indices:", shared_faces_ids
print "Edge ring indices are:", list ( set( ring_edges ) )