Journal Creation Process

In this article (or series of articles, depending on how it goes), I'd like to provide some insight on the journal creation process. Over the past few weeks, I've been cleaning up older NX files for import to Teamcenter. As such, I've written a few small utilities to help inspect and sometimes modify the older files. Rather than just posting the finished code, I'd like to take this opportunity to work through the journal creation process with you. It can be a bit intimidating starting a new journal project: Where to start? Is what I want to do even possible through the API? If so, what commands are necessary?

In my experience, the journal programming process usually goes through these phases:

  1. Problem statement
  2. Research
  3. Planning
  4. Development
  5. Bug fixes/polish

The list above is more descriptive than prescriptive, often the boundaries between phases are blurred and you may need to circle back to one or more of the phases. For a small utility that you are writing for your own use, the problem statement and planning may be fairly minimal. For these types of projects, the problem statement and planning are kept in my head. For larger projects, it can help to write down the current workflow and what you hope to automate through the API. When writing code for others to use, this step can be critical to help ensure that you understand the users' issue and that they understand the limitations of the code solution.

Problem Statement

Without getting into too much detail, some of these older files have wave linked datum planes in them that I'd like to replace with fixed datum planes. Some sketches later in the feature order will reference these linked planes for positioning of sketch geometry. I usually create a new, fixed plane in the same location as the linked plane then use the "replace feature" command to swap them out. However, the replace feature command doesn't always correctly catch the sketch geometric and dimensional constraints, causing the operation to fail. Tracking down these references can be tricky. Selecting the sketch and looking in the dependencies window can show other objects that the sketch references, but it won't tell you how these other objects are referenced. Identifying constraints that reference external objects requires opening the sketch and examining the constraint list. Geometric constraints that reference external objects can be found by scanning the list and looking for "DATUM" or "EDGE". Finding sketch dimensions that refer to external objects is more difficult; the only way that I have found (so far) is to open the sketch and inspect the dimensions one by one.

What I'd like my journal to do is to scan through the current work part's sketches and report if constraints and/or dimensions reference an external object. If a dimension references an external object, I'd like a way to easily identify the dimension (by expression name and/or value). I'd like to send the name of the sketch along with the dimension and/or geometric constraint info to the listing window so I can reference it later.

Research/Planning

Based on past experience, I know that the NXOpen Part object has a .Sketches collection that give you direct access to all the sketches in the part. If you are new to programming with the NXOpen API, it is worth perusing the methods and properties available through the NXOpen Part object. The Part object is fundamental to nearly all journals as it gives you access to query existing geometry and create new objects.

Ok, so the .Sketches collection will give us access to each individual sketch, how do we get the geometric and dimensional constraints from the sketch? Looking at the documentation for a Sketch object, there are a number of methods for creating and deleting constraints; there must be a way to access and query existing constraints... Aha! The .GetAllConstraintsOfType method sounds very promising. This method will give us the geometric and/or dimensional constraints. Now we need to find a way to track these constraints back to the geometry used to define them. Eventually, we'll need to figure this out for both the dimensional and geometric constraint types; at the moment, I'm more interested in the dimensional constraints, so let's start there. Looking at the help docs for dimensional constraints, it looks like the .GetDimensionGeometry will return the desired objects directly.

At this point we can start writing some code to experiment with or we can use the one or more of the method names as a keyword to search the GTAC solution center and the various NX programming forums to learn more. The objects and methods seem fairly straight forward so far, so let's jump in and write some code.

Development

So, based on what we learned in our research, we'll need a For loop to process each and every sketch in the work part. Each sketch may contain zero or more dimensional constraints, so we'll need another For loop to process each dimensional constraint. Each dimensional constraint can reference 1 or 2 objects, so we'll need another For loop to get the object information. Note that the following code will almost certainly NOT be the final form. This first attempt will show us if we are calling the methods correctly (errors will be reported if we are really wrong) and to see what type of information we can pull out of the dimensional constraints. I really have no idea if .GetDimensionGeometry is going to return exactly what we are looking for, so we need to write some test code to find out and plan the next steps. Here's our code so far:


Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF

Module Module1

Dim theSession As Session = Session.GetSession()
Dim theUfSession As UFSession = UFSession.GetUFSession()

Dim theUI As UI = UI.GetUI()
Dim lw As ListingWindow = theSession.ListingWindow

Sub Main()

Dim markId1 As Session.UndoMarkId
markId1 = theSession.SetUndoMark(Session.MarkVisibility.Visible, "NXJ")

lw.Open()

For Each tempSketch As Sketch In theSession.Parts.Work.Sketches

Dim tempSketchFeat As Features.SketchFeature = tempSketch.Feature
lw.WriteLine(tempSketchFeat.GetFeatureName)
Dim mySketchDimConstraints() As SketchConstraint = tempSketch.GetAllConstraintsOfType(Sketch.ConstraintClass.Dimension, Sketch.ConstraintType.NoCon)

For Each tempConstraint As SketchDimensionalConstraint In mySketchDimConstraints
lw.WriteLine(tempConstraint.ConstraintType.ToString)

lw.WriteLine("dimension: " & tempConstraint.AssociatedDimension.ComputedSize.ToString)

Dim dimGeo() As Sketch.DimensionGeometry = tempConstraint.GetDimensionGeometry
For Each tempDimGeo As Sketch.DimensionGeometry In dimGeo
lw.WriteLine(tempDimGeo.Geometry.GetType.ToString)
Next

lw.WriteLine("")
Next

lw.WriteLine("")
Next

lw.Close()

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

Testing

For my first test case, I like to create a simple part file with a small number of features which definitely contains the symptoms that I'm looking for. The output from my first run looks something like below:

SKETCH_000:Sketch(1)
AngularDim
dimension: 60.7856200197316
NXOpen.Line
NXOpen.Line

ParallelDim
dimension: 8.50000000000001
NXOpen.Line
NXOpen.Line

SKETCH_001:Sketch(3)
PerpendicularDim
dimension: 1.4
NXOpen.DatumPlane
NXOpen.Line

PerpendicularDim
dimension: 0.900000000000007
NXOpen.Line
NXOpen.Edge

PerpendicularDim
dimension: 3
NXOpen.DatumAxis
NXOpen.Line

ParallelDim
dimension: 6.1
NXOpen.Line
NXOpen.Line

I should note that for this test I added the sketch dimension's .ComputedSize to the output so I could determine which dimension the info applied to. The dimensions as reported do not exactly match what is seen on screen in NX. To get that, we'd need to use the .GetDimensionText method, but that returns a couple of string arrays that you need to parse through to get exactly what you want. For this first pass, I thought it would be easier to just use the .ComputedSize property. We can refine this bit of the code later; I wanted to get something up and running quickly to test the rest of the code for now.

The good news is that there are no run time errors and the output seems to give us what we were looking for. Of the dimensions reported, one references a datum plane, another references an edge, and yet another references a datum axis. So far, so good; usually the first test ends with an error or unexpected output (occasionally it hangs up NX completely - but not often). Let's test on an actual part file; this particular part has over 1000 features, including dozens of sketches. Again, the journal completes with no errors and the output appears to be correct (I didn't double check all the sketches in this one). However, the order of sketches in the output seems a bit odd; they are not in the same order as the feature tree. Upon further inspection, it appears that the order of the part's .Sketches collection matches creation order and not necessarily the order of the part navigator features (features can be re-ordered after creation).

Bug Fixes/Polish

This article is getting rather lengthy, so I'll wrap it up here for now and continue in part 2. There were no run time errors to correct in our first attempt, so the next article will focus on modifying the code to better meet our needs. Specifically, I'd like to change the following:

  • the order of the reported sketches should match the part navigator (it will make processing the list easier for me)
  • the dimension as reported should match the dimension text on screen (dimensions driven by a formula rather than a simple value may pose an issue)
  • the expression name associated to the dimension should be reported. My current NX settings reports the expression name and dim value; I'd like the output to match.
  • geometric constraints that reference external geometry are not currently reported
  • reporting of sketches that contain no external references: I'm not sure that I want these on the list. I think it would be better to only report the sketches that I'm interested in.
  • TBD: other ideas for improvements/changes will likely surface as we work on the issue.

Conclusion (so far)

Hopefully this article gives you some insight on the first steps of the journal creation process. Start with what you know and take it one step at a time. Check the programming help documentation for properties and methods that may be of use (the NXOpen Part object type is a great place to start looking). If it looks straight forward, write some code to try it out; if you still have questions, use the property or method name in a GTAC solution center search (you will often find example code this way). Write code, test, and repeat until you have a useful journal that meets your needs.

I'll get back to my little project now and write up a part 2 so we can see where it ends up.
Happy coding!

Comments

Thanks a lot for your post! Very interesting read :)
I´m also trying to retrieve data from sketches, but I stumbled upon problems while getting information from coincident constraints.

I wanted to get the associativ Constraint Geometry but whenever I try to retrieve it a journal execution error appears. It says:"could not get class name for tag:2 error 3615009 ....."

Have you recognized something similar?

Does this happen on every sketch in every file? Do the sketches have any missing references? What version of NX are you using? Can you post your code (or at least the relevant parts)?

The error seems to appear randomly. Probably there is a reason but I can´t find it. What do you mean with missing references? The DOFs? Some of the sketches have fullfilled DOFs and some not..
Here is my code. Thanks a lot for your reply! :)

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using NXOpen;
using NXOpenUI;
using System.Windows.Forms;
using NXOpen.Features;
using NXOpen.Annotations;
using NXOpen.UF;
using NXOpen.Motion;

namespace GetSketchInformation
{
public class SketchFeatures
{
public static void Main(string[] args)
{
/////////////////////////////////////////////////// Basics
Session theSession = Session.GetSession();
NXOpen.UI theUI = UI.GetUI();
Part thePart = theSession.Parts.Work;
NXOpen.UF.UFSession theUf = NXOpen.UF.UFSession.GetUFSession();

ListingWindow lw = theSession.ListingWindow;
lw.Open();

// Create some arrays for the objects
SketchConstraint[] sketchConstraints;
Sketch.ConstraintGeometry[] constraintGeometries;
NXObject[] allObjects;

/////////////////////////////////////////////////// Get Constraint Informations

foreach (Sketch sketch in thePart.Sketches)
{
lw.WriteLine(" " + sketch.Name);

// Get all Geometric Objects of the Sketch
allObjects = sketch.GetAllGeometry();

//Journal works only for Lines!
foreach (Line line in allObjects)
{
lw.WriteLine(" Line Name " + line.Name);

// Get all Geometric Constraints associated with the line
sketchConstraints = sketch.GetConstraintsForGeometry(line, Sketch.ConstraintClass.Geometric);

foreach (SketchGeometricConstraint sketchConstraint in sketchConstraints)
{
lw.WriteLine(" Constraint Type " + sketchConstraint.ConstraintType);

try
{
// Get the associated ConstraintGeometries
constraintGeometries = sketchConstraint.GetGeometry();

foreach (Sketch.ConstraintGeometry constraintGeometry in constraintGeometries)
{
// Display Information about the Constraing Geometry
lw.WriteLine(" " + constraintGeometry.ToString());

}
}

catch (Exception ex)
{
lw.WriteLine(ex.Message);
theSession.LogFile.WriteLine(" Failed to get Information " + ex);

}

}

}

}

}
public static int GetUnloadOption(string arg)
{
return System.Convert.ToInt32(Session.LibraryUnloadOption.Immediately);
}
}

}

Forgot to say that I´m using NX Version 1903

I created a simple test file and ran your code, but it completed successfully. If you have an NX part file that shows the issue (that you are willing to share), you can email it to info@nxjournaling.com.

Is there anyway, by which we can open an html page in NX via Journal?
If there is any sort of journal please share.

Parthasarathi Nayak