Cutting multiple bodies with single tool body

Cutting multiple bodies with single tool body

cmcampbellNDCUJ
Enthusiast Enthusiast
692 Views
6 Replies
Message 1 of 7

Cutting multiple bodies with single tool body

cmcampbellNDCUJ
Enthusiast
Enthusiast

I am looking for a way to cut all the bodies within a given component or assembly with a single tool body. The combine function will easily let me cut target bodies one at a time but in this case I'm looking to cut hundreds of target bodies with just a handful of tool bodies. Any help will be greatly appreciated.

 

0 Likes
Accepted solutions (1)
693 Views
6 Replies
Replies (6)
Message 2 of 7

kandennti
Mentor
Mentor
Accepted solution

Hi @cmcampbellNDCUJ -San.

 

I have tried to create it, but since I have only tested it with simple data, errors may occur.

# Fusion360API Python script

import traceback
import adsk
import adsk.core as core
import adsk.fusion as fusion
import sys

_app: core.Application = None
_ui: core.UserInterface = None
_handlers = []

CMD_INFO = {
    "id": "kantoku_cutting_multiple_bodies_test",
    "name": "cutting multiple bodies test",
    "tooltip": "cutting multiple bodies test"
}

_targetOccIpt: core.SelectionCommandInput = None
_toolBodyIpt: core.SelectionCommandInput = None

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)
            inputs: core.CommandInputs = cmd.commandInputs

            onDestroy = MyCommandDestroyHandler()
            cmd.destroy.add(onDestroy)
            _handlers.append(onDestroy)

            onValidateInputs = MyValidateInputsHandler()
            cmd.validateInputs.add(onValidateInputs)
            _handlers.append(onValidateInputs)

            onExecutePreview = MyExecutePreviewHandler()
            cmd.executePreview.add(onExecutePreview)
            _handlers.append(onExecutePreview)

            global _targetOccIpt
            _targetOccIpt = inputs.addSelectionInput(
                "_targetOccIptId",
                "Occurrences",
                "Select Target Occcurrence"
            )
            _targetOccIpt.addSelectionFilter("Occurrences")
            _targetOccIpt.setSelectionLimits(1,)

            global _toolBodyIpt
            _toolBodyIpt = inputs.addSelectionInput(
                "_toolBodyIptId",
                "Tool Body",
                "Select Tool Body"
            )
            _toolBodyIpt.addSelectionFilter("SolidBodies")

        except:
            _ui.messageBox("Failed:\n{}".format(traceback.format_exc()))


class MyExecutePreviewHandler(core.CommandEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args: core.CommandEventArgs):
        global _targetOccIpt
        occs = []
        for idx in range(_targetOccIpt.selectionCount):
            occs.append(_targetOccIpt.selection(idx).entity)

        global _toolBodyIpt
        exec_combines(
            occs,
            _toolBodyIpt.selection(0).entity
        )

        args.isValidResult = True


def exec_combines(
        targetOccs: list[fusion.Occurrence],
        toolBody: fusion.BRepBody,
) -> None:
    try:
        bodies = get_occurrences_has_bodies(
            targetOccs,
            get_show_bodies(),
        )
        if len(bodies) < 1: return

        exec_combine_diff(
            bodies,
            toolBody,
        )
    except:
        _ui.messageBox("Failed:\n{}".format(traceback.format_exc()))


def exec_combine_diff(
        bodies: list[fusion.BRepBody],
        toolBody: fusion.BRepBody,
) -> None:
    try:
        global _app
        des: fusion.Design = _app.activeProduct
        root: fusion.Component = des.rootComponent

        combFeats: fusion.CombineFeatures = root.features.combineFeatures
        for body in bodies:
            if body == toolBody: continue

            combIpt: fusion.CombineFeatureInput = combFeats.createInput(
                body,
                core.ObjectCollection.createWithArray(
                    [toolBody]
                ),
            )
            combIpt.operation = fusion.FeatureOperations.CutFeatureOperation
            combIpt.isKeepToolBodies = True

            combFeats.add(combIpt)

        toolBody.isLightBulbOn = False

    except:
        _ui.messageBox("Failed:\n{}".format(traceback.format_exc()))

def get_occurrences_has_bodies(
        targetOccs: list[fusion.Occurrence],
        bodies: list[fusion.BRepBody],
) -> list[fusion.BRepBody]:
    
    bodyLst = []
    for body in bodies:
        if body.assemblyContext in targetOccs:
            bodyLst.append(body)

    return bodyLst


def get_show_bodies() -> list[fusion.BRepBody]:
    global _app
    des: fusion.Design = _app.activeProduct
    root: fusion.Component = des.rootComponent

    showBodies = root.findBRepUsingPoint(
        core.Point3D.create(0,0,0),
        fusion.BRepEntityTypes.BRepBodyEntityType,
        sys.float_info.max,
        True,
    )

    return list(showBodies)


class MyValidateInputsHandler(core.ValidateInputsEventHandler):
    def __init__(self):
        super().__init__()
    def notify(self, args: core.ValidateInputsEventArgs):
        global _targetOccIpt
        if _targetOccIpt.selectionCount < 1:
            args.areInputsValid = False
            return

        global _toolBodyIpt
        if _toolBodyIpt.selectionCount < 1:
            args.areInputsValid = False
            return


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()))
Message 3 of 7

cmcampbellNDCUJ
Enthusiast
Enthusiast

Thanks @kandennti I'll give this a try and let you know how it goes. 

Message 4 of 7

cmcampbellNDCUJ
Enthusiast
Enthusiast

Hi @kandennti,

Your script worked perfectly!

Many thanks.

Message 5 of 7

kearlyHQ5QE
Observer
Observer

I used this script successfully a week or so ago (it worked great!).  All of a sudden it quit working.  There was an update to Fusion 360 since the last time I used it.  Could something have changed that makes it not work?

0 Likes
Message 6 of 7

BrianEkins
Mentor
Mentor

Nothing should have changed. Do you have an example that used to work that is failing now?

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com
0 Likes
Message 7 of 7

kearlyHQ5QE
Observer
Observer

Actually, it is still working, what I did not realize (remember) is that each of the Target bodies must be a separate Component... It would be good if Fusion 360 would make selection of multiple Target Bodies possible in the Combine function similar to like it can with the Split Body function... Thank you for your reply

0 Likes