Mayaで反対側のfaceを取得したい2


https://qiita.com/9boz/items/ea25603e51012e70401d

前回　反対側のvtxを取得できるようにしてみましたが、それを流れに入れ込んでみると


- faceを形成するvtxを取得する   
- 反対側にあるvtxを取得する  <- ここを前回  
    - 指定したvexの位置を取得
    - 反対側の位置を取得
    - 反対側の位置のclosestなfaceを取得
    - faceを形成しているvtxを取得
    - 形成しているvtxの中から　反対側の位置に最も近いvtxがそいつだ
- 反対側のvtxが形成するfaceを取得する  
- 全てのvtxが所属しているfaceがそいつだ

faceからvtx取得して、
反対側でfaceからまたvtx取得して、そのvtxからまたface取得してるので
なんかモヤっとしてます。

モヤっとしてるが実装
--




```python
import maya.cmds as cmds
import maya.api.OpenMaya as om

def getPosition(target):
    nodeType = cmds.nodeType(target)
    
    if nodeType == "joint" or nodeType == "transform" or nodeType == "ikHandle" or nodeType == "place3dTexture":
        return cmds.xform(target , q =True , ws = True, rotatePivot =True)

    elif nodeType == "mesh" or nodeType == "nurbsCurve" or nodeType == "nurbsSurface" or nodeType == "lattice":
        return cmds.xform(target , q =True , ws = True, t =True)

def getDagNode(target):    
    try:
        sellist = om.MGlobal.getSelectionListByName(target)
        return sellist.getDagPath(0)
    except:
        return None

def mirrorMatrix(source,pivot,mirrorAxis):        

    nodeType = cmds.nodeType(source)
    
    if nodeType == "joint" or nodeType == "transform" or nodeType == "ikHandle" or nodeType == "place3dTexture":
        curMatrix = om.MMatrix(cmds.xform(source , q =True , ws = True, matrix =True))
    elif nodeType == "mesh" or nodeType == "nurbsCurve" or nodeType == "nurbsSurface" or nodeType == "lattice":
        position = getPosition(source)
        curMatrix = om.MTransformationMatrix(om.MMatrix.kIdentity).setTranslation(om.MVector(position),om.MSpace.kWorld).asMatrix()
    
    if mirrorAxis == "x":
        mirrorScale = [-1.0,1.0,1.0]
    elif mirrorAxis == "y":
        mirrorScale = [1.0,-1.0,1.0]
    elif mirrorAxis == "z":
        mirrorScale = [1.0,1.0,-1.0]

    mirrorScaleMatrix = om.MTransformationMatrix(om.MMatrix.kIdentity).setScale(mirrorScale,om.MSpace.kWorld).asMatrix()

    if pivot == "world" or pivot == None:
        pivotMatrix = om.MMatrix.kIdentity
    else:
        pivotMatrix = om.MMatrix(cmds.xform(pivot , q =True , ws = True, matrix =True))
    
    pivotMatrix_inverse = pivotMatrix.inverse()
    dist_matrix = curMatrix * pivotMatrix_inverse * mirrorScaleMatrix * pivotMatrix

    dist_matrix = om.MTransformationMatrix(dist_matrix).setScale([1.0,1.0,1.0],om.MSpace.kWorld).asMatrix()    
    dist_matrix = om.MTransformationMatrix(dist_matrix).setScale([-1.0,-1.0,-1.0],om.MSpace.kObject).asMatrix()    
    dist_matrix = om.MTransformationMatrix(dist_matrix).setScale([1.0,1.0,1.0],om.MSpace.kWorld).asMatrix()    
    dist_matrix = om.MTransformationMatrix(dist_matrix).setShear([0.0,0.0,0.0],om.MSpace.kWorld).asMatrix()

    return dist_matrix

def getMirrorPosition(source,pivot,mirrorAxis):
    setMatrix = mirrorMatrix(source,pivot,mirrorAxis)
    mirrorPosition = om.MTransformationMatrix(setMatrix).translation(om.MSpace.kWorld)    
    return mirrorPosition
    
def getMirrorPosition(source,pivot,mirrorAxis):
    setMatrix = mirrorMatrix(source,pivot,mirrorAxis)
    mirrorPosition = om.MTransformationMatrix(setMatrix).translation(om.MSpace.kWorld)    
    return mirrorPosition

def getOtherSideVtx(sourceVtxID,tagetMesh,pivot = "world",mirrorAxis = "x"):    
    mirrorPosition = getMirrorPosition(tagetMesh + ".vtx["+str(sourceVtxID)+"]",pivot,mirrorAxis)       
    mirrorPositionVector = om.MVector(mirrorPosition)

    meshDagPath = getDagNode(tagetMesh)
    shapeFn = om.MFnMesh(meshDagPath)
    
    space =  om.MSpace.kWorld    
    otherSidePoint,faceID = shapeFn.getClosestPoint(om.MPoint(mirrorPosition),space)

    faceIterator = om.MItMeshPolygon(meshDagPath)
    faceIterator.setIndex(faceID)
    vtxIDs = faceIterator.getVertices()
    faceVtxPositions = faceIterator.getPoints(om.MSpace.kWorld)

    minlength = None
    targetVtxID = None
    for faceVtxPosition,vtxID in zip(faceVtxPositions,vtxIDs):
        targetVector = om.MVector(faceVtxPosition)        
        length = (mirrorPositionVector - targetVector).length()
        
        if minlength == None:
            minlength = length
            targetVtxID = vtxID
        elif minlength > length:
            minlength = length
            targetVtxID = vtxID
            
    return targetVtxID

##ここから追加--------------------
def getOtherSideFace(sourceFaceID,tagetMesh,pivot = "world",mirrorAxis = "x"):    
    meshDagPath = getDagNode(tagetMesh)
    faceIterator = om.MItMeshPolygon(meshDagPath)
    faceIterator.setIndex(sourceFaceID)
    vtxIDs = faceIterator.getVertices()
    mirrorFaceIDs = []
    VtxIterator = om.MItMeshVertex(meshDagPath)
    
    for vtxID in vtxIDs:
        mirrorVtxID = getOtherSideVtx(vtxID,tagetMesh,pivot,mirrorAxis)                
        VtxIterator.setIndex(mirrorVtxID)
        connectedFaceID = VtxIterator.getConnectedFaces()        
        if len(mirrorFaceIDs) == 0:
            mirrorFaceIDs = connectedFaceID
        else:
            mirrorFaceIDs = list(set(mirrorFaceIDs) & set(connectedFaceID))
                
    return mirrorFaceIDs
```

