C#ATIA

↑タイトル詐欺 主にFusion360API 偶にCATIA V5 VBA(絶賛ネタ切れ中)

トライアドコマンドインプット

トライアド・・・個人的には覚えられそうにないです。
マニピュレーターのようなインプットです。

使ったことがないです。ちょっと必要な気がしたのですが、
ドキュメントにもサンプルが無い状態なので、必要な状態で
サンプルを作りました。

# Fusion360API Python script

import traceback
import adsk.fusion
import adsk.core

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

_sktCrvIpt: adsk.core.SelectionCommandInput = None
_triadIpt: adsk.core.TriadCommandInput = None

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

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

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

            onExecute = MyExecuteHandler()
            cmd.execute.add(onExecute)
            _handlers.append(onExecute)

            onInputChanged = MyInputChangedHandler()
            cmd.inputChanged.add(onInputChanged)
            _handlers.append(onInputChanged)

            global _sktCrvIpt
            _sktCrvIpt = inputs.addSelectionInput(
                'sktCrvIptId',
                'スケッチ直線',
                'スケッチ直線を選択して!'
            )
            _sktCrvIpt.addSelectionFilter(adsk.core.SelectionCommandInput.SketchLines)

            global _triadIpt
            _triadIpt = inputs.addTriadCommandInput(
                'triadIptId',
                adsk.core.Matrix3D.create()
            )
            _triadIpt.setFullVisibility(False)

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


class MyInputChangedHandler(adsk.core.InputChangedEventHandler):
    def __init__(self):
        super().__init__()

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

        global _sktCrvIpt
        if not args.input == _sktCrvIpt:
            return

        # return
        global _triadIpt
        if _sktCrvIpt.selectionCount > 0:
            # 表示
            mat: adsk.core.Matrix3D = self._get_matrix_by_selection(
                _sktCrvIpt.selection(0),
                _triadIpt.transform
            )
            _triadIpt.transform = mat
            _triadIpt.isXRotationVisible = True
        else:
            # 非表示
            _triadIpt.setFullVisibility(False)

    def _get_vertical_vector(
        self,
        vec: adsk.core.Vector3D,
        refVec: adsk.core.Vector3D)-> adsk.core.Vector3D:

        vecs = [
            refVec,
            adsk.core.Vector3D.create(1,0,0),
            adsk.core.Vector3D.create(0,1,0)
        ]

        v: adsk.core.Vector3D
        for v in vecs:
            if not vec.isParallelTo(v):
                break

        return vec.crossProduct(vec.crossProduct(v))

    def _get_matrix_by_selection(
        self,
        sel: adsk.core.Selection,
        mat: adsk.core.Matrix3D) -> adsk.core.Matrix3D:

        _, _, yAxis, _ = mat.getAsCoordinateSystem()

        line: adsk.core.Line3D = sel.entity.geometry
        xAxis: adsk.core.Vector3D = line.asInfiniteLine().direction
        yAxis: adsk.core.Vector3D = self._get_vertical_vector(xAxis, yAxis)
        zAxis: adsk.core.Vector3D = xAxis.crossProduct(yAxis)

        mat.setWithCoordinateSystem(
            sel.point,
            xAxis,
            yAxis,
            zAxis
        )

        return mat

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

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


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

    def notify(self, args: adsk.core.CommandEventArgs):
        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

        cmdDef: adsk.core.CommandDefinition = _ui.commandDefinitions.itemById(
            'test_cmd'
        )

        if not cmdDef:
            cmdDef = _ui.commandDefinitions.addButtonDefinition(
                'test_cmd',
                'Test',
                'Test'
            )

        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()))

後発のインプットだけあって良く出来ているような気がしました。
が、謎も多かったです。

スクリプトを実行すると、単にSelectionCommandInputが
あるだけです。

スケッチの直線を選択したら、こんな感じです。

CAD画面側に回転用のマニュピレーターが表示されるだけでは
無く、ダイアログ側にも入力項目が表示されます。
本当に、良く出来ています。

謎なのは、選択を止めた際にトライアドコマンドインプットを
非表示にしたいのですが、isVisibleプロパティが効果有るのか?
無いのか?イマイチつかみ切れませんでした。

色々な機能(回転やら移動やら縮尺やら)の表示/非表示は
出来るので、目的は達成出来そうなのですが。

多機能なだけに、サンプル無いのはちょっと辛いかも。(でも便利)