Calculating rotation transformation to align component with direction
This VBA example demonstrates how to use the IMathUtility::CreateTransformRotateAxis SOLIDWORKS API to rotate the component and align the normal of its face with the direction from the linear edge.
As a precondition select the planar face on the first component in the assembly and linear edge on the second component in the assembly. First component must not be fixed and do not have any mates. As the result first component rotated in a way that its normal is collinear with the direction of the edge. Component is rotated around the origin.
Explanation
In order to transform the component in the expected way it is required to calculate its transform. For that it is required to find the origin of rotation, rotation vector and an angle.
At first we create vectors of the face normal and edge direction. It is required to apply the transformation of the components to represent vectors in the same coordinate system. The angle between those vectors is a required angle of transformation.
In order to find the vector of rotation it is required to find the vector perpendicular to both normal and direction. This can be achieved by finding the cross product.
Finally point of rotation is an origin of the component transformed to the assembly coordinate system.
Dim swApp As SldWorks.SldWorks
Sub main()
Set swApp = Application.SldWorks
Dim swModel As SldWorks.ModelDoc2
Set swModel = swApp.ActiveDoc
Dim swSelMgr As SldWorks.SelectionMgr
Set swSelMgr = swModel.SelectionManager
Dim swFace As SldWorks.Face2
Dim swEdge As SldWorks.Edge
Set swFace = swSelMgr.GetSelectedObject6(1, -1)
Dim swComp As SldWorks.Component2
Set swComp = swFace.GetComponent()
Dim swCompTransform As SldWorks.MathTransform
Set swCompTransform = swComp.Transform2
Set swEdge = swSelMgr.GetSelectedObject6(2, -1)
Dim swMathUtils As SldWorks.MathUtility
Set swMathUtils = swApp.GetMathUtility
Dim swNormalDir As SldWorks.MathVector
Set swNormalDir = swMathUtils.CreateVector(swFace.Normal)
Set swNormalDir = swNormalDir.MultiplyTransform(swCompTransform)
Dim swAlignDir As SldWorks.MathVector
Dim vLineParams As Variant
vLineParams = swEdge.GetCurve().lineParams
Dim dVec(2) As Double
dVec(0) = vLineParams(3): dVec(1) = vLineParams(4): dVec(2) = vLineParams(5)
Set swAlignDir = swMathUtils.CreateVector(dVec)
Set swAlignDir = swAlignDir.MultiplyTransform(swEdge.GetComponent().Transform2)
Dim swOrigin As SldWorks.MathPoint
Dim dOrigin(2) As Double
dOrigin(0) = 0: dOrigin(1) = 0: dOrigin(2) = 0
Set swOrigin = swMathUtils.CreatePoint(dOrigin)
Set swOrigin = swOrigin.MultiplyTransform(swCompTransform)
Dim swRotVect As SldWorks.MathVector
Set swRotVect = swNormalDir.Cross(swAlignDir)
Dim angle As Double
angle = GetAngle(swNormalDir, swAlignDir)
Dim swTransform As SldWorks.MathTransform
Set swTransform = swMathUtils.CreateTransformRotateAxis(swOrigin, swRotVect, angle)
Set swTransform = swCompTransform.Multiply(swTransform)
swComp.Transform2 = swTransform
swModel.GraphicsRedraw2
End Sub
Function GetAngle(vec1 As MathVector, vec2 As MathVector) As Double
'cos a= a*b/(|a|*|b|)
GetAngle = ACos(vec1.Dot(vec2) / (vec1.GetLength() * vec2.GetLength()))
End Function
Function ACos(val As Double) As Double
If val = 1 Then
ACos = 0
ElseIf val = -1 Then
ACos = 4 * Atn(1)
Else
ACos = Atn(-val / Sqr(-val * val + 1)) + 2 * Atn(1)
End If
End Function