Arc start point and end point

Recently, while working on a journal that processed existing lines and arcs, I needed to find the start and end points of the given lines and arcs. The line objects have a .StartPoint and .EndPoint property that return a Point3D object. This made writing the code for the line objects easy and I quickly moved on to the arc objects intending to use their .StartPoint and .EndPoint properties; however, this was not to be...

Neither .StartPoint nor .EndPoint properties showed up in the VB editor's 'Intellisense' list for my arc object. Thinking there must be some mistake, I opened the NX8 .NET API reference and looked up the arc class. Unfortunately, arc objects do not offer up their start and end points willingly, as the line objects do. More searching through the documentation failed to turn up a secondary NXOpen .NET function that would return the points of interest (though I'd love to be proved wrong here). So, I started searching in the UF functions and found a few that do the job. Two of the UF functions are shown in the following code along with a function I wrote which uses existing arc properties and a little trigonometry to calculate the start and end points.

UF to the rescue

UF_MODL_ask_curve_props

The first function I found was UF_MODL_ask_curve_props. From the help file:

Overview

Returns the point, tangent, unit principal normal, unit binormal, torsion, and radius of curvature on a curve at a given parameter. The input curve parameter, parm, is normalized between 0 and 1.

This function requires 8 parameters to be passed into it:

  • input: the tag of the curve of interest
  • input: a double value (the curve parameter) representing the length along the curve. In essence, the curve parameter is the percentage distance along the curve, with 0 (0%) representing the curve start point, and 1 (100%) representing the curve end point.
  • output: an array of doubles representing the point location. The function will fill this array with the X, Y, and Z values of the point location on the curve at the given parameter.
  • output: an array of doubles representing the tangent vector at the point of the given curve parameter.
  • output: an array of doubles representing the normal vector of the curve at the given curve parameter point.
  • output: an array of doubles representing the binormal vector of the curve at the given curve parameter point.
  • output: a double variable representing the torsion of the curve at the given parameter point
  • output: a double variable representing the radius of curvature at the given parameter point

In the code below, you will see that I passed in the arc object's .Tag property, the value of 0 (zero) or 1 as the parameter (for the start point and endpoint, respectively), an array to hold the point location information, an array named junk3 (3 times), and a double variable named junk1 (twice). Even though I wasn't interested in most of the function's output, I still had to pass in the required parameters. For what I was doing, I didn't need the tangent, normal, or binormal vectors or the torsion or radius of curvature. Instead of creating 3 extra arrays and 2 extra variables, I cheated a bit by only creating 1 array (junk3) and 1 variable (junk1) and passing them in multiple times to the function. The function got the parameters it required and I got the point information I was interested in, so we were both happy. Well, mostly happy... The UF function was happily offering up a lot of interesting information, but I felt a bit wasteful throwing most of it away. There must be another function to use...

UF_CURVE_evaluate_curve

The next UF function I found was UF_CURVE_evaluate_curve, which has 4 required parameters. Here's the overview from the help file:

Overview

Returns the point on the curve and the requested derivatives.
This function differs from UF_MODL_evaluate_curve in two ways:

The param and deriv_flag are not pointers, and the param value is specified in the "natural" parameter range of the curve. For example, to evaluate an arc, UF_MODL_evaluate_curve takes a parameter value between 0 and 1, normalized to the parameter range of the arc when created. UF_CURVE_evaluate_curve takes a parameter in radians, in the parameter range given when the arc was created.

This function only requires 4 parameters:

  • input: The tag of the curve object, easily obtained by using the .Tag property of my arc object
  • input: The curve parameter (or position along the curve of interest). This function uses a 'natural' parameter instead of a 'normalized' parameter, as was used in the UF_MODL_ask_curve_props function. In the case of an arc, a natural parameter means an angle measurement in radians. The arc object conveniently has a .StartAngle and .EndAngle property that represents an angle value measured in radians.
  • input: A flag value (integer) that signals what you want the function to return. NXOpen defines some constants to use here:
    • UF_CURVE_LOC = return the point
    • UF_CURVE_LOC_1STDERV = return the point and 1st derivative
    • UF_CURVE_LOC_1STDERV_2NDDERV = return the point, 1st and 2nd derivatives
  • output: An array of double values the size of which will depend on what values you have flagged for output

