Continue to Site

Eng-Tips is the largest engineering community on the Internet

Intelligent Work Forums for Engineering Professionals

  • Congratulations waross on being selected by the Eng-Tips community for having the most helpful posts in the forums last week. Way to Go!

NX8 Journaling: Automating the Movement of Objects from one CSYS to the Part Absolute CSYS 3

Status
Not open for further replies.

kfraysur

Bioengineer
Feb 4, 2010
42
How difficult would it be to take all points, lines, bodies, everything from all layers and move them from a defined CSYS to the part's absolute coordinate system? This would essentially automate the process of doing a 'Move Object' function of the 'CSYS to CSYS' variety and selecting everything in the part.

I have a pretty good understanding of how to add all of the objects to an array based on cowski's always appreciated help in this thread: thread561-321704

As this is part of a larger journal that will import data from several files, I also will already have the information necessary to create the 'From' CSYS: a plane normal to use for the z-axis, a line for the x-axis, and an origin point (the larger portion of this journal is dicussed in this thread: thread561-336844).

What I am unclear on is what function can be called to move this array of objects from the 'From' CSYS defined by the previously imported data to the absolute CSYS of the part.

Thanks for taking the time to read the thread. Any help would be greatly appreciated.
 
Replies continue below

Recommended for you

kfraysur said:
...this is part of a larger journal that will import data from several files...

Will the imported geometry be unparameterized? If so, it would be pretty easy to create a journal to move it all from csys to csys.

www.nxjournaling.com
 
Yes, the imported files contain only coordinate data for point creation. These points are used to create planes and lines. I've already got this part working and implemented in our system, which is discussed here:

As this is part of a larger journal that will import data from several files, I also will already have the information necessary to create the 'From' CSYS: a plane normal to use for the z-axis, a line for the x-axis, and an origin point (the larger portion of this journal is dicussed in this thread: thread561-336844).

So I have all these points, planes, and lines, some will be used to create the 'From' CSYS, and we need to move it all to the Absolute CSYS of the part. Thanks!
 
Here is a journal to which I have added a sub for moving bodies. I have also made some changes regarding the problem with the y axis direction. I the new sub you should be able to see the code that adds the bodies for moving. You should be able change this for any other objects. Remember that displayable object only are valid objects for moving. If the objects to be moved are on various layers then you may have to do this a number of times (I think).

Code:
Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.Features
Imports NXOpen.UF

Module MoveBodies
    Dim s As Session = Session.GetSession()
    Dim ufs As UFSession = UFSession.GetUFSession()
    Dim wp As Part = s.Parts.Work
    Sub Main()
        Dim response As Selection.Response = Nothing
        Dim response2 As Selection.Response = Nothing
        Dim dplane1 As DatumPlane = Nothing
        Dim line1 As Line = Nothing
        Dim cartesianCoordinateSystem1 As CartesianCoordinateSystem = Nothing
Start1:
        response = select_a_Dplane(dplane1)
        If response = Selection.Response.Back Then GoTo End1
        If response = Selection.Response.Cancel Then GoTo End1
        response2 = select_a_Line(line1)
        If response2 = Selection.Response.Back Then GoTo Start1 ' Select a new face
        If response2 = Selection.Response.Cancel Then GoTo End1
        Dim originonplane As Point3d = GetLinePlaneIntersectionPoint(dplane1, line1)
        CreateDatumCSYS(dplane1, line1, originonplane, cartesianCoordinateSystem1)
        MoveAllDisplayableObjects(cartesianCoordinateSystem1)
