Page 1 of 1

Rotation of component in 3D space

Posted: Wed Oct 18, 2023 7:11 am
by mario malic
Hi guys,

I want to place a component in assembly with particular orientation w.r.t. to origin axes. I have managed to successfully rotate a component about 1 axis by getting a RotationMatrix, and applying SetTransformAndSolve3 to the component.

Code: Select all

Function RotXMatrix(ByRef swComp As Component2, ByRef swMathUtil As MathUtility, ByVal angleX As Double) As MathTransform
    
    Dim TransformData() As Double
    ReDim TransformData(0 To 15) As Double
    TransformData(0) = 1 ' X-axis rotational components
    TransformData(1) = 0
    TransformData(2) = 0
    TransformData(3) = 0 ' Y-axis rotational components
    TransformData(4) = Math.Cos(angleX * pi / 180)
    TransformData(5) = Math.Sin(angleX * pi / 180) * (-1)
    TransformData(6) = 0 ' Z-axis rotational components
    TransformData(7) = Math.Sin(angleX * pi / 180)
    TransformData(8) = Math.Cos(angleX * pi / 180)
    TransformData(9) = 0 ' X-translation
    TransformData(10) = 0 ' Y-translation
    TransformData(11) = 0 ' Z-translation
    TransformData(12) = 1 ' Scaling factor
    TransformData(13) = 0 ' Unusued
    TransformData(14) = 0 ' Unusued
    TransformData(15) = 0 ' Unusued
    Dim TransformDataVariant As Variant
    TransformDataVariant = TransformData
    
    Set RotXMatrix = swMathUtil.CreateTransform((TransformDataVariant))
End Function
However, if I would like to place a component in a 3D space, with some arbitrary angle between X, Y and Z axes, how should I do it?
My idea was to get axis rotation matrices for each rotation, and then apply each rotation to component resulting in a correctly placed component, which doesn't happen. It places the component in the last rotation that I called.

Do I have to multiply the matrices (not sure about if the maths between transformations, element-wise, matrix-wise, or if it's even sensible to multiply them) for each rotation and supply them to component with SetTransformAndSolve3?

Thanks!

Re: Rotation of component in 3D space

Posted: Wed Oct 18, 2023 9:25 am
by josh
When you apply a transform to a component, you are not moving it from its current position by the transform, you are applying that transform to the component relative to the origin. So yes, if you are wanting to rotate a component in its current position by certain values, you will need to multiply all your transforms together, as well as multiplying that result by the component’s current transform, then apply the resultant transform to the component. You don’t have to do the matrix math yourself, SW API has MultiplyTransform.

Re: Rotation of component in 3D space

Posted: Mon Oct 30, 2023 7:07 am
by mario malic
Thank you for the reply Josh. I did not really understand the issue at the time when I was posting the question. I thought, if I rotate the component 45°w.r.t. assembly X-axis, followed by 45°w.r.t. assembly Y-axis, followed by 45°w.r.t. assembly Z-axis, the component will be oriented by that angle w.r.t. all axes, which is impossible.

I came up with a macro that orientates the desired component axis to be collinear with the desired vector and moves its origin to the desired coordinates in assembly.

Code: Select all

Function TransformComponent(ByRef swComp As Component2, ByRef swMath As MathUtility, ByRef swInitVec As MathVector, ByRef swFinalVec As MathVector, ByRef swOriginVec As MathVector, ByVal scaleVal As Double) As MathTransform
    ' INPUT:
    '   swComp - component to be transformed
    '   swMath - SW math utility
    '   swInitVec - vector to align to final vector
    '   swFinalVec - vector to align the initial vector to
    '   swOriginVec - vector with desired component origin
    '   scaleVal - scaling factor
    
    ' OUTPUT:
    '    TransformComponent - MathTransform for component
    
    ' Get unit vectors
    Set swInitVec = swInitVec.Normalise
    Set swFinalVec = swFinalVec.Normalise
    
    ' Component rotation
    Dim swPoint As MathPoint
    Dim pt(2) As Double: pt(0) = 0#: pt(1) = 0#: pt(2) = 0#
    Dim ptVar As Variant: ptVar = pt
    Set swPoint = swMath.CreatePoint(pt)
    
    Dim dAngle, dotProd As Double
    Dim swVec As MathVector
        
    Set swVec = swFinalVec.Cross(swInitVec) ' Vector axis to rotate initial vector by an angle
    dotProd = swInitVec.Dot(swFinalVec)
    dAngle = Arccos(dotProd) * (-1)
    Dim tol As Double: tol = 0.001
    
    ' Component rotation
    Dim swXformRot As MathTransform
    If (swVec.GetLength <= tol) Then  ' Case where vectors are opposite of each other, we need a crossproduct of initial and X-axes vector
        Dim swCaseVec As MathVector
        Dim swXvec As MathVector
        Dim xVec(2) As Double: xVec(0) = 1#: xVec(1) = 0#: xVec(2) = 0#
        Dim xVecVar As Variant: xVecVar = xVec
        Set swXvec = swMath.CreateVector(xVec)
        Set swCaseVec = swInitVec.Cross(swXvec)
        Set swXformRot = swMath.CreateTransformRotateAxis(swPoint, swCaseVec, dAngle) ' Applying rotation transform
    Else
        Set swXformRot = swMath.CreateTransformRotateAxis(swPoint, swVec, dAngle) ' Applying rotation transform
    End If
    
    ' Add component translation
    Dim xformMatrix As Variant
    Dim originVec As Variant
    xformMatrix = swXformRot.ArrayData
    originVec = swOriginVec.ArrayData
    xformMatrix(9) = originVec(0) ' X-origin
    xformMatrix(10) = originVec(1) ' Y-origin
    xformMatrix(11) = originVec(2) ' Z-origin
    xformMatrix(12) = scaleVal
    swXformRot.ArrayData = xformMatrix
    
    Set TransformComponent = swXformRot
    
End Function