Community
Fusion API and Scripts
Got a new add-in to share? Need something specialized to be scripted? Ask questions or share what you’ve discovered with the community.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Moving a BrepBody with a triad command input

2 REPLIES 2
SOLVED
Reply
Message 1 of 3
Joshua.mursic
182 Views, 2 Replies

Moving a BrepBody with a triad command input

I'm am trying to create a simple command to move a Brep body inside a component that will snap a triad to the center of the selected cylinder. I am not sure what I am doing wrong, the translation works correctly but when I try to rotate, it behaves unexpectedly.

 

import adsk.core,adsk.fusion,adsk.cam,traceback
from ...lib import fusion360utils as futil

app = adsk.core.Application.get()
ui = app.userInterface

local_handlers = []
activeBody:adsk.fusion.BRepBody = None

         
def command_created(args: adsk.core.CommandCreatedEventArgs):
    '''Function that is called when a user clicks the corresponding button in the UI. This defines the contents of the command dialog and connects to the command related events.'''
    cmd = args.command
    inputs = cmd.commandInputs
    cmd.setDialogSize(300,0)
    cmd.isPositionDependent = True

    selection = inputs.addSelectionInput("brepSelector","Part Selection","")
    selection.addSelectionFilter("SolidBodies")
    selection.setSelectionLimits(1,1)

    #Triad Control
    triad = cmd.commandInputs.addTriadCommandInput("partTransformer",adsk.core.Matrix3D.create())
    triad.setFullVisibility(False)
    triad.setPlanarMoveVisibility(True)
    triad.setRotateVisibility(True)

    futil.add_handler(args.command.execute, command_execute, local_handlers=local_handlers)
    futil.add_handler(args.command.destroy, command_destroy, local_handlers=local_handlers)
    futil.add_handler(args.command.executePreview, command_preview, local_handlers=local_handlers)
    futil.add_handler(args.command.inputChanged, command_inputChanged, local_handlers=local_handlers)

def command_execute(args: adsk.core.CommandEventArgs):
    global activeBody
    triad:adsk.core.TriadCommandInput = args.command.commandInputs.itemById("partTransformer")
    move = activeBody.parentComponent.features.moveFeatures
    objects = adsk.core.ObjectCollection.create()
    objects.add(activeBody)
    moveInput = move.createInput2(objects)
    moveInput.defineAsFreeMove(triad.transform)
    move.add(moveInput)

def command_inputChanged(args: adsk.core.InputChangedEventArgs):
    global activeBody
    inputs = args.inputs
    triad:adsk.core.TriadCommandInput = inputs.itemById("partTransformer")
    selector:adsk.core.SelectionCommandInput = inputs.itemById("brepSelector")

    #get the selected cylinder and position the traid on the center 
    if args.input == selector:
        selectedBody = selector.selection(0).entity
        if selectedBody != activeBody:
            activeBody = selectedBody
            for face in activeBody.faces:
                if face.geometry.surfaceType == adsk.core.SurfaceTypes.CylinderSurfaceType:
                    cylinderFace = face
                if face.geometry.surfaceType == adsk.core.SurfaceTypes.PlaneSurfaceType:
                    app.log("found flat")
                    planeFace = face
            origin = cylinderFace.centroid
            vector = planeFace.geometry.evaluator.getNormalAtPoint(planeFace.centroid)[1]
            mat = adsk.core.Matrix3D.create()
            mat.setToRotateTo(adsk.core.Vector3D.create(0,0,1),vector)
            mat.translation = adsk.core.Point3D.create(0,0,0).vectorTo(origin)
            triad.transform = mat
    
def command_preview(args: adsk.core.CommandEventArgs):
    global activeBody
    try:
        triad:adsk.core.TriadCommandInput = args.command.commandInputs.itemById("partTransformer")
        #get the change that occurred in the triad
        fo,fx,fy,fz = triad.lastTransform.getAsCoordinateSystem()
        to,tx,ty,tz = triad.transform.getAsCoordinateSystem()
        transform = adsk.core.Matrix3D.create()
        transform.setToAlignCoordinateSystems(fo,fx,fy,fz,to,tx,ty,tz)

        #move the activeBody by the transform
        move = activeBody.parentComponent.features.moveFeatures
        objects = adsk.core.ObjectCollection.create()
        objects.add(activeBody)
        moveInput = move.createInput2(objects)
        moveInput.defineAsFreeMove(transform)
        move.add(moveInput)

        #Reposition the triad on the center of the cylinder
        for face in activeBody.faces:
            if face.geometry.surfaceType == adsk.core.SurfaceTypes.CylinderSurfaceType:
                cylinderFace = face
            if face.geometry.surfaceType == adsk.core.SurfaceTypes.PlaneSurfaceType:
                planeFace = face
        origin = cylinderFace.centroid
        vector = planeFace.centroid.vectorTo(origin)
        mat = adsk.core.Matrix3D.create()
        mat.setToRotateTo(adsk.core.Vector3D.create(0,0,1),vector)
        mat.translation = adsk.core.Point3D.create(0,0,0).vectorTo(origin)
        triad.transform = mat
        
    except:
        app.log('Failed:\n{}'.format(traceback.format_exc()))

def command_destroy(args: adsk.core.CommandEventArgs):
    global local_handlers,activeBody
    local_handlers = []
    activeBody = None
    app.log("Complete")



    

 