This function looks like it will suit my needs perfectly. I can tell it to only output the point information (the only thing I'm interested in for my current task), and the other input values are easily obtained from the arc object.

Home-grown algorithm

Finally, there is an algorithm I came up with while looking for a solution that does not rely on any UF functions. I do not claim that my method is any better or faster than the UF functions, but I'll put it out there as an alternative. Here are the basic steps it takes:

  • save the current WCS position and orientation
  • move the WCS origin to the center point of the arc
  • rotate the WCS to the orientation of the arc
  • use the arc's .StartAngle, .EndAngle, and .Radius properties along with some trigonometry to calculate the start and end point locations
  • return the WCS to the position before the function was called

At first glance, "rotating the WCS to the orientation of the arc" may sound difficult but the arc object has a .Matrix property which stores the necessary information and can be used directly when orienting the WCS.

On to the Code...

Before you run the code, create/open a file that has several arcs created in it. The journal will prompt you to select an arc, then it will print out the start and end point locations to the listing window. The process will loop until you press 'Cancel'.


'NXJournaling.com
'January 22, 2013
'NX 7.5/8
'Unlike the Line object, the Arc object does not provide startpoint and endpoint properties.
'This journal shows 3 ways to get the arc start/end points.

'Modl.AskCurveProps will work on any curve. It requires a curve parameter as input which ranges from zero to one
' along the length of the curve (zero = start, one = end). It returns other curve properties at that point
' that you may not be interested in (tangent, normal, torsion, etc).

'Curve.EvaluateCurve will also work on any curve. It will return the point and optionally, the 1st and 2nd derivatives
' at that point. The input parameter is 'natural' which, for an arc, means the input parameter must be in radians.
' There is also a Modl.EvaluateCurve function similar to this one, but the parameter is normalized (between 0 and 1).

'The last demonstrated method is my own creation, it does not rely on any UF functions. It works by moving the WCS
' to the centerpoint of the arc and at the same orientation of the arc object. It then uses the arc's startangle
' and endangle properties to calculate the positon of the start/end points and finally maps those points to
' the absolute coordinate space.

Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF

Module Module1

Dim theSession As Session = Session.GetSession()
Dim workPart As Part = theSession.Parts.Work
Dim ufs As UFSession = UFSession.GetUFSession

Sub Main()

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

Dim myArc As Arc
Dim myStartPoint As Point3d
Dim myEndPoint As Point3d

Do Until SelectAnArc("select an arc", myArc) = Selection.Response.Cancel
lw.WriteLine("Center point: " & myArc.CenterPoint.ToString)
lw.WriteLine("Start angle: " & myArc.StartAngle.ToString)
lw.WriteLine("End angle: " & myArc.EndAngle.ToString)
lw.WriteLine("")

'use AskCurveProps to find start/end point of arc
'curve parameter is normalized (0 to 1)
lw.WriteLine("AskCurveProps")
Dim stPt(2) As Double
Dim edPt(2) As Double
Dim junk3(2) As Double
Dim junk1 As Double
ufs.Modl.AskCurveProps(myArc.Tag, 0.0, stPt, junk3, junk3, junk3, junk1, junk1)
lw.WriteLine("start point: " & stPt(0) & ", " & stPt(1) & ", " & stPt(2))
ufs.Modl.AskCurveProps(myArc.Tag, 1.0, edPt, junk3, junk3, junk3, junk1, junk1)
lw.WriteLine("end point: " & edPt(0) & ", " & edPt(1) & ", " & edPt(2))
lw.WriteLine("")

'use EvaluateCurve to find start/end point of arc
'curve parameter is "natural", i.e. the parameter is in radians in the range given when arc was created
lw.WriteLine("EvaluateCurve")
Dim evalStPt(2) As Double
Dim evalEndPt(2) As Double
ufs.Curve.EvaluateCurve(myArc.Tag, myArc.StartAngle, UFConstants.UF_CURVE_LOC, evalStPt)
lw.WriteLine("start point: " & evalStPt(0) & ", " & evalStPt(1) & ", " & evalStPt(2))
ufs.Curve.EvaluateCurve(myArc.Tag, myArc.EndAngle, UFConstants.UF_CURVE_LOC, evalEndPt)
lw.WriteLine("end point: " & evalEndPt(0) & ", " & evalEndPt(1) & ", " & evalEndPt(2))
lw.WriteLine("")

'Calculate start/end points of arc given centerpoint, start angle, end angle, and radius
lw.WriteLine("NXJournaling algorithm")
myStartPoint = ArcStartPoint(myArc)
myEndPoint = ArcEndPoint(myArc)
lw.WriteLine("start point: " & myStartPoint.ToString)
lw.WriteLine("end point: " & myEndPoint.ToString)
lw.WriteLine("")

Loop

End Sub

Function SelectAnArc(ByVal prompt As String, ByRef selObj As NXObject) As Selection.Response

Dim theUI As UI = UI.GetUI
Dim title As String = "Select an Arc"
Dim includeFeatures As Boolean = False
Dim keepHighlighted As Boolean = False
Dim selAction As Selection.SelectionAction = Selection.SelectionAction.ClearAndEnableSpecific
Dim cursor As Point3d
Dim scope As Selection.SelectionScope = Selection.SelectionScope.WorkPart
Dim selectionMask_array(0) As Selection.MaskTriple

With selectionMask_array(0)
.Type = UFConstants.UF_circle_type
.Subtype = 0
End With

Dim resp As Selection.Response = theUI.SelectionManager.SelectObject(prompt, _
title, scope, selAction, _
includeFeatures, keepHighlighted, selectionMask_array, _
selobj, cursor)
If resp = Selection.Response.ObjectSelected OrElse resp = Selection.Response.ObjectSelectedByName Then
Return Selection.Response.Ok
Else
Return Selection.Response.Cancel
End If

End Function

Function Abs2WCS(ByVal inPt As Point3d) As Point3d
Dim pt1(2), pt2(2) As Double

pt1(0) = inPt.X
pt1(1) = inPt.Y
pt1(2) = inPt.Z

ufs.Csys.MapPoint(UFConstants.UF_CSYS_ROOT_COORDS, pt1, _
UFConstants.UF_CSYS_ROOT_WCS_COORDS, pt2)

Abs2WCS.X = pt2(0)
Abs2WCS.Y = pt2(1)
Abs2WCS.Z = pt2(2)

End Function

Function WCS2Abs(ByVal inPt As Point3d) As Point3d
Dim pt1(2), pt2(2) As Double

pt1(0) = inPt.X
pt1(1) = inPt.Y
pt1(2) = inPt.Z

ufs.Csys.MapPoint(UFConstants.UF_CSYS_ROOT_WCS_COORDS, pt1, _
UFConstants.UF_CSYS_ROOT_COORDS, pt2)

WCS2Abs.X = pt2(0)
WCS2Abs.Y = pt2(1)
WCS2Abs.Z = pt2(2)

End Function

Function ArcStartPoint(ByVal myArc As Arc) As Point3d

Dim startWCS As CartesianCoordinateSystem
startWCS = workPart.WCS.CoordinateSystem
Dim startPT As Point3d = workPart.WCS.Origin

Dim startPoint As Point3d

workPart.WCS.SetOriginAndMatrix(myArc.CenterPoint, myArc.Matrix.Element)

'start point
startPoint.X = myArc.Radius * Math.Cos(myArc.StartAngle)
startPoint.Y = myArc.Radius * Math.Sin(myArc.StartAngle)
startPoint.Z = 0

'convert point work coordinates to ACS
Return WCS2Abs(startPoint)

workPart.WCS.SetOriginAndMatrix(startPT, startWCS.Orientation.Element)

End Function

Function ArcEndPoint(ByVal myArc As Arc) As Point3d

Dim startWCS As CartesianCoordinateSystem
startWCS = workPart.WCS.CoordinateSystem

Dim endPoint As Point3d

workPart.WCS.SetOriginAndMatrix(myArc.CenterPoint, myArc.Matrix.Element)

'end point
endPoint.X = myArc.Radius * Math.Cos(myArc.EndAngle)
endPoint.Y = myArc.Radius * Math.Sin(myArc.EndAngle)
endPoint.Z = 0

'convert point work coordinates to ACS
Return WCS2Abs(endPoint)

workPart.WCS.SetOriginAndMatrix(New Point3d(0, 0, 0), startWCS.Orientation.Element)

End Function

Public Function GetUnloadOption(ByVal dummy As String) As Integer

'Unloads the image when the NX session terminates
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination

End Function

End Module

Comments

Please Help.

The following code gives me an error
ufs.Modl.UF_ROUTE_ask_segment_wires(routingSplineTag , numWires , wires)
Journal Compile Errors: 'UF_ROUTE_ask_segment_wires' is not a member of 'NXOPEN.UF.UFModl'

So i tried something diferent, but still get errors.
ufs.route.UF_ROUTE_ask_segment_wires(routingSplineTag , numWires , wires)
Journal Compile Errors: 'UF_ROUTE_ask_segment_wires' is not a member of 'NXOPEN.UF.UFRoute'

Carlo Tony Daristotile

Make sure your code imports NXOpen.UF and the ufsession is created.


Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF

Module...
Sub...
Dim theUfSession As UFSession = UFSession.GetUFSession
.
.
.
theUfSession.Route.AskSegmentWires(...)
.

THANKS IT WORKED.
The only part corrected then was "AskSegmentWires"
I see what I did wrong, I was using "Wrapper method for UF_ROUTE_ask_segment_wires"

Carlo Tony Daristotile

hello I work with UG NX routing electrical.

What I would like to do is get the information on the wires for any selected routing.splinesegment.

This function "AskSegmentWires" helped me get the number of wires.
But I dont know how to use the wire tags array to get information on each wire, such as wire gauge, wire diameter, wire type, from conn and pin, to conn and pin, etc..

I cannot find the "ask" functions on this information, and the wire class doesnt have this information.

Any ideas?

Carlo Tony Daristotile

I'm not familiar with the routing application, but looking through the API reference, I found some functions that may help you:
UF_ROUTE_ask_port_on_segment
UF_ROUTE_ask_object_port
UF_ROUTE_ask_object_stock

Searching on the term "UF_ROUTE_ask*" will turn up more that may be of interest.

Could you modify it for bspline? Is it posible to know if the spline is linear or a curve?

See my reply further down the page:
http://nxjournaling.com/comment/5072#comment-5072

Hello,
the API functions you have described are very helpful to get the xyz coordinates of
a point located at a particular percentage position on the curve. My question, can I do the opposite?
Is there a function to get the percentage of a point on a curve?

I think the function you are looking for is "UF_EVAL_evaluate_closest_point". You will need to do some work to initialize the "evaluator", after which this function will return the closest point (and corresponding parameter) on the given curve to the given point.

Hello,
I've tried to use these API function for getting the curve parameter of a given point on the curve.
Acc. the API reference the resulting parameter is not normalized. What does this mean? When I use the
result parameter to create a new point on the curve, there is a difference between the first point
and the newly created point. How can I normalize the result?

What do you plan on doing with the curve parameter? If you only want to create a new point at that location, I suggest using the CreatePoint method that allows you to specify the close point and the offset from that point.

Can you post the relevant section of code you have so far?

Yes, I want to create a new point coincident with the first point, this new point should be parametric moveable along the curve with it's curve parameter. I do not have a code until yet, but my idea was to do it like this:

> Create an Intersection point between a plane (z=0) and the curve
> Using the curve parameter of the intersection point to create an associative point along the curve.

Problem is, if I use the curve parameter of the intersection point, the new created point is not coincident with the intersection point.

Perhaps the function:
theUfSession.Modl.AskCurveParmNoExt(...)

will work better here. This one returns a normalized parameter value.

I am trying to shorten a curve down to two points via an AdjustCurveBuilder. The parameters I pass in don't match my output parameters, they are off by a few tenths. Are the curve parameters linearly related to the curve length or is there a better way for me to be doing this?


Function adjustCurveLength(ByVal curve As Curve, ByVal pnt1 As Point3d, ByVal pnt2 As Point3d) As Curve

If curve.IsOccurrence Then
curve = curve.Prototype
End If

Dim crvStartPoint As Point3d = crvAskStartPoint(curve)
Dim crvEndPoint As Point3d = crvAskEndPoint(curve)
Dim crvLength As Double = crvAskLen(curve)

Dim section1 As Section = wrkPrt.Sections.CreateSection(0.000095, 0.0001, 0.125)
section1.DistanceTolerance = 0.0001
section1.ChainingTolerance = 0.000095
section1.AllowSelfIntersection(True)
'section1.SetAllowedEntityTypes(Section.AllowTypes.OnlyCurves)

'Curve to adjust
Dim curves1(0) As IBaseCurve
curves1(0) = curve
Dim curveDumbRule1 As CurveDumbRule = wrkPrt.ScRuleFactory.CreateRuleCurveDumb({curve})
Dim rules1(0) As SelectionIntentRule
rules1(0) = curveDumbRule1
section1.AddToSection(rules1, curve, Nothing, Nothing, crvStartPoint, Section.Mode.Create, False)

'Create curve builder
Dim curveLengthBuilder1 As Features.CurveLengthBuilder = wrkPrt.Features.CreateCurvelengthBuilder(Nothing)
With curveLengthBuilder1
.Section = section1
.DistanceTolerance = 0.0001
.CurvelengthData.ExtensionMethod = GeometricUtilities.ExtensionMethod.Incremental
.CurvelengthData.ExtensionSide = GeometricUtilities.ExtensionSide.StartEnd
.CurvelengthData.ExtensionDirection = GeometricUtilities.ExtensionDirection.Natural
.CurveOptions.Associative = False
.CurveOptions.InputCurveOption = GeometricUtilities.CurveOptions.InputCurve.Delete
End With

If PntEquiv(crvAskPntOn(curve, pnt1), pnt1) AndAlso PntEquiv(crvAskPntOn(curve, pnt2), pnt2) Then
Dim crvStartDist As Double = 0
Dim crvEndDist As Double = curve.GetLength
If crvAskPrmNormalized(curve, crvAskPrmOn(curve, pnt1)) < crvAskPrmNormalized(curve, crvAskPrmOn(curve, pnt2)) Then 'AskCurveParmNoExt
crvStartDist = curve.GetLength * crvAskPrmNormalized(curve, crvAskPrmOn(curve, pnt1))
crvEndDist = curve.GetLength * (1 - crvAskPrmNormalized(curve, crvAskPrmOn(curve, pnt2)))
Else
crvStartDist = curve.GetLength * crvAskPrmNormalized(curve, crvAskPrmOn(curve, pnt2))
crvEndDist = curve.GetLength * (1 - crvAskPrmNormalized(curve, crvAskPrmOn(curve, pnt1)))
End If
curveLengthBuilder1.CurvelengthData.SetStartDistance(-crvStartDist.ToString)
curveLengthBuilder1.CurvelengthData.SetEndDistance(-crvEndDist.ToString)

Else
Return curve
End If

'Commit the changes
Dim nXObject1 As NXObject = curveLengthBuilder1.Commit()
'Get the committed objects
Dim createdObjects() As NXObject = curveLengthBuilder1.GetCommittedObjects()

Dim adjustedCurve As Curve = createdObjects(0)

section1.Clear() 'NX7Probs
curveLengthBuilder1.Destroy()

ufSes.Modl.Update()

Return adjustedCurve
End Function

DHuskic
Nx 9 VB

Does your code make use of the .AskParameterization method? According to the reference docs, this returns the "natural" parameter range. From my testing, it looks like lines and splines are normalized from 0 to 1; but the values returned for arcs represent the start and end angle in radians.

No, my code is not using that. I'm currently treating all lines, splines, arcs as just curves. So arcs would have to be handled differently due to the parameterization being in units of start and end angles?

DHuskic
Nx 9 VB

Do you see the discrepancy with all curve types or just arcs? Have the curves that you are working with been trimmed associatively (I just thought about this possibility and haven't tested what affect this will have on the reported parameter, if any)?

From the code posted, I can't really tell how you are determining the curve parameter. It appears to call custom functions that are not included in the post.

The discrepancy is across all of my input curves, of which a majority seem to be splines. I inserted this at the beginning of my function. This project is also in NX7, which seems relatively buggy with certain pieces of code.


curve = crvExtract(curve)
Dim dbl(1) As Double
Dim int As Integer
ufSes.Curve.AskParameterization(curve.Tag, dbl, int)
nxLw.WriteLine(curve.GetType.ToString)
nxLw.WriteLine(dbl(0) & " = " & dbl(1)) ' & " = " & dbl(2))
nxLw.WriteLine(int)


NXOpen.Spline
0 = 1
1
NXOpen.Spline
0 = 1
1
NXOpen.Spline
0 = 1
1
NXOpen.Spline
0 = 1
1
NXOpen.Spline
0 = 1
1
NXOpen.Spline
0 = 1
1
NXOpen.Spline
0 = 1
1
NXOpen.Spline
0 = 1
1
NXOpen.Spline
0 = 1
1

These are my curve ask parameter functions:

'''
''' Normalize a non-normalized curve parameter
'''
''' Curve - curve to evaluate
''' Double - non-normalized parameter
''' Double - normalized parameter
'''
Public Function crvAskPrmNormalized(ByVal c0 As Curve, ByVal d0 As Double)
Dim d1 As Double
Dim p0a(2) As Double
ufSes.Curve.EvaluateCurve(c0.Tag, d0, UF_CURVE_LOC, p0a)
ufSes.Modl.AskCurveParm(c0.Tag, p0a, d1, p0a)
Return d1
End Function

'''
''' Return parameter on curve closest to given point
'''
''' Tag - tag of curve / edge to evaluate
''' Point3d - point to evaluate
''' Double - parameter of curve at closest point
'''
Public Function crvAskPrmOn(ByVal tag As Tag, ByVal pnt As Point3d) As Double
Dim pt0() As Double = {pnt.X, pnt.Y, pnt.Z}
Dim pt1(2), prm As Double
Dim crvEva As IntPtr = crvEvalInit(tag)
ufSes.Eval.EvaluateClosestPoint(crvEva, pt0, prm, pt1)
Dim crvPrm As crvPrmData = New crvPrmData(tag, crvEva)
ufSes.Eval.Free(crvEva)
Return crvPrm.rawToNorm(prm)
End Function

'Relative portions of the crvPrmData structure -------
'''
''' Initialize values for structure
'''
''' Tag - tag of curve / edge to use
''' IntPtr - UF evaluation pointer
'''
Private Sub init(ByVal tag As Tag, Optional ByVal crvEva As IntPtr = Nothing)
Dim fre As Boolean = False
If (crvEva = Nothing) Then fre = True
If (crvEva = Nothing) Then ufSes.Eval.Initialize(tag, crvEva)
Dim prm(1) As Double
ufSes.Eval.AskLimits(crvEva, prm)
beg = prm(0)
len = prm(1) - prm(0)
If (fre) Then ufSes.Eval.Free(crvEva)
End Sub
'''
''' Convert a raw curve parameter (not 0-1) to a normalized parameter (0-1)
'''
''' Double - raw curve paramter
''' Doubule - normalized curve parameter
'''
Public Function rawToNorm(ByVal raw As Double) As Double
Return (raw - beg) / len
End Function
'''
''' Convert a normalized curve parameter (0-1) to a raw curve parameter (not 0-1)
'''
''' Double - normalized curve parameter
''' Double - raw curve parameter
'''
Public Function normToRaw(ByVal prm As Double) As Double
Return beg + prm * len
End Function

DHuskic
Nx 9 VB

It appears that there are 2 very similar "evaluate curve" methods: UF_CURVE_evaluate_curve and UF_MODL_evaluate_curve. The CURVE version expects a "natural" parameter value and the MODL version expects a normalized parameter value. I'm not sure how this affects your code (if at all).

I changed the code to use the Modl calls but didn't see a difference in output but I'm still having issues. This debug log might be able to help explain the issue I'm seeing:

-------Parameters of the points on the curve
? crvAskPrmCustom(crv, crvAskPntCustom(crv, pnt1))
0.0 {Double}
? (1 - crvAskPrmCustom(crv, crvAskPntCustom(crv, pnt2)))
0.98397069728834019 {Double}
-------Adjust Curve Distance Modifications
? -crvStartDist
0.0
? -crvEndDist
-10.920522903303613
-------Curve Lengths before and after
? InitialCurve.GetLength
11.098422883322401
? adjustedcurve.GetLength
0.17789998001878113
-------Original Point Infomration
? pnt1
{[X=-1.31607429453635,Y=1.04646173602426,Z=-3]}
? pnt2
{[X=-1.26717384388905,Y=1.26566582754298,Z=-3]}
--------New adjusted curve point information
? crvaskstartpoint(adjustedCurve)
{[X=-1.31607429453635,Y=1.04646173602426,Z=-3]}
? crvaskendpoint(adjustedCurve)
{[X=-1.28145617346828,Y=1.22070199224183,Z=-3]}
--------Double checking my work to see if the points and parameters match
? crvaskpntcustom(InitialCurve, crvAskEndPoint(adjustedCurve))
0.013257581452849719 {Double}
?crvAskPrmCustom(InitialCurve, crvAskPntCustom(InitialCurve, pnt2))
0.016029302711659775 {Double}
--------They don't match

DHuskic
Nx 9 VB

If possible, please email me a sample NX file and your code (a journal with at least enough code to run and illustrate the problem). I might be able to provide better help if I can see what is going on for myself.

Thanks
info@nxjournaling.com

I have some questions about parameters.
First of all basicly the code EvaluateCurve(....) how do we know about what should be inside the paranthesis? How many?
Second,
I try to convert it to use for Bspline. There should not be parameters related to arcs. So what are the correct parameters for bspline inside the paranthesis?
Last question,
I want to know if the bspline is a straight line or curved.

ufs.Curve.EvaluateCurve(myArc.Tag, myArc.EndAngle, UFConstants.UF_CURVE_LOC, evalEndPt)
lw.WriteLine("end point: " & evalEndPt(0) & ", " & evalEndPt(1) & ", " & evalEndPt(2))
lw.WriteLine("")

The NXOpen API reference will give details on the required parameters and what they mean.

Below is a re-worked example that works for any curve type. It reports the type of curve picked and the curve's start and end point coordinates.

Determining if a spline is linear can be a bit tricky. One way to do it would be to examine the splines degree and pole structure. A degree 1, single segment spline will be linear (it could be replaced by a single straight line). If you increase the degree and/or add segments, it is less likely to be linear; in this case, all the spline's poles would need to be positioned on a line. An alternative, perhaps easier, way to determine if a spline is linear would be to create a line between the spline's start and end points then do a curve to curve deviation check between the spline and the line that you created. If the maximum deviation is greater than your allowable tolerance, the spline is not linear.

'NXJournaling.com
'March 16, 2018
'NX 9
'Report the start and end points of a curve.

'Modl.AskCurveProps will work on any curve. It requires a curve parameter as input which ranges from zero to one
' along the length of the curve (zero = start, one = end). It returns other curve properties at that point
' that you may not be interested in (tangent, normal, torsion, etc).

'Curve.EvaluateCurve will also work on any curve. It will return the point and optionally, the 1st and 2nd derivatives
' at that point. The input parameter is 'natural' which, for an arc, means the input parameter must be in radians.
' There is also a Modl.EvaluateCurve function similar to this one, but the parameter is normalized (between 0 and 1).

Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF

Module Module2

Dim theSession As Session = Session.GetSession()
Dim workPart As Part = theSession.Parts.Work
Dim ufs As UFSession = UFSession.GetUFSession

Sub Main()

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

Dim markId1 As Session.UndoMarkId
markId1 = theSession.SetUndoMark(Session.MarkVisibility.Visible, "report curve points")

Dim myCurve As Curve
Dim myStartPoint As Point3d
Dim myEndPoint As Point3d
'Dim startWCS As CartesianCoordinateSystem
'startWCS = workPart.WCS.CoordinateSystem

Do Until SelectCurve("select a curve", myCurve) = Selection.Response.Cancel

lw.WriteLine("curve type: " & myCurve.GetType.ToString)
lw.WriteLine("")

'use AskCurveProps to find start/end point of arc
'curve parameter is normalized (0 to 1)
lw.WriteLine("AskCurveProps")
Dim stPt(2) As Double
Dim edPt(2) As Double
Dim junk3(2) As Double
Dim junk1 As Double
ufs.Modl.AskCurveProps(myCurve.Tag, 0.0, stPt, junk3, junk3, junk3, junk1, junk1)
lw.WriteLine("start point: " & stPt(0) & ", " & stPt(1) & ", " & stPt(2))
Dim newStartPoint As Point3d = New Point3d(stPt(0), stPt(1), stPt(2))
workPart.Points.CreatePoint(newStartPoint).SetVisibility(SmartObject.VisibilityOption.Visible)
ufs.Modl.AskCurveProps(myCurve.Tag, 1.0, edPt, junk3, junk3, junk3, junk1, junk1)
lw.WriteLine("end point: " & edPt(0) & ", " & edPt(1) & ", " & edPt(2))
Dim newEndPoint As Point3d = New Point3d(edPt(0), edPt(1), edPt(2))
workPart.Points.CreatePoint(newEndPoint).SetVisibility(SmartObject.VisibilityOption.Visible)
lw.WriteLine("")

'Use an evaluator to find the start and end points
'
Dim evaluator As IntPtr
Dim limits(1) As Double
Dim spt(2) As Double
Dim ept(2) As Double
Dim junk(2) As Double
ufs.Eval.Initialize(myCurve.Tag, evaluator)
ufs.Eval.AskLimits(evaluator, limits)
ufs.Eval.Evaluate(evaluator, 0, limits(0), spt, junk)
ufs.Eval.Evaluate(evaluator, 0, limits(1), ept, junk)
ufs.Eval.Free(evaluator)

lw.WriteLine("Evaluate")
'lw.WriteLine("start parameter: " & limits(0).ToString)
'lw.WriteLine("end parameter: " & limits(1).ToString)
lw.WriteLine("start point: " & spt(0).ToString & ", " & spt(1).ToString & ", " & spt(2).ToString)
lw.WriteLine("end point: " & ept(0).ToString & ", " & ept(1).ToString & ", " & ept(2).ToString)
lw.WriteLine("")

'use Curve.EvaluateCurve to find start/end point of arc
'curve parameter is "natural", i.e. for an arc, the parameter is in radians in the range given when arc was created.
lw.WriteLine("Curve.EvaluateCurve")
Dim paramRange(1) As Double
Dim curvePeriodicity As Integer
ufs.Curve.AskParameterization(myCurve.Tag, paramRange, curvePeriodicity)
'lw.WriteLine("start parameter: " & paramRange(0).ToString)
'lw.WriteLine("end parameter: " & paramRange(1).ToString)
Dim evalStPt(2) As Double
Dim evalEndPt(2) As Double
ufs.Curve.EvaluateCurve(myCurve.Tag, limits(0), UFConstants.UF_CURVE_LOC, evalStPt)
lw.WriteLine("start point: " & evalStPt(0) & ", " & evalStPt(1) & ", " & evalStPt(2))
ufs.Curve.EvaluateCurve(myCurve.Tag, limits(1), UFConstants.UF_CURVE_LOC, evalEndPt)
lw.WriteLine("end point: " & evalEndPt(0) & ", " & evalEndPt(1) & ", " & evalEndPt(2))
lw.WriteLine("")

'use Modl.EvaluateCurve
'This is very similar to the Curve.EvaluateCurve, except that the parameter is normalized i.e. it ranges from 0 to 1.
'The start point is where the parameter = 0, end point is where parameter = 1.
'This way, no evaluator is required to find the parameter range.
lw.WriteLine("Modl.EvaluateCurve")
Dim startPt(2) As Double
Dim endPt(2) As Double
ufs.Modl.EvaluateCurve(myCurve.Tag, 0, UFConstants.UF_CURVE_LOC, startPt)
lw.WriteLine("start point: " & startPt(0).ToString & ", " & startPt(1).ToString & ", " & startPt(2).ToString)
ufs.Modl.EvaluateCurve(myCurve.Tag, 1, UFConstants.UF_CURVE_LOC, endPt)
lw.WriteLine("end point: " & endPt(0).ToString & ", " & endPt(1).ToString & ", " & endPt(2).ToString)
lw.WriteLine("")

Loop

'workPart.WCS.SetOriginAndMatrix(New Point3d(0, 0, 0), startWCS.Orientation.Element)

End Sub

Function SelectCurve(prompt As String,
ByRef selObj As Curve) As Selection.Response

Dim theUI As UI = UI.GetUI
Dim cursor As Point3d
Dim typeArray() As Selection.SelectionType =
{Selection.SelectionType.Curves}

Dim resp As Selection.Response = theUI.SelectionManager.SelectTaggedObject(
prompt, "Select a curve",
Selection.SelectionScope.WorkPart,
False, typeArray, selObj, cursor)

If resp = Selection.Response.ObjectSelected Or
resp = Selection.Response.ObjectSelectedByName Then
Return Selection.Response.Ok
Else
Return Selection.Response.Cancel
End If

End Function

Function Abs2WCS(ByVal inPt As Point3d) As Point3d
Dim pt1(2), pt2(2) As Double

pt1(0) = inPt.X
pt1(1) = inPt.Y
pt1(2) = inPt.Z

ufs.Csys.MapPoint(UFConstants.UF_CSYS_ROOT_COORDS, pt1,
UFConstants.UF_CSYS_ROOT_WCS_COORDS, pt2)

Abs2WCS.X = pt2(0)
Abs2WCS.Y = pt2(1)
Abs2WCS.Z = pt2(2)

End Function

Function WCS2Abs(ByVal inPt As Point3d) As Point3d
Dim pt1(2), pt2(2) As Double

pt1(0) = inPt.X
pt1(1) = inPt.Y
pt1(2) = inPt.Z

ufs.Csys.MapPoint(UFConstants.UF_CSYS_ROOT_WCS_COORDS, pt1,
UFConstants.UF_CSYS_ROOT_COORDS, pt2)

WCS2Abs.X = pt2(0)
WCS2Abs.Y = pt2(1)
WCS2Abs.Z = pt2(2)

End Function

Public Function GetUnloadOption(ByVal dummy As String) As Integer

'Unloads the image when the NX session terminates
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination

End Function

End Module

Below is an updated version that creates a line from the start point to the end point, then does a curve-curve deviation check between the selected curve and the line. It checks 100 points (you can change this) along the curve and if the max deviation is greater than the modeling tolerance, it reports that the curve is non linear.

Option Strict Off
Imports System
Imports NXOpen
Imports NXOpen.UF

Module Module3

Dim theSession As Session = Session.GetSession()
Dim workPart As Part = theSession.Parts.Work
Dim ufs As UFSession = UFSession.GetUFSession

Sub Main()

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

Dim markId1 As Session.UndoMarkId
markId1 = theSession.SetUndoMark(Session.MarkVisibility.Visible, "report curve points")

Dim myCurve As Curve
Dim myStartPoint As Point3d
Dim myEndPoint As Point3d
'Dim startWCS As CartesianCoordinateSystem
'startWCS = workPart.WCS.CoordinateSystem

Do Until SelectCurve("select a curve", myCurve) = Selection.Response.Cancel

lw.WriteLine("curve type: " & myCurve.GetType.ToString)
lw.WriteLine("")

'use Modl.EvaluateCurve
'This is very similar to the Curve.EvaluateCurve, except that the parameter is normalized i.e. it ranges from 0 to 1.
'The start point is where the parameter = 0, end point is where parameter = 1.
'This way, no evaluator is required to find the parameter range.
lw.WriteLine("Modl.EvaluateCurve")
Dim startPt(2) As Double
Dim endPt(2) As Double
ufs.Modl.EvaluateCurve(myCurve.Tag, 0, UFConstants.UF_CURVE_LOC, startPt)
lw.WriteLine("start point: " & startPt(0).ToString & ", " & startPt(1).ToString & ", " & startPt(2).ToString)
ufs.Modl.EvaluateCurve(myCurve.Tag, 1, UFConstants.UF_CURVE_LOC, endPt)
lw.WriteLine("end point: " & endPt(0).ToString & ", " & endPt(1).ToString & ", " & endPt(2).ToString)
lw.WriteLine("")

Dim undoMark1 As Session.UndoMarkId
theSession.SetUndoMark(Session.MarkVisibility.Invisible, "deviation")

'create line between selected curve endpoints
Dim ptStart As Point3d = New Point3d(startPt(0), startPt(1), startPt(2))
Dim ptEnd As Point3d = New Point3d(endPt(0), endPt(1), endPt(2))

Dim line1 As Line
line1 = workPart.Curves.CreateLine(ptStart, ptEnd)

Dim modelingTolerance As Double = 0
ufs.Modl.AskDistanceTolerance(modelingTolerance)
Dim numCheckPoints As Integer = 100
Dim devCheckData As UFModl.DeviationCheckData
ufs.Modl.DevchkCurveToCurve(myCurve.Tag, line1.Tag, numCheckPoints, devCheckData)
If devCheckData.maximum_distance_error > modelingTolerance Then
lw.WriteLine("selected curve IS NOT linear within given tolerance")
Else
lw.WriteLine("selected curve IS linear within the given tolerance")
End If

Dim notifyOnDelete1 As Boolean
notifyOnDelete1 = theSession.Preferences.Modeling.NotifyOnDelete

theSession.UpdateManager.ClearErrorList()

Dim nErrs1 As Integer
nErrs1 = theSession.UpdateManager.AddToDeleteList(line1)

Dim nErrs2 As Integer
nErrs2 = theSession.UpdateManager.DoUpdate(undoMark1)
workPart.Views.Refresh()

Loop

'workPart.WCS.SetOriginAndMatrix(New Point3d(0, 0, 0), startWCS.Orientation.Element)

End Sub

Function SelectCurve(prompt As String,
ByRef selObj As Curve) As Selection.Response

Dim theUI As UI = UI.GetUI
Dim cursor As Point3d
Dim typeArray() As Selection.SelectionType =
{Selection.SelectionType.Curves}

Dim resp As Selection.Response = theUI.SelectionManager.SelectTaggedObject(
prompt, "Select a curve",
Selection.SelectionScope.WorkPart,
False, typeArray, selObj, cursor)

If resp = Selection.Response.ObjectSelected Or
resp = Selection.Response.ObjectSelectedByName Then
Return Selection.Response.Ok
Else
Return Selection.Response.Cancel
End If

End Function

Public Function GetUnloadOption(ByVal dummy As String) As Integer

'Unloads the image when the NX session terminates
GetUnloadOption = NXOpen.Session.LibraryUnloadOption.AtTermination

End Function

End Module

Or, if your time is important to you, and you're willing to spend a little money for a SNAP license, you can just write:


p0 = myCurve.StartPoint
p1 = myCurve.EndPoint

You might also be able to get this to work with the free MiniSNAP subset. Not sure.

To check that a spline is linear, just do this:
Create the chord line (the line between the spline's start and end points). For each pole of the spline, measure its distance to the chord line.

The spline is linear if (and only if) these distances are all zero. In your code, you should use some small tolerance to check the distances, not zero.