C#ATIA

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

スケッチの点の正しい座標値の取得2

こちらの続きです。
スケッチの点の正しい座標値の取得1 - C#ATIA

Sketchオブジェクトを調べると、sketchToModelSpaceメソッドの
説明が、目的の内容に該当しそうな気がします。
その為、こんな感じにしてみます。

#Fusion360API_Python - test3
・・・

        #点が所属しているスケッチ
        skt = adsk.fusion.Sketch.cast(sktPnt.parentSketch)

        #点の座標値を表示する
        #本来はunitsManagerで単位を変換したりするのですが
        #今回の目的ではない為、10倍して単位をmmにします。
        pnt3d = skt.sketchToModelSpace(sktPnt.worldGeometry)

・・・

実行結果はこちら。
f:id:kandennti:20191028181246p:plain
ん~全然違いますね。これがバグなのか、仕様なのか、使い方が
間違っているのか 判断出来ません。そもそも何の数値が返ってきて
いるのかもわからなかったです。


今の所すんなり目的の値を得る方法が見当たらない為、地道に行く事に
します。そもそもの原因は明らかで、コンポーネントのズレがworldGeometry
プロパティで得られるPoint3Dでは、考慮されていない事ですよね。
つまり、sketchPointからコンポーネントのズレまで辿り着けるか? が
焦点になりそうです。

その前に、Fusion360コンポーネントについて理解しておく必要があります。
(個人的には、ここが非常に違和感がありました)
f:id:kandennti:20191028181306p:plain
今、画面上ではこのような状態になっています。
赤矢印部分は "ルートコンポーネント" と呼ばれ、全体の3D空間を
保持しています。
青矢印は追加した "コンポーネント" なのですが、これはAPI的に
"ルートコンポーネント" に直接ぶら下がっている状態では無いんです。
下手くそな絵ですが、こんなイメージです。
f:id:kandennti:20191028181317p:plain
"ルートコンポーネント" に直接ぶら下がっているのは "オカレンス"
で、それに "コンポーネント" が入っている感じです。
そして "オカレンス" にズレの要素が含まれています。
(余談ですが "ルートコンポーネント" にはオカレンスがありません)
Fusion 360 Help
"オカレンス" 自体がCAD画面上には表示されず、"ルートコンポーネント"
に直接 "コンポーネント" 自体がぶら下がっているように表示されて
いるため、個人的には非常に混乱します。


続いてはズレの要素が "オカレンス" に含まれているため、
sketchPointからOccurrenceまで辿り着くためのルート探しです。
ここでまた難問が・・・。
sketchPointから所属するComponentを求めるのは簡単です。

        #点が所属しているスケッチ
        skt = adsk.fusion.Sketch.cast(sktPnt.parentSketch)

        #スケッチが所属しているコンポーネント
        comp = skt.parentComponent

ところが肝心のComponentから関連するOccurrenceを取得するメソッド
が見当たりません。

ブログで記載している順番が前後するのですが、結果的にこちらに記載した
自作関数を利用して関連するOccurrence全てを取得することにしました。
任意のコンポーネントに関連するオカレンスを取得 - C#ATIA


Occurrenceの取得が出来たので、transformプロパティを利用することで
移動・回転に関するMatrix3Dオブジェクトの取得が可能となります。
Fusion 360 Help
最初transformは、てっきり変換するためのメソッドだと思っていたの
ですが、変換した位置情報を持ったプロパティなんですよね。
(先入観って怖い)

これらのMatrix3D情報をスケッチの点に反映してやれば、正しい位置情報を
得ることが出来そうです。

最後なのでコメント多めのコード丸ごとです。

#Fusion360API_Python
#Author-kantoku
#Description-スケッチ点の座標値の表示

import adsk.core, adsk.fusion, traceback

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

        #全てのスケッチ取得
        skts = [skt
                for comp in des.allComponents
                for skt in comp.sketches]
        
        #1個目のスケッチ内の2個目の点座標を取得
        #スケッチの1個目の点はスケッチ原点です
        sktPnt = skts[0].sketchPoints[1]

        #点が所属しているスケッチ
        skt = adsk.fusion.Sketch.cast(sktPnt.parentSketch)

        #スケッチが所属しているコンポーネント
        comp = adsk.fusion.Component.cast(skt.parentComponent)

        #ルートコンポーネント取得
        root =  comp.parentDesign.rootComponent
        pnt3d = None
        if comp == root:
            #ルートコンポーネントの場合はそのまま
            pnt3d = sktPnt.worldGeometry
        else:
            #point3dのクローン
            pnt3d = sktPnt.worldGeometry.copy()

            #関連オカレンス取得
            occs = GetParentOccurrenceList(comp)

            #関連変換位置取得
            mat3ds = [occ.transform for occ in occs]

            #クローンに全ての変換位置反映
            for mat3d in mat3ds:
                pnt3d.transformBy(mat3d)
        
        #点の座標値を表示する
        #本来はunitsManagerで単位を変換したりするのですが
        #今回の目的ではない為、10倍して単位をmmにします。
        ui.messageBox('X:{}\nY:{}\nZ:{}'.format(pnt3d.x * 10, pnt3d.y * 10, pnt3d.z * 10))

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

#任意のコンポーネントから関連するオカレンスを取得
def GetParentOccurrenceList(comp):
    comp = adsk.fusion.Component.cast(comp)
    des = adsk.fusion.Design.cast(comp.parentDesign)
    root =des.rootComponent

    if root == comp:
        return None

    occs = root.allOccurrencesByComponent(comp)
    if len(occs) < 1:
        return None

    occ = occs[0]
    occ_names = occ.fullPathName.split('+')
    occs = [root.allOccurrences.itemByName(name) 
                for name in occ_names]

    return occs

前回(20,30,40)を期待していたデータで試すと
f:id:kandennti:20191028181455p:plain
正しい値が返ってきました。
これであれば、階層が深いデータでも正しい値が取得出来ます。

・・・結果的にリンク先の回答が、間違っていることが判明