Extract Centerline of free form tube

Scene: a non-descript grey fabric covered box that currently contains a workstation running NX and 2 coworkers

Coworker: Hey, I need to measure the length of this tube I have...

NXJournaling: No problem, here's a journal that lets you select a tube and adds up the lengths of the defining sections

Coworker: actually, it is from an imported part; there are no defining objects in the file...

NXJournaling: Ok, assuming it is made of straights and bends, we can extract lines from the cylindrical faces then...

Coworker: Well, it doesn't have straight sections or simple bends so much... it seems to be made of B-surfaces

NXJournaling: oh, I see... well... hmmm

NXJournaling: Let me introduce you to Frank Swinkels. He is a regular contributor at the GTAC languages forum and also at the eng-tips Siemens NX forum and he likes to write and share the type of code that can get you out of situations like this.

He has given us permission to reproduce some code he originally posted in the GTAC forum in answer to the request for extracting the centerline of an unparameterized free form tube. The code works the following way:

  1. The user is prompted to select a B-surface face.
  2. Collect the B-surface data, make sure the surface is closed in the U direction. Use the V direction surface data to help generate the tube centerline.
  3. At each point of interest along the length of the tube, generate equally spaced points around the circumference (U direction) of the tube. The average of these points determines the center point of the tube cross section.
  4. Construct a studio spline through these points which will closely approximate the centerline of the tube.

  5. Notes

    This journal will only work with NX 8 or above.

    I encourage you to step through the code to see what is going on, I can almost guarantee that you will learn something.

    The code demonstrates the use of the AskFaceProps function and a couple of vector functions that may come in handy. Also, there is a subroutine for creating a through points studio spline. Pass in an array of points and the desired degree and the spline will be created. That's a good piece of reusable code to have on hand...

    The Code

    Download the code and a sample part.


    'Author: Frank Swinkels
    'for use only with NX 8.5 or above
    'Create approximate centerline of B-surface "tube"
    'user will be prompted to select B-surface, a 'through points' studio spline will be created along the centerline

    ' modified June 19, 2014 to include creating the bsurface and allow for faces with other then 0 to 1 parameters
    ' (typically cylinders or extended cylinders)
    '
    ' modified June 24 to change for selecting apply or OK
    '
    ' NXJournaling.com
    ' Report length of selected tube.

    Option Strict Off
    Imports System
    Imports NXOpen
    Imports NXOpen.UF
    Imports NXOpenUI
    Imports NXOpen.Features
    Imports System.IO

    Module CableCentreline

    Dim s As Session = Session.GetSession()
    Dim ufs As UFSession = UFSession.GetUFSession()
    Dim workPart As Part = s.Parts.Work
    Dim lw As ListingWindow = s.ListingWindow
    Sub Main()
    Dim no_pts As Integer = Nothing
    Dim pos1 As Integer = Nothing
    Dim junk3(2) As Double
    Dim junk2(1) As Double
    Dim periodic1 As Boolean = False
    Dim theFace As Face = Nothing
    Dim totalLength As Double = 0
    Dim response1 As Selection.Response = Selection.Response.Cancel
    Dim type1 As Integer = Nothing
    Dim subtype1 As Integer = Nothing
    Dim bsurface1 As UFModl.Bsurface = Nothing
    Dim extractedfeat1 As Feature = Nothing
    Dim extractedbodyfeat1 As BodyFeature = Nothing
    Dim extractedbody1() As Body = Nothing
    Dim faces() As Face
    Dim testface As Face
    lw.Open()
    While select_a_face("Select a tube extracted face or dumb solid face", theFace) = Selection.Response.Ok

    'response1 = select_a_face("Select a tube extracted face or dumb solid face", theFace)
    'If response1 = Selection.Response.Cancel Or response1 = Selection.Response.Back Then GoTo end1
    ' check that it is a bsurface
    Try
    ufs.Modl.AskBsurf(theFace.Tag, bsurface1)
    testface = theFace
    Catch ex As Exception
    createExtractedBSurface(theFace, extractedfeat1)
    extractedbodyfeat1 = DirectCast(extractedfeat1, BodyFeature)
    extractedbody1 = extractedbodyfeat1.GetBodies
    faces = extractedbody1(0).GetFaces
    ufs.Modl.AskBsurf(faces(0).Tag, bsurface1)
    testface = faces(0)
    End Try

    Dim noPolesV As Integer = bsurface1.num_poles_v
    Dim noPolesU As Integer = bsurface1.num_poles_u
    Dim poles1(,) As Double = bsurface1.poles
    Dim knotsU() As Double = bsurface1.knots_u
    Dim knotsV() As Double = bsurface1.knots_v
    Dim orderU As Integer = bsurface1.order_u
    Dim orderV As Integer = bsurface1.order_v
    Dim ptno As Integer = Nothing
    Dim params(1) As Double
    Dim pnt0(2) As Double
    Dim pnt1(2) As Double
    Dim pnt2(2) As Double
    Dim pnt3(2) As Double
    Dim vec0(2) As Double
    Dim vec1(2) As Double
    Dim vec2(2) As Double
    Dim vec3(2) As Double
    Dim rads(1) As Double
    Dim tolerance1 As Double = 0.001
    Dim magnitude1 As Double = Nothing
    Dim degree3 As Integer = orderV - 1
    Dim pointtag As Tag = Tag.Null
    Dim ArrayOfPoints(-1) As Point
    Dim uparm() As Double = {0.0, 0.25, 0.5, 0.75}
    Dim delta1 As Double
    Dim sum1 As Double = Nothing
    Dim distance1 As Double = Nothing
    Dim cnt1 As Integer = 0
    Dim tempcpt(2) As Double
    Dim coordinates1 As Point3d
    Dim temptag As Tag = Tag.Null
    ' tube bsurf u around tube, v along the tube
    Dim vparm(noPolesV - 1) As Double
    vparm(0) = 0.0
    vparm(noPolesV - 1) = 1.0
    Dim lengths(noPolesV - 2) As Double
    sum1 = 0.0
    cnt1 = 0
    For i As Integer = noPolesU To noPolesU * noPolesV - 1 Step noPolesU
    pnt1(0) = poles1(i, 0)
    pnt1(1) = poles1(i, 1)
    pnt1(2) = poles1(i, 2)
    pnt2(0) = poles1(i - noPolesU, 0)
    pnt2(1) = poles1(i - noPolesU, 1)
    pnt2(2) = poles1(i - noPolesU, 2)
    ufs.Vec3.Distance(pnt1, pnt2, distance1)
    lengths(cnt1) = distance1
    cnt1 += 1
    sum1 += distance1
    Next
    delta1 = 0.0
    For i As Integer = 0 To noPolesV - 2
    delta1 += lengths(i)
    vparm(i + 1) = delta1 / sum1
    Next
    Dim uvminmax(3) As Double
    ufs.Modl.AskFaceUvMinmax(testface.Tag, uvminmax)
    Dim total2 As Double = uvminmax(3) - uvminmax(2)
    Dim delta2 As Double = total2 / (noPolesV - 1)
    Dim zero1 As Double = uvminmax(2)
    For i As Integer = 0 To noPolesV - 1
    If i = 0 Then
    vparm(i) = zero1
    Else
    vparm(i) = vparm(i - 1) + delta2
    End If

    Next
    For i As Integer = 0 To noPolesV - 1
    params(0) = uparm(0)
    params(1) = vparm(i)
    ufs.Modl.AskFaceProps(testface.Tag, params, pnt0, junk3, vec0, junk3, junk3, junk3, rads)
    ufs.Vec3.Unitize(vec0, tolerance1, magnitude1, vec0)
    params(0) = uparm(1)
    ufs.Modl.AskFaceProps(testface.Tag, params, pnt1, junk3, vec1, junk3, junk3, junk3, rads)
    params(0) = uparm(2)
    ufs.Modl.AskFaceProps(testface.Tag, params, pnt2, junk3, vec2, junk3, junk3, junk3, rads)
    params(0) = uparm(3)
    ufs.Modl.AskFaceProps(testface.Tag, params, pnt3, junk3, vec3, junk3, junk3, junk3, rads)
    ufs.Vec3.Add(pnt0, pnt1, tempcpt)
    ufs.Vec3.Add(pnt2, tempcpt, tempcpt)
    ufs.Vec3.Add(pnt3, tempcpt, tempcpt)
    tempcpt(0) /= 4.0
    tempcpt(1) /= 4.0
    tempcpt(2) /= 4.0
    coordinates1 = New Point3d(tempcpt(0), tempcpt(1), tempcpt(2))

    ReDim Preserve ArrayOfPoints(i)
    ArrayOfPoints(i) = workPart.Points.CreatePoint(coordinates1)
    Next

    periodic1 = False
    Dim myStudioSpline As Features.StudioSpline
    myStudioSpline = CreateStudioSplineThruPoints(ArrayOfPoints, degree3)
    Dim tubeLength As Double = 0
    For Each tempCurve As Curve In myStudioSpline.GetEntities
    tubeLength += tempCurve.GetLength
    Next
    totalLength += tubeLength
    lw.WriteLine("section length: " & tubeLength.ToString)
    lw.WriteLine("total length: " & totalLength.ToString)
    lw.WriteLine("")
    End While
    end1:
    End Sub
    Public Sub createExtractedBSurface(ByVal face1 As Face, ByRef extractedfeat1 As Feature)
    Dim nullFeatures_Feature As Features.Feature = Nothing
    Dim extractFaceBuilder1 As Features.ExtractFaceBuilder
    extractFaceBuilder1 = workPart.Features.CreateExtractFaceBuilder(nullFeatures_Feature)
    extractFaceBuilder1.ParentPart = Features.ExtractFaceBuilder.ParentPartType.WorkPart
    extractFaceBuilder1.Associative = True
    extractFaceBuilder1.FixAtCurrentTimestamp = True
    extractFaceBuilder1.HideOriginal = False
    extractFaceBuilder1.Type = Features.ExtractFaceBuilder.ExtractType.Face
    extractFaceBuilder1.InheritDisplayProperties = False
    extractFaceBuilder1.SurfaceType = Features.ExtractFaceBuilder.FaceSurfaceType.PolynomialCubic
    Dim added1 As Boolean
    added1 = extractFaceBuilder1.ObjectToExtract.Add(face1)
    extractedfeat1 = extractFaceBuilder1.Commit
    End Sub
    Function select_a_face(ByRef prompt As String, ByRef face1 As Face) As Selection.Response
    Dim mask(0) As Selection.MaskTriple
    With mask(0)
    .Type = UFConstants.UF_solid_type
    .Subtype = 0
    .SolidBodySubtype = UFConstants.UF_UI_SEL_FEATURE_ANY_FACE
    End With
    Dim cursor As Point3d = Nothing
    Dim response1 As Selection.Response = Selection.Response.Cancel
    select_a_face = Nothing
    response1 = UI.GetUI.SelectionManager.SelectTaggedObject(prompt, "Select the Face", _
    Selection.SelectionScope.AnyInAssembly, _
    Selection.SelectionAction.ClearAndEnableSpecific, False, _
    False, mask, face1, cursor)
    If response1 = Selection.Response.ObjectSelected Or _
    response1 = Selection.Response.ObjectSelectedByName Then
    Return Selection.Response.Ok
    ElseIf response1 = Selection.Response.Back Then
    Return Selection.Response.Back
    Else
    Return Selection.Response.Cancel
    End If
    End Function

    Public Function CreateStudioSplineThruPoints(ByRef points() As Point, ByVal degree3 As Integer) As Features.StudioSpline
    Dim markId9 As Session.UndoMarkId
    markId9 = s.SetUndoMark(Session.MarkVisibility.Visible, "Studio Spline Thru Points")
    Dim Pcount As Integer = points.Length - 1
    Dim nullFeatures_StudioSpline As Features.StudioSpline = Nothing
    Dim studioSplineBuilderex1 As Features.StudioSplineBuilderEx
    studioSplineBuilderex1 = workPart.Features.CreateStudioSplineBuilderEx(nullFeatures_StudioSpline)
    studioSplineBuilderex1.OrientExpress.ReferenceOption = GeometricUtilities.OrientXpressBuilder.Reference.ProgramDefined
    studioSplineBuilderex1.Degree = degree3
    studioSplineBuilderex1.OrientExpress.AxisOption = GeometricUtilities.OrientXpressBuilder.Axis.Passive
    studioSplineBuilderex1.OrientExpress.PlaneOption = GeometricUtilities.OrientXpressBuilder.Plane.Passive
    studioSplineBuilderex1.MatchKnotsType = Features.StudioSplineBuilderEx.MatchKnotsTypes.None
    Dim knots1(-1) As Double
    studioSplineBuilderex1.SetKnots(knots1)
    Dim parameters1(-1) As Double
    studioSplineBuilderex1.SetParameters(parameters1)
    Dim nullDirection As Direction = Nothing
    Dim nullScalar As Scalar = Nothing
    Dim nullOffset As Offset = Nothing
    Dim geometricConstraintData(Pcount) As Features.GeometricConstraintData
    For ii As Integer = 0 To Pcount
    geometricConstraintData(ii) = studioSplineBuilderex1.ConstraintManager.CreateGeometricConstraintData()
    geometricConstraintData(ii).Point = points(ii)
    geometricConstraintData(ii).AutomaticConstraintDirection = Features.GeometricConstraintData.ParameterDirection.Iso
    geometricConstraintData(ii).AutomaticConstraintType = Features.GeometricConstraintData.AutoConstraintType.Tangent
    geometricConstraintData(ii).TangentDirection = nullDirection
    geometricConstraintData(ii).TangentMagnitude = nullScalar
    geometricConstraintData(ii).Curvature = nullOffset
    geometricConstraintData(ii).CurvatureDerivative = nullOffset
    geometricConstraintData(ii).HasSymmetricModelingConstraint = False
    Next ii
    studioSplineBuilderex1.ConstraintManager.SetContents(geometricConstraintData)
    Dim feature1 As Features.StudioSpline
    feature1 = studioSplineBuilderex1.CommitFeature()
    studioSplineBuilderex1.Destroy()

    Return feature1

    End Function

    Public Function GetUnloadOption(ByVal dummy As String) As Integer
    'Unloads the image when the NX session terminates
    GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
    End Function

    End Module

