2018年6月3日日曜日

選択したエッジを延長した先の交点を求める

選択したエッジを延長し、その交点で頂点をマージしたいという要望が会社でありました。
ベクトルを使えば簡単に解決できそうな感じがしましたが、気になったので調査してみました。
以下ソース
import maya.cmds as mc
import maya.api.OpenMaya as om2
def getVectorValue(pointA=[0.0,0.0,0.0],pointB=[0.0,0.0,0.0]):
tmpVecA = om2.MVector(pointA)
tmpVecB = om2.MVector(pointB)
return tmpVecB-tmpVecA
def getCrossPoint2Edge(vtxNamePist=[[]]):
result=[]
edgeVecAB = om2.MVector()
edgeVecCD = om2.MVector()
edgeVecAC = om2.MVector()
vtxList=[]
vtxList.append([mc.pointPosition(vtx,w=True) for vtx in vtxNamePist[0]])
vtxList.append([mc.pointPosition(vtx,w=True) for vtx in vtxNamePist[1]])
edgeVecAB = getVectorValue(vtxList[0][0],vtxList[0][1])
edgeVecCD = getVectorValue(vtxList[1][0],vtxList[1][1])
edgeVecAC = getVectorValue(vtxList[0][0],vtxList[1][0])
nAB = edgeVecAB.normal()
nCD = edgeVecCD.normal()
work1 = nAB*nCD;
work2 = 1 - work1*work1;
if work2==0.0:
mc.warning('2 edge is Concurrent')
return 0
d1 = ((edgeVecAC*nAB)-work1*(edgeVecAC*nCD))/ work2
d2 = (work1*(edgeVecAC*nAB)-(edgeVecAC*nCD))/ work2
result.append([vtxList[0][0][0]+d1*nAB.x,
vtxList[0][0][1]+d1*nAB.y,
vtxList[0][0][2]+d1*nAB.z])
result.append([vtxList[1][0][0]+d2*nCD.x,
vtxList[1][0][1]+d2*nCD.y,
vtxList[1][0][2]+d2*nCD.z])
return result
def connect2Edge(Threshold=0.001):
nodeList = mc.ls(sl=True,fl=True)
edgeList = mc.polyListComponentConversion(nodeList,te=True)
edgeList = mc.ls(edgeList,fl=True)
vtxList = []
vtxList.extend([mc.ls(mc.polyListComponentConversion(edgeList[0],tv=True),fl=True)])
vtxList.extend([mc.ls(mc.polyListComponentConversion(edgeList[1],tv=True),fl=True)])
print vtxList
crossPoints = getCrossPoint2Edge(vtxList)
crossPointA = om2.MVector(crossPoints[0])
crossPointB = om2.MVector(crossPoints[1])
rezPoint = crossPointA - crossPointB
if rezPoint.length()>Threshold:
mc.warning('Cannot Cross.')
return -1
editPoints = []
for points in vtxList:
vec1 = om2.MVector(mc.pointPosition(points[0],w=True))
vec2 = om2.MVector(mc.pointPosition(points[1],w=True))
chk1 = crossPointA-vec1
chk2 = crossPointA-vec2
if chk1.length()<chk2.length():
editPoints.append(points[0])
else:
editPoints.append(points[1])
editPoints=list(set(editPoints))
print editPoints
if len(editPoints)<2:
mc.warning('Already connect edges.')
return 0
for vtx in editPoints:
mc.move(crossPoints[0][0],crossPoints[0][1],crossPoints[0][2],vtx,ws=True,wd=True)
return 1
connect2Edge()
view raw connectEdge hosted with ❤ by GitHub
コードと考え方は以下を参考にしました。 http://www.sousakuba.com/Programming/gs_two_lines_intersect.html 
大変わかりやすく解説されています。 

このソースでは、選択したエッジの交点を求め、近いほうの頂点をその座標へ移動するまでとなっていますが、処理の根幹としては十分かと。

うん、やっぱベクトルってべんりだなーと…。