C#ATIA

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

APIサンプルを我流にかみ砕く2

こちらの続きです。
APIサンプルを我流にかみ砕く1 - C#ATIA

方向性と言いますか、何をテーマにしようかと迷いましたが、"押し出し" "スケッチ"
と行ったので、ソリッド/サーフェスのフィレットをにすることにしました。

サンプルはこちら。
Fusion 360 Help
デフォルトでC++のサンプルが表示されるので、"Python" のタブをクリックして
切り替えてもらうとpythonのサンプルが表示されます。

・・・このサンプル酷いな。前回説明したエントリポイントすら無視されている。
取りあえず、型ヒントを付けrun関数のみに書き換えました。

# Fusion360API Python script

import traceback
import adsk.fusion
import adsk.core

def run(context):
    ui: adsk.core.UserInterface = None
    try:
        # Fusion360取得
        app: adsk.core.Application = adsk.core.Application.get()

        # ユーザーインターフェース取得
        ui = app.userInterface

        # デザイン取得
        design: adsk.fusion.Design = app.activeProduct

        # アクティブなデザインのルートコンポーネントを取得
        root: adsk.fusion.Component = design.rootComponent

        # ユーザーにエッジを選択させる
        selection: adsk.core.Selection = ui.selectEntity(
            "フィレット付けるエッジを選択してください",
            "Edges"
        )
        edge: adsk.fusion.BRepEdge = selection.entity

        # 選択エッジをObjectCollectionに代入
        edgeCollection: adsk.core.ObjectCollection = adsk.core.ObjectCollection.create()
        edgeCollection.add(edge)

        # FilletInputオブジェクトを作成
        fillets: adsk.fusion.FilletFeatures = root.features.filletFeatures
        filletInput: adsk.fusion.FilletFeatureInput = fillets.createInput()

        # 一定Rサイズのフィレットをセット
        filletInput.addConstantRadiusEdgeSet(
            edgeCollection,
            adsk.core.ValueInput.createByString('3 mm'),
            True
        )

        # フィレット作成
        fillet: adsk.fusion.FilletFeature = fillets.add(filletInput)

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

フィレットサイズがインチサイズだったのですが、日本人にはなじみが無いため
3mmにも変更しています。


        # Fusion360取得
        app: adsk.core.Application = adsk.core.Application.get()

        # ユーザーインターフェース取得
        ui = app.userInterface

        # デザイン取得
        design: adsk.fusion.Design = app.activeProduct

        # アクティブなデザインのルートコンポーネントを取得
        root: adsk.fusion.Component = design.rootComponent

今回のサンプルは都合が悪いため、新規のドキュメントを作成しないように
なっているだけで、前回と同じ処理の為、説明は割愛します。


        # ユーザーにエッジを選択させる
        selection: adsk.core.Selection = ui.selectEntity(
            "フィレット付けるエッジを選択してください",
            "Edges"
        )
        edge: adsk.fusion.BRepEdge = selection.entity

この部分ではスクリプトのユーザーにフィレットを作成するエッジを
選択させています。
通常、これを行う為にはダイアログのスクリプトを作成する必要が
あるのですが、非常に手間です。
ユーザー選択を簡単に実装する方法が "UserInterface.selectEntity" メソッド
です。
Fusion 360 Help
引数は、メッセージと選択フィルタです。

このメッセージは、選択可能な要素の上にマウスカーソルを置いた際に表示される
ツールチップです。今回であればエッジ上にマウスカーソルを置いた際に
表示されます。※VSCodeから実行した場合は表示されないかも知れません。

マウスカーソルの含んだがスクショを撮るのが面倒なのでご勘弁。
赤矢印部分にマウスカーソルがあります。

選択フィルタはこちらに一覧があります。
Fusion 360 Help
あまりその様な場面は無いのですが、複数の種類の選択フィルタを使用したい
場面があるかもしれません。
その様な場合は、選択フィルタの文字列を ",(カンマ)" 区切りの文字列にする
ことで可能です。

