C#ATIA

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

スケッチの円形状パターンをAPIで2

こちらの続きです。
スケッチの円形状パターンをAPIで1 - C#ATIA

前回 "角度の間隔" の操作が分からなかったのですが・・・今もわかりません。
イロイロと都合があり、分からぬまま進めます。日本語で先に書く内容を決めて
おかないと英語での解説が進まぬ。


〇コマンドIDを調べる
まずコマンドIDを調べるのですが、こちらに記載したアドインで行っています。
Command Logger - C#ATIA
GUIで操作しながら表示されるため、劇的に楽です。
(あ~こんなコマンドも呼び出されているんだ と思う時もあります)

スケッチの円形状パターンのコマンドIDは "CircularSketchPatternCommand" です。


〇ダイアログのInputIDを調べる
続いてダイアログのInputIDを調べます。事前選択+コマンド呼び出しては
上手く行かないですからね。
以前、

UI.CurrentCommandInfo

を利用していたのですが、吐き出されるJSONフォーマットが読みにくいので
他サイトのサービスを利用し見やすくなおしていましたが、こちらのコマンドを
発見しました。

Toolkit.cmdDialog 

f:id:kandennti:20201210192139p:plain
遥かに見やすいです。スケッチパレット情報も出力されちゃいますが、
まぁ 見れば何となく察しは付きます。

"UI.CurrentCommandInfo" の場合、細かな情報が取得出来るのですが、今回の場合
"数量" に関しては見つけられませんでした。が、"Toolkit.cmdDialog" の方では
無事出力されています。

肝心のInputIDですが、

オブジェクト -> Geometries
中心点 -> CircularAxis
数量 -> infoCircularGridEntryCount

と言う事が確認出来ました。


〇要素をダイヤログに設定する
事前選択無しで行う方法は、過去にこちらで "ONK" を利用した方法を紹介しました。
テキストコマンド3 - C#ATIA
正直な所、結構面倒です。 もう少しGUIに近い方法を発見しました。

UI.EnableCommandInput <InputID>

こちらを使うと、指定したInputIDにフォーカスを移動させることが出来ます。
(但し、選択用のInputに限ります)
f:id:kandennti:20201210192156p:plain
任意のInputにフォーカスを移動させ、

userInterface.activeSelections.add

で目的の要素を選択させると、Inputに代入した事になります。

        # get selections
        sels :adsk.core.Selections = _ui.activeSelections
        sels.clear()

・・・

        # オブジェクト設定
        _app.executeTextCommand(u'UI.EnableCommandInput {}'.format('Geometries'))
        sels.add(tragetEntity)

・・・直感的だけど、楽かなこれ?
まぁ、"オブジェクト" と "中心点" については、これで解決です。

"数量" に関しては前回解決済みなので、この様な感じです。

        # 数
        _app.executeTextCommand(u'Commands.SetDouble infoCircularGridEntryCount 5')

後は、実行すれば無事円形状パターンが作成されます。
・・・ここまでですら、APIのみでは届かないんですよねぇ。


〇円形状パターンentityIDを探し出す
ここからがメインディッシュの修正です。
上記までで作成された円形状パターンを修正します。
修正する為の手順は、事前選択+修正コマンド呼び出しです。

修正用のコマンドIDは、先程までの手順と同じアドインを使用して行いました。
f:id:kandennti:20201210192309p:plain
コマンドIDは "SketchPatternCircularEdit" ですね。これは問題無いです。

困るのは、"円形状パターン" がAPIのオブジェクトとして提供されていない事にあります。
この子です。
f:id:kandennti:20201210192322p:plain

この様な手順で探し出しました。
f:id:kandennti:20201210192334p:plain

まず、GUIで "円形状パターン" を選択し、テキストコマンドでを取得します。①ですね。

Selections.List 
57:3:12:173:211

(数値はその時によって異なります)
"円形状パターン" のentityIDは "211" です。さらにこれの親entityIDは "173" だとわかります。

とりあえず "211" のプロパティを確認し、"173" を探し出すと "rParentNode" と言うキーで
親entityが取得出来る事が分かりますが、今回は要らないです。②部分ですが、画像で改行を
含んでしまうと言う失態を犯しましたが、再度画像を作るのが面倒な為お許しください。

続いて "173" のプロパティを確認してみます。"interfaceId" は "SKs::Geometry::MSketch"
なので、恐らくこれがスケッチなのだろうと思います(③部分)。

