こちらの続きです。
フィレットの元のエッジを探せ!!4 - C#ATIA
前回は単調にentityTokenを文字として出力しましたが、
比較が面倒な為、画面上に色付きのエッジとして表示させる
ことにしました。
# Fusion360API Python script import traceback import adsk.fusion import adsk.core _app: adsk.core.Application = None _ui: adsk.core.UserInterface = None _handlers = [] _selIpt: adsk.core.SelectionCommandInput = None _cmdInfo = { 'id': 'KANTOKU_EntityTokenDump', 'name': 'Entity TokenDump', 'tooltip': 'Entity TokenDump', } class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler): def __init__(self): super().__init__() def notify(self, args: adsk.core.CommandCreatedEventArgs): try: global _handlers cmd: adsk.core.Command = adsk.core.Command.cast(args.command) cmd.isOKButtonVisible = False inputs: adsk.core.CommandInputs = cmd.commandInputs onDestroy = MyCommandDestroyHandler() cmd.destroy.add(onDestroy) _handlers.append(onDestroy) onExecutePreview = MyExecutePreviewHandler() cmd.executePreview.add(onExecutePreview) _handlers.append(onExecutePreview) global _selIpt _selIpt = inputs.addSelectionInput( 'selIptId', 'Select Feature', '' ) _selIpt.addSelectionFilter( adsk.core.SelectionCommandInput.Features ) except: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) class MyExecutePreviewHandler(adsk.core.CommandEventHandler): def __init__(self): super().__init__() def notify(self, args: adsk.core.CommandEventArgs): global _selIpt feat: adsk.fusion.Feature = _selIpt.selection(0).entity showTokenEdges(feat) def showTokenEdges(feat: adsk.fusion.Feature): app: adsk.core.Application = adsk.core.Application.get() des: adsk.fusion.Design = app.activeProduct def getAllEdges(bodies: adsk.fusion.BRepBodies) -> list: bodyLst = [] try: for body in bodies: [bodyLst.append(e) for e in body.edges] except: pass return bodyLst def getEdgeTokenSet(bodies: adsk.fusion.BRepBodies) -> set: return set([e.entityToken for e in getAllEdges(bodies)]) def drawCG(edges, color): root: adsk.fusion.Component = des.rootComponent tmpMgr: adsk.fusion.TemporaryBRepManager = adsk.fusion.TemporaryBRepManager.get() clones = [tmpMgr.copy(e) for e in edges] cgGroup: adsk.fusion.CustomGraphicsGroup = root.customGraphicsGroups.add() for body in clones: try: cgCurve: adsk.fusion.CustomGraphicsCurve= cgGroup.addCurve(body.edges[0].geometry) cgCurve.weight = 3.0 cgCurve.color = color except: pass adsk.doEvents() app.activeViewport.refresh() # ***** timeline: adsk.fusion.Timeline = des.timeline timeObj: adsk.fusion.TimelineObject = feat.timelineObject timeObj.rollTo(True) previousTimeObj: adsk.fusion.TimelineObject = timeline.item( timeline.markerPosition - 1 ) previousFeat: adsk.fusion.Feature = previousTimeObj.entity if not hasattr(previousFeat, 'bodies'): return previousEdgeTokens = getEdgeTokenSet(previousFeat.bodies) timeObj.rollTo(False) if not hasattr(feat, 'bodies'): return intersection = [] difference = [] edges = getAllEdges(feat.bodies) for edge in edges: if edge.entityToken in previousEdgeTokens: intersection.append(edge) else: difference.append(edge) drawCG( intersection, adsk.fusion.CustomGraphicsSolidColorEffect.create( adsk.core.Color.create(0, 0, 255, 255) ) ) drawCG( difference, adsk.fusion.CustomGraphicsSolidColorEffect.create( adsk.core.Color.create(255, 0, 0, 255) ) ) class MyCommandDestroyHandler(adsk.core.CommandEventHandler): def __init__(self): super().__init__() def notify(self, args: adsk.core.CommandEventArgs): adsk.terminate() def run(context): try: global _app, _ui _app = adsk.core.Application.get() _ui = _app.userInterface global _cmdInfo cmdDef: adsk.core.CommandDefinition = _ui.commandDefinitions.itemById( _cmdInfo['id'] ) if not cmdDef: cmdDef = _ui.commandDefinitions.addButtonDefinition( _cmdInfo['id'], _cmdInfo['name'], _cmdInfo['tooltip'] ) global _handlers onCommandCreated = MyCommandCreatedHandler() cmdDef.commandCreated.add(onCommandCreated) _handlers.append(onCommandCreated) cmdDef.execute() adsk.autoTerminate(False) except: if _ui: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))
スクリプトを実行してタイムラインのフィーチャを選択すると、
もう一つ手前のタイムラインのフィーチャのエッジと
entityTokenを比較した結果を表示します。
ん~言葉じゃ難しい。
青色はentityTokenが変更されていないエッジで、
赤色はentityTokenが変更されたエッジです。
具体的に単純な例を示すと
・スケッチ->押し出し->フィレット1
・フィレット2
・フィレット3
の順で作成した場合に先程のフィレット2を選択した場合は
この様な表示になります。
黄色のエッジは画面上では変更が無いものの、entityTokenは
変更されています。
まぁこれはこれで、"Fusion360の仕様" として受け入れる
しかない と思っています。
ここで、タイムラインのフィレット2とフィレット3の
順番を入れ替え、今度はフィレット3をスクリプトで
選択した結果です。
黄色のエッジは画面上では変更が無く、entityTokenも
変更されてません。何故・・・。
念の為、タイムラインの入れ替えでは無く、新規にあの順番で
フィレットを付けた場合でも同様の結果となります。
モデリングを行った方法?順番?によって得られる結果が
異なるようでは、何が正しいものなのかが分からなく、
心底行き詰まり感を感じます。
推測ですが、エッジのentityTokenについては、今の所こんな
解釈でいます。
・エッジのentityTokenについては、面のentityTokenに依存している。
・共有しているエッジの場合は、両側の面のエッジのどちらかの
entityTokenとなっている。(恐らくエッジ自体が)
・両側の面のどちらかのエッジが採用されるか?のルールが
あるが、わからない。
例えば、フィレット1,2,3の時は
黄色星の面がピンク色エッジを持っていて、フィレットを付けた際に
黄色星の面が変更される為、新たな面が作成されentityTokenが
変更され、
フィレット1,3,2の時は
黄色星の面がエッジを持っているのだろうと思っています。
仮にこれが正しい解釈だとしても、依存を見つける事には
役に立たないです。 困った。