1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-16 10:08:36 +03:00
occt/src/BSplCLib/BSplCLib.cxx
abv d5f74e42d6 0024624: Lost word in license statement in source files
License statement text corrected; compiler warnings caused by Bison 2.41 disabled for MSVC; a few other compiler warnings on 54-bit Windows eliminated by appropriate type cast
Wrong license statements corrected in several files.
Copyright and license statements added in XSD and GLSL files.
Copyright year updated in some files.
Obsolete documentation files removed from DrawResources.
2014-02-20 16:15:17 +04:00

4211 lines
116 KiB
C++

// Created on: 1991-08-09
// Created by: JCV
// Copyright (c) 1991-1999 Matra Datavision
// Copyright (c) 1999-2014 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.
// Modified RLE 9 Sep 1993
// pmn : modified 28-01-97 : fixed a mistake in LocateParameter (PRO6973)
// pmn : modified 4-11-96 : fixed a mistake in BuildKnots (PRO6124)
// pmn : modified 28-Jun-96 : fixed a mistake in AntiBoorScheme
// xab : modified 15-Jun-95 : fixed a mistake in IsRational
// xab : modified 15-Mar-95 : removed Epsilon comparison in IsRational
// added RationalDerivatives.
// xab : 30-Mar-95 : fixed coupling with lti in RationalDerivatives
// xab : 15-Mar-96 : fixed a typo in Eval with extrapolation
// jct : 15-Apr-97 : added TangExtendToConstraint
// jct : 24-Apr-97 : correction on computation of Tbord and NewFlatKnots
// in TangExtendToConstraint; Continuity can be equal to 0
#include <BSplCLib.ixx>
#include <PLib.hxx>
#include <NCollection_LocalArray.hxx>
#include <Precision.hxx>
#include <Standard_NotImplemented.hxx>
typedef gp_Pnt Pnt;
typedef gp_Vec Vec;
typedef TColgp_Array1OfPnt Array1OfPnt;
typedef TColStd_Array1OfReal Array1OfReal;
typedef TColStd_Array1OfInteger Array1OfInteger;
//=======================================================================
//class : BSplCLib_LocalMatrix
//purpose: Auxiliary class optimizing creation of matrix buffer for
// evaluation of bspline (using stack allocation for main matrix)
//=======================================================================
class BSplCLib_LocalMatrix : public math_Matrix
{
public:
BSplCLib_LocalMatrix (Standard_Integer DerivativeRequest, Standard_Integer Order)
: math_Matrix (myBuffer, 1, DerivativeRequest + 1, 1, Order)
{
Standard_OutOfRange_Raise_if (DerivativeRequest > BSplCLib::MaxDegree() ||
Order > BSplCLib::MaxDegree()+1 || BSplCLib::MaxDegree() > 25,
"BSplCLib: bspline degree is greater than maximum supported");
}
private:
// local buffer, to be sufficient for addressing by index [Degree+1][Degree+1]
// (see math_Matrix implementation)
Standard_Real myBuffer[27*27];
};
//=======================================================================
//function : Hunt
//purpose :
//=======================================================================
void BSplCLib::Hunt (const Array1OfReal& XX,
const Standard_Real X,
Standard_Integer& Ilc)
{
// replaced by simple dichotomy (RLE)
Ilc = XX.Lower();
const Standard_Real *px = &XX(Ilc);
px -= Ilc;
if (X < px[Ilc]) {
Ilc--;
return;
}
Standard_Integer Ihi = XX.Upper();
if (X > px[Ihi]) {
Ilc = Ihi + 1;
return;
}
Standard_Integer Im;
while (Ihi - Ilc != 1) {
Im = (Ihi + Ilc) >> 1;
if (X > px[Im]) Ilc = Im;
else Ihi = Im;
}
}
//=======================================================================
//function : FirstUKnotIndex
//purpose :
//=======================================================================
Standard_Integer BSplCLib::FirstUKnotIndex (const Standard_Integer Degree,
const TColStd_Array1OfInteger& Mults)
{
Standard_Integer Index = Mults.Lower();
Standard_Integer SigmaMult = Mults(Index);
while (SigmaMult <= Degree) {
Index++;
SigmaMult += Mults (Index);
}
return Index;
}
//=======================================================================
//function : LastUKnotIndex
//purpose :
//=======================================================================
Standard_Integer BSplCLib::LastUKnotIndex (const Standard_Integer Degree,
const Array1OfInteger& Mults)
{
Standard_Integer Index = Mults.Upper();
Standard_Integer SigmaMult = Mults(Index);
while (SigmaMult <= Degree) {
Index--;
SigmaMult += Mults.Value (Index);
}
return Index;
}
//=======================================================================
//function : FlatIndex
//purpose :
//=======================================================================
Standard_Integer BSplCLib::FlatIndex
(const Standard_Integer Degree,
const Standard_Integer Index,
const TColStd_Array1OfInteger& Mults,
const Standard_Boolean Periodic)
{
Standard_Integer i, index = Index;
const Standard_Integer MLower = Mults.Lower();
const Standard_Integer *pmu = &Mults(MLower);
pmu -= MLower;
for (i = MLower + 1; i <= Index; i++)
index += pmu[i] - 1;
if ( Periodic)
index += Degree;
else
index += pmu[MLower] - 1;
return index;
}
//=======================================================================
//function : LocateParameter
//purpose : Processing of nodes with multiplicities
//pmn 28-01-97 -> compute eventual of the period.
//=======================================================================
void BSplCLib::LocateParameter
(const Standard_Integer , //Degree,
const Array1OfReal& Knots,
const Array1OfInteger& , //Mults,
const Standard_Real U,
const Standard_Boolean IsPeriodic,
const Standard_Integer FromK1,
const Standard_Integer ToK2,
Standard_Integer& KnotIndex,
Standard_Real& NewU)
{
Standard_Real uf = 0, ul=1;
if (IsPeriodic) {
uf = Knots(Knots.Lower());
ul = Knots(Knots.Upper());
}
BSplCLib::LocateParameter(Knots,U,IsPeriodic,FromK1,ToK2,
KnotIndex,NewU, uf, ul);
}
//=======================================================================
//function : LocateParameter
//purpose : For plane nodes
// pmn 28-01-97 -> There is a need of the degre to calculate
// the eventual period
//=======================================================================
void BSplCLib::LocateParameter
(const Standard_Integer Degree,
const Array1OfReal& Knots,
const Standard_Real U,
const Standard_Boolean IsPeriodic,
const Standard_Integer FromK1,
const Standard_Integer ToK2,
Standard_Integer& KnotIndex,
Standard_Real& NewU)
{
if (IsPeriodic)
BSplCLib::LocateParameter(Knots, U, IsPeriodic, FromK1, ToK2,
KnotIndex, NewU,
Knots(Knots.Lower() + Degree),
Knots(Knots.Upper() - Degree));
else
BSplCLib::LocateParameter(Knots, U, IsPeriodic, FromK1, ToK2,
KnotIndex, NewU,
0.,
1.);
}
//=======================================================================
//function : LocateParameter
//purpose : Effective computation
// pmn 28-01-97 : Add limits of the period as input argument,
// as it is imposible to produce them at this level.
//=======================================================================
void BSplCLib::LocateParameter
(const TColStd_Array1OfReal& Knots,
const Standard_Real U,
const Standard_Boolean IsPeriodic,
const Standard_Integer FromK1,
const Standard_Integer ToK2,
Standard_Integer& KnotIndex,
Standard_Real& NewU,
const Standard_Real UFirst,
const Standard_Real ULast)
{
Standard_Integer First,Last;
if (FromK1 < ToK2) {
First = FromK1;
Last = ToK2;
}
else {
First = ToK2;
Last = FromK1;
}
Standard_Integer Last1 = Last - 1;
NewU = U;
if (IsPeriodic) {
Standard_Real Period = ULast - UFirst;
while (NewU > ULast )
NewU -= Period;
while (NewU < UFirst)
NewU += Period;
}
BSplCLib::Hunt (Knots, NewU, KnotIndex);
Standard_Real Eps = Epsilon(U);
Standard_Real val;
if (Eps < 0) Eps = - Eps;
Standard_Integer KLower = Knots.Lower();
const Standard_Real *knots = &Knots(KLower);
knots -= KLower;
if ( KnotIndex < Knots.Upper()) {
val = NewU - knots[KnotIndex + 1];
if (val < 0) val = - val;
// <= to be coherent with Segment where Eps corresponds to a bit of error.
if (val <= Eps) KnotIndex++;
}
if (KnotIndex < First) KnotIndex = First;
if (KnotIndex > Last1) KnotIndex = Last1;
if (KnotIndex != Last1) {
Standard_Real K1 = knots[KnotIndex];
Standard_Real K2 = knots[KnotIndex + 1];
val = K2 - K1;
if (val < 0) val = - val;
while (val <= Eps) {
KnotIndex++;
K1 = K2;
K2 = knots[KnotIndex + 1];
val = K2 - K1;
if (val < 0) val = - val;
}
}
}
//=======================================================================
//function : LocateParameter
//purpose : the index is recomputed only if out of range
//pmn 28-01-97 -> eventual computation of the period.
//=======================================================================
void BSplCLib::LocateParameter
(const Standard_Integer Degree,
const TColStd_Array1OfReal& Knots,
const TColStd_Array1OfInteger& Mults,
const Standard_Real U,
const Standard_Boolean Periodic,
Standard_Integer& KnotIndex,
Standard_Real& NewU)
{
Standard_Integer first,last;
if (&Mults) {
if (Periodic) {
first = Knots.Lower();
last = Knots.Upper();
}
else {
first = FirstUKnotIndex(Degree,Mults);
last = LastUKnotIndex (Degree,Mults);
}
}
else {
first = Knots.Lower() + Degree;
last = Knots.Upper() - Degree;
}
if ( KnotIndex < first || KnotIndex > last)
BSplCLib::LocateParameter(Knots, U, Periodic, first, last,
KnotIndex, NewU, Knots(first), Knots(last));
else
NewU = U;
}
//=======================================================================
//function : MaxKnotMult
//purpose :
//=======================================================================
Standard_Integer BSplCLib::MaxKnotMult
(const Array1OfInteger& Mults,
const Standard_Integer FromK1,
const Standard_Integer ToK2)
{
Standard_Integer MLower = Mults.Lower();
const Standard_Integer *pmu = &Mults(MLower);
pmu -= MLower;
Standard_Integer MaxMult = pmu[FromK1];
for (Standard_Integer i = FromK1; i <= ToK2; i++) {
if (MaxMult < pmu[i]) MaxMult = pmu[i];
}
return MaxMult;
}
//=======================================================================
//function : MinKnotMult
//purpose :
//=======================================================================
Standard_Integer BSplCLib::MinKnotMult
(const Array1OfInteger& Mults,
const Standard_Integer FromK1,
const Standard_Integer ToK2)
{
Standard_Integer MLower = Mults.Lower();
const Standard_Integer *pmu = &Mults(MLower);
pmu -= MLower;
Standard_Integer MinMult = pmu[FromK1];
for (Standard_Integer i = FromK1; i <= ToK2; i++) {
if (MinMult > pmu[i]) MinMult = pmu[i];
}
return MinMult;
}
//=======================================================================
//function : NbPoles
//purpose :
//=======================================================================
Standard_Integer BSplCLib::NbPoles(const Standard_Integer Degree,
const Standard_Boolean Periodic,
const TColStd_Array1OfInteger& Mults)
{
Standard_Integer i,sigma = 0;
Standard_Integer f = Mults.Lower();
Standard_Integer l = Mults.Upper();
const Standard_Integer * pmu = &Mults(f);
pmu -= f;
Standard_Integer Mf = pmu[f];
Standard_Integer Ml = pmu[l];
if (Mf <= 0) return 0;
if (Ml <= 0) return 0;
if (Periodic) {
if (Mf > Degree) return 0;
if (Ml > Degree) return 0;
if (Mf != Ml ) return 0;
sigma = Mf;
}
else {
Standard_Integer Deg1 = Degree + 1;
if (Mf > Deg1) return 0;
if (Ml > Deg1) return 0;
sigma = Mf + Ml - Deg1;
}
for (i = f + 1; i < l; i++) {
if (pmu[i] <= 0 ) return 0;
if (pmu[i] > Degree) return 0;
sigma += pmu[i];
}
return sigma;
}
//=======================================================================
//function : KnotSequenceLength
//purpose :
//=======================================================================
Standard_Integer BSplCLib::KnotSequenceLength
(const TColStd_Array1OfInteger& Mults,
const Standard_Integer Degree,
const Standard_Boolean Periodic)
{
Standard_Integer i,l = 0;
Standard_Integer MLower = Mults.Lower();
Standard_Integer MUpper = Mults.Upper();
const Standard_Integer * pmu = &Mults(MLower);
pmu -= MLower;
for (i = MLower; i <= MUpper; i++)
l += pmu[i];
if (Periodic) l += 2 * (Degree + 1 - pmu[MLower]);
return l;
}
//=======================================================================
//function : KnotSequence
//purpose :
//=======================================================================
void BSplCLib::KnotSequence
(const TColStd_Array1OfReal& Knots,
const TColStd_Array1OfInteger& Mults,
TColStd_Array1OfReal& KnotSeq)
{
BSplCLib::KnotSequence(Knots,Mults,0,Standard_False,KnotSeq);
}
//=======================================================================
//function : KnotSequence
//purpose :
//=======================================================================
void BSplCLib::KnotSequence
(const TColStd_Array1OfReal& Knots,
const TColStd_Array1OfInteger& Mults,
const Standard_Integer Degree,
const Standard_Boolean Periodic,
TColStd_Array1OfReal& KnotSeq)
{
Standard_Real K;
Standard_Integer Mult;
Standard_Integer MLower = Mults.Lower();
const Standard_Integer * pmu = &Mults(MLower);
pmu -= MLower;
Standard_Integer KLower = Knots.Lower();
Standard_Integer KUpper = Knots.Upper();
const Standard_Real * pkn = &Knots(KLower);
pkn -= KLower;
Standard_Integer M1 = Degree + 1 - pmu[MLower]; // for periodic
Standard_Integer i,j,index = Periodic ? M1 + 1 : 1;
for (i = KLower; i <= KUpper; i++) {
Mult = pmu[i];
K = pkn[i];
for (j = 1; j <= Mult; j++) {
KnotSeq (index) = K;
index++;
}
}
if (Periodic) {
Standard_Real period = pkn[KUpper] - pkn[KLower];
Standard_Integer m;
m = 1;
j = KUpper - 1;
for (i = M1; i >= 1; i--) {
KnotSeq(i) = pkn[j] - period;
m++;
if (m > pmu[j]) {
j--;
m = 1;
}
}
m = 1;
j = KLower + 1;
for (i = index; i <= KnotSeq.Upper(); i++) {
KnotSeq(i) = pkn[j] + period;
m++;
if (m > pmu[j]) {
j++;
m = 1;
}
}
}
}
//=======================================================================
//function : KnotsLength
//purpose :
//=======================================================================
Standard_Integer BSplCLib::KnotsLength(const TColStd_Array1OfReal& SeqKnots,
// const Standard_Boolean Periodic)
const Standard_Boolean )
{
Standard_Integer sizeMult = 1;
Standard_Real val = SeqKnots(1);
for (Standard_Integer jj=2;
jj<=SeqKnots.Length();jj++)
{
// test on strict equality on nodes
if (SeqKnots(jj)!=val)
{
val = SeqKnots(jj);
sizeMult++;
}
}
return sizeMult;
}
//=======================================================================
//function : Knots
//purpose :
//=======================================================================
void BSplCLib::Knots(const TColStd_Array1OfReal& SeqKnots,
TColStd_Array1OfReal &knots,
TColStd_Array1OfInteger &mult,
// const Standard_Boolean Periodic)
const Standard_Boolean )
{
Standard_Real val = SeqKnots(1);
Standard_Integer kk=1;
knots(kk) = val;
mult(kk) = 1;
for (Standard_Integer jj=2;jj<=SeqKnots.Length();jj++)
{
// test on strict equality on nodes
if (SeqKnots(jj)!=val)
{
val = SeqKnots(jj);
kk++;
knots(kk) = val;
mult(kk) = 1;
}
else
{
mult(kk)++;
}
}
}
//=======================================================================
//function : KnotForm
//purpose :
//=======================================================================
BSplCLib_KnotDistribution BSplCLib::KnotForm
(const Array1OfReal& Knots,
const Standard_Integer FromK1,
const Standard_Integer ToK2)
{
Standard_Real DU0,DU1,Ui,Uj,Eps0,val;
BSplCLib_KnotDistribution KForm = BSplCLib_Uniform;
Standard_Integer KLower = Knots.Lower();
const Standard_Real * pkn = &Knots(KLower);
pkn -= KLower;
Ui = pkn[FromK1];
if (Ui < 0) Ui = - Ui;
Uj = pkn[FromK1 + 1];
if (Uj < 0) Uj = - Uj;
DU0 = Uj - Ui;
if (DU0 < 0) DU0 = - DU0;
Eps0 = Epsilon (Ui) + Epsilon (Uj) + Epsilon (DU0);
Standard_Integer i = FromK1 + 1;
while (KForm != BSplCLib_NonUniform && i < ToK2) {
Ui = pkn[i];
if (Ui < 0) Ui = - Ui;
i++;
Uj = pkn[i];
if (Uj < 0) Uj = - Uj;
DU1 = Uj - Ui;
if (DU1 < 0) DU1 = - DU1;
val = DU1 - DU0;
if (val < 0) val = -val;
if (val > Eps0) KForm = BSplCLib_NonUniform;
DU0 = DU1;
Eps0 = Epsilon (Ui) + Epsilon (Uj) + Epsilon (DU0);
}
return KForm;
}
//=======================================================================
//function : MultForm
//purpose :
//=======================================================================
BSplCLib_MultDistribution BSplCLib::MultForm
(const Array1OfInteger& Mults,
const Standard_Integer FromK1,
const Standard_Integer ToK2)
{
Standard_Integer First,Last;
if (FromK1 < ToK2) {
First = FromK1;
Last = ToK2;
}
else {
First = ToK2;
Last = FromK1;
}
Standard_Integer MLower = Mults.Lower();
const Standard_Integer *pmu = &Mults(MLower);
pmu -= MLower;
Standard_Integer FirstMult = pmu[First];
BSplCLib_MultDistribution MForm = BSplCLib_Constant;
Standard_Integer i = First + 1;
Standard_Integer Mult = pmu[i];
// while (MForm != BSplCLib_NonUniform && i <= Last) { ???????????JR????????
while (MForm != BSplCLib_NonConstant && i <= Last) {
if (i == First + 1) {
if (Mult != FirstMult) MForm = BSplCLib_QuasiConstant;
}
else if (i == Last) {
if (MForm == BSplCLib_QuasiConstant) {
if (FirstMult != pmu[i]) MForm = BSplCLib_NonConstant;
}
else {
if (Mult != pmu[i]) MForm = BSplCLib_NonConstant;
}
}
else {
if (Mult != pmu[i]) MForm = BSplCLib_NonConstant;
Mult = pmu[i];
}
i++;
}
return MForm;
}
//=======================================================================
//function : KnotAnalysis
//purpose :
//=======================================================================
void BSplCLib::KnotAnalysis (const Standard_Integer Degree,
const Standard_Boolean Periodic,
const TColStd_Array1OfReal& CKnots,
const TColStd_Array1OfInteger& CMults,
GeomAbs_BSplKnotDistribution& KnotForm,
Standard_Integer& MaxKnotMult)
{
KnotForm = GeomAbs_NonUniform;
BSplCLib_KnotDistribution KSet =
BSplCLib::KnotForm (CKnots, 1, CKnots.Length());
if (KSet == BSplCLib_Uniform) {
BSplCLib_MultDistribution MSet =
BSplCLib::MultForm (CMults, 1, CMults.Length());
switch (MSet) {
case BSplCLib_NonConstant :
break;
case BSplCLib_Constant :
if (CKnots.Length() == 2) {
KnotForm = GeomAbs_PiecewiseBezier;
}
else {
if (CMults (1) == 1) KnotForm = GeomAbs_Uniform;
}
break;
case BSplCLib_QuasiConstant :
if (CMults (1) == Degree + 1) {
Standard_Real M = CMults (2);
if (M == Degree ) KnotForm = GeomAbs_PiecewiseBezier;
else if (M == 1) KnotForm = GeomAbs_QuasiUniform;
}
break;
}
}
Standard_Integer FirstKM =
Periodic ? CKnots.Lower() : BSplCLib::FirstUKnotIndex (Degree,CMults);
Standard_Integer LastKM =
Periodic ? CKnots.Upper() : BSplCLib::LastUKnotIndex (Degree,CMults);
MaxKnotMult = 0;
if (LastKM - FirstKM != 1) {
Standard_Integer Multi;
for (Standard_Integer i = FirstKM + 1; i < LastKM; i++) {
Multi = CMults (i);
MaxKnotMult = Max (MaxKnotMult, Multi);
}
}
}
//=======================================================================
//function : Reparametrize
//purpose :
//=======================================================================
void BSplCLib::Reparametrize
(const Standard_Real U1,
const Standard_Real U2,
Array1OfReal& Knots)
{
Standard_Integer Lower = Knots.Lower();
Standard_Integer Upper = Knots.Upper();
Standard_Real UFirst = Min (U1, U2);
Standard_Real ULast = Max (U1, U2);
Standard_Real NewLength = ULast - UFirst;
BSplCLib_KnotDistribution KSet = BSplCLib::KnotForm (Knots, Lower, Upper);
if (KSet == BSplCLib_Uniform) {
Standard_Real DU = NewLength / (Upper - Lower);
Knots (Lower) = UFirst;
for (Standard_Integer i = Lower + 1; i <= Upper; i++) {
Knots (i) = Knots (i-1) + DU;
}
}
else {
Standard_Real K2;
Standard_Real Ratio;
Standard_Real K1 = Knots (Lower);
Standard_Real Length = Knots (Upper) - Knots (Lower);
Knots (Lower) = UFirst;
for (Standard_Integer i = Lower + 1; i <= Upper; i++) {
K2 = Knots (i);
Ratio = (K2 - K1) / Length;
Knots (i) = Knots (i-1) + (NewLength * Ratio);
//for CheckCurveData
Standard_Real Eps = Epsilon( Abs(Knots(i-1)) );
if (Knots(i) - Knots(i-1) <= Eps)
Knots(i) = NextAfter (Knots(i-1) + Eps, RealLast());
K1 = K2;
}
}
}
//=======================================================================
//function : Reverse
//purpose :
//=======================================================================
void BSplCLib::Reverse(TColStd_Array1OfReal& Knots)
{
Standard_Integer first = Knots.Lower();
Standard_Integer last = Knots.Upper();
Standard_Real kfirst = Knots(first);
Standard_Real klast = Knots(last);
Standard_Real tfirst = kfirst;
Standard_Real tlast = klast;
first++;
last--;
while (first <= last) {
tfirst += klast - Knots(last);
tlast -= Knots(first) - kfirst;
kfirst = Knots(first);
klast = Knots(last);
Knots(first) = tfirst;
Knots(last) = tlast;
first++;
last--;
}
}
//=======================================================================
//function : Reverse
//purpose :
//=======================================================================
void BSplCLib::Reverse(TColStd_Array1OfInteger& Mults)
{
Standard_Integer first = Mults.Lower();
Standard_Integer last = Mults.Upper();
Standard_Integer temp;
while (first < last) {
temp = Mults(first);
Mults(first) = Mults(last);
Mults(last) = temp;
first++;
last--;
}
}
//=======================================================================
//function : Reverse
//purpose :
//=======================================================================
void BSplCLib::Reverse(TColStd_Array1OfReal& Weights,
const Standard_Integer L)
{
Standard_Integer i, l = L;
l = Weights.Lower()+(l-Weights.Lower())%(Weights.Upper()-Weights.Lower()+1);
TColStd_Array1OfReal temp(0,Weights.Length()-1);
for (i = Weights.Lower(); i <= l; i++)
temp(l-i) = Weights(i);
for (i = l+1; i <= Weights.Upper(); i++)
temp(l-Weights.Lower()+Weights.Upper()-i+1) = Weights(i);
for (i = Weights.Lower(); i <= Weights.Upper(); i++)
Weights(i) = temp(i-Weights.Lower());
}
//=======================================================================
//function : IsRational
//purpose :
//=======================================================================
Standard_Boolean BSplCLib::IsRational(const TColStd_Array1OfReal& Weights,
const Standard_Integer I1,
const Standard_Integer I2,
// const Standard_Real Epsi)
const Standard_Real )
{
Standard_Integer i, f = Weights.Lower(), l = Weights.Length();
Standard_Integer I3 = I2 - f;
const Standard_Real * WG = &Weights(f);
WG -= f;
for (i = I1 - f; i < I3; i++) {
if (WG[f + (i % l)] != WG[f + ((i + 1) % l)]) return Standard_True;
}
return Standard_False ;
}
//=======================================================================
//function : Eval
//purpose : evaluate point and derivatives
//=======================================================================
void BSplCLib::Eval(const Standard_Real U,
const Standard_Integer Degree,
Standard_Real& Knots,
const Standard_Integer Dimension,
Standard_Real& Poles)
{
Standard_Integer step,i,Dms,Dm1,Dpi,Sti;
Standard_Real X, Y, *poles, *knots = &Knots;
Dm1 = Dms = Degree;
Dm1--;
Dms++;
switch (Dimension) {
case 1 : {
for (step = - 1; step < Dm1; step++) {
Dms--;
poles = &Poles;
Dpi = Dm1;
Sti = step;
for (i = 0; i < Dms; i++) {
Dpi++;
Sti++;
X = (knots[Dpi] - U) / (knots[Dpi] - knots[Sti]);
Y = 1 - X;
poles[0] *= X; poles[0] += Y * poles[1];
poles += 1;
}
}
break;
}
case 2 : {
for (step = - 1; step < Dm1; step++) {
Dms--;
poles = &Poles;
Dpi = Dm1;
Sti = step;
for (i = 0; i < Dms; i++) {
Dpi++;
Sti++;
X = (knots[Dpi] - U) / (knots[Dpi] - knots[Sti]);
Y = 1 - X;
poles[0] *= X; poles[0] += Y * poles[2];
poles[1] *= X; poles[1] += Y * poles[3];
poles += 2;
}
}
break;
}
case 3 : {
for (step = - 1; step < Dm1; step++) {
Dms--;
poles = &Poles;
Dpi = Dm1;
Sti = step;
for (i = 0; i < Dms; i++) {
Dpi++;
Sti++;
X = (knots[Dpi] - U) / (knots[Dpi] - knots[Sti]);
Y = 1 - X;
poles[0] *= X; poles[0] += Y * poles[3];
poles[1] *= X; poles[1] += Y * poles[4];
poles[2] *= X; poles[2] += Y * poles[5];
poles += 3;
}
}
break;
}
case 4 : {
for (step = - 1; step < Dm1; step++) {
Dms--;
poles = &Poles;
Dpi = Dm1;
Sti = step;
for (i = 0; i < Dms; i++) {
Dpi++;
Sti++;
X = (knots[Dpi] - U) / (knots[Dpi] - knots[Sti]);
Y = 1 - X;
poles[0] *= X; poles[0] += Y * poles[4];
poles[1] *= X; poles[1] += Y * poles[5];
poles[2] *= X; poles[2] += Y * poles[6];
poles[3] *= X; poles[3] += Y * poles[7];
poles += 4;
}
}
break;
}
default : {
Standard_Integer k;
for (step = - 1; step < Dm1; step++) {
Dms--;
poles = &Poles;
Dpi = Dm1;
Sti = step;
for (i = 0; i < Dms; i++) {
Dpi++;
Sti++;
X = (knots[Dpi] - U) / (knots[Dpi] - knots[Sti]);
Y = 1 - X;
for (k = 0; k < Dimension; k++) {
poles[k] *= X;
poles[k] += Y * poles[k + Dimension];
}
poles += Dimension;
}
}
}
}
}
//=======================================================================
//function : BoorScheme
//purpose :
//=======================================================================
void BSplCLib::BoorScheme(const Standard_Real U,
const Standard_Integer Degree,
Standard_Real& Knots,
const Standard_Integer Dimension,
Standard_Real& Poles,
const Standard_Integer Depth,
const Standard_Integer Length)
{
//
// Compute the values
//
// P(i,j) (U).
//
// for i = 0 to Depth,
// j = 0 to Length - i
//
// The Boor scheme is :
//
// P(0,j) = Pole(j)
// P(i,j) = x * P(i-1,j) + (1-x) * P(i-1,j+1)
//
// where x = (knot(i+j+Degree) - U) / (knot(i+j+Degree) - knot(i+j))
//
//
// The values are stored in the array Poles
// They are alternatively written if the odd and even positions.
//
// The successives contents of the array are
// ***** means unitialised, l = Degree + Length
//
// P(0,0) ****** P(0,1) ...... P(0,l-1) ******** P(0,l)
// P(0,0) P(1,0) P(0,1) ...... P(0,l-1) P(1,l-1) P(0,l)
// P(0,0) P(1,0) P(2,0) ...... P(2,l-1) P(1,l-1) P(0,l)
//
Standard_Integer i,k,step;
Standard_Real *knots = &Knots;
Standard_Real *pole, *firstpole = &Poles - 2 * Dimension;
// the steps of recursion
for (step = 0; step < Depth; step++) {
firstpole += Dimension;
pole = firstpole;
// compute the new row of poles
for (i = step; i < Length; i++) {
pole += 2 * Dimension;
// coefficient
Standard_Real X = (knots[i+Degree-step] - U)
/ (knots[i+Degree-step] - knots[i]);
Standard_Real Y = 1. - X;
// Value
// P(i,j) = X * P(i-1,j) + (1-X) * P(i-1,j+1)
for (k = 0; k < Dimension; k++)
pole[k] = X * pole[k - Dimension] + Y * pole[k + Dimension];
}
}
}
//=======================================================================
//function : AntiBoorScheme
//purpose :
//=======================================================================
Standard_Boolean BSplCLib::AntiBoorScheme(const Standard_Real U,
const Standard_Integer Degree,
Standard_Real& Knots,
const Standard_Integer Dimension,
Standard_Real& Poles,
const Standard_Integer Depth,
const Standard_Integer Length,
const Standard_Real Tolerance)
{
// do the Boor scheme reverted.
Standard_Integer i,k,step, half_length;
Standard_Real *knots = &Knots;
Standard_Real z,X,Y,*pole, *firstpole = &Poles + (Depth-1) * Dimension;
// Test the special case length = 1
// only verification of the central point
if (Length == 1) {
X = (knots[Degree] - U) / (knots[Degree] - knots[0]);
Y = 1. - X;
for (k = 0; k < Dimension; k++) {
z = X * firstpole[k] + Y * firstpole[k+2*Dimension];
if (Abs(z - firstpole[k+Dimension]) > Tolerance)
return Standard_False;
}
return Standard_True;
}
// General case
// the steps of recursion
for (step = Depth-1; step >= 0; step--) {
firstpole -= Dimension;
pole = firstpole;
// first step from left to right
for (i = step; i < Length-1; i++) {
pole += 2 * Dimension;
X = (knots[i+Degree-step] - U) / (knots[i+Degree-step] - knots[i]);
Y = 1. - X;
for (k = 0; k < Dimension; k++)
pole[k+Dimension] = (pole[k] - X*pole[k-Dimension]) / Y;
}
// second step from right to left
pole += 4* Dimension;
half_length = (Length - 1 + step) / 2 ;
//
// only do half of the way from right to left
// otherwise it start degenerating because of
// overflows
//
for (i = Length-1; i > half_length ; i--) {
pole -= 2 * Dimension;
// coefficient
X = (knots[i+Degree-step] - U) / (knots[i+Degree-step] - knots[i]);
Y = 1. - X;
for (k = 0; k < Dimension; k++) {
z = (pole[k] - Y * pole[k+Dimension]) / X;
if (Abs(z-pole[k-Dimension]) > Tolerance)
return Standard_False;
pole[k-Dimension] += z;
pole[k-Dimension] /= 2.;
}
}
}
return Standard_True;
}
//=======================================================================
//function : Derivative
//purpose :
//=======================================================================
void BSplCLib::Derivative(const Standard_Integer Degree,
Standard_Real& Knots,
const Standard_Integer Dimension,
const Standard_Integer Length,
const Standard_Integer Order,
Standard_Real& Poles)
{
Standard_Integer i,k,step,span = Degree;
Standard_Real *knot = &Knots;
for (step = 1; step <= Order; step++) {
Standard_Real* pole = &Poles;
for (i = step; i < Length; i++) {
Standard_Real coef = - span / (knot[i+span] - knot[i]);
for (k = 0; k < Dimension; k++) {
pole[k] -= pole[k+Dimension];
pole[k] *= coef;
}
pole += Dimension;
}
span--;
}
}
//=======================================================================
//function : Bohm
//purpose :
//=======================================================================
void BSplCLib::Bohm(const Standard_Real U,
const Standard_Integer Degree,
const Standard_Integer N,
Standard_Real& Knots,
const Standard_Integer Dimension,
Standard_Real& Poles)
{
// First phase independant of U, compute the poles of the derivatives
Standard_Integer i,j,iDim,min,Dmi,DDmi,jDmi,Degm1;
Standard_Real *knot = &Knots, *pole, coef, *tbis, *psav, *psDD, *psDDmDim;
psav = &Poles;
if (N < Degree) min = N;
else min = Degree;
Degm1 = Degree - 1;
DDmi = (Degree << 1) + 1;
switch (Dimension) {
case 1 : {
psDD = psav + Degree;
psDDmDim = psDD - 1;
for (i = 0; i < Degree; i++) {
DDmi--;
pole = psDD;
tbis = psDDmDim;
jDmi = DDmi;
for (j = Degm1; j >= i; j--) {
jDmi--;
*pole -= *tbis; *pole /= (knot[jDmi] - knot[j]);
pole--;
tbis--;
}
}
// Second phase, dependant of U
iDim = - 1;
for (i = 0; i < Degree; i++) {
iDim += 1;
pole = psav + iDim;
tbis = pole + 1;
coef = U - knot[i];
for (j = i; j >= 0; j--) {
*pole += coef * (*tbis);
pole--;
tbis--;
}
}
// multiply by the degrees
coef = Degree;
Dmi = Degree;
pole = psav + 1;
for (i = 1; i <= min; i++) {
*pole *= coef; pole++;
Dmi--;
coef *= Dmi;
}
break;
}
case 2 : {
psDD = psav + (Degree << 1);
psDDmDim = psDD - 2;
for (i = 0; i < Degree; i++) {
DDmi--;
pole = psDD;
tbis = psDDmDim;
jDmi = DDmi;
for (j = Degm1; j >= i; j--) {
jDmi--;
coef = 1. / (knot[jDmi] - knot[j]);
*pole -= *tbis; *pole *= coef; pole++; tbis++;
*pole -= *tbis; *pole *= coef;
pole -= 3;
tbis -= 3;
}
}
// Second phase, dependant of U
iDim = - 2;
for (i = 0; i < Degree; i++) {
iDim += 2;
pole = psav + iDim;
tbis = pole + 2;
coef = U - knot[i];
for (j = i; j >= 0; j--) {
*pole += coef * (*tbis); pole++; tbis++;
*pole += coef * (*tbis);
pole -= 3;
tbis -= 3;
}
}
// multiply by the degrees
coef = Degree;
Dmi = Degree;
pole = psav + 2;
for (i = 1; i <= min; i++) {
*pole *= coef; pole++;
*pole *= coef; pole++;
Dmi--;
coef *= Dmi;
}
break;
}
case 3 : {
psDD = psav + (Degree << 1) + Degree;
psDDmDim = psDD - 3;
for (i = 0; i < Degree; i++) {
DDmi--;
pole = psDD;
tbis = psDDmDim;
jDmi = DDmi;
for (j = Degm1; j >= i; j--) {
jDmi--;
coef = 1. / (knot[jDmi] - knot[j]);
*pole -= *tbis; *pole *= coef; pole++; tbis++;
*pole -= *tbis; *pole *= coef; pole++; tbis++;
*pole -= *tbis; *pole *= coef;
pole -= 5;
tbis -= 5;
}
}
// Second phase, dependant of U
iDim = - 3;
for (i = 0; i < Degree; i++) {
iDim += 3;
pole = psav + iDim;
tbis = pole + 3;
coef = U - knot[i];
for (j = i; j >= 0; j--) {
*pole += coef * (*tbis); pole++; tbis++;
*pole += coef * (*tbis); pole++; tbis++;
*pole += coef * (*tbis);
pole -= 5;
tbis -= 5;
}
}
// multiply by the degrees
coef = Degree;
Dmi = Degree;
pole = psav + 3;
for (i = 1; i <= min; i++) {
*pole *= coef; pole++;
*pole *= coef; pole++;
*pole *= coef; pole++;
Dmi--;
coef *= Dmi;
}
break;
}
case 4 : {
psDD = psav + (Degree << 2);
psDDmDim = psDD - 4;
for (i = 0; i < Degree; i++) {
DDmi--;
pole = psDD;
tbis = psDDmDim;
jDmi = DDmi;
for (j = Degm1; j >= i; j--) {
jDmi--;
coef = 1. / (knot[jDmi] - knot[j]);
*pole -= *tbis; *pole *= coef; pole++; tbis++;
*pole -= *tbis; *pole *= coef; pole++; tbis++;
*pole -= *tbis; *pole *= coef; pole++; tbis++;
*pole -= *tbis; *pole *= coef;
pole -= 7;
tbis -= 7;
}
}
// Second phase, dependant of U
iDim = - 4;
for (i = 0; i < Degree; i++) {
iDim += 4;
pole = psav + iDim;
tbis = pole + 4;
coef = U - knot[i];
for (j = i; j >= 0; j--) {
*pole += coef * (*tbis); pole++; tbis++;
*pole += coef * (*tbis); pole++; tbis++;
*pole += coef * (*tbis); pole++; tbis++;
*pole += coef * (*tbis);
pole -= 7;
tbis -= 7;
}
}
// multiply by the degrees
coef = Degree;
Dmi = Degree;
pole = psav + 4;
for (i = 1; i <= min; i++) {
*pole *= coef; pole++;
*pole *= coef; pole++;
*pole *= coef; pole++;
*pole *= coef; pole++;
Dmi--;
coef *= Dmi;
}
break;
}
default : {
Standard_Integer k;
Standard_Integer Dim2 = Dimension << 1;
psDD = psav + Degree * Dimension;
psDDmDim = psDD - Dimension;
for (i = 0; i < Degree; i++) {
DDmi--;
pole = psDD;
tbis = psDDmDim;
jDmi = DDmi;
for (j = Degm1; j >= i; j--) {
jDmi--;
coef = 1. / (knot[jDmi] - knot[j]);
for (k = 0; k < Dimension; k++) {
*pole -= *tbis; *pole *= coef; pole++; tbis++;
}
pole -= Dim2;
tbis -= Dim2;
}
}
// Second phase, dependant of U
iDim = - Dimension;
for (i = 0; i < Degree; i++) {
iDim += Dimension;
pole = psav + iDim;
tbis = pole + Dimension;
coef = U - knot[i];
for (j = i; j >= 0; j--) {
for (k = 0; k < Dimension; k++) {
*pole += coef * (*tbis); pole++; tbis++;
}
pole -= Dim2;
tbis -= Dim2;
}
}
// multiply by the degrees
coef = Degree;
Dmi = Degree;
pole = psav + Dimension;
for (i = 1; i <= min; i++) {
for (k = 0; k < Dimension; k++) {
*pole *= coef; pole++;
}
Dmi--;
coef *= Dmi;
}
}
}
}
//=======================================================================
//function : BuildKnots
//purpose :
//=======================================================================
void BSplCLib::BuildKnots(const Standard_Integer Degree,
const Standard_Integer Index,
const Standard_Boolean Periodic,
const TColStd_Array1OfReal& Knots,
const TColStd_Array1OfInteger& Mults,
Standard_Real& LK)
{
Standard_Integer KLower = Knots.Lower();
const Standard_Real * pkn = &Knots(KLower);
pkn -= KLower;
Standard_Real *knot = &LK;
if (&Mults == NULL) {
switch (Degree) {
case 1 : {
Standard_Integer j = Index ;
knot[0] = pkn[j]; j++;
knot[1] = pkn[j];
break;
}
case 2 : {
Standard_Integer j = Index - 1;
knot[0] = pkn[j]; j++;
knot[1] = pkn[j]; j++;
knot[2] = pkn[j]; j++;
knot[3] = pkn[j];
break;
}
case 3 : {
Standard_Integer j = Index - 2;
knot[0] = pkn[j]; j++;
knot[1] = pkn[j]; j++;
knot[2] = pkn[j]; j++;
knot[3] = pkn[j]; j++;
knot[4] = pkn[j]; j++;
knot[5] = pkn[j];
break;
}
case 4 : {
Standard_Integer j = Index - 3;
knot[0] = pkn[j]; j++;
knot[1] = pkn[j]; j++;
knot[2] = pkn[j]; j++;
knot[3] = pkn[j]; j++;
knot[4] = pkn[j]; j++;
knot[5] = pkn[j]; j++;
knot[6] = pkn[j]; j++;
knot[7] = pkn[j];
break;
}
case 5 : {
Standard_Integer j = Index - 4;
knot[0] = pkn[j]; j++;
knot[1] = pkn[j]; j++;
knot[2] = pkn[j]; j++;
knot[3] = pkn[j]; j++;
knot[4] = pkn[j]; j++;
knot[5] = pkn[j]; j++;
knot[6] = pkn[j]; j++;
knot[7] = pkn[j]; j++;
knot[8] = pkn[j]; j++;
knot[9] = pkn[j];
break;
}
case 6 : {
Standard_Integer j = Index - 5;
knot[ 0] = pkn[j]; j++;
knot[ 1] = pkn[j]; j++;
knot[ 2] = pkn[j]; j++;
knot[ 3] = pkn[j]; j++;
knot[ 4] = pkn[j]; j++;
knot[ 5] = pkn[j]; j++;
knot[ 6] = pkn[j]; j++;
knot[ 7] = pkn[j]; j++;
knot[ 8] = pkn[j]; j++;
knot[ 9] = pkn[j]; j++;
knot[10] = pkn[j]; j++;
knot[11] = pkn[j];
break;
}
default : {
Standard_Integer i,j;
Standard_Integer Deg2 = Degree << 1;
j = Index - Degree;
for (i = 0; i < Deg2; i++) {
j++;
knot[i] = pkn[j];
}
}
}
}
else {
Standard_Integer i;
Standard_Integer Deg1 = Degree - 1;
Standard_Integer KUpper = Knots.Upper();
Standard_Integer MLower = Mults.Lower();
Standard_Integer MUpper = Mults.Upper();
const Standard_Integer * pmu = &Mults(MLower);
pmu -= MLower;
Standard_Real dknot = 0;
Standard_Integer ilow = Index , mlow = 0;
Standard_Integer iupp = Index + 1, mupp = 0;
Standard_Real loffset = 0., uoffset = 0.;
Standard_Boolean getlow = Standard_True, getupp = Standard_True;
if (Periodic) {
dknot = pkn[KUpper] - pkn[KLower];
if (iupp > MUpper) {
iupp = MLower + 1;
uoffset = dknot;
}
}
// Find the knots around Index
for (i = 0; i < Degree; i++) {
if (getlow) {
mlow++;
if (mlow > pmu[ilow]) {
mlow = 1;
ilow--;
getlow = (ilow >= MLower);
if (Periodic && !getlow) {
ilow = MUpper - 1;
loffset = dknot;
getlow = Standard_True;
}
}
if (getlow)
knot[Deg1 - i] = pkn[ilow] - loffset;
}
if (getupp) {
mupp++;
if (mupp > pmu[iupp]) {
mupp = 1;
iupp++;
getupp = (iupp <= MUpper);
if (Periodic && !getupp) {
iupp = MLower + 1;
uoffset = dknot;
getupp = Standard_True;
}
}
if (getupp)
knot[Degree + i] = pkn[iupp] + uoffset;
}
}
}
}
//=======================================================================
//function : PoleIndex
//purpose :
//=======================================================================
Standard_Integer BSplCLib::PoleIndex(const Standard_Integer Degree,
const Standard_Integer Index,
const Standard_Boolean Periodic,
const TColStd_Array1OfInteger& Mults)
{
Standard_Integer i, pindex = 0;
for (i = Mults.Lower(); i <= Index; i++)
pindex += Mults(i);
if (Periodic)
pindex -= Mults(Mults.Lower());
else
pindex -= Degree + 1;
return pindex;
}
//=======================================================================
//function : BuildBoor
//purpose : builds the local array for boor
//=======================================================================
void BSplCLib::BuildBoor(const Standard_Integer Index,
const Standard_Integer Length,
const Standard_Integer Dimension,
const TColStd_Array1OfReal& Poles,
Standard_Real& LP)
{
Standard_Real *poles = &LP;
Standard_Integer i,k, ip = Poles.Lower() + Index * Dimension;
for (i = 0; i < Length+1; i++) {
for (k = 0; k < Dimension; k++) {
poles[k] = Poles(ip);
ip++;
if (ip > Poles.Upper()) ip = Poles.Lower();
}
poles += 2 * Dimension;
}
}
//=======================================================================
//function : BoorIndex
//purpose :
//=======================================================================
Standard_Integer BSplCLib::BoorIndex(const Standard_Integer Index,
const Standard_Integer Length,
const Standard_Integer Depth)
{
if (Index <= Depth) return Index;
if (Index <= Length) return 2 * Index - Depth;
return Length + Index - Depth;
}
//=======================================================================
//function : GetPole
//purpose :
//=======================================================================
void BSplCLib::GetPole(const Standard_Integer Index,
const Standard_Integer Length,
const Standard_Integer Depth,
const Standard_Integer Dimension,
Standard_Real& LP,
Standard_Integer& Position,
TColStd_Array1OfReal& Pole)
{
Standard_Integer k;
Standard_Real* pole = &LP + BoorIndex(Index,Length,Depth) * Dimension;
for (k = 0; k < Dimension; k++) {
Pole(Position) = pole[k];
Position++;
}
if (Position > Pole.Upper()) Position = Pole.Lower();
}
//=======================================================================
//function : PrepareInsertKnots
//purpose :
//=======================================================================
Standard_Boolean BSplCLib::PrepareInsertKnots
(const Standard_Integer Degree,
const Standard_Boolean Periodic,
const TColStd_Array1OfReal& Knots,
const TColStd_Array1OfInteger& Mults,
const TColStd_Array1OfReal& AddKnots,
const TColStd_Array1OfInteger& AddMults,
Standard_Integer& NbPoles,
Standard_Integer& NbKnots,
const Standard_Real Tolerance,
const Standard_Boolean Add)
{
Standard_Boolean addflat = &AddMults == NULL;
Standard_Integer first,last;
if (Periodic) {
first = Knots.Lower();
last = Knots.Upper();
}
else {
first = FirstUKnotIndex(Degree,Mults);
last = LastUKnotIndex(Degree,Mults);
}
Standard_Real adeltaK1 = Knots(first)-AddKnots(AddKnots.Lower());
Standard_Real adeltaK2 = AddKnots(AddKnots.Upper())-Knots(last);
if (adeltaK1 > Tolerance) return Standard_False;
if (adeltaK2 > Tolerance) return Standard_False;
Standard_Integer sigma = 0, mult, amult;
NbKnots = 0;
Standard_Integer k = Knots.Lower() - 1;
Standard_Integer ak = AddKnots.Lower();
if(Periodic && AddKnots.Length() > 1)
{
//gka for case when segments was produced on full period only one knot
//was added in the end of curve
if(fabs(adeltaK1) <= Precision::PConfusion() &&
fabs(adeltaK2) <= Precision::PConfusion())
ak++;
}
Standard_Real au,oldau = AddKnots(ak),Eps;
while (ak <= AddKnots.Upper()) {
au = AddKnots(ak);
if (au < oldau) return Standard_False;
oldau = au;
Eps = Max(Tolerance,Epsilon(au));
while ((k < Knots.Upper()) && (Knots(k+1) - au <= Eps)) {
k++;
NbKnots++;
sigma += Mults(k);
}
if (addflat) amult = 1;
else amult = Max(0,AddMults(ak));
while ((ak < AddKnots.Upper()) &&
(Abs(au - AddKnots(ak+1)) <= Eps)) {
ak++;
if (Add) {
if (addflat) amult++;
else amult += Max(0,AddMults(ak));
}
}
if (Abs(au - Knots(k)) <= Eps) {
// identic to existing knot
mult = Mults(k);
if (Add) {
if (mult + amult > Degree)
amult = Max(0,Degree - mult);
sigma += amult;
}
else if (amult > mult) {
if (amult > Degree) amult = Degree;
sigma += amult - mult;
}
/*
// on periodic curves if this is the last knot
// the multiplicity is added twice to account for the first knot
if (k == Knots.Upper() && Periodic) {
if (Add)
sigma += amult;
else
sigma += amult - mult;
}
*/
}
else {
// not identic to existing knot
if (amult > 0) {
if (amult > Degree) amult = Degree;
NbKnots++;
sigma += amult;
}
}
ak++;
}
// count the last knots
while (k < Knots.Upper()) {
k++;
NbKnots++;
sigma += Mults(k);
}
if (Periodic) {
//for periodic B-Spline the requirement is that multiplicites of the first
//and last knots must be equal (see Geom_BSplineCurve constructor for
//instance);
//respectively AddMults() must meet this requirement if AddKnots() contains
//knot(s) coincident with first or last
NbPoles = sigma - Mults(Knots.Upper());
}
else {
NbPoles = sigma - Degree - 1;
}
return Standard_True;
}
//=======================================================================
//function : Copy
//purpose : copy reals from an array to an other
//
// NbValues are copied from OldPoles(OldFirst)
// to NewPoles(NewFirst)
//
// Periodicity is handled.
// OldFirst and NewFirst are updated
// to the position after the last copied pole.
//
//=======================================================================
static void Copy(const Standard_Integer NbPoles,
Standard_Integer& OldFirst,
const TColStd_Array1OfReal& OldPoles,
Standard_Integer& NewFirst,
TColStd_Array1OfReal& NewPoles)
{
// reset the index in the range for periodicity
OldFirst = OldPoles.Lower() +
(OldFirst - OldPoles.Lower()) % (OldPoles.Upper() - OldPoles.Lower() + 1);
NewFirst = NewPoles.Lower() +
(NewFirst - NewPoles.Lower()) % (NewPoles.Upper() - NewPoles.Lower() + 1);
// copy
Standard_Integer i;
for (i = 1; i <= NbPoles; i++) {
NewPoles(NewFirst) = OldPoles(OldFirst);
OldFirst++;
if (OldFirst > OldPoles.Upper()) OldFirst = OldPoles.Lower();
NewFirst++;
if (NewFirst > NewPoles.Upper()) NewFirst = NewPoles.Lower();
}
}
//=======================================================================
//function : InsertKnots
//purpose : insert an array of knots and multiplicities
//=======================================================================
void BSplCLib::InsertKnots
(const Standard_Integer Degree,
const Standard_Boolean Periodic,
const Standard_Integer Dimension,
const TColStd_Array1OfReal& Poles,
const TColStd_Array1OfReal& Knots,
const TColStd_Array1OfInteger& Mults,
const TColStd_Array1OfReal& AddKnots,
const TColStd_Array1OfInteger& AddMults,
TColStd_Array1OfReal& NewPoles,
TColStd_Array1OfReal& NewKnots,
TColStd_Array1OfInteger& NewMults,
const Standard_Real Tolerance,
const Standard_Boolean Add)
{
Standard_Boolean addflat = &AddMults == NULL;
Standard_Integer i,k,mult,firstmult;
Standard_Integer index,kn,curnk,curk;
Standard_Integer p,np, curp, curnp, length, depth;
Standard_Real u;
Standard_Integer need;
Standard_Real Eps;
// -------------------
// create local arrays
// -------------------
Standard_Real *knots = new Standard_Real[2*Degree];
Standard_Real *poles = new Standard_Real[(2*Degree+1)*Dimension];
//----------------------------
// loop on the knots to insert
//----------------------------
curk = Knots.Lower()-1; // current position in Knots
curnk = NewKnots.Lower()-1; // current position in NewKnots
curp = Poles.Lower(); // current position in Poles
curnp = NewPoles.Lower(); // current position in NewPoles
// NewKnots, NewMults, NewPoles contains the current state of the curve
// index is the first pole of the current curve for insertion schema
if (Periodic) index = -Mults(Mults.Lower());
else index = -Degree-1;
// on Periodic curves the first knot and the last knot are inserted later
// (they are the same knot)
firstmult = 0; // multiplicity of the first-last knot for periodic
// kn current knot to insert in AddKnots
for (kn = AddKnots.Lower(); kn <= AddKnots.Upper(); kn++) {
u = AddKnots(kn);
Eps = Max(Tolerance,Epsilon(u));
//-----------------------------------
// find the position in the old knots
// and copy to the new knots
//-----------------------------------
while (curk < Knots.Upper() && Knots(curk+1) - u <= Eps) {
curk++; curnk++;
NewKnots(curnk) = Knots(curk);
index += NewMults(curnk) = Mults(curk);
}
//-----------------------------------
// Slice the knots and the mults
// to the current size of the new curve
//-----------------------------------
i = curnk + Knots.Upper() - curk;
TColStd_Array1OfReal nknots(NewKnots(NewKnots.Lower()),NewKnots.Lower(),i);
TColStd_Array1OfInteger nmults(NewMults(NewMults.Lower()),NewMults.Lower(),i);
//-----------------------------------
// copy enough knots
// to compute the insertion schema
//-----------------------------------
k = curk;
i = curnk;
mult = 0;
while (mult < Degree && k < Knots.Upper()) {
k++; i++;
nknots(i) = Knots(k);
mult += nmults(i) = Mults(k);
}
// copy knots at the end for periodic curve
if (Periodic) {
mult = 0;
k = Knots.Upper();
i = nknots.Upper();
while (mult < Degree && i > curnk) {
nknots(i) = Knots(k);
mult += nmults(i) = Mults(k);
k--;
i--;
}
nmults(nmults.Upper()) = nmults(nmults.Lower());
}
//------------------------------------
// do the boor scheme on the new curve
// to insert the new knot
//------------------------------------
Standard_Boolean sameknot = (Abs(u-NewKnots(curnk)) <= Eps);
if (sameknot) length = Max(0,Degree - NewMults(curnk));
else length = Degree;
if (addflat) depth = 1;
else depth = Min(Degree,AddMults(kn));
if (sameknot) {
if (Add) {
if ((NewMults(curnk) + depth) > Degree)
depth = Degree - NewMults(curnk);
}
else {
depth = Max(0,depth-NewMults(curnk));
}
if (Periodic) {
// on periodic curve the first and last knot are delayed to the end
if (curk == Knots.Lower() || (curk == Knots.Upper())) {
firstmult += depth;
depth = 0;
}
}
}
if (depth <= 0) continue;
BuildKnots(Degree,curnk,Periodic,nknots,nmults,*knots);
// copy the poles
need = NewPoles.Lower()+(index+length+1)*Dimension - curnp;
need = Min(need,Poles.Upper() - curp + 1);
p = curp;
np = curnp;
Copy(need,p,Poles,np,NewPoles);
curp += need;
curnp += need;
// slice the poles to the current number of poles in case of periodic
TColStd_Array1OfReal npoles(NewPoles(NewPoles.Lower()),NewPoles.Lower(),curnp-1);
BuildBoor(index,length,Dimension,npoles,*poles);
BoorScheme(u,Degree,*knots,Dimension,*poles,depth,length);
//-------------------
// copy the new poles
//-------------------
curnp += depth * Dimension; // number of poles is increased by depth
TColStd_Array1OfReal ThePoles(NewPoles(NewPoles.Lower()),NewPoles.Lower(),curnp-1);
np = NewKnots.Lower()+(index+1)*Dimension;
for (i = 1; i <= length + depth; i++)
GetPole(i,length,depth,Dimension,*poles,np,ThePoles);
//-------------------
// insert the knot
//-------------------
index += depth;
if (sameknot) {
NewMults(curnk) += depth;
}
else {
curnk++;
NewKnots(curnk) = u;
NewMults(curnk) = depth;
}
}
//------------------------------
// copy the last poles and knots
//------------------------------
Copy(Poles.Upper() - curp + 1,curp,Poles,curnp,NewPoles);
while (curk < Knots.Upper()) {
curk++; curnk++;
NewKnots(curnk) = Knots(curk);
NewMults(curnk) = Mults(curk);
}
//------------------------------
// process the first-last knot
// on periodic curves
//------------------------------
if (firstmult > 0) {
curnk = NewKnots.Lower();
if (NewMults(curnk) + firstmult > Degree) {
firstmult = Degree - NewMults(curnk);
}
if (firstmult > 0) {
length = Degree - NewMults(curnk);
depth = firstmult;
BuildKnots(Degree,curnk,Periodic,NewKnots,NewMults,*knots);
TColStd_Array1OfReal npoles(NewPoles(NewPoles.Lower()),
NewPoles.Lower(),
NewPoles.Upper()-depth*Dimension);
BuildBoor(0,length,Dimension,npoles,*poles);
BoorScheme(NewKnots(curnk),Degree,*knots,Dimension,*poles,depth,length);
//---------------------------
// copy the new poles
// but rotate them with depth
//---------------------------
np = NewPoles.Lower();
for (i = depth; i < length + depth; i++)
GetPole(i,length,depth,Dimension,*poles,np,NewPoles);
np = NewPoles.Upper() - depth*Dimension + 1;
for (i = 0; i < depth; i++)
GetPole(i,length,depth,Dimension,*poles,np,NewPoles);
NewMults(NewMults.Lower()) += depth;
NewMults(NewMults.Upper()) += depth;
}
}
// free local arrays
delete [] knots;
delete [] poles;
}
//=======================================================================
//function : RemoveKnot
//purpose :
//=======================================================================
Standard_Boolean BSplCLib::RemoveKnot
(const Standard_Integer Index,
const Standard_Integer Mult,
const Standard_Integer Degree,
const Standard_Boolean Periodic,
const Standard_Integer Dimension,
const TColStd_Array1OfReal& Poles,
const TColStd_Array1OfReal& Knots,
const TColStd_Array1OfInteger& Mults,
TColStd_Array1OfReal& NewPoles,
TColStd_Array1OfReal& NewKnots,
TColStd_Array1OfInteger& NewMults,
const Standard_Real Tolerance)
{
Standard_Integer index,i,j,k,p,np;
Standard_Integer TheIndex = Index;
// protection
Standard_Integer first,last;
if (Periodic) {
first = Knots.Lower();
last = Knots.Upper();
}
else {
first = BSplCLib::FirstUKnotIndex(Degree,Mults) + 1;
last = BSplCLib::LastUKnotIndex(Degree,Mults) - 1;
}
if (Index < first) return Standard_False;
if (Index > last) return Standard_False;
if ( Periodic && (Index == first)) TheIndex = last;
Standard_Integer depth = Mults(TheIndex) - Mult;
Standard_Integer length = Degree - Mult;
// -------------------
// create local arrays
// -------------------
Standard_Real *knots = new Standard_Real[4*Degree];
Standard_Real *poles = new Standard_Real[(2*Degree+1)*Dimension];
// ------------------------------------
// build the knots for anti Boor Scheme
// ------------------------------------
// the new sequence of knots
// is obtained from the knots at Index-1 and Index
BSplCLib::BuildKnots(Degree,TheIndex-1,Periodic,Knots,Mults,*knots);
index = PoleIndex(Degree,TheIndex-1,Periodic,Mults);
BSplCLib::BuildKnots(Degree,TheIndex,Periodic,Knots,Mults,knots[2*Degree]);
index += Mult;
for (i = 0; i < Degree - Mult; i++)
knots[i] = knots[i+Mult];
for (i = Degree-Mult; i < 2*Degree; i++)
knots[i] = knots[2*Degree+i];
// ------------------------------------
// build the poles for anti Boor Scheme
// ------------------------------------
p = Poles.Lower()+index * Dimension;
for (i = 0; i <= length + depth; i++) {
j = Dimension * BoorIndex(i,length,depth);
for (k = 0; k < Dimension; k++) {
poles[j+k] = Poles(p+k);
}
p += Dimension;
if (p > Poles.Upper()) p = Poles.Lower();
}
// ----------------
// Anti Boor Scheme
// ----------------
Standard_Boolean result = AntiBoorScheme(Knots(TheIndex),Degree,*knots,
Dimension,*poles,
depth,length,Tolerance);
// ----------------
// copy the results
// ----------------
if (result) {
// poles
p = Poles.Lower();
np = NewPoles.Lower();
// unmodified poles before
Copy((index+1)*Dimension,p,Poles,np,NewPoles);
// modified
for (i = 1; i <= length; i++)
BSplCLib::GetPole(i,length,0,Dimension,*poles,np,NewPoles);
p += (length + depth) * Dimension ;
// unmodified poles after
if (p != Poles.Lower()) {
i = Poles.Upper() - p + 1;
Copy(i,p,Poles,np,NewPoles);
}
// knots and mults
if (Mult > 0) {
NewKnots = Knots;
NewMults = Mults;
NewMults(TheIndex) = Mult;
if (Periodic) {
if (TheIndex == first) NewMults(last) = Mult;
if (TheIndex == last) NewMults(first) = Mult;
}
}
else {
if (!Periodic || (TheIndex != first && TheIndex != last)) {
for (i = Knots.Lower(); i < TheIndex; i++) {
NewKnots(i) = Knots(i);
NewMults(i) = Mults(i);
}
for (i = TheIndex+1; i <= Knots.Upper(); i++) {
NewKnots(i-1) = Knots(i);
NewMults(i-1) = Mults(i);
}
}
else {
// The interesting case of a Periodic curve
// where the first and last knot is removed.
for (i = first; i < last-1; i++) {
NewKnots(i) = Knots(i+1);
NewMults(i) = Mults(i+1);
}
NewKnots(last-1) = NewKnots(first) + Knots(last) - Knots(first);
NewMults(last-1) = NewMults(first);
}
}
}
// free local arrays
delete [] knots;
delete [] poles;
return result;
}
//=======================================================================
//function : IncreaseDegreeCountKnots
//purpose :
//=======================================================================
Standard_Integer BSplCLib::IncreaseDegreeCountKnots
(const Standard_Integer Degree,
const Standard_Integer NewDegree,
const Standard_Boolean Periodic,
const TColStd_Array1OfInteger& Mults)
{
if (Periodic) return Mults.Length();
Standard_Integer f = FirstUKnotIndex(Degree,Mults);
Standard_Integer l = LastUKnotIndex(Degree,Mults);
Standard_Integer m,i,removed = 0, step = NewDegree - Degree;
i = Mults.Lower();
m = Degree + (f - i + 1) * step + 1;
while (m > NewDegree+1) {
removed++;
m -= Mults(i) + step;
i++;
}
if (m < NewDegree+1) removed--;
i = Mults.Upper();
m = Degree + (i - l + 1) * step + 1;
while (m > NewDegree+1) {
removed++;
m -= Mults(i) + step;
i--;
}
if (m < NewDegree+1) removed--;
return Mults.Length() - removed;
}
//=======================================================================
//function : IncreaseDegree
//purpose :
//=======================================================================
void BSplCLib::IncreaseDegree
(const Standard_Integer Degree,
const Standard_Integer NewDegree,
const Standard_Boolean Periodic,
const Standard_Integer Dimension,
const TColStd_Array1OfReal& Poles,
const TColStd_Array1OfReal& Knots,
const TColStd_Array1OfInteger& Mults,
TColStd_Array1OfReal& NewPoles,
TColStd_Array1OfReal& NewKnots,
TColStd_Array1OfInteger& NewMults)
{
// Degree elevation of a BSpline Curve
// This algorithms loops on degree incrementation from Degree to NewDegree.
// The variable curDeg is the current degree to increment.
// Before degree incrementations a "working curve" is created.
// It has the same knot, poles and multiplicities.
// If the curve is periodic knots are added on the working curve before
// and after the existing knots to make it a non-periodic curves.
// The poles are also copied.
// The first and last multiplicity of the working curve are set to Degree+1,
// null poles are added if necessary.
// Then the degree is incremented on the working curve.
// The knots are unchanged but all multiplicities will be incremented.
// Each degree incrementation is achieved by averaging curDeg+1 curves.
// See : Degree elevation of B-spline curves
// Hartmut PRAUTZSCH
// CAGD 1 (1984)
//-------------------------
// create the working curve
//-------------------------
Standard_Integer i,k,f,l,m,pf,pl,firstknot;
pf = 0; // number of null poles added at beginning
pl = 0; // number of null poles added at end
Standard_Integer nbwknots = Knots.Length();
f = FirstUKnotIndex(Degree,Mults);
l = LastUKnotIndex (Degree,Mults);
if (Periodic) {
// Periodic curves are transformed in non-periodic curves
nbwknots += f - Mults.Lower();
pf = -Degree - 1;
for (i = Mults.Lower(); i <= f; i++)
pf += Mults(i);
nbwknots += Mults.Upper() - l;
pl = -Degree - 1;
for (i = l; i <= Mults.Upper(); i++)
pl += Mults(i);
}
// copy the knots and multiplicities
TColStd_Array1OfReal wknots(1,nbwknots);
TColStd_Array1OfInteger wmults(1,nbwknots);
if (!Periodic) {
wknots = Knots;
wmults = Mults;
}
else {
// copy the knots for a periodic curve
Standard_Real period = Knots(Knots.Upper()) - Knots(Knots.Lower());
i = 0;
for (k = l; k < Knots.Upper(); k++) {
i++;
wknots(i) = Knots(k) - period;
wmults(i) = Mults(k);
}
for (k = Knots.Lower(); k <= Knots.Upper(); k++) {
i++;
wknots(i) = Knots(k);
wmults(i) = Mults(k);
}
for (k = Knots.Lower()+1; k <= f; k++) {
i++;
wknots(i) = Knots(k) + period;
wmults(i) = Mults(k);
}
}
// set the first and last mults to Degree+1
// and add null poles
pf += Degree + 1 - wmults(1);
wmults(1) = Degree + 1;
pl += Degree + 1 - wmults(nbwknots);
wmults(nbwknots) = Degree + 1;
//---------------------------
// poles of the working curve
//---------------------------
Standard_Integer nbwpoles = 0;
for (i = 1; i <= nbwknots; i++) nbwpoles += wmults(i);
nbwpoles -= Degree + 1;
// we provide space for degree elevation
TColStd_Array1OfReal
wpoles(1,(nbwpoles + (nbwknots-1) * (NewDegree - Degree)) * Dimension);
for (i = 1; i <= pf * Dimension; i++)
wpoles(i) = 0;
k = Poles.Lower();
for (i = pf * Dimension + 1; i <= (nbwpoles - pl) * Dimension; i++) {
wpoles(i) = Poles(k);
k++;
if (k > Poles.Upper()) k = Poles.Lower();
}
for (i = (nbwpoles-pl)*Dimension+1; i <= nbwpoles*Dimension; i++)
wpoles(i) = 0;
//-----------------------------------------------------------
// Declare the temporary arrays used in degree incrementation
//-----------------------------------------------------------
Standard_Integer nbwp = nbwpoles + (nbwknots-1) * (NewDegree - Degree);
// Arrays for storing the temporary curves
TColStd_Array1OfReal tempc1(1,nbwp * Dimension);
TColStd_Array1OfReal tempc2(1,nbwp * Dimension);
// Array for storing the knots to insert
TColStd_Array1OfReal iknots(1,nbwknots);
// Arrays for receiving the knots after insertion
TColStd_Array1OfReal nknots(1,nbwknots);
//------------------------------
// Loop on degree incrementation
//------------------------------
Standard_Integer step,curDeg;
Standard_Integer nbp = nbwpoles;
nbwp = nbp;
for (curDeg = Degree; curDeg < NewDegree; curDeg++) {
nbp = nbwp; // current number of poles
nbwp = nbp + nbwknots - 1; // new number of poles
// For the averaging
TColStd_Array1OfReal nwpoles(1,nbwp * Dimension);
nwpoles.Init(0.0e0) ;
for (step = 0; step <= curDeg; step++) {
// Compute the bspline of rank step.
// if not the first time, decrement the multiplicities back
if (step != 0) {
for (i = 1; i <= nbwknots; i++)
wmults(i)--;
}
// Poles are the current poles
// but the poles congruent to step are duplicated.
Standard_Integer offset = 0;
for (i = 0; i < nbp; i++) {
offset++;
for (k = 0; k < Dimension; k++) {
tempc1((offset-1)*Dimension+k+1) =
wpoles(NewPoles.Lower()+i*Dimension+k);
}
if (i % (curDeg+1) == step) {
offset++;
for (k = 0; k < Dimension; k++) {
tempc1((offset-1)*Dimension+k+1) =
wpoles(NewPoles.Lower()+i*Dimension+k);
}
}
}
// Knots multiplicities are increased
// For each knot where the sum of multiplicities is congruent to step
Standard_Integer stepmult = step+1;
Standard_Integer nbknots = 0;
Standard_Integer smult = 0;
for (k = 1; k <= nbwknots; k++) {
smult += wmults(k);
if (smult >= stepmult) {
// this knot is increased
stepmult += curDeg+1;
wmults(k)++;
}
else {
// this knot is inserted
nbknots++;
iknots(nbknots) = wknots(k);
}
}
// the curve is obtained by inserting the knots
// to raise the multiplicities
// we build "slices" of the arrays to set the correct size
if (nbknots > 0) {
TColStd_Array1OfReal aknots(iknots(1),1,nbknots);
TColStd_Array1OfReal curve (tempc1(1),1,offset * Dimension);
TColStd_Array1OfReal ncurve(tempc2(1),1,nbwp * Dimension);
// InsertKnots(curDeg+1,Standard_False,Dimension,curve,wknots,wmults,
// aknots,NoMults(),ncurve,nknots,wmults,Epsilon(1.));
InsertKnots(curDeg+1,Standard_False,Dimension,curve,wknots,wmults,
aknots,NoMults(),ncurve,nknots,wmults,0.0);
// add to the average
for (i = 1; i <= nbwp * Dimension; i++)
nwpoles(i) += ncurve(i);
}
else {
// add to the average
for (i = 1; i <= nbwp * Dimension; i++)
nwpoles(i) += tempc1(i);
}
}
// The result is the average
for (i = 1; i <= nbwp * Dimension; i++) {
wpoles(i) = nwpoles(i) / (curDeg+1);
}
}
//-----------------
// Copy the results
//-----------------
// index in new knots of the first knot of the curve
if (Periodic)
firstknot = Mults.Upper() - l + 1;
else
firstknot = f;
// the new curve starts at index firstknot
// so we must remove knots until the sum of multiplicities
// from the first to the start is NewDegree+1
// m is the current sum of multiplicities
m = 0;
for (k = 1; k <= firstknot; k++)
m += wmults(k);
// compute the new first knot (k), pf will be the index of the first pole
k = 1;
pf = 0;
while (m > NewDegree+1) {
k++;
m -= wmults(k);
pf += wmults(k);
}
if (m < NewDegree+1) {
k--;
wmults(k) += m - NewDegree - 1;
pf += m - NewDegree - 1;
}
// on a periodic curve the knots start with firstknot
if (Periodic)
k = firstknot;
// copy knots
for (i = NewKnots.Lower(); i <= NewKnots.Upper(); i++) {
NewKnots(i) = wknots(k);
NewMults(i) = wmults(k);
k++;
}
// copy poles
pf *= Dimension;
for (i = NewPoles.Lower(); i <= NewPoles.Upper(); i++) {
pf++;
NewPoles(i) = wpoles(pf);
}
}
//=======================================================================
//function : PrepareUnperiodize
//purpose :
//=======================================================================
void BSplCLib::PrepareUnperiodize
(const Standard_Integer Degree,
const TColStd_Array1OfInteger& Mults,
Standard_Integer& NbKnots,
Standard_Integer& NbPoles)
{
Standard_Integer i;
// initialize NbKnots and NbPoles
NbKnots = Mults.Length();
NbPoles = - Degree - 1;
for (i = Mults.Lower(); i <= Mults.Upper(); i++)
NbPoles += Mults(i);
Standard_Integer sigma, k;
// Add knots at the beginning of the curve to raise Multiplicities
// to Degre + 1;
sigma = Mults(Mults.Lower());
k = Mults.Upper() - 1;
while ( sigma < Degree + 1) {
sigma += Mults(k);
NbPoles += Mults(k);
k--;
NbKnots++;
}
// We must add exactly until Degree + 1 ->
// Supress the excedent.
if ( sigma > Degree + 1)
NbPoles -= sigma - Degree - 1;
// Add knots at the end of the curve to raise Multiplicities
// to Degre + 1;
sigma = Mults(Mults.Upper());
k = Mults.Lower() + 1;
while ( sigma < Degree + 1) {
sigma += Mults(k);
NbPoles += Mults(k);
k++;
NbKnots++;
}
// We must add exactly until Degree + 1 ->
// Supress the excedent.
if ( sigma > Degree + 1)
NbPoles -= sigma - Degree - 1;
}
//=======================================================================
//function : Unperiodize
//purpose :
//=======================================================================
void BSplCLib::Unperiodize
(const Standard_Integer Degree,
const Standard_Integer , // Dimension,
const TColStd_Array1OfInteger& Mults,
const TColStd_Array1OfReal& Knots,
const TColStd_Array1OfReal& Poles,
TColStd_Array1OfInteger& NewMults,
TColStd_Array1OfReal& NewKnots,
TColStd_Array1OfReal& NewPoles)
{
Standard_Integer sigma, k, index = 0;
// evaluation of index : number of knots to insert before knot(1) to
// raise sum of multiplicities to <Degree + 1>
sigma = Mults(Mults.Lower());
k = Mults.Upper() - 1;
while ( sigma < Degree + 1) {
sigma += Mults(k);
k--;
index++;
}
Standard_Real period = Knots(Knots.Upper()) - Knots(Knots.Lower());
// set the 'interior' knots;
for ( k = 1; k <= Knots.Length(); k++) {
NewKnots ( k + index ) = Knots( k);
NewMults ( k + index ) = Mults( k);
}
// set the 'starting' knots;
for ( k = 1; k <= index; k++) {
NewKnots( k) = NewKnots( k + Knots.Length() - 1) - period;
NewMults( k) = NewMults( k + Knots.Length() - 1);
}
NewMults( 1) -= sigma - Degree -1;
// set the 'ending' knots;
sigma = NewMults( index + Knots.Length() );
for ( k = Knots.Length() + index + 1; k <= NewKnots.Length(); k++) {
NewKnots( k) = NewKnots( k - Knots.Length() + 1) + period;
NewMults( k) = NewMults( k - Knots.Length() + 1);
sigma += NewMults( k - Knots.Length() + 1);
}
NewMults(NewMults.Length()) -= sigma - Degree - 1;
for ( k = 1 ; k <= NewPoles.Length(); k++) {
NewPoles(k ) = Poles( (k-1) % Poles.Length() + 1);
}
}
//=======================================================================
//function : PrepareTrimming
//purpose :
//=======================================================================
void BSplCLib::PrepareTrimming(const Standard_Integer Degree,
const Standard_Boolean Periodic,
const TColStd_Array1OfReal& Knots,
const TColStd_Array1OfInteger& Mults,
const Standard_Real U1,
const Standard_Real U2,
Standard_Integer& NbKnots,
Standard_Integer& NbPoles)
{
Standard_Integer i;
Standard_Real NewU1, NewU2;
Standard_Integer index1 = 0, index2 = 0;
// Eval index1, index2 : position of U1 and U2 in the Array Knots
// such as Knots(index1-1) <= U1 < Knots(index1)
// Knots(index2-1) <= U2 < Knots(index2)
LocateParameter( Degree, Knots, Mults, U1, Periodic,
Knots.Lower(), Knots.Upper(), index1, NewU1);
LocateParameter( Degree, Knots, Mults, U2, Periodic,
Knots.Lower(), Knots.Upper(), index2, NewU2);
index1++;
if ( Abs(Knots(index2) - U2) <= Epsilon( U1))
index2--;
// eval NbKnots:
NbKnots = index2 - index1 + 3;
// eval NbPoles:
NbPoles = Degree + 1;
for ( i = index1; i <= index2; i++)
NbPoles += Mults(i);
}
//=======================================================================
//function : Trimming
//purpose :
//=======================================================================
void BSplCLib::Trimming(const Standard_Integer Degree,
const Standard_Boolean Periodic,
const Standard_Integer Dimension,
const TColStd_Array1OfReal& Knots,
const TColStd_Array1OfInteger& Mults,
const TColStd_Array1OfReal& Poles,
const Standard_Real U1,
const Standard_Real U2,
TColStd_Array1OfReal& NewKnots,
TColStd_Array1OfInteger& NewMults,
TColStd_Array1OfReal& NewPoles)
{
Standard_Integer i, nbpoles, nbknots;
Standard_Real kk[2];
Standard_Integer mm[2];
TColStd_Array1OfReal K( kk[0], 1, 2 );
TColStd_Array1OfInteger M( mm[0], 1, 2 );
K(1) = U1; K(2) = U2;
mm[0] = mm[1] = Degree;
if (!PrepareInsertKnots( Degree, Periodic, Knots, Mults, K, M,
nbpoles, nbknots, Epsilon( U1), 0))
Standard_OutOfRange::Raise();
TColStd_Array1OfReal TempPoles(1, nbpoles*Dimension);
TColStd_Array1OfReal TempKnots(1, nbknots);
TColStd_Array1OfInteger TempMults(1, nbknots);
//
// do not allow the multiplicities to Add : they must be less than Degree
//
InsertKnots(Degree, Periodic, Dimension, Poles, Knots, Mults,
K, M, TempPoles, TempKnots, TempMults, Epsilon(U1),
Standard_False);
// find in TempPoles the index of the pole corresponding to U1
Standard_Integer Kindex = 0, Pindex;
Standard_Real NewU1;
LocateParameter( Degree, TempKnots, TempMults, U1, Periodic,
TempKnots.Lower(), TempKnots.Upper(), Kindex, NewU1);
Pindex = PoleIndex ( Degree, Kindex, Periodic, TempMults);
Pindex *= Dimension;
for ( i = 1; i <= NewPoles.Length(); i++) NewPoles(i) = TempPoles(Pindex + i);
for ( i = 1; i <= NewKnots.Length(); i++) {
NewKnots(i) = TempKnots( Kindex+i-1);
NewMults(i) = TempMults( Kindex+i-1);
}
NewMults(1) = Min(Degree, NewMults(1)) + 1 ;
NewMults(NewMults.Length())= Min(Degree, NewMults(NewMults.Length())) + 1 ;
}
//=======================================================================
//function : Solves a LU factored Matrix
//purpose :
//=======================================================================
Standard_Integer
BSplCLib::SolveBandedSystem(const math_Matrix& Matrix,
const Standard_Integer UpperBandWidth,
const Standard_Integer LowerBandWidth,
const Standard_Integer ArrayDimension,
Standard_Real& Array)
{
Standard_Integer ii,
jj,
kk,
MinIndex,
MaxIndex,
ReturnCode = 0 ;
Standard_Real *PolesArray = &Array ;
Standard_Real Inverse ;
if (Matrix.LowerCol() != 1 ||
Matrix.UpperCol() != UpperBandWidth + LowerBandWidth + 1) {
ReturnCode = 1 ;
goto FINISH ;
}
for (ii = Matrix.LowerRow() + 1; ii <= Matrix.UpperRow() ; ii++) {
MinIndex = (ii - LowerBandWidth >= Matrix.LowerRow() ?
ii - LowerBandWidth : Matrix.LowerRow()) ;
for ( jj = MinIndex ; jj < ii ; jj++) {
for (kk = 0 ; kk < ArrayDimension ; kk++) {
PolesArray[(ii-1) * ArrayDimension + kk] +=
PolesArray[(jj-1) * ArrayDimension + kk] * Matrix(ii, jj - ii + LowerBandWidth + 1) ;
}
}
}
for (ii = Matrix.UpperRow() ; ii >= Matrix.LowerRow() ; ii--) {
MaxIndex = (ii + UpperBandWidth <= Matrix.UpperRow() ?
ii + UpperBandWidth : Matrix.UpperRow()) ;
for (jj = MaxIndex ; jj > ii ; jj--) {
for (kk = 0 ; kk < ArrayDimension ; kk++) {
PolesArray[(ii-1) * ArrayDimension + kk] -=
PolesArray[(jj - 1) * ArrayDimension + kk] *
Matrix(ii, jj - ii + LowerBandWidth + 1) ;
}
}
//fixing a bug PRO18577 to avoid divizion by zero
Standard_Real divizor = Matrix(ii,LowerBandWidth + 1) ;
Standard_Real Toler = 1.0e-16;
if ( Abs(divizor) > Toler )
Inverse = 1.0e0 / divizor ;
else {
Inverse = 1.0e0;
// cout << " BSplCLib::SolveBandedSystem() : zero determinant " << endl;
ReturnCode = 1;
goto FINISH;
}
for (kk = 0 ; kk < ArrayDimension ; kk++) {
PolesArray[(ii-1) * ArrayDimension + kk] *= Inverse ;
}
}
FINISH :
return (ReturnCode) ;
}
//=======================================================================
//function : Solves a LU factored Matrix
//purpose :
//=======================================================================
Standard_Integer
BSplCLib::SolveBandedSystem(const math_Matrix& Matrix,
const Standard_Integer UpperBandWidth,
const Standard_Integer LowerBandWidth,
const Standard_Boolean HomogeneousFlag,
const Standard_Integer ArrayDimension,
Standard_Real& Poles,
Standard_Real& Weights)
{
Standard_Integer ii,
kk,
ErrorCode = 0,
ReturnCode = 0 ;
Standard_Real Inverse,
*PolesArray = &Poles,
*WeightsArray = &Weights ;
if (Matrix.LowerCol() != 1 ||
Matrix.UpperCol() != UpperBandWidth + LowerBandWidth + 1) {
ReturnCode = 1 ;
goto FINISH ;
}
if (HomogeneousFlag == Standard_False) {
for (ii = 0 ; ii < Matrix.UpperRow() - Matrix.LowerRow() + 1; ii++) {
for (kk = 0 ; kk < ArrayDimension ; kk++) {
PolesArray[ii * ArrayDimension + kk] *=
WeightsArray[ii] ;
}
}
}
ErrorCode =
BSplCLib::SolveBandedSystem(Matrix,
UpperBandWidth,
LowerBandWidth,
ArrayDimension,
Poles) ;
if (ErrorCode != 0) {
ReturnCode = 2 ;
goto FINISH ;
}
ErrorCode =
BSplCLib::SolveBandedSystem(Matrix,
UpperBandWidth,
LowerBandWidth,
1,
Weights) ;
if (ErrorCode != 0) {
ReturnCode = 3 ;
goto FINISH ;
}
if (HomogeneousFlag == Standard_False) {
for (ii = 0 ; ii < Matrix.UpperRow() - Matrix.LowerRow() + 1 ; ii++) {
Inverse = 1.0e0 / WeightsArray[ii] ;
for (kk = 0 ; kk < ArrayDimension ; kk++) {
PolesArray[ii * ArrayDimension + kk] *= Inverse ;
}
}
}
FINISH : return (ReturnCode) ;
}
//=======================================================================
//function : BuildSchoenbergPoints
//purpose :
//=======================================================================
void BSplCLib::BuildSchoenbergPoints(const Standard_Integer Degree,
const TColStd_Array1OfReal& FlatKnots,
TColStd_Array1OfReal& Parameters)
{
Standard_Integer ii,
jj ;
Standard_Real Inverse ;
Inverse = 1.0e0 / (Standard_Real)Degree ;
for (ii = Parameters.Lower() ; ii <= Parameters.Upper() ; ii++) {
Parameters(ii) = 0.0e0 ;
for (jj = 1 ; jj <= Degree ; jj++) {
Parameters(ii) += FlatKnots(jj + ii) ;
}
Parameters(ii) *= Inverse ;
}
}
//=======================================================================
//function : Interpolate
//purpose :
//=======================================================================
void BSplCLib::Interpolate(const Standard_Integer Degree,
const TColStd_Array1OfReal& FlatKnots,
const TColStd_Array1OfReal& Parameters,
const TColStd_Array1OfInteger& ContactOrderArray,
const Standard_Integer ArrayDimension,
Standard_Real& Poles,
Standard_Integer& InversionProblem)
{
Standard_Integer ErrorCode,
UpperBandWidth,
LowerBandWidth ;
// Standard_Real *PolesArray = &Poles ;
math_Matrix InterpolationMatrix(1, Parameters.Length(),
1, 2 * Degree + 1) ;
ErrorCode =
BSplCLib::BuildBSpMatrix(Parameters,
ContactOrderArray,
FlatKnots,
Degree,
InterpolationMatrix,
UpperBandWidth,
LowerBandWidth) ;
Standard_OutOfRange_Raise_if (ErrorCode != 0, "BSplCLib::Interpolate") ;
ErrorCode =
BSplCLib::FactorBandedMatrix(InterpolationMatrix,
UpperBandWidth,
LowerBandWidth,
InversionProblem) ;
Standard_OutOfRange_Raise_if (ErrorCode != 0, "BSplCLib::Interpolate") ;
ErrorCode =
BSplCLib::SolveBandedSystem(InterpolationMatrix,
UpperBandWidth,
LowerBandWidth,
ArrayDimension,
Poles) ;
Standard_OutOfRange_Raise_if (ErrorCode != 0,"BSplCLib::Interpolate") ;
}
//=======================================================================
//function : Interpolate
//purpose :
//=======================================================================
void BSplCLib::Interpolate(const Standard_Integer Degree,
const TColStd_Array1OfReal& FlatKnots,
const TColStd_Array1OfReal& Parameters,
const TColStd_Array1OfInteger& ContactOrderArray,
const Standard_Integer ArrayDimension,
Standard_Real& Poles,
Standard_Real& Weights,
Standard_Integer& InversionProblem)
{
Standard_Integer ErrorCode,
UpperBandWidth,
LowerBandWidth ;
math_Matrix InterpolationMatrix(1, Parameters.Length(),
1, 2 * Degree + 1) ;
ErrorCode =
BSplCLib::BuildBSpMatrix(Parameters,
ContactOrderArray,
FlatKnots,
Degree,
InterpolationMatrix,
UpperBandWidth,
LowerBandWidth) ;
Standard_OutOfRange_Raise_if (ErrorCode != 0, "BSplCLib::Interpolate") ;
ErrorCode =
BSplCLib::FactorBandedMatrix(InterpolationMatrix,
UpperBandWidth,
LowerBandWidth,
InversionProblem) ;
Standard_OutOfRange_Raise_if (ErrorCode != 0, "BSplCLib::Interpolate") ;
ErrorCode =
BSplCLib::SolveBandedSystem(InterpolationMatrix,
UpperBandWidth,
LowerBandWidth,
Standard_False,
ArrayDimension,
Poles,
Weights) ;
Standard_OutOfRange_Raise_if (ErrorCode != 0,"BSplCLib::Interpolate") ;
}
//=======================================================================
//function : Evaluates a Bspline function : uses the ExtrapMode
//purpose : the function is extrapolated using the Taylor expansion
// of degree ExtrapMode[0] to the left and the Taylor
// expansion of degree ExtrapMode[1] to the right
// this evaluates the numerator by multiplying by the weights
// and evaluating it but does not call RationalDerivatives after
//=======================================================================
void BSplCLib::Eval
(const Standard_Real Parameter,
const Standard_Boolean PeriodicFlag,
const Standard_Integer DerivativeRequest,
Standard_Integer& ExtrapMode,
const Standard_Integer Degree,
const TColStd_Array1OfReal& FlatKnots,
const Standard_Integer ArrayDimension,
Standard_Real& Poles,
Standard_Real& Weights,
Standard_Real& PolesResults,
Standard_Real& WeightsResults)
{
Standard_Integer ii,
jj,
kk=0,
Index,
Index1,
Index2,
*ExtrapModeArray,
Modulus,
NewRequest,
ExtrapolatingFlag[2],
ErrorCode,
Order = Degree + 1,
FirstNonZeroBsplineIndex,
LocalRequest = DerivativeRequest ;
Standard_Real *PResultArray,
*WResultArray,
*PolesArray,
*WeightsArray,
LocalParameter,
Period,
Inverse,
Delta ;
PolesArray = &Poles ;
WeightsArray = &Weights ;
ExtrapModeArray = &ExtrapMode ;
PResultArray = &PolesResults ;
WResultArray = &WeightsResults ;
LocalParameter = Parameter ;
ExtrapolatingFlag[0] =
ExtrapolatingFlag[1] = 0 ;
//
// check if we are extrapolating to a degree which is smaller than
// the degree of the Bspline
//
if (PeriodicFlag) {
Period = FlatKnots(FlatKnots.Upper() - 1) - FlatKnots(2) ;
while (LocalParameter > FlatKnots(FlatKnots.Upper() - 1)) {
LocalParameter -= Period ;
}
while (LocalParameter < FlatKnots(2)) {
LocalParameter += Period ;
}
}
if (Parameter < FlatKnots(2) &&
LocalRequest < ExtrapModeArray[0] &&
ExtrapModeArray[0] < Degree) {
LocalRequest = ExtrapModeArray[0] ;
LocalParameter = FlatKnots(2) ;
ExtrapolatingFlag[0] = 1 ;
}
if (Parameter > FlatKnots(FlatKnots.Upper()-1) &&
LocalRequest < ExtrapModeArray[1] &&
ExtrapModeArray[1] < Degree) {
LocalRequest = ExtrapModeArray[1] ;
LocalParameter = FlatKnots(FlatKnots.Upper()-1) ;
ExtrapolatingFlag[1] = 1 ;
}
Delta = Parameter - LocalParameter ;
if (LocalRequest >= Order) {
LocalRequest = Degree ;
}
if (PeriodicFlag) {
Modulus = FlatKnots.Length() - Degree -1 ;
}
else {
Modulus = FlatKnots.Length() - Degree ;
}
BSplCLib_LocalMatrix BsplineBasis (LocalRequest, Order);
ErrorCode =
BSplCLib::EvalBsplineBasis(1,
LocalRequest,
Order,
FlatKnots,
LocalParameter,
FirstNonZeroBsplineIndex,
BsplineBasis) ;
if (ErrorCode != 0) {
goto FINISH ;
}
if (ExtrapolatingFlag[0] == 0 && ExtrapolatingFlag[1] == 0) {
Index = 0 ;
Index2 = 0 ;
for (ii = 1 ; ii <= LocalRequest + 1 ; ii++) {
Index1 = FirstNonZeroBsplineIndex ;
for (kk = 0 ; kk < ArrayDimension ; kk++) {
PResultArray[Index + kk] = 0.0e0 ;
}
WResultArray[Index] = 0.0e0 ;
for (jj = 1 ; jj <= Order ; jj++) {
for (kk = 0 ; kk < ArrayDimension ; kk++) {
PResultArray[Index + kk] +=
PolesArray[(Index1-1) * ArrayDimension + kk]
* WeightsArray[Index1-1] * BsplineBasis(ii,jj) ;
}
WResultArray[Index2] += WeightsArray[Index1-1] * BsplineBasis(ii,jj) ;
Index1 = Index1 % Modulus ;
Index1 += 1 ;
}
Index += ArrayDimension ;
Index2 += 1 ;
}
}
else {
//
// store Taylor expansion in LocalRealArray
//
NewRequest = DerivativeRequest ;
if (NewRequest > Degree) {
NewRequest = Degree ;
}
NCollection_LocalArray<Standard_Real> LocalRealArray((LocalRequest + 1)*ArrayDimension);
Index = 0 ;
Inverse = 1.0e0 ;
for (ii = 1 ; ii <= LocalRequest + 1 ; ii++) {
Index1 = FirstNonZeroBsplineIndex ;
for (kk = 0 ; kk < ArrayDimension ; kk++) {
LocalRealArray[Index + kk] = 0.0e0 ;
}
for (jj = 1 ; jj <= Order ; jj++) {
for (kk = 0 ; kk < ArrayDimension ; kk++) {
LocalRealArray[Index + kk] +=
PolesArray[(Index1-1)*ArrayDimension + kk] *
WeightsArray[Index1-1] * BsplineBasis(ii,jj) ;
}
Index1 = Index1 % Modulus ;
Index1 += 1 ;
}
for (kk = 0 ; kk < ArrayDimension ; kk++) {
LocalRealArray[Index + kk] *= Inverse ;
}
Index += ArrayDimension ;
Inverse /= (Standard_Real) ii ;
}
PLib::EvalPolynomial(Delta,
NewRequest,
Degree,
ArrayDimension,
LocalRealArray[0],
PolesResults) ;
Index = 0 ;
Inverse = 1.0e0 ;
for (ii = 1 ; ii <= LocalRequest + 1 ; ii++) {
Index1 = FirstNonZeroBsplineIndex ;
LocalRealArray[Index] = 0.0e0 ;
for (jj = 1 ; jj <= Order ; jj++) {
LocalRealArray[Index] +=
WeightsArray[Index1-1] * BsplineBasis(ii,jj) ;
Index1 = Index1 % Modulus ;
Index1 += 1 ;
}
LocalRealArray[Index + kk] *= Inverse ;
Index += 1 ;
Inverse /= (Standard_Real) ii ;
}
PLib::EvalPolynomial(Delta,
NewRequest,
Degree,
1,
LocalRealArray[0],
WeightsResults) ;
}
FINISH : ;
}
//=======================================================================
//function : Evaluates a Bspline function : uses the ExtrapMode
//purpose : the function is extrapolated using the Taylor expansion
// of degree ExtrapMode[0] to the left and the Taylor
// expansion of degree ExtrapMode[1] to the right
// WARNING : the array Results is supposed to have at least
// (DerivativeRequest + 1) * ArrayDimension slots and the
//
//=======================================================================
void BSplCLib::Eval
(const Standard_Real Parameter,
const Standard_Boolean PeriodicFlag,
const Standard_Integer DerivativeRequest,
Standard_Integer& ExtrapMode,
const Standard_Integer Degree,
const TColStd_Array1OfReal& FlatKnots,
const Standard_Integer ArrayDimension,
Standard_Real& Poles,
Standard_Real& Results)
{
Standard_Integer ii,
jj,
kk,
Index,
Index1,
*ExtrapModeArray,
Modulus,
NewRequest,
ExtrapolatingFlag[2],
ErrorCode,
Order = Degree + 1,
FirstNonZeroBsplineIndex,
LocalRequest = DerivativeRequest ;
Standard_Real *ResultArray,
*PolesArray,
LocalParameter,
Period,
Inverse,
Delta ;
PolesArray = &Poles ;
ExtrapModeArray = &ExtrapMode ;
ResultArray = &Results ;
LocalParameter = Parameter ;
ExtrapolatingFlag[0] =
ExtrapolatingFlag[1] = 0 ;
//
// check if we are extrapolating to a degree which is smaller than
// the degree of the Bspline
//
if (PeriodicFlag) {
Period = FlatKnots(FlatKnots.Upper() - 1) - FlatKnots(2) ;
while (LocalParameter > FlatKnots(FlatKnots.Upper() - 1)) {
LocalParameter -= Period ;
}
while (LocalParameter < FlatKnots(2)) {
LocalParameter += Period ;
}
}
if (Parameter < FlatKnots(2) &&
LocalRequest < ExtrapModeArray[0] &&
ExtrapModeArray[0] < Degree) {
LocalRequest = ExtrapModeArray[0] ;
LocalParameter = FlatKnots(2) ;
ExtrapolatingFlag[0] = 1 ;
}
if (Parameter > FlatKnots(FlatKnots.Upper()-1) &&
LocalRequest < ExtrapModeArray[1] &&
ExtrapModeArray[1] < Degree) {
LocalRequest = ExtrapModeArray[1] ;
LocalParameter = FlatKnots(FlatKnots.Upper()-1) ;
ExtrapolatingFlag[1] = 1 ;
}
Delta = Parameter - LocalParameter ;
if (LocalRequest >= Order) {
LocalRequest = Degree ;
}
if (PeriodicFlag) {
Modulus = FlatKnots.Length() - Degree -1 ;
}
else {
Modulus = FlatKnots.Length() - Degree ;
}
BSplCLib_LocalMatrix BsplineBasis (LocalRequest, Order);
ErrorCode =
BSplCLib::EvalBsplineBasis(1,
LocalRequest,
Order,
FlatKnots,
LocalParameter,
FirstNonZeroBsplineIndex,
BsplineBasis);
if (ErrorCode != 0) {
goto FINISH ;
}
if (ExtrapolatingFlag[0] == 0 && ExtrapolatingFlag[1] == 0) {
Index = 0 ;
for (ii = 1 ; ii <= LocalRequest + 1 ; ii++) {
Index1 = FirstNonZeroBsplineIndex ;
for (kk = 0 ; kk < ArrayDimension ; kk++) {
ResultArray[Index + kk] = 0.0e0 ;
}
for (jj = 1 ; jj <= Order ; jj++) {
for (kk = 0 ; kk < ArrayDimension ; kk++) {
ResultArray[Index + kk] +=
PolesArray[(Index1-1) * ArrayDimension + kk] * BsplineBasis(ii,jj) ;
}
Index1 = Index1 % Modulus ;
Index1 += 1 ;
}
Index += ArrayDimension ;
}
}
else {
//
// store Taylor expansion in LocalRealArray
//
NewRequest = DerivativeRequest ;
if (NewRequest > Degree) {
NewRequest = Degree ;
}
NCollection_LocalArray<Standard_Real> LocalRealArray((LocalRequest + 1)*ArrayDimension);
Index = 0 ;
Inverse = 1.0e0 ;
for (ii = 1 ; ii <= LocalRequest + 1 ; ii++) {
Index1 = FirstNonZeroBsplineIndex ;
for (kk = 0 ; kk < ArrayDimension ; kk++) {
LocalRealArray[Index + kk] = 0.0e0 ;
}
for (jj = 1 ; jj <= Order ; jj++) {
for (kk = 0 ; kk < ArrayDimension ; kk++) {
LocalRealArray[Index + kk] +=
PolesArray[(Index1-1)*ArrayDimension + kk] * BsplineBasis(ii,jj) ;
}
Index1 = Index1 % Modulus ;
Index1 += 1 ;
}
for (kk = 0 ; kk < ArrayDimension ; kk++) {
LocalRealArray[Index + kk] *= Inverse ;
}
Index += ArrayDimension ;
Inverse /= (Standard_Real) ii ;
}
PLib::EvalPolynomial(Delta,
NewRequest,
Degree,
ArrayDimension,
LocalRealArray[0],
Results) ;
}
FINISH : ;
}
//=======================================================================
//function : TangExtendToConstraint
//purpose : Extends a Bspline function using the tangency map
// WARNING :
//
//
//=======================================================================
void BSplCLib::TangExtendToConstraint
(const TColStd_Array1OfReal& FlatKnots,
const Standard_Real C1Coefficient,
const Standard_Integer NumPoles,
Standard_Real& Poles,
const Standard_Integer CDimension,
const Standard_Integer CDegree,
const TColStd_Array1OfReal& ConstraintPoint,
const Standard_Integer Continuity,
const Standard_Boolean After,
Standard_Integer& NbPolesResult,
Standard_Integer& NbKnotsResult,
Standard_Real& KnotsResult,
Standard_Real& PolesResult)
{
#if DEB
if (CDegree<Continuity+1) {
cout<<"The BSpline degree must be greater than the order of continuity"<<endl;
}
#endif
Standard_Real * Padr = &Poles ;
Standard_Real * KRadr = &KnotsResult ;
Standard_Real * PRadr = &PolesResult ;
////////////////////////////////////////////////////////////////////////
//
// 1. calculation of extension nD
//
////////////////////////////////////////////////////////////////////////
// Hermite matrix
Standard_Integer Csize = Continuity + 2;
math_Matrix MatCoefs(1,Csize, 1,Csize);
if (After) {
PLib::HermiteCoefficients(0, 1, // Limits
Continuity, 0, // Orders of constraints
MatCoefs);
}
else {
PLib::HermiteCoefficients(0, 1, // Limits
0, Continuity, // Orders of constraints
MatCoefs);
}
// position at the node of connection
Standard_Real Tbord ;
if (After) {
Tbord = FlatKnots(FlatKnots.Upper()-CDegree);
}
else {
Tbord = FlatKnots(FlatKnots.Lower()+CDegree);
}
Standard_Boolean periodic_flag = Standard_False ;
Standard_Integer ipos, extrap_mode[2], derivative_request = Max(Continuity,1);
extrap_mode[0] = extrap_mode[1] = CDegree;
TColStd_Array1OfReal EvalBS(1, CDimension * (derivative_request+1)) ;
Standard_Real * Eadr = (Standard_Real *) &EvalBS(1) ;
BSplCLib::Eval(Tbord,periodic_flag,derivative_request,extrap_mode[0],
CDegree,FlatKnots,CDimension,Poles,*Eadr);
// norm of the tangent at the node of connection
math_Vector Tgte(1,CDimension);
for (ipos=1;ipos<=CDimension;ipos++) {
Tgte(ipos) = EvalBS(ipos+CDimension);
}
Standard_Real L1=Tgte.Norm();
// matrix of constraints
math_Matrix Contraintes(1,Csize,1,CDimension);
if (After) {
for (ipos=1;ipos<=CDimension;ipos++) {
Contraintes(1,ipos) = EvalBS(ipos);
Contraintes(2,ipos) = C1Coefficient * EvalBS(ipos+CDimension);
if(Continuity >= 2) Contraintes(3,ipos) = EvalBS(ipos+2*CDimension) * Pow(C1Coefficient,2);
if(Continuity >= 3) Contraintes(4,ipos) = EvalBS(ipos+3*CDimension) * Pow(C1Coefficient,3);
Contraintes(Continuity+2,ipos) = ConstraintPoint(ipos);
}
}
else {
for (ipos=1;ipos<=CDimension;ipos++) {
Contraintes(1,ipos) = ConstraintPoint(ipos);
Contraintes(2,ipos) = EvalBS(ipos);
if(Continuity >= 1) Contraintes(3,ipos) = C1Coefficient * EvalBS(ipos+CDimension);
if(Continuity >= 2) Contraintes(4,ipos) = EvalBS(ipos+2*CDimension) * Pow(C1Coefficient,2);
if(Continuity >= 3) Contraintes(5,ipos) = EvalBS(ipos+3*CDimension) * Pow(C1Coefficient,3);
}
}
// calculate the coefficients of extension
Standard_Integer ii, jj, kk;
TColStd_Array1OfReal ExtraCoeffs(1,Csize*CDimension);
ExtraCoeffs.Init(0.);
for (ii=1; ii<=Csize; ii++) {
for (jj=1; jj<=Csize; jj++) {
for (kk=1; kk<=CDimension; kk++) {
ExtraCoeffs(kk+(jj-1)*CDimension) += MatCoefs(ii,jj)*Contraintes(ii,kk);
}
}
}
// calculate the poles of extension
TColStd_Array1OfReal ExtrapPoles(1,Csize*CDimension);
Standard_Real * EPadr = &ExtrapPoles(1) ;
PLib::CoefficientsPoles(CDimension,
ExtraCoeffs, PLib::NoWeights(),
ExtrapPoles, PLib::NoWeights());
// calculate the nodes of extension with multiplicities
TColStd_Array1OfReal ExtrapNoeuds(1,2);
ExtrapNoeuds(1) = 0.;
ExtrapNoeuds(2) = 1.;
TColStd_Array1OfInteger ExtrapMults(1,2);
ExtrapMults(1) = Csize;
ExtrapMults(2) = Csize;
// flat nodes of extension
TColStd_Array1OfReal FK2(1, Csize*2);
BSplCLib::KnotSequence(ExtrapNoeuds,ExtrapMults,FK2);
// norm of the tangent at the connection point
if (After) {
BSplCLib::Eval(0.,periodic_flag,1,extrap_mode[0],
Csize-1,FK2,CDimension,*EPadr,*Eadr);
}
else {
BSplCLib::Eval(1.,periodic_flag,1,extrap_mode[0],
Csize-1,FK2,CDimension,*EPadr,*Eadr);
}
for (ipos=1;ipos<=CDimension;ipos++) {
Tgte(ipos) = EvalBS(ipos+CDimension);
}
Standard_Real L2 = Tgte.Norm();
// harmonisation of degrees
TColStd_Array1OfReal NewP2(1, (CDegree+1)*CDimension);
TColStd_Array1OfReal NewK2(1, 2);
TColStd_Array1OfInteger NewM2(1, 2);
if (Csize-1<CDegree) {
BSplCLib::IncreaseDegree(Csize-1,CDegree,Standard_False,CDimension,
ExtrapPoles,ExtrapNoeuds,ExtrapMults,
NewP2,NewK2,NewM2);
}
else {
NewP2 = ExtrapPoles;
NewK2 = ExtrapNoeuds;
NewM2 = ExtrapMults;
}
// flat nodes of extension after harmonization of degrees
TColStd_Array1OfReal NewFK2(1, (CDegree+1)*2);
BSplCLib::KnotSequence(NewK2,NewM2,NewFK2);
////////////////////////////////////////////////////////////////////////
//
// 2. concatenation C0
//
////////////////////////////////////////////////////////////////////////
// ratio of reparametrization
Standard_Real Ratio=1, Delta;
if ( (L1 > Precision::Confusion()) && (L2 > Precision::Confusion()) ) {
Ratio = L2 / L1;
}
if ( (Ratio < 1.e-5) || (Ratio > 1.e5) ) Ratio = 1;
if (After) {
// do not touch the first BSpline
Delta = Ratio*NewFK2(NewFK2.Lower()) - FlatKnots(FlatKnots.Upper());
}
else {
// do not touch the second BSpline
Delta = Ratio*NewFK2(NewFK2.Upper()) - FlatKnots(FlatKnots.Lower());
}
// result of the concatenation
Standard_Integer NbP1 = NumPoles, NbP2 = CDegree+1;
Standard_Integer NbK1 = FlatKnots.Length(), NbK2 = 2*(CDegree+1);
TColStd_Array1OfReal NewPoles (1, (NbP1+ NbP2-1)*CDimension);
TColStd_Array1OfReal NewFlats (1, NbK1+NbK2-CDegree-2);
// poles
Standard_Integer indNP, indP, indEP;
if (After) {
for (ii=1; ii<=NbP1+NbP2-1; ii++) {
for (jj=1; jj<=CDimension; jj++) {
indNP = (ii-1)*CDimension+jj;
indP = (ii-1)*CDimension+jj-1;
indEP = (ii-NbP1)*CDimension+jj;
if (ii<NbP1) NewPoles(indNP) = Padr[indP];
else NewPoles(indNP) = NewP2(indEP);
}
}
}
else {
for (ii=1; ii<=NbP1+NbP2-1; ii++) {
for (jj=1; jj<=CDimension; jj++) {
indNP = (ii-1)*CDimension+jj;
indEP = (ii-1)*CDimension+jj;
indP = (ii-NbP2)*CDimension+jj-1;
if (ii<NbP2) NewPoles(indNP) = NewP2(indEP);
else NewPoles(indNP) = Padr[indP];
}
}
}
// flat nodes
if (After) {
// start with the nodes of the initial surface
for (ii=1; ii<NbK1; ii++) {
NewFlats(ii) = FlatKnots(FlatKnots.Lower()+ii-1);
}
// continue with the reparameterized nodes of the extension
for (ii=1; ii<=NbK2-CDegree-1; ii++) {
NewFlats(NbK1+ii-1) = Ratio*NewFK2(NewFK2.Lower()+ii+CDegree) - Delta;
}
}
else {
// start with the reparameterized nodes of the extension
for (ii=1; ii<NbK2-CDegree; ii++) {
NewFlats(ii) = Ratio*NewFK2(NewFK2.Lower()+ii-1) - Delta;
}
// continue with the nodes of the initial surface
for (ii=2; ii<=NbK1; ii++) {
NewFlats(NbK2+ii-CDegree-2) = FlatKnots(FlatKnots.Lower()+ii-1);
}
}
////////////////////////////////////////////////////////////////////////
//
// 3. reduction of multiplicite at the node of connection
//
////////////////////////////////////////////////////////////////////////
// number of separate nodes
Standard_Integer KLength = 1;
for (ii=2; ii<=NbK1+NbK2-CDegree-2;ii++) {
if (NewFlats(ii) != NewFlats(ii-1)) KLength++;
}
// flat nodes --> nodes + multiplicities
TColStd_Array1OfReal NewKnots (1, KLength);
TColStd_Array1OfInteger NewMults (1, KLength);
NewMults.Init(1);
jj = 1;
NewKnots(jj) = NewFlats(1);
for (ii=2; ii<=NbK1+NbK2-CDegree-2;ii++) {
if (NewFlats(ii) == NewFlats(ii-1)) NewMults(jj)++;
else {
jj++;
NewKnots(jj) = NewFlats(ii);
}
}
// reduction of multiplicity at the second or the last but one node
Standard_Integer Index = 2, M = CDegree;
if (After) Index = KLength-1;
TColStd_Array1OfReal ResultPoles (1, (NbP1+ NbP2-1)*CDimension);
TColStd_Array1OfReal ResultKnots (1, KLength);
TColStd_Array1OfInteger ResultMults (1, KLength);
Standard_Real Tol = 1.e-6;
Standard_Boolean Ok = Standard_True;
while ( (M>CDegree-Continuity) && Ok) {
Ok = RemoveKnot(Index, M-1, CDegree, Standard_False, CDimension,
NewPoles, NewKnots, NewMults,
ResultPoles, ResultKnots, ResultMults, Tol);
if (Ok) M--;
}
if (M == CDegree) {
// number of poles of the concatenation
NbPolesResult = NbP1 + NbP2 - 1;
// the poles of the concatenation
Standard_Integer PLength = NbPolesResult*CDimension;
for (jj=1; jj<=PLength; jj++) {
PRadr[jj-1] = NewPoles(jj);
}
// flat nodes of the concatenation
Standard_Integer ideb = 0;
for (jj=0; jj<NewKnots.Length(); jj++) {
for (ii=0; ii<NewMults(jj+1); ii++) {
KRadr[ideb+ii] = NewKnots(jj+1);
}
ideb += NewMults(jj+1);
}
NbKnotsResult = ideb;
}
else {
// number of poles of the result
NbPolesResult = NbP1 + NbP2 - 1 - CDegree + M;
// the poles of the result
Standard_Integer PLength = NbPolesResult*CDimension;
for (jj=0; jj<PLength; jj++) {
PRadr[jj] = ResultPoles(jj+1);
}
// flat nodes of the result
Standard_Integer ideb = 0;
for (jj=0; jj<ResultKnots.Length(); jj++) {
for (ii=0; ii<ResultMults(jj+1); ii++) {
KRadr[ideb+ii] = ResultKnots(jj+1);
}
ideb += ResultMults(jj+1);
}
NbKnotsResult = ideb;
}
}
//=======================================================================
//function : Resolution
//purpose :
// d
// Let C(t) = SUM Ci Bi(t) a Bspline curve of degree d
// i = 1,n
// with nodes tj for j = 1,n+d+1
//
//
// ' C1 - Ci-1 d-1
// Then C (t) = SUM d * --------- Bi (t)
// i = 2,n ti+d - ti
//
// d-1
// for the base of BSpline Bi (t) of degree d-1.
//
// Consequently the upper bound of the norm of the derivative from C is :
//
//
// | Ci - Ci-1 |
// d * Max | --------- |
// i = 2,n | ti+d - ti |
//
// N(t)
// In the rational case set C(t) = -----
// D(t)
//
//
// D(t) = SUM Di Bi(t)
// i=1,n
//
// N(t) = SUM Di * Ci Bi(t)
// i =1,n
//
// N'(t) - D'(t) C(t)
// C'(t) = -----------------------
// D(t)
//
//
// N'(t) - D'(t) C(t) =
//
// Di * (Ci - C(t)) - Di-1 * (Ci-1 - C(t)) d-1
// SUM d * ---------------------------------------- * Bi (t) =
// i=2,n ti+d - ti
//
//
// Di * (Ci - Cj) - Di-1 * (Ci-1 - Cj) d-1
// SUM SUM d * ----------------------------------- * Betaj(t) * Bi (t)
//i=2,n j=1,n ti+d - ti
//
//
//
// Dj Bj(t)
// Betaj(t) = --------
// D(t)
//
// Betaj(t) form a partition >= 0 of the entity with support
// tj, tj+d+1. Consequently if Rj = {j-d, ...., j+d+d+1}
// obtain an upper bound of the derivative of C by taking :
//
//
//
//
//
//
// Di * (Ci - Cj) - Di-1 * (Ci-1 - Cj)
// Max Max d * -----------------------------------
// j=1,n i dans Rj ti+d - ti
//
// --------------------------------------------------------
//
// Min Di
// i =1,n
//
//
//=======================================================================
void BSplCLib::Resolution( Standard_Real& Poles,
const Standard_Integer ArrayDimension,
const Standard_Integer NumPoles,
const TColStd_Array1OfReal& Weights,
const TColStd_Array1OfReal& FlatKnots,
const Standard_Integer Degree,
const Standard_Real Tolerance3D,
Standard_Real& UTolerance)
{
Standard_Integer ii,num_poles,ii_index,jj_index,ii_inDim;
Standard_Integer lower,upper,ii_minus,jj,ii_miDim;
Standard_Integer Deg1 = Degree + 1;
Standard_Integer Deg2 = (Degree << 1) + 1;
Standard_Real value,factor,W,min_weights,inverse;
Standard_Real pa_ii_inDim_0, pa_ii_inDim_1, pa_ii_inDim_2, pa_ii_inDim_3;
Standard_Real pa_ii_miDim_0, pa_ii_miDim_1, pa_ii_miDim_2, pa_ii_miDim_3;
Standard_Real wg_ii_index, wg_ii_minus;
Standard_Real *PA,max_derivative;
const Standard_Real * FK = &FlatKnots(FlatKnots.Lower());
PA = &Poles;
max_derivative = 0.0e0;
num_poles = FlatKnots.Length() - Deg1;
switch (ArrayDimension) {
case 2 : {
if (&Weights != NULL) {
const Standard_Real * WG = &Weights(Weights.Lower());
min_weights = WG[0];
for (ii = 1 ; ii < NumPoles ; ii++) {
W = WG[ii];
if (W < min_weights) min_weights = W;
}
for (ii = 1 ; ii < num_poles ; ii++) {
ii_index = ii % NumPoles;
ii_inDim = ii_index << 1;
ii_minus = (ii - 1) % NumPoles;
ii_miDim = ii_minus << 1;
pa_ii_inDim_0 = PA[ii_inDim]; ii_inDim++;
pa_ii_inDim_1 = PA[ii_inDim];
pa_ii_miDim_0 = PA[ii_miDim]; ii_miDim++;
pa_ii_miDim_1 = PA[ii_miDim];
wg_ii_index = WG[ii_index];
wg_ii_minus = WG[ii_minus];
inverse = FK[ii + Degree] - FK[ii];
inverse = 1.0e0 / inverse;
lower = ii - Deg1;
if (lower < 0) lower = 0;
upper = Deg2 + ii;
if (upper > num_poles) upper = num_poles;
for (jj = lower ; jj < upper ; jj++) {
jj_index = jj % NumPoles;
jj_index = jj_index << 1;
value = 0.0e0;
factor = (((PA[jj_index] - pa_ii_inDim_0) * wg_ii_index) -
((PA[jj_index] - pa_ii_miDim_0) * wg_ii_minus));
if (factor < 0) factor = - factor;
value += factor; jj_index++;
factor = (((PA[jj_index] - pa_ii_inDim_1) * wg_ii_index) -
((PA[jj_index] - pa_ii_miDim_1) * wg_ii_minus));
if (factor < 0) factor = - factor;
value += factor;
value *= inverse;
if (max_derivative < value) max_derivative = value;
}
}
max_derivative /= min_weights;
}
else {
for (ii = 1 ; ii < num_poles ; ii++) {
ii_index = ii % NumPoles;
ii_index = ii_index << 1;
ii_minus = (ii - 1) % NumPoles;
ii_minus = ii_minus << 1;
inverse = FK[ii + Degree] - FK[ii];
inverse = 1.0e0 / inverse;
value = 0.0e0;
factor = PA[ii_index] - PA[ii_minus];
if (factor < 0) factor = - factor;
value += factor; ii_index++; ii_minus++;
factor = PA[ii_index] - PA[ii_minus];
if (factor < 0) factor = - factor;
value += factor;
value *= inverse;
if (max_derivative < value) max_derivative = value;
}
}
break;
}
case 3 : {
if (&Weights != NULL) {
const Standard_Real * WG = &Weights(Weights.Lower());
min_weights = WG[0];
for (ii = 1 ; ii < NumPoles ; ii++) {
W = WG[ii];
if (W < min_weights) min_weights = W;
}
for (ii = 1 ; ii < num_poles ; ii++) {
ii_index = ii % NumPoles;
ii_inDim = (ii_index << 1) + ii_index;
ii_minus = (ii - 1) % NumPoles;
ii_miDim = (ii_minus << 1) + ii_minus;
pa_ii_inDim_0 = PA[ii_inDim]; ii_inDim++;
pa_ii_inDim_1 = PA[ii_inDim]; ii_inDim++;
pa_ii_inDim_2 = PA[ii_inDim];
pa_ii_miDim_0 = PA[ii_miDim]; ii_miDim++;
pa_ii_miDim_1 = PA[ii_miDim]; ii_miDim++;
pa_ii_miDim_2 = PA[ii_miDim];
wg_ii_index = WG[ii_index];
wg_ii_minus = WG[ii_minus];
inverse = FK[ii + Degree] - FK[ii];
inverse = 1.0e0 / inverse;
lower = ii - Deg1;
if (lower < 0) lower = 0;
upper = Deg2 + ii;
if (upper > num_poles) upper = num_poles;
for (jj = lower ; jj < upper ; jj++) {
jj_index = jj % NumPoles;
jj_index = (jj_index << 1) + jj_index;
value = 0.0e0;
factor = (((PA[jj_index] - pa_ii_inDim_0) * wg_ii_index) -
((PA[jj_index] - pa_ii_miDim_0) * wg_ii_minus));
if (factor < 0) factor = - factor;
value += factor; jj_index++;
factor = (((PA[jj_index] - pa_ii_inDim_1) * wg_ii_index) -
((PA[jj_index] - pa_ii_miDim_1) * wg_ii_minus));
if (factor < 0) factor = - factor;
value += factor; jj_index++;
factor = (((PA[jj_index] - pa_ii_inDim_2) * wg_ii_index) -
((PA[jj_index] - pa_ii_miDim_2) * wg_ii_minus));
if (factor < 0) factor = - factor;
value += factor;
value *= inverse;
if (max_derivative < value) max_derivative = value;
}
}
max_derivative /= min_weights;
}
else {
for (ii = 1 ; ii < num_poles ; ii++) {
ii_index = ii % NumPoles;
ii_index = (ii_index << 1) + ii_index;
ii_minus = (ii - 1) % NumPoles;
ii_minus = (ii_minus << 1) + ii_minus;
inverse = FK[ii + Degree] - FK[ii];
inverse = 1.0e0 / inverse;
value = 0.0e0;
factor = PA[ii_index] - PA[ii_minus];
if (factor < 0) factor = - factor;
value += factor; ii_index++; ii_minus++;
factor = PA[ii_index] - PA[ii_minus];
if (factor < 0) factor = - factor;
value += factor; ii_index++; ii_minus++;
factor = PA[ii_index] - PA[ii_minus];
if (factor < 0) factor = - factor;
value += factor;
value *= inverse;
if (max_derivative < value) max_derivative = value;
}
}
break;
}
case 4 : {
if (&Weights != NULL) {
const Standard_Real * WG = &Weights(Weights.Lower());
min_weights = WG[0];
for (ii = 1 ; ii < NumPoles ; ii++) {
W = WG[ii];
if (W < min_weights) min_weights = W;
}
for (ii = 1 ; ii < num_poles ; ii++) {
ii_index = ii % NumPoles;
ii_inDim = ii_index << 2;
ii_minus = (ii - 1) % NumPoles;
ii_miDim = ii_minus << 2;
pa_ii_inDim_0 = PA[ii_inDim]; ii_inDim++;
pa_ii_inDim_1 = PA[ii_inDim]; ii_inDim++;
pa_ii_inDim_2 = PA[ii_inDim]; ii_inDim++;
pa_ii_inDim_3 = PA[ii_inDim];
pa_ii_miDim_0 = PA[ii_miDim]; ii_miDim++;
pa_ii_miDim_1 = PA[ii_miDim]; ii_miDim++;
pa_ii_miDim_2 = PA[ii_miDim]; ii_miDim++;
pa_ii_miDim_3 = PA[ii_miDim];
wg_ii_index = WG[ii_index];
wg_ii_minus = WG[ii_minus];
inverse = FK[ii + Degree] - FK[ii];
inverse = 1.0e0 / inverse;
lower = ii - Deg1;
if (lower < 0) lower = 0;
upper = Deg2 + ii;
if (upper > num_poles) upper = num_poles;
for (jj = lower ; jj < upper ; jj++) {
jj_index = jj % NumPoles;
jj_index = jj_index << 2;
value = 0.0e0;
factor = (((PA[jj_index] - pa_ii_inDim_0) * wg_ii_index) -
((PA[jj_index] - pa_ii_miDim_0) * wg_ii_minus));
if (factor < 0) factor = - factor;
value += factor; jj_index++;
factor = (((PA[jj_index] - pa_ii_inDim_1) * wg_ii_index) -
((PA[jj_index] - pa_ii_miDim_1) * wg_ii_minus));
if (factor < 0) factor = - factor;
value += factor; jj_index++;
factor = (((PA[jj_index] - pa_ii_inDim_2) * wg_ii_index) -
((PA[jj_index] - pa_ii_miDim_2) * wg_ii_minus));
if (factor < 0) factor = - factor;
value += factor; jj_index++;
factor = (((PA[jj_index] - pa_ii_inDim_3) * wg_ii_index) -
((PA[jj_index] - pa_ii_miDim_3) * wg_ii_minus));
if (factor < 0) factor = - factor;
value += factor;
value *= inverse;
if (max_derivative < value) max_derivative = value;
}
}
max_derivative /= min_weights;
}
else {
for (ii = 1 ; ii < num_poles ; ii++) {
ii_index = ii % NumPoles;
ii_index = ii_index << 2;
ii_minus = (ii - 1) % NumPoles;
ii_minus = ii_minus << 2;
inverse = FK[ii + Degree] - FK[ii];
inverse = 1.0e0 / inverse;
value = 0.0e0;
factor = PA[ii_index] - PA[ii_minus];
if (factor < 0) factor = - factor;
value += factor; ii_index++; ii_minus++;
factor = PA[ii_index] - PA[ii_minus];
if (factor < 0) factor = - factor;
value += factor; ii_index++; ii_minus++;
factor = PA[ii_index] - PA[ii_minus];
if (factor < 0) factor = - factor;
value += factor; ii_index++; ii_minus++;
factor = PA[ii_index] - PA[ii_minus];
if (factor < 0) factor = - factor;
value += factor;
value *= inverse;
if (max_derivative < value) max_derivative = value;
}
}
break;
}
default : {
Standard_Integer kk;
if (&Weights != NULL) {
const Standard_Real * WG = &Weights(Weights.Lower());
min_weights = WG[0];
for (ii = 1 ; ii < NumPoles ; ii++) {
W = WG[ii];
if (W < min_weights) min_weights = W;
}
for (ii = 1 ; ii < num_poles ; ii++) {
ii_index = ii % NumPoles;
ii_inDim = ii_index * ArrayDimension;
ii_minus = (ii - 1) % NumPoles;
ii_miDim = ii_minus * ArrayDimension;
wg_ii_index = WG[ii_index];
wg_ii_minus = WG[ii_minus];
inverse = FK[ii + Degree] - FK[ii];
inverse = 1.0e0 / inverse;
lower = ii - Deg1;
if (lower < 0) lower = 0;
upper = Deg2 + ii;
if (upper > num_poles) upper = num_poles;
for (jj = lower ; jj < upper ; jj++) {
jj_index = jj % NumPoles;
jj_index *= ArrayDimension;
value = 0.0e0;
for (kk = 0 ; kk < ArrayDimension ; kk++) {
factor = (((PA[jj_index + kk] - PA[ii_inDim + kk]) * wg_ii_index) -
((PA[jj_index + kk] - PA[ii_miDim + kk]) * wg_ii_minus));
if (factor < 0) factor = - factor;
value += factor;
}
value *= inverse;
if (max_derivative < value) max_derivative = value;
}
}
max_derivative /= min_weights;
}
else {
for (ii = 1 ; ii < num_poles ; ii++) {
ii_index = ii % NumPoles;
ii_index *= ArrayDimension;
ii_minus = (ii - 1) % NumPoles;
ii_minus *= ArrayDimension;
inverse = FK[ii + Degree] - FK[ii];
inverse = 1.0e0 / inverse;
value = 0.0e0;
for (kk = 0 ; kk < ArrayDimension ; kk++) {
factor = PA[ii_index + kk] - PA[ii_minus + kk];
if (factor < 0) factor = - factor;
value += factor;
}
value *= inverse;
if (max_derivative < value) max_derivative = value;
}
}
}
}
max_derivative *= Degree;
if (max_derivative > RealSmall())
UTolerance = Tolerance3D / max_derivative;
else
UTolerance = Tolerance3D / RealSmall();
}
//=======================================================================
// function: FlatBezierKnots
// purpose :
//=======================================================================
// array of flat knots for bezier curve of maximum 25 degree
static const Standard_Real knots[52] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
const Standard_Real& BSplCLib::FlatBezierKnots (const Standard_Integer Degree)
{
Standard_OutOfRange_Raise_if (Degree < 1 || Degree > MaxDegree() || MaxDegree() != 25,
"Bezier curve degree greater than maximal supported");
return knots[25-Degree];
}