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!
by mario malic » Mon Oct 30, 2023 7:07 am
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
Go to full post
Looking for opportunities related to SolidWorks API usage.