End1:
    End Sub

    Function select_a_Dplane(ByRef obj As DatumPlane) As Selection.Response
        Dim ui As UI = ui.GetUI()
        Dim selectionMask_array(1) As Selection.MaskTriple
        With selectionMask_array(0)
            .Type = UFConstants.UF_datum_plane_type
            .Subtype = 0
            .SolidBodySubtype = 0
        End With
        Dim cursor As Point3d = Nothing
        Dim resp As Selection.Response = _
        ui.SelectionManager.SelectTaggedObject("Select a Datum Plane", "Select a Datum Plane", _
            Selection.SelectionScope.WorkPart, _
            Selection.SelectionAction.ClearAndEnableSpecific, _
            False, False, selectionMask_array, obj, cursor)
        If resp = Selection.Response.ObjectSelected Or _
           resp = Selection.Response.ObjectSelectedByName Then
            Return Selection.Response.Ok
        ElseIf resp = Selection.Response.Back Then
            Return Selection.Response.Back
        Else
            Return Selection.Response.Cancel
        End If
    End Function
    Function select_a_Line(ByRef ln1 As Line)
        Dim ui As UI = ui.GetUI()
        Dim mask(0) As Selection.MaskTriple
        With mask(0)
            .Type = UFConstants.UF_line_type
            .Subtype = 0
            .SolidBodySubtype = 0
        End With
        Dim cursor As Point3d = Nothing
        Dim resp As Selection.Response = _
        ui.SelectionManager.SelectTaggedObject("Select a Line", "Select a Line", _
            Selection.SelectionScope.AnyInAssembly, _
            Selection.SelectionAction.ClearAndEnableSpecific, _
            False, False, mask, ln1, cursor)
        If resp = Selection.Response.ObjectSelected Or _
           resp = Selection.Response.ObjectSelectedByName Then
            Return Selection.Response.Ok
        ElseIf resp = Selection.Response.Back Then
            Return Selection.Response.Back
        Else
            Return Selection.Response.Cancel
        End If
    End Function
    Public Function GetLinePlaneIntersectionPoint(ByVal dplane1 As DatumPlane, ByVal line1 As Line) As Point3d
        ' get intersection pt of line on datum plane
        ' datum plane data
        Dim dplaneOrigin(2) As Double
        Dim dplaneNormal(2) As Double
        ufs.Modl.AskDatumPlane(dplane1.Tag, dplaneOrigin, dplaneNormal)
        ' line data for line pnt and line vector
        Dim startpnt As Point3d = line1.StartPoint
        Dim endpnt As Point3d = line1.EndPoint
        Dim pnt1() As Double = {startpnt.X, startpnt.Y, startpnt.Z}
        Dim pnt2() As Double = {endpnt.X, endpnt.Y, endpnt.Z}
        Dim distance1 As Double = Nothing
        Dim distance2 As Double = Nothing
        Dim linevec(2) As Double
        Dim tol1 As Double = 0.001
        Dim mag1 As Double = Nothing
        ufs.Vec3.Distance(dplaneOrigin, pnt1, distance1)
        ufs.Vec3.Distance(dplaneOrigin, pnt2, distance2)
        Dim point1(2) As Double
        Dim sub1 As Double = Nothing
        Dim sub2 As Double = Nothing
        Dim w As Double = Nothing
        If distance1 > distance2 Then
            ' use startpnt and pnt1
            ufs.Vec3.Sub(pnt1, pnt2, linevec)
            ufs.Vec3.Unitize(linevec, tol1, mag1, linevec)
            ' dplaneOrigin - line origin
            point1(0) = dplaneOrigin(0) - pnt1(0)
            point1(1) = dplaneOrigin(1) - pnt1(1)
            point1(2) = dplaneOrigin(2) - pnt1(2)
            ' dplaneNormal dot point1
            ufs.Vec3.Dot(dplaneNormal, point1, sub1)
            ' dplaneNormal dot linevec
            ufs.Vec3.Dot(dplaneNormal, linevec, sub2)
            ' w is the parameter value of a line from the line point to the dplane along line vector
            w = sub1 / sub2
            ' calculate the point on the dpane
            point1(0) = pnt1(0) + w * linevec(0)
            point1(1) = pnt1(1) + w * linevec(1)
            point1(2) = pnt1(2) + w * linevec(2)
        Else
            ' use endpnt and pnt2
            ufs.Vec3.Sub(pnt2, pnt1, linevec)
            ufs.Vec3.Unitize(linevec, tol1, mag1, linevec)
            ' dplaneOrigin - line origin
            point1(0) = dplaneOrigin(0) - pnt2(0)
            point1(1) = dplaneOrigin(1) - pnt2(1)
            point1(2) = dplaneOrigin(2) - pnt2(2)
            ' dplaneNormal dot point1
            ufs.Vec3.Dot(dplaneNormal, point1, sub1)
            ' dplaneNormal dot linevec
            ufs.Vec3.Dot(dplaneNormal, linevec, sub2)
            ' w is the parameter value of a line from the line point to the dplane along line vector
            w = sub1 / sub2
            ' calculate the point on the dpane
            point1(0) = pnt2(0) + w * linevec(0)
            point1(1) = pnt2(1) + w * linevec(1)
            point1(2) = pnt2(2) + w * linevec(2)
        End If
        ' create the point
        Dim pointTag As Tag = Tag.Null
        ufs.Curve.CreatePoint(point1, pointTag)
        Dim pnt3d As Point3d = New Point3d(point1(0), point1(1), point1(2))
        Return pnt3d
    End Function

    Public Sub CreateDatumCSYS(ByVal dplane1 As DatumPlane, ByVal line1 As Line, ByVal originpt As Point3d, _
                               ByRef cartesianCoordinateSystem1 As CartesianCoordinateSystem)
        ' datum plane data
        Dim dplaneOrigin(2) As Double
        Dim xvec(2) As Double
        ufs.Modl.AskDatumPlane(dplane1.Tag, dplaneOrigin, xvec)
        Dim startpnt As Point3d = line1.StartPoint
        Dim endpnt As Point3d = line1.EndPoint
        Dim linevec(2) As Double
        ' get midpoint of line
        Dim midpnt(2) As Double
        midpnt(0) = (startpnt.X + endpnt.X) / 2.0
        midpnt(1) = (startpnt.Y + endpnt.Y) / 2.0
        midpnt(2) = (startpnt.Z + endpnt.Z) / 2.0
        Dim yvec(2) As Double
        Dim zvec(2) As Double
        Dim originpt1() As Double = {originpt.X, originpt.Y, originpt.Z}
        ufs.Vec3.Sub(midpnt, originpt1, yvec)
        ufs.Vec3.Cross(xvec, yvec, zvec)
        ufs.Vec3.Cross(zvec, xvec, yvec)
        Dim coordsx As Point3d = New Point3d(originpt.X + xvec(0), originpt.Y + xvec(1), originpt.Z + xvec(2))
        Dim coordsy As Point3d = New Point3d(originpt.X + yvec(0), originpt.Y + yvec(1), originpt.Z + yvec(2))
        Dim nullFeatures_Feature As Features.Feature = Nothing
        Dim datumCsysBuilder1 As Features.DatumCsysBuilder
        datumCsysBuilder1 = wp.Features.CreateDatumCsysBuilder(nullFeatures_Feature)
        Dim point1 As Point
        point1 = wp.Points.CreatePoint(originpt)
        Dim point2 As Point
        point2 = wp.Points.CreatePoint(coordsx)
        Dim point3 As Point
        point3 = wp.Points.CreatePoint(coordsy)
        Dim xform1 As Xform
        xform1 = wp.Xforms.CreateXform(point1, point2, point3, SmartObject.UpdateOption.WithinModeling, 1.0)

        cartesianCoordinateSystem1 = wp.CoordinateSystems.CreateCoordinateSystem(xform1, SmartObject.UpdateOption.WithinModeling)
        datumCsysBuilder1.Csys = cartesianCoordinateSystem1
        datumCsysBuilder1.DisplayScaleFactor = 1.25
        Dim nXObject1 As NXObject
        nXObject1 = datumCsysBuilder1.Commit()
        datumCsysBuilder1.Destroy()
    End Sub
    Public Sub MoveAllDisplayableObjects(ByVal cartesianCoordinateSystem1 As CartesianCoordinateSystem)
        Dim nullFeatures_MoveObject As Features.MoveObject = Nothing
        Dim moveObjectBuilder1 As Features.MoveObjectBuilder
        moveObjectBuilder1 = wp.BaseFeatures.CreateMoveObjectBuilder(nullFeatures_MoveObject)
        moveObjectBuilder1.TransformMotion.Option = GeometricUtilities.ModlMotion.Options.CsysToCsys
        moveObjectBuilder1.TransformMotion.DistanceAngle.OrientXpress.AxisOption = GeometricUtilities.OrientXpressBuilder.Axis.Passive
        moveObjectBuilder1.TransformMotion.DistanceAngle.OrientXpress.PlaneOption = GeometricUtilities.OrientXpressBuilder.Plane.Passive
        moveObjectBuilder1.TransformMotion.OrientXpress.AxisOption = GeometricUtilities.OrientXpressBuilder.Axis.Passive
        moveObjectBuilder1.TransformMotion.OrientXpress.PlaneOption = GeometricUtilities.OrientXpressBuilder.Plane.Passive
        Dim manipulatororigin1 As Point3d
        manipulatororigin1 = moveObjectBuilder1.TransformMotion.ManipulatorOrigin
        Dim manipulatormatrix1 As Matrix3x3
        manipulatormatrix1 = moveObjectBuilder1.TransformMotion.ManipulatorMatrix
        moveObjectBuilder1.TransformMotion.DeltaEnum = GeometricUtilities.ModlMotion.Delta.ReferenceWcsWorkPart
        moveObjectBuilder1.TransformMotion.DeltaXc.RightHandSide = "0"
        moveObjectBuilder1.TransformMotion.DeltaYc.RightHandSide = "0"
        moveObjectBuilder1.TransformMotion.DeltaZc.RightHandSide = "10"
        moveObjectBuilder1.TransformMotion.DistanceValue.RightHandSide = "25"
        moveObjectBuilder1.TransformMotion.Angle.RightHandSide = "90"
        moveObjectBuilder1.Layer = 4
        Dim added1 As Boolean = False
        Dim cnt1 As Integer = 0
        For Each b As Body In s.Parts.Work.Bodies
            added1 = moveObjectBuilder1.ObjectToMoveObject.Add(b)
            cnt1 += 1
        Next
        If cnt1 = 0 Then
            MsgBox("No bodies available for moving")
            Return
        End If
        moveObjectBuilder1.TransformMotion.Option = GeometricUtilities.ModlMotion.Options.CsysToCsys
        Dim xform1 As Xform
        xform1 = wp.Xforms.CreateXform(cartesianCoordinateSystem1, SmartObject.UpdateOption.WithinModeling)
        Dim cartesianCoordinateSystem2 As CartesianCoordinateSystem
        cartesianCoordinateSystem2 = wp.CoordinateSystems.CreateCoordinateSystem(xform1, SmartObject.UpdateOption.WithinModeling)
        moveObjectBuilder1.TransformMotion.FromCsys = cartesianCoordinateSystem2
        Dim xform2 As Xform
        xform2 = wp.Xforms.CreateXform(SmartObject.UpdateOption.WithinModeling, 1.0)
        Dim cartesianCoordinateSystem3 As CartesianCoordinateSystem
        cartesianCoordinateSystem3 = wp.CoordinateSystems.CreateCoordinateSystem(xform2, SmartObject.UpdateOption.WithinModeling)
        xform2.RemoveParameters()
        moveObjectBuilder1.TransformMotion.ToCsys = cartesianCoordinateSystem3
        Dim nXObject1 As NXObject
        nXObject1 = moveObjectBuilder1.Commit()
        moveObjectBuilder1.Destroy()
    End Sub
    Public Function GetUnloadOption(ByVal dummy As String) As Integer
        'Unloads the image immediately after execution within NX
        GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
    End Function
