スケッチコマンド(点)のようにスケッチ座標をゲットしたい。

スケッチコマンド(点)のようにスケッチ座標をゲットしたい。

obatake5TC3R
Advocate Advocate
1,095件の閲覧回数
4件の返信
メッセージ1/5

スケッチコマンド(点)のようにスケッチ座標をゲットしたい。

obatake5TC3R
Advocate
Advocate

APIを用いてスケッチ点のようにスケッチ平面の座標を得たいのですが、APIのドキュメントに見当たりません。

あれば教えてください。

0 件のいいね
解決済み
1,096件の閲覧回数
4件の返信
返信 (4)
メッセージ2/5

kandennti
Mentor
Mentor

@obatake5TC3R さん こんにちは。

 

スケッチ平面の座標” の意味が理解できないのですが、どのような事か

具体的に教えて頂けると、何かヒントが見つかるかもしれません。

 

スケッチ平面自体は、(パラメトリックモードであれば)referencePlaneプロパティで

取得出来ますが、 "座標" と言う意味が・・・。

https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-9d3a3278-3ab3-498d-9a44-ed0d02238296 

メッセージ3/5

obatake5TC3R
Advocate
Advocate

例えばスケッチモードでのコマンド起動[作成]->[点]を起動するとカレントスケッチ座標系上で座標を得ることができますが、このときスケッチグリッドでのスナップ、マウス移動でのポイント、スケッチエンティティのスケッチポイント、線分中点スナップなどできるのですが、これと同じ機能はありませんか?

ui.selectEntity(prompt, filter)ではこのようなことができません。

要するにスケッチのポイントコマンドと同じようなコマンドをAPIで作ろうとすると、スケッチ面上でマウス左クリック位置を得るにはAPIではどうしたらいいかということです。

以上よろしくお願いいたします。

0 件のいいね
メッセージ4/5

kandennti
Mentor
Mentor

@obatake5TC3R さん。

 

こちらの事を考慮すると・・・

https://forums.autodesk.com/t5/fusion-360-ri-ben-yu/suketchikomandode-biao-shisareruyounamausukasoru...

 

動的に、マウスカーソルの位置のスケッチ平面上の座標値を取得すれば

良いのでしょうか? (コメント多めのpythonになってしまいますが)

メッセージ5/5

kandennti
Mentor
Mentor
解決済み

@obatake5TC3R さん。

 

以下のスクリプトをスケッチに入った状態で実行すると、

マウスカーソル位置の座標値をダイアログ上に表示させます。

1.png

 

 

# Fusion360API Python script

import traceback
import adsk.fusion
import adsk.core

_app: adsk.core.Application = None
_ui: adsk.core.UserInterface = None
_handlers = []

# ダイアログ用
_cmdInfo = [
    'MouseCoordinatesDemo',
    'Mouse Coordinates Demo',
    'Mouse Coordinates Demo',
]

# 座標値表示用
_txtIptInfo = [
    'txtIpt',
    '座標',
    '-',
    3,
    True
]

class MyMouseMoveHandler(adsk.core.MouseEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args: adsk.core.MouseEventArgs):
        adsk.core.Application.get().log(args.firingEvent.name)

        # 現在のマウスカーソルポジション
        cursor2D: adsk.core.Point2D = args.viewportPosition

        # ビューポート取得
        vp: adsk.core.Viewport = args.viewport

        # ビュー座標から3D座標に変換
        pos3d: adsk.core.Point3D = vp.viewToModelSpace(cursor2D)

        # 作業中のスケッチ取得
        global _app
        skt: adsk.fusion.Sketch = _app.activeEditObject

        # スケッチ平面のジオメトリ(Plane)取得
        # 但しこの方法だとダイレクトモードではNGだと思います
        refPlane = skt.referencePlane
        plane: adsk.core.Plane = refPlane.geometry

        # カメラからeye-targetのベクトル取得
        # 要は向いている方向を取得
        cam: adsk.core.Camera = vp.camera
        vec: adsk.core.Vector3D = cam.eye.vectorTo(cam.target)

        # マウスカーソルポジション位置を通過しカメラの向きの無限直線を作成
        infiniteLine: adsk.core.InfiniteLine3D = adsk.core.InfiniteLine3D.create(
            pos3d, vec
        )

        # 平面と無限直線の交点取得
        interPnt: adsk.core.Point3D = plane.intersectWithLine(infiniteLine)

        # スケッチ上の座標値に変換
        posSkt: adsk.core.Point3D = skt.modelToSketchSpace(interPnt)

        # 単位変換用の比率を計算
        des: adsk.fusion.Design = _app.activeProduct
        unitMgr: adsk.core.UnitsManager = des.unitsManager
        unitInter = unitMgr.internalUnits
        unitDef = unitMgr.defaultLengthUnits

        ratio: float = unitMgr.convert(1, unitInter, unitDef)

        # ダイアログの座標値を更新
        global _txtIptInfo
        inputs: adsk.core.CommandInputs = args.firingEvent.sender.commandInputs
        txtIpt: adsk.core.TextBoxCommandInput = inputs.itemById(_txtIptInfo[0])

        txtIpt.text = f'X:{posSkt.x * ratio}\nY:{posSkt.y * ratio}\nZ:{posSkt.z * ratio}'


