Faces property, SubDEdge Object?

A subdvertex type has a handy property, below. Is there an equivalent to get, for example, all faces that an edge object is part of?

Edges All edges that this vertex is part of

From a face, you can get VertexAt or EdgeAt, but not necessarily just a list of the relevant edge / vertex Ids.

Hi @Jonathan_Hutchinson1,

Use SubDEdge.FaceCount and SubDEdge.FaceAt.

– Dale

Hi Dale,

Does the FaceAt not require the edge index? Doesn’t FaceCount only return the number/count of related faces, rather than their indices?

Apologies if I haven’t explained well enough.

Something like?

for i in range(count):
    faceref =  edgeobj.FaceAt(i)
    print faceref.Id

No. SubDEdge.FaceAt requires a value >= 0 and < SubDEdge.FaceCount.

– Dale

Thank you. So the ‘index’ that FaceAt required, is really just a temporary index for the sake of getting the subdface object? I’m trying to think whether the order of the returned FaceAt is going to cause me an issue.

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 ) )