（あれ、追加分意外に短かったぞ）

とりあえずテストしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/ec0b3ef4-d2fb-0f12-9509-ac40bdcee3e3.png)

こんなシーンでやってみます。

```python
ids = getOtherSideFace(236,"pSphere1",pivot = "world",mirrorAxis = "x")
    
for id in ids:
    cmds.select("pSphere1.f["+str(id)+"]",add =True)
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/2682c3c6-0484-d4fa-d14c-4c24d0f89dad.png)

を。いけましたね。

折角なので、使用方法を考える
--

あっさりできてしまったので、実際の運用例を。
自分の作業時に、faceに直接マテリアルをアサインすることがあります。

その際、右半分やったけど左半分にマテリアルコピーしたいなーとかそういうときにつかいます。

例えばこんな感じで半分にマテリアルをアサインし、反対側も同じようにしたいなぁと言うときに

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/ea35192a-07cb-2779-262b-00ca1b34a120.png)

SGのアサイン情報からfaceだけ引っ張り出して、反対側を取得してアサインという感じですね。

```python
assignItems = cmds.sets("lambert2SG",q=True)
assignItems = cmds.ls(assignItems,fl=True)

for assignItem in assignItems:   
    if "f[" in assignItem:        
        faceID = assignItem.split("[")[-1].replace("]","")
        targetMesh = assignItem.split(".")[0] 

        ids = getOtherSideFace(int(faceID),targetMesh,pivot = "world",mirrorAxis = "x")
    
        for id in ids:
            cmds.sets(targetMesh + ".f["+str(id)+"]",e =True,forceElement = "lambert2SG")
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/900b3850-e075-8153-d982-e034f0d5f4fe.png)


もう少し調整するなら、例えば　左から右にの様に方向を指定できるようにすると良さそうです。