Reset Component Position

Reset Component Position

When working with assembly files, moving components around in space, there may come a time when you want to reset a component to its absolute starting point; the position where it would appear when adding it with the "absolute position" option. There are various work-arounds in NX to get a component back to its absolute position, but out-of-the-box there is no one click solution - we'll have to make our own.

Component translations and rotations

The assembly file keeps track of each component's location and orientation. You can see how a component has been moved around at any time by using the "information -> object" command and selecting the component; in the information window, the translation and rotation will be reported. When you add a component with the "absolute origin" positioning option, the absolute coordinate system of the component part will align to the absolute coordinate system of the assembly part. If the component has not been moved, the component translation delta X, Y, and Z values will be zero, the X-axis vector rotation will be (1,0,0), the Y-axis vector rotation will be (0,1,0), and the Z-axis vector rotation will be (0,0,1) as shown below.

component position report

If you rotate the component by 30° about the X axis, the rotation vectors will be reported as shown below.

component rotation report

The delta X, Y, and Z values are easy enough to understand, but what's going on with the rotation vectors? The mathematicians in the crowd may recognize the previous values as the sine and cosine of a 30° angle. When you put the rotation angle vectors together, you get a rotation matrix. This rotation matrix is defined in terms of the sine and cosine values of the rotation angles. Defining the rotations in matrix notation this way has several advantages, most of which are beyond the scope of this article. For more information, the rotation matrix article on wikipedia is a great place to start.

The component's location and rotation information is easily accessible through the NXOpen API. With this information, it isn't too much trouble to move the component back to the absolute position. All we need to do is find a matrix that is the inverse of the current rotation matrix, rotate the component according to this new rotation matrix, then translate the component back to the origin. You may be thinking "matrix inverse? I'm outta here...", but wait a moment, because I see the mathematician smiling. Why is he smiling, does the thought of L-U decomposition get his blood racing? Well, possibly; but I think he knows a trick that will make this problem easier than it sounds...

Mathematician

Your rotation matrix contains 3 rows and 3 columns; this makes it a square matrix. One of the useful properties of a square matrix is that the inverse is the same as the transpose.

If the term "matrix inverse" made you instinctively reach for your favorite headache medicine, rest assured that performing a matrix transpose is much easier than finding the inverse. This property of square matrices will really come in handy for this journal. The transpose really is the trickiest part of this journal; it is not tricky in the sense of being difficult, but rather it is easy to make an error while typing which would result in a difficult to track down bug in our code.

To perform the transpose, we simply have to switch the row and column values in the matrix. So the following matrix:

1 2 3
4 5 6
7 8 9

becomes:
1 4 7
2 5 8
3 6 9

You can see how the values in the first column (1, 4, 7) become the values in the first row. Repeat for the other two columns and you end up with the transpose, which in our case is also the matrix inverse.

The Code

Option Strict Off
 
Imports System
Imports NXOpen
Imports NXOpen.UF
Imports NXOpenUI
 
