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!

Journal: Moving all objects to WCS 1

Status
Not open for further replies.

DHuskic

Computer
Dec 18, 2012
114
I am in search of a journal that moves all displayed objects to the WCS using their respective Part CSYS. I am running NX7.5, and would be moving geometry that is either all unparameterized or all parameterized but never both at the same time. I know the difference between doing this task by hand but I don't know what difference it would have in a journal or where I would even begin with a journal for this.

I was using the thread below as a guide but could not get the journal from it to work (not sure if it is because I am running NX7.5 instead of NX8?). I am not sure if this is possible with parameterized geometry but any insight on this subject would help me tremendously. Thanks in advanced and I appreciate any help!

thread561-338288

Denis Huskic
Data Prep
Kettering University
Class of '17
 
Replies continue below

Recommended for you

Cowski,
All the unparameterized bodies are in a part file. The parts with parameters are inside of an assembly file.
I would be pleased to be able to either one.

Denis Huskic
Data Prep
Kettering University
Class of '17
 
Looks like you want to move From CSYS To CSYS, are the 2 CSYS objects the same for each body/part? How do you want them defined? i.e. what is your "From CSYS" object, or what defines it?

From your question, I assume you want to use the current WCS as the "To CSYS", is this correct?

www.nxjournaling.com
 
The "From CSYS" would be the center of the part. I'm not sure of the official name for it but when I do a move object and move it dynamically, I would want that CSYS to be the "From CSYS". And yes, the "To CSYS" would be the WCS.

On a side note, originally I have a macro I made. I would select the body, then the macro would perform a Move Object -> Dynamic -> Point Dialog -> Refresh [to make the point (0,0,0)] -> <OK>. I'm not sure if this helps but this macro made the process the same for all parts and I wouldn't have to select anything(excluding the body in the beginning).

Denis Huskic
Data Prep
Kettering University
Class of '17
 
I'm not sure how the CSYS constructor handles in the dynamic move are calculated, though I suspect it is placed at the center of the object's bounding box.

Is this what you want? Move the object from the center of its bounding box to the WCS (0,0,0) point?

www.nxjournaling.com
 
I know that not all of my parts/bodies lie flat with the WCS but I would still take that over nothing, so yes please!

Denis Huskic
Data Prep
Kettering University
Class of '17
 
Denis,
Sorry for the delay, a bunch of other project deadlines all came due recently. Here's a journal that will move all the bodies in a file to the WCS (0,0,0). I've only tested it on unparameterized bodies.

Code for moving components in an assembly would be similar.

Code:
[COLOR=blue]Option Strict Off[/color]  
[COLOR=blue]Imports[/color] System  
[COLOR=blue]Imports[/color] NXOpen  
[COLOR=blue]Imports[/color] NXOpen.UF  