Comments

Would it be possible to get this code to work in NX6

'Author: Frank Swinkels
'for use only with NX 8 or above
'Create approximate centerline of B-surface "tube"
'user will be prompted to select B-surface, a 'through points' studio spline will be created along the centerline

Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF
Imports NXOpenUI
Imports NXOpen.Features
Imports System.IO

Module CableCentreline

Dim s As Session = Session.GetSession()
Dim ufs As UFSession = UFSession.GetUFSession()
Dim workPart As Part = s.Parts.Work
Dim lw As ListingWindow = s.ListingWindow
Sub Main()
Dim no_pts As Integer = Nothing
Dim pos1 As Integer = Nothing
Dim junk3(2) As Double
Dim junk2(1) As Double
Dim periodic1 As Boolean = False
Dim theFace As Face = Nothing
Dim response1 As Selection.Response = Selection.Response.Cancel
Dim type1 As Integer = Nothing
Dim subtype1 As Integer = Nothing
Dim bsurface1 As UFModl.Bsurface = Nothing
start1:
response1 = select_a_face("Select a tube extracted face or dumb solid face", theFace)
If response1 = Selection.Response.Cancel Or response1 = Selection.Response.Back Then GoTo end1
' check that it is a bsurface
Try
ufs.Modl.AskBsurf(theFace.Tag, bsurface1)
Catch ex As Exception
MsgBox("The selected face is not a BSurface")
GoTo start1
End Try
Dim noPolesV As Integer = bsurface1.num_poles_v
Dim noPolesU As Integer = bsurface1.num_poles_u
Dim poles1(,) As Double = bsurface1.poles
Dim knotsU() As Double = bsurface1.knots_u
Dim knotsV() As Double = bsurface1.knots_v
Dim orderU As Integer = bsurface1.order_u
Dim orderV As Integer = bsurface1.order_v
Dim ptno As Integer = Nothing
Dim params(1) As Double
Dim pnt0(2) As Double
Dim pnt1(2) As Double
Dim pnt2(2) As Double
Dim pnt3(2) As Double
Dim vec0(2) As Double
Dim vec1(2) As Double
Dim vec2(2) As Double
Dim vec3(2) As Double
Dim rads(1) As Double
Dim tolerance1 As Double = 0.001
Dim magnitude1 As Double = Nothing
Dim degree3 As Integer = orderV - 1
Dim pointtag As Tag = Tag.Null
Dim ArrayOfPoints(-1) As Point
Dim uparm() As Double = {0.0, 0.25, 0.5, 0.75}
Dim delta1 As Double
Dim sum1 As Double = Nothing
Dim distance1 As Double = Nothing
Dim cnt1 As Integer = 0
Dim tempcpt(2) As Double
Dim coordinates1 As Point3d
' tube bsurf u around tube, v along the tube
Dim vparm(noPolesV - 1) As Double
vparm(0) = 0.0
vparm(noPolesV - 1) = 1.0
Dim lengths(noPolesV - 2) As Double
sum1 = 0.0
cnt1 = 0
For i As Integer = noPolesU To noPolesU * noPolesV - 1 Step noPolesU
pnt1(0) = poles1(i, 0)
pnt1(1) = poles1(i, 1)
pnt1(2) = poles1(i, 2)
pnt2(0) = poles1(i - noPolesU, 0)
pnt2(1) = poles1(i - noPolesU, 1)
pnt2(2) = poles1(i - noPolesU, 2)
ufs.Vec3.Distance(pnt1, pnt2, distance1)
lengths(cnt1) = distance1
cnt1 += 1
sum1 += distance1
Next
delta1 = 0.0
For i As Integer = 0 To noPolesV - 2
delta1 += lengths(i)
vparm(i + 1) = delta1 / sum1
Next
For i As Integer = 0 To noPolesV - 1
params(0) = uparm(0)
params(1) = vparm(i)
ufs.Modl.AskFaceProps(theFace.Tag, params, pnt0, vec0, junk3, junk3, junk3, junk3, rads)
ufs.Vec3.Unitize(vec0, tolerance1, magnitude1, vec0)
params(0) = uparm(1)
ufs.Modl.AskFaceProps(theFace.Tag, params, pnt1, vec1, junk3, junk3, junk3, junk3, rads)
params(0) = uparm(2)
ufs.Modl.AskFaceProps(theFace.Tag, params, pnt2, vec2, junk3, junk3, junk3, junk3, rads)
params(0) = uparm(3)
ufs.Modl.AskFaceProps(theFace.Tag, params, pnt3, vec3, junk3, junk3, junk3, junk3, rads)
ufs.Vec3.Add(pnt0, pnt1, tempcpt)
ufs.Vec3.Add(pnt2, tempcpt, tempcpt)
ufs.Vec3.Add(pnt3, tempcpt, tempcpt)
tempcpt(0) /= 4.0
tempcpt(1) /= 4.0
tempcpt(2) /= 4.0
coordinates1 = New Point3d(tempcpt(0), tempcpt(1), tempcpt(2))
ReDim Preserve ArrayOfPoints(i)
ArrayOfPoints(i) = workPart.Points.CreatePoint(coordinates1)
Next
periodic1 = False
CreateStudioSplineThruPoints(ArrayOfPoints, degree3)
GoTo start1
end1:
End Sub

