Home Youtube GitHub

PyMel: find edges inbetween


#1

Hi!
I’m trying to get a list of edges between “selection”.

  1. I have a list of edges from the beginning
  2. I’m looking for mirrored ones
  3. Find edges inbetween those 2 lists.

edges

How would you approach that?
Not sure if that’s the right place, but I can not find any good and working solution for this.
Also, don’t know pymel as good yet, so any tips appreciated - maybe there are some built-in functions that would help me?

Thanks in advance!
Cheers!


#2

Hi @Krzym,
I wrote this little script that should solve your problem. Its commented well enough that you should be able to follow the basic logic. You can pass it a list off edges (one side of the mesh) or it can use your selection.
If this code doesn’t show up you can get it here:

from maya import cmds


def find_edges_between(input_edges=None, summery_axis='x'):
    '''
    Given an list of edges on one side of a mesh this function finds the edges on the same loop that are between
    the input edge(s) and a symetrical set of edges. This function is not dependant on edge indices
    :param input_edges A lsit of at least one edge on one side of a mesh.
    :param summery_axis The symmerty axsis in object space NOT world space.
    :returns List of the edges in between
    '''
    if not input_edges:  # Get selection if no list is passed
        edge_set_1 = cmds.ls(sl=True, fl=True)
    else:
        cmds.select(input_edges, r=True)  # Select the list
        edge_set_1 = cmds.ls(sl=True, fl=True)  # Make sure the edge list is flat (every edge name listed)
    cmds.symmetricModelling(about='object', axis=summery_axis, s=1)  # Turn on object symmetry around the axis passed
    cmds.select(edge_set_1, symmetry=True, r=True)  # Replace the selection with a symmetrical selection
    # Loop selection and keep a list of new edges aka symmetrical edges
    edge_set_2 = [e for e in cmds.ls(sl=True, fl=True) if e not in edge_set_1]
    cmds.symmetricModelling(s=0)  # Turn off object symmetry
    # Get the index of the first edge in the lists of edges and cast to int
    edge_1 = int(edge_set_1[0].split('[')[-1].split(']')[0])
    edge_2 = int(edge_set_2[0].split('[')[-1].split(']')[0])
    # Find the shortest edge loop path between the above two indices
    between_edges = [e for e in cmds.polySelect(edgeLoopPath=(edge_1, edge_2), ass=True, ns=True)
                     if e not in edge_set_1 and e not in edge_set_2]
    print(between_edges)  # Print the between edges for easy copy and paste
    return between_edges

#3

hi, sounds like a math test…

normally a edge loop has a continous edge numbering.
so maybe you could test for max minus min number and then compare with the selection list. if the some edge numbers are missing, then it should return the inbetween…

edit: lucas was quicker…


#4

Thanks guys, helped a lot!
Although I’m not so sure about using maya symmetry, I’ve used mGears find_mirror_edge.
As far as I’ve tested edgeLoopPath works fine, but I’m curious about the math test (soulcage).

I see that every edge is counted every 2, would you try to find a pattern? or what would be your approach?

Here’s my code:

import pymel.core as pm

from mgear.core import meshNavigation

def tests( ):

eLoop = pm.ls(sl=True)
singleModule = False

# Edges

if eLoop:
# Geo
    geo = pm.listRelatives(eLoop[0], parent=True)[0]
    geoTransform = pm.listRelatives(geo, fullPath=False, parent=True)[0]

else:
    pm.displayWarning("Please set the edge loop first")
    return

if singleModule is False:
# mirror module

# mirror edges
    mLoop = []
    for edge in eLoop:
        mEdge = meshNavigation.find_mirror_edge(geoTransform, edge.indices()[0])
        mLoop.append(mEdge)

# get side
    if eLoop[0].getPoint(0, space='world')[0] > 0:
        #left
        side = "L"
        l_Loop = eLoop
        r_Loop = mLoop
    else:
        #right
        side = "R"
        l_Loop = mLoop
        r_Loop = eLoop
# get center edges
#edge lists are sorted by default, just look for inner edges
    if l_Loop[0].getPoint(0, space='world')[0] < l_Loop[-1].getPoint(0, space='world')[0]:
        l_inner = l_Loop[0]
    else:
        l_inner = l_Loop[-1]

    if r_Loop[0].getPoint(0, space='world')[0] > r_Loop[-1].getPoint(0, space='world')[0]:
        r_inner = r_Loop[0]
    else:
        r_inner = r_Loop[-1]

# center segment
    c_Loop = [pm.PyNode(e) for e in pm.polySelect(edgeLoopPath=(l_inner.indices()[0], r_inner.indices()[0]), ass=True, ns=True)
              if pm.PyNode(e) not in l_Loop and pm.PyNode(e) not in r_Loop]


else:
# single module
    if not side:
        side = "C"

pm.select(c_Loop)

tests()