[COLOR=blue]Module[/color] Module1  

    [COLOR=blue]Dim[/color] theSession [COLOR=blue]As[/color] Session [COLOR=blue]=[/color] Session.GetSession()  
    [COLOR=blue]Dim[/color] theUfSession [COLOR=blue]As[/color] UFSession [COLOR=blue]=[/color] UFSession.GetUFSession()  

    [COLOR=blue]Sub[/color] Main()  

        [COLOR=blue]Dim[/color] workPart [COLOR=blue]As[/color] Part [COLOR=blue]=[/color] theSession.Parts.Work  

        [COLOR=blue]Dim[/color] markId1 [COLOR=blue]As[/color] Session.UndoMarkId  
        markId1 [COLOR=blue]=[/color] theSession.SetUndoMark(Session.MarkVisibility.Visible, "Move Bodies")  

        [COLOR=blue]For Each[/color] objBody [COLOR=blue]As[/color] Body [COLOR=blue]In[/color] workPart.Bodies  

            [COLOR=blue]Dim[/color] bbox(5) [COLOR=blue]As Double[/color]  
            [COLOR=blue]Dim[/color] midPoint [COLOR=blue]As[/color] Point3d  
            [COLOR=blue]Dim[/color] fromPoint [COLOR=blue]As[/color] Point  

 [COLOR=green]'grab bounding box[/color]
            theUfSession.Modl.AskBoundingBox(objBody.Tag, bbox)  

 [COLOR=green]'calculate midpoint[/color]
            midPoint.X [COLOR=blue]=[/color] bbox(0) [COLOR=blue]+[/color] (bbox(3) [COLOR=blue]-[/color] bbox(0)) [COLOR=blue]/[/color] 2  
            midPoint.Y [COLOR=blue]=[/color] bbox(1) [COLOR=blue]+[/color] (bbox(4) [COLOR=blue]-[/color] bbox(1)) [COLOR=blue]/[/color] 2  
            midPoint.Z [COLOR=blue]=[/color] bbox(2) [COLOR=blue]+[/color] (bbox(5) [COLOR=blue]-[/color] bbox(2)) [COLOR=blue]/[/color] 2  
            fromPoint [COLOR=blue]=[/color] workPart.Points.CreatePoint(midPoint)  

 [COLOR=green]'move body from midpoint to WCS 0,0,0[/color]
            [COLOR=blue]Dim[/color] nullFeatures_MoveObject [COLOR=blue]As[/color] Features.MoveObject [COLOR=blue]= Nothing[/color]  

            [COLOR=blue]Dim[/color] moveObjectBuilder1 [COLOR=blue]As[/color] Features.MoveObjectBuilder  
            moveObjectBuilder1 [COLOR=blue]=[/color] workPart.BaseFeatures.CreateMoveObjectBuilder(nullFeatures_MoveObject)  

            moveObjectBuilder1.TransformMotion.Option [COLOR=blue]=[/color] GeometricUtilities.ModlMotion.Options.PointToPoint  

            [COLOR=blue]Dim[/color] added1 [COLOR=blue]As Boolean[/color]  
            added1 [COLOR=blue]=[/color] moveObjectBuilder1.ObjectToMoveObject.Add(objBody)  

            moveObjectBuilder1.TransformMotion.FromPoint [COLOR=blue]=[/color] fromPoint  

            [COLOR=blue]Dim[/color] coordinates2 [COLOR=blue]As[/color] Point3d [COLOR=blue]= New[/color] Point3d(0.0, 0.0, 0.0)  
            coordinates2 [COLOR=blue]=[/color] WCS2Abs(coordinates2)  
            [COLOR=blue]Dim[/color] point1 [COLOR=blue]As[/color] Point  
            point1 [COLOR=blue]=[/color] workPart.Points.CreatePoint(coordinates2)  

            moveObjectBuilder1.TransformMotion.ToPoint [COLOR=blue]=[/color] point1  

            [COLOR=blue]Dim[/color] nXObject2 [COLOR=blue]As[/color] NXObject  
            nXObject2 [COLOR=blue]=[/color] moveObjectBuilder1.Commit()  

            [COLOR=blue]Dim[/color] objects1() [COLOR=blue]As[/color] NXObject  
            objects1 [COLOR=blue]=[/color] moveObjectBuilder1.GetCommittedObjects()  

            moveObjectBuilder1.Destroy()  

        [COLOR=blue]Next[/color]  

    End [COLOR=blue]Sub[/color]  

    [COLOR=blue]Function[/color] WCS2Abs(ByVal inPt [COLOR=blue]As[/color] Point3d) [COLOR=blue]As[/color] Point3d  
        [COLOR=blue]Dim[/color] pt1(2), pt2(2) [COLOR=blue]As Double[/color]  

        pt1(0) [COLOR=blue]=[/color] inPt.X  
        pt1(1) [COLOR=blue]=[/color] inPt.Y  
        pt1(2) [COLOR=blue]=[/color] inPt.Z  

        theUfSession.Csys.MapPoint(UFConstants.UF_CSYS_ROOT_WCS_COORDS, pt1, UFConstants.UF_CSYS_ROOT_COORDS, pt2)  

        WCS2Abs.X [COLOR=blue]=[/color] pt2(0)  
        WCS2Abs.Y [COLOR=blue]=[/color] pt2(1)  
        WCS2Abs.Z [COLOR=blue]=[/color] pt2(2)  

    End [COLOR=blue]Function[/color]  

    [COLOR=blue]Function[/color] Abs2WCS(ByVal inPt [COLOR=blue]As[/color] Point3d) [COLOR=blue]As[/color] Point3d  
        [COLOR=blue]Dim[/color] pt1(2), pt2(2) [COLOR=blue]As Double[/color]  

        pt1(0) [COLOR=blue]=[/color] inPt.X  
        pt1(1) [COLOR=blue]=[/color] inPt.Y  
        pt1(2) [COLOR=blue]=[/color] inPt.Z  

        theUfSession.Csys.MapPoint(UFConstants.UF_CSYS_ROOT_COORDS, pt1, UFConstants.UF_CSYS_ROOT_WCS_COORDS, pt2)  

        Abs2WCS.X [COLOR=blue]=[/color] pt2(0)  
        Abs2WCS.Y [COLOR=blue]=[/color] pt2(1)  
        Abs2WCS.Z [COLOR=blue]=[/color] pt2(2)  

    End [COLOR=blue]Function[/color]  
    [COLOR=blue]Public Function[/color] GetUnloadOption(ByVal dummy [COLOR=blue]As String[/color]) [COLOR=blue]As Integer[/color]  

 [COLOR=green]'Unloads the image when the NX session terminates[/color]
        GetUnloadOption [COLOR=blue]=[/color] NXOpen.Session.LibraryUnloadOption.AtTermination  

    End [COLOR=blue]Function[/color]  

