こちらのCATIAマクロをFusion360でも利用したい気持ちが山々です。
サーフェスの色をボディに反映する2 - C#ATIA
Fusion360もCATIA同様に、サーフェスをソリッド化した際に面の色は
引き継いでもらえません。(恐らく一番最初の面の色に統一)
CADにとって面の色は重要な要素だと思い込んでいます。
この処理を行う際、同一面を検索する必要があるのですが、既に
こちらでその処理は行った事があります。
3D間違い探しを解く2 - C#ATIA
ハードル的には高くは無さそうなので作ってみました。が、
# FusionAPI_python # Author-kantoku import adsk.core, adsk.fusion, traceback import bisect as bs import time from .Fusion360Utilities.Fusion360Utilities import AppObjects from .Fusion360Utilities.Fusion360CommandBase import Fusion360CommandBase # CommandInputs _selTgtInfo = ['dlgSelTgt','対象ボディ','色を変更するボディを選択'] _selRefInfo = ['dlgSelRef','参照コンポーネント','参照元となるコンポーネントを選択'] class ColorRestorationCore(Fusion360CommandBase): _handlers = [] def __init__(self, cmd_def, debug): super().__init__(cmd_def, debug) pass def on_preview(self, command: adsk.core.Command, inputs: adsk.core.CommandInputs, args, input_values): pass def on_destroy(self, command: adsk.core.Command, inputs: adsk.core.CommandInputs, reason, input_values): pass def on_input_changed(self, command: adsk.core.Command, inputs: adsk.core.CommandInputs, changed_input, input_values): pass def on_execute(self, command: adsk.core.Command, inputs: adsk.core.CommandInputs, args, input_values): ao = AppObjects() try: global _selTgtInfo, _selRefInfo # target selTgt :adsk.core.SelectionCommandInput = inputs.itemById(_selTgtInfo[0]) # reference selRef :adsk.core.SelectionCommandInput = inputs.itemById(_selRefInfo[0]) fact = ColorRestorationFactry( selTgt.selection(0).entity, selRef.selection(0).entity) fact.exec() except: if ao.ui: ao.ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) pass def on_create(self, command: adsk.core.Command, inputs: adsk.core.CommandInputs): ao = AppObjects() # comp Position check command.isPositionDependent = True # -- event -- onValid = self.ValidateInputHandler() command.validateInputs.add(onValid) self._handlers.append(onValid) onPreSelect = self.PreSelectHandler() command.preSelect.add(onPreSelect) self._handlers.append(onPreSelect) # -- Dialog -- global _selTgtInfo, _selRefInfo # target selTgt :adsk.core.SelectionCommandInput = inputs.addSelectionInput( _selTgtInfo[0], _selTgtInfo[1], _selTgtInfo[2]) selTgt.setSelectionLimits(0) selTgt.addSelectionFilter('Bodies') # reference selRef :adsk.core.SelectionCommandInput = inputs.addSelectionInput( _selRefInfo[0], _selRefInfo[1], _selRefInfo[2]) selRef.setSelectionLimits(0) selRef.addSelectionFilter('Occurrences') # -- Support class -- class PreSelectHandler(adsk.core.SelectionEventHandler): def __init__(self): super().__init__() def notify(self, args): try: args = adsk.core.SelectionEventArgs.cast(args) inputs = args.activeInput.commandInputs actIpt = adsk.core.SelectionCommandInput.cast( args.firingEvent.activeInput) if not actIpt: return global _selTgtInfo, _selRefInfo # target selTgt :adsk.core.SelectionCommandInput = inputs.itemById(_selTgtInfo[0]) # reference selRef :adsk.core.SelectionCommandInput = inputs.itemById(_selRefInfo[0]) # -- target -- if actIpt.id == _selTgtInfo[0]: if selTgt.selectionCount > 0: args.isSelectable = False return # comp ent = args.selection.entity comp = ent.parentComponent # Unmatched comp if selRef.selectionCount < 1: return tgt = selRef.selection(0).entity if comp == tgt.parentComponent: args.isSelectable = False return # -- reference -- if actIpt.id == _selRefInfo[0]: if selRef.selectionCount > 0: args.isSelectable = False return # comp ent = args.selection.entity comp = adsk.fusion.Component.cast(ent) if comp is None: occ = adsk.fusion.Occurrence.cast(ent) comp = occ.component # bRepBodies.count if comp.bRepBodies.count < 1: args.isSelectable = False return # Unmatched comp if selTgt.selectionCount < 1: return tgt = selTgt.selection(0).entity if comp == tgt.parentComponent: args.isSelectable = False return except: ao = AppObjects() ao.ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) class ValidateInputHandler(adsk.core.ValidateInputsEventHandler): def __init__(self): super().__init__() def notify(self, args): inputs = args.inputs global _selTgtInfo, _selRefInfo # target selTgt :adsk.core.SelectionCommandInput = inputs.itemById(_selTgtInfo[0]) # reference selRef :adsk.core.SelectionCommandInput = inputs.itemById(_selRefInfo[0]) if selTgt.selectionCount > 0 and selRef.selectionCount > 0: args.areInputsValid = True else: args.areInputsValid = False class ColorRestorationFactry(): _tgtFaces :list = [] _refFaces :list = [] _mat :adsk.core.Matrix3D = None def __init__( self, tgtBody :adsk.fusion.BRepBody, refOcc :adsk.fusion.Occurrence): occ = tgtBody.assemblyContext mat = adsk.core.Matrix3D.create() if occ: mat = occ.transform self._mat = self.getMatrix( mat, refOcc.transform) self._tgtFaces = [f for f in tgtBody.faces] lst = [] for bdy in refOcc.bRepBodies: for f in bdy.faces: lst.append(f) self._refFaces = lst def exec( self, cogTolerance = 0.001, areaTolerance = 0.001): ao = AppObjects() try: adsk.fusion.BRepFace.isOverRap = False adsk.fusion.BRepFace.transform_centroid = None face = adsk.fusion.BRepFace.cast(None) tgtFaces = sorted(self._tgtFaces, key=lambda v: v.area) refFaces = sorted(self._refFaces, key=lambda v: v.area) refAreas = [face.area for face in refFaces] for face in refFaces: face.transform_centroid = self.transformByClone( face.centroid, self._mat) ref = adsk.fusion.BRepFace.cast(None) tgtCog = adsk.core.Point3D.cast(None) for face in tgtFaces: if face.isOverRap: continue lwr = bs.bisect_left(refAreas, face.area - areaTolerance) upr = bs.bisect_right(refAreas, face.area + areaTolerance) tgtCog = face.centroid rangeFaces = [ref for ref in refFaces[lwr : upr] if not ref.isOverRap] for ref in rangeFaces: if tgtCog.isEqualToByTolerance( ref.transform_centroid, cogTolerance): face.appearance = ref.appearance ref.isOverRap = True vp :adsk.core.Viewport = AppObjects().app.activeViewport vp.refresh() except: ao.ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) # 補正後の重心 def transformByClone( self, pnt :adsk.core.Point3D, mat :adsk.core.Matrix3D) -> adsk.core.Point3D: p = pnt.copy() p.transformBy(mat) return p # 位置ずれ def getMatrix( self, fromMat :adsk.core.Matrix3D, toMat :adsk.core.Matrix3D) -> adsk.core.Matrix3D: (f_ori, f_x, f_y, f_z) = fromMat.getAsCoordinateSystem() (t_ori, t_x, t_y, t_z) = toMat.getAsCoordinateSystem() mat = adsk.core.Matrix3D.create() mat.setToAlignCoordinateSystems( t_ori, t_x, t_y, t_z, f_ori, f_x, f_y, f_z) return mat
劇的に遅いです・・・。原因が分からないのですが、使い物にならないほど
遅いんです。
同一面を見つけながら、見付けた時点で色を反映しているのですが、
まとめて色を変える方法は恐らく無いと思うのですが。
1枚色を反映する毎にグラフィックの更新がかかっている感じがするので、
それを食い止めたいのですが、方法がみつからないんです。