End Module

Regards

Frank Swinkels
 
Frank,

The direction of the Y-axis is working as intended. Thank you so much.

As for the movement from one CSYS to another, the part file is only going to have points, lines, and datum planes when the move function will be called. Unfortunately the current code will not work. How difficult would it be to modify to move such objects?
 
OK I thought that since you indicated that "I have a pretty good understanding of how to add all of the objects" that if I demonstrated the format for body move that would be sufficient for any other types of object. Anyway if you replace the code

For Each b As Body In s.Parts.Work.Bodies
added1 = moveObjectBuilder1.ObjectToMoveObject.Add(b)
cnt1 += 1
Next
If cnt1 = 0 Then
MsgBox("No bodies available for moving")
Return
End If

with

For Each obj As DisplayableObject In s.Parts.Work.Datums
If TypeOf obj Is DatumPlane Then
added1 = moveObjectBuilder1.ObjectToMoveObject.Add(obj)
cnt1 += 1
End If
Next
For Each obj As DisplayableObject In s.Parts.Work.Points
If TypeOf obj Is Point Then
added1 = moveObjectBuilder1.ObjectToMoveObject.Add(obj)
cnt1 += 1
End IfNext
For Each obj As DisplayableObject In s.Parts.Work.Lines
If TypeOf obj Is Line Then
added1 = moveObjectBuilder1.ObjectToMoveObject.Add(obj)
cnt1 += 1
End If
Next
If cnt1 = 0 Then
MsgBox("No points, line or datumn planes available for moving")
Return
End If