End [COLOR=blue]Module[/color]


www.nxjournaling.com
 
Cowski,
Thanks for that code, it works great! I have gotten to the point where I want to figure out how to move all the objects and lay them flat onto the WCS. I have some ideas but I still need some of the specific NX callouts to accomplish this. I am working with unparameterized bodies at the moment that are anywhere from .125" to 1.25", the plates are normally longer than taller as well. Please let me know if you can help me out with this. I am in the process of writing an algorithm to space flatten bodies out into a sheet but I can only do this if they are all flat.

1) Use the bounding box information to find the surface with the most surface area. Create an "FROM CSYS" using that face with the most area. This would mimic clicking a face to get the CSYS, then moving to the WCS.
2) Change the angle corresponding to the X and Y axis' by 1 degree repeatedly until the Z height of the bounding box reaches a minimum, then use the bounding box method from the code to move it. This one would run very slowing I'm assuming due to a very large number of bounding boxes being created but that is an acceptable sacrifice.
3) Use a variation of the above two after the objects have been moved to the WCS to try and flatten them all out as much as possible.

Denis Huskic
Data Prep NX7.5
Kettering University
Class of '17
 
There is a code sample in the GTAC database that you might be interested in, it creates a csys based on a chosen planar face. It might give you some ideas or even work as a good starting point.

This code was written by Steve Labout (a Siemens employee) and can be found in the GTAC solutions center database.

Code:
' This allows you to select a planar face.
'
' The program will then find the longest LINEAR edge of that face.
' It will find the start and end points of that edge.
'
' Then it will find the LINEAR edge of the face that intersects
' the longest edge at the start point of the long edge.
'
' It creates vectors based on those two edges, and then creates
' a matrix from those vectors.
'
' It creates a CSYS entity whose origin is at the start point of
' the long edge, and which is aligned to the matrix.
'
' Then it moves the WCS to the newly-created CSYS.
'
' There is very little error-checking, so it may not behave nicely if
' one of the expected prerequisites mentioned above is not met.
'
' Also, you might want to modify it to allow the user to 
' reverse the X-vector and put the origin at the other end
' of the longest edge, because it is hard-coded to use the start
' point of that edge, which will sometimes be wrong.

Option Strict Off

Imports System
Imports NXOpen
Imports NXOpen.UF
Imports NXOpen.UI
Imports NXOpen.Utilities

