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: 

Move and rotate body at the same time

3 REPLIES 3
SOLVED
Reply
Message 1 of 4
ebunn3
223 Views, 3 Replies

Move and rotate body at the same time

Hi all,

 

I've put together a script called "moveMultBodiesinList" that I would like to use to translate and rotate a body(s) with.  When you run the script I posted below with these variables:  moveMultBodiesinList([body],90,20,0,0,'XY'), it will perform the rotation but not move.  If I set rotation to 0 it will move the body using the x,y,z values.  

 

Can someone tell me why this script will only work for just a rotation, or just a move, but not both at the same time?

 

If you copy and paste the code below into a python module and run it you will see that it rotates the selected body but does not move it.  If you set the rotation to 0 and run it you will see the translation occur.

 

Thanks for the help!!

 

Eric

import adsk.core, adsk.fusion, traceback,math

def selectEnt(msg: str,filtterStr: str) -> adsk.core.Selection:
    try:
        app = adsk.core.Application.get()
        ui = app.userInterface
        sel = ui.selectEntity(msg, filtterStr)
        #get the BRep from the selection (Programming Interface  Fusion 360 API User's Manual  Selection Filters)
        if filtterStr == 'Faces':
            face = adsk.fusion.BRepFace.cast(sel.entity)
            return face
        elif  filtterStr == 'Bodies':
            body = adsk.fusion.BRepBody.cast(sel.entity)
            return body
        elif  filtterStr == 'SolidBodies':
            body = adsk.fusion.BRepBody.cast(sel.entity)
            comp = body.parentComponent
            #comp.saveCopyAs()
            return body
        elif  filtterStr == 'Edges':
            body = adsk.fusion.BRepEdge.cast(sel.entity)
            return body
        elif  filtterStr == 'SketchPoints':
            body = adsk.fusion.SketchPoint.cast(sel.entity)
            return body
        elif  filtterStr == 'Vertices':
            body = adsk.fusion.BRepVertex.cast(sel.entity)
            return body
        elif  filtterStr == 'Occurrences':
            body = adsk.fusion.Occurrence.cast(sel.entity)
            return body
        else:
            return sel
    except:
        return None
    
def GetBB_Mult(bodies):
    """Calculates the bounding box coordinates of the selected objects and returns the following in order:
        X_Min,Y_Min,Z_Min,X_Max,Y_Max,Z_Max,length_X,length_Y,length_Z,mid_X,mid_Y,mid_Z"""
        
    #Set initial values for Max and Min
    MaxDouble = 1.79769313486231e10
    MinDouble = -1.79769313486231e10

    # Initialize to large/small values
    X_Max = MinDouble;X_Min = MaxDouble;Y_Max = MinDouble;Y_Min = MaxDouble;Z_Max = MinDouble;Z_Min = MaxDouble

    for i in bodies:
        #Get Bounding Box
        box = i.boundingBox
        # XMin = box[0][0];YMin = box[0][1];ZMin = box[0][2];XMax = box[6][0];YMax = box[6][1];ZMax = box[6][2]   

        XMin = box.minPoint.x
        YMin = box.minPoint.y
        ZMin = box.minPoint.z
        
        XMax = box.maxPoint.x
        YMax = box.maxPoint.y
        ZMax = box.maxPoint.z 

        #Check for Min/Max Values
        if XMin <= X_Min:
            X_Min = XMin
        if YMin <= Y_Min:
            Y_Min = YMin
        if ZMin <= Z_Min:
            Z_Min = ZMin
        if XMax >= X_Max:
            X_Max = XMax
        if YMax >= Y_Max:
            Y_Max = YMax
        if ZMax >= Z_Max:
            Z_Max = ZMax

    #Calculate L,W,H
    length_X = X_Max - X_Min
    length_Y = Y_Max - Y_Min
    length_Z = Z_Max - Z_Min
    
    #Calc Mid Point
    mid_X = X_Min + ((X_Max-X_Min)/2)
    mid_Y = Y_Min + ((Y_Max-Y_Min)/2)
    mid_Z = Z_Min + ((Z_Max-Z_Min)/2)

    return X_Min,Y_Min,Z_Min,X_Max,Y_Max,Z_Max,length_X,length_Y,length_Z,mid_X,mid_Y,mid_Z

