以前のものは選択したポリゴン面の法泉を基準(これは少し怪しい)に平面化してましたが
今回はスクリプトを実行するとポイントをピックさせられます。
3点ピックするとそれを元に平面化します。
相変わらず4つ以上の面に接したポイントがあるとダメです。
いやぁ使えない使えない。。。
from win32com.client import * xsi = Application def GetReferencePoints(): ''' リファレンスポイントを取得(最低3点) ''' xsi.ActivateVertexSelTool() lPnts = [] while len(lPnts) < 3: rtn = xsi.PickElement(constants.siPointFilter) oPick = rtn[2] if not oPick: #ピックが足りない場合処理中止 return for oCmp in oPick.SubComponent.ComponentCollection: lPnts.append(oCmp) return lPnts def GetReferenceTransform(lPnts): ''' リファレンストランスフォームを取得 ''' #外積を取得 v1 = XSIMath.CreateVector3() v2 = XSIMath.CreateVector3() vCrs = XSIMath.CreateVector3() v1.Sub(lPnts[1].Position, lPnts[0].Position) v2.Sub(lPnts[2].Position, lPnts[0].Position) vCrs.Cross(v1, v2) #トランスフォームに変換(後でレイキャストさせるために位置をどのポイントとも違う位置(ポイントの中点)に) vPos = XSIMath.CreateVector3() for i in range(3): vPos.AddInPlace(lPnts[i].Position) vPos.ScaleInPlace(1.0/len(lPnts)) vYAxis = XSIMath.CreateVector3(0,1,0) oTrans = XSIMath.CreateTransform() oTrans.Translation = vPos nAgl = vYAxis.Angle(vCrs) vCrs.Cross(vCrs, vYAxis) vCrs.NegateInPlace() oTrans.SetRotationFromAxisAngle(vCrs, nAgl) return oTrans def MovePointToReferenceTransform(oFace, oItemTrans, oRefTrans, oAllPnts): ''' ポイントをリファレンストランスフォーム上のY=0に移動 ''' lPosArr = [list(t) for t in oAllPnts.PositionArray] for oPnt in oFace.Points: vPosOnRef = XSIMath.MapObjectPositionToObjectSpace(oItemTrans, oRefTrans, oPnt.Position) vPosOnRef.Y = 0 vPosOnRef.ScaleInPlace(10) vPos = XSIMath.MapObjectPositionToObjectSpace(oRefTrans, oItemTrans, vPosOnRef) lPosArr[0][oPnt.Index] = vPos.X lPosArr[1][oPnt.Index] = vPos.Y lPosArr[2][oPnt.Index] = vPos.Z oAllPnts.PositionArray = lPosArr def GetEdgeInfo(oFace): ''' エッジ情報を取得 ''' def GetInfo(oEdge, lPntIndxsOnFace): oPnts = oEdge.Points if oPnts[0].Index in lPntIndxsOnFace: oStartPnt = oPnts[1] oEndPnt = oPnts[0] else: oStartPnt = oPnts[0] oEndPnt = oPnts[1] vStart = oStartPnt.Position vEnd = oEndPnt.Position vEnd.SubInPlace(vStart) vStart.SubInPlace(vEnd) return vStart, vEnd, oEndPnt.Index oNgbrEdges = oFace.Edges.NeighborEdges() lPntIndxsOnFace = [oPnt.Index for oPnt in oFace.Points] lPos = [] #開始位置リスト lAxis = [] #方向リスト lPntIdx = [] #対象ポイントインデックスリスト for oEdge in oNgbrEdges: lInfo = GetInfo(oEdge, lPntIndxsOnFace) lPos.extend(lInfo[0].Get2()) lAxis.extend(lInfo[1].Get2()) lPntIdx.append(lInfo[2]) return lPos, lAxis, lPntIdx def MovePointToRaycastPosition(oGeom, oFace, lEdgeInfo): ''' ポイントをレイキャストした先に移動 ''' oGeom.SetupPointLocatorQueries(3, None, [oFace.Index], -1) oPntLocations = oGeom.GetRaycastIntersections(lEdgeInfo[0], lEdgeInfo[1], 0) lPos = oGeom.EvaluatePositions(oPntLocations) oPnts = oGeom.Points lPosArr = [list(t) for t in oPnts.PositionArray] for idx, allidx in enumerate(lEdgeInfo[2]): lPosArr[0][allidx] = lPos[0][idx] lPosArr[1][allidx] = lPos[1][idx] lPosArr[2][allidx] = lPos[2][idx] oPnts.PositionArray = lPosArr def main(): oSel = xsi.Selection(0) if oSel.Type != 'polySubComponent': #ポリゴンが選択されてない場合処理中止 return #選択ポリゴンのサブコンポーネントからいろいろ取得 oSubCmp = oSel.SubComponent oFace = oSubCmp.ComponentCollection[0] oPoly = oFace.Nodes[0] oItem = oSubCmp.Parent3DObject xsi.FreezeModeling(oItem) #フリーズしとかないとポイントの移動ができない oItemTrans = oItem.Kinematics.Global.Transform oGeom = oItem.ActivePrimitive.Geometry oAllPnts = oGeom.Points lPosArr = [list(t) for t in oAllPnts.PositionArray] oAllPnts.PositionArray = lPosArr #一旦ポイントをいじっとくことで初回実行からちゃんと動く(なぞ) lEdgeInfo = GetEdgeInfo(oFace) #エッジ情報を保存 lPnts = GetReferencePoints() #参照トランスフォーム作成用ポイントをピックさせる(最低3点) if not lPnts: return oRefTrans = GetReferenceTransform(lPnts) #参照トランスフォームを作成 MovePointToReferenceTransform(oFace, oItemTrans, oRefTrans, oAllPnts) #とりあえず平面化 MovePointToRaycastPosition(oGeom, oFace, lEdgeInfo) #できた面と保存しておいてエッジをレイキャストして補正 xsi.ActivateRaycastPolySelTool() main()
0 件のコメント:
コメントを投稿