C#ATIA

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

オブジェクトとして提供されない要素を選択する4

こちらの続きです。
オブジェクトとして提供されない要素を選択する3 - C#ATIA

説明の順番を間違えています・・・。まずコンポーネントのボディ内にグループを
作成します。
f:id:kandennti:20201207105720p:plain
GUIとテキストコマンドで試すと、こちらのボディを選択状態にして、
f:id:kandennti:20201207105834p:plain

Commands.Start FusionCreateSurfaceGroupCommand

を実行する事で実現する事が分かっています。

そこで、上記の操作をそのままスクリプトにして実行してみます。

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

_app = adsk.core.Application.cast(None)
_ui = adsk.core.UserInterface.cast(None)

def run(context):
    try:
        global _app, _ui
        _app = adsk.core.Application.get()
        _ui = _app.userInterface
        des  :adsk.fusion.Design = _app.activeProduct
        root :adsk.fusion.Component = des.rootComponent

         # オカレンスの<ボディ>を取得
        occ :adsk.fusion.Occurrence = root.occurrences[0]
        bodies :adsk.fusion.BRepBodies = occ.component.bRepBodies

        # 又はコンポーネントの<ボディ>を取得
        # bodies :adsk.fusion.BRepBodies = occ.component.bRepBodies

        # 選択状態にする
        sels :adsk.core.Selections = _ui.activeSelections
        sels.clear()
        sels.add(bodies)

        # グループ作成コマンド実行
        _app.executeTextCommand('Commands.Start FusionCreateSurfaceGroupCommand')

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

オカレンスとしてでもコンポーネントとしてでも、残念な事にここで

        sels.add(bodies)

エラーとなってしまいます。ルートコンポーネントではエラーとならないのですが・・・。

イロイロと試しているうちにテキストコマンドの

Selections.Add <paths>

の場合は選択可能だと言う事が分かりました。SelectionsオブジェクトのAddメソッドとは
異なるようです。全く表記が表記が同じなのですが・・・。

が、必要となるのが上記の理由から直接オカレンスの<ボディ>を選択状態に
する事が出来ない為、オカレンスを選択状態としてを取得します。

import os

・・・

        # Selections取得
        sels :adsk.core.Selections = _ui.activeSelections
        sels.clear()

        # オカレンスを選択状態にする
        sels.add(occ)

        # オカレンスの<paths>を取得
        linesep = os.linesep # os別の改行コードを取得
        occPaths = _app.executeTextCommand(u'Selections.List').rstrip(linesep)

ここからオカレンスのentityIDを取得し、プロパティを見てみます。

import json
import neu_server

・・・

        # オカレンスのentityIDを取得
        occId = str(occPaths).split(':')[-1] # 最後の数字がentityID

        # プロパティの表示
        propTxt = neu_server.get_entity_properties(occId)
        prop =  json.loads(json.dumps(propTxt))
        print(str(json.dumps(propTxt, indent=2)))
{
  "interfaceId": "Ns::Comp::ComponentInstance",
  "segment": 8,
  "creationIndex": 1,
  "lastSavedTargetRevisionGuid": "f88c7cb0-7f91-4563-a215-b3b01d5df3af",
  "persistentId": "54aabc9a-62f8-4c98-a881-66e78560a09c",
  "rOwningDeriveFeature": {},
  "rTargetComponent": {
    "segId": 8,
    "entityId": 173,
    "rootId": ""
  },
  "transform": [
    [
      1,
      0,
      0,
      0
    ],
    [
      0,
      1,
      0,
      0
    ],
    [
      0,
      0,
      1,
      0
    ],
    [
      0,
      0,
      0,
      1
    ]
  ],
  "userName": "",
  "xAssetLinkName": "",
  "rClientObject": {},
  "rParent": {
    "segId": 8,
    "entityId": 4,
    "rootId": ""
  }
}