この中から "211" を探し出すと(④部分)、"constraints" キー内にあることが確認出来ます。(⑤部分)
このスケッチ内には "円形状パターン" が1個しか無い為、画像のような表示となっていますが、
"constraints" キーはリストの様で、複数の値が存在出来ます。
ちょっと分かりにくい説明ですかね?

        sels.clear()
        sels.add(skt)

        # スケッチの<paths>取得
        linesep = os.linesep # os別の改行コードを取得
        sktPaths = _app.executeTextCommand(u'Selections.List').rstrip(linesep)

        # スケッチのentityID取得
        oktId = str(sktPaths).split(':')[-1] # 最後の数字がentityID

        # プロパティ取得
        propTxt = neu_server.get_entity_properties(oktId)
        sktProp =  json.loads(json.dumps(propTxt))

        # CircularSketchPattern entityID
        # 但し他のパターンも入る気がするので、本当は"interfaceId"を
        # チェックしたり等が必要なはず。
        circularSketchPatternId = sktProp['constraints'][-1]['entityId']


〇円形状パターンを選択する
ここまで来ると、選択自体は簡単ですね。スケッチのに円形状パターンentityIDを
くっ付け、テキストコマンドのSelections.addでOKです。

        # CircularSketchPattern paths
        circularSketchPatternPaths = sktPaths + ':' + str(circularSketchPatternId)

        # 選択
        sels.clear()
        _app.executeTextCommand(u'Selections.add {}'.format(circularSketchPatternPaths))

〇設定を修正する
後は "SketchPatternCircularEdit" を呼び出すとコマンドダイアログが表示されるので
円形状パターンを作成した時と同様にInputを修正すればOKです。



〇おまとめ
一連の処理をまとめるとこんな感じです。

# Fusion360API Python script
# スケッチの円形状パターンの作成と修正
import adsk.core, adsk.fusion, traceback
import os
import json
import neu_server

_app = adsk.core.Application.cast(None)
_ui = adsk.core.UserInterface.cast(None)

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

        # get active sketch
        skt :adsk.fusion.Sketch = des.activeEditObject
        if not skt:
            return

        # get entity
        tragetEntity :adsk.fusion.SketchEntity = skt.sketchCurves.sketchCircles[0]
        circularAxis :adsk.fusion.SketchPoint = skt.originPoint

        # get selections
        sels :adsk.core.Selections = _ui.activeSelections
        sels.clear()

        # call CircularSketchPatternCommand
        _app.executeTextCommand(u'Commands.Start CircularSketchPatternCommand')

        # オブジェクト設定
        _app.executeTextCommand(u'UI.EnableCommandInput {}'.format('Geometries'))
        sels.add(tragetEntity)

        # 中心点設定
        _app.executeTextCommand(u'UI.EnableCommandInput {}'.format('CircularAxis'))
        sels.add(circularAxis)

        # 数
        _app.executeTextCommand(u'Commands.SetDouble infoCircularGridEntryCount 5')

        # 実行
        _app.executeTextCommand(u'NuCommands.CommitCmd')

        # メッセージ
        _ui.messageBox('円形状パターンを修正するよ!')

        # -- 編集開始 --
        # スケッチ選択
        sels.clear()
        sels.add(skt)

        # スケッチの<paths>取得
        linesep = os.linesep # os別の改行コードを取得
        sktPaths = _app.executeTextCommand(u'Selections.List').rstrip(linesep)

        # スケッチのentityID取得
        oktId = str(sktPaths).split(':')[-1] # 最後の数字がentityID

        # プロパティ取得
        propTxt = neu_server.get_entity_properties(oktId)
        sktProp =  json.loads(json.dumps(propTxt))

        # CircularSketchPattern entityID
        # 但し他のパターンも入る気がするので、本当は"interfaceId"を
        # チェックしたり等が必要なはず。
        circularSketchPatternId = sktProp['constraints'][-1]['entityId']

        # CircularSketchPattern paths
        circularSketchPatternPaths = sktPaths + ':' + str(circularSketchPatternId)

        # 選択
        sels.clear()
        _app.executeTextCommand(u'Selections.add {}'.format(circularSketchPatternPaths))

        # 編集コマンド呼び出し
        _app.executeTextCommand(u'Commands.Start SketchPatternCircularEdit')

        # 数量を変更
        _app.executeTextCommand(u'Commands.SetDouble infoCircularGridEntryCount 7')

        # 実行
        _app.executeTextCommand(u'NuCommands.CommitCmd')

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

f:id:kandennti:20201210192424p:plain

APIのみに比べ、びっくりするぐらい開発に時間がかかるのですが(一向に慣れない)
APIでオブジェクトが提供されていないものでも選択が出来て、APIのみでは作れなかった
ものが作れるようになります。

Fusion360のアドイン開発者にもメリットが大きいはずですし、Fusion360APIとしては
最先端技術のはず。(あくまで個人的な感想です)
・・・英語版の説明、もう1週間ぐらい取り組んでいる。早く終わらせたい。