こちらの続きです。
マウスカーソルの座標値を取得する2 - C#ATIA
前回はマウスカーソルの3D位置は正しい値が取得できていませんでしたが、
今回は正しい値が取得出来ているはずです。
#FusionAPI_python #Author-kantoku #Description-MouseMoveTest ver0.0.3 import adsk.core, adsk.fusion, traceback _ui = None _handlers = [] _faces = [] _covunit = 0 #このコマンドのイベント・ダイアログ作成 class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler): def __init__(self): super().__init__() def notify(self, args): try: global _handlers cmd = adsk.core.Command.cast(args.command) onDestroy = MyCommandDestroyHandler() cmd.destroy.add(onDestroy) _handlers.append(onDestroy) onMouseMove = MyMouseMoveHandler() cmd.mouseMove.add(onMouseMove) _handlers.append(onMouseMove) inputs = cmd.commandInputs inputs.addTextBoxCommandInput('Vp_Pos', 'Fusion360画面上の座標値', '-', 1, True) inputs.addTextBoxCommandInput('Sc_Pos', 'ディスプレイ上の座標値', '-', 1, True) inputs.addTextBoxCommandInput('3D_Pos', 'マウス3D仮座標値', '-', 1, True) inputs.addTextBoxCommandInput('Cam_Vec', 'カメラ向き(単位ベクトル)', '-', 1, True) inputs.addTextBoxCommandInput('Hit', 'マウス3D座標値', 'Non!', 1, True) except: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) #このコマンドの破棄 class MyCommandDestroyHandler(adsk.core.CommandEventHandler): def __init__(self): super().__init__() def notify(self, args): try: adsk.terminate() except: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) #MouseMoveイベント class MyMouseMoveHandler(adsk.core.MouseEventHandler): def __init__(self): super().__init__() def notify(self, args): eventArgs = adsk.core.MouseEventArgs.cast(args) cmd = eventArgs.firingEvent.sender inputs = cmd.commandInputs #ビューポイント vp = eventArgs.viewport #Fusion360画面上の座標値 vppos = eventArgs.viewportPosition ui_vp = inputs.itemById('Vp_Pos') ui_vp.text = 'x:[%d] y:[%d]'%(vppos.x, vppos.y) #ディスプレイ上の座標値 scrpos = vp.viewToScreen(vppos) ui_sc = inputs.itemById('Sc_Pos') ui_sc.text = 'x:[%d] y:[%d]'%(scrpos.x, scrpos.y) #マウス3D仮座標値-奥行きがNGな為正しくない(通過点) d3pos = vp.viewToModelSpace(vppos) d3_sc = inputs.itemById('3D_Pos') d3_sc.text = 'x:{:.3f} y:{:.3f} z:{:.3f}'.format( d3pos.x * _covunit, d3pos.y * _covunit, d3pos.z * _covunit) #カメラ向き(単位ベクトル) cam = vp.camera vec = cam.eye.vectorTo(cam.target) vec.normalize() vec_sc = inputs.itemById('Cam_Vec') vec_sc.text = 'x:{:.3f} y:{:.3f} z:{:.3f}'.format(vec.x, vec.y, vec.z) #マウス3D座標値 hit_sc = inputs.itemById('Hit') onface = OnFace(vp, eventArgs.viewportPosition) if onface == None: hit_sc.text = 'Non!' else: hit_sc.text = 'x:{:.3f} y:{:.3f} z:{:.3f}'.format( onface[1].x * _covunit, onface[1].y * _covunit, onface[1].z * _covunit) #マウスカーソルの3D取得 def OnFace(vp, vp_pos): d3pos = vp.viewToModelSpace(vp_pos) cam = vp.camera vec = cam.eye.vectorTo(cam.target) pnt = adsk.core.Point3D.create( d3pos.x + vec.x, d3pos.y + vec.y, d3pos.z + vec.z) mouse3d = adsk.core.Line3D.create(d3pos, pnt).asInfiniteLine() ints = [(face, mouse3d.intersectWithSurface(geo)) for (face, geo) in _faces if mouse3d.intersectWithSurface(geo).count > 0] ints = [(face, p) for (face, pnts) in ints for p in pnts] ints = [(face, p, face.evaluator.getParameterAtPoint(p)) for (face, p) in ints] ints = [(face, p, prm) for (face, p, (res, prm)) in ints if res] ints = [(face, p, prm) for (face, p, prm) in ints] ints = [(face, p, cam.eye.distanceTo(p)) for (face, p, prm) in ints if face.evaluator.isParameterOnFace(prm)] if len(ints) < 1: return None return min(ints, key = (lambda x: x[2])) def run(context): try: app = adsk.core.Application.get() _ui = app.userInterface cmdDef = _ui.commandDefinitions.itemById('Mouse_Move_Test') if not cmdDef: cmdDef = _ui.commandDefinitions.addButtonDefinition( 'Mouse_Move_Test', 'Mouse_Move_Test', 'Mouse_Move_Test') onCommandCreated = MyCommandCreatedHandler() cmdDef.commandCreated.add(onCommandCreated) _handlers.append(onCommandCreated) des = adsk.fusion.Design.cast(app.activeProduct) #全サーフェス取得 global _faces _faces = [(face, face.geometry) for comp in des.allComponents if comp.isBodiesFolderLightBulbOn for bBody in comp.bRepBodies if bBody.isLightBulbOn & bBody.isVisible for face in bBody.faces] #単位準備 global _covunit unitsMgr = des.unitsManager defLenUnit = unitsMgr.defaultLengthUnits _covunit = unitsMgr.convert(1, unitsMgr.internalUnits, defLenUnit) cmdDef.execute() adsk.autoTerminate(False) except: if _ui: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
コードが汚い。特にOnFace関数。
スプリクト実行後、ダイアログが出ますが一番下の項目が正確であろう3D座標値です。
マウスカーソルが面の上に無い時は "Non!" と表示されています。
確認しやすそうな数値でBodyを作り、マウスを動かし
確認してみました。
動画の最後の方ですが、スプリクトを中止しマウスを動かしているのですが
(要は何のコマンドにも入っていない状態です)、マウスカーソル下の
面がハイライト状態になります。(スプリクトではなりません)
・・・と言うことはFusion360自体でどの面の上にマウスカーソルが
認識しているのではないかな? と感じているのですが・・・。
現状、ファイル内の全ての面との交差を取得し、複数交差した点と
カメラとの距離を測定し、最短となった点の座標値を取得し表示させています。
効率が非常に悪いんです。どうしたらこの面を取得できるのだろう???