如何根据公共元素对项目进行排序

71 阅读2分钟

给定一个多边形边列表,需要将所有由顶点连接的边分组。通过编程检测连接,结果是未连接的边数和每个连接的边。

以下是用 Python 编写的示例代码:

import maya.cmds as cmds

# 获取选定的多边形边
looseComponents = cmds.ls(sl=True, fl=True)

# 创建子项查找表
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:
    foundConnectingSet = False  # 标志是否找到连接组件集
    for i in range(len(componentSets)):
        for j in range(len(componentSets[i])):
            for h in range(len(looseComponents)):
                if componentVerts[componentSets[i][j]] & componentVerts[looseComponents[h]]:
                    if looseComponents[h] not in componentSets[i]:
                        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))

2、解决方案

问题是,在代码中,有两处错误:

  • if componentVerts[componentSets[i][j]] & componentVerts[looseComponents[h]]: 一行中,& 运算符不应用于比较集合。应该使用 intersection 方法。

  • if looseComponents[h] not in componentSets[i]: 一行中,判断 looseComponents[h] 是否在 componentSets[i] 中时,应该使用 any 函数。

修改后的代码如下:

import maya.cmds as cmds

# 获取选定的多边形边
looseComponents = cmds.ls(sl=True, fl=True)

# 创建子项查找表
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:
    foundConnectingSet = False  # 标志是否找到连接组件集
    for i in range(len(componentSets)):
        for j in range(len(componentSets[i])):
            for h in range(len(looseComponents)):
                if componentVerts[componentSets[i][j]].intersection(componentVerts[looseComponents[h]]):
                    if any(looseComponents[h] in componentSet for componentSet in componentSets):
                        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))