Foundation Classes, Convert - Replace handle-based APIs with direct array access (#1057)

Refactor the Convert package to eliminate heap-allocated handle-based storage
in favor of direct NCollection_Array members, improving performance and
simplifying the API. Deprecate single-element accessors (Pole, Knot, etc.)
in favor of batch const-reference accessors (Poles, Knots, etc.).

Convert_ConicToBSplineCurve:
- Replace handle members (poles, weights, knots, mults) with direct
  NCollection_Array1 fields (myPoles, myWeights, myKnots, myMults).
- Replace BuildCosAndSin handle-based parameters with array references.
- Add batch accessors: Poles(), Weights(), Knots(), Multiplicities().
- Deprecate single-element accessors: Pole(), Weight(), Knot(), Multiplicity().
- Update all conic subclasses: Circle, Ellipse, Hyperbola, Parabola.

Convert_ElementarySurfaceToBSplineSurface:
- Replace handle members with direct NCollection_Array fields
  (myPoles, myWeights, myUKnots, myVKnots, myUMults, myVMults).
- Add Finalize() to trim oversized arrays in derived constructors.
- Add batch accessors: Poles(), Weights(), UKnots(), VKnots(),
  UMultiplicities(), VMultiplicities().
- Deprecate single-element accessors: Pole(), Weight(), UKnot(), VKnot(),
  UMultiplicity(), VMultiplicity().
- Update all surface subclasses: Cone, Cylinder, Sphere, Torus.

Convert_CompPolynomialToPoles / Convert_GridPolynomialToPoles:
- Replace handle-based output parameters with direct const-reference
  accessors for Poles, Knots, Multiplicities.
- Deprecate old handle-based Poles(), Knots(), Multiplicities() overloads.

Convert_CompBezierCurvesToBSplineCurve (2D and 3D):
- Extract common logic into Convert_CompBezierCurvesToBSplineCurveBase
  template header to eliminate code duplication.
- Replace handle<HArray1> members with direct NCollection_Array1 storage
  in the internal sequence, removing unnecessary heap indirection.

NCollection_Sequence:
- Fix Node constructors to use member initializer lists (copy/move
  construction) instead of default-construct + assign, which failed for
  types like NCollection_Array1 where operator= requires matching sizes.

Downstream callers migrated:
- AdvApprox_ApproxAFunction: use new const-ref Knots()/Multiplicities().
- AppDef_Variational: use new const-ref Knots()/Multiplicities().
- AdvApp2Var_ApproxAFunc2Var, AdvApp2Var_Patch: use new const-ref API.
- Geom2dConvert, GeomConvert, GeomConvert_1: use new const-ref API.
- GeomFill_PolynomialConvertor, GeomFill_QuasiAngularConvertor: adapted.
- Geom_OsculatingSurface: use direct array references instead of
  handle->Array*() calls.

Added GTests for all Convert classes covering conic curves,
elementary surfaces, CompBezier, CompPolynomial, and GridPolynomial
conversions.
This commit is contained in:
Pasukhin Dmitry
2026-02-09 16:38:55 +00:00
committed by GitHub
parent 87703a2dac
commit 498e7cd173
48 changed files with 3112 additions and 1929 deletions
@@ -24,7 +24,6 @@
#include <Standard_DomainError.hxx>
#include <gp_Pnt2d.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
// Attention :
// To avoid use of persistent tables in the fields
@@ -53,41 +52,38 @@ Convert_CircleToBSplineCurve::Convert_CircleToBSplineCurve(
int ii;
double R, value;
occ::handle<NCollection_HArray1<double>> CosNumeratorPtr, SinNumeratorPtr;
double R, value;
NCollection_Array1<double> CosNumerator, SinNumerator;
R = C.Radius();
if (Parameterisation != Convert_TgtThetaOver2 && Parameterisation != Convert_RationalC1)
{
// In case if BuildCosAndSin does not know how to manage the periodicity
// => trim on 0,2*PI
isperiodic = false;
myIsPeriodic = false;
Convert_ConicToBSplineCurve::BuildCosAndSin(Parameterisation,
0,
2 * M_PI,
CosNumeratorPtr,
SinNumeratorPtr,
weights,
degree,
knots,
mults);
CosNumerator,
SinNumerator,
myWeights,
myDegree,
myKnots,
myMults);
}
else
{
isperiodic = true;
myIsPeriodic = true;
Convert_ConicToBSplineCurve::BuildCosAndSin(Parameterisation,
CosNumeratorPtr,
SinNumeratorPtr,
weights,
degree,
knots,
mults);
CosNumerator,
SinNumerator,
myWeights,
myDegree,
myKnots,
myMults);
}
nbPoles = CosNumeratorPtr->Length();
nbKnots = knots->Length();
poles = new NCollection_HArray1<gp_Pnt2d>(1, nbPoles);
myPoles = NCollection_Array1<gp_Pnt2d>(1, CosNumerator.Length());
gp_Dir2d Ox = C.XAxis().Direction();
gp_Dir2d Oy = C.YAxis().Direction();
@@ -105,11 +101,11 @@ Convert_CircleToBSplineCurve::Convert_CircleToBSplineCurve(
// Replace the bspline in the reference of the circle.
// and calculate the weight of the bspline.
for (ii = 1; ii <= nbPoles; ii++)
for (ii = 1; ii <= myPoles.Length(); ii++)
{
poles->ChangeArray1()(ii).SetCoord(1, R * CosNumeratorPtr->Value(ii));
poles->ChangeArray1()(ii).SetCoord(2, value * SinNumeratorPtr->Value(ii));
poles->ChangeArray1()(ii).Transform(Trsf);
myPoles(ii).SetCoord(1, R * CosNumerator(ii));
myPoles(ii).SetCoord(2, value * SinNumerator(ii));
myPoles(ii).Transform(Trsf);
}
}
@@ -133,26 +129,23 @@ Convert_CircleToBSplineCurve::Convert_CircleToBSplineCurve(
throw Standard_DomainError("Convert_CircleToBSplineCurve");
}
int ii;
double R, value;
occ::handle<NCollection_HArray1<double>> CosNumeratorPtr, SinNumeratorPtr;
int ii;
double R, value;
NCollection_Array1<double> CosNumerator, SinNumerator;
R = C.Radius();
isperiodic = false;
R = C.Radius();
myIsPeriodic = false;
Convert_ConicToBSplineCurve::BuildCosAndSin(Parameterisation,
UFirst,
ULast,
CosNumeratorPtr,
SinNumeratorPtr,
weights,
degree,
knots,
mults);
CosNumerator,
SinNumerator,
myWeights,
myDegree,
myKnots,
myMults);
nbPoles = CosNumeratorPtr->Length();
nbKnots = knots->Length();
poles = new NCollection_HArray1<gp_Pnt2d>(1, nbPoles);
myPoles = NCollection_Array1<gp_Pnt2d>(1, CosNumerator.Length());
gp_Dir2d Ox = C.XAxis().Direction();
gp_Dir2d Oy = C.YAxis().Direction();
@@ -170,10 +163,10 @@ Convert_CircleToBSplineCurve::Convert_CircleToBSplineCurve(
// Replace the bspline in the reference of the circle.
// and calculate the weight of the bspline.
for (ii = 1; ii <= nbPoles; ii++)
for (ii = 1; ii <= myPoles.Length(); ii++)
{
poles->ChangeArray1()(ii).SetCoord(1, R * CosNumeratorPtr->Value(ii));
poles->ChangeArray1()(ii).SetCoord(2, value * SinNumeratorPtr->Value(ii));
poles->ChangeArray1()(ii).Transform(Trsf);
myPoles(ii).SetCoord(1, R * CosNumerator(ii));
myPoles(ii).SetCoord(2, value * SinNumerator(ii));
myPoles(ii).Transform(Trsf);
}
}
@@ -14,203 +14,12 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <BSplCLib.hxx>
#include <Convert_CompBezierCurves2dToBSplineCurve2d.hxx>
#include <gp.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Vec2d.hxx>
#include <PLib.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
//=================================================================================================
//==================================================================================================
Convert_CompBezierCurves2dToBSplineCurve2d::Convert_CompBezierCurves2dToBSplineCurve2d(
const double AngularTolerance)
: myDegree(0),
myAngular(AngularTolerance),
myDone(false)
const double theAngularTolerance)
: Convert_CompBezierCurvesToBSplineCurveBase<gp_Pnt2d, gp_Vec2d>(theAngularTolerance)
{
}
//=================================================================================================
void Convert_CompBezierCurves2dToBSplineCurve2d::AddCurve(const NCollection_Array1<gp_Pnt2d>& Poles)
{
if (!mySequence.IsEmpty())
{
gp_Pnt2d P1, P2;
P1 = mySequence.Last()->Value(mySequence.Last()->Upper());
P2 = Poles(Poles.Lower());
// User defined tolerance NYI
// Standard_ConstructionError_Raise_if
// ( !P1.IsEqual(P2,Precision::Confusion()),
// "Convert_CompBezierCurves2dToBSplineCurve2d::Addcurve");
}
myDone = false;
occ::handle<NCollection_HArray1<gp_Pnt2d>> HPoles =
new NCollection_HArray1<gp_Pnt2d>(Poles.Lower(), Poles.Upper());
HPoles->ChangeArray1() = Poles;
mySequence.Append(HPoles);
}
//=================================================================================================
int Convert_CompBezierCurves2dToBSplineCurve2d::Degree() const
{
return myDegree;
}
//=================================================================================================
int Convert_CompBezierCurves2dToBSplineCurve2d::NbPoles() const
{
return CurvePoles.Length();
}
//=================================================================================================
void Convert_CompBezierCurves2dToBSplineCurve2d::Poles(NCollection_Array1<gp_Pnt2d>& Poles) const
{
int i, Lower = Poles.Lower(), Upper = Poles.Upper();
int k = 1;
for (i = Lower; i <= Upper; i++)
{
Poles(i) = CurvePoles(k++);
}
}
//=================================================================================================
int Convert_CompBezierCurves2dToBSplineCurve2d::NbKnots() const
{
return CurveKnots.Length();
}
//=================================================================================================
void Convert_CompBezierCurves2dToBSplineCurve2d::KnotsAndMults(NCollection_Array1<double>& Knots,
NCollection_Array1<int>& Mults) const
{
int i, LowerK = Knots.Lower(), UpperK = Knots.Upper();
int LowerM = Mults.Lower(), UpperM = Mults.Upper();
int k = 1;
for (i = LowerK; i <= UpperK; i++)
{
Knots(i) = CurveKnots(k++);
}
k = 1;
for (i = LowerM; i <= UpperM; i++)
{
Mults(i) = KnotsMultiplicities(k++);
}
}
//=================================================================================================
void Convert_CompBezierCurves2dToBSplineCurve2d::Perform()
{
myDone = true;
CurvePoles.Clear();
CurveKnots.Clear();
KnotsMultiplicities.Clear();
int LowerI = 1;
int UpperI = mySequence.Length();
int NbrCurv = UpperI - LowerI + 1;
// int NbKnotsSpl = NbrCurv + 1 ;
NCollection_Array1<double> CurveKnVals(1, NbrCurv);
int i;
myDegree = 0;
for (i = 1; i <= mySequence.Length(); i++)
{
myDegree = std::max(myDegree, (mySequence(i))->Length() - 1);
}
double Det = 0;
gp_Pnt2d P1, P2, P3;
int Deg, Inc, MaxDegree = myDegree;
NCollection_Array1<gp_Pnt2d> Points(1, myDegree + 1);
for (i = LowerI; i <= UpperI; i++)
{
// 1- Rise Bezier curve to the maximum degree.
Deg = mySequence(i)->Length() - 1;
Inc = myDegree - Deg;
if (Inc > 0)
{
BSplCLib::IncreaseDegree(myDegree,
mySequence(i)->Array1(),
BSplCLib::NoWeights(),
Points,
BSplCLib::NoWeights());
}
else
{
Points = mySequence(i)->Array1();
}
// 2- Process the node of junction between Bezier curves.
if (i == LowerI)
{
// Processing of initial node of the BSpline.
for (int j = 1; j <= MaxDegree; j++)
{
CurvePoles.Append(Points(j));
}
CurveKnVals(1) = 1.; // To begin the series.
KnotsMultiplicities.Append(MaxDegree + 1);
Det = 1.;
}
if (i != LowerI)
{
P2 = Points(1);
P3 = Points(2);
gp_Vec2d V1(P1, P2), V2(P2, P3);
// Processing of the tangency between the Bezier and the previous.
// This allows guaranteeing at least continuity C1 if the tangents are coherent.
// Test of angle at myAngular
double D1 = V1.SquareMagnitude();
double D2 = V2.SquareMagnitude();
if (MaxDegree > 1 && // rln 20.06.99 work-around
D1 > gp::Resolution() && D2 > gp::Resolution() && V1.IsParallel(V2, myAngular))
{
double Lambda = std::sqrt(D2 / D1);
KnotsMultiplicities.Append(MaxDegree - 1);
CurveKnVals(i) = CurveKnVals(i - 1) * Lambda;
}
else
{
CurvePoles.Append(Points(1));
KnotsMultiplicities.Append(MaxDegree);
CurveKnVals(i) = 1.0;
}
Det += CurveKnVals(i);
// Store poles.
for (int j = 2; j <= MaxDegree; j++)
{
CurvePoles.Append(Points(j));
}
}
if (i == UpperI)
{
// Process end node of the BSpline.
CurvePoles.Append(Points(MaxDegree + 1));
KnotsMultiplicities.Append(MaxDegree + 1);
}
P1 = Points(MaxDegree);
}
// Correct nodal values to make them variable within [0.,1.].
CurveKnots.Append(0.0);
for (i = 2; i <= NbrCurv; i++)
{
CurveKnots.Append(CurveKnots(i - 1) + (CurveKnVals(i - 1) / Det));
}
CurveKnots.Append(1.0);
}
@@ -17,161 +17,26 @@
#ifndef _Convert_CompBezierCurves2dToBSplineCurve2d_HeaderFile
#define _Convert_CompBezierCurves2dToBSplineCurve2d_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Convert_CompBezierCurvesToBSplineCurveBase.hxx>
#include <gp_Pnt2d.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
#include <NCollection_Sequence.hxx>
#include <Standard_Integer.hxx>
#include <gp_Vec2d.hxx>
//! Converts a list of connecting Bezier Curves 2d to a
//! BSplineCurve 2d.
//! if possible, the continuity of the BSpline will be
//! increased to more than C0.
class Convert_CompBezierCurves2dToBSplineCurve2d
: public Convert_CompBezierCurvesToBSplineCurveBase<gp_Pnt2d, gp_Vec2d>
{
public:
DEFINE_STANDARD_ALLOC
//! Constructs a framework for converting a sequence of
//! adjacent non-rational Bezier curves into a BSpline curve.
//! Knots will be created on the computed BSpline curve at
//! each junction point of two consecutive Bezier curves. The
//! degree of continuity of the BSpline curve will be increased at
//! the junction point of two consecutive Bezier curves if their
//! tangent vectors at this point are parallel. AngularTolerance
//! (given in radians, and defaulted to 1.0 e-4) will be used
//! to check the parallelism of the two tangent vectors.
//! Use the following functions:
//! - AddCurve to define in sequence the adjacent Bezier
//! curves to be converted,
//! - Perform to compute the data needed to build the BSpline curve,
//! - and the available consultation functions to access the
//! computed data. This data may be used to construct the BSpline curve.
//! @param[in] theAngularTolerance angular tolerance in radians
//! for checking tangent parallelism at junction points
Standard_EXPORT Convert_CompBezierCurves2dToBSplineCurve2d(
const double AngularTolerance = 1.0e-4);
//! Adds the Bezier curve defined by the table of poles Poles, to
//! the sequence (still contained in this framework) of adjacent
//! Bezier curves to be converted into a BSpline curve.
//! Only polynomial (i.e. non-rational) Bezier curves are
//! converted using this framework.
//! If this is not the first call to the function (i.e. if this framework
//! still contains data in its sequence of Bezier curves), the
//! degree of continuity of the BSpline curve will be increased at
//! the time of computation at the first point of the added Bezier
//! curve (i.e. the first point of the Poles table). This will be the
//! case if the tangent vector of the curve at this point is
//! parallel to the tangent vector at the end point of the
//! preceding Bezier curve in the sequence of Bezier curves still
//! contained in this framework. An angular tolerance given at
//! the time of construction of this framework, will be used to
//! check the parallelism of the two tangent vectors. This
//! checking procedure, and all the relative computations will be
//! performed by the function Perform.
//! When the sequence of adjacent Bezier curves is complete,
//! use the following functions:
//! - Perform to compute the data needed to build the BSpline curve,
//! - and the available consultation functions to access the
//! computed data. This data may be used to construct the BSpline curve.
//! Warning
//! The sequence of Bezier curves treated by this framework is
//! automatically initialized with the first Bezier curve when the
//! function is first called. During subsequent use of this function,
//! ensure that the first point of the added Bezier curve (i.e. the
//! first point of the Poles table) is coincident with the last point
//! of the sequence (i.e. the last point of the preceding Bezier
//! curve in the sequence) of Bezier curves still contained in
//! this framework. An error may occur at the time of
//! computation if this condition is not satisfied. Particular care
//! must be taken with respect to the above, as this condition is
//! not checked either when defining the sequence of Bezier
//! curves or at the time of computation.
Standard_EXPORT void AddCurve(const NCollection_Array1<gp_Pnt2d>& Poles);
//! Computes all the data needed to build a BSpline curve
//! equivalent to the sequence of adjacent Bezier curves still
//! contained in this framework.
//! A knot is inserted on the computed BSpline curve at the
//! junction point of two consecutive Bezier curves. The
//! degree of continuity of the BSpline curve will be increased
//! at the junction point of two consecutive Bezier curves if
//! their tangent vectors at this point are parallel. An angular
//! tolerance given at the time of construction of this
//! framework is used to check the parallelism of the two
//! tangent vectors.
//! Use the available consultation functions to access the
//! computed data. This data may then be used to construct
//! the BSpline curve.
//! Warning
//! Ensure that the curves in the sequence of Bezier curves
//! contained in this framework are adjacent. An error may
//! occur at the time of computation if this condition is not
//! satisfied. Particular care must be taken with respect to the
//! above as this condition is not checked, either when
//! defining the Bezier curve sequence or at the time of computation.
Standard_EXPORT void Perform();
//! Returns the degree of the BSpline curve whose data is
//! computed in this framework.
//! Warning
//! Take particular care not to use this function before the
//! computation is performed (Perform function), as this
//! condition is not checked and an error may therefore occur.
Standard_EXPORT int Degree() const;
//! Returns the number of poles of the BSpline curve whose
//! data is computed in this framework.
//! Warning
//! Take particular care not to use this function before the
//! computation is performed (Perform function), as this
//! condition is not checked and an error may therefore occur.
Standard_EXPORT int NbPoles() const;
//! Loads the Poles table with the poles of the BSpline curve
//! whose data is computed in this framework.
//! Warning
//! - Do not use this function before the computation is
//! performed (Perform function).
//! - The length of the Poles array must be equal to the
//! number of poles of the BSpline curve whose data is
//! computed in this framework.
//! Particular care must be taken with respect to the above, as
//! these conditions are not checked, and an error may occur.
Standard_EXPORT void Poles(NCollection_Array1<gp_Pnt2d>& Poles) const;
//! Returns the number of knots of the BSpline curve whose
//! data is computed in this framework.
//! Warning
//! Take particular care not to use this function before the
//! computation is performed (Perform function), as this
//! condition is not checked and an error may therefore occur.
Standard_EXPORT int NbKnots() const;
//! Loads the Knots table with the knots
//! and the Mults table with the corresponding multiplicities
//! of the BSpline curve whose data is computed in this framework.
//! Warning
//! - Do not use this function before the computation is
//! performed (Perform function).
//! - The length of the Knots and Mults arrays must be equal
//! to the number of knots in the BSpline curve whose data is
//! computed in this framework.
//! Particular care must be taken with respect to the above as
//! these conditions are not checked, and an error may occur.
Standard_EXPORT void KnotsAndMults(NCollection_Array1<double>& Knots,
NCollection_Array1<int>& Mults) const;
private:
NCollection_Sequence<occ::handle<NCollection_HArray1<gp_Pnt2d>>> mySequence;
NCollection_Sequence<gp_Pnt2d> CurvePoles;
NCollection_Sequence<double> CurveKnots;
NCollection_Sequence<int> KnotsMultiplicities;
int myDegree;
double myAngular;
bool myDone;
const double theAngularTolerance = 1.0e-4);
};
#endif // _Convert_CompBezierCurves2dToBSplineCurve2d_HeaderFile
@@ -14,214 +14,12 @@
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <BSplCLib.hxx>
#include <Convert_CompBezierCurvesToBSplineCurve.hxx>
#include <gp.hxx>
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <Precision.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
//=================================================================================================
//==================================================================================================
Convert_CompBezierCurvesToBSplineCurve::Convert_CompBezierCurvesToBSplineCurve(
const double AngularTolerance)
: myDegree(0),
myAngular(AngularTolerance),
myDone(false)
const double theAngularTolerance)
: Convert_CompBezierCurvesToBSplineCurveBase<gp_Pnt, gp_Vec>(theAngularTolerance)
{
}
//=================================================================================================
void Convert_CompBezierCurvesToBSplineCurve::AddCurve(const NCollection_Array1<gp_Pnt>& Poles)
{
if (!mySequence.IsEmpty())
{
gp_Pnt P1, P2;
P1 = mySequence.Last()->Value(mySequence.Last()->Upper());
P2 = Poles(Poles.Lower());
#ifdef OCCT_DEBUG
if (!P1.IsEqual(P2, Precision::Confusion()))
std::cout << "Convert_CompBezierCurvesToBSplineCurve::Addcurve" << std::endl;
#endif
}
myDone = false;
occ::handle<NCollection_HArray1<gp_Pnt>> HPoles =
new NCollection_HArray1<gp_Pnt>(Poles.Lower(), Poles.Upper());
HPoles->ChangeArray1() = Poles;
mySequence.Append(HPoles);
}
//=================================================================================================
int Convert_CompBezierCurvesToBSplineCurve::Degree() const
{
return myDegree;
}
//=================================================================================================
int Convert_CompBezierCurvesToBSplineCurve::NbPoles() const
{
return CurvePoles.Length();
}
//=================================================================================================
void Convert_CompBezierCurvesToBSplineCurve::Poles(NCollection_Array1<gp_Pnt>& Poles) const
{
int i, Lower = Poles.Lower(), Upper = Poles.Upper();
int k = 1;
for (i = Lower; i <= Upper; i++)
{
Poles(i) = CurvePoles(k++);
}
}
//=================================================================================================
int Convert_CompBezierCurvesToBSplineCurve::NbKnots() const
{
return CurveKnots.Length();
}
//=================================================================================================
void Convert_CompBezierCurvesToBSplineCurve::KnotsAndMults(NCollection_Array1<double>& Knots,
NCollection_Array1<int>& Mults) const
{
int i, LowerK = Knots.Lower(), UpperK = Knots.Upper();
int LowerM = Mults.Lower(), UpperM = Mults.Upper();
int k = 1;
for (i = LowerK; i <= UpperK; i++)
{
Knots(i) = CurveKnots(k++);
}
k = 1;
for (i = LowerM; i <= UpperM; i++)
{
Mults(i) = KnotsMultiplicities(k++);
}
}
//=================================================================================================
void Convert_CompBezierCurvesToBSplineCurve::Perform()
{
myDone = true;
CurvePoles.Clear();
CurveKnots.Clear();
KnotsMultiplicities.Clear();
int LowerI = 1;
int UpperI = mySequence.Length();
int NbrCurv = UpperI - LowerI + 1;
// int NbKnotsSpl = NbrCurv + 1 ;
NCollection_Array1<double> CurveKnVals(1, NbrCurv);
int i;
myDegree = 0;
for (i = 1; i <= mySequence.Length(); i++)
{
myDegree = std::max(myDegree, (mySequence(i))->Length() - 1);
}
double Det = 0;
gp_Pnt P1, P2, P3;
int Deg, Inc, MaxDegree = myDegree;
NCollection_Array1<gp_Pnt> Points(1, myDegree + 1);
for (i = LowerI; i <= UpperI; i++)
{
// 1- Raise the Bezier curve to the maximum degree.
Deg = mySequence(i)->Length() - 1;
Inc = myDegree - Deg;
if (Inc > 0)
{
BSplCLib::IncreaseDegree(myDegree,
mySequence(i)->Array1(),
BSplCLib::NoWeights(),
Points,
BSplCLib::NoWeights());
}
else
{
Points = mySequence(i)->Array1();
}
// 2- Process the node of junction between 2 Bezier curves.
if (i == LowerI)
{
// Processing of the initial node of the BSpline.
for (int j = 1; j <= MaxDegree; j++)
{
CurvePoles.Append(Points(j));
}
CurveKnVals(1) = 1.; // To begin the series.
KnotsMultiplicities.Append(MaxDegree + 1);
Det = 1.;
}
if (i != LowerI)
{
P2 = Points(1);
P3 = Points(2);
gp_Vec V1(P1, P2), V2(P2, P3);
// Processing of the tangency between Bezier and the previous.
// This allows to guarantee at least a C1 continuity if the tangents are
// coherent.
double D1 = V1.SquareMagnitude();
double D2 = V2.SquareMagnitude();
if (MaxDegree > 1 && // rln 20.06.99 work-around
D1 > gp::Resolution() && D2 > gp::Resolution() && V1.IsParallel(V2, myAngular))
{
double Lambda = std::sqrt(D2 / D1);
if (CurveKnVals(i - 1) * Lambda > 10. * Epsilon(Det))
{
KnotsMultiplicities.Append(MaxDegree - 1);
CurveKnVals(i) = CurveKnVals(i - 1) * Lambda;
}
else
{
CurvePoles.Append(Points(1));
KnotsMultiplicities.Append(MaxDegree);
CurveKnVals(i) = 1.0;
}
}
else
{
CurvePoles.Append(Points(1));
KnotsMultiplicities.Append(MaxDegree);
CurveKnVals(i) = 1.0;
}
Det += CurveKnVals(i);
// Store the poles.
for (int j = 2; j <= MaxDegree; j++)
{
CurvePoles.Append(Points(j));
}
}
if (i == UpperI)
{
// Processing of the end node of the BSpline.
CurvePoles.Append(Points(MaxDegree + 1));
KnotsMultiplicities.Append(MaxDegree + 1);
}
P1 = Points(MaxDegree);
}
// Correct nodal values to make them variable within [0.,1.].
CurveKnots.Append(0.0);
// std::cout << "Convert : Det = " << Det << std::endl;
for (i = 2; i <= NbrCurv; i++)
{
CurveKnots.Append(CurveKnots(i - 1) + (CurveKnVals(i - 1) / Det));
}
CurveKnots.Append(1.0);
}
@@ -17,14 +17,9 @@
#ifndef _Convert_CompBezierCurvesToBSplineCurve_HeaderFile
#define _Convert_CompBezierCurvesToBSplineCurve_HeaderFile
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Convert_CompBezierCurvesToBSplineCurveBase.hxx>
#include <gp_Pnt.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
#include <NCollection_Sequence.hxx>
#include <Standard_Integer.hxx>
#include <gp_Vec.hxx>
//! An algorithm to convert a sequence of adjacent
//! non-rational Bezier curves into a BSpline curve.
@@ -36,146 +31,16 @@
//! Warning
//! Do not attempt to convert rational Bezier curves using this type of algorithm.
class Convert_CompBezierCurvesToBSplineCurve
: public Convert_CompBezierCurvesToBSplineCurveBase<gp_Pnt, gp_Vec>
{
public:
DEFINE_STANDARD_ALLOC
//! Constructs a framework for converting a sequence of
//! adjacent non-rational Bezier curves into a BSpline curve.
//! Knots will be created on the computed BSpline curve at
//! each junction point of two consecutive Bezier curves. The
//! degree of continuity of the BSpline curve will be increased at
//! the junction point of two consecutive Bezier curves if their
//! tangent vectors at this point are parallel. AngularTolerance
//! (given in radians, and defaulted to 1.0 e-4) will be used
//! to check the parallelism of the two tangent vectors.
//! Use the following functions:
//! - AddCurve to define in sequence the adjacent Bezier
//! curves to be converted,
//! - Perform to compute the data needed to build the BSpline curve,
//! - and the available consultation functions to access the
//! computed data. This data may be used to construct the BSpline curve.
Standard_EXPORT Convert_CompBezierCurvesToBSplineCurve(const double AngularTolerance = 1.0e-4);
//! Adds the Bezier curve defined by the table of poles Poles, to
//! the sequence (still contained in this framework) of adjacent
//! Bezier curves to be converted into a BSpline curve.
//! Only polynomial (i.e. non-rational) Bezier curves are
//! converted using this framework.
//! If this is not the first call to the function (i.e. if this framework
//! still contains data in its Bezier curve sequence), the degree
//! of continuity of the BSpline curve will be increased at the
//! time of computation at the first point of the added Bezier
//! curve (i.e. the first point of the Poles table). This will be the
//! case if the tangent vector of the curve at this point is
//! parallel to the tangent vector at the end point of the
//! preceding Bezier curve in the Bezier curve sequence still
//! contained in this framework. An angular tolerance given at
//! the time of construction of this framework will be used to
//! check the parallelism of the two tangent vectors. This
//! checking procedure and all related computations will be
//! performed by the Perform function.
//! When the adjacent Bezier curve sequence is complete, use
//! the following functions:
//! - Perform to compute the data needed to build the BSpline curve,
//! - and the available consultation functions to access the
//! computed data. This data may be used to construct the BSpline curve.
//! Warning
//! The Bezier curve sequence treated by this framework is
//! automatically initialized with the first Bezier curve when the
//! function is first called. During subsequent use of this function,
//! ensure that the first point of the added Bezier curve (i.e. the
//! first point of the Poles table) is coincident with the last point
//! of the Bezier curve sequence (i.e. the last point of the
//! preceding Bezier curve in the sequence) still contained in
//! this framework. An error may occur at the time of
//! computation if this condition is not satisfied. Particular care
//! must be taken with respect to the above, as this condition is
//! not checked either when defining the Bezier curve
//! sequence or at the time of computation.
Standard_EXPORT void AddCurve(const NCollection_Array1<gp_Pnt>& Poles);
//! Computes all the data needed to build a BSpline curve
//! equivalent to the adjacent Bezier curve sequence still
//! contained in this framework.
//! A knot is inserted on the computed BSpline curve at the
//! junction point of two consecutive Bezier curves. The
//! degree of continuity of the BSpline curve will be increased
//! at the junction point of two consecutive Bezier curves if
//! their tangent vectors at this point are parallel. An angular
//! tolerance given at the time of construction of this
//! framework is used to check the parallelism of the two
//! tangent vectors.
//! Use the available consultation functions to access the
//! computed data. This data may then be used to construct
//! the BSpline curve.
//! Warning
//! Make sure that the curves in the Bezier curve sequence
//! contained in this framework are adjacent. An error may
//! occur at the time of computation if this condition is not
//! satisfied. Particular care must be taken with respect to the
//! above as this condition is not checked, either when
//! defining the Bezier curve sequence or at the time of computation.
Standard_EXPORT void Perform();
//! Returns the degree of the BSpline curve whose data is
//! computed in this framework.
//! Warning
//! Take particular care not to use this function before the
//! computation is performed (Perform function), as this
//! condition is not checked and an error may therefore occur.
Standard_EXPORT int Degree() const;
//! Returns the number of poles of the BSpline curve whose
//! data is computed in this framework.
//! Warning
//! Take particular care not to use this function before the
//! computation is performed (Perform function), as this
//! condition is not checked and an error may therefore occur.
Standard_EXPORT int NbPoles() const;
//! Loads the Poles table with the poles of the BSpline curve
//! whose data is computed in this framework.
//! Warning
//! - Do not use this function before the computation is
//! performed (Perform function).
//! - The length of the Poles array must be equal to the
//! number of poles of the BSpline curve whose data is
//! computed in this framework.
//! Particular care must be taken with respect to the above, as
//! these conditions are not checked, and an error may occur.
Standard_EXPORT void Poles(NCollection_Array1<gp_Pnt>& Poles) const;
//! Returns the number of knots of the BSpline curve whose
//! data is computed in this framework.
//! Warning
//! Take particular care not to use this function before the
//! computation is performed (Perform function), as this
//! condition is not checked and an error may therefore occur.
Standard_EXPORT int NbKnots() const;
//! - loads the Knots table with the knots,
//! - and loads the Mults table with the corresponding multiplicities
//! of the BSpline curve whose data is computed in this framework.
//! Warning
//! - Do not use this function before the computation is
//! performed (Perform function).
//! - The length of the Knots and Mults arrays must be equal
//! to the number of knots in the BSpline curve whose data is
//! computed in this framework.
//! Particular care must be taken with respect to the above as
//! these conditions are not checked, and an error may occur.
Standard_EXPORT void KnotsAndMults(NCollection_Array1<double>& Knots,
NCollection_Array1<int>& Mults) const;
private:
NCollection_Sequence<occ::handle<NCollection_HArray1<gp_Pnt>>> mySequence;
NCollection_Sequence<gp_Pnt> CurvePoles;
NCollection_Sequence<double> CurveKnots;
NCollection_Sequence<int> KnotsMultiplicities;
int myDegree;
double myAngular;
bool myDone;
//! @param[in] theAngularTolerance angular tolerance in radians
//! for checking tangent parallelism at junction points
Standard_EXPORT Convert_CompBezierCurvesToBSplineCurve(const double theAngularTolerance = 1.0e-4);
};
#endif // _Convert_CompBezierCurvesToBSplineCurve_HeaderFile
@@ -0,0 +1,222 @@
// Copyright (c) 2025 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#ifndef _Convert_CompBezierCurvesToBSplineCurveBase_HeaderFile
#define _Convert_CompBezierCurvesToBSplineCurveBase_HeaderFile
#include <BSplCLib.hxx>
#include <gp.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_Sequence.hxx>
#include <type_traits>
class gp_Pnt;
class gp_Pnt2d;
//! Template base class for converting a sequence of adjacent
//! non-rational Bezier curves into a BSpline curve.
//! PointType is gp_Pnt or gp_Pnt2d; VecType is gp_Vec or gp_Vec2d.
template <typename PointType, typename VecType>
class Convert_CompBezierCurvesToBSplineCurveBase
{
public:
//! Constructs a framework for converting a sequence of
//! adjacent non-rational Bezier curves into a BSpline curve.
//! @param[in] theAngularTolerance angular tolerance in radians
//! for checking tangent parallelism at junction points
explicit Convert_CompBezierCurvesToBSplineCurveBase(const double theAngularTolerance = 1.0e-4)
: myDegree(0),
myAngular(theAngularTolerance)
{
}
//! Adds the Bezier curve defined by the table of poles to
//! the sequence of adjacent Bezier curves to be converted.
//! @param[in] thePoles poles of the Bezier curve to add
void AddCurve(const NCollection_Array1<PointType>& thePoles) { mySequence.Append(thePoles); }
//! Computes all the data needed to build a BSpline curve
//! equivalent to the adjacent Bezier curve sequence.
void Perform()
{
myCurvePoles.Clear();
myCurveKnots.Clear();
myKnotsMults.Clear();
if (mySequence.IsEmpty())
{
return;
}
const int aLowerI = 1;
const int anUpperI = mySequence.Length();
const int aNbrCurv = anUpperI - aLowerI + 1;
NCollection_Array1<double> aCurveKnVals(1, aNbrCurv);
myDegree = 0;
for (int i = 1; i <= mySequence.Length(); i++)
{
myDegree = std::max(myDegree, mySequence(i).Length() - 1);
}
double aDet = 0;
PointType aP1, aP2, aP3;
const int aMaxDegree = myDegree;
NCollection_Array1<PointType> aPoints(1, myDegree + 1);
for (int i = aLowerI; i <= anUpperI; i++)
{
// 1- Raise the Bezier curve to the maximum degree.
const int aDeg = mySequence(i).Length() - 1;
const int anInc = myDegree - aDeg;
if (anInc > 0)
{
BSplCLib::IncreaseDegree(myDegree,
mySequence(i),
BSplCLib::NoWeights(),
aPoints,
BSplCLib::NoWeights());
}
else
{
aPoints = mySequence(i);
}
// 2- Process the node of junction between 2 Bezier curves.
if (i == aLowerI)
{
// Processing of the initial node of the BSpline.
for (int j = 1; j <= aMaxDegree; j++)
{
myCurvePoles.Append(aPoints(j));
}
aCurveKnVals(1) = 1.; // To begin the series.
myKnotsMults.Append(aMaxDegree + 1);
aDet = 1.;
}
if (i != aLowerI)
{
aP2 = aPoints(1);
aP3 = aPoints(2);
VecType aV1(aP1, aP2), aV2(aP2, aP3);
// Processing of the tangency between Bezier and the previous.
// This allows to guarantee at least a C1 continuity if the tangents are coherent.
const double aD1 = aV1.SquareMagnitude();
const double aD2 = aV2.SquareMagnitude();
if (aMaxDegree > 1 && aD1 > gp::Resolution() && aD2 > gp::Resolution()
&& aV1.IsParallel(aV2, myAngular))
{
const double aLambda = std::sqrt(aD2 / aD1);
if constexpr (std::is_same_v<PointType, gp_Pnt>)
{
// 3D-specific epsilon guard to avoid numerical issues
// when accumulated knot values become too small relative to Det.
if (aCurveKnVals(i - 1) * aLambda > 10. * Epsilon(aDet))
{
myKnotsMults.Append(aMaxDegree - 1);
aCurveKnVals(i) = aCurveKnVals(i - 1) * aLambda;
}
else
{
myCurvePoles.Append(aPoints(1));
myKnotsMults.Append(aMaxDegree);
aCurveKnVals(i) = 1.0;
}
}
else
{
myKnotsMults.Append(aMaxDegree - 1);
aCurveKnVals(i) = aCurveKnVals(i - 1) * aLambda;
}
}
else
{
myCurvePoles.Append(aPoints(1));
myKnotsMults.Append(aMaxDegree);
aCurveKnVals(i) = 1.0;
}
aDet += aCurveKnVals(i);
// Store the poles.
for (int j = 2; j <= aMaxDegree; j++)
{
myCurvePoles.Append(aPoints(j));
}
}
if (i == anUpperI)
{
// Processing of the end node of the BSpline.
myCurvePoles.Append(aPoints(aMaxDegree + 1));
myKnotsMults.Append(aMaxDegree + 1);
}
aP1 = aPoints(aMaxDegree);
}
// Correct nodal values to make them variable within [0.,1.].
myCurveKnots.Append(0.0);
for (int i = 2; i <= aNbrCurv; i++)
{
myCurveKnots.Append(myCurveKnots(i - 1) + (aCurveKnVals(i - 1) / aDet));
}
myCurveKnots.Append(1.0);
}
//! Returns the degree of the BSpline curve.
[[nodiscard]] int Degree() const { return myDegree; }
//! Returns the number of poles of the BSpline curve.
[[nodiscard]] int NbPoles() const { return myCurvePoles.Length(); }
//! Loads the Poles table with the poles of the BSpline curve.
//! @param[out] thePoles array to fill with poles
void Poles(NCollection_Array1<PointType>& thePoles) const
{
int k = 1;
for (int i = thePoles.Lower(); i <= thePoles.Upper(); i++)
{
thePoles(i) = myCurvePoles(k++);
}
}
//! Returns the number of knots of the BSpline curve.
[[nodiscard]] int NbKnots() const { return myCurveKnots.Length(); }
//! Loads the Knots and Mults tables with the knots
//! and corresponding multiplicities of the BSpline curve.
//! @param[out] theKnots array to fill with knots
//! @param[out] theMults array to fill with multiplicities
void KnotsAndMults(NCollection_Array1<double>& theKnots, NCollection_Array1<int>& theMults) const
{
int k = 1;
for (int i = theKnots.Lower(); i <= theKnots.Upper(); i++)
{
theKnots(i) = myCurveKnots(k++);
}
k = 1;
for (int i = theMults.Lower(); i <= theMults.Upper(); i++)
{
theMults(i) = myKnotsMults(k++);
}
}
private:
NCollection_Sequence<NCollection_Array1<PointType>> mySequence;
NCollection_Sequence<PointType> myCurvePoles;
NCollection_Sequence<double> myCurveKnots;
NCollection_Sequence<int> myKnotsMults;
int myDegree;
double myAngular;
};
#endif // _Convert_CompBezierCurvesToBSplineCurveBase_HeaderFile
@@ -22,17 +22,16 @@
// 15-04-97 : PMN : Constructeurs avec un seul segement ou differentes
// continuitees.
#define No_Standard_OutOfRange
#include <BSplCLib.hxx>
#include <Convert_CompPolynomialToPoles.hxx>
#include <PLib.hxx>
#include <Standard_ConstructionError.hxx>
#include <Standard_Integer.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
#include <NCollection_HArray2.hxx>
#include <PLib.hxx>
#include <Standard_ConstructionError.hxx>
#include <StdFail_NotDone.hxx>
//=================================================================================================
//==================================================================================================
Convert_CompPolynomialToPoles::Convert_CompPolynomialToPoles(
const int NumCurves,
@@ -43,19 +42,18 @@ Convert_CompPolynomialToPoles::Convert_CompPolynomialToPoles(
const occ::handle<NCollection_HArray1<double>>& Coefficients,
const occ::handle<NCollection_HArray2<double>>& PolynomialIntervals,
const occ::handle<NCollection_HArray1<double>>& TrueIntervals)
: myDone(false)
: myDegree(0),
myDone(false)
{
int ii, delta;
if (NumCurves <= 0 || NumCoeffPerCurve.IsNull() || Coefficients.IsNull()
|| PolynomialIntervals.IsNull() || TrueIntervals.IsNull() || Continuity < 0 || MaxDegree <= 0
|| Dimension <= 0 || PolynomialIntervals->RowLength() != 2)
{
throw Standard_ConstructionError("Convert_CompPolynomialToPoles:bad arguments");
}
myDegree = 0;
delta = NumCurves - 1;
for (ii = NumCoeffPerCurve->Lower(); ii <= NumCoeffPerCurve->Lower() + delta; ii++)
const int aDelta = NumCurves - 1;
for (int ii = NumCoeffPerCurve->Lower(); ii <= NumCoeffPerCurve->Lower() + aDelta; ii++)
{
myDegree = std::max(NumCoeffPerCurve->Value(ii) - 1, myDegree);
}
@@ -63,25 +61,21 @@ Convert_CompPolynomialToPoles::Convert_CompPolynomialToPoles(
{
throw Standard_ConstructionError("Convert_CompPolynomialToPoles:Continuity is too great");
}
//
// prepare output
//
int Tindex, multiplicities;
myKnots = new NCollection_HArray1<double>(1, NumCurves + 1);
for (ii = 1, Tindex = TrueIntervals->Lower(); ii <= NumCurves + 1; ii++, Tindex++)
myKnots = NCollection_Array1<double>(1, NumCurves + 1);
for (int ii = 1, Tindex = TrueIntervals->Lower(); ii <= NumCurves + 1; ii++, Tindex++)
{
myKnots->ChangeArray1().SetValue(ii, TrueIntervals->Value(Tindex));
myKnots.SetValue(ii, TrueIntervals->Value(Tindex));
}
multiplicities = myDegree - Continuity;
myMults = new NCollection_HArray1<int>(1, NumCurves + 1);
for (ii = 2; ii < NumCurves + 1; ii++)
const int aMultiplicities = myDegree - Continuity;
myMults = NCollection_Array1<int>(1, NumCurves + 1);
for (int ii = 2; ii < NumCurves + 1; ii++)
{
myMults->SetValue(ii, multiplicities);
myMults.SetValue(ii, aMultiplicities);
}
myMults->SetValue(1, myDegree + 1);
myMults->SetValue(NumCurves + 1, myDegree + 1);
myMults.SetValue(1, myDegree + 1);
myMults.SetValue(NumCurves + 1, myDegree + 1);
Perform(NumCurves,
MaxDegree,
@@ -101,45 +95,39 @@ Convert_CompPolynomialToPoles::Convert_CompPolynomialToPoles(
const NCollection_Array1<double>& Coefficients,
const NCollection_Array2<double>& PolynomialIntervals,
const NCollection_Array1<double>& TrueIntervals)
: myDone(false)
: myDegree(0),
myDone(false)
{
int ii, delta;
if (NumCurves <= 0 || MaxDegree <= 0 || Dimension <= 0 || PolynomialIntervals.RowLength() != 2)
{
throw Standard_ConstructionError("Convert_CompPolynomialToPoles:bad arguments");
}
myDegree = 0;
delta = NumCurves - 1;
for (ii = NumCoeffPerCurve.Lower(); ii <= NumCoeffPerCurve.Lower() + delta; ii++)
const int aDelta = NumCurves - 1;
for (int ii = NumCoeffPerCurve.Lower(); ii <= NumCoeffPerCurve.Lower() + aDelta; ii++)
{
myDegree = std::max(NumCoeffPerCurve.Value(ii) - 1, myDegree);
}
//
// prepare output
//
int Tindex;
myKnots = new NCollection_HArray1<double>(1, NumCurves + 1);
for (ii = 1, Tindex = TrueIntervals.Lower(); ii <= NumCurves + 1; ii++, Tindex++)
myKnots = NCollection_Array1<double>(1, NumCurves + 1);
for (int ii = 1, Tindex = TrueIntervals.Lower(); ii <= NumCurves + 1; ii++, Tindex++)
{
myKnots->ChangeArray1().SetValue(ii, TrueIntervals.Value(Tindex));
myKnots.SetValue(ii, TrueIntervals.Value(Tindex));
}
myMults = new NCollection_HArray1<int>(1, NumCurves + 1);
for (ii = 2; ii < NumCurves + 1; ii++)
myMults = NCollection_Array1<int>(1, NumCurves + 1);
for (int ii = 2; ii < NumCurves + 1; ii++)
{
if ((Continuity(ii) > myDegree) && (NumCurves > 1))
{
throw Standard_ConstructionError("Convert_CompPolynomialToPoles:Continuity is too great");
}
myMults->SetValue(ii, myDegree - Continuity(ii));
myMults.SetValue(ii, myDegree - Continuity(ii));
}
myMults->SetValue(1, myDegree + 1);
myMults->SetValue(NumCurves + 1, myDegree + 1);
myMults.SetValue(1, myDegree + 1);
myMults.SetValue(NumCurves + 1, myDegree + 1);
// Calculs
Perform(NumCurves,
MaxDegree,
Dimension,
@@ -158,7 +146,6 @@ Convert_CompPolynomialToPoles::Convert_CompPolynomialToPoles(
const NCollection_Array1<double>& TrueIntervals)
: myDegree(Degree),
myDone(false)
{
if (MaxDegree <= 0 || Dimension <= 0 || PolynomialIntervals.Length() != 2)
{
@@ -172,14 +159,13 @@ Convert_CompPolynomialToPoles::Convert_CompPolynomialToPoles(
NCollection_Array1<int> NumCoeffPerCurve(1, 1);
NumCoeffPerCurve(1) = Degree + 1;
myKnots = new NCollection_HArray1<double>(1, 2);
myKnots->ChangeArray1().SetValue(1, TrueIntervals.Value(TrueIntervals.Lower()));
myKnots->ChangeArray1().SetValue(2, TrueIntervals.Value(TrueIntervals.Lower() + 1));
myKnots = NCollection_Array1<double>(1, 2);
myKnots.SetValue(1, TrueIntervals.Value(TrueIntervals.Lower()));
myKnots.SetValue(2, TrueIntervals.Value(TrueIntervals.Lower() + 1));
myMults = new NCollection_HArray1<int>(1, 2);
myMults->Init(myDegree + 1);
myMults = NCollection_Array1<int>(1, 2);
myMults.Init(myDegree + 1);
// Calculs
Perform(1,
MaxDegree,
Dimension,
@@ -202,26 +188,22 @@ void Convert_CompPolynomialToPoles::Perform(const int Nu
double normalized_value, *coefficient_array, *poles_array;
num_flat_knots = 2 * myDegree + 2;
for (ii = 2; ii < myMults->Length(); ii++)
for (ii = 2; ii < myMults.Length(); ii++)
{
num_flat_knots += myMults->Value(ii);
num_flat_knots += myMults.Value(ii);
}
num_poles = num_flat_knots - myDegree - 1;
myFlatKnots = new NCollection_HArray1<double>(1, num_flat_knots);
BSplCLib::KnotSequence(myKnots->Array1(),
myMults->Array1(),
myDegree,
false,
myFlatKnots->ChangeArray1());
myFlatKnots = NCollection_Array1<double>(1, num_flat_knots);
BSplCLib::KnotSequence(myKnots, myMults, myDegree, false, myFlatKnots);
NCollection_Array1<double> parameters(1, num_poles);
BSplCLib::BuildSchoenbergPoints(myDegree, myFlatKnots->Array1(), parameters);
myPoles = new NCollection_HArray2<double>(1, num_poles, 1, Dimension);
BSplCLib::BuildSchoenbergPoints(myDegree, myFlatKnots, parameters);
myPoles = NCollection_Array2<double>(1, num_poles, 1, Dimension);
index = 2;
Tindex = TrueIntervals.Lower() + 1;
Pindex = PolynomialIntervals.LowerRow();
poles_array = (double*)&(myPoles->ChangeArray2()).Value(1, 1);
poles_array = (double*)&myPoles.ChangeValue(1, 1);
NCollection_Array1<int> contact_array(1, num_poles);
@@ -262,7 +244,7 @@ void Convert_CompPolynomialToPoles::Perform(const int Nu
// result
//
BSplCLib::Interpolate(myDegree,
myFlatKnots->Array1(),
myFlatKnots,
parameters,
contact_array,
Dimension,
@@ -275,68 +257,94 @@ void Convert_CompPolynomialToPoles::Perform(const int Nu
myDone = true;
}
//=================================================================================================
//==================================================================================================
int Convert_CompPolynomialToPoles::NbPoles() const
{
if (myDone)
{
return myPoles->ColLength();
return myPoles.ColLength();
}
else
return 0;
return 0;
}
//=================================================================================================
//==================================================================================================
void Convert_CompPolynomialToPoles::Poles(occ::handle<NCollection_HArray2<double>>& P) const
const NCollection_Array2<double>& Convert_CompPolynomialToPoles::Poles() const
{
StdFail_NotDone_Raise_if(!myDone, "Convert_CompPolynomialToPoles::Poles");
return myPoles;
}
//==================================================================================================
Standard_DISABLE_DEPRECATION_WARNINGS void Convert_CompPolynomialToPoles::Poles(
occ::handle<NCollection_HArray2<double>>& P) const
{
if (myDone)
{
P = myPoles;
P = new NCollection_HArray2<double>(myPoles);
}
}
//=================================================================================================
//==================================================================================================
int Convert_CompPolynomialToPoles::NbKnots() const
{
if (myDone)
{
return myKnots->Length();
return myKnots.Length();
}
else
return 0;
return 0;
}
//=================================================================================================
//==================================================================================================
const NCollection_Array1<double>& Convert_CompPolynomialToPoles::Knots() const
{
StdFail_NotDone_Raise_if(!myDone, "Convert_CompPolynomialToPoles::Knots");
return myKnots;
}
//==================================================================================================
void Convert_CompPolynomialToPoles::Knots(occ::handle<NCollection_HArray1<double>>& K) const
{
if (myDone)
{
K = myKnots;
K = new NCollection_HArray1<double>(myKnots);
}
}
//=================================================================================================
//==================================================================================================
const NCollection_Array1<int>& Convert_CompPolynomialToPoles::Multiplicities() const
{
StdFail_NotDone_Raise_if(!myDone, "Convert_CompPolynomialToPoles::Multiplicities");
return myMults;
}
//==================================================================================================
void Convert_CompPolynomialToPoles::Multiplicities(occ::handle<NCollection_HArray1<int>>& M) const
{
if (myDone)
{
M = myMults;
M = new NCollection_HArray1<int>(myMults);
}
}
//=================================================================================================
Standard_ENABLE_DEPRECATION_WARNINGS
bool Convert_CompPolynomialToPoles::IsDone() const
//==================================================================================================
bool
Convert_CompPolynomialToPoles::IsDone() const
{
return myDone;
}
//=================================================================================================
//==================================================================================================
int Convert_CompPolynomialToPoles::Degree() const
{
@@ -20,10 +20,10 @@
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
#include <Standard_Macro.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
#include <Standard_Integer.hxx>
#include <NCollection_Array2.hxx>
#include <NCollection_HArray2.hxx>
@@ -109,26 +109,40 @@ public:
const NCollection_Array1<double>& PolynomialIntervals,
const NCollection_Array1<double>& TrueIntervals);
//! number of poles of the n-dimensional BSpline
Standard_EXPORT int NbPoles() const;
//! Returns the number of poles of the n-dimensional BSpline.
[[nodiscard]] Standard_EXPORT int NbPoles() const;
//! returns the poles of the n-dimensional BSpline
//! in the following format :
//! Returns the poles of the n-dimensional BSpline
//! in the following format:
//! [1..NumPoles][1..Dimension]
Standard_EXPORT void Poles(occ::handle<NCollection_HArray2<double>>& Poles) const;
[[nodiscard]] Standard_EXPORT const NCollection_Array2<double>& Poles() const;
Standard_EXPORT int Degree() const;
//! Returns the poles of the n-dimensional BSpline via output parameter.
Standard_DEPRECATED("Use Poles() returning const reference instead")
Standard_EXPORT void Poles(occ::handle<NCollection_HArray2<double>>& thePoles) const;
//! Degree of the n-dimensional Bspline
Standard_EXPORT int NbKnots() const;
//! Returns the degree of the n-dimensional BSpline.
[[nodiscard]] Standard_EXPORT int Degree() const;
//! Knots of the n-dimensional Bspline
Standard_EXPORT void Knots(occ::handle<NCollection_HArray1<double>>& K) const;
//! Returns the number of knots of the n-dimensional BSpline.
[[nodiscard]] Standard_EXPORT int NbKnots() const;
//! Multiplicities of the knots in the BSpline
Standard_EXPORT void Multiplicities(occ::handle<NCollection_HArray1<int>>& M) const;
//! Returns the knots of the n-dimensional BSpline.
[[nodiscard]] Standard_EXPORT const NCollection_Array1<double>& Knots() const;
Standard_EXPORT bool IsDone() const;
//! Returns the knots of the n-dimensional BSpline via output parameter.
Standard_DEPRECATED("Use Knots() returning const reference instead")
Standard_EXPORT void Knots(occ::handle<NCollection_HArray1<double>>& theKnots) const;
//! Returns the multiplicities of the knots in the BSpline.
[[nodiscard]] Standard_EXPORT const NCollection_Array1<int>& Multiplicities() const;
//! Returns the multiplicities of the knots via output parameter.
Standard_DEPRECATED("Use Multiplicities() returning const reference instead")
Standard_EXPORT void Multiplicities(occ::handle<NCollection_HArray1<int>>& theMults) const;
//! Returns true if the conversion was successful.
[[nodiscard]] Standard_EXPORT bool IsDone() const;
private:
Standard_EXPORT void Perform(const int NumCurves,
@@ -139,12 +153,12 @@ private:
const NCollection_Array2<double>& PolynomialIntervals,
const NCollection_Array1<double>& TrueIntervals);
occ::handle<NCollection_HArray1<double>> myFlatKnots;
occ::handle<NCollection_HArray1<double>> myKnots;
occ::handle<NCollection_HArray1<int>> myMults;
occ::handle<NCollection_HArray2<double>> myPoles;
int myDegree;
bool myDone;
NCollection_Array1<double> myFlatKnots;
NCollection_Array1<double> myKnots;
NCollection_Array1<int> myMults;
NCollection_Array2<double> myPoles;
int myDegree;
bool myDone;
};
#endif // _Convert_CompPolynomialToPoles_HeaderFile
@@ -20,6 +20,8 @@
#include <gp_Trsf.hxx>
#include <Standard_DomainError.hxx>
#include <array>
namespace
{
constexpr int TheUDegree = 2;
@@ -46,8 +48,8 @@ static void ComputePoles(const double R,
int nbUSpans = (int)std::trunc(1.2 * deltaU / M_PI) + 1;
double AlfaU = deltaU / (nbUSpans * 2);
double x[TheNbVPoles];
double z[TheNbVPoles];
std::array<double, TheNbVPoles> x;
std::array<double, TheNbVPoles> z;
x[0] = R + V1 * std::sin(A);
z[0] = V1 * std::cos(A);
@@ -93,8 +95,8 @@ Convert_ConeToBSplineSurface::Convert_ConeToBSplineSurface(const gp_Cone& C,
|| (deltaU < 0.),
"Convert_ConeToBSplineSurface");
isuperiodic = false;
isvperiodic = false;
myIsUPeriodic = false;
myIsVPeriodic = false;
int i, j;
// construction of cone in the reference mark xOy.
@@ -103,28 +105,28 @@ Convert_ConeToBSplineSurface::Convert_ConeToBSplineSurface(const gp_Cone& C,
int nbUSpans = (int)std::trunc(1.2 * deltaU / M_PI) + 1;
double AlfaU = deltaU / (nbUSpans * 2);
nbUPoles = 2 * nbUSpans + 1;
nbUKnots = nbUSpans + 1;
myNbUPoles = 2 * nbUSpans + 1;
myNbUKnots = nbUSpans + 1;
nbVPoles = 2;
nbVKnots = 2;
myNbVPoles = 2;
myNbVKnots = 2;
double R = C.RefRadius();
double A = C.SemiAngle();
ComputePoles(R, A, U1, U2, V1, V2, poles);
ComputePoles(R, A, U1, U2, V1, V2, myPoles);
for (i = 1; i <= nbUKnots; i++)
for (i = 1; i <= myNbUKnots; i++)
{
uknots(i) = U1 + (i - 1) * 2 * AlfaU;
umults(i) = 2;
myUKnots(i) = U1 + (i - 1) * 2 * AlfaU;
myUMults(i) = 2;
}
umults(1)++;
umults(nbUKnots)++;
vknots(1) = V1;
vmults(1) = 2;
vknots(2) = V2;
vmults(2) = 2;
myUMults(1)++;
myUMults(myNbUKnots)++;
myVKnots(1) = V1;
myVMults(1) = 2;
myVKnots(2) = V2;
myVMults(2) = 2;
// Replace the bspline in the mark of the sphere.
// and calculate the weight of the bspline.
@@ -132,19 +134,20 @@ Convert_ConeToBSplineSurface::Convert_ConeToBSplineSurface(const gp_Cone& C,
gp_Trsf Trsf;
Trsf.SetTransformation(C.Position(), gp::XOY());
for (i = 1; i <= nbUPoles; i++)
for (i = 1; i <= myNbUPoles; i++)
{
if (i % 2 == 0)
W1 = std::cos(AlfaU);
else
W1 = 1.;
for (j = 1; j <= nbVPoles; j++)
for (j = 1; j <= myNbVPoles; j++)
{
weights(i, j) = W1;
poles(i, j).Transform(Trsf);
myWeights(i, j) = W1;
myPoles(i, j).Transform(Trsf);
}
}
Finalize();
}
//=================================================================================================
@@ -164,30 +167,30 @@ Convert_ConeToBSplineSurface::Convert_ConeToBSplineSurface(const gp_Cone& C,
int i, j;
isuperiodic = true;
isvperiodic = false;
myIsUPeriodic = true;
myIsVPeriodic = false;
// construction of the cone in the reference mark xOy.
double R = C.RefRadius();
double A = C.SemiAngle();
ComputePoles(R, A, 0., 2. * M_PI, V1, V2, poles);
ComputePoles(R, A, 0., 2. * M_PI, V1, V2, myPoles);
nbUPoles = 6;
nbUKnots = 4;
nbVPoles = 2;
nbVKnots = 2;
myNbUPoles = 6;
myNbUKnots = 4;
myNbVPoles = 2;
myNbVKnots = 2;
for (i = 1; i <= nbUKnots; i++)
for (i = 1; i <= myNbUKnots; i++)
{
uknots(i) = (i - 1) * 2. * M_PI / 3.;
umults(i) = 2;
myUKnots(i) = (i - 1) * 2. * M_PI / 3.;
myUMults(i) = 2;
}
vknots(1) = V1;
vmults(1) = 2;
vknots(2) = V2;
vmults(2) = 2;
myVKnots(1) = V1;
myVMults(1) = 2;
myVKnots(2) = V2;
myVMults(2) = 2;
// replace bspline in the mark of the cone.
// and calculate the weight of bspline.
@@ -195,17 +198,18 @@ Convert_ConeToBSplineSurface::Convert_ConeToBSplineSurface(const gp_Cone& C,
gp_Trsf Trsf;
Trsf.SetTransformation(C.Position(), gp::XOY());
for (i = 1; i <= nbUPoles; i++)
for (i = 1; i <= myNbUPoles; i++)
{
if (i % 2 == 0)
W = 0.5; // = std::cos(pi /3)
else
W = 1.;
for (j = 1; j <= nbVPoles; j++)
for (j = 1; j <= myNbVPoles; j++)
{
weights(i, j) = W;
poles(i, j).Transform(Trsf);
myWeights(i, j) = W;
myPoles(i, j).Transform(Trsf);
}
}
Finalize();
}
@@ -14,107 +14,196 @@
// JCV 16/10/91
#define No_Standard_OutOfRange
#include <BSplCLib.hxx>
#include <Convert_ConicToBSplineCurve.hxx>
#include <Convert_CosAndSinEvalFunction.hxx>
#include <Convert_PolynomialCosAndSin.hxx>
#include <gp_Pnt2d.hxx>
#include <PLib.hxx>
#include <Standard_ConstructionError.hxx>
#include <Standard_OutOfRange.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
#include <PLib.hxx>
#include <Standard_ConstructionError.hxx>
#include <Standard_Integer.hxx>
#include <Standard_OutOfRange.hxx>
//=================================================================================================
Convert_ConicToBSplineCurve::Convert_ConicToBSplineCurve(const int NbPoles,
const int NbKnots,
const int Degree)
: degree(Degree),
nbPoles(NbPoles),
nbKnots(NbKnots),
isperiodic(false)
//==================================================================================================
Convert_ConicToBSplineCurve::Convert_ConicToBSplineCurve(const int theNumberOfPoles,
const int theNumberOfKnots,
const int theDegree)
: myDegree(theDegree)
{
if (NbPoles >= 2)
if (theNumberOfPoles >= 2)
{
poles = new NCollection_HArray1<gp_Pnt2d>(1, NbPoles);
weights = new NCollection_HArray1<double>(1, NbPoles);
myPoles = NCollection_Array1<gp_Pnt2d>(1, theNumberOfPoles);
myWeights = NCollection_Array1<double>(1, theNumberOfPoles);
}
if (NbKnots >= 2)
if (theNumberOfKnots >= 2)
{
knots = new NCollection_HArray1<double>(1, NbKnots);
mults = new NCollection_HArray1<int>(1, NbKnots);
myKnots = NCollection_Array1<double>(1, theNumberOfKnots);
myMults = NCollection_Array1<int>(1, theNumberOfKnots);
}
}
//=================================================================================================
//==================================================================================================
int Convert_ConicToBSplineCurve::Degree() const
{
return degree;
return myDegree;
}
//=================================================================================================
//==================================================================================================
int Convert_ConicToBSplineCurve::NbPoles() const
{
return nbPoles;
return myPoles.Length();
}
//=================================================================================================
//==================================================================================================
int Convert_ConicToBSplineCurve::NbKnots() const
{
return nbKnots;
return myKnots.Length();
}
//=================================================================================================
//==================================================================================================
bool Convert_ConicToBSplineCurve::IsPeriodic() const
{
return isperiodic;
return myIsPeriodic;
}
//=================================================================================================
//==================================================================================================
gp_Pnt2d Convert_ConicToBSplineCurve::Pole(const int Index) const
Standard_DISABLE_DEPRECATION_WARNINGS gp_Pnt2d
Convert_ConicToBSplineCurve::Pole(const int theIndex) const
{
if (Index < 1 || Index > nbPoles)
throw Standard_OutOfRange(" ");
return poles->Value(Index);
if (theIndex < 1 || theIndex > myPoles.Length())
throw Standard_OutOfRange("Convert_ConicToBSplineCurve::Pole: Index out of range");
return myPoles(theIndex);
}
//=================================================================================================
//==================================================================================================
double Convert_ConicToBSplineCurve::Weight(const int Index) const
double Convert_ConicToBSplineCurve::Weight(const int theIndex) const
{
if (Index < 1 || Index > nbPoles)
throw Standard_OutOfRange(" ");
return weights->Value(Index);
if (theIndex < 1 || theIndex > myPoles.Length())
throw Standard_OutOfRange("Convert_ConicToBSplineCurve::Weight: Index out of range");
return myWeights(theIndex);
}
//=================================================================================================
//==================================================================================================
double Convert_ConicToBSplineCurve::Knot(const int Index) const
double Convert_ConicToBSplineCurve::Knot(const int theIndex) const
{
if (Index < 1 || Index > nbKnots)
throw Standard_OutOfRange(" ");
return knots->Value(Index);
if (theIndex < 1 || theIndex > myKnots.Length())
throw Standard_OutOfRange("Convert_ConicToBSplineCurve::Knot: Index out of range");
return myKnots(theIndex);
}
//=================================================================================================
//==================================================================================================
int Convert_ConicToBSplineCurve::Multiplicity(const int Index) const
int Convert_ConicToBSplineCurve::Multiplicity(const int theIndex) const
{
if (Index < 1 || Index > nbKnots)
throw Standard_OutOfRange(" ");
return mults->Value(Index);
if (theIndex < 1 || theIndex > myKnots.Length())
throw Standard_OutOfRange("Convert_ConicToBSplineCurve::Multiplicity: Index out of range");
return myMults(theIndex);
}
Standard_ENABLE_DEPRECATION_WARNINGS
//==================================================================================================
const NCollection_Array1<gp_Pnt2d>&
Convert_ConicToBSplineCurve::Poles() const
{
return myPoles;
}
//==================================================================================================
const NCollection_Array1<double>& Convert_ConicToBSplineCurve::Weights() const
{
return myWeights;
}
//==================================================================================================
const NCollection_Array1<double>& Convert_ConicToBSplineCurve::Knots() const
{
return myKnots;
}
//==================================================================================================
const NCollection_Array1<int>& Convert_ConicToBSplineCurve::Multiplicities() const
{
return myMults;
}
//==================================================================================================
void Convert_ConicToBSplineCurve::BuildCosAndSin(
const Convert_ParameterisationType theParametrisation,
occ::handle<NCollection_HArray1<double>>& theCosNumerator,
occ::handle<NCollection_HArray1<double>>& theSinNumerator,
occ::handle<NCollection_HArray1<double>>& theDenominator,
int& theDegree,
occ::handle<NCollection_HArray1<double>>& theKnots,
occ::handle<NCollection_HArray1<int>>& theMults) const
{
NCollection_Array1<double> aCosNumerator;
NCollection_Array1<double> aSinNumerator;
NCollection_Array1<double> aDenominator;
NCollection_Array1<double> aKnots;
NCollection_Array1<int> aMults;
BuildCosAndSin(theParametrisation,
aCosNumerator,
aSinNumerator,
aDenominator,
theDegree,
aKnots,
aMults);
theCosNumerator = new NCollection_HArray1<double>(aCosNumerator);
theSinNumerator = new NCollection_HArray1<double>(aSinNumerator);
theDenominator = new NCollection_HArray1<double>(aDenominator);
theKnots = new NCollection_HArray1<double>(aKnots);
theMults = new NCollection_HArray1<int>(aMults);
}
//==================================================================================================
void Convert_ConicToBSplineCurve::BuildCosAndSin(
const Convert_ParameterisationType theParametrisation,
const double theUFirst,
const double theULast,
occ::handle<NCollection_HArray1<double>>& theCosNumerator,
occ::handle<NCollection_HArray1<double>>& theSinNumerator,
occ::handle<NCollection_HArray1<double>>& theDenominator,
int& theDegree,
occ::handle<NCollection_HArray1<double>>& theKnots,
occ::handle<NCollection_HArray1<int>>& theMults) const
{
NCollection_Array1<double> aCosNumerator;
NCollection_Array1<double> aSinNumerator;
NCollection_Array1<double> aDenominator;
NCollection_Array1<double> aKnots;
NCollection_Array1<int> aMults;
BuildCosAndSin(theParametrisation,
theUFirst,
theULast,
aCosNumerator,
aSinNumerator,
aDenominator,
theDegree,
aKnots,
aMults);
theCosNumerator = new NCollection_HArray1<double>(aCosNumerator);
theSinNumerator = new NCollection_HArray1<double>(aSinNumerator);
theDenominator = new NCollection_HArray1<double>(aDenominator);
theKnots = new NCollection_HArray1<double>(aKnots);
theMults = new NCollection_HArray1<int>(aMults);
}
//=======================================================================
@@ -126,7 +215,6 @@ int Convert_ConicToBSplineCurve::Multiplicity(const int Index) const
// 2 2
// U + V
//
// 2 * U*V
// sin (theta(t)) = ----------
// 2 2
@@ -136,12 +224,12 @@ int Convert_ConicToBSplineCurve::Multiplicity(const int Index) const
// with is helpful when having to make a C1 BSpline by merging two BSpline together
//=======================================================================
void CosAndSinRationalC1(double Parameter,
const int EvalDegree,
const NCollection_Array1<gp_Pnt2d>& EvalPoles,
const NCollection_Array1<double>& EvalKnots,
const NCollection_Array1<int>* EvalMults,
double Result[2])
static void CosAndSinRationalC1(double Parameter,
const int EvalDegree,
const NCollection_Array1<gp_Pnt2d>& EvalPoles,
const NCollection_Array1<double>& EvalKnots,
const NCollection_Array1<int>* EvalMults,
double Result[2])
{
gp_Pnt2d a_point;
BSplCLib::D0(Parameter,
@@ -166,50 +254,57 @@ void CosAndSinRationalC1(double Parameter,
// 2 2
// U + V
//
// 2 * U*V
// sin (theta(t)) = ----------
// 2 2
// U + V
//=======================================================================
void CosAndSinQuasiAngular(double Parameter,
const int EvalDegree,
const NCollection_Array1<gp_Pnt2d>& EvalPoles,
// const NCollection_Array1<double>& EvalKnots,
const NCollection_Array1<double>&,
// const NCollection_Array1<int>& EvalMults,
const NCollection_Array1<int>*,
double Result[2])
static void CosAndSinQuasiAngular(double Parameter,
const int EvalDegree,
const NCollection_Array1<gp_Pnt2d>& EvalPoles,
const NCollection_Array1<double>&,
const NCollection_Array1<int>*,
double Result[2])
{
double param, *coeff;
coeff = (double*)&EvalPoles(EvalPoles.Lower());
// Extract X,Y coordinates from all EvalPoles into a flat double array
// to safely pass to PLib::NoDerivativeEvalPolynomial.
Standard_OutOfRange_Raise_if(EvalPoles.Length() != EvalDegree + 1,
"CosAndSinQuasiAngular: EvalPoles size mismatch");
const int aNumCoords = (EvalDegree + 1) * 2;
NCollection_Array1<double> aCoeffs(0, aNumCoords - 1);
for (int i = EvalPoles.Lower(); i <= EvalPoles.Upper(); i++)
{
const int anIdx = (i - EvalPoles.Lower()) * 2;
aCoeffs(anIdx) = EvalPoles(i).X();
aCoeffs(anIdx + 1) = EvalPoles(i).Y();
}
//
// rational_function_coeff represent a rational approximation
// of U ---> cotan( PI * U /2) between [0 1]
// rational_function_coeff[i][0] is the denominator
// rational_function_coeff[i][1] is the numerator
//
param = Parameter * 0.5e0;
PLib::NoDerivativeEvalPolynomial(param, EvalDegree, 2, EvalDegree << 1, coeff[0], Result[0]);
const double param = Parameter * 0.5e0;
PLib::NoDerivativeEvalPolynomial(param, EvalDegree, 2, EvalDegree << 1, aCoeffs(0), Result[0]);
}
//=======================================================================
// function : function that build the Bspline Representation of
// an algorithmic description of the function cos and sin
// purpose :
// function : AlgorithmicCosAndSin
// purpose : Build the Bspline representation of
// an algorithmic description of the function cos and sin
//=======================================================================
void AlgorithmicCosAndSin(int Degree,
const NCollection_Array1<double>& FlatKnots,
const int EvalDegree,
const NCollection_Array1<gp_Pnt2d>& EvalPoles,
const NCollection_Array1<double>& EvalKnots,
const NCollection_Array1<int>* EvalMults,
Convert_CosAndSinEvalFunction Evaluator,
NCollection_Array1<double>& CosNumerator,
NCollection_Array1<double>& SinNumerator,
NCollection_Array1<double>& Denominator)
static void AlgorithmicCosAndSin(int Degree,
const NCollection_Array1<double>& FlatKnots,
const int EvalDegree,
const NCollection_Array1<gp_Pnt2d>& EvalPoles,
const NCollection_Array1<double>& EvalKnots,
const NCollection_Array1<int>* EvalMults,
Convert_CosAndSinEvalFunction Evaluator,
NCollection_Array1<double>& CosNumerator,
NCollection_Array1<double>& SinNumerator,
NCollection_Array1<double>& Denominator)
{
int order, num_poles, pivot_index_problem, ii;
@@ -251,18 +346,18 @@ void AlgorithmicCosAndSin(int Degree,
}
}
//=================================================================================================
//==================================================================================================
void Convert_ConicToBSplineCurve::BuildCosAndSin(
const Convert_ParameterisationType Parameterisation,
const double UFirst,
const double ULast,
occ::handle<NCollection_HArray1<double>>& CosNumeratorPtr,
occ::handle<NCollection_HArray1<double>>& SinNumeratorPtr,
occ::handle<NCollection_HArray1<double>>& DenominatorPtr,
int& Degree,
occ::handle<NCollection_HArray1<double>>& KnotsPtr,
occ::handle<NCollection_HArray1<int>>& MultsPtr) const
const Convert_ParameterisationType Parameterisation,
const double UFirst,
const double ULast,
NCollection_Array1<double>& CosNumerator,
NCollection_Array1<double>& SinNumerator,
NCollection_Array1<double>& Denominator,
int& Degree,
NCollection_Array1<double>& Knots,
NCollection_Array1<int>& Mults) const
{
double delta = ULast - UFirst, direct, inverse, value1, value2, cos_beta, sin_beta, alpha = 0,
alpha_2, alpha_4, tan_alpha_2, beta, p_param, q_param, param;
@@ -336,35 +431,35 @@ void Convert_ConicToBSplineCurve::BuildCosAndSin(
num_poles = 2 * num_spans + 1;
}
CosNumeratorPtr = new NCollection_HArray1<double>(1, num_poles);
SinNumeratorPtr = new NCollection_HArray1<double>(1, num_poles);
DenominatorPtr = new NCollection_HArray1<double>(1, num_poles);
KnotsPtr = new NCollection_HArray1<double>(1, num_spans + 1);
MultsPtr = new NCollection_HArray1<int>(1, num_spans + 1);
CosNumerator = NCollection_Array1<double>(1, num_poles);
SinNumerator = NCollection_Array1<double>(1, num_poles);
Denominator = NCollection_Array1<double>(1, num_poles);
Knots = NCollection_Array1<double>(1, num_spans + 1);
Mults = NCollection_Array1<int>(1, num_spans + 1);
if (tgt_theta_flag)
{
param = UFirst;
CosNumeratorPtr->SetValue(1, std::cos(UFirst));
SinNumeratorPtr->SetValue(1, std::sin(UFirst));
DenominatorPtr->SetValue(1, 1.0e0);
KnotsPtr->SetValue(1, param);
MultsPtr->SetValue(1, Degree + 1);
direct = std::cos(alpha);
inverse = 1.0e0 / direct;
param = UFirst;
CosNumerator(1) = std::cos(UFirst);
SinNumerator(1) = std::sin(UFirst);
Denominator(1) = 1.0e0;
Knots(1) = param;
Mults(1) = Degree + 1;
direct = std::cos(alpha);
inverse = 1.0e0 / direct;
for (ii = 1; ii <= num_spans; ii++)
{
CosNumeratorPtr->SetValue(2 * ii, inverse * std::cos(param + alpha));
SinNumeratorPtr->SetValue(2 * ii, inverse * std::sin(param + alpha));
DenominatorPtr->SetValue(2 * ii, direct);
CosNumeratorPtr->SetValue(2 * ii + 1, std::cos(param + 2 * alpha));
SinNumeratorPtr->SetValue(2 * ii + 1, std::sin(param + 2 * alpha));
DenominatorPtr->SetValue(2 * ii + 1, 1.0e0);
KnotsPtr->SetValue(ii + 1, param + 2 * alpha);
MultsPtr->SetValue(ii + 1, 2);
CosNumerator(2 * ii) = inverse * std::cos(param + alpha);
SinNumerator(2 * ii) = inverse * std::sin(param + alpha);
Denominator(2 * ii) = direct;
CosNumerator(2 * ii + 1) = std::cos(param + 2 * alpha);
SinNumerator(2 * ii + 1) = std::sin(param + 2 * alpha);
Denominator(2 * ii + 1) = 1.0e0;
Knots(ii + 1) = param + 2 * alpha;
Mults(ii + 1) = 2;
param += 2 * alpha;
}
MultsPtr->SetValue(num_spans + 1, Degree + 1);
Mults(num_spans + 1) = Degree + 1;
}
else if (Parameterisation != Convert_Polynomial)
{
@@ -389,10 +484,10 @@ void Convert_ConicToBSplineCurve::BuildCosAndSin(
flat_knots(ii) = -alpha;
flat_knots(ii + num_poles) = alpha;
}
KnotsPtr->SetValue(1, UFirst);
KnotsPtr->SetValue(num_knots, ULast);
MultsPtr->SetValue(1, order);
MultsPtr->SetValue(num_knots, order);
Knots(1) = UFirst;
Knots(num_knots) = ULast;
Mults(1) = order;
Mults(num_knots) = order;
switch (Parameterisation)
{
@@ -458,8 +553,8 @@ void Convert_ConicToBSplineCurve::BuildCosAndSin(
{
flat_knots(ii) = 0.0e0;
}
KnotsPtr->SetValue(2, UFirst + alpha);
MultsPtr->SetValue(2, Degree - 1);
Knots(2) = UFirst + alpha;
Mults(2) = Degree - 1;
temp_degree = 2;
alpha_2 = alpha * 0.5e0;
alpha_4 = alpha * 0.25e0;
@@ -494,49 +589,42 @@ void Convert_ConicToBSplineCurve::BuildCosAndSin(
temp_knots,
&temp_mults,
*EvaluatorPtr,
CosNumeratorPtr->ChangeArray1(),
SinNumeratorPtr->ChangeArray1(),
DenominatorPtr->ChangeArray1());
CosNumerator,
SinNumerator,
Denominator);
for (ii = 1; ii <= num_poles; ii++)
{
value1 = cos_beta * CosNumeratorPtr->Value(ii) - sin_beta * SinNumeratorPtr->Value(ii);
value2 = sin_beta * CosNumeratorPtr->Value(ii) + cos_beta * SinNumeratorPtr->Value(ii);
CosNumeratorPtr->SetValue(ii, value1);
SinNumeratorPtr->SetValue(ii, value2);
value1 = cos_beta * CosNumerator(ii) - sin_beta * SinNumerator(ii);
value2 = sin_beta * CosNumerator(ii) + cos_beta * SinNumerator(ii);
CosNumerator(ii) = value1;
SinNumerator(ii) = value2;
}
}
else
{ // Convert_Polynomial
KnotsPtr->SetValue(1, 0.);
KnotsPtr->SetValue(num_knots, 1.);
MultsPtr->SetValue(1, num_poles);
MultsPtr->SetValue(num_knots, num_poles);
Knots(1) = 0.;
Knots(num_knots) = 1.;
Mults(1) = num_poles;
Mults(num_knots) = num_poles;
BuildPolynomialCosAndSin(UFirst,
ULast,
num_poles,
CosNumeratorPtr,
SinNumeratorPtr,
DenominatorPtr);
BuildPolynomialCosAndSin(UFirst, ULast, num_poles, CosNumerator, SinNumerator, Denominator);
}
}
//=================================================================================================
//==================================================================================================
void Convert_ConicToBSplineCurve::BuildCosAndSin(
const Convert_ParameterisationType Parameterisation,
occ::handle<NCollection_HArray1<double>>& CosNumeratorPtr,
occ::handle<NCollection_HArray1<double>>& SinNumeratorPtr,
occ::handle<NCollection_HArray1<double>>& DenominatorPtr,
int& Degree,
occ::handle<NCollection_HArray1<double>>& KnotsPtr,
occ::handle<NCollection_HArray1<int>>& MultsPtr) const
const Convert_ParameterisationType Parameterisation,
NCollection_Array1<double>& CosNumerator,
NCollection_Array1<double>& SinNumerator,
NCollection_Array1<double>& Denominator,
int& Degree,
NCollection_Array1<double>& Knots,
NCollection_Array1<int>& Mults) const
{
double half_pi, param, first_param, last_param,
// direct,
inverse, value1, value2, value3;
double half_pi, param, first_param, last_param, inverse, value1, value2, value3;
int ii, jj, index, num_poles, num_periodic_poles, temp_degree, pivot_index_problem,
num_flat_knots, num_knots;
@@ -545,32 +633,31 @@ void Convert_ConicToBSplineCurve::BuildCosAndSin(
{
throw Standard_ConstructionError();
}
occ::handle<NCollection_HArray1<double>> temp_cos_ptr, temp_sin_ptr, temp_denominator_ptr,
temp_knots_ptr;
occ::handle<NCollection_HArray1<int>> temp_mults_ptr;
NCollection_Array1<double> temp_cos, temp_sin, temp_denominator, temp_knots;
NCollection_Array1<int> temp_mults;
if (Parameterisation == Convert_TgtThetaOver2)
{
BuildCosAndSin(Convert_TgtThetaOver2_3,
0.0e0,
2 * M_PI,
temp_cos_ptr,
temp_sin_ptr,
temp_denominator_ptr,
temp_cos,
temp_sin,
temp_denominator,
Degree,
KnotsPtr,
MultsPtr);
CosNumeratorPtr = new NCollection_HArray1<double>(1, temp_cos_ptr->Length() - 1);
SinNumeratorPtr = new NCollection_HArray1<double>(1, temp_cos_ptr->Length() - 1);
DenominatorPtr = new NCollection_HArray1<double>(1, temp_cos_ptr->Length() - 1);
for (ii = temp_cos_ptr->Lower(); ii <= temp_cos_ptr->Upper() - 1; ii++)
Knots,
Mults);
CosNumerator = NCollection_Array1<double>(1, temp_cos.Length() - 1);
SinNumerator = NCollection_Array1<double>(1, temp_cos.Length() - 1);
Denominator = NCollection_Array1<double>(1, temp_cos.Length() - 1);
for (ii = temp_cos.Lower(); ii <= temp_cos.Upper() - 1; ii++)
{
CosNumeratorPtr->SetValue(ii, temp_cos_ptr->Value(ii));
SinNumeratorPtr->SetValue(ii, temp_sin_ptr->Value(ii));
DenominatorPtr->SetValue(ii, temp_denominator_ptr->Value(ii));
CosNumerator(ii) = temp_cos(ii);
SinNumerator(ii) = temp_sin(ii);
Denominator(ii) = temp_denominator(ii);
}
for (ii = MultsPtr->Lower(); ii <= MultsPtr->Upper(); ii++)
for (ii = Mults.Lower(); ii <= Mults.Upper(); ii++)
{
MultsPtr->SetValue(ii, Degree);
Mults(ii) = Degree;
}
}
else if (Parameterisation == Convert_RationalC1)
@@ -580,12 +667,12 @@ void Convert_ConicToBSplineCurve::BuildCosAndSin(
BuildCosAndSin(Convert_RationalC1,
first_param,
last_param,
temp_cos_ptr,
temp_sin_ptr,
temp_denominator_ptr,
temp_cos,
temp_sin,
temp_denominator,
temp_degree,
temp_knots_ptr,
temp_mults_ptr);
temp_knots,
temp_mults);
Degree = 4;
num_knots = 5;
@@ -593,9 +680,9 @@ void Convert_ConicToBSplineCurve::BuildCosAndSin(
num_poles = num_flat_knots - Degree - 1;
num_periodic_poles = num_poles - 2;
NCollection_Array1<double> flat_knots(1, num_flat_knots);
CosNumeratorPtr = new NCollection_HArray1<double>(1, num_periodic_poles);
SinNumeratorPtr = new NCollection_HArray1<double>(1, num_periodic_poles);
DenominatorPtr = new NCollection_HArray1<double>(1, num_periodic_poles);
CosNumerator = NCollection_Array1<double>(1, num_periodic_poles);
SinNumerator = NCollection_Array1<double>(1, num_periodic_poles);
Denominator = NCollection_Array1<double>(1, num_periodic_poles);
half_pi = M_PI * 0.5e0;
index = 1;
@@ -618,12 +705,12 @@ void Convert_ConicToBSplineCurve::BuildCosAndSin(
flat_knots(index) = 2 * M_PI + half_pi;
index += 1;
}
KnotsPtr = new NCollection_HArray1<double>(1, num_knots);
MultsPtr = new NCollection_HArray1<int>(1, num_knots);
Knots = NCollection_Array1<double>(1, num_knots);
Mults = NCollection_Array1<int>(1, num_knots);
for (ii = 1; ii <= num_knots; ii++)
{
KnotsPtr->SetValue(ii, (ii - 1) * half_pi);
MultsPtr->SetValue(ii, Degree - 1);
Knots(ii) = (ii - 1) * half_pi;
Mults(ii) = Degree - 1;
}
NCollection_Array1<double> parameters(1, num_poles);
@@ -643,29 +730,29 @@ void Convert_ConicToBSplineCurve::BuildCosAndSin(
0,
temp_degree,
false,
temp_cos_ptr->Array1(),
&temp_denominator_ptr->Array1(),
temp_knots_ptr->Array1(),
&temp_mults_ptr->Array1(),
temp_cos,
&temp_denominator,
temp_knots,
&temp_mults,
value1);
BSplCLib::D0(param,
0,
temp_degree,
false,
temp_sin_ptr->Array1(),
&temp_denominator_ptr->Array1(),
temp_knots_ptr->Array1(),
&temp_mults_ptr->Array1(),
temp_sin,
&temp_denominator,
temp_knots,
&temp_mults,
value2);
BSplCLib::D0(param,
0,
temp_degree,
false,
temp_denominator_ptr->Array1(),
temp_denominator,
BSplCLib::NoWeights(),
temp_knots_ptr->Array1(),
&temp_mults_ptr->Array1(),
temp_knots,
&temp_mults,
value3);
contact_order_array(ii) = 0;
@@ -681,10 +768,10 @@ void Convert_ConicToBSplineCurve::BuildCosAndSin(
pivot_index_problem);
for (ii = 1; ii <= num_periodic_poles; ii++)
{
inverse = 1.0e0 / poles_array(ii).Coord(3);
CosNumeratorPtr->ChangeArray1()(ii) = poles_array(ii).Coord(1) * inverse;
SinNumeratorPtr->ChangeArray1()(ii) = poles_array(ii).Coord(2) * inverse;
DenominatorPtr->ChangeArray1()(ii) = poles_array(ii).Coord(3);
inverse = 1.0e0 / poles_array(ii).Coord(3);
CosNumerator(ii) = poles_array(ii).Coord(1) * inverse;
SinNumerator(ii) = poles_array(ii).Coord(2) * inverse;
Denominator(ii) = poles_array(ii).Coord(3);
}
}
}
@@ -20,13 +20,12 @@
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
#include <Standard_Macro.hxx>
#include <Convert_ParameterisationType.hxx>
#include <gp_Pnt2d.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
#include <Standard_Integer.hxx>
#include <Convert_ParameterisationType.hxx>
class gp_Pnt2d;
//! Root class for algorithms which convert a conic curve into
//! a BSpline curve (CircleToBSplineCurve, EllipseToBSplineCurve,
@@ -40,17 +39,6 @@ class gp_Pnt2d;
//! - a knots table with associated multiplicities.
//! The abstract class ConicToBSplineCurve provides a
//! framework for storing and consulting this computed data.
//! The data may then be used to construct a
//! Geom2d_BSplineCurve curvSuper class of the following classes :
//! This abstract class implements the methods to get the geometric
//! representation of the B-spline curve equivalent to the conic.
//! The B-spline is computed at the creation time in the sub classes.
//! The B-spline curve is defined with its degree, its control points
//! (Poles), its weights, its knots and their multiplicity.
//! All the geometric entities used in this package are defined in 2D
//! space.
//! KeyWords :
//! Convert, Conic, BSplineCurve, 2D.
class Convert_ConicToBSplineCurve
{
public:
@@ -58,79 +46,116 @@ public:
//! Returns the degree of the BSpline curve whose data is
//! computed in this framework.
Standard_EXPORT int Degree() const;
[[nodiscard]] Standard_EXPORT int Degree() const;
//! Returns the number of poles of the BSpline curve whose
//! data is computed in this framework.
Standard_EXPORT int NbPoles() const;
[[nodiscard]] Standard_EXPORT int NbPoles() const;
//! Returns the number of knots of the BSpline curve whose
//! data is computed in this framework.
Standard_EXPORT int NbKnots() const;
[[nodiscard]] Standard_EXPORT int NbKnots() const;
//! Returns true if the BSpline curve whose data is computed in
//! this framework is periodic.
Standard_EXPORT bool IsPeriodic() const;
[[nodiscard]] Standard_EXPORT bool IsPeriodic() const;
//! Returns the pole of index Index to the poles table of the
//! BSpline curve whose data is computed in this framework.
//! Exceptions
//! Standard_OutOfRange if Index is outside the bounds of
//! the poles table of the BSpline curve whose data is computed in this framework.
Standard_EXPORT gp_Pnt2d Pole(const int Index) const;
//! @param[in] theIndex pole index (1-based)
//! @return pole at the given index
//! @throws Standard_OutOfRange if theIndex is out of bounds
Standard_DEPRECATED("Use Poles() batch accessor instead")
Standard_EXPORT gp_Pnt2d Pole(const int theIndex) const;
//! Returns the weight of the pole of index Index to the poles
//! table of the BSpline curve whose data is computed in this framework.
//! Exceptions
//! Standard_OutOfRange if Index is outside the bounds of
//! the poles table of the BSpline curve whose data is computed in this framework.
Standard_EXPORT double Weight(const int Index) const;
//! @param[in] theIndex weight index (1-based)
//! @return weight at the given index
//! @throws Standard_OutOfRange if theIndex is out of bounds
Standard_DEPRECATED("Use Weights() batch accessor instead")
Standard_EXPORT double Weight(const int theIndex) const;
//! Returns the knot of index Index to the knots table of the
//! BSpline curve whose data is computed in this framework.
//! Exceptions
//! Standard_OutOfRange if Index is outside the bounds of
//! the knots table of the BSpline curve whose data is computed in this framework.
Standard_EXPORT double Knot(const int Index) const;
//! @param[in] theIndex knot index (1-based)
//! @return knot at the given index
//! @throws Standard_OutOfRange if theIndex is out of bounds
Standard_DEPRECATED("Use Knots() batch accessor instead")
Standard_EXPORT double Knot(const int theIndex) const;
//! Returns the multiplicity of the knot of index Index to the
//! knots table of the BSpline curve whose data is computed in this framework.
//! Exceptions
//! Standard_OutOfRange if Index is outside the bounds of
//! the knots table of the BSpline curve whose data is computed in this framework.
Standard_EXPORT int Multiplicity(const int Index) const;
//! @param[in] theIndex multiplicity index (1-based)
//! @return multiplicity at the given index
//! @throws Standard_OutOfRange if theIndex is out of bounds
Standard_DEPRECATED("Use Multiplicities() batch accessor instead")
Standard_EXPORT int Multiplicity(const int theIndex) const;
Standard_EXPORT void BuildCosAndSin(const Convert_ParameterisationType Parametrisation,
occ::handle<NCollection_HArray1<double>>& CosNumerator,
occ::handle<NCollection_HArray1<double>>& SinNumerator,
occ::handle<NCollection_HArray1<double>>& Denominator,
int& Degree,
occ::handle<NCollection_HArray1<double>>& Knots,
occ::handle<NCollection_HArray1<int>>& Mults) const;
//! Returns the poles of the BSpline curve.
[[nodiscard]] Standard_EXPORT const NCollection_Array1<gp_Pnt2d>& Poles() const;
Standard_EXPORT void BuildCosAndSin(const Convert_ParameterisationType Parametrisation,
const double UFirst,
const double ULast,
occ::handle<NCollection_HArray1<double>>& CosNumerator,
occ::handle<NCollection_HArray1<double>>& SinNumerator,
occ::handle<NCollection_HArray1<double>>& Denominator,
int& Degree,
occ::handle<NCollection_HArray1<double>>& Knots,
occ::handle<NCollection_HArray1<int>>& Mults) const;
//! Returns the weights of the BSpline curve.
[[nodiscard]] Standard_EXPORT const NCollection_Array1<double>& Weights() const;
//! Returns the knots of the BSpline curve.
[[nodiscard]] Standard_EXPORT const NCollection_Array1<double>& Knots() const;
//! Returns the multiplicities of the BSpline curve.
[[nodiscard]] Standard_EXPORT const NCollection_Array1<int>& Multiplicities() const;
//! Legacy API returning handle arrays for compatibility.
Standard_DEPRECATED("Use array-based BuildCosAndSin() overload instead")
Standard_EXPORT void BuildCosAndSin(const Convert_ParameterisationType theParametrisation,
occ::handle<NCollection_HArray1<double>>& theCosNumerator,
occ::handle<NCollection_HArray1<double>>& theSinNumerator,
occ::handle<NCollection_HArray1<double>>& theDenominator,
int& theDegree,
occ::handle<NCollection_HArray1<double>>& theKnots,
occ::handle<NCollection_HArray1<int>>& theMults) const;
//! Legacy API returning handle arrays for compatibility.
Standard_DEPRECATED("Use array-based BuildCosAndSin() overload instead")
Standard_EXPORT void BuildCosAndSin(const Convert_ParameterisationType theParametrisation,
const double theUFirst,
const double theULast,
occ::handle<NCollection_HArray1<double>>& theCosNumerator,
occ::handle<NCollection_HArray1<double>>& theSinNumerator,
occ::handle<NCollection_HArray1<double>>& theDenominator,
int& theDegree,
occ::handle<NCollection_HArray1<double>>& theKnots,
occ::handle<NCollection_HArray1<int>>& theMults) const;
protected:
Standard_EXPORT Convert_ConicToBSplineCurve(const int NumberOfPoles,
const int NumberOfKnots,
const int Degree);
Standard_EXPORT Convert_ConicToBSplineCurve(const int theNumberOfPoles,
const int theNumberOfKnots,
const int theDegree);
occ::handle<NCollection_HArray1<gp_Pnt2d>> poles;
occ::handle<NCollection_HArray1<double>> weights;
occ::handle<NCollection_HArray1<double>> knots;
occ::handle<NCollection_HArray1<int>> mults;
int degree;
int nbPoles;
int nbKnots;
bool isperiodic;
Standard_EXPORT void BuildCosAndSin(const Convert_ParameterisationType theParametrisation,
NCollection_Array1<double>& theCosNumerator,
NCollection_Array1<double>& theSinNumerator,
NCollection_Array1<double>& theDenominator,
int& theDegree,
NCollection_Array1<double>& theKnots,
NCollection_Array1<int>& theMults) const;
Standard_EXPORT void BuildCosAndSin(const Convert_ParameterisationType theParametrisation,
const double theUFirst,
const double theULast,
NCollection_Array1<double>& theCosNumerator,
NCollection_Array1<double>& theSinNumerator,
NCollection_Array1<double>& theDenominator,
int& theDegree,
NCollection_Array1<double>& theKnots,
NCollection_Array1<int>& theMults) const;
protected:
NCollection_Array1<gp_Pnt2d> myPoles;
NCollection_Array1<double> myWeights;
NCollection_Array1<double> myKnots;
NCollection_Array1<int> myMults;
int myDegree = 0;
bool myIsPeriodic = false;
};
#endif // _Convert_ConicToBSplineCurve_HeaderFile
@@ -21,7 +21,9 @@
#include <NCollection_Array1.hxx>
#include <Standard_Integer.hxx>
typedef void Convert_CosAndSinEvalFunction(double,
//! Function type for evaluating cos and sin representations
//! used in rational curve parameterization.
using Convert_CosAndSinEvalFunction = void(double,
const int,
const NCollection_Array1<gp_Pnt2d>&,
const NCollection_Array1<double>&,
@@ -84,8 +84,8 @@ Convert_CylinderToBSplineSurface::Convert_CylinderToBSplineSurface(const gp_Cyli
|| (deltaU < 0.),
"Convert_CylinderToBSplineSurface");
isuperiodic = false;
isvperiodic = false;
myIsUPeriodic = false;
myIsVPeriodic = false;
int i, j;
// construction of the cylinder in the reference mark xOy.
@@ -94,27 +94,27 @@ Convert_CylinderToBSplineSurface::Convert_CylinderToBSplineSurface(const gp_Cyli
int nbUSpans = (int)std::trunc(1.2 * deltaU / M_PI) + 1;
double AlfaU = deltaU / (nbUSpans * 2);
nbUPoles = 2 * nbUSpans + 1;
nbUKnots = nbUSpans + 1;
myNbUPoles = 2 * nbUSpans + 1;
myNbUKnots = nbUSpans + 1;
nbVPoles = 2;
nbVKnots = 2;
myNbVPoles = 2;
myNbVKnots = 2;
double R = Cyl.Radius();
ComputePoles(R, U1, U2, V1, V2, poles);
ComputePoles(R, U1, U2, V1, V2, myPoles);
for (i = 1; i <= nbUKnots; i++)
for (i = 1; i <= myNbUKnots; i++)
{
uknots(i) = U1 + (i - 1) * 2 * AlfaU;
umults(i) = 2;
myUKnots(i) = U1 + (i - 1) * 2 * AlfaU;
myUMults(i) = 2;
}
umults(1)++;
umults(nbUKnots)++;
vknots(1) = V1;
vmults(1) = 2;
vknots(2) = V2;
vmults(2) = 2;
myUMults(1)++;
myUMults(myNbUKnots)++;
myVKnots(1) = V1;
myVMults(1) = 2;
myVKnots(2) = V2;
myVMults(2) = 2;
// Replace bspline in the mark of the sphere.
// and calculate the weight of the bspline.
@@ -122,19 +122,20 @@ Convert_CylinderToBSplineSurface::Convert_CylinderToBSplineSurface(const gp_Cyli
gp_Trsf Trsf;
Trsf.SetTransformation(Cyl.Position(), gp::XOY());
for (i = 1; i <= nbUPoles; i++)
for (i = 1; i <= myNbUPoles; i++)
{
if (i % 2 == 0)
W1 = std::cos(AlfaU);
else
W1 = 1.;
for (j = 1; j <= nbVPoles; j++)
for (j = 1; j <= myNbVPoles; j++)
{
weights(i, j) = W1;
poles(i, j).Transform(Trsf);
myWeights(i, j) = W1;
myPoles(i, j).Transform(Trsf);
}
}
Finalize();
}
//=================================================================================================
@@ -154,29 +155,29 @@ Convert_CylinderToBSplineSurface::Convert_CylinderToBSplineSurface(const gp_Cyli
int i, j;
isuperiodic = true;
isvperiodic = false;
myIsUPeriodic = true;
myIsVPeriodic = false;
// construction of the cylinder in the reference mark xOy.
double R = Cyl.Radius();
ComputePoles(R, 0., 2. * M_PI, V1, V2, poles);
ComputePoles(R, 0., 2. * M_PI, V1, V2, myPoles);
nbUPoles = 6;
nbUKnots = 4;
nbVPoles = 2;
nbVKnots = 2;
myNbUPoles = 6;
myNbUKnots = 4;
myNbVPoles = 2;
myNbVKnots = 2;
for (i = 1; i <= nbUKnots; i++)
for (i = 1; i <= myNbUKnots; i++)
{
uknots(i) = (i - 1) * 2. * M_PI / 3.;
umults(i) = 2;
myUKnots(i) = (i - 1) * 2. * M_PI / 3.;
myUMults(i) = 2;
}
vknots(1) = V1;
vmults(1) = 2;
vknots(2) = V2;
vmults(2) = 2;
myVKnots(1) = V1;
myVMults(1) = 2;
myVKnots(2) = V2;
myVMults(2) = 2;
// Replace the bspline inn the mark of the cone.
// and calculate the weight of the bspline.
@@ -184,17 +185,18 @@ Convert_CylinderToBSplineSurface::Convert_CylinderToBSplineSurface(const gp_Cyli
gp_Trsf Trsf;
Trsf.SetTransformation(Cyl.Position(), gp::XOY());
for (i = 1; i <= nbUPoles; i++)
for (i = 1; i <= myNbUPoles; i++)
{
if (i % 2 == 0)
W = 0.5; // = std::cos(pi /3)
else
W = 1.;
for (j = 1; j <= nbVPoles; j++)
for (j = 1; j <= myNbVPoles; j++)
{
weights(i, j) = W;
poles(i, j).Transform(Trsf);
myWeights(i, j) = W;
myPoles(i, j).Transform(Trsf);
}
}
Finalize();
}
@@ -18,135 +18,219 @@
#include <gp_Pnt.hxx>
#include <Standard_OutOfRange.hxx>
//=================================================================================================
//==================================================================================================
void Convert_ElementarySurfaceToBSplineSurface::Finalize()
{
// Trim oversized arrays down to actual sizes, preserving 2D element positions.
if (myPoles.NbRows() != myNbUPoles || myPoles.NbColumns() != myNbVPoles)
{
myPoles.ResizeWithTrim(1, myNbUPoles, 1, myNbVPoles, true);
}
if (myWeights.NbRows() != myNbUPoles || myWeights.NbColumns() != myNbVPoles)
{
myWeights.ResizeWithTrim(1, myNbUPoles, 1, myNbVPoles, true);
}
if (myUKnots.Length() != myNbUKnots)
{
myUKnots.Resize(1, myNbUKnots, true);
}
if (myUMults.Length() != myNbUKnots)
{
myUMults.Resize(1, myNbUKnots, true);
}
if (myVKnots.Length() != myNbVKnots)
{
myVKnots.Resize(1, myNbVKnots, true);
}
if (myVMults.Length() != myNbVKnots)
{
myVMults.Resize(1, myNbVKnots, true);
}
}
//==================================================================================================
Convert_ElementarySurfaceToBSplineSurface::Convert_ElementarySurfaceToBSplineSurface(
const int NbUPoles,
const int NbVPoles,
const int NbUKnots,
const int NbVKnots,
const int UDegree,
const int VDegree)
: poles(1, NbUPoles, 1, NbVPoles),
weights(1, NbUPoles, 1, NbVPoles),
uknots(1, NbUKnots),
umults(1, NbUKnots),
vknots(1, NbVKnots),
vmults(1, NbVKnots),
udegree(UDegree),
vdegree(VDegree),
nbUPoles(NbUPoles),
nbVPoles(NbVPoles),
nbUKnots(NbUKnots),
nbVKnots(NbVKnots),
isuperiodic(false),
isvperiodic(false)
const int theNbUPoles,
const int theNbVPoles,
const int theNbUKnots,
const int theNbVKnots,
const int theUDegree,
const int theVDegree)
: myPoles(1, theNbUPoles, 1, theNbVPoles),
myWeights(1, theNbUPoles, 1, theNbVPoles),
myUKnots(1, theNbUKnots),
myVKnots(1, theNbVKnots),
myUMults(1, theNbUKnots),
myVMults(1, theNbVKnots),
myUDegree(theUDegree),
myVDegree(theVDegree),
myNbUPoles(theNbUPoles),
myNbVPoles(theNbVPoles),
myNbUKnots(theNbUKnots),
myNbVKnots(theNbVKnots)
{
}
//=================================================================================================
//==================================================================================================
int Convert_ElementarySurfaceToBSplineSurface::UDegree() const
{
return udegree;
return myUDegree;
}
//=================================================================================================
//==================================================================================================
int Convert_ElementarySurfaceToBSplineSurface::VDegree() const
{
return vdegree;
return myVDegree;
}
//=================================================================================================
//==================================================================================================
int Convert_ElementarySurfaceToBSplineSurface::NbUPoles() const
{
return nbUPoles;
return myNbUPoles;
}
//=================================================================================================
//==================================================================================================
int Convert_ElementarySurfaceToBSplineSurface::NbVPoles() const
{
return nbVPoles;
return myNbVPoles;
}
//=================================================================================================
//==================================================================================================
int Convert_ElementarySurfaceToBSplineSurface::NbUKnots() const
{
return nbUKnots;
return myNbUKnots;
}
//=================================================================================================
//==================================================================================================
int Convert_ElementarySurfaceToBSplineSurface::NbVKnots() const
{
return nbVKnots;
return myNbVKnots;
}
//=================================================================================================
//==================================================================================================
bool Convert_ElementarySurfaceToBSplineSurface::IsUPeriodic() const
{
return isuperiodic;
return myIsUPeriodic;
}
//=================================================================================================
//==================================================================================================
bool Convert_ElementarySurfaceToBSplineSurface::IsVPeriodic() const
{
return isvperiodic;
return myIsVPeriodic;
}
//=================================================================================================
//==================================================================================================
gp_Pnt Convert_ElementarySurfaceToBSplineSurface::Pole(const int UIndex, const int VIndex) const
Standard_DISABLE_DEPRECATION_WARNINGS gp_Pnt
Convert_ElementarySurfaceToBSplineSurface::Pole(const int UIndex, const int VIndex) const
{
Standard_OutOfRange_Raise_if(UIndex < 1 || UIndex > nbUPoles || VIndex < 1 || VIndex > nbVPoles,
" ");
return poles(UIndex, VIndex);
Standard_OutOfRange_Raise_if(
UIndex < 1 || UIndex > myNbUPoles || VIndex < 1 || VIndex > myNbVPoles,
"Convert_ElementarySurfaceToBSplineSurface::Pole: Index out of range");
return myPoles(UIndex, VIndex);
}
//=================================================================================================
//==================================================================================================
double Convert_ElementarySurfaceToBSplineSurface::Weight(const int UIndex, const int VIndex) const
{
Standard_OutOfRange_Raise_if(UIndex < 1 || UIndex > nbUPoles || VIndex < 1 || VIndex > nbVPoles,
" ");
return weights(UIndex, VIndex);
Standard_OutOfRange_Raise_if(
UIndex < 1 || UIndex > myNbUPoles || VIndex < 1 || VIndex > myNbVPoles,
"Convert_ElementarySurfaceToBSplineSurface::Weight: Index out of range");
return myWeights(UIndex, VIndex);
}
//=================================================================================================
//==================================================================================================
double Convert_ElementarySurfaceToBSplineSurface::UKnot(const int UIndex) const
{
Standard_OutOfRange_Raise_if(UIndex < 1 || UIndex > nbUKnots, " ");
return uknots(UIndex);
Standard_OutOfRange_Raise_if(
UIndex < 1 || UIndex > myNbUKnots,
"Convert_ElementarySurfaceToBSplineSurface::UKnot: Index out of range");
return myUKnots(UIndex);
}
//=================================================================================================
//==================================================================================================
double Convert_ElementarySurfaceToBSplineSurface::VKnot(const int VIndex) const
{
Standard_OutOfRange_Raise_if(VIndex < 1 || VIndex > nbVKnots, " ");
return vknots(VIndex);
Standard_OutOfRange_Raise_if(
VIndex < 1 || VIndex > myNbVKnots,
"Convert_ElementarySurfaceToBSplineSurface::VKnot: Index out of range");
return myVKnots(VIndex);
}
//=================================================================================================
//==================================================================================================
int Convert_ElementarySurfaceToBSplineSurface::UMultiplicity(const int UIndex) const
{
Standard_OutOfRange_Raise_if(UIndex < 1 || UIndex > nbUKnots, " ");
return umults(UIndex);
Standard_OutOfRange_Raise_if(
UIndex < 1 || UIndex > myNbUKnots,
"Convert_ElementarySurfaceToBSplineSurface::UMultiplicity: Index out of range");
return myUMults(UIndex);
}
//=================================================================================================
//==================================================================================================
int Convert_ElementarySurfaceToBSplineSurface::VMultiplicity(const int VIndex) const
{
Standard_OutOfRange_Raise_if(VIndex < 1 || VIndex > nbVKnots, " ");
return vmults(VIndex);
Standard_OutOfRange_Raise_if(
VIndex < 1 || VIndex > myNbVKnots,
"Convert_ElementarySurfaceToBSplineSurface::VMultiplicity: Index out of range");
return myVMults(VIndex);
}
Standard_ENABLE_DEPRECATION_WARNINGS
//==================================================================================================
const NCollection_Array2<gp_Pnt>&
Convert_ElementarySurfaceToBSplineSurface::Poles() const
{
return myPoles;
}
//==================================================================================================
const NCollection_Array2<double>& Convert_ElementarySurfaceToBSplineSurface::Weights() const
{
return myWeights;
}
//==================================================================================================
const NCollection_Array1<double>& Convert_ElementarySurfaceToBSplineSurface::UKnots() const
{
return myUKnots;
}
//==================================================================================================
const NCollection_Array1<double>& Convert_ElementarySurfaceToBSplineSurface::VKnots() const
{
return myVKnots;
}
//==================================================================================================
const NCollection_Array1<int>& Convert_ElementarySurfaceToBSplineSurface::UMultiplicities() const
{
return myUMults;
}
//==================================================================================================
const NCollection_Array1<int>& Convert_ElementarySurfaceToBSplineSurface::VMultiplicities() const
{
return myVMults;
}
@@ -20,132 +20,126 @@
#include <Standard.hxx>
#include <Standard_DefineAlloc.hxx>
#include <Standard_Handle.hxx>
#include <Standard_Macro.hxx>
#include <gp_Pnt.hxx>
#include <NCollection_Array2.hxx>
#include <NCollection_Array1.hxx>
#include <Standard_Integer.hxx>
#include <Standard_Boolean.hxx>
class gp_Pnt;
#include <NCollection_Array2.hxx>
//! Root class for algorithms which convert an elementary
//! surface (cylinder, cone, sphere or torus) into a BSpline
//! surface (CylinderToBSplineSurface, ConeToBSplineSurface,
//! SphereToBSplineSurface, TorusToBSplineSurface).
//! surface (cylinder, cone, sphere or torus) into a BSpline surface.
//! These algorithms all work on elementary surfaces from
//! the gp package and compute all the data needed to
//! construct a BSpline surface equivalent to the cylinder,
//! cone, sphere or torus. This data consists of the following:
//! - degrees in the u and v parametric directions,
//! - periodic characteristics in the u and v parametric directions,
//! - a poles table with associated weights,
//! - a knots table (for the u and v parametric directions)
//! with associated multiplicities.
//! The abstract class
//! ElementarySurfaceToBSplineSurface provides a
//! framework for storing and consulting this computed data.
//! This data may then be used to construct a
//! Geom_BSplineSurface surface, for example.
//! All those classes define algorithms to convert an
//! ElementarySurface into a B-spline surface.
//! This abstract class implements the methods to get
//! the geometric representation of the B-spline surface.
//! The B-spline representation is computed at the creation
//! time in the sub classes.
//! The B-spline surface is defined with its degree in the
//! parametric U and V directions, its control points (Poles),
//! its weights, its knots and their multiplicity.
//! KeyWords :
//! Convert, ElementarySurface, BSplineSurface.
//! cone, sphere or torus.
class Convert_ElementarySurfaceToBSplineSurface
{
public:
DEFINE_STANDARD_ALLOC
Standard_EXPORT int UDegree() const;
//! Returns the degree in the U parametric direction.
[[nodiscard]] Standard_EXPORT int UDegree() const;
//! Returns the degree for the u or v parametric direction of
//! the BSpline surface whose data is computed in this framework.
Standard_EXPORT int VDegree() const;
//! Returns the degree in the V parametric direction.
[[nodiscard]] Standard_EXPORT int VDegree() const;
Standard_EXPORT int NbUPoles() const;
//! Returns the number of poles in the U parametric direction.
[[nodiscard]] Standard_EXPORT int NbUPoles() const;
//! Returns the number of poles for the u or v parametric
//! direction of the BSpline surface whose data is computed in this framework.
Standard_EXPORT int NbVPoles() const;
//! Returns the number of poles in the V parametric direction.
[[nodiscard]] Standard_EXPORT int NbVPoles() const;
Standard_EXPORT int NbUKnots() const;
//! Returns the number of knots in the U parametric direction.
[[nodiscard]] Standard_EXPORT int NbUKnots() const;
//! Returns the number of knots for the u or v parametric
//! direction of the BSpline surface whose data is computed in this framework .
Standard_EXPORT int NbVKnots() const;
//! Returns the number of knots in the V parametric direction.
[[nodiscard]] Standard_EXPORT int NbVKnots() const;
Standard_EXPORT bool IsUPeriodic() const;
//! Returns true if the surface is periodic in the U parametric direction.
[[nodiscard]] Standard_EXPORT bool IsUPeriodic() const;
//! Returns true if the BSpline surface whose data is computed
//! in this framework is periodic in the u or v parametric direction.
Standard_EXPORT bool IsVPeriodic() const;
//! Returns true if the surface is periodic in the V parametric direction.
[[nodiscard]] Standard_EXPORT bool IsVPeriodic() const;
//! Returns the pole of index (UIndex,VIndex) to the poles
//! table of the BSpline surface whose data is computed in this framework.
//! Exceptions
//! Standard_OutOfRange if, for the BSpline surface whose
//! data is computed in this framework:
//! - UIndex is outside the bounds of the poles table in the u
//! parametric direction, or
//! - VIndex is outside the bounds of the poles table in the v
//! parametric direction.
//! Returns the pole of index (UIndex, VIndex).
//! @throws Standard_OutOfRange if indices are out of bounds
Standard_DEPRECATED("Use Poles() batch accessor instead")
Standard_EXPORT gp_Pnt Pole(const int UIndex, const int VIndex) const;
//! Returns the weight of the pole of index (UIndex,VIndex) to
//! the poles table of the BSpline surface whose data is computed in this framework.
//! Exceptions
//! Standard_OutOfRange if, for the BSpline surface whose
//! data is computed in this framework:
//! - UIndex is outside the bounds of the poles table in the u
//! parametric direction, or
//! - VIndex is outside the bounds of the poles table in the v
//! parametric direction.
//! Returns the weight of the pole of index (UIndex, VIndex).
//! @throws Standard_OutOfRange if indices are out of bounds
Standard_DEPRECATED("Use Weights() batch accessor instead")
Standard_EXPORT double Weight(const int UIndex, const int VIndex) const;
//! Returns the U-knot of range UIndex.
//! Raised if UIndex < 1 or UIndex > NbUKnots.
//! @throws Standard_OutOfRange if UIndex is out of bounds
Standard_DEPRECATED("Use UKnots() batch accessor instead")
Standard_EXPORT double UKnot(const int UIndex) const;
//! Returns the V-knot of range VIndex.
//! Raised if VIndex < 1 or VIndex > NbVKnots.
Standard_EXPORT double VKnot(const int UIndex) const;
//! @throws Standard_OutOfRange if VIndex is out of bounds
Standard_DEPRECATED("Use VKnots() batch accessor instead")
Standard_EXPORT double VKnot(const int VIndex) const;
//! Returns the multiplicity of the U-knot of range UIndex.
//! Raised if UIndex < 1 or UIndex > NbUKnots.
//! @throws Standard_OutOfRange if UIndex is out of bounds
Standard_DEPRECATED("Use UMultiplicities() batch accessor instead")
Standard_EXPORT int UMultiplicity(const int UIndex) const;
//! Returns the multiplicity of the V-knot of range VIndex.
//! Raised if VIndex < 1 or VIndex > NbVKnots.
//! @throws Standard_OutOfRange if VIndex is out of bounds
Standard_DEPRECATED("Use VMultiplicities() batch accessor instead")
Standard_EXPORT int VMultiplicity(const int VIndex) const;
protected:
Standard_EXPORT Convert_ElementarySurfaceToBSplineSurface(const int NumberOfUPoles,
const int NumberOfVPoles,
const int NumberOfUKnots,
const int NumberOfVKnots,
const int UDegree,
const int VDegree);
//! Returns the poles of the BSpline surface.
[[nodiscard]] Standard_EXPORT const NCollection_Array2<gp_Pnt>& Poles() const;
NCollection_Array2<gp_Pnt> poles;
NCollection_Array2<double> weights;
NCollection_Array1<double> uknots;
NCollection_Array1<int> umults;
NCollection_Array1<double> vknots;
NCollection_Array1<int> vmults;
int udegree;
int vdegree;
int nbUPoles;
int nbVPoles;
int nbUKnots;
int nbVKnots;
bool isuperiodic;
bool isvperiodic;
//! Returns the weights of the BSpline surface.
[[nodiscard]] Standard_EXPORT const NCollection_Array2<double>& Weights() const;
//! Returns the U-knots of the BSpline surface.
[[nodiscard]] Standard_EXPORT const NCollection_Array1<double>& UKnots() const;
//! Returns the V-knots of the BSpline surface.
[[nodiscard]] Standard_EXPORT const NCollection_Array1<double>& VKnots() const;
//! Returns the U-multiplicities of the BSpline surface.
[[nodiscard]] Standard_EXPORT const NCollection_Array1<int>& UMultiplicities() const;
//! Returns the V-multiplicities of the BSpline surface.
[[nodiscard]] Standard_EXPORT const NCollection_Array1<int>& VMultiplicities() const;
protected:
Standard_EXPORT Convert_ElementarySurfaceToBSplineSurface(const int theNbUPoles,
const int theNbVPoles,
const int theNbUKnots,
const int theNbVKnots,
const int theUDegree,
const int theVDegree);
//! Resizes internal arrays (poles, weights, knots, multiplicities)
//! to match the actual sizes stored in myNbUPoles, myNbVPoles,
//! myNbUKnots, and myNbVKnots. This is intended to be called at the
//! end of derived class constructors when the base class constructor
//! allocates arrays with maximum possible sizes but the derived
//! constructor uses fewer elements.
Standard_EXPORT void Finalize();
protected:
NCollection_Array2<gp_Pnt> myPoles;
NCollection_Array2<double> myWeights;
NCollection_Array1<double> myUKnots;
NCollection_Array1<double> myVKnots;
NCollection_Array1<int> myUMults;
NCollection_Array1<int> myVMults;
int myUDegree = 0;
int myVDegree = 0;
bool myIsUPeriodic = false;
bool myIsVPeriodic = false;
int myNbUPoles;
int myNbVPoles;
int myNbUKnots;
int myNbVKnots;
};
#endif // _Convert_ElementarySurfaceToBSplineSurface_HeaderFile
@@ -24,14 +24,13 @@
#include <Standard_DomainError.hxx>
#include <gp_Pnt2d.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
// Attention :
// To avoid use of persistent tables in the fields
// the tables are dimensioned to the maximum (TheNbKnots and TheNbPoles)
// that correspond to the full circle. For an arc of circle there is a
// need of less poles and nodes, that is why the fields
// nbKnots and nbPoles are present and updated in the
// myNbKnots and myNbPoles are present and updated in the
// constructor of an arc of B-spline circle to take into account
// the real number of poles and nodes.
// parameterization :
@@ -53,8 +52,8 @@ Convert_EllipseToBSplineCurve::Convert_EllipseToBSplineCurve(
int ii;
double R, r, value;
occ::handle<NCollection_HArray1<double>> CosNumeratorPtr, SinNumeratorPtr;
double R, r, value;
NCollection_Array1<double> CosNumerator, SinNumerator;
R = E.MajorRadius();
r = E.MinorRadius();
@@ -63,33 +62,30 @@ Convert_EllipseToBSplineCurve::Convert_EllipseToBSplineCurve(
{
// If BuildCosAndSin cannot manage the periodicity
// => trim on 0,2*PI
isperiodic = false;
myIsPeriodic = false;
Convert_ConicToBSplineCurve::BuildCosAndSin(Parameterisation,
0,
2 * M_PI,
CosNumeratorPtr,
SinNumeratorPtr,
weights,
degree,
knots,
mults);
CosNumerator,
SinNumerator,
myWeights,
myDegree,
myKnots,
myMults);
}
else
{
isperiodic = true;
myIsPeriodic = true;
Convert_ConicToBSplineCurve::BuildCosAndSin(Parameterisation,
CosNumeratorPtr,
SinNumeratorPtr,
weights,
degree,
knots,
mults);
CosNumerator,
SinNumerator,
myWeights,
myDegree,
myKnots,
myMults);
}
nbPoles = CosNumeratorPtr->Length();
nbKnots = knots->Length();
poles = new NCollection_HArray1<gp_Pnt2d>(1, nbPoles);
myPoles = NCollection_Array1<gp_Pnt2d>(1, CosNumerator.Length());
gp_Dir2d Ox = E.XAxis().Direction();
gp_Dir2d Oy = E.YAxis().Direction();
@@ -107,11 +103,11 @@ Convert_EllipseToBSplineCurve::Convert_EllipseToBSplineCurve(
// Replace the bspline in the mark of the circle.
// and calculate the weight of the bspline.
for (ii = 1; ii <= nbPoles; ii++)
for (ii = 1; ii <= myPoles.Length(); ii++)
{
poles->ChangeArray1()(ii).SetCoord(1, R * CosNumeratorPtr->Value(ii));
poles->ChangeArray1()(ii).SetCoord(2, value * SinNumeratorPtr->Value(ii));
poles->ChangeArray1()(ii).Transform(Trsf);
myPoles(ii).SetCoord(1, R * CosNumerator(ii));
myPoles(ii).SetCoord(2, value * SinNumerator(ii));
myPoles(ii).Transform(Trsf);
}
}
@@ -133,28 +129,25 @@ Convert_EllipseToBSplineCurve::Convert_EllipseToBSplineCurve(
#endif
Standard_DomainError_Raise_if((delta > (2 * M_PI + Tol)) || (delta <= 0.0e0),
"Convert_EllipseToBSplineCurve");
int ii;
double R, r, value;
occ::handle<NCollection_HArray1<double>> CosNumeratorPtr, SinNumeratorPtr;
int ii;
double R, r, value;
NCollection_Array1<double> CosNumerator, SinNumerator;
R = E.MajorRadius();
r = E.MinorRadius();
isperiodic = false;
myIsPeriodic = false;
Convert_ConicToBSplineCurve::BuildCosAndSin(Parameterisation,
UFirst,
ULast,
CosNumeratorPtr,
SinNumeratorPtr,
weights,
degree,
knots,
mults);
CosNumerator,
SinNumerator,
myWeights,
myDegree,
myKnots,
myMults);
nbPoles = CosNumeratorPtr->Length();
nbKnots = knots->Length();
poles = new NCollection_HArray1<gp_Pnt2d>(1, nbPoles);
myPoles = NCollection_Array1<gp_Pnt2d>(1, CosNumerator.Length());
gp_Dir2d Ox = E.XAxis().Direction();
gp_Dir2d Oy = E.YAxis().Direction();
@@ -172,10 +165,10 @@ Convert_EllipseToBSplineCurve::Convert_EllipseToBSplineCurve(
// Replace the bspline in the mark of the circle.
// and calculate the weight of the bspline.
for (ii = 1; ii <= nbPoles; ii++)
for (ii = 1; ii <= myPoles.Length(); ii++)
{
poles->ChangeArray1()(ii).SetCoord(1, R * CosNumeratorPtr->Value(ii));
poles->ChangeArray1()(ii).SetCoord(2, value * SinNumeratorPtr->Value(ii));
poles->ChangeArray1()(ii).Transform(Trsf);
myPoles(ii).SetCoord(1, R * CosNumerator(ii));
myPoles(ii).SetCoord(2, value * SinNumerator(ii));
myPoles(ii).Transform(Trsf);
}
}
@@ -33,7 +33,9 @@ Convert_GridPolynomialToPoles::Convert_GridPolynomialToPoles(
const occ::handle<NCollection_HArray1<double>>& Coefficients,
const occ::handle<NCollection_HArray1<double>>& PolynomialUIntervals,
const occ::handle<NCollection_HArray1<double>>& PolynomialVIntervals)
: myDone(false)
: myUDegree(0),
myVDegree(0),
myDone(false)
{
// Les Controles
if ((NumCoeffPerSurface->Lower() != 1) || (NumCoeffPerSurface->Upper() != 2))
@@ -84,13 +86,12 @@ Convert_GridPolynomialToPoles::Convert_GridPolynomialToPoles(
const occ::handle<NCollection_HArray1<double>>& PolynomialVIntervals,
const occ::handle<NCollection_HArray1<double>>& TrueUIntervals,
const occ::handle<NCollection_HArray1<double>>& TrueVIntervals)
: myDone(false)
: myUDegree(0),
myVDegree(0),
myDone(false)
{
int ii;
int RealUDegree = std::max(MaxUDegree, 2 * UContinuity + 1);
int RealVDegree = std::max(MaxVDegree, 2 * VContinuity + 1);
myUDegree = 0;
myVDegree = 0;
// Les controles
if ((NumCoeffPerSurface->LowerRow() != 1)
@@ -108,7 +109,7 @@ Convert_GridPolynomialToPoles::Convert_GridPolynomialToPoles(
}
// Calcul des degree
for (ii = 1; ii <= NbUSurfaces * NbVSurfaces; ii++)
for (int ii = 1; ii <= NbUSurfaces * NbVSurfaces; ii++)
{
if (NumCoeffPerSurface->Value(ii, 1) > myUDegree + 1)
myUDegree = NumCoeffPerSurface->Value(ii, 1) - 1;
@@ -146,11 +147,9 @@ void Convert_GridPolynomialToPoles::Perform(
const occ::handle<NCollection_HArray1<double>>& TrueVIntervals)
{
// (1) Construction des Tables monodimensionnelles ----------------------------
occ::handle<NCollection_HArray1<double>> UParameters, VParameters;
myUKnots = new (NCollection_HArray1<double>)(1, TrueUIntervals->Length());
myUKnots->ChangeArray1() = TrueUIntervals->Array1();
myVKnots = new (NCollection_HArray1<double>)(1, TrueVIntervals->Length());
myVKnots->ChangeArray1() = TrueVIntervals->Array1();
NCollection_Array1<double> UParameters, VParameters;
myUKnots = NCollection_Array1<double>(TrueUIntervals->Array1());
myVKnots = NCollection_Array1<double>(TrueVIntervals->Array1());
BuildArray(myUDegree, myUKnots, UContinuity, myUFlatKnots, myUMults, UParameters);
@@ -163,46 +162,46 @@ void Convert_GridPolynomialToPoles::Perform(
double NValue, UValue, VValue;
int dimension = 3 * (myVDegree + 1);
int SizPatch = 3 * (MaxUDegree + 1) * (MaxVDegree + 1);
myPoles = new (NCollection_HArray2<gp_Pnt>)(1, UParameters->Length(), 1, VParameters->Length());
myPoles = NCollection_Array2<gp_Pnt>(1, UParameters.Length(), 1, VParameters.Length());
NCollection_Array1<double> Patch(1, (myUDegree + 1) * dimension);
NCollection_Array1<double> Point(1, 3);
double* Coeffs = (double*)&Patch.ChangeValue(1);
double* Digit = (double*)&Point.ChangeValue(1);
for (ii = 1, Uindex = 1; ii <= UParameters->Length(); ii++)
for (ii = 1, Uindex = 1; ii <= UParameters.Length(); ii++)
{
while (UParameters->Value(ii) > TrueUIntervals->Value(Uindex + 1)
&& Uindex < myUKnots->Length() - 1)
while (UParameters.Value(ii) > TrueUIntervals->Value(Uindex + 1)
&& Uindex < myUKnots.Length() - 1)
{
Uindex++;
}
NValue = (UParameters->Value(ii) - TrueUIntervals->Value(Uindex))
NValue = (UParameters.Value(ii) - TrueUIntervals->Value(Uindex))
/ (TrueUIntervals->Value(Uindex + 1) - TrueUIntervals->Value(Uindex));
UValue =
(1 - NValue) * PolynomialUIntervals->Value(1) + NValue * PolynomialUIntervals->Value(2);
for (jj = 1, Vindex = 1; jj <= VParameters->Length(); jj++)
for (jj = 1, Vindex = 1; jj <= VParameters.Length(); jj++)
{
while (VParameters->Value(jj) > TrueVIntervals->Value(Vindex + 1)
&& Vindex < myVKnots->Length() - 1)
while (VParameters.Value(jj) > TrueVIntervals->Value(Vindex + 1)
&& Vindex < myVKnots.Length() - 1)
{
Vindex++;
}
NValue = (VParameters->Value(jj) - TrueVIntervals->Value(Vindex))
NValue = (VParameters.Value(jj) - TrueVIntervals->Value(Vindex))
/ (TrueVIntervals->Value(Vindex + 1) - TrueVIntervals->Value(Vindex));
VValue =
(1 - NValue) * PolynomialVIntervals->Value(1) + NValue * PolynomialVIntervals->Value(2);
// (2.1) Extraction du bon Patch
if (Patch_Indice != Uindex + (myUKnots->Length() - 1) * (Vindex - 1))
if (Patch_Indice != Uindex + (myUKnots.Length() - 1) * (Vindex - 1))
{
int k1, k2, pos, ll = 1;
Patch_Indice = Uindex + (myUKnots->Length() - 1) * (Vindex - 1);
Patch_Indice = Uindex + (myUKnots.Length() - 1) * (Vindex - 1);
for (k1 = 1; k1 <= NumCoeffPerSurface->Value(Patch_Indice, 1); k1++)
{
pos = SizPatch * (Patch_Indice - 1) + 3 * (MaxVDegree + 1) * (k1 - 1) + 1;
@@ -227,7 +226,7 @@ void Convert_GridPolynomialToPoles::Perform(
Coeffs[0],
Digit[0]);
myPoles->SetValue(ii, jj, gp_Pnt(Digit[0], Digit[1], Digit[2]));
myPoles.SetValue(ii, jj, gp_Pnt(Digit[0], Digit[1], Digit[2]));
}
}
@@ -236,121 +235,139 @@ void Convert_GridPolynomialToPoles::Perform(
int InversionProblem;
BSplSLib::Interpolate(myUDegree,
myVDegree,
myUFlatKnots->Array1(),
myVFlatKnots->Array1(),
UParameters->Array1(),
VParameters->Array1(),
myPoles->ChangeArray2(),
myUFlatKnots,
myVFlatKnots,
UParameters,
VParameters,
myPoles,
InversionProblem);
myDone = (InversionProblem == 0);
}
void Convert_GridPolynomialToPoles::BuildArray(
const int Degree,
const occ::handle<NCollection_HArray1<double>>& Knots,
const int Continuity,
occ::handle<NCollection_HArray1<double>>& FlatKnots,
occ::handle<NCollection_HArray1<int>>& Mults,
occ::handle<NCollection_HArray1<double>>& Parameters) const
void Convert_GridPolynomialToPoles::BuildArray(const int Degree,
const NCollection_Array1<double>& Knots,
const int Continuity,
NCollection_Array1<double>& FlatKnots,
NCollection_Array1<int>& Mults,
NCollection_Array1<double>& Parameters) const
{
int NumCurves = Knots->Length() - 1;
const int NumCurves = Knots.Length() - 1;
// Calcul des Multiplicites
int ii;
int multiplicities = Degree - Continuity;
Mults = new (NCollection_HArray1<int>)(1, Knots->Length());
const int multiplicities = Degree - Continuity;
Mults = NCollection_Array1<int>(1, Knots.Length());
for (ii = 2; ii < Knots->Length(); ii++)
for (int ii = 2; ii < Knots.Length(); ii++)
{
Mults->SetValue(ii, multiplicities);
Mults.SetValue(ii, multiplicities);
}
Mults->SetValue(1, Degree + 1);
Mults->SetValue(NumCurves + 1, Degree + 1);
Mults.SetValue(1, Degree + 1);
Mults.SetValue(NumCurves + 1, Degree + 1);
// Calcul des Noeuds Plats
int num_flat_knots = multiplicities * (NumCurves - 1) + 2 * Degree + 2;
FlatKnots = new NCollection_HArray1<double>(1, num_flat_knots);
const int num_flat_knots = multiplicities * (NumCurves - 1) + 2 * Degree + 2;
FlatKnots = NCollection_Array1<double>(1, num_flat_knots);
BSplCLib::KnotSequence(Knots->Array1(),
Mults->Array1(),
Degree,
false,
FlatKnots->ChangeArray1());
BSplCLib::KnotSequence(Knots, Mults, Degree, false, FlatKnots);
// Calcul du nombre de Poles
int num_poles = num_flat_knots - Degree - 1;
const int num_poles = num_flat_knots - Degree - 1;
// Cacul des parametres d'interpolation
Parameters = new (NCollection_HArray1<double>)(1, num_poles);
BSplCLib::BuildSchoenbergPoints(Degree, FlatKnots->Array1(), Parameters->ChangeArray1());
Parameters = NCollection_Array1<double>(1, num_poles);
BSplCLib::BuildSchoenbergPoints(Degree, FlatKnots, Parameters);
}
//==================================================================================================
int Convert_GridPolynomialToPoles::NbUPoles() const
{
StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
return myPoles->ColLength();
return myPoles.ColLength();
}
//==================================================================================================
int Convert_GridPolynomialToPoles::NbVPoles() const
{
StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
return myPoles->RowLength();
return myPoles.RowLength();
}
const occ::handle<NCollection_HArray2<gp_Pnt>>& Convert_GridPolynomialToPoles::Poles() const
//==================================================================================================
const NCollection_Array2<gp_Pnt>& Convert_GridPolynomialToPoles::Poles() const
{
StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
return myPoles;
}
//==================================================================================================
int Convert_GridPolynomialToPoles::UDegree() const
{
StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
return myUDegree;
}
//==================================================================================================
int Convert_GridPolynomialToPoles::VDegree() const
{
StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
return myVDegree;
}
//==================================================================================================
int Convert_GridPolynomialToPoles::NbUKnots() const
{
StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
return myUKnots->Length();
return myUKnots.Length();
}
//==================================================================================================
int Convert_GridPolynomialToPoles::NbVKnots() const
{
StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
return myVKnots->Length();
return myVKnots.Length();
}
const occ::handle<NCollection_HArray1<double>>& Convert_GridPolynomialToPoles::UKnots() const
//==================================================================================================
const NCollection_Array1<double>& Convert_GridPolynomialToPoles::UKnots() const
{
StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
return myUKnots;
}
const occ::handle<NCollection_HArray1<double>>& Convert_GridPolynomialToPoles::VKnots() const
//==================================================================================================
const NCollection_Array1<double>& Convert_GridPolynomialToPoles::VKnots() const
{
StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
return myVKnots;
}
const occ::handle<NCollection_HArray1<int>>& Convert_GridPolynomialToPoles::UMultiplicities() const
//==================================================================================================
const NCollection_Array1<int>& Convert_GridPolynomialToPoles::UMultiplicities() const
{
StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
return myUMults;
}
const occ::handle<NCollection_HArray1<int>>& Convert_GridPolynomialToPoles::VMultiplicities() const
//==================================================================================================
const NCollection_Array1<int>& Convert_GridPolynomialToPoles::VMultiplicities() const
{
StdFail_NotDone_Raise_if(!myDone, "GridPolynomialToPoles");
return myVMults;
}
//==================================================================================================
bool Convert_GridPolynomialToPoles::IsDone() const
{
return myDone;
@@ -23,7 +23,6 @@
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
#include <Standard_Integer.hxx>
#include <gp_Pnt.hxx>
#include <NCollection_Array2.hxx>
#include <NCollection_HArray2.hxx>
@@ -81,6 +80,43 @@ public:
const occ::handle<NCollection_HArray1<double>>& TrueUIntervals,
const occ::handle<NCollection_HArray1<double>>& TrueVIntervals);
//! Returns the number of poles in the U parametric direction.
[[nodiscard]] Standard_EXPORT int NbUPoles() const;
//! Returns the number of poles in the V parametric direction.
[[nodiscard]] Standard_EXPORT int NbVPoles() const;
//! Returns the poles of the BSpline Surface.
[[nodiscard]] Standard_EXPORT const NCollection_Array2<gp_Pnt>& Poles() const;
//! Returns the degree in the U parametric direction.
[[nodiscard]] Standard_EXPORT int UDegree() const;
//! Returns the degree in the V parametric direction.
[[nodiscard]] Standard_EXPORT int VDegree() const;
//! Returns the number of knots in the U parametric direction.
[[nodiscard]] Standard_EXPORT int NbUKnots() const;
//! Returns the number of knots in the V parametric direction.
[[nodiscard]] Standard_EXPORT int NbVKnots() const;
//! Returns the knots in the U direction.
[[nodiscard]] Standard_EXPORT const NCollection_Array1<double>& UKnots() const;
//! Returns the knots in the V direction.
[[nodiscard]] Standard_EXPORT const NCollection_Array1<double>& VKnots() const;
//! Returns the multiplicities of the knots in the U direction.
[[nodiscard]] Standard_EXPORT const NCollection_Array1<int>& UMultiplicities() const;
//! Returns the multiplicities of the knots in the V direction.
[[nodiscard]] Standard_EXPORT const NCollection_Array1<int>& VMultiplicities() const;
//! Returns true if the conversion was successful.
[[nodiscard]] Standard_EXPORT bool IsDone() const;
private:
Standard_EXPORT void Perform(const int UContinuity,
const int VContinuity,
const int MaxUDegree,
@@ -92,53 +128,24 @@ public:
const occ::handle<NCollection_HArray1<double>>& TrueUIntervals,
const occ::handle<NCollection_HArray1<double>>& TrueVIntervals);
Standard_EXPORT int NbUPoles() const;
Standard_EXPORT int NbVPoles() const;
//! returns the poles of the BSpline Surface
Standard_EXPORT const occ::handle<NCollection_HArray2<gp_Pnt>>& Poles() const;
Standard_EXPORT int UDegree() const;
Standard_EXPORT int VDegree() const;
Standard_EXPORT int NbUKnots() const;
Standard_EXPORT int NbVKnots() const;
//! Knots in the U direction
Standard_EXPORT const occ::handle<NCollection_HArray1<double>>& UKnots() const;
//! Knots in the V direction
Standard_EXPORT const occ::handle<NCollection_HArray1<double>>& VKnots() const;
//! Multiplicities of the knots in the U direction
Standard_EXPORT const occ::handle<NCollection_HArray1<int>>& UMultiplicities() const;
//! Multiplicities of the knots in the V direction
Standard_EXPORT const occ::handle<NCollection_HArray1<int>>& VMultiplicities() const;
Standard_EXPORT bool IsDone() const;
Standard_EXPORT void BuildArray(const int Degree,
const NCollection_Array1<double>& Knots,
const int Continuity,
NCollection_Array1<double>& FlatKnots,
NCollection_Array1<int>& Mults,
NCollection_Array1<double>& Parameters) const;
private:
Standard_EXPORT void BuildArray(const int Degree,
const occ::handle<NCollection_HArray1<double>>& Knots,
const int Continuty,
occ::handle<NCollection_HArray1<double>>& FlatKnots,
occ::handle<NCollection_HArray1<int>>& Mults,
occ::handle<NCollection_HArray1<double>>& Parameters) const;
occ::handle<NCollection_HArray1<double>> myUFlatKnots;
occ::handle<NCollection_HArray1<double>> myVFlatKnots;
occ::handle<NCollection_HArray1<double>> myUKnots;
occ::handle<NCollection_HArray1<double>> myVKnots;
occ::handle<NCollection_HArray1<int>> myUMults;
occ::handle<NCollection_HArray1<int>> myVMults;
occ::handle<NCollection_HArray2<gp_Pnt>> myPoles;
int myUDegree;
int myVDegree;
bool myDone;
NCollection_Array1<double> myUFlatKnots;
NCollection_Array1<double> myVFlatKnots;
NCollection_Array1<double> myUKnots;
NCollection_Array1<double> myVKnots;
NCollection_Array1<int> myUMults;
NCollection_Array1<int> myVMults;
NCollection_Array2<gp_Pnt> myPoles;
int myUDegree;
int myVDegree;
bool myDone;
};
#endif // _Convert_GridPolynomialToPoles_HeaderFile
@@ -18,17 +18,16 @@
#include <gp.hxx>
#include <gp_Dir2d.hxx>
#include <gp_Hypr2d.hxx>
#include <gp_Trsf2d.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Trsf2d.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
#include <Standard_Integer.hxx>
static int TheDegree = 2;
static int MaxNbKnots = 2;
static int MaxNbPoles = 3;
constexpr int TheDegree = 2;
constexpr int MaxNbKnots = 2;
constexpr int MaxNbPoles = 3;
//=================================================================================================
//==================================================================================================
Convert_HyperbolaToBSplineCurve::Convert_HyperbolaToBSplineCurve(const gp_Hypr2d& H,
const double U1,
@@ -36,18 +35,16 @@ Convert_HyperbolaToBSplineCurve::Convert_HyperbolaToBSplineCurve(const gp_Hypr2d
: Convert_ConicToBSplineCurve(MaxNbPoles, MaxNbKnots, TheDegree)
{
Standard_DomainError_Raise_if(std::abs(U2 - U1) < Epsilon(0.), "Convert_ParabolaToBSplineCurve");
Standard_DomainError_Raise_if(std::abs(U2 - U1) < Epsilon(0.), "Convert_HyperbolaToBSplineCurve");
double UF = std::min(U1, U2);
double UL = std::max(U1, U2);
nbPoles = 3;
nbKnots = 2;
isperiodic = false;
knots->ChangeArray1()(1) = UF;
mults->ChangeArray1()(1) = 3;
knots->ChangeArray1()(2) = UL;
mults->ChangeArray1()(2) = 3;
myIsPeriodic = false;
myKnots(1) = UF;
myMults(1) = 3;
myKnots(2) = UL;
myMults(2) = 3;
// construction of hyperbola in the reference xOy.
@@ -62,21 +59,21 @@ Convert_HyperbolaToBSplineCurve::Convert_HyperbolaToBSplineCurve(const gp_Hypr2d
// at points P(UF), P(UL)
// the weight of this pole is equal to : std::cosh((UL-UF)/2)
weights->ChangeArray1()(1) = 1.;
weights->ChangeArray1()(2) = std::cosh((UL - UF) / 2);
weights->ChangeArray1()(3) = 1.;
myWeights(1) = 1.;
myWeights(2) = std::cosh((UL - UF) / 2);
myWeights(3) = 1.;
double delta = std::sinh(UL - UF);
double x = R * (std::sinh(UL) - std::sinh(UF)) / delta;
double y = S * r * (std::cosh(UL) - std::cosh(UF)) / delta;
poles->ChangeArray1()(1) = gp_Pnt2d(R * std::cosh(UF), S * r * std::sinh(UF));
poles->ChangeArray1()(2) = gp_Pnt2d(x, y);
poles->ChangeArray1()(3) = gp_Pnt2d(R * std::cosh(UL), S * r * std::sinh(UL));
double delta = std::sinh(UL - UF);
double x = R * (std::sinh(UL) - std::sinh(UF)) / delta;
double y = S * r * (std::cosh(UL) - std::cosh(UF)) / delta;
myPoles(1) = gp_Pnt2d(R * std::cosh(UF), S * r * std::sinh(UF));
myPoles(2) = gp_Pnt2d(x, y);
myPoles(3) = gp_Pnt2d(R * std::cosh(UL), S * r * std::sinh(UL));
// replace the bspline in the mark of the hyperbola
gp_Trsf2d Trsf;
Trsf.SetTransformation(H.Axis().XAxis(), gp::OX2d());
poles->ChangeArray1()(1).Transform(Trsf);
poles->ChangeArray1()(2).Transform(Trsf);
poles->ChangeArray1()(3).Transform(Trsf);
myPoles(1).Transform(Trsf);
myPoles(2).Transform(Trsf);
myPoles(3).Transform(Trsf);
}
@@ -18,17 +18,16 @@
#include <gp.hxx>
#include <gp_Dir2d.hxx>
#include <gp_Parab2d.hxx>
#include <gp_Trsf2d.hxx>
#include <gp_Pnt2d.hxx>
#include <gp_Trsf2d.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
#include <Standard_Integer.hxx>
static int TheDegree = 2;
static int MaxNbKnots = 2;
static int MaxNbPoles = 3;
constexpr int TheDegree = 2;
constexpr int MaxNbKnots = 2;
constexpr int MaxNbPoles = 3;
//=================================================================================================
//==================================================================================================
Convert_ParabolaToBSplineCurve::Convert_ParabolaToBSplineCurve(const gp_Parab2d& Prb,
const double U1,
@@ -42,31 +41,29 @@ Convert_ParabolaToBSplineCurve::Convert_ParabolaToBSplineCurve(const gp_Parab2d&
double p = Prb.Parameter();
nbPoles = 3;
nbKnots = 2;
isperiodic = false;
knots->ChangeArray1()(1) = UF;
mults->ChangeArray1()(1) = 3;
knots->ChangeArray1()(2) = UL;
mults->ChangeArray1()(2) = 3;
myIsPeriodic = false;
myKnots(1) = UF;
myMults(1) = 3;
myKnots(2) = UL;
myMults(2) = 3;
weights->ChangeArray1()(1) = 1.;
weights->ChangeArray1()(2) = 1.;
weights->ChangeArray1()(3) = 1.;
myWeights(1) = 1.;
myWeights(2) = 1.;
myWeights(3) = 1.;
gp_Dir2d Ox = Prb.Axis().XDirection();
gp_Dir2d Oy = Prb.Axis().YDirection();
double S = (Ox.X() * Oy.Y() - Ox.Y() * Oy.X() > 0.) ? 1 : -1;
// poles expressed in the reference mark
poles->ChangeArray1()(1) = gp_Pnt2d((UF * UF) / (2. * p), S * UF);
poles->ChangeArray1()(2) = gp_Pnt2d((UF * UL) / (2. * p), S * (UF + UL) / 2.);
poles->ChangeArray1()(3) = gp_Pnt2d((UL * UL) / (2. * p), S * UL);
myPoles(1) = gp_Pnt2d((UF * UF) / (2. * p), S * UF);
myPoles(2) = gp_Pnt2d((UF * UL) / (2. * p), S * (UF + UL) / 2.);
myPoles(3) = gp_Pnt2d((UL * UL) / (2. * p), S * UL);
// replace the bspline in the mark of the parabola
gp_Trsf2d Trsf;
Trsf.SetTransformation(Prb.Axis().XAxis(), gp::OX2d());
poles->ChangeArray1()(1).Transform(Trsf);
poles->ChangeArray1()(2).Transform(Trsf);
poles->ChangeArray1()(3).Transform(Trsf);
myPoles(1).Transform(Trsf);
myPoles(2).Transform(Trsf);
myPoles(3).Transform(Trsf);
}
@@ -20,9 +20,11 @@
#include <gp_Pnt2d.hxx>
#include <gp_XY.hxx>
#include <BSplCLib.hxx>
#include <gp.hxx>
#include <Precision.hxx>
#include <BSplCLib.hxx>
#include <array>
static double Locate(const double Angfin,
const NCollection_Array1<gp_Pnt2d>& TPoles,
@@ -59,12 +61,12 @@ static double Locate(const double Angfin,
return (umin + umax) / 2.;
}
void BuildPolynomialCosAndSin(const double UFirst,
const double ULast,
const int num_poles,
occ::handle<NCollection_HArray1<double>>& CosNumeratorPtr,
occ::handle<NCollection_HArray1<double>>& SinNumeratorPtr,
occ::handle<NCollection_HArray1<double>>& DenominatorPtr)
void BuildPolynomialCosAndSin(const double UFirst,
const double ULast,
const int num_poles,
NCollection_Array1<double>& CosNumerator,
NCollection_Array1<double>& SinNumerator,
NCollection_Array1<double>& Denominator)
{
double Delta, locUFirst,
@@ -89,16 +91,14 @@ void BuildPolynomialCosAndSin(const double UFirst,
Delta = ULast - UFirst;
middle = 0.5e0 * Delta;
// coincide the required bisector of the angular sector with
// axis -Ox definition of the circle in Bezier of degree 7 so that
// parametre 1/2 of Bezier was exactly a point of the bissectrice
// Coincide the required bisector of the angular sector with
// axis -Ox. Definition of the circle in Bezier of degree 7 so that
// parameter 1/2 of Bezier is exactly a point of the bisectrix
// of the required angular sector.
//
Angle = middle - M_PI;
//
// Circle of radius 1. See Euclid
//
// Bezier control points for a unit circle (degree-7 polynomial approximation).
// Coefficients from Tiller's algorithm for polynomial cos/sin representation.
NCollection_Array1<gp_Pnt2d> TPoles(1, 8), NewTPoles(1, 8);
TPoles(1).SetCoord(1., 0.);
TPoles(2).SetCoord(1., 1.013854);
@@ -128,12 +128,8 @@ void BuildPolynomialCosAndSin(const double UFirst,
trim_min = 1.0e0 - trim_max;
//
double knot_array[2];
int mults_array[2];
knot_array[0] = 0.0e0;
knot_array[1] = 1.0e0;
mults_array[0] = degree + 1;
mults_array[1] = degree + 1;
std::array<double, 2> knot_array = {0.0e0, 1.0e0};
std::array<int, 2> mults_array = {degree + 1, degree + 1};
NCollection_Array1<double> the_knots(knot_array[0], 1, 2), the_new_knots(knot_array[0], 1, 2);
NCollection_Array1<int> the_mults(mults_array[0], 1, 2), the_new_mults(mults_array[0], 1, 2);
@@ -178,109 +174,8 @@ void BuildPolynomialCosAndSin(const double UFirst,
for (ii = 1; ii <= num_poles; ii++)
{
CosNumeratorPtr->SetValue(ii, NewTPoles(ii).X());
SinNumeratorPtr->SetValue(ii, NewTPoles(ii).Y());
DenominatorPtr->SetValue(ii, 1.);
CosNumerator(ii) = NewTPoles(ii).X();
SinNumerator(ii) = NewTPoles(ii).Y();
Denominator(ii) = 1.;
}
}
/*
void BuildHermitePolynomialCosAndSin
(const double UFirst,
const double ULast,
const int num_poles,
occ::handle<NCollection_HArray1<double>>& CosNumeratorPtr,
occ::handle<NCollection_HArray1<double>>& SinNumeratorPtr,
occ::handle<NCollection_HArray1<double>>& DenominatorPtr)
{
if (num_poles%2 != 0) {
throw Standard_ConstructionError();
}
int ii;
int ordre_deriv = num_poles/2;
double ang = ULast - UFirst;
double Cd = std::cos(UFirst);
double Sd = std::sin(UFirst);
double Cf = std::cos(ULast);
double Sf = std::sin(ULast);
int Degree = num_poles-1;
NCollection_Array1<double> FlatKnots(1,2*num_poles);
NCollection_Array1<double> Parameters(1,num_poles);
NCollection_Array1<int> ContactOrderArray(1,num_poles);
NCollection_Array1<gp_Pnt2d> Poles(1,num_poles);
NCollection_Array1<gp_Pnt2d> TPoles(1,num_poles);
for (ii=1; ii<=num_poles; ii++) {
FlatKnots(ii) = 0.;
FlatKnots(ii+num_poles) = 1.;
}
double coef = 1.;
double xd,yd,xf,yf;
for (ii=1; ii<=ordre_deriv; ii++) {
Parameters(ii) = 0.;
Parameters(ii+ordre_deriv) = 1.;
ContactOrderArray(ii) = ContactOrderArray(num_poles-ii+1) = ii-1;
switch ((ii-1)%4) {
case 0:
{
xd = Cd*coef;
yd = Sd*coef;
xf = Cf*coef;
yf = Sf*coef;
}
break;
case 1:
{
xd = -Sd*coef;
yd = Cd*coef;
xf = -Sf*coef;
yf = Cf*coef;
}
break;
case 2:
{
xd = -Cd*coef;
yd = -Sd*coef;
xf = -Cf*coef;
yf = -Sf*coef;
}
break;
case 3:
{
xd = Sd*coef;
yd = -Cd*coef;
xf = Sf*coef;
yf = -Cf*coef;
}
break;
}
Poles(ii).SetX(xd);
Poles(ii).SetY(yd);
Poles(num_poles-ii+1).SetX(xf);
Poles(num_poles-ii+1).SetY(yf);
coef *= ang;
}
int InversionPb;
BSplCLib::Interpolate(Degree,FlatKnots,Parameters,
ContactOrderArray,Poles,InversionPb);
if (InversionPb !=0) {
throw Standard_ConstructionError();
}
for (ii=1; ii<=num_poles; ii++) {
CosNumeratorPtr->SetValue(ii,Poles(ii).X());
SinNumeratorPtr->SetValue(ii,Poles(ii).Y());
DenominatorPtr->SetValue(ii,1.);
}
}
*/
@@ -18,14 +18,13 @@
#define Convert_PolynomialCosAndSin_HeaderFile
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
#include <Standard_Integer.hxx>
void BuildPolynomialCosAndSin(const double,
const double,
const int,
occ::handle<NCollection_HArray1<double>>&,
occ::handle<NCollection_HArray1<double>>&,
occ::handle<NCollection_HArray1<double>>&);
void BuildPolynomialCosAndSin(const double theUFirst,
const double theULast,
const int theNumPoles,
NCollection_Array1<double>& theCosNumerator,
NCollection_Array1<double>& theSinNumerator,
NCollection_Array1<double>& theDenominator);
#endif
@@ -20,6 +20,8 @@
#include <gp_Trsf.hxx>
#include <Standard_DomainError.hxx>
#include <array>
namespace
{
constexpr int TheUDegree = 2;
@@ -50,8 +52,8 @@ static void ComputePoles(const double R,
int nbVP = 2 * nbVSpans + 1;
double x[MaxNbVPoles];
double z[MaxNbVPoles];
std::array<double, MaxNbVPoles> x;
std::array<double, MaxNbVPoles> z;
x[0] = R * std::cos(V1);
z[0] = R * std::sin(V1);
@@ -106,8 +108,8 @@ Convert_SphereToBSplineSurface::Convert_SphereToBSplineSurface(const gp_Sphere&
|| (V2 > M_PI / 2),
"Convert_SphereToBSplineSurface");
isuperiodic = false;
isvperiodic = false;
myIsUPeriodic = false;
myIsVPeriodic = false;
int i, j;
// construction of the sphere in the reference mark xOy.
@@ -118,29 +120,29 @@ Convert_SphereToBSplineSurface::Convert_SphereToBSplineSurface(const gp_Sphere&
double AlfaU = deltaU / (nbUSpans * 2);
double AlfaV = deltaV / (nbVSpans * 2);
nbUPoles = 2 * nbUSpans + 1;
nbVPoles = 2 * nbVSpans + 1;
nbUKnots = nbUSpans + 1;
nbVKnots = nbVSpans + 1;
myNbUPoles = 2 * nbUSpans + 1;
myNbVPoles = 2 * nbVSpans + 1;
myNbUKnots = nbUSpans + 1;
myNbVKnots = nbVSpans + 1;
double R = Sph.Radius();
ComputePoles(R, U1, U2, V1, V2, poles);
ComputePoles(R, U1, U2, V1, V2, myPoles);
for (i = 1; i <= nbUKnots; i++)
for (i = 1; i <= myNbUKnots; i++)
{
uknots(i) = U1 + (i - 1) * 2 * AlfaU;
umults(i) = 2;
myUKnots(i) = U1 + (i - 1) * 2 * AlfaU;
myUMults(i) = 2;
}
umults(1)++;
umults(nbUKnots)++;
for (i = 1; i <= nbVKnots; i++)
myUMults(1)++;
myUMults(myNbUKnots)++;
for (i = 1; i <= myNbVKnots; i++)
{
vknots(i) = V1 + (i - 1) * 2 * AlfaV;
vmults(i) = 2;
myVKnots(i) = V1 + (i - 1) * 2 * AlfaV;
myVMults(i) = 2;
}
vmults(1)++;
vmults(nbVKnots)++;
myVMults(1)++;
myVMults(myNbVKnots)++;
// Replace the bspline in the reference of the sphere.
// and calculate the weight of the bspline.
@@ -148,24 +150,25 @@ Convert_SphereToBSplineSurface::Convert_SphereToBSplineSurface(const gp_Sphere&
gp_Trsf Trsf;
Trsf.SetTransformation(Sph.Position(), gp::XOY());
for (i = 1; i <= nbUPoles; i++)
for (i = 1; i <= myNbUPoles; i++)
{
if (i % 2 == 0)
W1 = std::cos(AlfaU);
else
W1 = 1.;
for (j = 1; j <= nbVPoles; j++)
for (j = 1; j <= myNbVPoles; j++)
{
if (j % 2 == 0)
W2 = std::cos(AlfaV);
else
W2 = 1.;
weights(i, j) = W1 * W2;
poles(i, j).Transform(Trsf);
myWeights(i, j) = W1 * W2;
myPoles(i, j).Transform(Trsf);
}
}
Finalize();
}
//=================================================================================================
@@ -190,68 +193,68 @@ Convert_SphereToBSplineSurface::Convert_SphereToBSplineSurface(const gp_Sphere&
int i, j;
double deltaU, deltaV;
isuperiodic = !UTrim;
isvperiodic = false;
myIsUPeriodic = !UTrim;
myIsVPeriodic = false;
double R = Sph.Radius();
double W1, W2, CosU, CosV;
if (isuperiodic)
if (myIsUPeriodic)
{
ComputePoles(R, 0., 2. * M_PI, Param1, Param2, poles);
ComputePoles(R, 0., 2. * M_PI, Param1, Param2, myPoles);
nbUPoles = 6;
nbUKnots = 4;
myNbUPoles = 6;
myNbUKnots = 4;
deltaV = Param2 - Param1;
int nbVSpans = (int)std::trunc(1.2 * deltaV / M_PI) + 1;
double AlfaV = deltaV / (nbVSpans * 2);
nbVPoles = 2 * nbVSpans + 1;
nbVKnots = nbVSpans + 1;
myNbVPoles = 2 * nbVSpans + 1;
myNbVKnots = nbVSpans + 1;
for (i = 1; i <= nbUKnots; i++)
for (i = 1; i <= myNbUKnots; i++)
{
uknots(i) = (i - 1) * 2. * M_PI / 3.;
umults(i) = 2;
myUKnots(i) = (i - 1) * 2. * M_PI / 3.;
myUMults(i) = 2;
}
for (i = 1; i <= nbVKnots; i++)
for (i = 1; i <= myNbVKnots; i++)
{
vknots(i) = Param1 + (i - 1) * 2 * AlfaV;
vmults(i) = 2;
myVKnots(i) = Param1 + (i - 1) * 2 * AlfaV;
myVMults(i) = 2;
}
vmults(1)++;
vmults(nbVKnots)++;
myVMults(1)++;
myVMults(myNbVKnots)++;
CosU = 0.5; // = std::cos(pi /3)
CosV = std::cos(AlfaV);
}
else
{
ComputePoles(R, Param1, Param2, -M_PI / 2., M_PI / 2., poles);
ComputePoles(R, Param1, Param2, -M_PI / 2., M_PI / 2., myPoles);
nbVPoles = 5;
nbVKnots = 3;
myNbVPoles = 5;
myNbVKnots = 3;
deltaU = Param2 - Param1;
int nbUSpans = (int)std::trunc(1.2 * deltaU / M_PI) + 1;
double AlfaU = deltaU / (nbUSpans * 2);
nbUPoles = 2 * nbUSpans + 1;
nbUKnots = nbUSpans + 1;
myNbUPoles = 2 * nbUSpans + 1;
myNbUKnots = nbUSpans + 1;
vknots(1) = -M_PI / 2.;
vmults(1) = 3;
vknots(2) = 0.;
vmults(2) = 2;
vknots(3) = M_PI / 2.;
vmults(3) = 3;
for (i = 1; i <= nbUKnots; i++)
myVKnots(1) = -M_PI / 2.;
myVMults(1) = 3;
myVKnots(2) = 0.;
myVMults(2) = 2;
myVKnots(3) = M_PI / 2.;
myVMults(3) = 3;
for (i = 1; i <= myNbUKnots; i++)
{
uknots(i) = Param1 + (i - 1) * 2 * AlfaU;
umults(i) = 2;
myUKnots(i) = Param1 + (i - 1) * 2 * AlfaU;
myUMults(i) = 2;
}
umults(1)++;
umults(nbUKnots)++;
myUMults(1)++;
myUMults(myNbUKnots)++;
CosV = 0.5; // = std::cos(pi /3)
CosU = std::cos(AlfaU);
@@ -262,24 +265,25 @@ Convert_SphereToBSplineSurface::Convert_SphereToBSplineSurface(const gp_Sphere&
gp_Trsf Trsf;
Trsf.SetTransformation(Sph.Position(), gp::XOY());
for (i = 1; i <= nbUPoles; i++)
for (i = 1; i <= myNbUPoles; i++)
{
if (i % 2 == 0)
W1 = CosU;
else
W1 = 1.;
for (j = 1; j <= nbVPoles; j++)
for (j = 1; j <= myNbVPoles; j++)
{
if (j % 2 == 0)
W2 = CosV;
else
W2 = 1.;
weights(i, j) = W1 * W2;
poles(i, j).Transform(Trsf);
myWeights(i, j) = W1 * W2;
myPoles(i, j).Transform(Trsf);
}
}
Finalize();
}
//=================================================================================================
@@ -292,58 +296,59 @@ Convert_SphereToBSplineSurface::Convert_SphereToBSplineSurface(const gp_Sphere&
TheUDegree,
TheVDegree)
{
isuperiodic = true;
isvperiodic = false;
myIsUPeriodic = true;
myIsVPeriodic = false;
double W1, W2;
int i, j;
nbUPoles = 6;
nbVPoles = 5;
nbUKnots = 4;
nbVKnots = 3;
myNbUPoles = 6;
myNbVPoles = 5;
myNbUKnots = 4;
myNbVKnots = 3;
// Construction of the sphere in the reference mark xOy.
double R = Sph.Radius();
ComputePoles(R, 0., 2. * M_PI, -M_PI / 2., M_PI / 2., poles);
ComputePoles(R, 0., 2. * M_PI, -M_PI / 2., M_PI / 2., myPoles);
uknots(1) = 0.;
uknots(2) = 2. * M_PI / 3.;
uknots(3) = 4. * M_PI / 3.;
uknots(4) = 2. * M_PI;
vknots(1) = -M_PI / 2.;
vknots(2) = 0.;
vknots(3) = M_PI / 2.;
myUKnots(1) = 0.;
myUKnots(2) = 2. * M_PI / 3.;
myUKnots(3) = 4. * M_PI / 3.;
myUKnots(4) = 2. * M_PI;
myVKnots(1) = -M_PI / 2.;
myVKnots(2) = 0.;
myVKnots(3) = M_PI / 2.;
for (i = 1; i <= 4; i++)
{
umults(i) = 2;
myUMults(i) = 2;
}
vmults(1) = vmults(3) = 3;
vmults(2) = 2;
myVMults(1) = myVMults(3) = 3;
myVMults(2) = 2;
// Replace the bspline in the mark of the sphere.
// and calculate the weight of the bspline.
gp_Trsf Trsf;
Trsf.SetTransformation(Sph.Position(), gp::XOY());
for (i = 1; i <= nbUPoles; i++)
for (i = 1; i <= myNbUPoles; i++)
{
if (i % 2 == 0)
W1 = 0.5;
else
W1 = 1.;
for (j = 1; j <= nbVPoles; j++)
for (j = 1; j <= myNbVPoles; j++)
{
if (j % 2 == 0)
W2 = std::sqrt(2.) / 2.;
else
W2 = 1.;
weights(i, j) = W1 * W2;
poles(i, j).Transform(Trsf);
myWeights(i, j) = W1 * W2;
myPoles(i, j).Transform(Trsf);
}
}
Finalize();
}
@@ -20,6 +20,8 @@
#include <gp_Trsf.hxx>
#include <Standard_DomainError.hxx>
#include <array>
namespace
{
constexpr int TheUDegree = 2;
@@ -51,8 +53,8 @@ static void ComputePoles(const double R,
int nbVP = 2 * nbVSpans + 1;
double x[MaxNbVPoles];
double z[MaxNbVPoles];
std::array<double, MaxNbVPoles> x;
std::array<double, MaxNbVPoles> z;
x[0] = R + r * std::cos(V1);
z[0] = r * std::sin(V1);
@@ -107,8 +109,8 @@ Convert_TorusToBSplineSurface::Convert_TorusToBSplineSurface(const gp_Torus& T,
|| (deltaV < 0.),
"Convert_TorusToBSplineSurface");
isuperiodic = false;
isvperiodic = false;
myIsUPeriodic = false;
myIsVPeriodic = false;
int i, j;
// construction of the torus in the reference mark xOy.
@@ -119,30 +121,30 @@ Convert_TorusToBSplineSurface::Convert_TorusToBSplineSurface(const gp_Torus& T,
double AlfaU = deltaU / (nbUSpans * 2);
double AlfaV = deltaV / (nbVSpans * 2);
nbUPoles = 2 * nbUSpans + 1;
nbVPoles = 2 * nbVSpans + 1;
nbUKnots = nbUSpans + 1;
nbVKnots = nbVSpans + 1;
myNbUPoles = 2 * nbUSpans + 1;
myNbVPoles = 2 * nbVSpans + 1;
myNbUKnots = nbUSpans + 1;
myNbVKnots = nbVSpans + 1;
double R = T.MajorRadius();
double r = T.MinorRadius();
ComputePoles(R, r, U1, U2, V1, V2, poles);
ComputePoles(R, r, U1, U2, V1, V2, myPoles);
for (i = 1; i <= nbUKnots; i++)
for (i = 1; i <= myNbUKnots; i++)
{
uknots(i) = U1 + (i - 1) * 2 * AlfaU;
umults(i) = 2;
myUKnots(i) = U1 + (i - 1) * 2 * AlfaU;
myUMults(i) = 2;
}
umults(1)++;
umults(nbUKnots)++;
for (i = 1; i <= nbVKnots; i++)
myUMults(1)++;
myUMults(myNbUKnots)++;
for (i = 1; i <= myNbVKnots; i++)
{
vknots(i) = V1 + (i - 1) * 2 * AlfaV;
vmults(i) = 2;
myVKnots(i) = V1 + (i - 1) * 2 * AlfaV;
myVMults(i) = 2;
}
vmults(1)++;
vmults(nbVKnots)++;
myVMults(1)++;
myVMults(myNbVKnots)++;
// Replace the bspline in the reference of the torus.
// and calculate the weight of the bspline.
@@ -150,24 +152,25 @@ Convert_TorusToBSplineSurface::Convert_TorusToBSplineSurface(const gp_Torus& T,
gp_Trsf Trsf;
Trsf.SetTransformation(T.Position(), gp::XOY());
for (i = 1; i <= nbUPoles; i++)
for (i = 1; i <= myNbUPoles; i++)
{
if (i % 2 == 0)
W1 = std::cos(AlfaU);
else
W1 = 1.;
for (j = 1; j <= nbVPoles; j++)
for (j = 1; j <= myNbVPoles; j++)
{
if (j % 2 == 0)
W2 = std::cos(AlfaV);
else
W2 = 1.;
weights(i, j) = W1 * W2;
poles(i, j).Transform(Trsf);
myWeights(i, j) = W1 * W2;
myPoles(i, j).Transform(Trsf);
}
}
Finalize();
}
//=================================================================================================
@@ -192,68 +195,68 @@ Convert_TorusToBSplineSurface::Convert_TorusToBSplineSurface(const gp_Torus& T,
int i, j;
double deltaU, deltaV;
isuperiodic = !UTrim;
isvperiodic = UTrim;
myIsUPeriodic = !UTrim;
myIsVPeriodic = UTrim;
double R = T.MajorRadius();
double r = T.MinorRadius();
double W1, W2, CosU, CosV;
if (isuperiodic)
if (myIsUPeriodic)
{
ComputePoles(R, r, 0, 2. * M_PI, Param1, Param2, poles);
ComputePoles(R, r, 0, 2. * M_PI, Param1, Param2, myPoles);
nbUPoles = 6;
nbUKnots = 4;
myNbUPoles = 6;
myNbUKnots = 4;
deltaV = Param2 - Param1;
int nbVSpans = (int)std::trunc(1.2 * deltaV / M_PI) + 1;
double AlfaV = deltaV / (nbVSpans * 2);
nbVPoles = 2 * nbVSpans + 1;
nbVKnots = nbVSpans + 1;
myNbVPoles = 2 * nbVSpans + 1;
myNbVKnots = nbVSpans + 1;
for (i = 1; i <= nbUKnots; i++)
for (i = 1; i <= myNbUKnots; i++)
{
uknots(i) = (i - 1) * 2. * M_PI / 3.;
umults(i) = 2;
myUKnots(i) = (i - 1) * 2. * M_PI / 3.;
myUMults(i) = 2;
}
for (i = 1; i <= nbVKnots; i++)
for (i = 1; i <= myNbVKnots; i++)
{
vknots(i) = Param1 + (i - 1) * 2 * AlfaV;
vmults(i) = 2;
myVKnots(i) = Param1 + (i - 1) * 2 * AlfaV;
myVMults(i) = 2;
}
vmults(1)++;
vmults(nbVKnots)++;
myVMults(1)++;
myVMults(myNbVKnots)++;
CosU = 0.5; // = std::cos(pi /3)
CosV = std::cos(AlfaV);
}
else
{
ComputePoles(R, r, Param1, Param2, 0., 2. * M_PI, poles);
ComputePoles(R, r, Param1, Param2, 0., 2. * M_PI, myPoles);
nbVPoles = 6;
nbVKnots = 4;
myNbVPoles = 6;
myNbVKnots = 4;
deltaU = Param2 - Param1;
int nbUSpans = (int)std::trunc(1.2 * deltaU / M_PI) + 1;
double AlfaU = deltaU / (nbUSpans * 2);
nbUPoles = 2 * nbUSpans + 1;
nbUKnots = nbUSpans + 1;
myNbUPoles = 2 * nbUSpans + 1;
myNbUKnots = nbUSpans + 1;
for (i = 1; i <= nbVKnots; i++)
for (i = 1; i <= myNbVKnots; i++)
{
vknots(i) = (i - 1) * 2. * M_PI / 3.;
vmults(i) = 2;
myVKnots(i) = (i - 1) * 2. * M_PI / 3.;
myVMults(i) = 2;
}
for (i = 1; i <= nbUKnots; i++)
for (i = 1; i <= myNbUKnots; i++)
{
uknots(i) = Param1 + (i - 1) * 2 * AlfaU;
umults(i) = 2;
myUKnots(i) = Param1 + (i - 1) * 2 * AlfaU;
myUMults(i) = 2;
}
umults(1)++;
umults(nbUKnots)++;
myUMults(1)++;
myUMults(myNbUKnots)++;
CosV = 0.5; // = std::cos(pi /3)
CosU = std::cos(AlfaU);
@@ -264,24 +267,25 @@ Convert_TorusToBSplineSurface::Convert_TorusToBSplineSurface(const gp_Torus& T,
gp_Trsf Trsf;
Trsf.SetTransformation(T.Position(), gp::XOY());
for (i = 1; i <= nbUPoles; i++)
for (i = 1; i <= myNbUPoles; i++)
{
if (i % 2 == 0)
W1 = CosU;
else
W1 = 1.;
for (j = 1; j <= nbVPoles; j++)
for (j = 1; j <= myNbVPoles; j++)
{
if (j % 2 == 0)
W2 = CosV;
else
W2 = 1.;
weights(i, j) = W1 * W2;
poles(i, j).Transform(Trsf);
myWeights(i, j) = W1 * W2;
myPoles(i, j).Transform(Trsf);
}
}
Finalize();
}
//=================================================================================================
@@ -294,31 +298,31 @@ Convert_TorusToBSplineSurface::Convert_TorusToBSplineSurface(const gp_Torus& T)
TheUDegree,
TheVDegree)
{
isuperiodic = true;
isvperiodic = true;
myIsUPeriodic = true;
myIsVPeriodic = true;
double W1, W2;
int i, j;
nbUPoles = 6;
nbVPoles = 6;
nbUKnots = 4;
nbVKnots = 4;
myNbUPoles = 6;
myNbVPoles = 6;
myNbUKnots = 4;
myNbVKnots = 4;
// Construction of the Torus in the reference mark xOy.
double R = T.MajorRadius();
double r = T.MinorRadius();
ComputePoles(R, r, 0., 2. * M_PI, 0., 2. * M_PI, poles);
ComputePoles(R, r, 0., 2. * M_PI, 0., 2. * M_PI, myPoles);
uknots(1) = vknots(1) = 0.;
uknots(2) = vknots(2) = 2. * M_PI / 3.;
uknots(3) = vknots(3) = 4. * M_PI / 3.;
uknots(4) = vknots(4) = 2. * M_PI;
myUKnots(1) = myVKnots(1) = 0.;
myUKnots(2) = myVKnots(2) = 2. * M_PI / 3.;
myUKnots(3) = myVKnots(3) = 4. * M_PI / 3.;
myUKnots(4) = myVKnots(4) = 2. * M_PI;
for (i = 1; i <= 4; i++)
{
umults(i) = vmults(i) = 2;
myUMults(i) = myVMults(i) = 2;
}
// Replace the bspline in the mark of the torus.
@@ -326,22 +330,23 @@ Convert_TorusToBSplineSurface::Convert_TorusToBSplineSurface(const gp_Torus& T)
gp_Trsf Trsf;
Trsf.SetTransformation(T.Position(), gp::XOY());
for (i = 1; i <= nbUPoles; i++)
for (i = 1; i <= myNbUPoles; i++)
{
if (i % 2 == 0)
W1 = 0.5;
else
W1 = 1.;
for (j = 1; j <= nbVPoles; j++)
for (j = 1; j <= myNbVPoles; j++)
{
if (j % 2 == 0)
W2 = 0.5;
else
W2 = 1.;
weights(i, j) = W1 * W2;
poles(i, j).Transform(Trsf);
myWeights(i, j) = W1 * W2;
myPoles(i, j).Transform(Trsf);
}
}
Finalize();
}
@@ -8,6 +8,7 @@ set(OCCT_Convert_FILES
Convert_CompBezierCurves2dToBSplineCurve2d.hxx
Convert_CompBezierCurvesToBSplineCurve.cxx
Convert_CompBezierCurvesToBSplineCurve.hxx
Convert_CompBezierCurvesToBSplineCurveBase.hxx
Convert_CompPolynomialToPoles.cxx
Convert_CompPolynomialToPoles.hxx
Convert_ConeToBSplineSurface.cxx
@@ -0,0 +1,163 @@
// Copyright (c) 2026 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <gtest/gtest.h>
#include <Convert_CircleToBSplineCurve.hxx>
#include <Convert_ParameterisationType.hxx>
#include <gp_Ax2d.hxx>
#include <gp_Circ2d.hxx>
#include <gp_Dir2d.hxx>
#include <gp_Pnt2d.hxx>
TEST(Convert_CircleToBSplineCurveTest, FullCircle_TgtThetaOver2)
{
const gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0);
const Convert_CircleToBSplineCurve aConv(aCirc, Convert_TgtThetaOver2);
EXPECT_EQ(aConv.Degree(), 2);
EXPECT_TRUE(aConv.IsPeriodic());
EXPECT_GT(aConv.NbPoles(), 0);
EXPECT_GT(aConv.NbKnots(), 0);
// Verify all weights are positive
const NCollection_Array1<double>& aWeights = aConv.Weights();
for (int i = 1; i <= aConv.NbPoles(); ++i)
{
EXPECT_GT(aWeights(i), 0.0) << "Weight at index " << i << " is not positive";
}
// Verify knots are monotonically increasing
const NCollection_Array1<double>& aKnots = aConv.Knots();
for (int i = 2; i <= aConv.NbKnots(); ++i)
{
EXPECT_GT(aKnots(i), aKnots(i - 1)) << "Knots not monotonically increasing at index " << i;
}
}
TEST(Convert_CircleToBSplineCurveTest, FullCircle_RationalC1)
{
const gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(1.0, 2.0), gp_Dir2d(1.0, 0.0)), 3.0);
const Convert_CircleToBSplineCurve aConv(aCirc, Convert_RationalC1);
EXPECT_TRUE(aConv.IsPeriodic());
EXPECT_GT(aConv.NbPoles(), 0);
// Verify all weights are positive
const NCollection_Array1<double>& aWeights = aConv.Weights();
for (int i = 1; i <= aConv.NbPoles(); ++i)
{
EXPECT_GT(aWeights(i), 0.0) << "Weight at index " << i << " is not positive";
}
// Verify knots are monotonically increasing
const NCollection_Array1<double>& aKnots = aConv.Knots();
for (int i = 2; i <= aConv.NbKnots(); ++i)
{
EXPECT_GT(aKnots(i), aKnots(i - 1)) << "Knots not monotonically increasing at index " << i;
}
}
TEST(Convert_CircleToBSplineCurveTest, Arc_TgtThetaOver2)
{
const gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 1.0);
const double aU1 = M_PI / 6.0;
const double aU2 = 5.0 * M_PI / 3.0;
const Convert_CircleToBSplineCurve aConv(aCirc, aU1, aU2, Convert_TgtThetaOver2);
EXPECT_FALSE(aConv.IsPeriodic());
EXPECT_EQ(aConv.Degree(), 2);
EXPECT_GT(aConv.NbPoles(), 0);
// Verify first pole matches conic point at U1
const NCollection_Array1<gp_Pnt2d>& aPoles = aConv.Poles();
const double aR = aCirc.Radius();
const gp_Pnt2d aCenter = aCirc.Location();
const gp_Dir2d aXDir = aCirc.XAxis().Direction();
const gp_Dir2d aYDir = aCirc.YAxis().Direction();
const double aFirstX = aCenter.X() + aR * (std::cos(aU1) * aXDir.X() + std::sin(aU1) * aYDir.X());
const double aFirstY = aCenter.Y() + aR * (std::cos(aU1) * aXDir.Y() + std::sin(aU1) * aYDir.Y());
EXPECT_NEAR(aPoles(1).X(), aFirstX, 1.0e-10);
EXPECT_NEAR(aPoles(1).Y(), aFirstY, 1.0e-10);
// Verify last pole matches conic point at U2
const double aLastX = aCenter.X() + aR * (std::cos(aU2) * aXDir.X() + std::sin(aU2) * aYDir.X());
const double aLastY = aCenter.Y() + aR * (std::cos(aU2) * aXDir.Y() + std::sin(aU2) * aYDir.Y());
EXPECT_NEAR(aPoles(aConv.NbPoles()).X(), aLastX, 1.0e-10);
EXPECT_NEAR(aPoles(aConv.NbPoles()).Y(), aLastY, 1.0e-10);
// Verify all weights are positive
const NCollection_Array1<double>& aWeights = aConv.Weights();
for (int i = 1; i <= aConv.NbPoles(); ++i)
{
EXPECT_GT(aWeights(i), 0.0) << "Weight at index " << i << " is not positive";
}
// Verify knots are monotonically increasing
const NCollection_Array1<double>& aKnots = aConv.Knots();
for (int i = 2; i <= aConv.NbKnots(); ++i)
{
EXPECT_GT(aKnots(i), aKnots(i - 1)) << "Knots not monotonically increasing at index " << i;
}
}
TEST(Convert_CircleToBSplineCurveTest, Arc_QuasiAngular)
{
const gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 2.0);
const double aU1 = 0.0;
const double aU2 = M_PI;
const Convert_CircleToBSplineCurve aConv(aCirc, aU1, aU2, Convert_QuasiAngular);
EXPECT_FALSE(aConv.IsPeriodic());
EXPECT_EQ(aConv.Degree(), 6);
EXPECT_GT(aConv.NbPoles(), 0);
// Verify all weights are positive
const NCollection_Array1<double>& aWeights = aConv.Weights();
for (int i = 1; i <= aConv.NbPoles(); ++i)
{
EXPECT_GT(aWeights(i), 0.0) << "Weight at index " << i << " is not positive";
}
// Verify knots are monotonically increasing
const NCollection_Array1<double>& aKnots = aConv.Knots();
for (int i = 2; i <= aConv.NbKnots(); ++i)
{
EXPECT_GT(aKnots(i), aKnots(i - 1)) << "Knots not monotonically increasing at index " << i;
}
}
TEST(Convert_CircleToBSplineCurveTest, Arc_Polynomial)
{
const gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 1.0);
const double aU1 = 0.0;
const double aU2 = M_PI * 0.5;
const Convert_CircleToBSplineCurve aConv(aCirc, aU1, aU2, Convert_Polynomial);
EXPECT_FALSE(aConv.IsPeriodic());
EXPECT_EQ(aConv.Degree(), 7);
EXPECT_EQ(aConv.NbPoles(), 8);
}
TEST(Convert_CircleToBSplineCurveTest, WeightsArePositive)
{
const gp_Circ2d aCirc(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 1.0);
const Convert_CircleToBSplineCurve aConv(aCirc, Convert_TgtThetaOver2);
const NCollection_Array1<double>& aWeights = aConv.Weights();
for (int i = 1; i <= aConv.NbPoles(); ++i)
{
EXPECT_GT(aWeights(i), 0.0);
}
}
@@ -0,0 +1,197 @@
// Copyright (c) 2026 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <gtest/gtest.h>
#include <Convert_CompBezierCurvesToBSplineCurve.hxx>
#include <Convert_CompBezierCurves2dToBSplineCurve2d.hxx>
#include <gp_Pnt.hxx>
#include <gp_Pnt2d.hxx>
#include <NCollection_Array1.hxx>
TEST(Convert_CompBezierCurvesToBSplineCurveTest, SingleLinearBezier)
{
Convert_CompBezierCurvesToBSplineCurve aConv;
NCollection_Array1<gp_Pnt> aPoles(1, 2);
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
aPoles(2) = gp_Pnt(1.0, 1.0, 0.0);
aConv.AddCurve(aPoles);
aConv.Perform();
EXPECT_GE(aConv.Degree(), 1);
EXPECT_EQ(aConv.NbPoles(), 2);
EXPECT_EQ(aConv.NbKnots(), 2);
NCollection_Array1<gp_Pnt> aResPoles(1, aConv.NbPoles());
aConv.Poles(aResPoles);
EXPECT_NEAR(aResPoles(1).X(), 0.0, 1.0e-15);
EXPECT_NEAR(aResPoles(2).X(), 1.0, 1.0e-15);
}
TEST(Convert_CompBezierCurvesToBSplineCurveTest, SingleCubicBezier)
{
Convert_CompBezierCurvesToBSplineCurve aConv;
NCollection_Array1<gp_Pnt> aPoles(1, 4);
aPoles(1) = gp_Pnt(0.0, 0.0, 0.0);
aPoles(2) = gp_Pnt(1.0, 2.0, 0.0);
aPoles(3) = gp_Pnt(3.0, 2.0, 0.0);
aPoles(4) = gp_Pnt(4.0, 0.0, 0.0);
aConv.AddCurve(aPoles);
aConv.Perform();
EXPECT_EQ(aConv.Degree(), 3);
EXPECT_EQ(aConv.NbPoles(), 4);
EXPECT_EQ(aConv.NbKnots(), 2);
}
TEST(Convert_CompBezierCurvesToBSplineCurveTest, TwoAdjacentBeziers_C0)
{
Convert_CompBezierCurvesToBSplineCurve aConv;
// First linear segment
NCollection_Array1<gp_Pnt> aPoles1(1, 2);
aPoles1(1) = gp_Pnt(0.0, 0.0, 0.0);
aPoles1(2) = gp_Pnt(1.0, 1.0, 0.0);
// Second linear segment, adjacent but not tangent
NCollection_Array1<gp_Pnt> aPoles2(1, 2);
aPoles2(1) = gp_Pnt(1.0, 1.0, 0.0);
aPoles2(2) = gp_Pnt(2.0, 0.0, 0.0);
aConv.AddCurve(aPoles1);
aConv.AddCurve(aPoles2);
aConv.Perform();
EXPECT_GE(aConv.Degree(), 1);
EXPECT_EQ(aConv.NbKnots(), 3);
NCollection_Array1<gp_Pnt> aResPoles(1, aConv.NbPoles());
NCollection_Array1<double> aKnots(1, aConv.NbKnots());
NCollection_Array1<int> aMults(1, aConv.NbKnots());
aConv.Poles(aResPoles);
aConv.KnotsAndMults(aKnots, aMults);
// First and last knot multiplicities should be degree+1
EXPECT_EQ(aMults(1), aConv.Degree() + 1);
EXPECT_EQ(aMults(aConv.NbKnots()), aConv.Degree() + 1);
}
TEST(Convert_CompBezierCurvesToBSplineCurveTest, TwoAdjacentBeziers_C1)
{
Convert_CompBezierCurvesToBSplineCurve aConv;
// Two cubic Beziers with parallel tangent at junction
NCollection_Array1<gp_Pnt> aPoles1(1, 4);
aPoles1(1) = gp_Pnt(0.0, 0.0, 0.0);
aPoles1(2) = gp_Pnt(1.0, 1.0, 0.0);
aPoles1(3) = gp_Pnt(2.0, 1.0, 0.0);
aPoles1(4) = gp_Pnt(3.0, 0.0, 0.0);
NCollection_Array1<gp_Pnt> aPoles2(1, 4);
aPoles2(1) = gp_Pnt(3.0, 0.0, 0.0);
aPoles2(2) = gp_Pnt(4.0, -1.0, 0.0);
aPoles2(3) = gp_Pnt(5.0, -1.0, 0.0);
aPoles2(4) = gp_Pnt(6.0, 0.0, 0.0);
aConv.AddCurve(aPoles1);
aConv.AddCurve(aPoles2);
aConv.Perform();
EXPECT_EQ(aConv.Degree(), 3);
EXPECT_EQ(aConv.NbKnots(), 3);
// Check that junction has multiplicity Degree-1 (C1)
NCollection_Array1<int> aMults(1, aConv.NbKnots());
NCollection_Array1<double> aKnots(1, aConv.NbKnots());
aConv.KnotsAndMults(aKnots, aMults);
EXPECT_EQ(aMults(2), aConv.Degree() - 1);
}
TEST(Convert_CompBezierCurvesToBSplineCurveTest, MixedDegreeBeziers)
{
Convert_CompBezierCurvesToBSplineCurve aConv;
// Linear segment
NCollection_Array1<gp_Pnt> aPoles1(1, 2);
aPoles1(1) = gp_Pnt(0.0, 0.0, 0.0);
aPoles1(2) = gp_Pnt(1.0, 0.0, 0.0);
// Cubic segment
NCollection_Array1<gp_Pnt> aPoles2(1, 4);
aPoles2(1) = gp_Pnt(1.0, 0.0, 0.0);
aPoles2(2) = gp_Pnt(2.0, 1.0, 0.0);
aPoles2(3) = gp_Pnt(3.0, 1.0, 0.0);
aPoles2(4) = gp_Pnt(4.0, 0.0, 0.0);
aConv.AddCurve(aPoles1);
aConv.AddCurve(aPoles2);
aConv.Perform();
// Degree should be raised to the maximum
EXPECT_EQ(aConv.Degree(), 3);
}
// 2D variant tests
TEST(Convert_CompBezierCurves2dToBSplineCurve2dTest, SingleLinear2d)
{
Convert_CompBezierCurves2dToBSplineCurve2d aConv;
NCollection_Array1<gp_Pnt2d> aPoles(1, 2);
aPoles(1) = gp_Pnt2d(0.0, 0.0);
aPoles(2) = gp_Pnt2d(1.0, 1.0);
aConv.AddCurve(aPoles);
aConv.Perform();
EXPECT_GE(aConv.Degree(), 1);
EXPECT_EQ(aConv.NbPoles(), 2);
EXPECT_EQ(aConv.NbKnots(), 2);
NCollection_Array1<gp_Pnt2d> aResPoles(1, aConv.NbPoles());
aConv.Poles(aResPoles);
EXPECT_NEAR(aResPoles(1).X(), 0.0, 1.0e-15);
EXPECT_NEAR(aResPoles(2).X(), 1.0, 1.0e-15);
}
TEST(Convert_CompBezierCurves2dToBSplineCurve2dTest, TwoAdjacent2d_C1)
{
Convert_CompBezierCurves2dToBSplineCurve2d aConv;
NCollection_Array1<gp_Pnt2d> aPoles1(1, 4);
aPoles1(1) = gp_Pnt2d(0.0, 0.0);
aPoles1(2) = gp_Pnt2d(1.0, 1.0);
aPoles1(3) = gp_Pnt2d(2.0, 1.0);
aPoles1(4) = gp_Pnt2d(3.0, 0.0);
NCollection_Array1<gp_Pnt2d> aPoles2(1, 4);
aPoles2(1) = gp_Pnt2d(3.0, 0.0);
aPoles2(2) = gp_Pnt2d(4.0, -1.0);
aPoles2(3) = gp_Pnt2d(5.0, -1.0);
aPoles2(4) = gp_Pnt2d(6.0, 0.0);
aConv.AddCurve(aPoles1);
aConv.AddCurve(aPoles2);
aConv.Perform();
EXPECT_EQ(aConv.Degree(), 3);
EXPECT_EQ(aConv.NbKnots(), 3);
NCollection_Array1<int> aMults(1, aConv.NbKnots());
NCollection_Array1<double> aKnots(1, aConv.NbKnots());
aConv.KnotsAndMults(aKnots, aMults);
EXPECT_EQ(aMults(2), aConv.Degree() - 1);
}
@@ -0,0 +1,153 @@
// Copyright (c) 2026 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <gtest/gtest.h>
#include <Convert_CompPolynomialToPoles.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_Array2.hxx>
#include <NCollection_HArray1.hxx>
#include <NCollection_HArray2.hxx>
TEST(Convert_CompPolynomialToPolesTest, SingleLinearPolynomial)
{
// Convert f(x) = 2*x + 1 on [-1,1] to BSpline
// Polynomial domain [-1,1], True interval [-1,1]
const int aDim = 1;
const int aMaxDeg = 1;
const int aDeg = 1;
NCollection_Array1<double> aCoeffs(1, 2);
aCoeffs(1) = 1.0; // constant term
aCoeffs(2) = 2.0; // linear term
NCollection_Array1<double> aPolyIntervals(1, 2);
aPolyIntervals(1) = -1.0;
aPolyIntervals(2) = 1.0;
NCollection_Array1<double> aTrueIntervals(1, 2);
aTrueIntervals(1) = -1.0;
aTrueIntervals(2) = 1.0;
Convert_CompPolynomialToPoles aConv(aDim, aMaxDeg, aDeg, aCoeffs, aPolyIntervals, aTrueIntervals);
EXPECT_TRUE(aConv.IsDone());
EXPECT_EQ(aConv.Degree(), 1);
EXPECT_EQ(aConv.NbKnots(), 2);
EXPECT_GT(aConv.NbPoles(), 0);
}
TEST(Convert_CompPolynomialToPolesTest, SingleQuadraticPolynomial)
{
// Convert f(x) = x^2 on [0,1] to BSpline
const int aDim = 1;
const int aMaxDeg = 2;
const int aDeg = 2;
NCollection_Array1<double> aCoeffs(1, 3);
aCoeffs(1) = 0.0; // x^0
aCoeffs(2) = 0.0; // x^1
aCoeffs(3) = 1.0; // x^2
NCollection_Array1<double> aPolyIntervals(1, 2);
aPolyIntervals(1) = 0.0;
aPolyIntervals(2) = 1.0;
NCollection_Array1<double> aTrueIntervals(1, 2);
aTrueIntervals(1) = 0.0;
aTrueIntervals(2) = 1.0;
Convert_CompPolynomialToPoles aConv(aDim, aMaxDeg, aDeg, aCoeffs, aPolyIntervals, aTrueIntervals);
EXPECT_TRUE(aConv.IsDone());
EXPECT_EQ(aConv.Degree(), 2);
}
TEST(Convert_CompPolynomialToPolesTest, TwoSpansUniformContinuity)
{
// Two linear polynomials with C0 continuity
const int aNumCurves = 2;
const int aContinuity = 0;
const int aDim = 1;
const int aMaxDeg = 1;
occ::handle<NCollection_HArray1<int>> aNumCoeff = new NCollection_HArray1<int>(1, 2);
aNumCoeff->SetValue(1, 2); // linear = 2 coefficients
aNumCoeff->SetValue(2, 2);
// Coefficients: [curve1: c0, c1] [curve2: c0, c1]
occ::handle<NCollection_HArray1<double>> aCoeffs = new NCollection_HArray1<double>(1, 4);
aCoeffs->SetValue(1, 0.0);
aCoeffs->SetValue(2, 1.0);
aCoeffs->SetValue(3, 1.0);
aCoeffs->SetValue(4, -1.0);
occ::handle<NCollection_HArray2<double>> aPolyIntervals =
new NCollection_HArray2<double>(1, 2, 1, 2);
aPolyIntervals->SetValue(1, 1, 0.0);
aPolyIntervals->SetValue(1, 2, 1.0);
aPolyIntervals->SetValue(2, 1, 0.0);
aPolyIntervals->SetValue(2, 2, 1.0);
occ::handle<NCollection_HArray1<double>> aTrueIntervals = new NCollection_HArray1<double>(1, 3);
aTrueIntervals->SetValue(1, 0.0);
aTrueIntervals->SetValue(2, 0.5);
aTrueIntervals->SetValue(3, 1.0);
Convert_CompPolynomialToPoles aConv(aNumCurves,
aContinuity,
aDim,
aMaxDeg,
aNumCoeff,
aCoeffs,
aPolyIntervals,
aTrueIntervals);
EXPECT_TRUE(aConv.IsDone());
EXPECT_EQ(aConv.Degree(), 1);
EXPECT_EQ(aConv.NbKnots(), 3);
}
TEST(Convert_CompPolynomialToPolesTest, ThreeDimensional)
{
// 3D linear curve
const int aDim = 3;
const int aMaxDeg = 1;
const int aDeg = 1;
// Coefficients for 3D: [x0, y0, z0, x1, y1, z1]
NCollection_Array1<double> aCoeffs(1, 6);
aCoeffs(1) = 0.0;
aCoeffs(2) = 0.0;
aCoeffs(3) = 0.0; // constant
aCoeffs(4) = 1.0;
aCoeffs(5) = 2.0;
aCoeffs(6) = 3.0; // linear
NCollection_Array1<double> aPolyIntervals(1, 2);
aPolyIntervals(1) = 0.0;
aPolyIntervals(2) = 1.0;
NCollection_Array1<double> aTrueIntervals(1, 2);
aTrueIntervals(1) = 0.0;
aTrueIntervals(2) = 1.0;
Convert_CompPolynomialToPoles aConv(aDim, aMaxDeg, aDeg, aCoeffs, aPolyIntervals, aTrueIntervals);
EXPECT_TRUE(aConv.IsDone());
EXPECT_EQ(aConv.Degree(), 1);
const NCollection_Array2<double>& aPoles = aConv.Poles();
// Poles should be [1..NbPoles][1..3]
EXPECT_EQ(aPoles.RowLength(), 3);
}
@@ -0,0 +1,112 @@
// Copyright (c) 2026 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <gtest/gtest.h>
#include <BSplSLib.hxx>
#include <Convert_ConeToBSplineSurface.hxx>
#include <gp_Cone.hxx>
#include <gp_Ax3.hxx>
#include <gp_Pnt.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_Array2.hxx>
TEST(Convert_ConeToBSplineSurfaceTest, FullCone)
{
const gp_Cone aCone(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), M_PI / 6.0, 3.0);
const Convert_ConeToBSplineSurface aConv(aCone, 0.0, 10.0);
EXPECT_EQ(aConv.UDegree(), 2);
EXPECT_EQ(aConv.VDegree(), 1);
EXPECT_TRUE(aConv.IsUPeriodic());
EXPECT_FALSE(aConv.IsVPeriodic());
EXPECT_GT(aConv.NbUPoles(), 0);
EXPECT_GT(aConv.NbVPoles(), 0);
}
TEST(Convert_ConeToBSplineSurfaceTest, TrimmedCone)
{
const gp_Cone aCone(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), M_PI / 4.0, 2.0);
const double aU1 = 0.0, aU2 = M_PI;
const double aV1 = 0.0, aV2 = 5.0;
const Convert_ConeToBSplineSurface aConv(aCone, aU1, aU2, aV1, aV2);
EXPECT_FALSE(aConv.IsUPeriodic());
EXPECT_FALSE(aConv.IsVPeriodic());
}
TEST(Convert_ConeToBSplineSurfaceTest, WeightsArePositive)
{
const gp_Cone aCone(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), M_PI / 6.0, 1.0);
const Convert_ConeToBSplineSurface aConv(aCone, 0.0, 5.0);
const NCollection_Array2<double>& aWeights = aConv.Weights();
for (int i = 1; i <= aConv.NbUPoles(); ++i)
{
for (int j = 1; j <= aConv.NbVPoles(); ++j)
{
EXPECT_GT(aWeights(i, j), 0.0);
}
}
}
TEST(Convert_ConeToBSplineSurfaceTest, GeometricVerification)
{
const double aSemiAngle = M_PI / 6.0;
const double aRadius = 3.0;
const gp_Ax3 anAx3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
const gp_Cone aCone(anAx3, aSemiAngle, aRadius);
const Convert_ConeToBSplineSurface aConv(aCone, 0.0, M_PI, 0.0, 10.0);
const double aTol = 1.0e-10;
const NCollection_Array1<double>& aUK = aConv.UKnots();
const NCollection_Array1<double>& aVK = aConv.VKnots();
const double aUMin = aUK(aUK.Lower()), aUMax = aUK(aUK.Upper());
const double aVMin = aVK(aVK.Lower()), aVMax = aVK(aVK.Upper());
for (int i = 0; i <= 4; ++i)
{
const double aU = aUMin + i * (aUMax - aUMin) / 4.0;
for (int j = 0; j <= 4; ++j)
{
const double aV = aVMin + j * (aVMax - aVMin) / 4.0;
gp_Pnt aPnt;
BSplSLib::D0(aU,
aV,
0,
0,
aConv.Poles(),
&aConv.Weights(),
aConv.UKnots(),
aConv.VKnots(),
&aConv.UMultiplicities(),
&aConv.VMultiplicities(),
aConv.UDegree(),
aConv.VDegree(),
true,
false,
false,
false,
aPnt);
// Verify the point lies on the cone:
// For a cone with axis Z, semi-angle a, reference radius R:
// r(z) = R + z * tan(a), distance from axis = r
const double aDistFromAxis = std::sqrt(aPnt.X() * aPnt.X() + aPnt.Y() * aPnt.Y());
const double aExpectedR = aRadius + aPnt.Z() * std::tan(aSemiAngle);
EXPECT_NEAR(aDistFromAxis, aExpectedR, aTol)
<< "Point not on cone at U=" << aU << " V=" << aV;
}
}
}
@@ -0,0 +1,132 @@
// Copyright (c) 2026 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <gtest/gtest.h>
#include <BSplSLib.hxx>
#include <Convert_CylinderToBSplineSurface.hxx>
#include <gp_Cylinder.hxx>
#include <gp_Ax3.hxx>
#include <gp_Pnt.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_Array2.hxx>
TEST(Convert_CylinderToBSplineSurfaceTest, FullCylinder)
{
const gp_Cylinder aCyl(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 3.0);
const Convert_CylinderToBSplineSurface aConv(aCyl, 0.0, 10.0);
EXPECT_EQ(aConv.UDegree(), 2);
EXPECT_EQ(aConv.VDegree(), 1);
EXPECT_TRUE(aConv.IsUPeriodic());
EXPECT_FALSE(aConv.IsVPeriodic());
EXPECT_GT(aConv.NbUPoles(), 0);
EXPECT_GT(aConv.NbVPoles(), 0);
}
TEST(Convert_CylinderToBSplineSurfaceTest, TrimmedCylinder)
{
const gp_Cylinder aCyl(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 2.0);
const double aU1 = 0.0, aU2 = M_PI;
const double aV1 = -5.0, aV2 = 5.0;
const Convert_CylinderToBSplineSurface aConv(aCyl, aU1, aU2, aV1, aV2);
EXPECT_FALSE(aConv.IsUPeriodic());
EXPECT_FALSE(aConv.IsVPeriodic());
EXPECT_GT(aConv.NbUPoles(), 0);
EXPECT_GT(aConv.NbVPoles(), 0);
}
TEST(Convert_CylinderToBSplineSurfaceTest, WeightsArePositive)
{
const gp_Cylinder aCyl(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 1.0);
const Convert_CylinderToBSplineSurface aConv(aCyl, 0.0, 1.0);
const NCollection_Array2<double>& aWeights = aConv.Weights();
for (int i = 1; i <= aConv.NbUPoles(); ++i)
{
for (int j = 1; j <= aConv.NbVPoles(); ++j)
{
EXPECT_GT(aWeights(i, j), 0.0);
}
}
}
TEST(Convert_CylinderToBSplineSurfaceTest, KnotsAreMonotonic)
{
const gp_Cylinder aCyl(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 1.0);
const Convert_CylinderToBSplineSurface aConv(aCyl, 0.0, 1.0);
const NCollection_Array1<double>& aUKnots = aConv.UKnots();
for (int i = 2; i <= aConv.NbUKnots(); ++i)
{
EXPECT_GT(aUKnots(i), aUKnots(i - 1));
}
const NCollection_Array1<double>& aVKnots = aConv.VKnots();
for (int i = 2; i <= aConv.NbVKnots(); ++i)
{
EXPECT_GT(aVKnots(i), aVKnots(i - 1));
}
}
TEST(Convert_CylinderToBSplineSurfaceTest, GeometricVerification)
{
const double aRadius = 3.0;
const double aV1 = -5.0, aV2 = 5.0;
const gp_Ax3 anAx3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
const gp_Cylinder aCyl(anAx3, aRadius);
const Convert_CylinderToBSplineSurface aConv(aCyl, 0.0, M_PI, aV1, aV2);
const double aTol = 1.0e-10;
// Sample 5x5 grid of BSpline parameters within the domain
const NCollection_Array1<double>& aUK = aConv.UKnots();
const NCollection_Array1<double>& aVK = aConv.VKnots();
const double aUMin = aUK(aUK.Lower()), aUMax = aUK(aUK.Upper());
const double aVMin = aVK(aVK.Lower()), aVMax = aVK(aVK.Upper());
for (int i = 0; i <= 4; ++i)
{
const double aU = aUMin + i * (aUMax - aUMin) / 4.0;
for (int j = 0; j <= 4; ++j)
{
const double aV = aVMin + j * (aVMax - aVMin) / 4.0;
gp_Pnt aPnt;
BSplSLib::D0(aU,
aV,
0,
0,
aConv.Poles(),
&aConv.Weights(),
aConv.UKnots(),
aConv.VKnots(),
&aConv.UMultiplicities(),
&aConv.VMultiplicities(),
aConv.UDegree(),
aConv.VDegree(),
true,
false,
false,
false,
aPnt);
// Verify the point lies on the cylinder: distance from Z axis = R
const double aDistFromAxis = std::sqrt(aPnt.X() * aPnt.X() + aPnt.Y() * aPnt.Y());
EXPECT_NEAR(aDistFromAxis, aRadius, aTol)
<< "Point not on cylinder at U=" << aU << " V=" << aV;
// Verify Z is within the V range
EXPECT_GE(aPnt.Z(), aV1 - aTol);
EXPECT_LE(aPnt.Z(), aV2 + aTol);
}
}
}
@@ -0,0 +1,139 @@
// Copyright (c) 2026 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <gtest/gtest.h>
#include <Convert_EllipseToBSplineCurve.hxx>
#include <Convert_ParameterisationType.hxx>
#include <gp_Ax2d.hxx>
#include <gp_Dir2d.hxx>
#include <gp_Elips2d.hxx>
#include <gp_Pnt2d.hxx>
TEST(Convert_EllipseToBSplineCurveTest, FullEllipse_TgtThetaOver2)
{
const gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0, 3.0);
const Convert_EllipseToBSplineCurve aConv(anElips, Convert_TgtThetaOver2);
EXPECT_TRUE(aConv.IsPeriodic());
EXPECT_EQ(aConv.Degree(), 2);
EXPECT_GT(aConv.NbPoles(), 0);
EXPECT_GT(aConv.NbKnots(), 0);
// Verify all weights are positive
const NCollection_Array1<double>& aWeights = aConv.Weights();
for (int i = 1; i <= aConv.NbPoles(); ++i)
{
EXPECT_GT(aWeights(i), 0.0) << "Weight at index " << i << " is not positive";
}
// Verify knots are monotonically increasing
const NCollection_Array1<double>& aKnots = aConv.Knots();
for (int i = 2; i <= aConv.NbKnots(); ++i)
{
EXPECT_GT(aKnots(i), aKnots(i - 1)) << "Knots not monotonically increasing at index " << i;
}
// Verify multiplicities are within valid range
const NCollection_Array1<int>& aMults = aConv.Multiplicities();
for (int i = 1; i <= aConv.NbKnots(); ++i)
{
EXPECT_GT(aMults(i), 0);
EXPECT_LE(aMults(i), aConv.Degree() + 1);
}
}
TEST(Convert_EllipseToBSplineCurveTest, Arc_TgtThetaOver2)
{
const gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(1.0, 1.0), gp_Dir2d(1.0, 0.0)), 4.0, 2.0);
const double aU1 = M_PI / 4.0;
const double aU2 = 3.0 * M_PI / 2.0;
const Convert_EllipseToBSplineCurve aConv(anElips, aU1, aU2, Convert_TgtThetaOver2);
EXPECT_FALSE(aConv.IsPeriodic());
EXPECT_GT(aConv.NbPoles(), 0);
EXPECT_GT(aConv.NbKnots(), 0);
// Verify first pole matches ellipse point at U1
const NCollection_Array1<gp_Pnt2d>& aPoles = aConv.Poles();
const double aMajR = anElips.MajorRadius();
const double aMinR = anElips.MinorRadius();
const gp_Pnt2d aCenter = anElips.Location();
const gp_Dir2d aXDir = anElips.XAxis().Direction();
const gp_Dir2d aYDir = anElips.YAxis().Direction();
const double aFirstX =
aCenter.X() + aMajR * std::cos(aU1) * aXDir.X() + aMinR * std::sin(aU1) * aYDir.X();
const double aFirstY =
aCenter.Y() + aMajR * std::cos(aU1) * aXDir.Y() + aMinR * std::sin(aU1) * aYDir.Y();
EXPECT_NEAR(aPoles(1).X(), aFirstX, 1.0e-10);
EXPECT_NEAR(aPoles(1).Y(), aFirstY, 1.0e-10);
// Verify last pole matches ellipse point at U2
const double aLastX =
aCenter.X() + aMajR * std::cos(aU2) * aXDir.X() + aMinR * std::sin(aU2) * aYDir.X();
const double aLastY =
aCenter.Y() + aMajR * std::cos(aU2) * aXDir.Y() + aMinR * std::sin(aU2) * aYDir.Y();
EXPECT_NEAR(aPoles(aConv.NbPoles()).X(), aLastX, 1.0e-10);
EXPECT_NEAR(aPoles(aConv.NbPoles()).Y(), aLastY, 1.0e-10);
// Verify all weights are positive
const NCollection_Array1<double>& aWeights = aConv.Weights();
for (int i = 1; i <= aConv.NbPoles(); ++i)
{
EXPECT_GT(aWeights(i), 0.0) << "Weight at index " << i << " is not positive";
}
// Verify knots are monotonically increasing
const NCollection_Array1<double>& aKnots = aConv.Knots();
for (int i = 2; i <= aConv.NbKnots(); ++i)
{
EXPECT_GT(aKnots(i), aKnots(i - 1)) << "Knots not monotonically increasing at index " << i;
}
}
TEST(Convert_EllipseToBSplineCurveTest, FullEllipse_RationalC1)
{
const gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 3.0, 1.0);
const Convert_EllipseToBSplineCurve aConv(anElips, Convert_RationalC1);
EXPECT_TRUE(aConv.IsPeriodic());
EXPECT_GT(aConv.NbPoles(), 0);
EXPECT_GT(aConv.NbKnots(), 0);
// Verify all weights are positive
const NCollection_Array1<double>& aWeights = aConv.Weights();
for (int i = 1; i <= aConv.NbPoles(); ++i)
{
EXPECT_GT(aWeights(i), 0.0) << "Weight at index " << i << " is not positive";
}
// Verify knots are monotonically increasing
const NCollection_Array1<double>& aKnots = aConv.Knots();
for (int i = 2; i <= aConv.NbKnots(); ++i)
{
EXPECT_GT(aKnots(i), aKnots(i - 1)) << "Knots not monotonically increasing at index " << i;
}
}
TEST(Convert_EllipseToBSplineCurveTest, WeightsArePositive)
{
const gp_Elips2d anElips(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 5.0, 3.0);
const Convert_EllipseToBSplineCurve aConv(anElips, Convert_TgtThetaOver2);
const NCollection_Array1<double>& aWeights = aConv.Weights();
for (int i = 1; i <= aConv.NbPoles(); ++i)
{
EXPECT_GT(aWeights(i), 0.0);
}
}
@@ -0,0 +1,124 @@
// Copyright (c) 2026 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <gtest/gtest.h>
#include <Convert_GridPolynomialToPoles.hxx>
#include <gp_Pnt.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_Array2.hxx>
#include <NCollection_HArray1.hxx>
TEST(Convert_GridPolynomialToPolesTest, SinglePlanarPatch)
{
// A single bilinear patch: z = 0, x = u, y = v
// MaxUDegree = 1, MaxVDegree = 1
// Coefficients as "C array" [MaxUDegree+1][MaxVDegree+1][3]
// For P(u,v) = (u, v, 0): coefficients in polynomial form
const int aMaxUDeg = 1;
const int aMaxVDeg = 1;
occ::handle<NCollection_HArray1<int>> aNumCoeff = new NCollection_HArray1<int>(1, 2);
aNumCoeff->SetValue(1, 2); // U degree + 1
aNumCoeff->SetValue(2, 2); // V degree + 1
// Coefficients [2][2][3] = 12 values
// Layout: for u_i, v_j: coeff(u_i, v_j) = {x, y, z}
// P(u,v) = sum c_{ij} * u^i * v^j
// c_{00} = (0,0,0), c_{10} = (1,0,0), c_{01} = (0,1,0), c_{11} = (0,0,0)
occ::handle<NCollection_HArray1<double>> aCoeffs = new NCollection_HArray1<double>(1, 12);
// c_{00}: x=0,y=0,z=0
aCoeffs->SetValue(1, 0.0);
aCoeffs->SetValue(2, 0.0);
aCoeffs->SetValue(3, 0.0);
// c_{01}: x=0,y=1,z=0
aCoeffs->SetValue(4, 0.0);
aCoeffs->SetValue(5, 1.0);
aCoeffs->SetValue(6, 0.0);
// c_{10}: x=1,y=0,z=0
aCoeffs->SetValue(7, 1.0);
aCoeffs->SetValue(8, 0.0);
aCoeffs->SetValue(9, 0.0);
// c_{11}: x=0,y=0,z=0
aCoeffs->SetValue(10, 0.0);
aCoeffs->SetValue(11, 0.0);
aCoeffs->SetValue(12, 0.0);
occ::handle<NCollection_HArray1<double>> aPolyU = new NCollection_HArray1<double>(1, 2);
aPolyU->SetValue(1, 0.0);
aPolyU->SetValue(2, 1.0);
occ::handle<NCollection_HArray1<double>> aPolyV = new NCollection_HArray1<double>(1, 2);
aPolyV->SetValue(1, 0.0);
aPolyV->SetValue(2, 1.0);
Convert_GridPolynomialToPoles aConv(aMaxUDeg, aMaxVDeg, aNumCoeff, aCoeffs, aPolyU, aPolyV);
EXPECT_TRUE(aConv.IsDone());
EXPECT_GT(aConv.NbUPoles(), 0);
EXPECT_GT(aConv.NbVPoles(), 0);
EXPECT_EQ(aConv.UDegree(), 1);
EXPECT_EQ(aConv.VDegree(), 1);
EXPECT_GT(aConv.NbUKnots(), 0);
EXPECT_GT(aConv.NbVKnots(), 0);
// Check poles are accessible
const NCollection_Array2<gp_Pnt>& aPoles = aConv.Poles();
EXPECT_GT(aPoles.Size(), 0);
}
TEST(Convert_GridPolynomialToPolesTest, QueryMethods)
{
const int aMaxUDeg = 1;
const int aMaxVDeg = 1;
occ::handle<NCollection_HArray1<int>> aNumCoeff = new NCollection_HArray1<int>(1, 2);
aNumCoeff->SetValue(1, 2);
aNumCoeff->SetValue(2, 2);
occ::handle<NCollection_HArray1<double>> aCoeffs = new NCollection_HArray1<double>(1, 12);
for (int i = 1; i <= 12; ++i)
{
aCoeffs->SetValue(i, 0.0);
}
// Just set x = u coefficient
aCoeffs->SetValue(7, 1.0);
// y = v coefficient
aCoeffs->SetValue(5, 1.0);
occ::handle<NCollection_HArray1<double>> aPolyU = new NCollection_HArray1<double>(1, 2);
aPolyU->SetValue(1, 0.0);
aPolyU->SetValue(2, 1.0);
occ::handle<NCollection_HArray1<double>> aPolyV = new NCollection_HArray1<double>(1, 2);
aPolyV->SetValue(1, 0.0);
aPolyV->SetValue(2, 1.0);
Convert_GridPolynomialToPoles aConv(aMaxUDeg, aMaxVDeg, aNumCoeff, aCoeffs, aPolyU, aPolyV);
ASSERT_TRUE(aConv.IsDone());
// Verify knot data is accessible
const NCollection_Array1<double>& aUKnots = aConv.UKnots();
const NCollection_Array1<double>& aVKnots = aConv.VKnots();
const NCollection_Array1<int>& aUMults = aConv.UMultiplicities();
const NCollection_Array1<int>& aVMults = aConv.VMultiplicities();
EXPECT_GT(aUKnots.Size(), 0);
EXPECT_GT(aVKnots.Size(), 0);
EXPECT_GT(aUMults.Size(), 0);
EXPECT_GT(aVMults.Size(), 0);
EXPECT_EQ(aUKnots.Length(), aConv.NbUKnots());
EXPECT_EQ(aVKnots.Length(), aConv.NbVKnots());
}
@@ -0,0 +1,139 @@
// Copyright (c) 2026 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <gtest/gtest.h>
#include <Convert_HyperbolaToBSplineCurve.hxx>
#include <gp_Ax2d.hxx>
#include <gp_Dir2d.hxx>
#include <gp_Hypr2d.hxx>
#include <gp_Pnt2d.hxx>
TEST(Convert_HyperbolaToBSplineCurveTest, BasicConversion)
{
const gp_Hypr2d aHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 3.0, 2.0);
const double aU1 = -1.0;
const double aU2 = 1.0;
const Convert_HyperbolaToBSplineCurve aConv(aHypr, aU1, aU2);
EXPECT_FALSE(aConv.IsPeriodic());
EXPECT_EQ(aConv.Degree(), 2);
EXPECT_GT(aConv.NbPoles(), 0);
EXPECT_GT(aConv.NbKnots(), 0);
// Verify first pole matches hyperbola point at U1
const NCollection_Array1<gp_Pnt2d>& aPoles = aConv.Poles();
const double aMajR = aHypr.MajorRadius();
const double aMinR = aHypr.MinorRadius();
const gp_Pnt2d aCenter = aHypr.Location();
const gp_Dir2d aXDir = aHypr.XAxis().Direction();
const gp_Dir2d aYDir = aHypr.YAxis().Direction();
const double aFirstX =
aCenter.X() + aMajR * std::cosh(aU1) * aXDir.X() + aMinR * std::sinh(aU1) * aYDir.X();
const double aFirstY =
aCenter.Y() + aMajR * std::cosh(aU1) * aXDir.Y() + aMinR * std::sinh(aU1) * aYDir.Y();
EXPECT_NEAR(aPoles(1).X(), aFirstX, 1.0e-10);
EXPECT_NEAR(aPoles(1).Y(), aFirstY, 1.0e-10);
// Verify last pole matches hyperbola point at U2
const double aLastX =
aCenter.X() + aMajR * std::cosh(aU2) * aXDir.X() + aMinR * std::sinh(aU2) * aYDir.X();
const double aLastY =
aCenter.Y() + aMajR * std::cosh(aU2) * aXDir.Y() + aMinR * std::sinh(aU2) * aYDir.Y();
EXPECT_NEAR(aPoles(aConv.NbPoles()).X(), aLastX, 1.0e-10);
EXPECT_NEAR(aPoles(aConv.NbPoles()).Y(), aLastY, 1.0e-10);
// Verify all weights are positive
const NCollection_Array1<double>& aWeights = aConv.Weights();
for (int i = 1; i <= aConv.NbPoles(); ++i)
{
EXPECT_GT(aWeights(i), 0.0) << "Weight at index " << i << " is not positive";
}
// Verify knots are monotonically increasing
const NCollection_Array1<double>& aKnots = aConv.Knots();
for (int i = 2; i <= aConv.NbKnots(); ++i)
{
EXPECT_GT(aKnots(i), aKnots(i - 1)) << "Knots not monotonically increasing at index " << i;
}
// Verify multiplicities are within valid range
const NCollection_Array1<int>& aMults = aConv.Multiplicities();
for (int i = 1; i <= aConv.NbKnots(); ++i)
{
EXPECT_GT(aMults(i), 0);
EXPECT_LE(aMults(i), aConv.Degree() + 1);
}
}
TEST(Convert_HyperbolaToBSplineCurveTest, LargeRange)
{
const gp_Hypr2d aHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 1.0, 1.0);
const double aU1 = -2.0;
const double aU2 = 2.0;
const Convert_HyperbolaToBSplineCurve aConv(aHypr, aU1, aU2);
EXPECT_FALSE(aConv.IsPeriodic());
EXPECT_GT(aConv.NbPoles(), 0);
EXPECT_GT(aConv.NbKnots(), 0);
// Verify first pole matches hyperbola point at U1
const NCollection_Array1<gp_Pnt2d>& aPoles = aConv.Poles();
const double aMajR = aHypr.MajorRadius();
const double aMinR = aHypr.MinorRadius();
const gp_Pnt2d aCenter = aHypr.Location();
const gp_Dir2d aXDir = aHypr.XAxis().Direction();
const gp_Dir2d aYDir = aHypr.YAxis().Direction();
const double aFirstX =
aCenter.X() + aMajR * std::cosh(aU1) * aXDir.X() + aMinR * std::sinh(aU1) * aYDir.X();
const double aFirstY =
aCenter.Y() + aMajR * std::cosh(aU1) * aXDir.Y() + aMinR * std::sinh(aU1) * aYDir.Y();
EXPECT_NEAR(aPoles(1).X(), aFirstX, 1.0e-10);
EXPECT_NEAR(aPoles(1).Y(), aFirstY, 1.0e-10);
// Verify last pole matches hyperbola point at U2
const double aLastX =
aCenter.X() + aMajR * std::cosh(aU2) * aXDir.X() + aMinR * std::sinh(aU2) * aYDir.X();
const double aLastY =
aCenter.Y() + aMajR * std::cosh(aU2) * aXDir.Y() + aMinR * std::sinh(aU2) * aYDir.Y();
EXPECT_NEAR(aPoles(aConv.NbPoles()).X(), aLastX, 1.0e-10);
EXPECT_NEAR(aPoles(aConv.NbPoles()).Y(), aLastY, 1.0e-10);
// Verify all weights are positive
const NCollection_Array1<double>& aWeights = aConv.Weights();
for (int i = 1; i <= aConv.NbPoles(); ++i)
{
EXPECT_GT(aWeights(i), 0.0) << "Weight at index " << i << " is not positive";
}
// Verify knots are monotonically increasing
const NCollection_Array1<double>& aKnots = aConv.Knots();
for (int i = 2; i <= aConv.NbKnots(); ++i)
{
EXPECT_GT(aKnots(i), aKnots(i - 1)) << "Knots not monotonically increasing at index " << i;
}
}
TEST(Convert_HyperbolaToBSplineCurveTest, WeightsArePositive)
{
const gp_Hypr2d aHypr(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 3.0, 2.0);
const Convert_HyperbolaToBSplineCurve aConv(aHypr, -1.0, 1.0);
const NCollection_Array1<double>& aWeights = aConv.Weights();
for (int i = 1; i <= aConv.NbPoles(); ++i)
{
EXPECT_GT(aWeights(i), 0.0);
}
}
@@ -0,0 +1,100 @@
// Copyright (c) 2026 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <gtest/gtest.h>
#include <Convert_ParabolaToBSplineCurve.hxx>
#include <ElCLib.hxx>
#include <gp_Parab2d.hxx>
#include <gp_Ax2d.hxx>
#include <gp_Ax22d.hxx>
#include <gp_Pnt2d.hxx>
#include <BSplCLib.hxx>
#include <NCollection_Array1.hxx>
namespace
{
void checkParabolaPoint(const Convert_ParabolaToBSplineCurve& theConv,
const gp_Parab2d& theParab,
const double theParam)
{
const NCollection_Array1<gp_Pnt2d>& aPoles = theConv.Poles();
const NCollection_Array1<double>& aWeights = theConv.Weights();
const NCollection_Array1<double>& aKnots = theConv.Knots();
const NCollection_Array1<int>& aMults = theConv.Multiplicities();
gp_Pnt2d aBSPnt;
BSplCLib::D0(theParam,
0,
theConv.Degree(),
theConv.IsPeriodic(),
aPoles,
&aWeights,
aKnots,
&aMults,
aBSPnt);
// Use ElCLib to evaluate the reference point on the parabola
const gp_Pnt2d aExpPnt = ElCLib::Value(theParam, theParab);
const double aExpX = aExpPnt.X();
const double aExpY = aExpPnt.Y();
EXPECT_NEAR(aBSPnt.X(), aExpX, 1.0e-10);
EXPECT_NEAR(aBSPnt.Y(), aExpY, 1.0e-10);
}
} // namespace
TEST(Convert_ParabolaToBSplineCurveTest, BasicConversion)
{
const gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 1.0);
const double aU1 = -2.0;
const double aU2 = 2.0;
const Convert_ParabolaToBSplineCurve aConv(aParab, aU1, aU2);
EXPECT_FALSE(aConv.IsPeriodic());
EXPECT_EQ(aConv.Degree(), 2);
EXPECT_GT(aConv.NbPoles(), 0);
EXPECT_GT(aConv.NbKnots(), 0);
for (int i = 0; i <= 4; ++i)
{
const double aParam = aU1 + i * (aU2 - aU1) / 4.0;
checkParabolaPoint(aConv, aParab, aParam);
}
}
TEST(Convert_ParabolaToBSplineCurveTest, SmallRange)
{
const gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 0.5);
const double aU1 = -0.5;
const double aU2 = 0.5;
const Convert_ParabolaToBSplineCurve aConv(aParab, aU1, aU2);
for (int i = 0; i <= 4; ++i)
{
const double aParam = aU1 + i * (aU2 - aU1) / 4.0;
checkParabolaPoint(aConv, aParab, aParam);
}
}
TEST(Convert_ParabolaToBSplineCurveTest, AllWeightsAreOne)
{
// Parabola conversion produces non-rational (polynomial) BSpline
const gp_Parab2d aParab(gp_Ax2d(gp_Pnt2d(0.0, 0.0), gp_Dir2d(1.0, 0.0)), 1.0);
const Convert_ParabolaToBSplineCurve aConv(aParab, -1.0, 1.0);
const NCollection_Array1<double>& aWeights = aConv.Weights();
for (int i = aWeights.Lower(); i <= aWeights.Upper(); ++i)
{
EXPECT_NEAR(aWeights(i), 1.0, 1.0e-15);
}
}
@@ -0,0 +1,141 @@
// Copyright (c) 2026 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <gtest/gtest.h>
#include <BSplSLib.hxx>
#include <Convert_SphereToBSplineSurface.hxx>
#include <gp_Sphere.hxx>
#include <gp_Ax3.hxx>
#include <gp_Pnt.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_Array2.hxx>
TEST(Convert_SphereToBSplineSurfaceTest, FullSphere)
{
const gp_Sphere aSphere(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 5.0);
const Convert_SphereToBSplineSurface aConv(aSphere);
EXPECT_EQ(aConv.UDegree(), 2);
EXPECT_EQ(aConv.VDegree(), 2);
EXPECT_TRUE(aConv.IsUPeriodic());
EXPECT_FALSE(aConv.IsVPeriodic());
EXPECT_GT(aConv.NbUPoles(), 0);
EXPECT_GT(aConv.NbVPoles(), 0);
EXPECT_GT(aConv.NbUKnots(), 0);
EXPECT_GT(aConv.NbVKnots(), 0);
// Check all weights are non-negative (sphere poles may have zero weights)
const NCollection_Array2<double>& aWeights = aConv.Weights();
for (int i = 1; i <= aConv.NbUPoles(); ++i)
{
for (int j = 1; j <= aConv.NbVPoles(); ++j)
{
EXPECT_GE(aWeights(i, j), 0.0);
}
}
}
TEST(Convert_SphereToBSplineSurfaceTest, TrimmedUV)
{
const gp_Sphere aSphere(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 3.0);
const double aU1 = 0.0, aU2 = M_PI;
const double aV1 = -M_PI / 4.0, aV2 = M_PI / 4.0;
const Convert_SphereToBSplineSurface aConv(aSphere, aU1, aU2, aV1, aV2);
EXPECT_FALSE(aConv.IsUPeriodic());
EXPECT_FALSE(aConv.IsVPeriodic());
EXPECT_GT(aConv.NbUPoles(), 0);
EXPECT_GT(aConv.NbVPoles(), 0);
}
TEST(Convert_SphereToBSplineSurfaceTest, UTrimmed)
{
const gp_Sphere aSphere(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 2.0);
const Convert_SphereToBSplineSurface aConv(aSphere, 0.0, M_PI, true);
EXPECT_FALSE(aConv.IsUPeriodic());
}
TEST(Convert_SphereToBSplineSurfaceTest, VTrimmed)
{
const gp_Sphere aSphere(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 2.0);
const Convert_SphereToBSplineSurface aConv(aSphere, -M_PI / 4.0, M_PI / 4.0, false);
EXPECT_TRUE(aConv.IsUPeriodic());
}
TEST(Convert_SphereToBSplineSurfaceTest, KnotsAreMonotonic)
{
const gp_Sphere aSphere(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 1.0);
const Convert_SphereToBSplineSurface aConv(aSphere);
const NCollection_Array1<double>& aUKnots = aConv.UKnots();
for (int i = 2; i <= aConv.NbUKnots(); ++i)
{
EXPECT_GT(aUKnots(i), aUKnots(i - 1));
}
const NCollection_Array1<double>& aVKnots = aConv.VKnots();
for (int i = 2; i <= aConv.NbVKnots(); ++i)
{
EXPECT_GT(aVKnots(i), aVKnots(i - 1));
}
}
TEST(Convert_SphereToBSplineSurfaceTest, GeometricVerification)
{
const double aRadius = 5.0;
const gp_Ax3 anAx3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
const gp_Sphere aSphere(anAx3, aRadius);
// Use trimmed sphere to avoid degenerate poles
const Convert_SphereToBSplineSurface aConv(aSphere, 0.0, M_PI, -M_PI / 4.0, M_PI / 4.0);
const double aTol = 1.0e-10;
const NCollection_Array1<double>& aUK = aConv.UKnots();
const NCollection_Array1<double>& aVK = aConv.VKnots();
const double aUMin = aUK(aUK.Lower()), aUMax = aUK(aUK.Upper());
const double aVMin = aVK(aVK.Lower()), aVMax = aVK(aVK.Upper());
for (int i = 0; i <= 4; ++i)
{
const double aU = aUMin + i * (aUMax - aUMin) / 4.0;
for (int j = 0; j <= 4; ++j)
{
const double aV = aVMin + j * (aVMax - aVMin) / 4.0;
gp_Pnt aPnt;
BSplSLib::D0(aU,
aV,
0,
0,
aConv.Poles(),
&aConv.Weights(),
aConv.UKnots(),
aConv.VKnots(),
&aConv.UMultiplicities(),
&aConv.VMultiplicities(),
aConv.UDegree(),
aConv.VDegree(),
true,
true,
false,
false,
aPnt);
// Verify the point lies on the sphere: x^2 + y^2 + z^2 = R^2
const double aDistFromOrigin = aPnt.Distance(gp_Pnt(0.0, 0.0, 0.0));
EXPECT_NEAR(aDistFromOrigin, aRadius, aTol)
<< "Point not on sphere at U=" << aU << " V=" << aV;
}
}
}
@@ -0,0 +1,148 @@
// Copyright (c) 2026 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <gtest/gtest.h>
#include <BSplSLib.hxx>
#include <Convert_TorusToBSplineSurface.hxx>
#include <gp_Torus.hxx>
#include <gp_Ax3.hxx>
#include <gp_Pnt.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_Array2.hxx>
TEST(Convert_TorusToBSplineSurfaceTest, FullTorus)
{
const gp_Torus aTorus(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 5.0, 2.0);
const Convert_TorusToBSplineSurface aConv(aTorus);
EXPECT_EQ(aConv.UDegree(), 2);
EXPECT_EQ(aConv.VDegree(), 2);
EXPECT_TRUE(aConv.IsUPeriodic());
EXPECT_TRUE(aConv.IsVPeriodic());
EXPECT_GT(aConv.NbUPoles(), 0);
EXPECT_GT(aConv.NbVPoles(), 0);
}
TEST(Convert_TorusToBSplineSurfaceTest, TrimmedUV)
{
const gp_Torus aTorus(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 5.0, 2.0);
const double aU1 = 0.0, aU2 = M_PI;
const double aV1 = 0.0, aV2 = M_PI;
const Convert_TorusToBSplineSurface aConv(aTorus, aU1, aU2, aV1, aV2);
EXPECT_FALSE(aConv.IsUPeriodic());
EXPECT_FALSE(aConv.IsVPeriodic());
EXPECT_GT(aConv.NbUPoles(), 0);
EXPECT_GT(aConv.NbVPoles(), 0);
}
TEST(Convert_TorusToBSplineSurfaceTest, UTrimmed)
{
const gp_Torus aTorus(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 5.0, 2.0);
const Convert_TorusToBSplineSurface aConv(aTorus, 0.0, M_PI, true);
EXPECT_FALSE(aConv.IsUPeriodic());
EXPECT_TRUE(aConv.IsVPeriodic());
}
TEST(Convert_TorusToBSplineSurfaceTest, VTrimmed)
{
const gp_Torus aTorus(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 5.0, 2.0);
const Convert_TorusToBSplineSurface aConv(aTorus, 0.0, M_PI, false);
EXPECT_TRUE(aConv.IsUPeriodic());
EXPECT_FALSE(aConv.IsVPeriodic());
}
TEST(Convert_TorusToBSplineSurfaceTest, WeightsArePositive)
{
const gp_Torus aTorus(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 5.0, 2.0);
const Convert_TorusToBSplineSurface aConv(aTorus);
const NCollection_Array2<double>& aWeights = aConv.Weights();
for (int i = 1; i <= aConv.NbUPoles(); ++i)
{
for (int j = 1; j <= aConv.NbVPoles(); ++j)
{
EXPECT_GT(aWeights(i, j), 0.0);
}
}
}
TEST(Convert_TorusToBSplineSurfaceTest, KnotsAreMonotonic)
{
const gp_Torus aTorus(gp_Ax3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0)), 5.0, 2.0);
const Convert_TorusToBSplineSurface aConv(aTorus);
const NCollection_Array1<double>& aUKnots = aConv.UKnots();
for (int i = 2; i <= aConv.NbUKnots(); ++i)
{
EXPECT_GT(aUKnots(i), aUKnots(i - 1));
}
const NCollection_Array1<double>& aVKnots = aConv.VKnots();
for (int i = 2; i <= aConv.NbVKnots(); ++i)
{
EXPECT_GT(aVKnots(i), aVKnots(i - 1));
}
}
TEST(Convert_TorusToBSplineSurfaceTest, GeometricVerification)
{
const double aMajorRadius = 5.0;
const double aMinorRadius = 2.0;
const gp_Ax3 anAx3(gp_Pnt(0.0, 0.0, 0.0), gp_Dir(0.0, 0.0, 1.0));
const gp_Torus aTorus(anAx3, aMajorRadius, aMinorRadius);
const Convert_TorusToBSplineSurface aConv(aTorus, 0.0, M_PI, 0.0, M_PI);
const double aTol = 1.0e-10;
const NCollection_Array1<double>& aUK = aConv.UKnots();
const NCollection_Array1<double>& aVK = aConv.VKnots();
const double aUMin = aUK(aUK.Lower()), aUMax = aUK(aUK.Upper());
const double aVMin = aVK(aVK.Lower()), aVMax = aVK(aVK.Upper());
for (int i = 0; i <= 4; ++i)
{
const double aU = aUMin + i * (aUMax - aUMin) / 4.0;
for (int j = 0; j <= 4; ++j)
{
const double aV = aVMin + j * (aVMax - aVMin) / 4.0;
gp_Pnt aPnt;
BSplSLib::D0(aU,
aV,
0,
0,
aConv.Poles(),
&aConv.Weights(),
aConv.UKnots(),
aConv.VKnots(),
&aConv.UMultiplicities(),
&aConv.VMultiplicities(),
aConv.UDegree(),
aConv.VDegree(),
true,
true,
false,
false,
aPnt);
// Verify the point lies on the torus:
// (sqrt(x^2 + y^2) - R_major)^2 + z^2 = R_minor^2
const double aRxy = std::sqrt(aPnt.X() * aPnt.X() + aPnt.Y() * aPnt.Y());
const double aDistSq = (aRxy - aMajorRadius) * (aRxy - aMajorRadius) + aPnt.Z() * aPnt.Z();
EXPECT_NEAR(aDistSq, aMinorRadius * aMinorRadius, aTol)
<< "Point not on torus at U=" << aU << " V=" << aV;
}
}
}
@@ -22,6 +22,18 @@ set(OCCT_TKMath_GTests_FILES
BVH_Traverse_Test.cxx
BVH_Triangulation_Test.cxx
BVH_Tree_Test.cxx
# Convert tests
Convert_CircleToBSplineCurve_Test.cxx
Convert_CompBezierCurvesToBSplineCurve_Test.cxx
Convert_CompPolynomialToPoles_Test.cxx
Convert_ConeToBSplineSurface_Test.cxx
Convert_CylinderToBSplineSurface_Test.cxx
Convert_EllipseToBSplineCurve_Test.cxx
Convert_GridPolynomialToPoles_Test.cxx
Convert_HyperbolaToBSplineCurve_Test.cxx
Convert_ParabolaToBSplineCurve_Test.cxx
Convert_SphereToBSplineSurface_Test.cxx
Convert_TorusToBSplineSurface_Test.cxx
CSLib_Test.cxx
ElCLib_Test.cxx
gp_Ax3_Test.cxx
@@ -41,16 +41,16 @@ public:
public:
//! Constructor
Node(const TheItemType& theItem)
: NCollection_SeqNode()
: NCollection_SeqNode(),
myValue(theItem)
{
myValue = theItem;
}
//! Constructor
Node(TheItemType&& theItem)
: NCollection_SeqNode()
: NCollection_SeqNode(),
myValue(std::forward<TheItemType>(theItem))
{
myValue = std::forward<TheItemType>(theItem);
}
//! Constructor with in-place value construction
@@ -20,8 +20,8 @@
#include <gp_Pnt.hxx>
#include <gp_Vec.hxx>
#include <PLib.hxx>
#include <StdFail_NotDone.hxx>
#include <Standard_Integer.hxx>
#include <StdFail_NotDone.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_HArray1.hxx>
#include <NCollection_Array2.hxx>
@@ -77,7 +77,7 @@ void GeomFill_PolynomialConvertor::Init()
Coeffs,
Inter,
TrueInter); En attente du bon Geomlite*/
AConverter.Poles(Poles1d);
Poles1d = new NCollection_HArray2<double>(AConverter.Poles());
for (jj = 1; jj <= Ordre; jj++)
{
@@ -93,7 +93,7 @@ void GeomFill_QuasiAngularConvertor::Init()
// Convertion
Convert_CompPolynomialToPoles AConverter(Ordre, Ordre - 1, Ordre - 1, Coeffs, Inter, TrueInter);
AConverter.Poles(Poles1d);
Poles1d = new NCollection_HArray2<double>(AConverter.Poles());
for (jj = 1; jj <= Ordre; jj++)
{
@@ -844,22 +844,21 @@ void AdvApprox_ApproxAFunction::Perform(const int Num1DSS,
if (AConverter.IsDone())
{
occ::handle<NCollection_HArray2<double>> PolesPtr;
AConverter.Poles(PolesPtr);
AConverter.Knots(myKnots);
AConverter.Multiplicities(myMults);
const NCollection_Array2<double>& aPoles = AConverter.Poles();
myKnots = new NCollection_HArray1<double>(AConverter.Knots());
myMults = new NCollection_HArray1<int>(AConverter.Multiplicities());
myDegree = AConverter.Degree();
index = 0;
if (myNumSubSpaces[0] > 0)
{
my1DPoles = new NCollection_HArray2<double>(1, PolesPtr->ColLength(), 1, myNumSubSpaces[0]);
my1DMaxError = new NCollection_HArray1<double>(1, myNumSubSpaces[0]);
my1DPoles = new NCollection_HArray2<double>(1, aPoles.ColLength(), 1, myNumSubSpaces[0]);
my1DMaxError = new NCollection_HArray1<double>(1, myNumSubSpaces[0]);
my1DAverageError = new NCollection_HArray1<double>(1, myNumSubSpaces[0]);
for (ii = 1; ii <= PolesPtr->ColLength(); ii++)
for (ii = 1; ii <= aPoles.ColLength(); ii++)
{
for (jj = 1; jj <= myNumSubSpaces[0]; jj++)
{
my1DPoles->SetValue(ii, jj, PolesPtr->Value(ii, jj));
my1DPoles->SetValue(ii, jj, aPoles.Value(ii, jj));
}
}
@@ -892,18 +891,17 @@ void AdvApprox_ApproxAFunction::Perform(const int Num1DSS,
if (myNumSubSpaces[1] > 0)
{
gp_Pnt2d Point2d;
my2DPoles =
new NCollection_HArray2<gp_Pnt2d>(1, PolesPtr->ColLength(), 1, myNumSubSpaces[1]);
my2DPoles = new NCollection_HArray2<gp_Pnt2d>(1, aPoles.ColLength(), 1, myNumSubSpaces[1]);
my2DMaxError = new NCollection_HArray1<double>(1, myNumSubSpaces[1]);
my2DAverageError = new NCollection_HArray1<double>(1, myNumSubSpaces[1]);
for (ii = 1; ii <= PolesPtr->ColLength(); ii++)
for (ii = 1; ii <= aPoles.ColLength(); ii++)
{
for (jj = 1; jj <= myNumSubSpaces[1]; jj++)
{
local_index = index + (jj - 1) * 2;
for (kk = 1; kk <= 2; kk++)
{
Point2d.SetCoord(kk, PolesPtr->Value(ii, local_index + kk));
Point2d.SetCoord(kk, aPoles.Value(ii, local_index + kk));
}
my2DPoles->SetValue(ii, jj, Point2d);
}
@@ -938,17 +936,17 @@ void AdvApprox_ApproxAFunction::Perform(const int Num1DSS,
if (myNumSubSpaces[2] > 0)
{
gp_Pnt Point;
my3DPoles = new NCollection_HArray2<gp_Pnt>(1, PolesPtr->ColLength(), 1, myNumSubSpaces[2]);
my3DMaxError = new NCollection_HArray1<double>(1, myNumSubSpaces[2]);
my3DPoles = new NCollection_HArray2<gp_Pnt>(1, aPoles.ColLength(), 1, myNumSubSpaces[2]);
my3DMaxError = new NCollection_HArray1<double>(1, myNumSubSpaces[2]);
my3DAverageError = new NCollection_HArray1<double>(1, myNumSubSpaces[2]);
for (ii = 1; ii <= PolesPtr->ColLength(); ii++)
for (ii = 1; ii <= aPoles.ColLength(); ii++)
{
for (jj = 1; jj <= myNumSubSpaces[2]; jj++)
{
local_index = dim_index + (jj - 1) * 3;
for (kk = 1; kk <= 3; kk++)
{
Point.SetCoord(kk, PolesPtr->Value(ii, local_index + kk));
Point.SetCoord(kk, aPoles.Value(ii, local_index + kk));
}
my3DPoles->SetValue(ii, jj, Point);
}
@@ -683,11 +683,11 @@ bool Geom_OsculatingSurface::buildOsculatingSurface(double theParam,
TrueUIntervals,
TrueVIntervals);
theBSpl = new Geom_BSplineSurface(Data.Poles()->Array2(),
Data.UKnots()->Array1(),
Data.VKnots()->Array1(),
Data.UMultiplicities()->Array1(),
Data.VMultiplicities()->Array1(),
theBSpl = new Geom_BSplineSurface(Data.Poles(),
Data.UKnots(),
Data.VKnots(),
Data.UMultiplicities(),
Data.VMultiplicities(),
Data.UDegree(),
Data.VDegree(),
false,
@@ -972,11 +972,11 @@ void AdvApp2Var_ApproxAFunc2Var::ConvertBS()
}
// Conversion into BSpline
mySurfaces->ChangeValue(SSP) = new (Geom_BSplineSurface)(CvP.Poles()->Array2(),
CvP.UKnots()->Array1(),
CvP.VKnots()->Array1(),
CvP.UMultiplicities()->Array1(),
CvP.VMultiplicities()->Array1(),
mySurfaces->ChangeValue(SSP) = new (Geom_BSplineSurface)(CvP.Poles(),
CvP.UKnots(),
CvP.VKnots(),
CvP.UMultiplicities(),
CvP.VMultiplicities(),
CvP.UDegree(),
CvP.VDegree());
}
@@ -1157,7 +1157,7 @@ occ::handle<NCollection_HArray2<gp_Pnt>> AdvApp2Var_Patch::Poles(
Intervalle,
Intervalle);
return Conv.Poles();
return new NCollection_HArray2<gp_Pnt>(Conv.Poles());
}
//============================================================================
@@ -28,8 +28,6 @@
#define No_Standard_DimensionError
#define No_Standard_ConstructionError
#include <Standard_Macro.hxx>
#include <iostream>
#include <iomanip>
@@ -551,24 +549,23 @@ void AppDef_Variational::Approximate()
IntervallesPtr);
if (AConverter.IsDone())
{
occ::handle<NCollection_HArray2<double>> PolesPtr;
occ::handle<NCollection_HArray1<int>> Mults;
int NbPoles = AConverter.NbPoles();
occ::handle<NCollection_HArray1<int>> Mults;
int NbPoles = AConverter.NbPoles();
// int Deg=AConverter.Degree();
NCollection_Array1<AppParCurves_MultiPoint> TabMU(1, NbPoles);
AConverter.Poles(PolesPtr);
AConverter.Knots(myKnots);
AConverter.Multiplicities(Mults);
const NCollection_Array2<double>& aPoles = AConverter.Poles();
myKnots = new NCollection_HArray1<double>(AConverter.Knots());
Mults = new NCollection_HArray1<int>(AConverter.Multiplicities());
for (ipole = PolesPtr->LowerRow(); ipole <= PolesPtr->UpperRow(); ipole++)
for (ipole = aPoles.LowerRow(); ipole <= aPoles.UpperRow(); ipole++)
{
int index = PolesPtr->LowerCol();
int index = aPoles.LowerCol();
/* if(myNbP2d !=0 )
{
for (jp2d=1;jp2d<=myNbP2d;jp2d++)
{
P2d.SetX(PolesPtr->Value(ipole,index++));
P2d.SetY(PolesPtr->Value(ipole,index++));
P2d.SetX(aPoles.Value(ipole,index++));
P2d.SetY(aPoles.Value(ipole,index++));
TabP2d.SetValue(jp2d,P2d);
}
}*/
@@ -577,14 +574,14 @@ void AppDef_Variational::Approximate()
for (jp3d = 1; jp3d <= myNbP3d; jp3d++)
{
// std::cout << "\n Poles(ipole,1)" <<
// PolesPtr->Value(ipole,index);
P3d.SetX(PolesPtr->Value(ipole, index++));
// aPoles.Value(ipole,index);
P3d.SetX(aPoles.Value(ipole, index++));
// std::cout << "\n Poles(ipole,1)" <<
// PolesPtr->Value(ipole,index);
P3d.SetY(PolesPtr->Value(ipole, index++));
// aPoles.Value(ipole,index);
P3d.SetY(aPoles.Value(ipole, index++));
// std::cout << "\n Poles(ipole,1)" <<
// PolesPtr->Value(ipole,index);
P3d.SetZ(PolesPtr->Value(ipole, index++));
// aPoles.Value(ipole,index);
P3d.SetZ(aPoles.Value(ipole, index++));
TabP3d.SetValue(jp3d, P3d);
}
}
@@ -592,8 +589,8 @@ void AppDef_Variational::Approximate()
{
for (jp2d = 1; jp2d <= myNbP2d; jp2d++)
{
P2d.SetX(PolesPtr->Value(ipole, index++));
P2d.SetY(PolesPtr->Value(ipole, index++));
P2d.SetX(aPoles.Value(ipole, index++));
P2d.SetY(aPoles.Value(ipole, index++));
TabP2d.SetValue(jp2d, P2d);
}
}
@@ -74,24 +74,12 @@ static occ::handle<Geom2d_BSplineCurve> BSplineCurveBuilder(
{
occ::handle<Geom2d_BSplineCurve> TheCurve;
int NbPoles = Convert.NbPoles();
int NbKnots = Convert.NbKnots();
Array1OfPnt2d Poles(1, NbPoles);
Array1OfReal Weights(1, NbPoles);
Array1OfReal Knots(1, NbKnots);
Array1OfInteger Mults(1, NbKnots);
int i;
for (i = 1; i <= NbPoles; i++)
{
Poles(i) = Convert.Pole(i);
Weights(i) = Convert.Weight(i);
}
for (i = 1; i <= NbKnots; i++)
{
Knots(i) = Convert.Knot(i);
Mults(i) = Convert.Multiplicity(i);
}
TheCurve = new BSplineCurve(Poles, Weights, Knots, Mults, Convert.Degree(), Convert.IsPeriodic());
TheCurve = new BSplineCurve(Convert.Poles(),
Convert.Weights(),
Convert.Knots(),
Convert.Multiplicities(),
Convert.Degree(),
Convert.IsPeriodic());
gp_Ax22d Axis = TheConic->Position();
if ((Axis.XDirection() ^ Axis.YDirection()) < 0.)
@@ -62,30 +62,19 @@ static occ::handle<Geom_BSplineCurve> BSplineCurveBuilder(
const Convert_ConicToBSplineCurve& Convert)
{
occ::handle<Geom_BSplineCurve> TheCurve;
int NbPoles = Convert.NbPoles();
int NbKnots = Convert.NbKnots();
NCollection_Array1<gp_Pnt> Poles(1, NbPoles);
NCollection_Array1<double> Weights(1, NbPoles);
NCollection_Array1<double> Knots(1, NbKnots);
NCollection_Array1<int> Mults(1, NbKnots);
int i;
gp_Pnt2d P2d;
gp_Pnt P3d;
for (i = 1; i <= NbPoles; i++)
occ::handle<Geom_BSplineCurve> TheCurve;
const NCollection_Array1<gp_Pnt2d>& aPoles2d = Convert.Poles();
const NCollection_Array1<double>& aWeights = Convert.Weights();
const NCollection_Array1<double>& aKnots = Convert.Knots();
const NCollection_Array1<int>& aMults = Convert.Multiplicities();
NCollection_Array1<gp_Pnt> Poles(1, aPoles2d.Length());
for (int i = aPoles2d.Lower(); i <= aPoles2d.Upper(); i++)
{
P2d = Convert.Pole(i);
P3d.SetCoord(P2d.X(), P2d.Y(), 0.0);
Poles(i) = P3d;
Weights(i) = Convert.Weight(i);
}
for (i = 1; i <= NbKnots; i++)
{
Knots(i) = Convert.Knot(i);
Mults(i) = Convert.Multiplicity(i);
const gp_Pnt2d& aP2d = aPoles2d(i);
Poles(i).SetCoord(aP2d.X(), aP2d.Y(), 0.0);
}
TheCurve =
new Geom_BSplineCurve(Poles, Weights, Knots, Mults, Convert.Degree(), Convert.IsPeriodic());
new Geom_BSplineCurve(Poles, aWeights, aKnots, aMults, Convert.Degree(), Convert.IsPeriodic());
gp_Trsf T;
T.SetTransformation(TheConic->Position(), gp::XOY());
occ::handle<Geom_BSplineCurve> Cres;
@@ -48,15 +48,9 @@
#include <gp_Pnt.hxx>
#include <NCollection_Array1.hxx>
#include <NCollection_Array2.hxx>
#include <Standard_Integer.hxx>
typedef Geom_Surface Surface;
typedef Geom_BSplineSurface BSplineSurface;
typedef NCollection_Array1<double> Array1OfReal;
typedef NCollection_Array2<double> Array2OfReal;
typedef NCollection_Array1<int> Array1OfInteger;
typedef NCollection_Array2<gp_Pnt> Array2OfPnt;
typedef gp_Pnt Pnt;
typedef Geom_Surface Surface;
typedef Geom_BSplineSurface BSplineSurface;
//=================================================================================================
@@ -64,45 +58,14 @@ static occ::handle<Geom_BSplineSurface> BSplineSurfaceBuilder(
const Convert_ElementarySurfaceToBSplineSurface& Convert)
{
occ::handle<Geom_BSplineSurface> TheSurface;
int UDegree = Convert.UDegree();
int VDegree = Convert.VDegree();
int NbUPoles = Convert.NbUPoles();
int NbVPoles = Convert.NbVPoles();
int NbUKnots = Convert.NbUKnots();
int NbVKnots = Convert.NbVKnots();
Array2OfPnt Poles(1, NbUPoles, 1, NbVPoles);
Array2OfReal Weights(1, NbUPoles, 1, NbVPoles);
Array1OfReal UKnots(1, NbUKnots);
Array1OfReal VKnots(1, NbVKnots);
Array1OfInteger UMults(1, NbUKnots);
Array1OfInteger VMults(1, NbVKnots);
int i, j;
for (j = 1; j <= NbVPoles; j++)
{
for (i = 1; i <= NbUPoles; i++)
{
Poles(i, j) = Convert.Pole(i, j);
Weights(i, j) = Convert.Weight(i, j);
}
}
for (i = 1; i <= NbUKnots; i++)
{
UKnots(i) = Convert.UKnot(i);
UMults(i) = Convert.UMultiplicity(i);
}
for (i = 1; i <= NbVKnots; i++)
{
VKnots(i) = Convert.VKnot(i);
VMults(i) = Convert.VMultiplicity(i);
}
TheSurface = new BSplineSurface(Poles,
Weights,
UKnots,
VKnots,
UMults,
VMults,
UDegree,
VDegree,
TheSurface = new BSplineSurface(Convert.Poles(),
Convert.Weights(),
Convert.UKnots(),
Convert.VKnots(),
Convert.UMultiplicities(),
Convert.VMultiplicities(),
Convert.UDegree(),
Convert.VDegree(),
Convert.IsUPeriodic(),
Convert.IsVPeriodic());
return TheSurface;