Examine your geometry
Make Euclid proud
Even if you are a brand new user to NX, you should be familiar with the Examine Geometry command, it can be found in the Analysis menu. Running this check will ensure your model is valid during the modeling process and for downstream uses (drafting, FEA, CAM, etc). At a minimum, the model should be required to pass the face and body checks before releasing the file for production; also, running examine geometry is the recommended first step in troubleshooting should your file develop strange behavior (boolean operation failing, mass properties obviously incorrect, section view strangeness, shaded views missing faces, etc, etc). If you are unfamiliar with the command or just want more background, search the GTAC solution center with the phrase "examine geometry" to find several informative articles. There are links to three of the articles below, you will need a webkey to access the GTAC site.
Divide and Conquer
When you have a parameterized file that does not pass the geometry checks, it can become a tedious task to hunt down the offending geometry. When I starting using NX, I was taught a "divide and conquer" technique to help quickly identify the problem entities. The goal is to identify which feature in the history tree is causing the model to fail the checks. We put "bounds" around the bad feature and through a series of tests we can progressively narrow the bounds until we find the offending feature. The overall steps are as follows:
- The first feature is the lower bound (feature A), the last feature in the history tree is the upper bound (feature B).
- Unsuppress all features, fix any/all feature errors.
- Run examine geometry with all body and face checks set (at a minimum).
- Set the current feature in the tree to the point 1/2 way between the upper and lower bound, re-run the examine geometry checks.
- If the check fails, we know the error is somewhere between the lower bound (feature A) and the current feature. Make note of the current feature number, this becomes the new upper bound (feature B).
- If the check passes, we know the error is somewhere between the current feature and the upper bound (feature B). Make note of the current feature number, this becomes the new lower bound (feature A).
- Go to step 4 and repeat until you find the offending feature
The list above looks very much like an algorithm because, well... it is an algorithm. If you have studied numerical methods, you may recognize it bears a strong resemblance to the bisection root finding method.
Now that we have an algorithm, let's put it to use:
'NXJournaling.com 'January 9, 2013 'tested on NX 8 'journal version 0.11 (beta release) ' 0.11: fixed bug where journal would crash if "cancel" was clicked in the selection step 'Journal runs geometry checks (body structure, body consistency, face-face intersect, face self-intersect) 'on the selected solid. You do not need to window select the geometry (as you do with the examine geometry command), 'the journal will automatically select the faces of the selected solid body. 'If the solid does not pass one of the initial checks, the journal will search for the last feature in the history tree 'where the target solid passed all the checks. This feature will be made the current feature. '** Note: This does not necessarily mean that the next feature is causing the failure, but should serve as ' a good starting point in your search for the bad geometry. ' For example: suppose you have a file with 1000 features and the journal indicates feature 882 is the ' last valid state of the solid; this does not necessarily mean that SUBTRACT(883) is the problem. ' Perhaps the real problem is the geometry in THROUGH_CURVE_MESH(876) that trims the tool body of SUBTRACT(883). ' In this case, the journal simply indicates that the geometry that contributes to SUBTRACT(883) needs to be investigated. 'Usage notes: ' The journal will prompt for the selection of a solid body. ' If the body passes all the checks, a note indicating success will be written to the Information Window ' If the body fails a check, the journal will search for the last feature in the history tree where the selected body ' passed all the checks. ' The journal works best on parts that are fully parameterized and have no suppressed features or features with errors. ' There is no point of running this journal on a solid body that is a "body" feature (imported body), the examine geometry ' will serve better in this case. 'I don't consider this the 'final' version of this journal; there are other options and checks I'd like to add. 'Any suggestions, bug reports, or general feedback can be sent to firstname.lastname@example.org 'Thanks! Option Strict Off Imports System Imports NXOpen Imports NXOpen.UF Imports System.Collections.Generic Module examine_geometry Dim ufs As UFSession = UFSession.GetUFSession() Dim theSession As Session = Session.GetSession() Dim workPart As Part = theSession.Parts.Work Dim lw As ListingWindow = theSession.ListingWindow Sub Main() lw.Open() Dim myFeatures As Features.Feature() = workPart.Features.GetFeatures Dim featureCount As Integer = 0 Dim featureA As Integer = 0 Dim featureB As Integer = 0 Dim featureX As Integer = 0 Dim featureCheck As Features.Feature Dim featureList As New List(Of Features.Feature) For Each someFeature As Features.Feature In myFeatures If Not (someFeature.IsInternal Or someFeature.Suppressed) Then featureList.Add(someFeature) End If Next featureCount = featureList.Count 'lw.WriteLine("Feature count: " & featureCount.ToString) featureB = featureCount - 1 Dim mySolid As Body If SelectSolid("Select a solid body", mySolid) = Selection.Response.Cancel Then Exit Sub End If Dim partGood As Boolean = False partGood = GoodGeometry(mySolid) If Not partGood Then lw.WriteLine("Current feature: " & workPart.CurrentFeature.GetFeatureName) lw.WriteLine("Failed geometry check") Do Until (featureB - featureA) <= 1 featureX = featureA + (featureB - featureA) \ 2 lw.WriteLine("") featureCheck = featureList.Item(featureX) featureCheck.MakeCurrentFeature() lw.WriteLine("Current feature: " & workPart.CurrentFeature.GetFeatureName) partGood = GoodGeometry(mySolid) If partGood Then featureA = featureX Else featureB = featureX End If Loop lw.WriteLine("") lw.WriteLine("Current feature adjusted to last good state of selected solid") Else lw.WriteLine("Passed all geometry checks") End If End Sub Function GoodGeometry(ByVal someSolid As Body) As Boolean Dim myFaces() As Face = someSolid.GetFaces Dim badFacesEdges As Integer Dim faultTags(-1) As Tag Dim faultTokens(-1) As Integer Dim faceSelfIntersectPoint(2) As Double ufs.Modl.AskBodyStructures(someSolid.Tag, badFacesEdges, faultTags) If badFacesEdges = 0 Then lw.WriteLine("Passed Body Structure test") ufs.Modl.AskBodyConsistency(someSolid.Tag, badFacesEdges, faultTokens, faultTags) If badFacesEdges = 0 Then lw.WriteLine("Passed Body Consistency test") ufs.Modl.AskFaceFaceIntersect(someSolid.Tag, badFacesEdges, faultTags) If badFacesEdges = 0 Then lw.WriteLine("Passed Face Face Intersect test") For Each faceToTest As Face In myFaces ufs.Modl.AskFaceSelfIntersect(faceToTest.Tag, badFacesEdges, faceSelfIntersectPoint) If badFacesEdges = 0 Then 'lw.WriteLine("Face passed self-intersection test") Else lw.WriteLine("Failed Face self intersection test") Exit For Return False End If Next lw.WriteLine("Passed Face self intersection test") Return True Else lw.WriteLine("Failed Face Face Intersect test") Return False End If Else lw.WriteLine("Failed Body Consistency test") Return False End If Else lw.WriteLine("Failed Body Structure test") Return False End If lw.Close() End Function Function SelectSolid(ByVal prompt As String, ByRef selObj As NXObject) As Selection.Response Dim theUI As UI = UI.GetUI Dim title As String = "Select a solid body" 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.WorkPart Dim selectionMask_array(0) As Selection.MaskTriple With selectionMask_array(0) .Type = UFConstants.UF_solid_type .SolidBodySubtype = UFConstants.UF_UI_SEL_FEATURE_SOLID_BODY End With Dim resp As Selection.Response = theUI.SelectionManager.SelectObject(prompt, _ 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 'Unloads the image when the NX session terminates GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination End Function End Module
This journal is meant to be run on a fully parameterized model since it will search for the "last good feature". If you need to check unparameterized bodies, I'd suggest running the interactive Examine Geometry checks. If you only have one feature in the file (the unparameterized body feature) and it fails the checks, the journal may crash or do other strange things (I don't know exactly what it will do since I don't currently have such a file to check against).
Normally when you use the examine geometry command, you will window select around the solid body so that the body, all the faces, and all the edges get selected. The journal will prompt you to select a solid body, it will collect all the faces and edges it needs from this single selection. The journal will write messages to the information window as it runs to keep you informed as to what is happening. It currently only runs the body structure, body consistency, face face intersection, and face self intersection tests. If the solid of interest passes all of these checks, congratulations! you are done. If the solid does not pass one or more of the checks, the journal will run through the steps outlined above. The model will be left with the current feature set to the last one where the model passes all the checks. Check out the parent geometry for the next feature in the tree, chances are good it is causing the problem.
If you record a journal when using the examine geometry function, the code you will get will look very different from my code. There is an ExamineGeometry object that allows you to set the checks to run, run the checks, etc, etc. However, as of this writing, there is a bug with the GetResults method that causes the journal to crash. When this bug is fixed in a future update, I'd like to revisit this code and clean it up to use the .NET versions of the various functions.
This article is a good example of translating a process used in interactive NX, translating it to an algorithm, and finally implementing that algorithm into code. I hope it has resulted in a time-saving journal that you will find useful.
So, what manual processes are you following in NX? It's time to automate them!