PyMEL: Finding non-border edges on a UV shell?


#1

So I’m looking into the component class methods in PyMEL (MeshEdge, MeshVertex, MeshFace and so on) to see what can be done and can’t be done. Tried the isOnBoundary() method of the MeshEdge class only to discover that it only applies to polygon mesh borders - and not actual UV shell borders, so how can I get the same results but for UV shells?

I guess that a picture says more than a thousand words so:

How do I find those three edges in code?


#2

This should be doable from the Python API again. When I get some time, I can try to prototype it, but the way I would approach it is:

  1. Get the UV shell membership (should be available off MFnMesh).
  2. For the shell you’re interested in, record the list of edges.
  3. Store the vertices for each mesh edge.
  4. Iterate over the faces of the mesh and record the UVIds for each edge vert.
  5. Now the test I believe should be:

If the edge participates in more than one face and the UVIds for the edge verts for both faces are the same, then it is an interior UV edge.

If it participates in only one face, then it’s clearly a border edge.
If it participates in 2 faces, but the UVIds are different, then that is a UV seam/border.


#3

But how would the logic know what shell “I’m” interested in? I would have to run that algorithm for all shells.
Also how would 4. work considering a vertex can belong to any number of UV’s (and therefore, UVId’s).

Anyway, I thought some more about this. What I really want to do is check how many UV’s a particular edge is connected to (either it’s connected to 2 or 4 - it can’t be connected to any other number) but my thoughts got back to the super slow “select-and-convert” method until I realized that there is actually a component conversion functions that doesn’t involve pm.select()

Example:

import pymel.core as pm
import time

orgSel = pm.ls(selection=True, flatten=True)[0] # Just checking one edge for demonstration
boolVar = False

start = time.time()
for edge in orgSel:
    edgeUVs = pm.ls( pm.polyListComponentConversion(edge, fromEdge=True, toUV=True), flatten=True )
    if len(edgeUVs) == 2:
        boolVar = False
    else: boolVar = True
print "func took %.8f seconds" % (time.time() - start) # Takes, AT MOST 2 ms on my PC - most of the time we are talking nanoseconds
if boolVar == False:
    print("selected edge was closed")
else:
    print("selected edge was open")
# On the edges at the center of a shell, this will say that the edge was closed - and for edges that are belonging to two different shells it will say that the edge is open.

So yea, the only thing I’m really interested in here is to see how many UV’s a particular edge is selected to. It is what is gonna take time for the particular thing I’m interested in. I did a sloppy measurement on this and it turns out that doing this conversion with polyListComponentConversion is actually rather fast. Not super-fast ofc - above check takes at most 2 milliseconds on my computer (so for it to feel slow you would basically need a selection of 100+ edges - give or take). I realized that this is probably acceptable in my case, as I’m really not chasing nanoseconds.

I think I’ll go with this unless ofc there is some genious approach out there :slight_smile: Thanks for your input anyways - it lead me into this thinking, and ultimately: this solution.


#4

No worries. As long as you got what you wanted. Just to clarify my points though:

The way 1 would work is you would have some indication of a shell like an edge/face/vert. Something to indicate which shell you’re interested in. Given your requirements it would be an edge.

The way 4 would work is that you don’t look at vertices. You look at face vertices. You can create a unique face/vertex pair for each face that a vertex participates in. Each one of these can have an individual UV Id assignment.


#5

Ahh, yes that is true. I was thinking about ordinary faces.