Using StudioSplineBuilder in an external application

I am working on an External NX application using C and C++ API.
I am trying to fit curves and surfaces through some point data that I have.


Session *theSession = Session::GetSession();
Part *workPart(theSession->Parts()->Work());
Part *displayPart(theSession->Parts()->Display());

NXOpen::DirectionCollection *spDirCollection = workPart->Directions();
Features::StudioSpline *nullFeatures_StudioSpline(NULL);
if ( !workPart->Preferences()->Modeling()->GetHistoryMode() )
{
throw NXException::Create("Create or edit of a Feature was recorded in History Mode but playback is in History-Free Mode.");
}

Features::StudioSplineBuilder *studioSplineBuilder1;
studioSplineBuilder1 = workPart->Features()->CreateStudioSplineBuilder(nullFeatures_StudioSpline);

Spline *spline1 = (NXOpen::Spline*) NXOpen::NXObjectManager::Get(someCurve);

studioSplineBuilder1->SetNonParametricSpline(spline1, Features::StudioSplineBuilder::MethodByPoles);
studioSplineBuilder1->SetAssociative(true);
studioSplineBuilder1->SetInputCurveOption(Features::StudioSplineBuilder::CurveOptionRetain);
studioSplineBuilder1->SetSplineMethod(Features::StudioSplineBuilder::MethodByPoles);
studioSplineBuilder1->SetDegree(nDegree);
studioSplineBuilder1->SetPeriodic(false);

std::vector knots(0);
for (int i = 0; i < nKnots; i++)
knots.push_back(dKnots[i]);

studioSplineBuilder1->SetKnots(knots);

Here the SetKnots method for studioSplineBuilder1 throws up an exception. In debug mode it says memory access violation. The other set methods for studioSplineBuilder1 above SetKnots seem to work.

Similarly the setContents method also throws up a memory acccess violation error.

studioSplineBuilder1->ConstraintManager()->SetContents(somegeometricConstraintData);

I am not sure why this might be happening. Any pointer would be highly appreciated.

Thanks
Wilson

What version of NX are you using?
The studioSplineBuilder object was deprecated in NX 8. If you are using NX 8 or above, try using the studioSplineBuilderEx instead.

However, I have a feeling it won't completely solve your issue. What are the parameters of the spline that you are trying to create? (degree, number of segments, knot sequence, etc)?

Also note that newer versions of NX (8.5? and higher) have a "fit curve" function that will return a best fit spline through the given points. If you have the appropriate version of NX, it may be worthwhile to investigate this function.

Thanks for the reply. I am using NX 8.5

The curve I am trying to create is of degree 3 with around 20 or more points. The routine i use takes the parameters from another curve that is passed to it and fits a studio spline.
As you said, the issue does not seem to be with deprecated classes. I can see in debug mode that the object is created. Few of the setter functions are working. But few in which the parameter passed is of vector type are showing the error. The error window says "Unhandled exception at 0x000007fedfca65b6 in exe: 0xC0000005: Access violation reading location 0x0000000000000000." Am I missing any header here ?

This code I am using is part of an old library code that was developed in an earlier version, i am trying to get it to run in this version. This library is big and may need changes at several places which would be too cumbersome. Any way to get the code to run as is?

Regards
Wilson

Wilson

I'm sure you know this already, but I'll say it anyway. When you compile your code for your current version of NX, make sure that you are referencing the proper NX files and not the old ones.

The error message isn't very helpful (not to me, at least). If your test case is one that worked correctly with the older NX version, but doesn't work with the new one, you may want to contact GTAC. They should be able to give you more help.

The code you gave must be only a part of the whole. I don't see where dKnots and nKnots are defined.

If you want to create a cubic spline with given poles, I'd suggest either NXOpen.UF.UFCurve.CreateSpline or Snap.Create.Spline. The former has a C-callable version, but the latter is .NET-only, of course.

Thank you all for your comments and sorry for a late reply. Yes, this code is pretty old but was working earlier. I have an NX internal application based on this code that is working.

I tried seperating only the curve fitting code into a different project. This is what I have.

// These includes are in different Header file

#include
#include
#include

#include
#include
#include
#include

#include
#include

#include

#include
#include

#include
#include

#include
#include
#include
#include

#include

#include
#include

#include
#include

#include
#include

#include
#include
#include
#include

#include
#include

#include

#include
#include
#include
#include
#include
#include
#include

