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