Reference text update

Hello

I've put together a code for thread engraving. The problem is that it is not updating when the thread size changes, even thou reference text is checked on. How to make it parametric?

Here's the code

Imports System
Imports NXOpen
Imports NXOpen.UF
Imports NXOpen.Utilities
Imports MiniSnap
Imports NXOpen.Features
Imports System.Text.RegularExpressions
Imports System.IO

Module Text_on_face

Public theSession As NXOpen.Session = NXOpen.Session.GetSession()
Public theUfSession As UFSession = UFSession.GetUFSession()
Public workPart As NXOpen.Part = theSession.Parts.Work
Public ui As UI = UI.GetUI()
Public ufs As UFSession = UFSession.GetUFSession()
Public prompt As String = "Select Position on Face"
Public temptag As Tag = Tag.Null
Public cp(2) As Double
Public face1 As Face = Nothing
Public facetag As Tag = Tag.Null
Public pointC As Point = Nothing
Public displayPart As NXOpen.Part = theSession.Parts.Display
Public ok_click As Boolean
Public text2 As String
Public TextLayer As Integer = 45
Public text As String
Public lw As ListingWindow = theSession.ListingWindow
Dim myGeo As Features.Feature
Dim cancel As Boolean = False

Sub Main()

Dim lw As ListingWindow = theSession.ListingWindow
lw.Open()

Start1:

myGeo = SelectSymbolicThread("Select symbolic thread")
If myGeo Is Nothing Then
cancel = True
Exit Sub
End If

If myGeo.FeatureType.Equals("SYMBOLIC_THREAD") Then
' lw.WriteLine(myGeo.GetFeatureName())
Dim data As UFModl.SymbThreadData = New UFModl.SymbThreadData()
theUfSession.Modl.AskSymbThreadParms(myGeo.Tag, data)

Dim str As String = data.major_dia
Dim leftPart As String = str.Split("=")(0)
Dim expression1 As NXOpen.Expression = Nothing
Dim theExp As NXOpen.Expression = Nothing
Dim thr_exp As NXOpen.Expression = Nothing

Dim faceid As String = data.cyl_face.ToString()
Dim expression_a As String = "thr_txt" & "_" & faceid