#include
#include
#include

#include

#include
#include
#include

#include
#include

#include
#include

//NXOpen header files
#include
#include
#include
#include
#include
#include
#include
#include
#include

//UFunc Headers
#include
#include
#include
#include

// UGOpen headers
#include
#include
#include

#include
#include
#include
#include

#include

///////////////////////////////////

//NX Open C++ header files
#include
#include
#include
#include
#include
#include
#include
#include
#include

//Open C Headers

//UFunc Headers
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include

// standard headers
#include
#include
#include
#include

#include

#include
#include

#include

using namespace std;
using namespace NXOpen;

NXOpen::Spline* createSpline(vector points, NXOpen::Session *theSession)
{

//We grab the current part before we can work on it.
Part *workPart(theSession->Parts()->Work());

//Now we need to create a studiosplinebuilder object. This is what we will use to build our spline,
//it contains the necessary functions. We also set some necessary parameters for the studiosplinebuilder.
Features::StudioSpline *nullFeatures_StudioSpline(NULL);
Features::StudioSplineBuilder *studioSplineBuilder1;
studioSplineBuilder1 = workPart->Features()->CreateStudioSplineBuilder(nullFeatures_StudioSpline);
studioSplineBuilder1->SetAssociative(true);
studioSplineBuilder1->SetInputCurveOption(Features::StudioSplineBuilder::CurveOptionRetain);
studioSplineBuilder1->SetSplineMethod(Features::StudioSplineBuilder::MethodThroughPoints);
studioSplineBuilder1->SetDegree(5);
studioSplineBuilder1->SetPeriodic(false);
studioSplineBuilder1->SetMatchKnots(Features::StudioSplineBuilder::MatchKnotsTypeNone);

//A few more required objects that we don't need to elaborate on
std::vector knots1(0);

studioSplineBuilder1->SetKnots(knots1);
std::vector parameters1(0);
studioSplineBuilder1->SetParameters(parameters1);

//These objects are required for the loop that adds the points to the spline
Features::GeometricConstraintData *geometricConstraintData1;
Direction *nullDirection(NULL);
Scalar *nullScalar(NULL);
Offset *nullOffset(NULL);
std::vector constraints1(points.size());

//This loop is where the points are actually inserted into the spline
for(unsigned int j = 0; j < points.size(); j++)
{
geometricConstraintData1 = studioSplineBuilder1->ConstraintManager()->CreateGeometricConstraintData();
//The code contained in SetPoint() creates a point from the current index of point objects
geometricConstraintData1->SetPoint(workPart->Points()->CreatePoint(points.at(j)));
geometricConstraintData1->SetAutomaticConstraintDirection(Features::GeometricConstraintData::ParameterDirectionIso);
geometricConstraintData1->SetAutomaticConstraintType(Features::GeometricConstraintData::AutoConstraintTypeNone);
geometricConstraintData1->SetTangentDirection(nullDirection);
geometricConstraintData1->SetTangentMagnitude(nullScalar);
geometricConstraintData1->SetCurvature(nullOffset);
geometricConstraintData1->SetCurvatureDerivative(nullOffset);
geometricConstraintData1->SetHasSymmetricModelingConstraint(false);
constraints1[j] = geometricConstraintData1;
}
studioSplineBuilder1->ConstraintManager()->SetContents(constraints1);

//Here is where we actually create the object and insert it into the workview. We also extract the spline from the feature.
Features::Feature *feature1;
feature1 = studioSplineBuilder1->CommitFeature();
Spline* returnSpline = studioSplineBuilder1->Curve();

return returnSpline;
}