Function select_a_face(ByRef prompt As String, ByRef face1 As Face) As Selection.Response
Dim mask(0) As Selection.MaskTriple
With mask(0)
.Type = UFConstants.UF_solid_type
.Subtype = 0
.SolidBodySubtype = UFConstants.UF_UI_SEL_FEATURE_ANY_FACE
End With
Dim cursor As Point3d = Nothing
Dim response1 As Selection.Response = Selection.Response.Cancel
select_a_face = Nothing
response1 = UI.GetUI.SelectionManager.SelectTaggedObject(prompt, "Select the Face", _
Selection.SelectionScope.AnyInAssembly, _
Selection.SelectionAction.ClearAndEnableSpecific, False, _
False, mask, face1, cursor)
Return response1
End Function

Public Sub CreateStudioSplineThruPoints(ByRef points() As Point, ByVal degree3 As Integer)
Dim markId9 As Session.UndoMarkId
markId9 = s.SetUndoMark(Session.MarkVisibility.Visible, "Studio Spline Thru Points")
Dim Pcount As Integer = points.Length - 1
Dim nullFeatures_StudioSpline As Features.StudioSpline = Nothing
Dim studioSplineBuilderex1 As Features.StudioSplineBuilderEx
studioSplineBuilderex1 = workPart.Features.CreateStudioSplineBuilderEx(nullFeatures_StudioSpline)
studioSplineBuilderex1.OrientExpress.ReferenceOption = GeometricUtilities.OrientXpressBuilder.Reference.ProgramDefined
studioSplineBuilderex1.Degree = degree3
studioSplineBuilderex1.OrientExpress.AxisOption = GeometricUtilities.OrientXpressBuilder.Axis.Passive
studioSplineBuilderex1.OrientExpress.PlaneOption = GeometricUtilities.OrientXpressBuilder.Plane.Passive
studioSplineBuilderex1.MatchKnotsType = Features.StudioSplineBuilderEx.MatchKnotsTypes.None
Dim knots1(-1) As Double
studioSplineBuilderex1.SetKnots(knots1)
Dim parameters1(-1) As Double
studioSplineBuilderex1.SetParameters(parameters1)
Dim nullDirection As Direction = Nothing
Dim nullScalar As Scalar = Nothing
Dim nullOffset As Offset = Nothing
Dim geometricConstraintData(Pcount) As Features.GeometricConstraintData
For ii As Integer = 0 To Pcount
geometricConstraintData(ii) = studioSplineBuilderex1.ConstraintManager.CreateGeometricConstraintData()
geometricConstraintData(ii).Point = points(ii)
geometricConstraintData(ii).AutomaticConstraintDirection = Features.GeometricConstraintData.ParameterDirection.Iso
geometricConstraintData(ii).AutomaticConstraintType = Features.GeometricConstraintData.AutoConstraintType.Tangent
geometricConstraintData(ii).TangentDirection = nullDirection
geometricConstraintData(ii).TangentMagnitude = nullScalar
geometricConstraintData(ii).Curvature = nullOffset
geometricConstraintData(ii).CurvatureDerivative = nullOffset
geometricConstraintData(ii).HasSymmetricModelingConstraint = False
Next ii
studioSplineBuilderex1.ConstraintManager.SetContents(geometricConstraintData)
Dim feature1 As Features.Feature
feature1 = studioSplineBuilderex1.CommitFeature()
studioSplineBuilderex1.Destroy()
End Sub

