Move and rotate body at the same time

Move and rotate body at the same time

ebunn3
Advocate Advocate
905 Views
3 Replies
Message 1 of 4

Move and rotate body at the same time

ebunn3
Advocate
Advocate

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')

 

0 Likes
Accepted solutions (1)
906 Views
3 Replies
Replies (3)
Message 2 of 4

Jorge_Jaramillo
Collaborator
Collaborator
Accepted solution

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
Advocate
Advocate

 

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()))

 

 

0 Likes
Message 4 of 4

Jorge_Jaramillo
Collaborator
Collaborator

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

 

 

0 Likes