2 REPLIES 2
Message 2 of 3
kandennti
in reply to: Joshua.mursic

Hi @Joshua.mursic -San.

 

The cause is the transaction of the executePreview event.
After moving and then rotating, it appears to be reverting back to its pre-move state.

If you record and use the matrix3D when the body is selected, you should be able to get the desired movement.


# Matrix3D when body is selected
_mat: adsk.core.Matrix3D = None

def command_created(args: adsk.core.CommandCreatedEventArgs):
    '''Function that is called when a user clicks the corresponding button in the UI. This defines the contents of the command dialog and connects to the command related events.'''
    cmd = args.command
    inputs = cmd.commandInputs
    cmd.setDialogSize(300,0)
    cmd.isPositionDependent = True

    selection = inputs.addSelectionInput("brepSelector","Part Selection","")
    selection.addSelectionFilter("SolidBodies")
    selection.setSelectionLimits(1,1)

    #Triad Control
    triad = cmd.commandInputs.addTriadCommandInput("partTransformer",adsk.core.Matrix3D.create())
    triad.setFullVisibility(False)
    triad.setPlanarMoveVisibility(True)
    triad.setRotateVisibility(True)

    # futil.add_handler(args.command.execute, command_execute, local_handlers=local_handlers)
    futil.add_handler(args.command.destroy, command_destroy, local_handlers=local_handlers)
    futil.add_handler(args.command.executePreview, command_preview, local_handlers=local_handlers)
    futil.add_handler(args.command.inputChanged, command_inputChanged, local_handlers=local_handlers)

# def command_execute(args: adsk.core.CommandEventArgs):
#     global activeBody
#     triad:adsk.core.TriadCommandInput = args.command.commandInputs.itemById("partTransformer")
#     move = activeBody.parentComponent.features.moveFeatures
#     objects = adsk.core.ObjectCollection.create()
#     objects.add(activeBody)
#     moveInput = move.createInput2(objects)
#     moveInput.defineAsFreeMove(triad.transform)
#     move.add(moveInput)

def command_inputChanged(args: adsk.core.InputChangedEventArgs):
    global activeBody
    inputs = args.inputs
    triad:adsk.core.TriadCommandInput = inputs.itemById("partTransformer")
    selector:adsk.core.SelectionCommandInput = inputs.itemById("brepSelector")

    #get the selected cylinder and position the traid on the center 
    if args.input == selector:
        selectedBody = selector.selection(0).entity
        if selectedBody != activeBody:
            activeBody = selectedBody
            for face in activeBody.faces:
                if face.geometry.surfaceType == adsk.core.SurfaceTypes.CylinderSurfaceType:
                    cylinderFace = face
                if face.geometry.surfaceType == adsk.core.SurfaceTypes.PlaneSurfaceType:
                    app.log("found flat")
                    planeFace = face
            origin = cylinderFace.centroid
            vector = planeFace.geometry.evaluator.getNormalAtPoint(planeFace.centroid)[1]
            mat = adsk.core.Matrix3D.create()
            mat.setToRotateTo(adsk.core.Vector3D.create(0,0,1),vector)
            mat.translation = adsk.core.Point3D.create(0,0,0).vectorTo(origin)
            triad.transform = mat
            global _mat
            _mat = mat
    
def command_preview(args: adsk.core.CommandEventArgs):
    global activeBody
    try:
        triad:adsk.core.TriadCommandInput = args.command.commandInputs.itemById("partTransformer")
        #get the change that occurred in the triad
        # fo,fx,fy,fz = triad.lastTransform.getAsCoordinateSystem()
        global _mat
        fo,fx,fy,fz = _mat.getAsCoordinateSystem()
        to,tx,ty,tz = triad.transform.getAsCoordinateSystem()
        transform = adsk.core.Matrix3D.create()
        transform.setToAlignCoordinateSystems(fo,fx,fy,fz,to,tx,ty,tz)

        #move the activeBody by the transform
        move = activeBody.parentComponent.features.moveFeatures
        objects = adsk.core.ObjectCollection.create()
        objects.add(activeBody)
        moveInput = move.createInput2(objects)
        moveInput.defineAsFreeMove(transform)
        move.add(moveInput)

        #Reposition the triad on the center of the cylinder
        for face in activeBody.faces:
            if face.geometry.surfaceType == adsk.core.SurfaceTypes.CylinderSurfaceType:
                cylinderFace = face
            if face.geometry.surfaceType == adsk.core.SurfaceTypes.PlaneSurfaceType:
                planeFace = face
        origin = cylinderFace.centroid
        vector = planeFace.centroid.vectorTo(origin)
        mat = adsk.core.Matrix3D.create()
        mat.setToRotateTo(adsk.core.Vector3D.create(0,0,1),vector)
        mat.translation = adsk.core.Point3D.create(0,0,0).vectorTo(origin)
        triad.transform = mat

        args.isValidResult = True

    except:
        app.log('Failed:\n{}'.format(traceback.format_exc()))

def command_destroy(args: adsk.core.CommandEventArgs):
    global local_handlers,activeBody
    local_handlers = []
    activeBody = None
    app.log("Complete")
Message 3 of 3
Joshua.mursic
in reply to: kandennti

Thank you @kandennti, very much appreciated.

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Design & Make Report