"Ns::Comp::ComponentInstance" には<ボディ>に関する情報を持っていません。
"rTargetComponent"キーの"entityId"を利用して、コンポーネントのプロパティ
を見てみます。

        # コンポーネントのentityIDを取得
        compId = prop['rTargetComponent']['entityId']

        # プロパティの表示
        propTxt = neu_server.get_entity_properties(compId)
        prop =  json.loads(json.dumps(propTxt))
        print(str(json.dumps(propTxt, indent=2)))
c:\Users\n-ooshima\OneDrive\fusion360API\Script\a1
{
  "interfaceId": "Na::FusionComponent",
  "segment": 8,
  "isAsBuiltPositions": true,
  "opacity": 1,
  "rCanvases": {
    "segId": 8,
    "entityId": 217,
    "rootId": ""
  },

・・・

  "rAltBodies": {
    "segId": 8,
    "entityId": 178,
    "rootId": ""
  },
  "rBodies": {
    "segId": 8,
    "entityId": 176,
    "rootId": ""
  },
  "rContactSets": {
    "segId": 8,
    "entityId": 186,
    "rootId": ""
  },
・・・
}

長すぎるので省略しましたが、"rBodies" が目的のキーです。

これを

オカレンスの<paths> + ':' + コンポーネントID + ':' + <ボディ>のID

となった文字列がオカレンスのボディのとなります。

        # <ボディ>のentityIDを取得
        bodiesId = prop['rBodies']['entityId']

        # <ボディ>の<paths>
        bodiesPaths = '{}:{}:{}'.format(occPaths, compId, bodiesId)

これで選択状態を作ることが出来ます。

        # <ボディ>を選択
        sels.clear()
        _app.executeTextCommand(u'Selections.add {}'.format(bodiesPaths))

        # グループ作成コマンド実行
        _app.executeTextCommand('Commands.Start FusionCreateSurfaceGroupCommand')

これを実行すると無事目的のグループが作成されます。
細切れにコードを表示したので、こちらが全体的なものになります。

# Fusion360API Python script
import adsk.core, adsk.fusion, traceback
import os
import json
import neu_server

_app = adsk.core.Application.cast(None)
_ui = adsk.core.UserInterface.cast(None)

def run(context):
    try:
        global _app, _ui
        _app = adsk.core.Application.get()
        _ui = _app.userInterface
        des  :adsk.fusion.Design = _app.activeProduct
        root :adsk.fusion.Component = des.rootComponent

         # オカレンスの取得
        occ :adsk.fusion.Occurrence = root.occurrences[0]

        # Selections取得
        sels :adsk.core.Selections = _ui.activeSelections
        sels.clear()

        # オカレンスを選択状態にする
        sels.add(occ)

        # オカレンスの<paths>を取得
        linesep = os.linesep # os別の改行コードを取得
        occPaths = _app.executeTextCommand(u'Selections.List').rstrip(linesep)

        # オカレンスのentityIDを取得
        occId = str(occPaths).split(':')[-1] # 最後の数字がentityID

        # プロパティの表示
        propTxt = neu_server.get_entity_properties(occId)
        prop =  json.loads(json.dumps(propTxt))
        print(str(json.dumps(propTxt, indent=2)))

        # コンポーネントのentityIDを取得
        compId = prop['rTargetComponent']['entityId']

        # プロパティの表示
        propTxt = neu_server.get_entity_properties(compId)
        prop =  json.loads(json.dumps(propTxt))
        print(str(json.dumps(propTxt, indent=2)))

        # <ボディ>のentityIDを取得
        bodiesId = prop['rBodies']['entityId']

        # <ボディ>の<paths>
        bodiesPaths = '{}:{}:{}'.format(occPaths, compId, bodiesId)

        # <ボディ>を選択
        sels.clear()
        _app.executeTextCommand(u'Selections.add {}'.format(bodiesPaths))

        # グループ作成コマンド実行
        _app.executeTextCommand('Commands.Start FusionCreateSurfaceGroupCommand')

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

通常の方法に比べ、桁違いに面倒です。しかし、通常のFusion360APIでは選択出来ない要素が
選択可能となり、大幅に処理が出来るものが増えます。
上手く伝わるかな? APIフォーラムを見ても他の方が気が付いていないようなので、
専売特許状態でも良いのは良いのですが。