Module wcs_from_face_and_longest_edge

   Dim s As Session = Session.GetSession()
   Dim ufs As UFSession = UFSession.GetUFSession()
   Dim lw As ListingWindow = s.ListingWindow

   Sub Main()

      Dim planarFace As NXOpen.Tag = NXOpen.Tag.Null
      Dim longEdge As NXOpen.Tag = NXOpen.Tag.Null
      Dim otherEdge As NXOpen.Tag = NXOpen.Tag.Null
      Dim origin() As Double = {0, 0, 0}

      Dim xVector(2) As Double
      Dim yVector(2) As Double

      If select_a_planar_face(planarFace) = Selection.Response.Ok Then

         ufs.Disp.SetHighlight(planarFace, 0)

      End If

      Dim faceObject As Face = NXObjectManager.Get(planarFace)
      Dim edges() As Edge = faceObject.GetEdges()

      longEdge = get_longest_edge(edges)

      Dim sp(2) As Double
      Dim ep(2) As Double
      Dim lineData As UFCurve.Line
      lineData.start_point = sp
      lineData.end_point = ep

      ufs.Curve.AskLineData(longEdge, lineData)
      sp = lineData.start_point
      ep = lineData.end_point

      ufs.Vec3.Sub(ep, sp, xVector)
      ufs.Vec3.Copy(sp, origin)

      Dim sp2(2) As Double
      Dim ep2(2) As Double

      otherEdge = find_edge_adjacent_to_start_point(edges, sp, longEdge)

      ufs.Curve.AskLineData(otherEdge, lineData)
      sp2 = lineData.start_point
      ep2 = lineData.end_point

      If sp2(0) = sp(0) And sp2(1) = sp(1) And sp2(2) = sp(2) Then
         ufs.Vec3.Sub(ep2, sp2, yVector)
      Else
         ufs.Vec3.Sub(sp2, ep2, yVector)
      End If
      Dim mtx As NXOpen.Tag = NXOpen.Tag.Null
      Dim new_csys As NXOpen.Tag = NXOpen.Tag.Null
      Dim mtx_vals(8) As Double
      ufs.Mtx3.Initialize(xVector, yVector, mtx_vals)

      ufs.Csys.CreateMatrix(mtx_vals, mtx)
      ufs.Csys.CreateCsys(origin, mtx, new_csys)

      If new_csys <> NXOpen.Tag.Null Then
         ufs.Csys.SetWcs(new_csys)
      End If

   End Sub

   Function find_edge_adjacent_to_start_point(ByVal edges() As Edge, _
            ByVal org() As Double, ByVal longEdge As NXOpen.Tag) As NXOpen.Tag

      Dim thisEdge As NXOpen.Tag = NXOpen.Tag.Null
      Dim inx As Integer = 0

      For inx = 0 To edges.GetUpperBound(0)
         thisEdge = edges(inx).Tag

         If thisEdge <> longEdge Then ' to make sure we skip the xVector edge
            Dim edgeType As Integer = 0
            ufs.Modl.AskEdgeType(thisEdge, edgeType)
            If edgeType = UFConstants.UF_MODL_LINEAR_EDGE Then

               Dim sp(2) As Double
               Dim ep(2) As Double
               Dim lineData As UFCurve.Line
               lineData.start_point = sp
               lineData.end_point = ep

               ufs.Curve.AskLineData(thisEdge, lineData)
               sp = lineData.start_point
               ep = lineData.end_point

               If sp(0) = org(0) And sp(1) = org(1) And sp(2) = org(2) Then
                  Return thisEdge
               End If

               If ep(0) = org(0) And ep(1) = org(1) And ep(2) = org(2) Then
                  Return thisEdge
               End If
            End If

         End If
      Next

   End Function

   Function get_longest_edge(ByVal edges() As Edge) As NXOpen.Tag
      Dim lgth As Double = 0
      Dim inx As Integer = 0
      Dim thisEdge As NXOpen.Tag = NXOpen.Tag.Null
      Dim longestNumber As Double = 0
      Dim longestEdge As NXOpen.Tag = NXOpen.Tag.Null

      For inx = 0 To edges.GetUpperBound(0)

         thisEdge = edges(inx).Tag
         Dim edgeType As Integer = 0
         ufs.Modl.AskEdgeType(thisEdge, edgeType)

         If edgeType = UFConstants.UF_MODL_LINEAR_EDGE Then

            ufs.Curve.AskArcLength(thisEdge, 0, 1, ModlUnits.ModlUnitsPart, lgth)

            If lgth > longestNumber Then
               longestEdge = thisEdge
               longestNumber = lgth
            End If

         End If

      Next inx

      Return longestEdge

   End Function

   Function select_a_planar_face(ByRef face As NXOpen.Tag) As Selection.Response

      Dim message As String = "Planar Face:"
      Dim title As String = "Select a PLANAR FACE"
      Dim scope As Integer = UFConstants.UF_UI_SEL_SCOPE_ANY_IN_ASSEMBLY
      Dim response As Integer
      Dim view As NXOpen.Tag
      Dim cursor(2) As Double
      Dim mask_face As UFUi.SelInitFnT = AddressOf mask_for_planar_faces

      ufs.Ui.LockUgAccess(UFConstants.UF_UI_FROM_CUSTOM)

      Try
         ufs.Ui.SelectWithSingleDialog(message, title, scope, mask_face, _
                      Nothing, response, face, cursor, view)
      Finally
         ufs.Ui.UnlockUgAccess(UFConstants.UF_UI_FROM_CUSTOM)
      End Try

      If response <> UFConstants.UF_UI_OBJECT_SELECTED And _
         response <> UFConstants.UF_UI_OBJECT_SELECTED_BY_NAME Then
         Return Selection.Response.Cancel
      Else
         Return Selection.Response.Ok
      End If

   End Function

   Function mask_for_planar_faces(ByVal select_ As IntPtr, _
                          ByVal userdata As IntPtr) As Integer

      Dim num_triples As Integer = 1
      Dim mask_triples(0) As UFUi.Mask
      mask_triples(0).object_type = UFConstants.UF_solid_type
      mask_triples(0).object_subtype = UFConstants.UF_solid_face_subtype
      mask_triples(0).solid_type = UFConstants.UF_UI_SEL_FEATURE_PLANAR_FACE

      ufs.Ui.SetSelMask(select_, _
                         UFUi.SelMaskAction.SelMaskClearAndEnableSpecific, _
                         num_triples, mask_triples)
      Return UFConstants.UF_UI_SEL_SUCCESS

   End Function


   Public Function GetUnloadOption(ByVal dummy As String) As Integer

      Return Session.LibraryUnloadOption.Immediately

   End Function

