Fusion360で僕が一番悩むのが、コンポーネントに対応させたスクリプト(とアドイン)です。
APIフォーラムでも比較的最近は少なくなりましたが、コンポーネント(正しくはOccurrence)
絡みで "正しい結果が得られない" "バグじゃないのか?" のようなものの原因は恐らくこれです。
今後、Fusion360APIを取り組まれる方の為に知っている範囲で記載しておきます。
対象は初心者を脱したかな? 辺りです(それは僕)
通常であれば "履歴をキャプチャする" モードで行うはずなので、それを前提でお話を進めます。
構築-オフセット平面でXY平面+30mmの平面を作成します。
続いて、オフセット平面をサポートにしてスケッチを作成し、X 10mm Y 20mmを中心とする
円を描きます。こんな感じです。(直径は無関係です)
この円の中心点は、X 10mm Y 20mm Z 30mm として存在しているはずですよね?
測定コマンドを使用してもご覧の通りです。
これをスプリクトで取得し表示させるために、この様なものを作成しました。
# Fusion360API Python script # sample1 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 # コンポーネント内の1個目のスケッチ skt :adsk.fusion.Sketch = root.sketches[0] # スケッチ内の1個目の円 - 目的の円 curvrs :adsk.fusion.SketchCurves = skt.sketchCurves circle :adsk.fusion.SketchCircle = curvrs.sketchCircles[0] # SketchCircleには中心点情報が無いので、geometryを取得 geo :adsk.core.Circle3D = circle.geometry # 単位を正しくしたい為、係数取得 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()))
これを実行すると・・・
裏切られました。Zの値が正しくありません。
原因はこちらです。
・・・ # SketchCircleには中心点情報が無いので、geometryを取得 geo :adsk.core.Circle3D = circle.geometry # <-ここ ・・・
円(SketchCircleオブジェクト)には中心の情報が無いため、幾何学的情報を得るためには
ジオメトリ(Circle3Dオブジェクト)を取得し調べることになりますが、
geometryプロパティ:スケッチ内での状態 worldGeometryプロパティ:スケッチを抜けた状態
で取得する事になります。
Fusion 360 Help
つまりこの様に修正します。
・・・ # SketchCircleには中心点情報が無いので、geometryを取得 geo :adsk.core.Circle3D = circle.worldGeometry # <-こんな感じ ・・・
これで実行すると
無事、目的の値で取得出来ました。worldGeometryプロパティを使用しなくても
正しい値を取得する方法はあるのですが、これが一番間違いない方法だと思います。
・・・コンポーネントを使用しなければ ですが。
次にコンポーネントを使用した場合を見ていきます。
まず、新規にコンポーネントを作成します。
外部だとややこしいので "内部" にしましょう。
予め言葉の整合性を保つため、青矢印部分は "ルートコンポーネント" と呼ぶことにします。
(APIでそうなっているからです)
この状態の場合、ルートコンポーネントと新作のコンポーネントの原点位置は同じです。
続いて新作のコンポーネント内にXY平面をサポートしたスケッチを作成して、スケッチの原点を
中心に円を描きます。
その後スケッチを抜け、移動コマンドでコンポーネントを移動させます。
X 10mm Y 20mm Z 30mm としておきましょう。
移動コマンドを終了した際、注意が必要です。
通常、ツールパネルに一番右側にこちらが表示されます。
"位置をキャプチャ" を必ずさせて位置を確定させます。
確定後、ルートコンポーネントをアクティブにすると履歴に追加されます。
これを行わないと何を行っても、移動前の情報しか取得できません。
(以前、悩まされました。 これはAPIでも確定させることは可能です。)
・・・今気が付きましたが、移動コマンドのダイアログ内に "位置をキャプチャ" の
チェックボックスが有ったんですね。皆使ってないと思うけど。
さて、この状態で円の中心座標を取得する場合、当然ルートコンポーネントから見た状態の
X 10mm Y 20mm Z 30mm を期待します。
この様に、コンポーネントに対応した状態にスクリプトを修正しました
# Fusion360API Python script # sample2 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 # ルートコンポーネント内のオカレンスの1個目 occs :adsk.fusion.Occurrences = root.allOccurrences occ :adsk.fusion.Occurrence = occs[0] # オカレンスのコンポーネント # オカレンスにはスケッチが無く、参照元のコンポーネントに有り comp :adsk.fusion.Component = occ.component # コンポーネント内の1個目のスケッチ skt :adsk.fusion.Sketch = comp.sketches[0] # スケッチ内の1個目の円 - 目的の円 curvrs :adsk.fusion.SketchCurves = skt.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()))
この状態で実行すると・・・
あっさり期待を裏切られます。先程のworldGeometryプロパティを使っているにも関わらず。
"ちっともWorldじゃねぇじゃないか!” と、お思いになった方、正解です。
worldGeometryは、スケッチから抜けた状態で取得しているのは間違いないです。
しかし抜けた状態なだけで、スケッチの所属しているコンポーネントでの円を
取得しているにすぎません。例えるのであれば、新作したコンポーネントを
アクティブにした状態と考えて良いでしょう。
念のためお伝えしておきますが、ルートコンポーネントをアクティブにした状態でも
裏切られます。
じゃあどうすれば・・・と言う事になりますが長くなりすぎた為、本題に入らないまま
次回に続けます。