class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args):
        adsk.core.Application.get().log(args.firingEvent.name)
        try:
            global _handlers
            cmd = adsk.core.Command.cast(args.command)
            cmd.isOKButtonVisible = False

            inputs = cmd.commandInputs

            onDestroy = MyCommandDestroyHandler()
            cmd.destroy.add(onDestroy)
            _handlers.append(onDestroy)

            # Mouse Move Event
            # https://help.autodesk.com/view/fusion360/ENU/?guid=GUID-38f68c1a-ac30-4773-adac-db81527aea5d
            onMouseMove = MyMouseMoveHandler()
            cmd.mouseMove.add(onMouseMove)
            _handlers.append(onMouseMove)

            global _txtIptInfo
            inputs.addTextBoxCommandInput(
                _txtIptInfo[0],
                _txtIptInfo[1],
                _txtIptInfo[2],
                _txtIptInfo[3],
                _txtIptInfo[4]
            )

        except:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))


class MyCommandDestroyHandler(adsk.core.CommandEventHandler):
    def __init__(self):
        super().__init__()

    def notify(self, args):
        adsk.core.Application.get().log(args.firingEvent.name)
        adsk.terminate()


def run(context):
    try:
        global _app, _ui
        _app = adsk.core.Application.get()
        _ui = _app.userInterface

        # スケッチ作業中では無い時は、スクリプトを終了する
        actEditObj = _app.activeProduct.activeEditObject
        if actEditObj.objectType != 'adsk::fusion::Sketch':
            _ui.messageBox(
                'スケッチ作業中では無い為、終了します'
            )
            return

        global _cmdInfo
        cmdDef: adsk.core.CommandDefinition = _ui.commandDefinitions.itemById(
            _cmdInfo[0]
        )

        if not cmdDef:
            cmdDef = _ui.commandDefinitions.addButtonDefinition(
                _cmdInfo[0], _cmdInfo[1], _cmdInfo[2]
        )

        global _handlers
        onCommandCreated = MyCommandCreatedHandler()
        cmdDef.commandCreated.add(onCommandCreated)
        _handlers.append(onCommandCreated)

        cmdDef.execute()

        adsk.autoTerminate(False)

    except:
        if _ui:
            _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

まだ試していませんが、ルートコンポーネント上のスケッチでパラメトリックモードで
実行しないと正しい値にならないと思います。
 
単純な説明であれば "MouseMoveイベントを利用して座標値取得してます” なのですが、
座標値の計算が複雑でした。
(MyMouseMoveHandlerクラスのnotifyメソッド以外は大した処理はしてませんので)
 
PCの画面が2Dの為、マウスカーソルの3D座標を求めるためには、どうしても何かに
ぶつかる必要があります。今回は明確に "スケッチ平面" がぶつかる相手と分かっていたので
比較的分かりやすかったです。
(この辺りの説明は3Dゲームを作成しているサイトに説明書きが見つかるかも知れません)
 
 ひょっとしたらもう少し簡単に座標値を求める方法があるかも知れませんが、
ズバリの関数・メソッドは無さそうです。
・・・但し、テキストコマンドを利用すると簡単に取得出来るかも と言う心当たりはあります。