End Module

www.nxjournaling.com
 
Thank you!
I've made a lot of progress with the program. I plan on checking all of the faces on each body, and taking the face with the most surface area, orientating the wcs to that face, and then continuing with the bounding box. When processing all of the faces on a body, how would I get the area of that face?

Denis Huskic
Data Prep NX7.5
Kettering University
Class of '17
 
Here is what I have so far. The code needs to be review once I finish it but at the moment, between the Move WCS to the Move WCS Back portion I need code to check all of the bodies' faces(the planar ones are most important) and return area for each face and grab the face with the most surface area. I had code set up early to do this but kept receiving license errors when trying to get the area.
Once I find that face with the most surface area:
1)I want to orientate the WCS to the face
2)Create the bounding box
3)Move the WCS back
4)Move the object with respect to the bounding box
5)Move onto the next body.

Here are the two sets of code I tried that gave me the errors:

Code 1:
Code:
Sub Main()
Dim theSession As Session = Session.GetSession()
Dim workPart As Part = theSession.Parts.Work
Dim displayPart As Part = theSession.Parts.Display
Dim uf As UFSession = UFSession.GetUFSession()
Dim theSf As UFSf = uf.Sf
Dim x1, x2 As Double
Dim mySelectedObjects As nxobject()
Dim nullNXObject As NXObject = Nothing
Dim measureFaceBuilder1 As MeasureFaceBuilder
measureFaceBuilder1 = workPart.MeasureManager.CreateMeasureFaceBuilder(nullNXObject)
Dim bodies As BodyCollection = workPart.Bodies
Dim bodyTags As Tag() = Nothing
       theSf.AskAllPolygonBodies(bodies.ToArray.Length, bodyTags)
       For Each bodyTag As Tag In bodyTags
          Dim body As CAE.CAEBody = NXOpen.Utilities.NXObjectManager.Get(bodyTag)
   Next
       For Each mySelObj As Object In bodies
          Dim boundaryFaces1(-1) As Face
          Dim faceTangentRule1 As FaceTangentRule
          'faceTangentRule1 = workPart.ScRuleFactory.CreateRuleFaceTangent(mySelObj, boundaryFaces1, 0.5)
          Dim unit1 As Unit = CType(workPart.UnitCollection.FindObject("SquareMilliMeter"), Unit)
          Dim unit2 As Unit = CType(workPart.UnitCollection.FindObject("MilliMeter"), Unit)
          Dim rules1(0) As SelectionIntentRule
          rules1(0) = faceTangentRule1
          'measureFaceBuilder1.FaceCollector.ReplaceRules(rules1, False)

          Dim measureFaces1 As MeasureFaces
          'measureFaces1 = workPart.MeasureManager.NewFaceProperties(unit1, unit2, 0.99, measureFaceBuilder1.FaceCollector)

          Dim measure1 As Measure
          measure1 = measureFaces1.CreateFeature()

          x1 = measureFaces1.Area
          x2 = measureFaces1.Perimeter
   Next