Public Function GetUnloadOption(ByVal dummy As String) As Integer
'Unloads the image when the NX session terminates
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
End Function

End Module

Paul Fillion

I don't have NX 6 installed to do any testing.
What errors you do get when you try to run it in NX 6?

Okay this is what the Journal Compile Errors Says

Line 132: 'SelectTaggedObject' is not a member of 'NXOpen.Selection'.
Line 144: Type 'Features.StudioSplineBuilderEx' is not defined.
Line 145: 'CreateStudioSplineBUilderEx' is not a member of 'NXOpen.Features.FeatureCollection'.
Line 150: 'StudioSplineBuilderEc' is not amember of 'Features'.

Paul Fillion

Fixing the SelectTaggedObject error would be easy, but some of the code that uses the StudioSplineBuilderEx (NX 8.0 object) doesn't have a direct replacement with the older StudioSplineBuilder (pre NX 8.0) object. I'm pretty sure it could be rewritten to work with NX 6, but offhand, I don't know how much trouble it would be.

Does anyone know Frank Swinkels? Maybe possible he has an older version.

Paul Fillion

I contacted Frank, he has very kindly responded with code that should work in NX 6.

'Author: Frank Swinkels
'for use only with NX6
'Create approximate centerline of B-surface "tube"
'user will be prompted to select B-surface, a 'through points' studio spline will be created along the centerline

Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF
Imports NXOpenUI
Imports NXOpen.Features
Imports System.IO

