C#ATIA

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

要素の依存関係9

こちらの続きです。
要素の依存関係8 - 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
        # des: adsk.fusion.Design = app.activeProduct

        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

    # ************
    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 = {}
    # treeDict = {}
    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)
        [bodiesDict[info['id']]['children'].append(initFeatureInfo(feat)) for info in bodyInfos]

    timeline.markerPosition = backupMarker

    return bodiesDict


# '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))


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

CATIA V5の履歴は、
・Tree自体はボディ同士の依存関係
・ボディ内は時系列
の状態になっており、”ボディありき” な考え方になっているような
気がしますが、Fusion360の場合は "結果的にボディ" のような感覚です。

今進めているのは、正にそれに近い状態でしてグラフ表現では無く
ツリー表現にしようと思っています。jsTreeで。