Try
expression1 = workPart.Expressions.CreateExpression("String", expression_a & "=""M""+stringValue( " & leftPart & " )")
Catch ex As NXException
If ex.ErrorCode = 1050017 Then
'expression already exists
theExp = workPart.Expressions.FindObject(expression_a)
workPart.Expressions.Edit(theExp, """M""+stringValue( " & leftPart & ")")
Else
End If
End Try

thr_exp = workPart.Expressions.FindObject(expression_a)
text = "" & thr_exp.StringValue & ""

' lw.WriteLine(text)

End If

facetag = select_point_on_face(prompt, cp)

If facetag = Tag.Null Then GoTo End1
face1 = NXObjectManager.Get(facetag)
Dim pnt3d As Point3d = New Point3d(cp(0), cp(1), cp(2))

' ----------------------------------------------
Dim ufmodl As UFModl = theUfSession.Modl
Dim faceType As Integer
Dim facePt As Double() = New Double(2) {}
Dim faceDir As Double() = New Double(2) {}
Dim bbox As Double() = New Double(5) {}
Dim faceRadius As Double
Dim faceRadData As Double
Dim normDirection As Integer
Dim bodyObjFaceID As Tag
ufmodl.AskFaceData(facetag, faceType, facePt, faceDir, bbox, faceRadius, faceRadData, normDirection)
Dim dir As Vector = faceDir
Dim uvminmax As Double() = New Double(3) {}
ufmodl.AskFaceUvMinmax(facetag, uvminmax)
ufmodl.AskFaceBody(facetag, bodyObjFaceID)
Dim umin As Double = uvminmax(0)
Dim vmin As Double = uvminmax(2)
Dim surfaceValue As NXOpen.UF.ModlSrfValue = New NXOpen.UF.ModlSrfValue()
Dim mode As Integer = NXOpen.UF.UFConstants.UF_MODL_EVAL_UNIT_NORMAL
ufmodl.EvaluateFace(facetag, mode, New Double() {umin, vmin}, surfaceValue)
Dim u As Vector = surfaceValue.srf_du
Dim v As Vector = Vector.Cross(dir, u)
Dim oriview As MiniSnap.Orientation = New MiniSnap.Orientation(workPart.ModelingViews.WorkView.Matrix)
Dim a0 As Double = u * oriview.AxisX + v * oriview.AxisY
Dim a1 As Double = v * oriview.AxisX - u * oriview.AxisY
Dim a2 As Double = -u * oriview.AxisX - v * oriview.AxisY
Dim faceA As NXOpen.Face = face1
Dim text2DScale As Double = 130.0
Dim text3DScale As Double = 80
Dim nullNXOpen_Features_Text As NXOpen.Features.Text = Nothing

' ----------------------------------------------
Dim markId1 As NXOpen.Session.UndoMarkId = Nothing
markId1 = theSession.SetUndoMark(NXOpen.Session.MarkVisibility.Visible, "Start")

' ------------- Text Builder - START -----------------------------------------------
Dim unit1 As NXOpen.Unit = Nothing

Dim textBuilder2 As NXOpen.Features.TextBuilder = Nothing
textBuilder2 = workPart.Features.CreateTextBuilder(nullNXOpen_Features_Text)
unit1 = textBuilder2.PrintMarkThickness.Units
textBuilder2.CanReferenceText = True
textBuilder2.PlanarFrame.AnchorLocation = NXOpen.GeometricUtilities.RectangularFrameBuilder.AnchorLocationType.MiddleCenter

textBuilder2.PlanarFrame.WScale = text3DScale
textBuilder2.PlanarFrame.Shear.RightHandSide = "0"
textBuilder2.PrintMarkThickness.RightHandSide = "1"
textBuilder2.FrameOnPath.AnchorPosition.Expression.RightHandSide = "50"
textBuilder2.PlanarFrame.Length.RightHandSide = "10"
textBuilder2.PlanarFrame.Height.RightHandSide = "7"

textBuilder2.TextString = "" & text &""
textBuilder2.SelectFont("Arial", NXOpen.Features.TextBuilder.ScriptOptions.CentralEuropean)
theSession.SetUndoMarkName(markId1, "Text Dialog")
Dim xform2 As NXOpen.Xform = Nothing
xform2 = workPart.Xforms.CreateXform(faceA, NXOpen.SmartObject.UpdateOption.WithinModeling)
Dim cartesianCoordinateSystem2 As NXOpen.CartesianCoordinateSystem = Nothing
cartesianCoordinateSystem2 = workPart.CoordinateSystems.CreateCoordinateSystem(pnt3d, u, v)
textBuilder2.PlanarFrame.CoordinateSystem = cartesianCoordinateSystem2
ufs.Obj.DeleteObject(cartesianCoordinateSystem2.Tag)
textBuilder2.PlanarFrame.UpdateOnCoordinateSystem()
cartesianCoordinateSystem2.SetVisibility(SmartObject.VisibilityOption.Invisible)
cartesianCoordinateSystem2.Evaluate()
theSession.UpdateManager.ClearErrorList()
Dim nXObject2 As NXOpen.NXObject = Nothing
nXObject2 = textBuilder2.Commit()
textBuilder2.Destroy()

Dim allFeats() As Feature = displayPart.Features.ToArray()
Dim topFeat As Integer = allFeats.GetUpperBound(0)
Dim lastFeature As Feature = allFeats(topFeat)
Dim myCurve As Curve
Dim featTag As Tag = Tag.Null
Dim myFeature As Features.Feature

myFeature = Utilities.NXObjectManager.Get(lastFeature.Tag)
' lw.WriteLine("used by: " & myFeature.GetFeatureName)

Dim FeatStr As String = myFeature.ToString.Substring(0, 4)

If FeatStr = "Text" Then
Dim numObjs As Integer
Dim objs() As NXOpen.Tag = Nothing

ufs.Modl.AskFeatObject(myFeature.Tag, numObjs, objs)
For Each thisObj As NXOpen.Tag In objs
ufs.Obj.SetLayer(thisObj, TextLayer)
Next

End If

Dim stateArray1(0) As NXOpen.Layer.StateInfo
stateArray1(0) = New NXOpen.Layer.StateInfo(TextLayer, NXOpen.Layer.State.Hidden)
workPart.Layers.ChangeStates(stateArray1, False)

Dim section1 As Section
section1 = theSession.Parts.Work.Sections.CreateSection(0.00038, 0.0004, 0.5)
section1.SetAllowedEntityTypes(Section.AllowTypes.OnlyCurves)
Dim curveFeatureRule1 As CurveFeatureRule
curveFeatureRule1 = theSession.Parts.Work.ScRuleFactory.CreateRuleCurveFeature({myFeature})
section1.AllowSelfIntersection(True)
Dim rules1(0) As SelectionIntentRule
rules1(0) = curveFeatureRule1
Dim nullNXObject As NXObject = Nothing
section1.AddToSection(rules1, myCurve, nullNXObject, nullNXObject, Nothing, Section.Mode.Create, False)

Dim nullFeatures_Feature As Features.Feature = Nothing
Dim extrudeBuilder1 As Features.ExtrudeBuilder
extrudeBuilder1 = theSession.Parts.Work.Features.CreateExtrudeBuilder(nullFeatures_Feature)
extrudeBuilder1.Section = section1
extrudeBuilder1.Limits.SymmetricOption = True
extrudeBuilder1.Limits.StartExtend.Value.RightHandSide = ".1"
extrudeBuilder1.Limits.EndExtend.Value.RightHandSide = ".1"
extrudeBuilder1.Limits.StartExtend.TrimType = NXOpen.GeometricUtilities.Extend.ExtendType.Symmetric
extrudeBuilder1.Limits.EndExtend.TrimType = NXOpen.GeometricUtilities.Extend.ExtendType.Symmetric
extrudeBuilder1.AllowSelfIntersectingSection(True)
extrudeBuilder1.DistanceTolerance = 0.001
extrudeBuilder1.BooleanOperation.Type = GeometricUtilities.BooleanOperation.BooleanType.Create
extrudeBuilder1.BooleanOperation.Type = NXOpen.GeometricUtilities.BooleanOperation.BooleanType.Subtract
Dim The_Body As NXOpen.Body = NXObjectManager.Get(bodyObjFaceID)
Dim targetBodies2(0) As Body
targetBodies2(0) = The_Body
extrudeBuilder1.BooleanOperation.SetTargetBodies(targetBodies2)
Dim origin1 As Point3d = New Point3d(0.0, 0.0, 0.0)
Dim vector1 As Vector3d = New Vector3d(0.0, 0.0, 1.0)
Dim direction1 As Direction
direction1 = theSession.Parts.Work.Directions.CreateDirection(pnt3d, dir, SmartObject.UpdateOption.WithinModeling)
extrudeBuilder1.Direction = direction1
extrudeBuilder1.Draft.DraftOption = GeometricUtilities.SimpleDraft.SimpleDraftType.NoDraft
extrudeBuilder1.ParentFeatureInternal = False
Dim feature1 As Features.Feature
feature1 = extrudeBuilder1.CommitFeature()
extrudeBuilder1.Destroy()

' ------------------------ Text Builder - END -----------------------------------------------

GoTo Start1
End1:

End Sub

Public Sub map_view2abs(ByRef c() As Double)
Dim vname As String = ""
Dim abs_mx() As Double = {0, 0, 0, 1, 0, 0, 0, 1, 0}
Dim vw() As Double = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
Dim mx() As Double = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
Dim irc As Integer = 0
ufs.Ui.AskLastPickedView(vname)
Dim wp As Part = theSession.Parts.Work
Dim lastViewPicked As NXOpen.View = CType(wp.ModelingViews.FindObject(vname), ModelingView)
Dim vmx As Matrix3x3 = lastViewPicked.Matrix()
vw(3) = vmx.Xx
vw(4) = vmx.Xy
vw(5) = vmx.Xz
vw(6) = vmx.Yx
vw(7) = vmx.Yy
vw(8) = vmx.Yz
vw(9) = vmx.Zx
vw(10) = vmx.Zy
vw(11) = vmx.Zz
ufs.Trns.CreateCsysMappingMatrix(vw, abs_mx, mx, irc)
ufs.Trns.MapPosition(c, mx)
End Sub

Public Sub map_abs2view(ByRef c() As Double)
Dim vname As String = ""
Dim abs_mx() As Double = {0, 0, 0, 1, 0, 0, 0, 1, 0}
Dim vw() As Double = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
Dim mx() As Double = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
Dim irc As Integer = 0
ufs.Ui.AskLastPickedView(vname)
Dim wp As Part = theSession.Parts.Work
Dim lastViewPicked As NXOpen.View =
CType(wp.ModelingViews.FindObject(vname), ModelingView)
Dim vmx As Matrix3x3 = lastViewPicked.Matrix()
vw(3) = vmx.Xx
vw(4) = vmx.Xy
vw(5) = vmx.Xz
vw(6) = vmx.Yx
vw(7) = vmx.Yy
vw(8) = vmx.Yz
vw(9) = vmx.Zx
vw(10) = vmx.Zy
vw(11) = vmx.Zz
ufs.Trns.CreateCsysMappingMatrix(abs_mx, vw, mx, irc)
ufs.Trns.MapPosition(c, mx)

End Sub

Public Sub ask_pos_on_obj(ByVal obj As NXOpen.Tag, ByVal loc() As Double)
Dim aLine As NXOpen.Tag = NXOpen.Tag.Null
Dim cp() As Double = {0, 0, 0}
Dim dist As Double = 0
Dim lp As UFCurve.Line
Dim sp(2) As Double
Dim ep(2) As Double
lp.start_point = sp
lp.end_point = ep
map_abs2view(loc)
lp.start_point(0) = loc(0)
lp.start_point(1) = loc(1)
lp.start_point(2) = loc(2) + 10000
lp.end_point(0) = loc(0)
lp.end_point(1) = loc(1)
lp.end_point(2) = loc(2) - 10000
map_view2abs(lp.start_point)
map_view2abs(lp.end_point)
ufs.Curve.CreateLine(lp, aLine)
ufs.Modl.AskMinimumDist(obj, aLine, 0, cp, 0, cp, dist, loc, cp)
ufs.Obj.DeleteObject(aLine)
End Sub

Public Function mask_for_face(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 = 0
mask_triples(0).solid_type = UFConstants.UF_UI_SEL_FEATURE_ANY_FACE
ufs.Ui.SetSelMask(select_,
UFUi.SelMaskAction.SelMaskClearAndEnableSpecific,
num_triples, mask_triples)
Return UFConstants.UF_UI_SEL_SUCCESS
End Function

Public Function select_point_on_face(ByVal prompt As String, ByRef cp() As Double) As NXOpen.Tag
Dim resp As Integer = 0
Dim thing As NXOpen.Tag = NXOpen.Tag.Null
Dim face1 As Face = Nothing
Dim theView As NXOpen.Tag = NXOpen.Tag.Null
Dim mask_face As UFUi.SelInitFnT = AddressOf mask_for_face
Dim facetag As Tag = Tag.Null
ufs.Ui.LockUgAccess(UFConstants.UF_UI_FROM_CUSTOM)
ufs.Ui.SelectWithSingleDialog("Select a face", prompt,
UFConstants.UF_UI_SEL_SCOPE_ANY_IN_ASSEMBLY,
mask_face, Nothing, resp, facetag, cp, theView)
ufs.Ui.UnlockUgAccess(UFConstants.UF_UI_FROM_CUSTOM)
If resp = UFConstants.UF_UI_OBJECT_SELECTED Or
resp = UFConstants.UF_UI_OBJECT_SELECTED_BY_NAME Then
ask_pos_on_obj(facetag, cp)
ufs.Disp.SetHighlight(facetag, 0)
Return facetag
End If
Return Tag.Null
End Function

Public Function PointFeatureOnFace(ByVal where As Point3d) As Point
Dim markId1 As Session.UndoMarkId = theSession.SetUndoMark(Session.MarkVisibility.Visible, "Create Point")
Dim point1 As Point
point1 = workPart.Points.CreatePoint(where)
Dim nullFeatures_Feature As Features.Feature = Nothing
Dim pointFeatureBuilder1 As Features.PointFeatureBuilder
pointFeatureBuilder1 = workPart.BaseFeatures.CreatePointFeatureBuilder(nullFeatures_Feature)
pointFeatureBuilder1.Point = point1
Dim nXObject1 As NXObject = pointFeatureBuilder1.Commit()
pointFeatureBuilder1.Destroy()
Return point1
End Function

Function SelectSymbolicThread(ByVal prompt As String) As Features.Feature

Dim response As Integer = 0
Dim objs() As Tag = Nothing
Dim user_data As System.IntPtr
Dim selTag As Tag = Nothing
Dim cursor(2) As Double
Dim view As Tag = Nothing

theUfSession.Ui.LockUgAccess(UFConstants.UF_UI_FROM_CUSTOM)

Dim cursorView As Integer
theUfSession.Ui.AskCursorView(cursorView)
theUfSession.Ui.SetCursorView(0)

Try
theUfSession.Ui.SelectWithSingleDialog("Select symbolic thread arc: ", prompt,
UFConstants.UF_UI_SEL_SCOPE_ANY_IN_ASSEMBLY, AddressOf init_proc_body,
user_data, response, selTag, cursor, view)
Finally
theUfSession.Ui.UnlockUgAccess(UFConstants.UF_UI_FROM_CUSTOM)
theUfSession.Ui.SetCursorView(cursorView)
End Try

If Not selTag.Equals(Tag.Null) Then

'the SelectWithSingleDialog method returns a tag,
'return the object from the given tag
Dim myCurve As Curve = Utilities.NXObjectManager.Get(selTag)
Dim featTag As Tag = Tag.Null
Dim myFeature As Features.Feature = Nothing

theUfSession.Modl.AskObjectFeat(myCurve.Tag, featTag)

myFeature = Utilities.NXObjectManager.Get(featTag)

theUfSession.Disp.SetHighlight(selTag, 0)
Return myFeature
Else
Return Nothing
End If

End Function

Function init_proc_body(ByVal select_ As IntPtr,
ByVal userdata As IntPtr) As Integer
'this function must have the same signature as UFUi.SelInitFnT Delegate

'setup mask to filter for arcs, lines, and silhouette curves
Dim mask_triples As UFUi.Mask() = New UFUi.Mask(1) {}
mask_triples(0).object_type = UFConstants.UF_circle_type
mask_triples(0).object_subtype = 0
mask_triples(0).solid_type = 0

mask_triples(1).object_type = UFConstants.UF_line_type
mask_triples(1).object_subtype = 0
mask_triples(1).solid_type = 0

theUfSession.Ui.SetSelMask(select_,
UFUi.SelMaskAction.SelMaskClearAndEnableSpecific,
mask_triples.Length, mask_triples)

theUfSession.Ui.SetSelProcs(select_, AddressOf HoleFeatureFilter, Nothing, userdata)

Return UFConstants.UF_UI_SEL_SUCCESS

End Function

Function HoleFeatureFilter(ByVal _object As Tag,
ByVal type As Integer(),
ByVal user_data As IntPtr,
ByVal select_ As IntPtr) As Integer
'type, user_data, and select_ are unused (in this implementation), but this function must have
'the same signature as UFUi.SelFilterFnT Delegate

Dim myCurve As Curve = Utilities.NXObjectManager.Get(_object)
Dim featTag As Tag = Tag.Null
Dim myFeature As Features.Feature = Nothing

theUfSession.Modl.AskObjectFeat(myCurve.Tag, featTag)

myFeature = Utilities.NXObjectManager.Get(featTag)
If myFeature.FeatureType = "SYMBOLIC_THREAD" Then
Return UFConstants.UF_UI_SEL_ACCEPT
Else
Return UFConstants.UF_UI_SEL_REJECT
End If

End Function

Public Function GetUnloadOption(ByVal dummy As String) As Integer
'----Other unload options-------
'Unloads the image immediately after execution within NX
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
End Function

End Module

A couple of things stood out while reviewing your code:
1) If you want to text to update, you need to reference an expression. The original code created a string variable and used it in the text builder object. The string variable created in code is not associated to anything in the model. Once the journal exits, the text feature is left with a constant string value.
2) Even after updating the text feature to point to the "major diameter" expression, the value would not update after editing the hole size. I'm not sure why. Even though the expression value updated, the text and extrude features would not follow without a model update. The code below makes use of the "thread size" expression, which does change as expected after editing the hole feature.

Imports System
Imports NXOpen
Imports NXOpen.UF
Imports NXOpen.Utilities
Imports MiniSnap
Imports NXOpen.Features
Imports System.Text.RegularExpressions
Imports System.IO

Module Text_on_face

Public theSession As NXOpen.Session = NXOpen.Session.GetSession()
Public theUfSession As UFSession = ufsession.GetUFSession()
Public workPart As NXOpen.Part = theSession.Parts.Work
Public ui As UI = ui.GetUI()
Public ufs As UFSession = ufsession.GetUFSession()
Public prompt As String = "Select Position on Face"
Public temptag As Tag = Tag.Null
Public cp(2) As Double
Public face1 As Face = Nothing
Public facetag As Tag = Tag.Null
Public pointC As Point = Nothing
Public displayPart As NXOpen.Part = theSession.Parts.Display
Public ok_click As Boolean
Public text2 As String
Public TextLayer As Integer = 45
Public text As String
Public lw As ListingWindow = theSession.ListingWindow
Dim myGeo As Features.Feature
Dim cancel As Boolean = False

Sub Main()

Dim lw As ListingWindow = theSession.ListingWindow
lw.Open()

Start1:

Dim expThreadSize As Expression = Nothing

myGeo = SelectSymbolicThread("Select symbolic thread")
If myGeo Is Nothing Then
cancel = True
Exit Sub
Else
'lw.WriteLine("myGeo: " & myGeo.GetFeatureName)
For Each tempExp As Expression In theSession.Parts.Work.Expressions
If IsNothing(tempExp.GetOwningFeature) Then
'skip this one
Continue For
End If
'lw.WriteLine("owning feature: " & tempExp.GetOwningFeature.GetFeatureName)
If tempExp.GetOwningFeature.Timestamp = myGeo.Timestamp Then
'look for thread size expression
If tempExp.GetDescriptor.ToUpper.Contains("SIZE") Then
expThreadSize = tempExp
'lw.WriteLine("thread size exp: " & expThreadSize.Name)
End If
End If
Next
End If

Dim str As String = ""
Dim leftPart As String = ""
Dim theExp As NXOpen.Expression = Nothing
Dim thr_exp As NXOpen.Expression = Nothing
Dim faceid As String = ""
Dim expression_a As String = ""

If myGeo.FeatureType.Equals("SYMBOLIC_THREAD") Then
' lw.WriteLine(myGeo.GetFeatureName())
Dim data As UFModl.SymbThreadData = New UFModl.SymbThreadData()
theUfSession.Modl.AskSymbThreadParms(myGeo.Tag, data)
str = data.major_dia
leftPart = str.Split("=")(0)
faceid = data.cyl_face.ToString()
expression_a = "thr_txt" & "_" & faceid

Try
theExp = workPart.Expressions.CreateExpression("String", expression_a & "=replacestring(first(splitstring(p100,""x"")), "" "", """")")
Catch ex As NXException
If ex.ErrorCode = 1050017 Then
'expression already exists
theExp = workPart.Expressions.FindObject(expression_a)
workPart.Expressions.Edit(theExp, "replacestring(first(splitstring(p100,""x"")), "" "", """")")
Else
End If
End Try

thr_exp = workPart.Expressions.FindObject(expression_a)
text = "" & thr_exp.StringValue & ""

'lw.WriteLine("text: " & text)
'lw.WriteLine("str: " & str)

End If

facetag = select_point_on_face(prompt, cp)

If facetag = Tag.Null Then GoTo End1
face1 = NXObjectManager.Get(facetag)
Dim pnt3d As Point3d = New Point3d(cp(0), cp(1), cp(2))

' ----------------------------------------------
Dim ufmodl As UFModl = theUfSession.Modl
Dim faceType As Integer
Dim facePt As Double() = New Double(2) {}
Dim faceDir As Double() = New Double(2) {}
Dim bbox As Double() = New Double(5) {}
Dim faceRadius As Double
Dim faceRadData As Double
Dim normDirection As Integer
Dim bodyObjFaceID As Tag
ufmodl.AskFaceData(facetag, faceType, facePt, faceDir, bbox, faceRadius, faceRadData, normDirection)
Dim dir As Vector = faceDir
Dim uvminmax As Double() = New Double(3) {}
ufmodl.AskFaceUvMinmax(facetag, uvminmax)
ufmodl.AskFaceBody(facetag, bodyObjFaceID)
Dim umin As Double = uvminmax(0)
Dim vmin As Double = uvminmax(2)
Dim surfaceValue As NXOpen.UF.ModlSrfValue = New NXOpen.UF.ModlSrfValue()
Dim mode As Integer = NXOpen.UF.UFConstants.UF_MODL_EVAL_UNIT_NORMAL
ufmodl.EvaluateFace(facetag, mode, New Double() {umin, vmin}, surfaceValue)
Dim u As Vector = surfaceValue.srf_du
Dim v As Vector = Vector.Cross(dir, u)
Dim oriview As MiniSnap.Orientation = New MiniSnap.Orientation(workPart.ModelingViews.WorkView.Matrix)
Dim a0 As Double = u * oriview.AxisX + v * oriview.AxisY
Dim a1 As Double = v * oriview.AxisX - u * oriview.AxisY
Dim a2 As Double = -u * oriview.AxisX - v * oriview.AxisY
Dim faceA As NXOpen.Face = face1
Dim text2DScale As Double = 130.0
Dim text3DScale As Double = 80
Dim nullNXOpen_Features_Text As NXOpen.Features.Text = Nothing

' ----------------------------------------------
Dim markId1 As NXOpen.Session.UndoMarkId = Nothing
markId1 = theSession.SetUndoMark(NXOpen.Session.MarkVisibility.Visible, "Start")

' ------------- Text Builder - START -----------------------------------------------
Dim unit1 As NXOpen.Unit = Nothing

Dim textBuilder2 As NXOpen.Features.TextBuilder = Nothing
textBuilder2 = workPart.Features.CreateTextBuilder(nullNXOpen_Features_Text)
unit1 = textBuilder2.PrintMarkThickness.Units
textBuilder2.CanReferenceText = True
textBuilder2.PlanarFrame.AnchorLocation = NXOpen.GeometricUtilities.RectangularFrameBuilder.AnchorLocationType.MiddleCenter

textBuilder2.PlanarFrame.WScale = text3DScale
textBuilder2.PlanarFrame.Shear.RightHandSide = "0"
textBuilder2.PrintMarkThickness.RightHandSide = "1"
textBuilder2.FrameOnPath.AnchorPosition.Expression.RightHandSide = "50"
textBuilder2.PlanarFrame.Length.RightHandSide = "10"
textBuilder2.PlanarFrame.Height.RightHandSide = "7"

'textBuilder2.TextString = "" & text &""
textBuilder2.Text.RightHandSide = thr_exp.Name

textBuilder2.SelectFont("Arial", NXOpen.Features.TextBuilder.ScriptOptions.CentralEuropean)
theSession.SetUndoMarkName(markId1, "Text Dialog")
Dim xform2 As NXOpen.Xform = Nothing
xform2 = workPart.Xforms.CreateXform(faceA, NXOpen.SmartObject.UpdateOption.WithinModeling)
Dim cartesianCoordinateSystem2 As NXOpen.CartesianCoordinateSystem = Nothing
cartesianCoordinateSystem2 = workPart.CoordinateSystems.CreateCoordinateSystem(pnt3d, u, v)
textBuilder2.PlanarFrame.CoordinateSystem = cartesianCoordinateSystem2
ufs.Obj.DeleteObject(cartesianCoordinateSystem2.Tag)
textBuilder2.PlanarFrame.UpdateOnCoordinateSystem()
cartesianCoordinateSystem2.SetVisibility(SmartObject.VisibilityOption.Invisible)
cartesianCoordinateSystem2.Evaluate()
theSession.UpdateManager.ClearErrorList()
Dim nXObject2 As NXOpen.NXObject = Nothing
nXObject2 = textBuilder2.Commit()
textBuilder2.Destroy()

Dim allFeats() As Feature = displayPart.Features.ToArray()
Dim topFeat As Integer = allFeats.GetUpperBound(0)
Dim lastFeature As Feature = allFeats(topFeat)
Dim myCurve As Curve
Dim featTag As Tag = Tag.Null
Dim myFeature As Features.Feature

myFeature = Utilities.NXObjectManager.Get(lastFeature.Tag)
' lw.WriteLine("used by: " & myFeature.GetFeatureName)

Dim FeatStr As String = myFeature.ToString.Substring(0, 4)

If FeatStr = "Text" Then
Dim numObjs As Integer
Dim objs() As NXOpen.Tag = Nothing

ufs.Modl.AskFeatObject(myFeature.Tag, numObjs, objs)
For Each thisObj As NXOpen.Tag In objs
ufs.Obj.SetLayer(thisObj, TextLayer)
Next

End If

Dim stateArray1(0) As NXOpen.Layer.StateInfo
stateArray1(0) = New NXOpen.Layer.StateInfo(TextLayer, NXOpen.Layer.State.Hidden)
workPart.Layers.ChangeStates(stateArray1, False)

Dim section1 As Section
section1 = theSession.Parts.Work.Sections.CreateSection(0.00038, 0.0004, 0.5)
section1.SetAllowedEntityTypes(Section.AllowTypes.OnlyCurves)
Dim curveFeatureRule1 As CurveFeatureRule
curveFeatureRule1 = theSession.Parts.Work.ScRuleFactory.CreateRuleCurveFeature({myFeature})
section1.AllowSelfIntersection(True)
Dim rules1(0) As SelectionIntentRule
rules1(0) = curveFeatureRule1
Dim nullNXObject As NXObject = Nothing
section1.AddToSection(rules1, myCurve, nullNXObject, nullNXObject, Nothing, Section.Mode.Create, False)

Dim nullFeatures_Feature As Features.Feature = Nothing
Dim extrudeBuilder1 As Features.ExtrudeBuilder
extrudeBuilder1 = theSession.Parts.Work.Features.CreateExtrudeBuilder(nullFeatures_Feature)
extrudeBuilder1.Section = section1
extrudeBuilder1.Limits.SymmetricOption = True
extrudeBuilder1.Limits.StartExtend.Value.RightHandSide = ".1"
extrudeBuilder1.Limits.EndExtend.Value.RightHandSide = ".1"
extrudeBuilder1.Limits.StartExtend.TrimType = NXOpen.GeometricUtilities.Extend.ExtendType.Symmetric
extrudeBuilder1.Limits.EndExtend.TrimType = NXOpen.GeometricUtilities.Extend.ExtendType.Symmetric
extrudeBuilder1.AllowSelfIntersectingSection(True)
extrudeBuilder1.DistanceTolerance = 0.001
extrudeBuilder1.BooleanOperation.Type = GeometricUtilities.BooleanOperation.BooleanType.Create
extrudeBuilder1.BooleanOperation.Type = NXOpen.GeometricUtilities.BooleanOperation.BooleanType.Subtract
Dim The_Body As NXOpen.Body = NXObjectManager.Get(bodyObjFaceID)
Dim targetBodies2(0) As Body
targetBodies2(0) = The_Body
extrudeBuilder1.BooleanOperation.SetTargetBodies(targetBodies2)
Dim origin1 As Point3d = New Point3d(0.0, 0.0, 0.0)
Dim vector1 As Vector3d = New Vector3d(0.0, 0.0, 1.0)
Dim direction1 As Direction
direction1 = theSession.Parts.Work.Directions.CreateDirection(pnt3d, dir, SmartObject.UpdateOption.WithinModeling)
extrudeBuilder1.Direction = direction1
extrudeBuilder1.Draft.DraftOption = GeometricUtilities.SimpleDraft.SimpleDraftType.NoDraft
extrudeBuilder1.ParentFeatureInternal = False
Dim feature1 As Features.Feature
feature1 = extrudeBuilder1.CommitFeature()
extrudeBuilder1.Destroy()

' ------------------------ Text Builder - END -----------------------------------------------

GoTo Start1
End1:

End Sub

Public Sub map_view2abs(ByRef c() As Double)
Dim vname As String = ""
Dim abs_mx() As Double = {0, 0, 0, 1, 0, 0, 0, 1, 0}
Dim vw() As Double = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
Dim mx() As Double = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
Dim irc As Integer = 0
ufs.Ui.AskLastPickedView(vname)
Dim wp As Part = theSession.Parts.Work
Dim lastViewPicked As NXOpen.View = CType(wp.ModelingViews.FindObject(vname), ModelingView)
Dim vmx As Matrix3x3 = lastViewPicked.Matrix()
vw(3) = vmx.Xx
vw(4) = vmx.Xy
vw(5) = vmx.Xz
vw(6) = vmx.Yx
vw(7) = vmx.Yy
vw(8) = vmx.Yz
vw(9) = vmx.Zx
vw(10) = vmx.Zy
vw(11) = vmx.Zz
ufs.Trns.CreateCsysMappingMatrix(vw, abs_mx, mx, irc)
ufs.Trns.MapPosition(c, mx)
End Sub

Public Sub map_abs2view(ByRef c() As Double)
Dim vname As String = ""
Dim abs_mx() As Double = {0, 0, 0, 1, 0, 0, 0, 1, 0}
Dim vw() As Double = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
Dim mx() As Double = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
Dim irc As Integer = 0
ufs.Ui.AskLastPickedView(vname)
Dim wp As Part = theSession.Parts.Work
Dim lastViewPicked As NXOpen.View =
CType(wp.ModelingViews.FindObject(vname), ModelingView)
Dim vmx As Matrix3x3 = lastViewPicked.Matrix()
vw(3) = vmx.Xx
vw(4) = vmx.Xy
vw(5) = vmx.Xz
vw(6) = vmx.Yx
vw(7) = vmx.Yy
vw(8) = vmx.Yz
vw(9) = vmx.Zx
vw(10) = vmx.Zy
vw(11) = vmx.Zz
ufs.Trns.CreateCsysMappingMatrix(abs_mx, vw, mx, irc)
ufs.Trns.MapPosition(c, mx)

End Sub

Public Sub ask_pos_on_obj(ByVal obj As NXOpen.Tag, ByVal loc() As Double)
Dim aLine As NXOpen.Tag = NXOpen.Tag.Null
Dim cp() As Double = {0, 0, 0}
Dim dist As Double = 0
Dim lp As UFCurve.Line
Dim sp(2) As Double
Dim ep(2) As Double
lp.start_point = sp
lp.end_point = ep
map_abs2view(loc)
lp.start_point(0) = loc(0)
lp.start_point(1) = loc(1)
lp.start_point(2) = loc(2) + 10000
lp.end_point(0) = loc(0)
lp.end_point(1) = loc(1)
lp.end_point(2) = loc(2) - 10000
map_view2abs(lp.start_point)
map_view2abs(lp.end_point)
ufs.Curve.CreateLine(lp, aLine)
ufs.Modl.AskMinimumDist(obj, aLine, 0, cp, 0, cp, dist, loc, cp)
ufs.Obj.DeleteObject(aLine)
End Sub

Public Function mask_for_face(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 = 0
mask_triples(0).solid_type = UFConstants.UF_UI_SEL_FEATURE_ANY_FACE
ufs.Ui.SetSelMask(select_,
UFUi.SelMaskAction.SelMaskClearAndEnableSpecific,
num_triples, mask_triples)
Return UFConstants.UF_UI_SEL_SUCCESS
End Function

Public Function select_point_on_face(ByVal prompt As String, ByRef cp() As Double) As NXOpen.Tag
Dim resp As Integer = 0
Dim thing As NXOpen.Tag = NXOpen.Tag.Null
Dim face1 As Face = Nothing
Dim theView As NXOpen.Tag = NXOpen.Tag.Null
Dim mask_face As UFUi.SelInitFnT = AddressOf mask_for_face
Dim facetag As Tag = Tag.Null
ufs.Ui.LockUgAccess(UFConstants.UF_UI_FROM_CUSTOM)
ufs.Ui.SelectWithSingleDialog("Select a face", prompt,
UFConstants.UF_UI_SEL_SCOPE_ANY_IN_ASSEMBLY,
mask_face, Nothing, resp, facetag, cp, theView)
ufs.Ui.UnlockUgAccess(UFConstants.UF_UI_FROM_CUSTOM)
If resp = UFConstants.UF_UI_OBJECT_SELECTED Or
resp = UFConstants.UF_UI_OBJECT_SELECTED_BY_NAME Then
ask_pos_on_obj(facetag, cp)
ufs.Disp.SetHighlight(facetag, 0)
Return facetag
End If
Return Tag.Null
End Function

Public Function PointFeatureOnFace(ByVal where As Point3d) As Point
Dim markId1 As Session.UndoMarkId = theSession.SetUndoMark(Session.MarkVisibility.Visible, "Create Point")
Dim point1 As Point
point1 = workPart.Points.CreatePoint(where)
Dim nullFeatures_Feature As Features.Feature = Nothing
Dim pointFeatureBuilder1 As Features.PointFeatureBuilder
pointFeatureBuilder1 = workPart.BaseFeatures.CreatePointFeatureBuilder(nullFeatures_Feature)
pointFeatureBuilder1.Point = point1
Dim nXObject1 As NXObject = pointFeatureBuilder1.Commit()
pointFeatureBuilder1.Destroy()
Return point1
End Function

Function SelectSymbolicThread(ByVal prompt As String) As Features.Feature

Dim response As Integer = 0
Dim objs() As Tag = Nothing
Dim user_data As System.IntPtr
Dim selTag As Tag = Nothing
Dim cursor(2) As Double
Dim view As Tag = Nothing

theUfSession.Ui.LockUgAccess(UFConstants.UF_UI_FROM_CUSTOM)

Dim cursorView As Integer
theUfSession.Ui.AskCursorView(cursorView)
theUfSession.Ui.SetCursorView(0)

Try
theUfSession.Ui.SelectWithSingleDialog("Select symbolic thread arc: ", prompt,
UFConstants.UF_UI_SEL_SCOPE_ANY_IN_ASSEMBLY, AddressOf init_proc_body,
user_data, response, selTag, cursor, view)
Finally
theUfSession.Ui.UnlockUgAccess(UFConstants.UF_UI_FROM_CUSTOM)
theUfSession.Ui.SetCursorView(cursorView)
End Try

If Not selTag.Equals(Tag.Null) Then

'the SelectWithSingleDialog method returns a tag,
'return the object from the given tag
Dim myCurve As Curve = Utilities.NXObjectManager.Get(selTag)
Dim featTag As Tag = Tag.Null
Dim myFeature As Features.Feature = Nothing

theUfSession.Modl.AskObjectFeat(myCurve.Tag, featTag)

myFeature = Utilities.NXObjectManager.Get(featTag)

theUfSession.Disp.SetHighlight(selTag, 0)
Return myFeature
Else
Return Nothing
End If

End Function

Function init_proc_body(ByVal select_ As IntPtr,
ByVal userdata As IntPtr) As Integer
'this function must have the same signature as UFUi.SelInitFnT Delegate

'setup mask to filter for arcs, lines, and silhouette curves
Dim mask_triples As UFUi.Mask() = New UFUi.Mask(1) {}
mask_triples(0).object_type = UFConstants.UF_circle_type
mask_triples(0).object_subtype = 0
mask_triples(0).solid_type = 0

mask_triples(1).object_type = UFConstants.UF_line_type
mask_triples(1).object_subtype = 0
mask_triples(1).solid_type = 0

theUfSession.Ui.SetSelMask(select_,
UFUi.SelMaskAction.SelMaskClearAndEnableSpecific,
mask_triples.Length, mask_triples)

theUfSession.Ui.SetSelProcs(select_, AddressOf HoleFeatureFilter, Nothing, userdata)

Return UFConstants.UF_UI_SEL_SUCCESS

End Function

Function HoleFeatureFilter(ByVal _object As Tag,
ByVal type As Integer(),
ByVal user_data As IntPtr,
ByVal select_ As IntPtr) As Integer
'type, user_data, and select_ are unused (in this implementation), but this function must have
'the same signature as UFUi.SelFilterFnT Delegate

Dim myCurve As Curve = Utilities.NXObjectManager.Get(_object)
Dim featTag As Tag = Tag.Null
Dim myFeature As Features.Feature = Nothing

theUfSession.Modl.AskObjectFeat(myCurve.Tag, featTag)

myFeature = Utilities.NXObjectManager.Get(featTag)
If myFeature.FeatureType = "SYMBOLIC_THREAD" Then
Return UFConstants.UF_UI_SEL_ACCEPT
Else
Return UFConstants.UF_UI_SEL_REJECT
End If

End Function

Public Function GetUnloadOption(ByVal dummy As String) As Integer
'----Other unload options-------
'Unloads the image immediately after execution within NX
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
End Function

End Module

Thank You for your reply.

Adding a string variable was the only way that I found that worked. Not parametric but it does the job.
Your code only engraves thread type. Is there any other way to get thread major diameter data that would be parametric.
The other question that I have is how to make this journal work in assembly by making component as work.