int testSpline()
{
cout << "Creating point array" << endl;

vector points(0);
points.push_back(NXOpen::Point3d(0.551833582E+01, -.751787484E+00, -.164708939E+02));
points.push_back(NXOpen::Point3d(0.553420258E+01, -0.722469866E+00, -0.164536076E+02));
points.push_back(NXOpen::Point3d(0.555618429E+01, -0.690917611E+00, -0.164276180E+02));
points.push_back(NXOpen::Point3d(0.557990170E+01, -0.661347866E+00, -0.163984585E+02 ));
points.push_back(NXOpen::Point3d(0.559568548E+01, -0.642132103E+00, -0.163788280E+02 ));
points.push_back(NXOpen::Point3d(0.562709475E+01, -0.603930891E+00, -0.163393974E+02 ));
points.push_back(NXOpen::Point3d(0.567364693E+01, -0.547425508E+00, -0.162801094E+02 ));
points.push_back(NXOpen::Point3d(0.571962833E+01, -0.491778433E+00, -0.162205620E+02 ));
points.push_back(NXOpen::Point3d(0.576506901E+01, -0.437105417E+00, -0.161607571E+02 ));
points.push_back(NXOpen::Point3d(0.581000900E+01, -0.383398294E+00, -0.161007004E+02 ));
points.push_back(NXOpen::Point3d(0.585456467E+01, -0.330540240E+00, -0.160402966E+02 ));
points.push_back(NXOpen::Point3d(0.589891195E+01, -0.278634399E+00, -0.159793291E+02 ));
points.push_back(NXOpen::Point3d(0.594296455E+01, -0.228052020E+00, -0.159179573E+02 ));
points.push_back(NXOpen::Point3d(0.598668861E+01, -0.178970233E+00, -0.158562908E+02 ));
points.push_back(NXOpen::Point3d(0.603012180E+01, -0.131551802E+00, -0.157943335E+02 ));
points.push_back(NXOpen::Point3d(0.607330799E+01, -0.855702534E-01, -0.157320976E+02 ));
points.push_back(NXOpen::Point3d(0.611628342E+01, -0.410230793E-01, -0.156695929E+02 ));
points.push_back(NXOpen::Point3d(0.615908098E+01, 0.209187460E-02, -0.156068258E+02 ));

cout << "Initializing the Open C API environment - UF_initialize()" << endl;
/* Initialize the Open C API environment */
int errorCode = UF_initialize();

if ( 0 != errorCode )
throw NXOpen::NXException::Create(errorCode);

cout << "Initializing NX Open C++ API environment - NXOpen::Session::GetSession()" << endl;
/* Initialize the NX Open C++ API environment */
NXOpen::Session *theSession = NXOpen::Session::GetSession();

/* Create a new part.
To create new part one can use Open C API as well as NX Open C++ API.
*/

/* To create new part using Open C API. */
char* partName = "testSpline.prt";
tag_t partTag;
cout << "Creating UG Part using C API - UF_PART_new " << endl;
UF_PART_new(partName,2,&partTag);

NXOpen::Part *part1 = NULL;
cout << "Casting part to C++ object from part tag " << endl;
part1 = theSession->Parts()->Work(); // Session::GetSession()->Parts()->Work();

part1 = theSession->Parts()->Work();
partTag = part1->GetTag();

if(partTag == NULL)
{
std::cerr << "Could not create Part. Does it already exist from a from previous run?" << std::endl;
return 1;
}

cout << "Calling CreateSpline() ....." << endl;
NXOpen::Spline* l_spline = createSpline( points, theSession);

/* To get the part from the part tag */
part1 = (NXOpen::Part*)NXOpen::NXObjectManager::Get(partTag);

cout << "Save part " << endl;

/* To save work part using NX Open C++ APIs */
NXOpen::PartSaveStatus *partSaveStatus = part1->Save(NXOpen::Part::SaveComponentsTrue, NXOpen::Part::CloseAfterSaveTrue);
/* To close all parts using NX Open C++ APIs */
theSession->Parts()->CloseAll(NXOpen::BasePart::CloseModifiedCloseModified, NULL);

cout << "Terminate session - UF_terminate() " << endl;
/* Terminate the Open C API environment */
errorCode = UF_terminate();

return 0;
}

I am adding some points to an array and trying to fit a curve through those. I need a NURBS curve so I use studioSplineBuilder. This is a simple piece of code. But I still get the same issue. The functions SetKnots and SetContents show error "Access Violation reading location 0x0000000 ".
I am not able to figure out what I am missing here. Is there something with the settings that I needto add ?

I have added following lib references in the project settings.
libnxopencpp.lib
libnxopencpp_features.lib
libnxopencpp_geometricutilities.lib
libnxopencpp_preferences.lib
libugopenint.lib
libufun.lib

I am using Visual Studio 2005 for development.

Wilson

This may not be the cause of your trouble, but for NX 8.5 the "officially supported" compiler is Visual Studio 2010 (with service pack 1).

You can find the recommended compiler versions for each release in the NX help -> release notes -> caveats and product notes -> programming tools -> product notes.

I have tried my earlier application with VS2010 as well. See the same issue there as well.

Wilson