こちらの続きです。
スケッチの点の正しい座標値の取得1 - C#ATIA
Sketchオブジェクトを調べると、sketchToModelSpaceメソッドの
説明が、目的の内容に該当しそうな気がします。
その為、こんな感じにしてみます。
#Fusion360API_Python - test3 ・・・ #点が所属しているスケッチ skt = adsk.fusion.Sketch.cast(sktPnt.parentSketch) #点の座標値を表示する #本来はunitsManagerで単位を変換したりするのですが #今回の目的ではない為、10倍して単位をmmにします。 pnt3d = skt.sketchToModelSpace(sktPnt.worldGeometry) ・・・
実行結果はこちら。
ん~全然違いますね。これがバグなのか、仕様なのか、使い方が
間違っているのか 判断出来ません。そもそも何の数値が返ってきて
いるのかもわからなかったです。
今の所すんなり目的の値を得る方法が見当たらない為、地道に行く事に
します。そもそもの原因は明らかで、コンポーネントのズレがworldGeometry
プロパティで得られるPoint3Dでは、考慮されていない事ですよね。
つまり、sketchPointからコンポーネントのズレまで辿り着けるか? が
焦点になりそうです。
その前に、Fusion360のコンポーネントについて理解しておく必要があります。
(個人的には、ここが非常に違和感がありました)
今、画面上ではこのような状態になっています。
赤矢印部分は "ルートコンポーネント" と呼ばれ、全体の3D空間を
保持しています。
青矢印は追加した "コンポーネント" なのですが、これはAPI的に
"ルートコンポーネント" に直接ぶら下がっている状態では無いんです。
下手くそな絵ですが、こんなイメージです。
"ルートコンポーネント" に直接ぶら下がっているのは "オカレンス"
で、それに "コンポーネント" が入っている感じです。
そして "オカレンス" にズレの要素が含まれています。
(余談ですが "ルートコンポーネント" にはオカレンスがありません)
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)を期待していたデータで試すと
正しい値が返ってきました。
これであれば、階層が深いデータでも正しい値が取得出来ます。
・・・結果的にリンク先の回答が、間違っていることが判明