Module CableCentreline

Dim s As Session = Session.GetSession()
Dim ufs As UFSession = UFSession.GetUFSession()
Dim workPart As Part = s.Parts.Work
Dim lw As ListingWindow = s.ListingWindow
Sub Main()
Dim no_pts As Integer = Nothing
Dim pos1 As Integer = Nothing
Dim junk3(2) As Double
Dim junk2(1) As Double
Dim periodic1 As Boolean = False
Dim theFace As Face = Nothing
Dim response1 As Selection.Response = Selection.Response.Cancel
Dim type1 As Integer = Nothing
Dim subtype1 As Integer = Nothing
Dim bsurface1 As UFModl.Bsurface = Nothing
start1:
response1 = select_a_face("Select a tube extracted face or dumb solid face", theFace)
If response1 = Selection.Response.Cancel Or response1 = Selection.Response.Back Then GoTo end1
' check that it is a bsurface
Try
ufs.Modl.AskBsurf(theFace.Tag, bsurface1)
Catch ex As Exception
MsgBox("The selected face is not a BSurface")
GoTo start1
End Try
Dim noPolesV As Integer = bsurface1.num_poles_v
Dim noPolesU As Integer = bsurface1.num_poles_u
Dim poles1(,) As Double = bsurface1.poles
Dim knotsU() As Double = bsurface1.knots_u
Dim knotsV() As Double = bsurface1.knots_v
Dim orderU As Integer = bsurface1.order_u
Dim orderV As Integer = bsurface1.order_v
Dim ptno As Integer = Nothing
Dim params(1) As Double
Dim pnt0(2) As Double
Dim pnt1(2) As Double
Dim tolerance1 As Double = 0.001
Dim magnitude1 As Double = Nothing
Dim degree3 As Integer = orderV - 1
Dim pointtag As Tag = Tag.Null
Dim sum1 As Double = Nothing
Dim distance1 As Double = Nothing
Dim cnt1 As Integer = 0
Dim tempcpt(2) As Double
Dim coordinates1 As Point3d = New Point3d