that will address points, lines and datumn planes. Now if in the future you need to add other types it must surely be straight forward.

Regards

Frank Swinkels
 
Frank,

Thanks for the response. After I left the office last night I went back and looked at some code for an automated stp file export we use (admittedly, I should have done this prior to posting) and realized the changes I needed to make to get the code to work for this. I'm glad to see that my implementation and yours look the same.

Thanks so much for the help.
 
The Add method of the moveObjectBuilder.ObjectToMoveObject has an overloaded version that accepts an array of objects. This will allow you to skip the For Each loops and should run a bit faster on large files with lots of objects.

Code:
[COLOR=#4E9A06]'move all bodies[/color]
added1 = moveObjectBuilder1.ObjectToMoveObject.Add(s.Parts.Work.Bodies.ToArray)
cnt1 += s.Parts.Work.Bodies.ToArray.Length

[COLOR=#4E9A06]'move all curves (lines, arcs, splines, conics)[/color]
added1 = moveObjectBuilder1.ObjectToMoveObject.Add(s.Parts.Work.Curves.ToArray)
cnt1 += s.Parts.Work.Curves.ToArray.Length

[COLOR=#4E9A06]'move all datums (planes, axes, csys)[/color]
added1 = moveObjectBuilder1.ObjectToMoveObject.Add(s.Parts.Work.Datums.ToArray)
cnt1 += s.Parts.Work.Datums.ToArray.Length

www.nxjournaling.com
 
Thanks for the tip cowski. I will look to implement that in this process as well as the stp file export I was talking about before.
 
I meant to add this to my previous post:
If you need to separate out only datum planes, then you'd need to revert to looping through the datum collection and testing the object's type. But there are collections specifically for lines, arcs, and splines. So you can use the Curves collection to grab everything, or one of the other collections to get more specific while avoiding the object type test.

www.nxjournaling.com
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor