Rotate object to be perpendicular to a selected CircularEdge plane

Rotate object to be perpendicular to a selected CircularEdge plane

ll100avgas
Observer Observer
459 Views
1 Reply
Message 1 of 2

Rotate object to be perpendicular to a selected CircularEdge plane

ll100avgas
Observer
Observer

Hi,

 

I'm trying to create a script that places screw instances to the list of selected screw holes on a body. Currently it can find the hole pivot (origin) and can put the screw into that. Currently it works if the screw is parallel to the hole. If the whole has an angle with the screw the script puts the screw in a wrong direction.

 

Here is the code I have currently:

 

                    command = args.firingEvent.sender
                    eventArgs = adsk.core.CommandEventArgs.cast(args)

                    # Get the values from the command inputs. 
                    inputs = eventArgs.command.commandInputs

                    numberOfSelectedEdge = inputs.itemById(edgeSelectionInputId).selectionCount
                    # screw:
                    selectedBodyToInstantiate = inputs.itemById(bodySelectionInputId).selection(0).entity
                    # holes to put screw:
                    selectedEdges = []
                    for i in range (0, numberOfSelectedEdge ):
                        selectedEdges.append(inputs.itemById(edgeSelectionInputId).selection(i).entity)
                    
                    #ui.messageBox(('selected: {} ').format(selectedEdges))

                    for edge in selectedEdges:
                        ent = edge

                        circGeom = ent.geometry
                
                        center = getCircleGeometryInfo(circGeom)

                        # The second point is defined using a known coordinate.
                        p = selectedBodyToInstantiate.transform.translation
                        pnt1 = adsk.core.Point3D.create(p.x, p.y, p.z)
                        pnt2 = adsk.core.Point3D.create(center.x, center.y, center.z)

                        # Create a matrix that defines the translation from point 1 to point 2.
                        trans: adsk.core.Matrix3D = adsk.core.Matrix3D.create()
                        trans.translation = pnt1.vectorTo(pnt2)

                        addResult = design.activeComponent.occurrences.addExistingComponent(selectedBodyToInstantiate.component, trans)

 

This places the screw to the pivot (center) of circle, but as you can see in the attachment, the angle is wrong. My plan is to calculate a vector that is perpendicular to the CircularEdge plane (so a vector that goes through the hole). Then pick the same for the screw (ie. picking the CircularEdge under the screw head) calculate that vector as well, and transform the second one to the first one somehow to take the rotation. This sounds easy, but I do not know where to start, I'm not familiar with the API...

 

(the whole stuff is needed because the Align described here: https://forums.autodesk.com/t5/fusion-360-api-and-scripts/api-access-to-align-components-function/td... works only for two selection, and I cannot find the programmatical way of joining/aligning two objects in Fusion 360)

 

Thanks for your help!

0 Likes
460 Views
1 Reply
Reply (1)
Message 2 of 2

BrianEkins
Mentor
Mentor

The code below replaces your for loop where it builds a matrix for each bolt. It does this by getting the planar face the edge connects to and using the normal of that face as the Z-axis. It then creates arbitrary Y and Z axes but makes sure they are perpendicular to each other, that they define a right-handed coordinate system, and are unit vectors. It then creates a matrix using this data and uses that matrix to place the bolt. You might need to adjust this depending on how your bolt is defined. For mine, the Z-axis comes out of the head of the bolt, and the origin is at the base where the shaft meets the head.

 

edge: adsk.fusion.BRepEdge = None
for edge in selectedEdges:
    # Get the planar face for the edge.
    planeFace: adsk.fusion.BRepFace = None
    if edge.faces.item(0).geometry.objectType == adsk.core.Plane.classType():
        planeFace = edge.faces.item(0)
    elif edge.faces.item(1).geometry.objectType == adsk.core.Plane.classType():
        planeFace = edge.faces.item(1)

    # Get the normal from the face.
    zVec: adsk.core.Vector3D = None
    (_, zVec) = planeFace.evaluator.getNormalAtPoint(planeFace.pointOnFace)

    # Create an arbitrary vector that is different than the normal. This will
    # be used to define the X axis.
    tempY = adsk.core.Vector3D.create(zVec.x + 1, zVec.y + 2, zVec.z + 3)
    xVec = zVec.crossProduct(tempY)
    xVec.normalize()
    yVec = zVec.crossProduct(xVec)

    circGeom: adsk.core.Circle3D = edge.geometry
    origin = circGeom.center

    trans = adsk.core.Matrix3D.create()
    trans.setWithCoordinateSystem(origin, xVec, yVec, zVec)

    bolt = root.occurrences.addExistingComponent(boltComp, trans)

 

Here's an image illustrating the origin of the bolt and an example part where I picked several edges in different orientations and it correctly positioned the bolt.

 

Bolt.png

 

 

---------------------------------------------------------------
Brian Ekins
Inventor and Fusion 360 API Expert
Website/Blog: https://EkinsSolutions.com