def moveMultBodiesinList(bodLst,angle,x,y,z,refPlane):
    """This function will move a single body. x,y and z should be in cm.
     """
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface

        inputEnts = adsk.core.ObjectCollection.create()

        for body in bodLst:
            inputEnts.add(body)

        #create the Matrix3D
        mat = adsk.core.Matrix3D.create()

        #set the rotation
        angle = math.radians(angle)

        # return X_Min,Y_Min,Z_Min,X_Max,Y_Max,Z_Max,length_X,length_Y,length_Z,mid_X,mid_Y,mid_Z
        BB = GetBB_Mult(bodLst)
        ctr = adsk.core.Point3D.create(BB[9],BB[10],BB[11])

        if refPlane == 'YZ':
            rot = adsk.core.Vector3D.create(1,0,0)
            #define the vector
            if (y != 0.00) or (z != 0.00):
                vector = adsk.core.Vector3D.create(x, y, z)
                mat.translation = vector
        if refPlane == 'XZ':
            rot = adsk.core.Vector3D.create(0,1,0)
            #define the vector
            if (x != 0.00) or (z != 0.00):
                vector = adsk.core.Vector3D.create(x, y, z)
                mat.translation = vector
        if refPlane == 'XY':
            rot = adsk.core.Vector3D.create(0,0,1)
            #define the vector
            if (x != 0.00) or (y != 0.00):
                vector = adsk.core.Vector3D.create(x, y, z)
                mat.translation = vector

        if angle != 0:   
            rotate = mat.setToRotation(angle, rot, ctr)

        #make the move
        try:
            moveInput = body.parentComponent.features.moveFeatures.createInput(inputEnts, mat)
            body.parentComponent.features.moveFeatures.add(moveInput)
        except:
            pass

    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))



# #Select body
body = selectEnt('Select Body','Bodies')

moveMultBodiesinList([body],90,20,0,0,'XY')

 

3 REPLIES 3
Message 2 of 4
Jorge_Jaramillo
in reply to: ebunn3

Hi @ebunn3 ,

 

On line #130, when you use mat.setToRation() it will override any previous settings in the matrix.

You might need to use mat.transformby() instead, in order to rotate what yo have previously defined in the matrix, like so:

        if angle != 0:
            mat_rotation = adsk.core.Matrix3D.create()
            rotate = mat_rotation.setToRotation(angle, rot, ctr)
            mat.transformBy(mat_rotation)

 

Hope this could help.

 

Regards,

Jorge Jaramillo

 

Message 3 of 4
ebunn3
in reply to: Jorge_Jaramillo

 

The TransformBy didn't really work for me since it also transformed the origin in the rotation but I was able to  solve my issues by realizing that I could set up two separate Matrix3D objects, one for the rotation and one for the translation.

 

I do the rotation first followed by the move and it works the way I wanted it too.  Thanks.  Code is below.

 

Eric

 

def moveMultBodiesinList(bodLst,angle,x,y,z,refPlane):
    """This function will move a single body. x,y and z should be in cm.
     """
    ui = None
    try:
        app = adsk.core.Application.get()
        ui  = app.userInterface

        inputEnts = adsk.core.ObjectCollection.create()

        for body in bodLst:
            inputEnts.add(body)

        #set the rotation
        angle = math.radians(angle)

        # return X_Min,Y_Min,Z_Min,X_Max,Y_Max,Z_Max,length_X,length_Y,length_Z,mid_X,mid_Y,mid_Z
        BB = GetBB_Mult(bodLst)
        ctr = adsk.core.Point3D.create(BB[9],BB[10],BB[11])

        #define move vectors based on refPlane
        if refPlane == 'YZ':
            rot = adsk.core.Vector3D.create(1,0,0)
            #define the vector
            if (y != 0.00) or (z != 0.00):
                vector = adsk.core.Vector3D.create(x, y, z)
        if refPlane == 'XZ':
            rot = adsk.core.Vector3D.create(0,1,0)
            #define the vector
            if (x != 0.00) or (z != 0.00):
                vector = adsk.core.Vector3D.create(x, y, z)
        if refPlane == 'XY':
            rot = adsk.core.Vector3D.create(0,0,1)
            #define the vector
            if (x != 0.00) or (y != 0.00):
                vector = adsk.core.Vector3D.create(x, y, z)

        #make the rotation
        if angle != 0:   
            mat_rotation = adsk.core.Matrix3D.create()
            rotate = mat_rotation.setToRotation(angle,rot,ctr)
            try:
                moveInput = body.parentComponent.features.moveFeatures.createInput(inputEnts, mat_rotation)
                body.parentComponent.features.moveFeatures.add(moveInput)
            except:
                pass

        #make the move
        if x!=0.00 or y!= 0.00 or z!= 0.00:
            try:
                matMove = adsk.core.Matrix3D.create()
                matMove.translation = vector
                moveInput = body.parentComponent.features.moveFeatures.createInput(inputEnts, matMove)
                body.parentComponent.features.moveFeatures.add(moveInput)
            except:
                pass
        
    except:
        if ui:
            ui.messageBox('Failed:\n{}'.format(traceback.format_exc()))

 

 

Message 4 of 4
Jorge_Jaramillo
in reply to: ebunn3

hi @ebunn3 ,

The order matters, so you could transform the rotation matrix with the translation to get the result you want, like so:

 

        if angle != 0:
            mat_rotation = adsk.core.Matrix3D.create()
            rotate = mat_rotation.setToRotation(angle, rot, ctr)
            # mat.transformBy(mat_rotation)
            mat_rotation.transformBy(mat)
            mat = mat_rotation

 

Best regards,

Jorge Jaramillo

 

 

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

Post to forums  

Autodesk DevCon in Munich May 28-29th


Autodesk Design & Make Report