C#ATIA

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

NativeObjectとProxyの理解とモロモロ4

こちらの続きです。
NativeObjectとProxyの理解とモロモロ3 - C#ATIA

前回は、タイトルとしていたNativeObjectとProxyが登場し、大体解決しました。
あくまで大体なので、解決しない事例が出てきます。

早速ですが、前回のGUIコンポーネント(正しくはオカレンス)内にコンポーネント
さらに作ります。(コンポーネント2:1)
ルートコンポーネントから見ると、孫世代のコンポーネントとなります。
これを便利上、"孫コンポーネント" と呼ぶことにします。

この孫コンポーネント内に、孫コンポーネントのXY平面をサポートとしたスケッチ作成します。
f:id:kandennti:20201129213015p:plain
スケッチ内では前回同等、原点を中心とした円を作成します。

続いて、"コンポーネント1:1" 内の孫コンポーネントを移動します。
"位置をキャプチャ" 忘れず行ってください。
f:id:kandennti:20201129213028p:plain
これも移動量は X 10mm Y 20mm Z 30mm としておきましょう。
ルートコンポーネントから見た場合、 X 20mm Y 40mm Z 60mm となっています。
f:id:kandennti:20201129213041p:plain

これを前回のコードを修正し、孫コンポーネントのスケッチ円の中心座標を取得出来るようにします。

# Fusion360API Python script
# sample4
import adsk.core, adsk.fusion, traceback

def run(context):
    ui = None
    try:
        # おまじない
        app :adsk.core.Application = adsk.core.Application.get()
        ui :adsk.core.UserInterface = app.userInterface
        des :adsk.fusion.Design = app.activeDocument.design

        # ルートコンポーネント
        root :adsk.fusion.Component = des.rootComponent

        # 孫コンポーネント(正しくはオカレンス)取得
        occs :adsk.fusion.Occurrences = root.allOccurrences
        occ :adsk.fusion.Occurrence = occs.itemByName('コンポーネント2:1')

        # オカレンスのコンポーネント
        # オカレンスにはスケッチが無く、参照元のコンポーネントに有り
        comp :adsk.fusion.Component = occ.component

        # コンポーネント内の1個目のスケッチ
        skt :adsk.fusion.Sketch = comp.sketches[0]

        # proxyとして取得
        skt_proxy :adsk.fusion.Sketch = skt.createForAssemblyContext(occ)

        # スケッチ内の1個目の円 - 目的の円
        curvrs :adsk.fusion.SketchCurves = skt_proxy.sketchCurves
        circle :adsk.fusion.SketchCircle = curvrs.sketchCircles[0]

        # SketchCircleには中心点情報が無いので、geometryを取得
        geo :adsk.core.Circle3D = circle.worldGeometry

        # 単位を正しくしたい為、係数取得
        unitsMgr :adsk.core.UnitsManager = des.unitsManager
        defLenUnit :str = unitsMgr.defaultLengthUnits
        covunit :float = unitsMgr.convert(1, unitsMgr.internalUnits, defLenUnit)

        # 中心座標表示
        ctr :adsk.core.Point3D = geo.center
        ui.messageBox('X: {1}{0}\nY: {2}{0}\nZ: {3}{0}'.format(
            defLenUnit, ctr.x * covunit, ctr.y * covunit, ctr.z * covunit))

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

結果はこちら
f:id:kandennti:20201129213057p:plain
あぁ予定外。正しく取得出来ました。
ん~そうか、選択じゃないからか・・・。


コンポーネントを作りましたが、実はルートコンポーネント直下にはコピペした
GUIコンポーネント(便利上、子コンポーネントと呼びます)にも出来ています。
f:id:kandennti:20201129213110p:plain
しかも運の悪い事に同一のオカレンス名と言う扱いの悪さ・・・。
座標値を測定すると X 20mm Y 30mm Z 40mm です。
f:id:kandennti:20201129213123p:plain
確かに先程移動したのは "コンポーネント1:1" の孫コンポーネントだけだったためです。
個人的には、これちょっと納得出来ない仕様なんですけど仕様なので仕方ないです。

結局、"コンポーネント1:2" の孫コンポーネントの円の中心(青矢印)は取得出来て
いないです。
原因はこちらのオカレンスの取得方法です。

・・・

        # 孫コンポーネント(正しくはオカレンス)取得
        occs :adsk.fusion.Occurrences = root.allOccurrences
        occ :adsk.fusion.Occurrence = occs.itemByName('コンポーネント2:1') # <-これ

・・・

itemByNameメソッドで目的のオカレンス名を指定しましたが、複数ある場合は
恐らく上にある方を優先的に返すのだろうと思われます。
こうして考えるとitemByNameメソッドに頼るのは、若干危ないな。

ん~結局悩んだ末、上から順番に目的の子コンポーネント(オカレンス)を取得し、
childOccurrencesプロパティを利用しました。
Fusion 360 Help

・・・
        # ルートコンポーネント
        root :adsk.fusion.Component = des.rootComponent

        # 全オカレンス取得
        occs :adsk.fusion.Occurrences = root.allOccurrences # <-修正

        # 子コンポーネント(コピペされたオカレンス)取得
        child_occ :adsk.fusion.Occurrence = occs.itemByName('コンポーネント1:2') # <-修正

        # 孫コンポーネント(正しくはオカレンス)取得
        occ :adsk.fusion.Occurrence = child_occ.childOccurrences.itemByName('コンポーネント2:1') # <-修正

        # オカレンスのコンポーネント
        # オカレンスにはスケッチが無く、参照元のコンポーネントに有り
        comp :adsk.fusion.Component = occ.component
・・・

実行結果はこちら
f:id:kandennti:20201129213139p:plain
無事取得出来ました・・・出来たけどすっきりしませんね。
ルートコンポーネントから、目的のスケッチが入っているオカレンスまでの道のりを
知っているから出来ただけなので。


次回はもうちょっと実践的?な内容で続けます。