C#ATIA

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

要素の依存関係10

こちらの続きです。
要素の依存関係9 - C#ATIA

結合に対応させました。出力は望んだ状態になりましたが、
処理が汚い・・・。

# Fusion360API Python script

import traceback
import adsk.fusion
import adsk.core
import itertools
import json

def run(context):
    ui = adsk.core.UserInterface.cast(None)
    try:
        app: adsk.core.Application = adsk.core.Application.get()
        ui = app.userInterface

        dict = getBodiesTree()

        print(json.dumps(dict, indent=2, ensure_ascii=False))
        app.log(f'{json.dumps(dict, indent=2, ensure_ascii=False)}')

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


def getBodiesTree() -> dict:

    # Expansion
    adsk.fusion.ExtrudeFeature.getRefs = getReferences_Extrude
    adsk.fusion.RevolveFeature.getRefs = getReferences_Extrude
    adsk.fusion.LoftFeature.getRefs = getReferences_Loft
    adsk.fusion.SweepFeature.getRefs = getReferences_Sweep
    adsk.fusion.HoleFeature.getRefs = getReferences_Hole

    adsk.fusion.CombineFeature.getRefs = getReferences_Combine

    # ************
    def initBodyInfo(body: adsk.fusion.BRepBody) -> dict:
        return {
            'id' : body.entityToken,
            'text' : body.name,
            'icon' : '',
            'children' : [],
        }

    def initFeatureInfo(feat: adsk.fusion.Feature) -> dict:
        if hasattr(feat, 'getRefs'):

            children = feat.getRefs()
        else:
            children = []

        return {
            'id' : feat.entityToken,
            'text' : feat.name,
            'icon' : '',
            'children' : children,
        }

    # ******
    app: adsk.core.Application = adsk.core.Application.get()
    des: adsk.fusion.Design = app.activeProduct

    timeline: adsk.fusion.Timeline = des.timeline
    backupMarker = timeline.markerPosition

    bodiesDict = {}

    timeObjs = [timeline.item(idx) for idx in range(timeline.count)]
    for timeObj in timeObjs:
        timeObj: adsk.fusion.TimelineObject

        feat: adsk.fusion.Feature = adsk.fusion.Feature.cast(timeObj.entity)
        if not feat:
            continue

        timeObj.rollTo(False)

        if not hasattr(feat, 'bodies'):
            continue

        bodyInfos = [initBodyInfo(b) for b in feat.bodies]
        [bodiesDict.setdefault(info['id'], info) for info in bodyInfos]

        timeObj.rollTo(True)
        if feat.classType() == adsk.fusion.CombineFeature.classType():
            # 結合
            for info in bodyInfos:
                children = []
                featInfo = initFeatureInfo(feat)
                for token in featInfo['children']:
                    children.append(bodiesDict[token])
                    bodiesDict.pop(token)
                featInfo['children'] = children
                bodiesDict[info['id']]['children'].append(featInfo)

        else:
            # その他
            [bodiesDict[info['id']]['children'].append(initFeatureInfo(feat)) for info in bodyInfos]

    timeline.markerPosition = backupMarker

    return bodiesDict

def getBodies() -> list:
    app: adsk.core.Application = adsk.core.Application.get()
    des: adsk.fusion.Design = app.activeProduct

    bodiesList = [c.bRepBodies for c in des.allComponents]
    bodyList = []
    for bodies in bodiesList:
        bodyList.extend([b for b in bodies])

    bodyInfos = []
    for body in bodyList:
        bodyInfos.append(
            {
                'id' : body.entityToken,
                'text' : body.name,
            }
        )

    return bodyInfos

# 'adsk::fusion::RevolveFeature'
# 'adsk::fusion::ExtrudeFeature'
def getReferences_Extrude(self):

    def getParentEntity(prof):
        if hasattr(prof, 'parentSketch'):
            return prof.parentSketch.name
        else:
            return

    parent = None
    try:
        prof = self.profile
        if hasattr(prof, '__iter__'):
            profs = [getParentEntity(p) for p in self.profile]
            parent = list(set(profs))
        else:
            parent = [getParentEntity(prof)]
    except:
        parent = []

    return parent


# 'adsk::fusion::LoftFeature'
def getReferences_Loft(self) -> list:

    def getAllReference() -> list:
        refs = []

        for groupName in ['loftSections', 'centerLineOrRails']:
            try:
                group = getattr(self, groupName)
                refs.extend(e for e in group)
            except:
                continue

        return refs

    def getParent(sect) -> str:
        try:
            return sect.entity.parentSketch.name
        except:
            return None

    parent = None
    try:
        sections = getAllReference()
        refs = removeBlanks([getParent(s) for s in sections])
        parent = list(set(refs))
    except:
        parent = []

    return parent


# 'adsk::fusion::SweepFeature'
def getReferences_Sweep(self) -> list:

    def getParent(ent) -> str:
        try:
            return ent.parentSketch.name
        except:
            return None

    parent = []
    # profile
    try:
        parent.append(getParent(self.profile))
    except:
        pass

    # path
    try:
        parent.extend([getParent(p.entity) for p in self.path])
    except:
        pass

    return list(set(parent))


# 'adsk::fusion::HoleFeature'
def getReferences_Hole(self) -> list:

    def getParent(ent) -> str:
        try:
            return ent.parentSketch.name
        except:
            return None

    parent = []
    try:
        points: adsk.core.ObjectCollection = self.holePositionDefinition.sketchPoints
        parent.extend([getParent(p) for p in points])
    except:
        pass

    return list(set(parent))


# 'adsk::fusion::CombineFeature'
def getReferences_Combine(self) -> list:
    parent = []
    for body in self.toolBodies:
        parent.append(body.entityToken)

    return parent



def removeBlanks(lst: list):
    return list(filter(lambda x: x is not None, lst))

取りあえず悩んでいた部分だったのですが、まぁ取りあえずは
これで進めます。
後で修正・追加は必要になるとは思うますが、ここまで作れば
Tree表示に取り掛かりましょう。