Module componentOriginalPosition
 
	Dim theSession As Session = Session.GetSession()
	Dim workPart As Part = theSession.Parts.Work
 
	Sub Main()
 
        Dim selComp As NXOpen.Assemblies.Component = Nothing
        If SelectComponent(selComp) = Selection.Response.Cancel Then
            Exit Sub
        End If
 
        Dim myInterpartDelay As Boolean = theSession.UpdateManager.InterpartDelay
 
        Dim pt As Point3d
        Dim RotMat As Matrix3x3
 
        Dim pt2 As Vector3d
        Dim RotMat2 As Matrix3x3
 
        selComp.GetPosition(pt, RotMat)
        'msgbox("Translation: " & pt.x & ", " & pt.y & ", " & pt.z)
        'msgbox("Rotation: " & vbcrlf & _
        '	RotMat.xx & ", " & RotMat.xy & ", " & RotMat.xz & vbcrlf & _
        '	RotMat.yx & ", " & RotMat.yy & ", " & RotMat.yz & vbcrlf & _
        '	RotMat.zx & ", " & RotMat.zy & ", " & RotMat.zz)
 
        'no translation of component on first pass
        pt2.X = 0
        pt2.Y = 0
        pt2.Z = 0
 
        'transpose of the rotation matrix, undo any rotations on the component
        RotMat2.Xx = RotMat.Xx
        RotMat2.Xy = RotMat.Yx
        RotMat2.Xz = RotMat.Zx
        RotMat2.Yx = RotMat.Xy
        RotMat2.Yy = RotMat.Yy
        RotMat2.Yz = RotMat.Zy
        RotMat2.Zx = RotMat.Xz
        RotMat2.Zy = RotMat.Yz
        RotMat2.Zz = RotMat.Zz
 
        'avoid problems if the part contains wave links or other interpart data
        theSession.UpdateManager.InterpartDelay = True
 
        'move the component back to the original rotation
        workPart.ComponentAssembly.MoveComponent(selComp, pt2, RotMat2)
 
        'get the translation information again, now that the component has been rotated back to absolute
        selComp.GetPosition(pt, RotMat)
 
        'negate the translations that have been applied to the component
        pt2.X = -pt.X
        pt2.Y = -pt.Y
        pt2.Z = -pt.Z
 
        'set rotation matrix to identity matrix, we want no new rotations on the component
        'or simply use RotMat returned from GetPosition, as it will be the identity matrix
        'after the component has been rotated back to its original position
        RotMat2.Xx = 1
        RotMat2.Xy = 0
        RotMat2.Xz = 0
        RotMat2.Yx = 0
        RotMat2.Yy = 1
        RotMat2.Yz = 0
        RotMat2.Zx = 0
        RotMat2.Zy = 0
        RotMat2.Zz = 1
 
        'translate component back to 0,0,0
        workPart.ComponentAssembly.MoveComponent(selComp, pt2, RotMat2)
 
        'reset interpart delay to original value
        theSession.UpdateManager.InterpartDelay = myInterpartDelay
 
	End Sub
 
    Function SelectComponent(ByRef selObj As TaggedObject) As Selection.Response
 
        Dim theUI As UI = UI.GetUI
        Dim message As String = "Select component to reset position"
        Dim title As String = "Select a Component"
        Dim includeFeatures As Boolean = False
        Dim keepHighlighted As Boolean = False
        Dim selAction As Selection.SelectionAction = Selection.SelectionAction.ClearAndEnableSpecific
        Dim cursor As Point3d
        Dim scope As Selection.SelectionScope = Selection.SelectionScope.AnyInAssembly
        Dim selectionMask_array(0) As Selection.MaskTriple
 
        With selectionMask_array(0)
            .Type = UFConstants.UF_component_type
            .Subtype = UFConstants.UF_all_subtype
        End With
 
        Dim resp As Selection.Response = theUI.SelectionManager.SelectTaggedObject(message, _
         title, scope, selAction, _
         includeFeatures, keepHighlighted, selectionMask_array, _
         selObj, cursor)
        If resp = Selection.Response.ObjectSelected OrElse resp = Selection.Response.ObjectSelectedByName Then
            Return Selection.Response.Ok
        Else
            Return Selection.Response.Cancel
        End If
 
    End Function
 
    Public Function GetUnloadOption(ByVal dummy As String) As Integer
        GetUnloadOption = NXOpen.UF.UFConstants.UF_UNLOAD_IMMEDIATELY
    End Function
 
End Module

Conclusion

In this article we looked at how to get the component's location and orientation information. We then used that information to move the component back to the absolute origin. You've also seen how to use the .MoveComponent method and how to temporarily turn off the interpart update option. Hopefully, these methods will come in handy when creating your own journals.

Notes:
1) The code above is meant to be used on components that do not have constraints applied to them. If the journal is run on a component that has constraints applied to it, the component will move only insofar as the constraints allow.
2) The interpart update is turned off while moving the component because otherwise errors may occur during the move process if the component is involved in a wave link operation.

Comments

Is there a way of keeping the previous position of the part and then apply a new transfor from that position? Every time I try to move the object again, the object would move according to its origion position rather than from the previous one.