こちらの続きです。
毛を生やす4 - C#ATIA
え~今回は毛を生やしません。
前回のサーフェスを作る・作らないは、その面が該当するボディにとっての外側・内側を
判断し外側と判定した面の場合のみ作っていました。
(そもそも外側・内側の境界って何なのかな?)
これをボディ丸ごと処理するようにしたものがこちらです。
# Fusion360API Python script # サンプルデータ # https://grabcad.com/library/random-part-13 import traceback import adsk import adsk.core as core import adsk.fusion as fusion _app: core.Application = None _ui: core.UserInterface = None _handlers = [] _selFace: core.SelectionCommandInput = None CMD_INFO = { 'id': 'kantoku_test', 'name': 'test', 'tooltip': 'test' } class MyCommandCreatedHandler(core.CommandCreatedEventHandler): def __init__(self): super().__init__() def notify(self, args: core.CommandCreatedEventArgs): try: global _handlers cmd: core.Command = core.Command.cast(args.command) # cmd.isOKButtonVisible = False onDestroy = MyCommandDestroyHandler() cmd.destroy.add(onDestroy) _handlers.append(onDestroy) onExecutePreview = MyExecutePreviewHandler() cmd.executePreview.add(onExecutePreview) _handlers.append(onExecutePreview) inputs: core.CommandInputs = cmd.commandInputs global _selFace _selFace = inputs.addSelectionInput( "_selFaceId", "ボディ", "外側のみ抜き出すボディを選んで!", ) _selFace.addSelectionFilter(core.SelectionCommandInput.Bodies) except: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) class MyExecutePreviewHandler(core.CommandEventHandler): def __init__(self): super().__init__() def notify(self, args: core.CommandEventArgs): args.isValidResult = True body: fusion.BRepBody = _selFace.selection(0).entity outerBody: fusion.BRepBody = get_shell_faces(body) if not outerBody: return comp: fusion.Component = body.parentComponent des: fusion.Design = comp.parentDesign baseFeat: fusion.BaseFeature = None if des.designType == fusion.DesignTypes.ParametricDesignType: baseFeat = comp.features.baseFeatures.add() bodies: fusion.BRepBodies = comp.bRepBodies if baseFeat: baseFeat.startEdit() bodies.add(outerBody, baseFeat) baseFeat.finishEdit() else: bodies.add(outerBody, baseFeat) def get_shell_faces( body: fusion.BRepBody,) -> fusion.BRepBody: comp: fusion.Component = body.parentComponent tmpFeat: fusion.TemporaryBRepManager = fusion.TemporaryBRepManager.get() # findBRepUsingRayの結果が自身のBodyとなる結果が、nodesの30%以上であれば内側面 outerBody: fusion.BRepBody = None face: fusion.BRepFace = None for face in body.faces: meshCalculator: fusion.TriangleMeshCalculator = face.meshManager.createMeshCalculator() meshCalculator.maxAspectRatio = 1 meshCalculator.maxSideLength = 0.1 if face.area < 1 else face.area * 0.1 triMesh: fusion.TriangleMesh = meshCalculator.calculate() nodes = list(triMesh.nodeCoordinates) normals = list(triMesh.normalVectors) limit = int(len(nodes) * 0.3) innerPoints: int = 0 # UsingRayで自身のボディと交差するかチェック for p, v in zip(nodes,normals): v2: core.Vector3D = v.copy() v2.scaleBy(0.01) p2: core.Point3D = p.copy() p2.translateBy(v2) hitBodies = comp.findBRepUsingRay( p2, v, fusion.BRepEntityTypes.BRepBodyEntityType, -1, False, None, ) if hitBodies.count < 1: continue for hitBody in hitBodies: if hitBody.entityToken == body.entityToken: innerPoints += 1 break if innerPoints > limit: break if not innerPoints > limit: # コピー if outerBody: tmpFeat.booleanOperation( outerBody, tmpFeat.copy(face), fusion.BooleanTypes.UnionBooleanType, ) else: outerBody = tmpFeat.copy(face) return outerBody class MyCommandDestroyHandler(core.CommandEventHandler): def __init__(self): super().__init__() def notify(self, args: core.CommandEventArgs): adsk.terminate() def run(context): try: global _app, _ui _app = core.Application.get() _ui = _app.userInterface cmdDef: core.CommandDefinition = _ui.commandDefinitions.itemById( CMD_INFO['id'] ) if not cmdDef: cmdDef = _ui.commandDefinitions.addButtonDefinition( CMD_INFO['id'], CMD_INFO['name'], CMD_INFO['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()))
前回のデータで試すとこんな感じです。


久々にこうしておきます。
"これはいったい何に使うの?" と思われた方には役に立たないでしょうね。