' check if closed in u direction or in v direction
If knotsU(0) < 0.0 Then
' closed in u direction
Dim uparm() As Double = {0.0, 0.5}
Dim vparm(knotsV.Length - 5) As Double
vparm(0) = 0.0
For i As Integer = 1 To knotsV.Length - 7 Step 3
vparm(i) = knotsV(i + 2) + (knotsV(i + 3) - knotsV(i + 2)) / 3.0
vparm(i + 1) = knotsV(i + 2) + 2.0 * (knotsV(i + 3) - knotsV(i + 2)) / 3.0
vparm(i + 2) = knotsV(i + 3)
Next
Dim ArrayOfPoints(vparm.Length - 1) As Point
For i As Integer = 0 To vparm.Length - 1
params(0) = uparm(0)
params(1) = vparm(i)
ufs.Modl.AskFaceProps(theFace.Tag, params, pnt0, junk3, junk3, junk3, junk3, junk3, junk2)
params(0) = uparm(1)
ufs.Modl.AskFaceProps(theFace.Tag, params, pnt1, junk3, junk3, junk3, junk3, junk3, junk2)
coordinates1 = New Point3d((pnt0(0) + pnt1(0)) / 2.0, (pnt0(1) + pnt1(1)) / 2.0, (pnt0(2) + pnt1(2)) / 2.0)
ArrayOfPoints(i) = workPart.Points.CreatePoint(coordinates1)
Next
CreateStudioSplineThruPoints(ArrayOfPoints)
ElseIf knotsV(0) < 0.0 Then
' closed in v direction
Dim vparm() As Double = {0.0, 0.5}
Dim uparm(knotsU.Length - 5) As Double
uparm(0) = 0.0
For i As Integer = 1 To knotsU.Length - 7 Step 3
uparm(i) = knotsU(i + 2) + (knotsU(i + 3) - knotsU(i + 2)) / 3.0
uparm(i + 1) = knotsU(i + 2) + 2.0 * (knotsU(i + 3) - knotsU(i + 2)) / 3.0
uparm(i + 2) = knotsU(i + 3)
Next
Dim ArrayOfPoints(uparm.Length - 1) As Point
For i As Integer = 0 To uparm.Length - 1
params(0) = uparm(i)
params(1) = vparm(0)
ufs.Modl.AskFaceProps(theFace.Tag, params, pnt0, junk3, junk3, junk3, junk3, junk3, junk2)
params(1) = vparm(1)
ufs.Modl.AskFaceProps(theFace.Tag, params, pnt1, junk3, junk3, junk3, junk3, junk3, junk2)
coordinates1 = New Point3d((pnt0(0) + pnt1(0)) / 2.0, (pnt0(1) + pnt1(1)) / 2.0, (pnt0(2) + pnt1(2)) / 2.0)
ArrayOfPoints(i) = workPart.Points.CreatePoint(coordinates1)
Next
CreateStudioSplineThruPoints(ArrayOfPoints)
Else
MsgBox("Surface must be closed in one direction")
GoTo end1
End If
GoTo start1
end1:
End Sub

