Journal: Moving all objects to WCS
Journal: Moving all objects to WCS
(OP)
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: NX8 Journaling: Automating the Movement of Objects from one CSYS to the Part Absolute CSYS
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: NX8 Journaling: Automating the Movement of Objects from one CSYS to the Part Absolute CSYS
Denis Huskic
Data Prep
Kettering University
Class of '17





RE: Journal: Moving all objects to WCS
Are you moving components in an assembly file or bodies in a part file?
www.nxjournaling.com
RE: Journal: Moving all objects to WCS
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
RE: Journal: Moving all objects to WCS
From your question, I assume you want to use the current WCS as the "To CSYS", is this correct?
www.nxjournaling.com
RE: Journal: Moving all objects to 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
RE: Journal: Moving all objects to WCS
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
RE: Journal: Moving all objects to WCS
Denis Huskic
Data Prep
Kettering University
Class of '17
RE: Journal: Moving all objects to WCS
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
www.nxjournaling.com
RE: Journal: Moving all objects to WCS
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
RE: Journal: Moving all objects to WCS
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 Modulewww.nxjournaling.com
RE: Journal: Moving all objects to WCS
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
RE: Journal: Moving all objects to WCS
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 --> VB
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 SubCode 2 from GTAC: Sample NX Open .NET Visual Basic program : demo evaluate CAE geometry
CODE --> VB
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
RE: Journal: Moving all objects to WCS
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 Functionwww.nxjournaling.com
RE: Journal: Moving all objects to WCS
Denis Huskic
Data Prep NX7.5
Kettering University
Class of '17
RE: Journal: Moving all objects to WCS
www.nxjournaling.com
RE: Journal: Moving all objects to WCS
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
RE: Journal: Moving all objects to WCS
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
www.nxjournaling.com
RE: Journal: Moving all objects to WCS
I plan to use it with something similar to what I have below.
CODE --> vb
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 NextDenis Huskic
Data Prep NX7.5
Kettering University
Class of '17
RE: Journal: Moving all objects to WCS
Try searching the GTAC solution center, they may have some example code.
http://solutions.industrysoftware.automation.sieme...
If you don't find anything there, I'd suggest recording a journal while moving a component and modifying the resulting code to your use.
www.nxjournaling.com