ボディと方向を指定した際、方向に対しての最大位置・最小位置に
平面を作るスクリプトを作成しました。
# Author-kantoku # Description-極平面 # Fusion360API Python script import traceback import adsk.fusion import adsk.core _app: adsk.core.Application = None _ui: adsk.core.UserInterface = None _handlers = [] _cmdInfo = { 'id': 'polar_plane', 'name': '極平面', 'tooltip': '指定方向に極平面作成', } _bodyIpt: adsk.core.SelectionCommandInput = None _directionIpt: adsk.core.SelectionCommandInput = None 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())) def getNormalVec( entity) -> adsk.core.Vector3D: def getMat( entity) -> adsk.core.Matrix3D: occ: adsk.fusion.Occurrence = entity.assemblyContext if occ: return occ.transform2 # ***** mat: adsk.core.Matrix3D = getMat(entity) geo = entity.geometry if mat: geo.transformBy(mat) if hasattr(entity, 'worldGeometry'): geo = entity.worldGeometry if hasattr(geo, 'normal'): return geo.normal elif hasattr(geo, 'direction'): return geo.direction elif hasattr(geo, 'asInfiniteLine'): inf: adsk.core.InfiniteLine3D = geo.asInfiniteLine() return inf.direction raise Exception def initPolarPlanes( body: adsk.fusion.BRepBody, direction: adsk.core.Vector3D) -> list: def initConstructionPlane( plane: adsk.core.Plane, constPlanes: adsk.fusion.ConstructionPlanes) -> adsk.fusion.ConstructionPlane: plnIpt: adsk.fusion.ConstructionPlaneInput = constPlanes.createInput() plnIpt.setByPlane(plane) return constPlanes.add(plnIpt) def initVerticalPlanes( bBox: adsk.core.OrientedBoundingBox3D) -> list: lengthLst = [ bBox.height * 0.5, bBox.height * -0.5 ] planes = [] for l in lengthLst: v: adsk.core.Vector3D = bBox.heightDirection.copy() v.scaleBy(l) p: adsk.core.Point3D = bBox.centerPoint.copy() p.translateBy(v) planes.append( adsk.core.Plane.create(p, bBox.heightDirection) ) return planes def getBoundingBox( body: adsk.fusion.BRepBody, direction: adsk.core.Vector3D) -> adsk.core.OrientedBoundingBox3D: plane = adsk.core.Plane = adsk.core.Plane.create( adsk.core.Point3D.create(0,0,0), direction ) app: adsk.core.Application = adsk.core.Application.get() measMgr: adsk.core.MeasureManager = app.measureManager return measMgr.getOrientedBoundingBox( body, plane.vDirection, plane.uDirection ) # **************** # get OrientedBoundingBox bBox: adsk.core.OrientedBoundingBox3D = getBoundingBox( body, direction ) # get Vertical Planes planes = initVerticalPlanes(bBox) # init Construction Planes app: adsk.core.Application = adsk.core.Application.get() des: adsk.fusion.Design = app.activeProduct comp: adsk.fusion.Component = body.parentComponent baseFeat: adsk.fusion.BaseFeature = None if des.designType == adsk.fusion.DesignTypes.ParametricDesignType: baseFeat = comp.features.baseFeatures.add() constPlanes: adsk.fusion.ConstructionPlanes = comp.constructionPlanes resPlanes = [] if baseFeat: baseFeat.startEdit() for pln in planes: resPlanes.append(initConstructionPlane(pln, constPlanes)) baseFeat.finishEdit() else: for pln in planes: resPlanes.append(initConstructionPlane(pln, constPlanes)) return resPlanes class MyInputChangedHandler(adsk.core.InputChangedEventHandler): def __init__(self): super().__init__() def notify(self, args: adsk.core.InputChangedEventArgs): # adsk.core.Application.get().log(args.firingEvent.name) if args.input.classType() != adsk.core.SelectionCommandInput.classType(): return global _bodyIpt, _directionIpt if _bodyIpt.selectionCount < 1: _bodyIpt.hasFocus = True return if _directionIpt.selectionCount < 1: _directionIpt.hasFocus = True class MyExecutePreviewHandler(adsk.core.CommandEventHandler): def __init__(self): super().__init__() def notify(self, args: adsk.core.CommandEventArgs): # adsk.core.Application.get().log(args.firingEvent.name) global _bodyIpt, _directionIpt initPolarPlanes( _bodyIpt.selection(0).entity, getNormalVec(_directionIpt.selection(0).entity) ) args.isValidResult = True class MyPreSelectHandler(adsk.core.SelectionEventHandler): def __init__(self): super().__init__() def notify(self, args: adsk.core.SelectionEventArgs): # adsk.core.Application.get().log(args.firingEvent.name) selIpt: adsk.core.SelectionCommandInput = args.activeInput if selIpt.selectionCount > 0: args.isSelectable = False class MyValidateInputsHandler(adsk.core.ValidateInputsEventHandler): def __init__(self): super().__init__() def notify(self, args: adsk.core.ValidateInputsEventArgs): # adsk.core.Application.get().log(args.firingEvent.name) global _bodyIpt, _directionIpt if _bodyIpt.selectionCount < 1 or _directionIpt.selectionCount < 1: args.areInputsValid = False class MyCommandCreatedHandler(adsk.core.CommandCreatedEventHandler): def __init__(self): super().__init__() def notify(self, args: adsk.core.CommandCreatedEventArgs): # adsk.core.Application.get().log(args.firingEvent.name) try: global _handlers cmd: adsk.core.Command = adsk.core.Command.cast(args.command) # event onDestroy = MyCommandDestroyHandler() cmd.destroy.add(onDestroy) _handlers.append(onDestroy) onInputChanged = MyInputChangedHandler() cmd.inputChanged.add(onInputChanged) _handlers.append(onInputChanged) onExecutePreview = MyExecutePreviewHandler() cmd.executePreview.add(onExecutePreview) _handlers.append(onExecutePreview) onPreSelect = MyPreSelectHandler() cmd.preSelect.add(onPreSelect) _handlers.append(onPreSelect) onValidateInputs = MyValidateInputsHandler() cmd.validateInputs.add(onValidateInputs) _handlers.append(onValidateInputs) # inputs inputs: adsk.core.CommandInputs = cmd.commandInputs global _bodyIpt, _directionIpt _bodyIpt = inputs.addSelectionInput( 'bodyIpt', 'ボディ', 'ボディを選択して下さい' ) _bodyIpt.addSelectionFilter('Bodies') _bodyIpt.setSelectionLimits(0) _directionIpt = inputs.addSelectionInput( 'directionIpt', '方向', '方向となる要素を選択して下さい' ) _directionIpt.addSelectionFilter('SketchLines') _directionIpt.addSelectionFilter('ConstructionLines') _directionIpt.addSelectionFilter('ConstructionPlanes') _directionIpt.addSelectionFilter('LinearEdges') _directionIpt.addSelectionFilter('PlanarFaces') _directionIpt.setSelectionLimits(0) except: _ui.messageBox('Failed:\n{}'.format(traceback.format_exc())) class MyCommandDestroyHandler(adsk.core.CommandEventHandler): def __init__(self): super().__init__() def notify(self, args: adsk.core.CommandEventArgs): # adsk.core.Application.get().log(args.firingEvent.name) adsk.terminate()
ボディ:ソリッド・サーフェス等のボディ(メッシュはNG)
方向:スケッチの直線、構築軸、構築平面、ボディのまっすぐなエッジ、
ボディの平らな面 等
を選択すると、最大位置・最小位置に平面をプレビューします
(相当見えにくい・・・)ので、OKボタンで作成されます。
上記のコードをコピーしこちらの "素のコード" の方法で作成した
ファイルにペーストし実行して頂くと、利用出来ると思います。
Fusion360のスクリプト/アドインの登録 - C#ATIA