Function select_a_face(ByRef prompt As String, ByRef face1 As Face) As Selection.Response
Dim mask(0) As Selection.MaskTriple
With mask(0)
.Type = UFConstants.UF_solid_type
.Subtype = 0
.SolidBodySubtype = UFConstants.UF_UI_SEL_FEATURE_ANY_FACE
End With
Dim cursor As Point3d = Nothing
Dim response1 As Selection.Response = Selection.Response.Cancel
select_a_face = Nothing
response1 = UI.GetUI.SelectionManager.SelectObject(prompt, "Select the Face", _
Selection.SelectionScope.AnyInAssembly, _
Selection.SelectionAction.ClearAndEnableSpecific, False, _
False, mask, face1, cursor)
Return response1
End Function

Public Sub CreateStudioSplineThruPoints(ByRef points() As Point)
Dim markId9 As Session.UndoMarkId
markId9 = s.SetUndoMark(Session.MarkVisibility.Visible, "Studio Spline Thru Points")
Dim Pcount As Integer = points.Length - 1
Dim nullFeatures_StudioSpline As Features.StudioSpline = Nothing
Dim studioSplineBuilderex1 As Features.StudioSplineBuilder
studioSplineBuilderex1 = workPart.Features.CreateStudioSplineBuilder(nullFeatures_StudioSpline)
studioSplineBuilderex1.Degree = 3
Dim knots1(-1) As Double
studioSplineBuilderex1.SetKnots(knots1)
Dim parameters1(-1) As Double
studioSplineBuilderex1.SetParameters(parameters1)
Dim nullDirection As Direction = Nothing
Dim nullScalar As Scalar = Nothing
Dim nullOffset As Offset = Nothing
Dim geometricConstraintData(Pcount) As Features.GeometricConstraintData
For ii As Integer = 0 To Pcount
geometricConstraintData(ii) = studioSplineBuilderex1.ConstraintManager.CreateGeometricConstraintData()
geometricConstraintData(ii).Point = points(ii)
geometricConstraintData(ii).AutomaticConstraintDirection = Features.GeometricConstraintData.ParameterDirection.Iso
geometricConstraintData(ii).AutomaticConstraintType = Features.GeometricConstraintData.AutoConstraintType.Tangent
geometricConstraintData(ii).TangentDirection = nullDirection
geometricConstraintData(ii).TangentMagnitude = nullScalar
geometricConstraintData(ii).Curvature = nullOffset
geometricConstraintData(ii).CurvatureDerivative = nullOffset
geometricConstraintData(ii).HasSymmetricModelingConstraint = False
Next ii
studioSplineBuilderex1.ConstraintManager.SetContents(geometricConstraintData)
Dim feature1 As Features.Feature
feature1 = studioSplineBuilderex1.CommitFeature()
studioSplineBuilderex1.Destroy()
End Sub