End Sub

Code 2 from GTAC: Sample NX Open .NET Visual Basic program : demo evaluate CAE geometry
Code:
For Each faceTag As Tag In faceTags
                Dim face As CAE.CAEFace = NXOpen.Utilities.NXObjectManager.Get(faceTag)
                Dim area As Double = 0.0
                theSf.FaceAskArea(faceTag, area)

Denis Huskic
Data Prep NX7.5
Kettering University
Class of '17
 
I have some similar code I wrote a while back that found the largest revolved face on a given solid. You can modify it to look for planar faces...

This is a function that takes a solid body as input and returns the largest revolved face. You may want to add a check to see that there is at least 1 face of the type you are looking for (this version of the function doesn't have that).

Code:
    Function LargestRevolvedFace(ByVal inputSolid As Body) As Face

        Dim nullNXObject As NXObject = Nothing
        Dim measureFaceBuilder1 As MeasureFaceBuilder
        measureFaceBuilder1 = workPart.MeasureManager.CreateMeasureFaceBuilder(nullNXObject)

        Dim unit1 As Unit = CType(workPart.UnitCollection.FindObject("SquareInch"), Unit)
        Dim unit2 As Unit = CType(workPart.UnitCollection.FindObject("Inch"), Unit)

        Dim objects1(0) As IParameterizedSurface
        Dim measureFaces1 As MeasureFaces

        Dim myFaces() As Face
        myFaces = inputSolid.GetFaces
        Dim largestFace As Face = myFaces(0)
        Dim largestArea As Double
        Dim added1 As Boolean
        Dim i As Integer = 0

        For Each tempFace As Face In myFaces
            Select Case tempFace.SolidFaceType
                Case 2, 3, 5
                    'type 2 = cylindrical
                    'type 3 = conical
                    'type 5 = surface of revolution
                    i += 1
                    'lw.WriteLine("case 2,3,5: " & tempFace.SolidFaceType.ToString)
                    measureFaceBuilder1.FaceObjects.Clear()
                    added1 = measureFaceBuilder1.FaceObjects.Add(tempFace)
                    objects1(0) = tempFace
                    measureFaces1 = workPart.MeasureManager.NewFaceProperties(unit1, unit2, 0.999, objects1)
                    If i = 1 Then
                        largestFace = tempFace
                        largestArea = measureFaces1.Area
                        'lw.WriteLine("initial face:")
                        'lw.WriteLine("area: " & largestArea)
                        'largestFace.Highlight()
                    Else
                        If measureFaces1.Area > largestArea Then
                            'largestFace.Unhighlight()
                            largestFace = tempFace
                            'largestFace.Highlight()
                            largestArea = measureFaces1.Area
                            'lw.WriteLine("new largest face, area: " & largestArea)

                        End If
                    End If

                Case Else
                    'skip to next face
            End Select
        Next

        measureFaces1.Dispose()
        measureFaceBuilder1.FaceObjects.Clear()
        measureFaceBuilder1.Destroy()

        If i = 0 Then
            Return Nothing
        Else
            Return largestFace
        End If

    End Function

www.nxjournaling.com
 
I'm almost finished. The program worked on the first two bodies I tested and then I received a "null tag not allowed" error on line 117. The program is attached, could you let me know if you see anything wrong as far as those few likes of code where the error is occuring? I know the rest of the program is a bit of a mess.

Denis Huskic
Data Prep NX7.5
Kettering University
Class of '17
 
 https://www.dropbox.com/s/x090ujf6uzmotgb/MoveFlattenBodies.vb
Check the output of the find_edge_adjacent_to_start_point function, it may be returning a null tag. Then, take a look at your input planar face; check the edge geometry, if it is intersection curve, or tolerant curve - that might cause problems for the journal.

www.nxjournaling.com
 
Thanks for all the help Cowski! This program helps our dept out very much as is! I am working on fine tuning it now.
Any ideas on how I would be able to sort through a body collection in a specific order?
Biggest to smallest depending on bounding box size. I just am not sure how to place them into another collection specifically with that criteria.

My idea is to turn the plate into an array and check for empty space(magic number "0"), to place pieces and best fit/compact best I can.

Denis Huskic
Data Prep NX7.5
Kettering University
Class of '17
 
You can sort your collection based on a custom function that you write. In the code sample below, we put all the body objects in the work part into a list then sort the list based on the volume of the bounding boxes of the bodies. You can rewrite the function(s) to sort based on whatever criteria you choose.

To try out the code, open a part that has 2 or (preferably) more body objects (solid or sheet bodies) then run the journal.

Code:
[COLOR=green]'NXJournaling[/color]
[COLOR=green]'June 25, 2013[/color]
[COLOR=green]'compare and sort body objects based on bounding box volume[/color]

[COLOR=blue]Option Strict Off[/color]  
[COLOR=blue]Imports[/color] System  
[COLOR=blue]Imports[/color] System.Collections.Generic  
[COLOR=blue]Imports[/color] NXOpen  
[COLOR=blue]Imports[/color] NXOpen.UF  

[COLOR=blue]Module[/color] Module1  

    [COLOR=blue]Dim[/color] theSession [COLOR=blue]As[/color] Session [COLOR=blue]=[/color] Session.GetSession()  
    [COLOR=blue]Dim[/color] theUFSession [COLOR=blue]As[/color] UFSession [COLOR=blue]=[/color] UFSession.GetUFSession  

    [COLOR=blue]Sub[/color] Main()  

        [COLOR=blue]Dim[/color] lw [COLOR=blue]As[/color] ListingWindow [COLOR=blue]=[/color] theSession.ListingWindow  
        lw.Open()  
        [COLOR=blue]Dim[/color] workPart [COLOR=blue]As[/color] Part [COLOR=blue]=[/color] theSession.Parts.Work  
        [COLOR=blue]Dim[/color] theBodies [COLOR=blue]As New[/color] List(Of Body)  

 [COLOR=green]'gather solid and sheet bodies into a list[/color]
        [COLOR=blue]For Each[/color] temp [COLOR=blue]As[/color] Body [COLOR=blue]In[/color] workPart.Bodies  
            theBodies.Add(temp)  
        [COLOR=blue]Next[/color]  

 [COLOR=green]'write the list out as it was built[/color]
        lw.WriteLine("Before sort:")  
        lw.WriteLine("Body Tag : Bounding box volume")  
        [COLOR=blue]For Each[/color] temp [COLOR=blue]As[/color] Body [COLOR=blue]In[/color] theBodies  
            lw.WriteLine(temp.Tag.ToString [COLOR=blue]&[/color] ": " [COLOR=blue]&[/color] BoundingBoxVolume(temp).ToString)  
        [COLOR=blue]Next[/color]  
        lw.WriteLine("")  

 [COLOR=green]'sort the list with our custom compare function[/color]
        theBodies.Sort(AddressOf CompareByBoundingBoxVolume)  

 [COLOR=green]'write out sorted list[/color]
        lw.WriteLine("After sort:")  
        lw.WriteLine("Body Tag : Bounding box volume")  
        [COLOR=blue]For Each[/color] temp [COLOR=blue]As[/color] Body [COLOR=blue]In[/color] theBodies  
            lw.WriteLine(temp.Tag.ToString [COLOR=blue]&[/color] ": " [COLOR=blue]&[/color] BoundingBoxVolume(temp).ToString)  
        [COLOR=blue]Next[/color]  
        lw.WriteLine("")  

 [COLOR=green]'reverse the list and write it out again[/color]
        lw.WriteLine("Reverse list")  
        lw.WriteLine("Body Tag : Bounding box volume")  
        theBodies.Reverse()  
        [COLOR=blue]For Each[/color] temp [COLOR=blue]As[/color] Body [COLOR=blue]In[/color] theBodies  
            lw.WriteLine(temp.Tag.ToString [COLOR=blue]&[/color] ": " [COLOR=blue]&[/color] BoundingBoxVolume(temp).ToString)  
        [COLOR=blue]Next[/color]  

    End [COLOR=blue]Sub[/color]  

    [COLOR=blue]Public Function[/color] BoundingBoxVolume(ByVal tempObj [COLOR=blue]As[/color] NXObject) [COLOR=blue]As Double[/color]  

        [COLOR=blue]Dim[/color] bbox(5) [COLOR=blue]As Double[/color]  

        theUFSession.Modl.AskBoundingBox(tempObj.Tag, bbox)  
        [COLOR=blue]Return[/color] (bbox(3) [COLOR=blue]-[/color] bbox(0)) [COLOR=blue]*[/color] (bbox(4) [COLOR=blue]-[/color] bbox(1)) [COLOR=blue]*[/color] (bbox(5) [COLOR=blue]-[/color] bbox(2))  

    End [COLOR=blue]Function[/color]  

    [COLOR=blue]Private Function[/color] CompareByBoundingBoxVolume(ByVal x [COLOR=blue]As[/color] Body, [COLOR=blue]ByVal[/color] y [COLOR=blue]As[/color] Body) [COLOR=blue]As Integer[/color]  

        [COLOR=blue]Dim[/color] volX [COLOR=blue]As Double =[/color] BoundingBoxVolume(x)  
        [COLOR=blue]Dim[/color] volY [COLOR=blue]As Double =[/color] BoundingBoxVolume(y)  

        [COLOR=blue]If[/color] volX > volY [COLOR=blue]Then[/color]  
            [COLOR=blue]Return[/color] 1  
        End [COLOR=blue]If[/color]  

        [COLOR=blue]If[/color] volX < volY [COLOR=blue]Then[/color]  
            [COLOR=blue]Return[/color] -1  
        End [COLOR=blue]If[/color]  

        [COLOR=blue]If[/color] volX [COLOR=blue]=[/color] volY [COLOR=blue]Then[/color]  
            [COLOR=blue]Return[/color] 0  
        End [COLOR=blue]If[/color]  

    End [COLOR=blue]Function[/color]  

    [COLOR=blue]Public Function[/color] GetUnloadOption(ByVal dummy [COLOR=blue]As String[/color]) [COLOR=blue]As Integer[/color]  

 [COLOR=green]'Unloads the image when the NX session terminates[/color]
        GetUnloadOption [COLOR=blue]=[/color] NXOpen.Session.LibraryUnloadOption.AtTermination  

    End [COLOR=blue]Function[/color]  

End [COLOR=blue]Module[/color]



www.nxjournaling.com
 
Do you have a journal I could use as a guideline for moving components?
I plan to use it with something similar to what I have below.

Code:
         Dim c As Component = part1.ComponentAssembly.RootComponent
         Dim children As Component() = c.GetChildren()

            For Each child As Component In children
               child.SetAttribute("MY_ATTRIBUTE", "12345")
               'More processing
               'Code to move Components
            Next

Denis Huskic
Data Prep NX7.5
Kettering University
Class of '17
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor