Creating Lines, part 2

Associative Line Features

In this tutorial, we'll look at creating some associative lines. These will be fully associative to the defining geometry and will show up in the feature tree as line features. 

 

The first journal creates a line with an associative start and end point. This is equivalent to the interactive operation of creating a line with the associative option checked and typing in start and end point coordinates.

 

'NXJournaling.com
'create associative line example journal
'creates line from (1,2,0) to (4,5,0)
'tested on NX 7.5 and 8
 
 
Option Strict Off
Imports System
Imports NXOpen
 
Module Module1
 
    Sub Main()
 
        Dim theSession As Session = Session.GetSession()
        Dim workPart As Part = theSession.Parts.Work
        Dim lw As ListingWindow = theSession.ListingWindow
        lw.Open()
 
        Dim markId1 As Session.UndoMarkId
        markId1 = theSession.SetUndoMark(Session.MarkVisibility.Visible, "line journal")
 
        Dim nullFeatures_AssociativeLine As Features.AssociativeLine = Nothing
 
        Dim associativeLineBuilder1 As Features.AssociativeLineBuilder
        associativeLineBuilder1 = workPart.BaseFeatures.CreateAssociativeLineBuilder(nullFeatures_AssociativeLine)
 
        Dim unit1 As Unit
        unit1 = associativeLineBuilder1.Limits.StartLimit.Distance.Units
 
        associativeLineBuilder1.StartPointOptions = Features.AssociativeLineBuilder.StartOption.Point
        'start point X coordinate
        Dim expressionX1 As Expression
        expressionX1 = workPart.Expressions.CreateSystemExpressionWithUnits("1", unit1)
 
        Dim scalar1 As Scalar
        scalar1 = workPart.Scalars.CreateScalarExpression(expressionX1, Scalar.DimensionalityType.Length, SmartObject.UpdateOption.WithinModeling)
 
        'start point Y coordinate
        Dim expressionY1 As Expression
        expressionY1 = workPart.Expressions.CreateSystemExpressionWithUnits("2", unit1)
 
        Dim scalar2 As Scalar
        scalar2 = workPart.Scalars.CreateScalarExpression(expressionY1, Scalar.DimensionalityType.Length, SmartObject.UpdateOption.WithinModeling)
 
        'start point Z coordinate
        Dim expressionZ1 As Expression
        expressionZ1 = workPart.Expressions.CreateSystemExpressionWithUnits("0", unit1)
 
        Dim scalar3 As Scalar
        scalar3 = workPart.Scalars.CreateScalarExpression(expressionZ1, Scalar.DimensionalityType.Length, SmartObject.UpdateOption.WithinModeling)
 
        Dim point1 As Point
        point1 = workPart.Points.CreatePoint(scalar1, scalar2, scalar3, SmartObject.UpdateOption.WithinModeling)
 
        associativeLineBuilder1.StartPoint.Value = point1
 
        associativeLineBuilder1.EndPointOptions = Features.AssociativeLineBuilder.EndOption.Point
 
        'end point X coordinate
        Dim expressionX2 As Expression
        expressionX2 = workPart.Expressions.CreateSystemExpressionWithUnits("4", unit1)
 
        Dim scalar4 As Scalar
        scalar4 = workPart.Scalars.CreateScalarExpression(expressionX2, Scalar.DimensionalityType.Length, SmartObject.UpdateOption.WithinModeling)
 
        'end point Y coordinate
        Dim expressionY2 As Expression
        expressionY2 = workPart.Expressions.CreateSystemExpressionWithUnits("5", unit1)
 
        Dim scalar5 As Scalar
        scalar5 = workPart.Scalars.CreateScalarExpression(expressionY2, Scalar.DimensionalityType.Length, SmartObject.UpdateOption.WithinModeling)
 
        'end point Z coordinate
        Dim expressionZ2 As Expression
        expressionZ2 = workPart.Expressions.CreateSystemExpressionWithUnits("0", unit1)
 
        Dim scalar6 As Scalar
        scalar6 = workPart.Scalars.CreateScalarExpression(expressionZ2, Scalar.DimensionalityType.Length, SmartObject.UpdateOption.WithinModeling)
 
        Dim point2 As Point
        point2 = workPart.Points.CreatePoint(scalar4, scalar5, scalar6, SmartObject.UpdateOption.WithinModeling)
 
        associativeLineBuilder1.EndPoint.Value = point2
 
        'code as output by the journal recorder
        'Dim nXObject1 As NXObject
        'nXObject1 = associativeLineBuilder1.Commit()
 
        'code specific to our new line object
        Dim myLineFeature As Features.AssociativeLine
        myLineFeature = associativeLineBuilder1.Commit
 
        associativeLineBuilder1.Destroy()
 
        'do something with the new line feature
        lw.WriteLine("line feature timestamp: " & myLineFeature.Timestamp)
 
        'get entities created by the feature
        Dim myEntities() As NXObject
        myEntities = myLineFeature.GetEntities()
 
        'we created one line, so it should be the first (and only) entity returned
        Dim myLine As Line
        myLine = myEntities(0)
 
        lw.WriteLine("line length: " & myLine.GetLength.ToString)
        lw.WriteLine("line start: " & myLine.StartPoint.ToString)
        lw.WriteLine("line end: " & myLine.EndPoint.ToString)
 
        lw.Close()
 
    End Sub
 
 
    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 is largely a recorded journal that has been cleared of unnecessary code. It starts by creating theSession and workPart variables then creates an undo mark. The undo mark serves two purposes:

  1. a visible undo mark will show up in the undo list, allowing the user to undo the actions of the journal if necessary.
  2. should anything go horribly wrong in the statements following the undo mark, NX can restore itself to a known good state.

A unit variable is created that will reference the length units of the part the journal is run in; i.e. for a metric part the units will be mm, for an imperial part the units will be inch. The units variable will be used in the definition of the line start and end points.

 

An expression and scalar is created for each point coordinate. The expression will hold the coordinate value; in this journal they are simply integers but could be decimal numbers or equations involving other expressions. The expressions are created using the CreateSystemExpressionWithUnits method; there are several methods available when creating an expression, the system expression methods allow NX to manage the expression name. NX will choose a valid and available, if uninspired, name such as p402. If you want to give the expression a more meaningful name, or allow the user to input an expression name, you can rename an existing expression or use one of the creation methods that allow you to specify an expression name. If/when you or the user specifies an expression name, be sure to check that the name is currently unused and valid (some characters are illegal, check NX help for info on your version). The scalar is an internal object that will be used to associate the expression with the point object. When we create the scalar object we specify the expression we want it to be associated with, the dimensionality (which for this journal is length) and the update option. There are four update options available, within modeling means it will update right away, which is what we need to keep our line feature and any potential child features up to date. A point object is created for the line's start and end points. Like the scalar objects, these points are used internally in NX and will not show up in the feature tree or on the graphical display. The CreatePoint method used references the previously created scalar objects which allows the point locations to be driven by user editable expressions.

 

Once the points are created, all that is really left to do is assign those points to the associative line builder's start point and end point properties and calling the commit method. The Commit method returns the newly created object(s) from the builder. In the case of an AssociativeLineBuilder, an object of type Features.AssociativeLine is returned. The journal recorder creates an array of NXObject as a generic catch all. I have commented out these lines and instead created a more specific object to match the output. The associative line builder's Destroy method is then called to free up the memory used by this object. Then, to prove we have a reference to the line feature, its timestamp is output to the listing window. To get at the actual line object we created, we call the line feature's GetEntities() method; this method will return an array of type NXObject. We declare a variable of type Line and retrieve the first (and only) object from the myEntities array. To prove we have the line object we then use it to write some information out to the listing window.

 

Warning: DO NOT alter properties of this line object that would change its geometry (changing the start or end points, for instance). If you need to edit the associative line with a journal you should create an associative line builder object and pass it a reference to the line feature you wish to edit (a null reference creates a new line feature, a reference to an existing feature edits that feature).

 

Associative Tangent Lines

The next example journal will create two circles at random (the center points will fall within (-10,-10)-(10,10) and the radii will be between 1 and 4) then 2 associative tangent lines to create a "belt" like shape. Warning: it is possible that one circle will be created within the other; in this case the journal will error out because no tangent lines are possible. To keep the code short and readable, no checks are made for this error condition. If the code errors out, OK the dialog boxes, undo the operation and try running the journal again.

 

The associative line builder's start and end options will be set to Tangent, and the start and end values will be set to the created circles. Finally we will need to supply a start and end point. Don't worry, you do not have to calculate the exact start and end points that will result in the tangent line. The supplied points will help the NX solver determine which tangent line you want, similar to interactive NX - the side of the circle you pick determines which tangent line is created. For the first tangent line, we supply the arc center + the arc radius; and for the second tangent line we supply the arc center - the arc radius. After running the journal, move one or both of the circles to make sure the associative tangent lines update correctly.

 

The end of the journal is left as the journal recorder created it. If you need to refer to the line features or objects created modify it as in the first example journal.

 

'NXJournaling.com
'create associative tangent lines example
'this journal will create 2 circles at random (center point between (-10,-10) and (10,10), radius between 1 part unit and 4 part units)
'the journal will then create 2 associative lines tangent to these 2 circles
'*** may error out if one circle contains the other, there are no provisions in the code to check/handle this condition
'
'tested on NX 7.5 and 8
 
 
Option Strict Off
Imports System
Imports NXOpen
 
Module Module1
 
    Sub Main()
 
        Dim theSession As Session = Session.GetSession()
        Dim workPart As Part = theSession.Parts.Work
        'create random number generator
        Dim rnd1 As New Random()
 
        'set undo mark
        Dim markId1 As Session.UndoMarkId
        markId1 = theSession.SetUndoMark(Session.MarkVisibility.Visible, "Journal")
 
        'create matrix that will be used when creating the circles (absolute coordinate system)
        Dim identity As Matrix3x3
        identity.Xx = 1
        identity.Xy = 0
        identity.Xz = 0
        identity.Yx = 0
        identity.Yy = 1
        identity.Yz = 0
        identity.Zx = 0
        identity.Zy = 0
        identity.Zz = 1
 
        Dim circleCoordinateSystem As NXMatrix = workPart.NXMatrices.Create(identity)
 
        'generate circle center points and radii
        Dim c1 As Point3d = New Point3d(rnd1.Next(-10, 10), rnd1.Next(-10, 10), 0)
        Dim c2 As Point3d = New Point3d(rnd1.Next(-10, 10), rnd1.Next(-10, 10), 0)
        Dim cr1 As Double = rnd1.Next(1, 3) + rnd1.NextDouble
        Dim cr2 As Double = rnd1.Next(1, 3) + rnd1.NextDouble
 
        'create the circles
        Dim arc1 As Arc = workPart.Curves.CreateArc(c1, circleCoordinateSystem, cr1, 0, 2 * Math.PI)
        Dim arc2 As Arc = workPart.Curves.CreateArc(c2, circleCoordinateSystem, cr2, 0, 2 * Math.PI)
 
        'create null feature, when passed to the associative line builder this will create a new line
        '  to edit an existing line, pass the existing line feature to the associative line builder
        Dim nullFeatures_AssociativeLine As Features.AssociativeLine = Nothing
 
        Dim associativeLineBuilder1 As Features.AssociativeLineBuilder
        associativeLineBuilder1 = workPart.BaseFeatures.CreateAssociativeLineBuilder(nullFeatures_AssociativeLine)
 
        'set options for first tangent line
        associativeLineBuilder1.StartPointOptions = Features.AssociativeLineBuilder.StartOption.Tangent
        associativeLineBuilder1.StartTangent.Value = arc1
 
        associativeLineBuilder1.EndPointOptions = Features.AssociativeLineBuilder.EndOption.Tangent
        associativeLineBuilder1.EndTangent.Value = arc2
 
        Dim nullView As View = Nothing
 
        'create a point near where we want the tangent line to start
        Dim point1 As Point3d = New Point3d(arc1.CenterPoint.X + arc1.Radius, arc1.CenterPoint.Y + arc1.Radius, 0.0)
        associativeLineBuilder1.StartTangent.SetValue(arc1, nullView, point1)
 
        'create a point near where we want the tangent line to end
        Dim point2 As Point3d = New Point3d(arc2.CenterPoint.X + arc2.Radius, arc2.CenterPoint.Y + arc2.Radius, 0.0)
        associativeLineBuilder1.EndTangent.SetValue(arc2, nullView, point2)
 
        'the objects created by the associative line builder, returned as generic NXObjects
        Dim nXObject1 As NXObject
        nXObject1 = associativeLineBuilder1.Commit()
 
        Dim objects1() As NXObject
        objects1 = associativeLineBuilder1.GetCommittedObjects()
 
        'set options for second tangent line
        associativeLineBuilder1 = workPart.BaseFeatures.CreateAssociativeLineBuilder(nullFeatures_AssociativeLine)
 
        associativeLineBuilder1.StartPointOptions = Features.AssociativeLineBuilder.StartOption.Tangent
        associativeLineBuilder1.StartTangent.Value = arc1
 
        associativeLineBuilder1.EndPointOptions = Features.AssociativeLineBuilder.EndOption.Tangent
        associativeLineBuilder1.EndTangent.Value = arc2
 
        'create a point near where we want the tangent line to start, notice sign change from first tangent line
        point1 = New Point3d(arc1.CenterPoint.X - arc1.Radius, arc1.CenterPoint.Y - arc1.Radius, 0.0)
        associativeLineBuilder1.StartTangent.SetValue(arc1, nullView, point1)
 
        'create a point near where we want the tangent line to end, notice sign change from first tangent line
        point2 = New Point3d(arc2.CenterPoint.X - arc2.Radius, arc2.CenterPoint.Y - arc2.Radius, 0.0)
        associativeLineBuilder1.EndTangent.SetValue(arc2, nullView, point2)
 
        Dim nXObject2 As NXObject
        nXObject2 = associativeLineBuilder1.Commit()
 
        Dim objects2() As NXObject
        objects2 = associativeLineBuilder1.GetCommittedObjects()
 
        associativeLineBuilder1.Destroy()
 
 
    End Sub
 
 
    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

Comments

Do I must use Unit for every value. If my part is millimitric why I can't
Use The part Unit.
And please if this is the way NX work, What is the code for reassign all part unit values to millimitric or inches. In other words code to convert part unit.

Thanks In advance

In the first code sample the line will be drawn in the part's unit system. The line will start at (1,2,0) and end at (4,5,0). If the part is metric, the resulting line will be ~4.24 mm long (for an inch part the line will be ~4.24 in long).

The lines were created in part by creating expressions with units. To create these expressions requires the use of a "unit" object. You cannot use the workPart's PartUnit property because it returns an integer indicating whether the part units are inch or metric, it does not return a unit object.

If you need information on how to convert a part's unit system, there is a utility shipped with NX to do the job. In the NX help files, search for the term "ug_convert_part". After some digging in the help files, you may also want to look here: http://www.eng-tips.com/viewthread.cfm?qid=296279

Hi,

I try eventually to create a rectangle in a Sketch plane. I managed easily to draw an ellipse on this specific plane.
Now I'm trying the rectangle. All I see with the journal, is that a rectangle is 4 lines with constraints.

I have a special Sketch plane and an CSYS attached to it. I want to draw in this plane.
But when I record the journal, the coordinates used are the one from the original CSYS, not the last one in use.

Before calling the function to draw the rectangle I've put
pDatumCsys->SetWcsAtCsys();

But it doesn't seem to do anything about coordinates ...
If I want to draw a rectangle centered in in the new CSYS origin, the four points cooridnates will be :
Point1 ( -L/2, l/2,0)
Point2 (+L/2, l/2, 0)
Point3( +L/2,-l/2,0)
Point4( -L/2, -l/2,0)

L : length
l : width
But when I try to create lines with that I end up with an "object not in the plane" ...

My question is : How do I draw lines in a sketch with a specific DatumCSYS ?

The goal of drawing in a Sketch is to be in 2D, but I don't see how to do it ...

Please, help me !