例えば、エッジと面を許可する選択フィルタにしたいのであればこの様にすると
可能です。

        selection: adsk.core.Selection = ui.selectEntity(
            "フィルタのテストなので面を選択するとエラーになります",
            "Edges,Faces"
        )

又、ドキュメントには記載されていないのですが、SelectionCommandInputオブジェクトの
プロパティには選択フィルタとなる文字列を持っています。
例えば、"Edges" の代わりにこの様な記載でも機能します。

        selection: adsk.core.Selection = ui.selectEntity(
            "フィレット付けるエッジを選択してください",
            adsk.core.SelectionCommandInput.Edges
        )

まぁ好みのレベルの話ではないかな・・・こっちの方が安全なのかな?


selectEntityメソッドの戻り値は、選択した要素そのものでは無く
Selectionオブジェクトです。
Fusion 360 Help
選択した要素を取得したい場合はentityプロパティに含まれています。

今回のサンプルでは利用しませんが、Selectionオブジェクトには
選択した際クリックした位置情報をpointプロパティで持っています。
Fusion 360 Help
前回扱ったPoint3Dオブジェクトですね。

        # 選択エッジをObjectCollectionに代入
        edgeCollection: adsk.core.ObjectCollection = adsk.core.ObjectCollection.create()
        edgeCollection.add(edge)

この部分は後の処理で必要となる為の準備です。
"ObjectCollection" って何?となるのですが、pythonのリストのようなものです。
Fusion 360 Help
これの存在意義がかなり疑問で、過去にフォーラムでも "ObjectCollection不要論"
が出ていたのですが、内部的な都合(C++)で、どうしても必要となるものらしいです。


        # FilletInputオブジェクトを作成
        fillets: adsk.fusion.FilletFeatures = root.features.filletFeatures

ここはフィレットを作成するための準備です。
"filletFeatures" はフィレットフィーチャーの親分です。
"features" はフィーチャーの親分です。
・・・フィーチャーって何? ってなりますよね。

例えば、GUIの履歴をキャプチャしない状態(以下ダイレクトモード)で
フィレットを作成します。
ブラウザツリーにはこんな感じなものが出来ますが、これがfilletFeatureです。

ダイレクトモードに馴染みがないと思うのですが、こちらをダブルクリックすると
Rサイズが変更出来たりします。


念の為、履歴をキャプチャしている(以下パラメトリックモード)場合、
タイムラインではこの様な状態になります。
が、厳密にはこちらはフィレットフィーチャーではありません・・・。

アイコンは同じなんですけどね。


        # 一定Rサイズのフィレットをセット
        filletInput: adsk.fusion.FilletFeatureInput = fillets.createInput()
        filletInput.addConstantRadiusEdgeSet(
            edgeCollection,
            adsk.core.ValueInput.createByString('3 mm'),
            True
        )

"FilletFeatureInput" ですが、こちらはフィレットを作成する為の
詳細な設定を行います。が、実際は後のaddメソッドの引数としてしか利用しない様な
記憶の為、"~FeatureInput" は全て引数の為に用意されているオブジェクトのような
気がしてます。

"addConstantRadiusEdgeSet" メソッドは一定Rサイズのフィレットを作成する為の
メソッドです。
Fusion 360 Help
それぞれの引数をGUIのダイアログで比較すると

赤:edges
緑:radius
青:isTangentChain
です。こうして見ると、APIで行うフィレットはあまり細かな設定出来ないのかも
知れません。(未調査)

        # フィレット作成
        fillet: adsk.fusion.FilletFeature = fillets.add(filletInput)

ここまでの処理は全て画面上には出てきません。
先程作り設定を行った "FilletFeatureInput" を親分のaddメソッド引き渡すと
実際にフィレットが作成されます。

試しに、こちらのaddメソッドの行をコメント化して実行してみて頂ければ
フィレットが作成されない事が分かると思います。


実はこちらのサンプルですが、個人的にはイロイロと問題が有る事を
感じておりますので、次回はその問題点と回避策をご紹介します。