2013-07-14 4 views
0

Название немного абстрагировано, но я думаю, что это точно то, что я ищу. В частности, с учетом списка краев многоугольника группируйте все ребра, связанные вершиной.Сортировка предметов по общим элементам

Я знаю, что это должна быть простая проблема, но я продолжаю находить неправильное решение.

Пример ввода:

looseComponents = cmds.ls(sl=True, fl=True) 
# Result: [u'pCube1.e[3]', u'pCube1.e[6]'] # 

Получение выход:

found 2 component sets 
[u'pCube1.e[3]'] 
[u'pCube1.e[3]'] 

Ожидаемое Ouput:

found 2 component sets 
[u'pCube1.e[3]'] 
[u'pCube1.e[6]'] 

Это то, что у меня есть на данный момент, это работает в Maya, написанный в Python.

looseComponents = cmds.ls(sl=True, fl=True) 

#build sub item lookup 
componentVerts = {} 
for component in looseComponents: 
    verts = cmds.ls(cmds.polyListComponentConversion(component, toVertex=True), fl=True) 
    vertIds = [] 
    for vert in verts: 
     i = int(vert.split('[')[-1].strip(']')) 
     vertIds.append(i) 
    componentVerts[component] = set(vertIds) 

sortedComponents = 0 
totalComponents = len(looseComponents) 
componentSets = [ [] ] 
componentSets[0].append(looseComponents[0]) 
sortedComponents += 1 

while sortedComponents < totalComponents: 
    # for each subSetA of setA 
    foundConnectingSet = False 
    for i in range(len(componentSets)): 
     # for each itemA of subSetA 
     for j in range(len(componentSets[i])): 
      # for each itemB of setB 
      for h in range(len(looseComponents)): 
       # check if itemA and itemB share a sub item 
       if componentVerts[componentSets[i][j]] & componentVerts[looseComponents[h]]: 
        # if itemB isn't already part of this subSetA 
        if looseComponents[h] not in componentSets[i]: 
         # add itemB to this subSetA 
         componentSets[i].append(looseComponents[h]) 
         sortedComponents += 1 
         foundConnectingSet = True 

    if not foundConnectingSet: 
     starter = looseComponents[0] 
     for i in range(len(componentSets)): 
      looseComponents = list(set(looseComponents) - set(componentSets[i])) 
     componentSets.append([ starter ])   
     sortedComponents += 1 

print 'found ' +str(len(componentSets))+ ' component sets' 
for componentSet in componentSets: 
    cmds.confirmDialog() 
    cmds.select(componentSet, replace=True) 
    print cmds.ls(sl=True) 

С одним выбранным краем я получаю один комплект. При выборе двух несвязанных краев я получаю два набора, но оба набора имеют одинаковое ребро.

+0

Обратите внимание, что при дои ng 'для i в диапазоне (len (foo))', вы также можете сделать 'для i, _ в перечислении (foo)'. – Amber

+0

Как это «сортировка»? Я думаю, что правильнее сказать, что вы классифицируете полигоны. Кроме того, без вывода, который вы получаете, и ожидаемого результата, который вы хотели бы получить, трудно понять, что именно вы хотите. – Bakuriu

+0

true, редактирование сообщения для добавления ввода, вывода и ожидаемого вывода. –

ответ

0

Хорошо, у меня есть одно решение для работы последовательно.

looseComponents = cmds.ls(sl=True, fl=True) 

totalComponents = len(looseComponents) 
sortedComponents = 0  
componentSets = [] 

vertComponent = {} 
componentVert = {} 
for component in looseComponents: 
    verts = cmds.ls(cmds.polyListComponentConversion(component, toVertex=True), fl=True) 
    for vert in verts: 
     if vert in vertComponent: 
      vertComponent[vert].append(component) 
     else: 
      vertComponent[vert] = [component] 
    componentVert[component] = verts 

def getConnectedComponent(component): 
    verts = componentVert[component] 
    connections = [] 
    for vert in verts: 
     connections.extend(vertComponent[vert]) 
    return list(set(connections) - set([component])) 

def getRemainingComponent(): 
    remainingComponents = looseComponents 
    for componentSet in componentSets: 
     remainingComponents = list(set(remainingComponents)-set(componentSet)) 
    if remainingComponents: 
     return remainingComponents[0] 
    else: 
     return None 

while sortedComponents < totalComponents: 
    component = getRemainingComponent() 
    if component: 
     componentSets.append([component]) 
     sortedComponents += 1 
    connections = getConnectedComponent(component) 
    while set(connections) - set(componentSets[-1]): 
     newConnections = list(set(connections) - set(componentSets[-1])) 
     componentSets[-1].extend(newConnections) 
     sortedComponents += len(newConnections) 
     connections = [] 
     for component in newConnections: 
      connections.extend(getConnectedComponent(component)) 

print 'found ' +str(len(componentSets))+ ' component sets' 
for componentSet in componentSets: 
    cmds.confirmDialog() 
    cmds.select(componentSet, replace=True) 
    print cmds.ls(sl=True) 
0

Я знаю, что, как правило, арфа pymel здесь совсем немного, но это просто так больно смотреть все идут через хлопот CMDS. Если вы не обязаны им, то альтернатива будет такой:

from pymel.core import * 

verts = [i for i in polyCube()[0].vtx] 

for j in verts: 
    print "{0} is connected to {1}".format(j, j.connectedEdges()) 

Это гораздо более жидкий, когда это объектно ориентированный.

0

я бы просто попробовать это сделать словарь из всех Verts преобразованных к краям:

import maya.cmds as cmds 

def vert_edge_map(obj): 
    verts = cmds.polyEvaluate(obj, v=True) 
    mapping = {} 
    for r in range(0, verts): 
     edges = cmds.polyListComponentConversion(obj + ".vtx[%i]" % r, fv=True, te=True) 
     edges = cmds.filterExpand(edges, sm=32) 
     mapping[r] = set(edges) 
    return mapping 

vert_edge_map('pCube1') 
# Result: {0: set([u'pCube1.e[4]', u'pCube1.e[0]', u'pCube1.e[10]']), 1: set([u'pCube1.e[0]', u'pCube1.e[11]', u'pCube1.e[5]']), 2: set([u'pCube1.e[4]', u'pCube1.e[1]', u'pCube1.e[6]']), 3: set([u'pCube1.e[1]', u'pCube1.e[7]', u'pCube1.e[5]']), 4: set([u'pCube1.e[2]', u'pCube1.e[8]', u'pCube1.e[6]']), 5: set([u'pCube1.e[2]', u'pCube1.e[9]', u'pCube1.e[7]']), 6: set([u'pCube1.e[3]', u'pCube1.e[8]', u'pCube1.e[10]']), 7: set([u'pCube1.e[3]', u'pCube1.e[9]', u'pCube1.e[11]'])} # 

Все значения являются наборы, так что вы можете проверить, чтобы увидеть, если два Verts соединены в пересекающейся наборы этих двух Vert в:

def are_connected(v1, v2, mapping): 
    return len(mapping[v1].intersection(mapping[v2])) > 0 

и создать островки связного материала с союзами:

def lots_of_edges(mapping, *verts): 
    result = set() 
    for v in verts: 
     result = result.union(mapping[v]) 
    return result 
Смежные вопросы