Public Function GetUnloadOption(ByVal dummy As String) As Integer
'Unloads the image when the NX session terminates
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.Immediately
End Function

End Module

Big thanks to Frank!

You know you guys are FREAKING AWESOME! Yeah Frank very nice Thank You very much

Paul Fillion

Here's a much easier approach. Basically, you just construct two iso-curves running along opposite sides of the tube, connect them with a ruled surface, and get the mid-curve of this ruled surface.

Option Infer On
Imports Snap, Snap.Create, Snap.UI, Snap.NX.ObjectTypes

Public Class MyProgram

Public Shared Sub Main()
' Create a selection dialog and set filter
Dim dialog = Selection.SelectObject("Select a b-surface tube face")
dialog.SetFaceFilter(SubType.FaceBsurface)

' Display the dialog and get the face
Dim result = dialog.Show()
Dim bsurf As NX.Face.Bsurface = Nothing
If result.Response <> Response.Cancel And result.Response <> Response.Back Then
bsurf = result.Object
End If

' Create two iso-curves running along opposite sides of the tube
Dim side1 As NX.Spline = bsurf.IsoCurveU(0.25)(0)
Dim side2 As NX.Spline = bsurf.IsoCurveU(0.75)(0)

' Create a ruled surface between the two iso-curves
Dim crossSurf As NX.Face.Bsurface = Ruled(side1, side2).Faces(0)

' Construct the center curve of the ruled surface
Dim centerline As NX.Spline = crossSurf.IsoCurveV(0.5)(0)

End Sub

End Class

This uses SNAP functions, but you can do roughly the same thing with older functions: use NXOpen.UF.UFModl.CreateIsocurve to create the iso-curves and NXOpen.UF.UFModl.CreateRuled to create the ruled surface.

Okay thanks I will give it a shot

Paul Fillion

Okay I gave it the Boy Scout try.

Option Infer On
NXOpen.UF.UFModl.CreateIsocurve
NXOpen.UF.UFModl.CreateRuled

Public Class MyProgram

Public Shared Sub Main()
' Create a selection dialog and set filter
Dim dialog = Selection.SelectObject("Select a b-surface tube face")
dialog.SetFaceFilter(SubType.FaceBsurface)

' Display the dialog and get the face
Dim result = dialog.Show()
Dim bsurf As NX.Face.Bsurface = Nothing
If result.Response <> Response.Cancel And result.Response <> Response.Back Then
bsurf = result.Object
End If

' Create two iso-curves running along opposite sides of the tube
Dim side1 As NX.Spline = bsurf.IsoCurveU(0.25)(0)
Dim side2 As NX.Spline = bsurf.IsoCurveU(0.75)(0)

' Create a ruled surface between the two iso-curves
Dim crossSurf As NX.Face.Bsurface = Ruled(side1, side2).Faces(0)

' Construct the center curve of the ruled surface
Dim centerline As NX.Spline = crossSurf.IsoCurveV(0.5)(0)

End Sub

End Class

Theses are the codes I got

Line 1: 'Option'must be followe by 'Compare', 'Explict' or 'Strict'.
Line 2: Declaration expected.
Line 3: Declaration expected.
Line 4: Declaration expected.
Line 11: Name 'Selection' is not declared.
Line 12: Name 'SubTye' is not declared.
Line 16: Type 'NX Face.Bsurface' is not defined.
Line 17: Name 'Respnes' is not declared.
Line 22: Type'NX SPline' is not defined.
Line 23: Type'NX SPline' is not defined.
Line 26: Type'NC.Face.Bsurface' is not defined
Line 29: Type 'NX.Spline' is not defined.

Paul Fillion

Hi I'm Fiqih, I'm new in journaling, i need your help.
How about code to NX 11 version?

Regards,