Create Geom_BSplineCurve with full Constructor

Hi,

I read every thread about Geom_BSplineCurve, but I have no idea what my failure is. With the following Code I get an "Standard_ConstructionError". Does anyone knows what is wronge?

const Standard_Integer degree = 5;
const Standard_Boolean periodic = Standard_False;
const Standard_Boolean checkRational = Standard_True;

TColgp_Array1OfPnt controlPoints(0,5);
controlPoints.SetValue(0,gp_Pnt(87.11555544,-56.56854249,4.527510435E-016));
controlPoints.SetValue(1,gp_Pnt(141.0061529,-2.677945084,4.527510435E-016));
controlPoints.SetValue(2,gp_Pnt(194.8967503,51.21265233,4.527510435E-016));
controlPoints.SetValue(3,gp_Pnt(248.7873477,105.1032497,4.527510435E-016));
controlPoints.SetValue(4,gp_Pnt(302.6779451,158.9938471,4.527510435E-016));

TColStd_Array1OfReal weights(0,6);
weights.SetValue(0,Standard_Real(1.0));
weights.SetValue(1,Standard_Real(1.0));
weights.SetValue(2,Standard_Real(1.0));
weights.SetValue(3,Standard_Real(1.0));
weights.SetValue(4,Standard_Real(1.0));
weights.SetValue(5,Standard_Real(1.0));

TColStd_Array1OfReal knots(0,12);
knots.SetValue(0,Standard_Real(0.0));
knots.SetValue(1,Standard_Real(0.0));
knots.SetValue(2,Standard_Real(0.0));
knots.SetValue(3,Standard_Real(0.0));
knots.SetValue(4,Standard_Real(0.0));
knots.SetValue(5,Standard_Real(0.0));
knots.SetValue(6,Standard_Real(381.0640687));
knots.SetValue(7,Standard_Real(381.0640687));
knots.SetValue(8,Standard_Real(381.0640687));
knots.SetValue(9,Standard_Real(381.0640687));
knots.SetValue(10,Standard_Real(381.0640687));
knots.SetValue(11,Standard_Real(381.0640687));

TColStd_Array1OfInteger multiplicities(0,12);
multiplicities.SetValue(0,Standard_Real(1.0));
multiplicities.SetValue(1,Standard_Real(1.0));
multiplicities.SetValue(2,Standard_Real(1.0));
multiplicities.SetValue(3,Standard_Real(1.0));
multiplicities.SetValue(4,Standard_Real(1.0));
multiplicities.SetValue(5,Standard_Real(1.0));
multiplicities.SetValue(6,Standard_Real(1.0));
multiplicities.SetValue(7,Standard_Real(1.0));
multiplicities.SetValue(8,Standard_Real(1.0));
multiplicities.SetValue(9,Standard_Real(1.0));
multiplicities.SetValue(10,Standard_Real(1.0));
multiplicities.SetValue(11,Standard_Real(1.0));

Handle(Geom_BSplineCurve) myCurve;
try
{
myCurve = new Geom_BSplineCurve(controlPoints, weights, knots, multiplicities, degree, periodic);

BRepBuilderAPI_MakeEdge ME(myCurve);
if (ME.IsDone())
{
Handle(AIS_Shape) aCrv = new AIS_Shape(ME.Edge());
this->myOCC->getContext()->SetMaterial(aCrv,Graphic3d_NOM_GOLD);
this->myOCC->getContext()->SetColor(aCrv, Quantity_NOC_RED);
this->myOCC->getContext()->SetDisplayMode(aCrv,1,Standard_False);
this->myOCC->getContext()->Display(aCrv, Standard_False);
}
}
catch (Standard_ConstructionError e)
{
std::cout }
catch(Standard_Failure s)
{
std::cout }
catch (...)
{
};

Thank you and best regards,
Franz

JuryS's picture

Try next code:

TopoDS_Shape ResultShape;
try
{
Handle(Geom_BSplineCurve) SPL1 =
GeomAPI_PointsToBSpline(array).Curve(); //! HERE IS YOUR ARRAY

BRep_Builder Brep;
TopoDS_Edge& E = TopoDS::Edge(ResultShape);

Brep.MakeEdge(E,SPL1,1.e-7);

TopoDS_Vertex Vfirst,Vend;
Brep.MakeVertex(Vfirst,array.Value(1),1.e-7);
Brep.MakeVertex(Vend,array.Value(aCurrent-1),1.e-7);

Vfirst.Orientation(TopAbs_FORWARD);
Vend.Orientation(TopAbs_REVERSED);

Brep.Add(E,Vfirst); //FORWARD POINT (first)
/*
for (int i = 2; i < (aCurrent-1); ++i) //SOME CONTROL POINTS
{
TopoDS_Vertex V;
Brep.MakeVertex(V,array.Value(i),1.e-7);
Brep.Add(E,V);
}
*/

Brep.Add(E,Vend); //RESERVE POINT (Last)

}
catch (...)
{
return QString::fromUtf8("Can't build this.");
}

jelle's picture

hi Yuriy,

I'm pretty sure you can make an edge from the GeomAPI_PointsToBSpline result.
There is no need to add the array once again to edge E.

-jf

Franz Engel's picture

o.k. I tried it like you suggested (with small changes):
TopoDS_Shape ResultShape;
Handle(Geom_BSplineCurve) SPL1;
try
{
SPL1 = GeomAPI_PointsToBSpline(controlPoints).Curve(); //! HERE IS YOUR ARRAY

BRep_Builder Brep;
TopoDS_Edge& E = TopoDS::Edge(ResultShape);

Brep.MakeEdge(E,SPL1,1.e-7);

TopoDS_Vertex Vfirst,Vend;
Brep.MakeVertex(Vfirst,controlPoints.Value(0),1.e-7);
Brep.MakeVertex(Vend,controlPoints.Value(5),1.e-7);

Vfirst.Orientation(TopAbs_FORWARD);
Vend.Orientation(TopAbs_REVERSED);

Brep.Add(E,Vfirst); //FORWARD POINT (first)

for (int i = 2; i < (4); ++i) //SOME CONTROL POINTS
{
TopoDS_Vertex V;
Brep.MakeVertex(V,controlPoints.Value(i),1.e-7);
Brep.Add(E,V);
}

Brep.Add(E,Vend); //RESERVE POINT (Last)

}
catch (...)
{

}

But... is it not needful to set the weights, knots and multiplicities. I try to rebuild a IGES curve, so I have to rebuild every aspect of the curve.

JuryS's picture

I don't understand how convert control point in spline, and this a reason that I'm use a control point in the shape. But I must remove all this point before creating path or face. Maybe you are need too save the input points in the shape ?

EricThompson's picture

I think I see two problems:

1) I believe you are setting the array bounds incorrectly. The values passed in to the array constructor are the low and high bounds of the array. So for your control points, if you are using five values indexed 0-4, your constructor would be: TColgp_Array1OfPnt controlPoints(0,4);

2) The number of elements in the array of weights must be the same as the number of elements in the array of control points.

I'm not sure if those are the only problems in your code, the Geom_BSplineCurve does a lot of checking of the values you pass in, and throws the same exception for any problem it finds.

Franz Engel's picture

Ohhh... Yes, you are right. Now I get a curve very similar to my original curve. Currently I have only a straight line. But I'm still in the opinion that I don't rebuild every information of the B-Spline. I'm not an expert for splines, but the wights and knots should have a meaining or not?

Thank you Eric!

EricThompson's picture

I'm not a spline expert either, the splines I'm constructing are based on values that I read in, so I have not actually studied what they all mean. If your are not supplied with weights it seems safe to set them all to 1. Knots are used to effect the degree of the curve, they are commonly used for creating straight segments, and effecting the straightness at the end of a non-periodic curve.

Gilles Paiva's picture

Hi, everybody!

I have to create 2 splines and a ruled surface in the middle of them.

What code is really correct? Can anybody send an simple example of how to make it?
____
/ \
_/ \___
| |
| |
| ____ |
| / \ |
|__/ \__|

something like that. 2 splines, with a ruled surface between them. There´s a pictured attached.

Does anyone can send me a sample program, just to understand how to do this? I am pretty new on OpenCascade and confused with some points on it.

Attachments: 
Wout Rikkerink's picture

Hi Franz,

First of all, I think you're missing one control point.

OpenCascade uses a multiplier for the knots. Setting all multipliers to 1 should work theoretically, but OCC wants the knot values to increase: knot[i] - knot[i-1] > epsilon.

The solution is to merge the knots by value and set the correct multiplier:

TColStd_Array1OfReal knots(0,1);
knots.SetValue(0,Standard_Real(0.0));
knots.SetValue(1,Standard_Real(381.0640687));

TColStd_Array1OfInteger multiplicities(0,1);
multiplicities.SetValue(0,Standard_Real(6.0));
multiplicities.SetValue(1,Standard_Real(6.0));

Hope this helps you and anyone else trying to construct a Geom_BSplineCurve.

Best regards,

Wout Rikkerink