Logo Search packages:      
Sourcecode: opencascade version File versions  Download package

Law_BSpline.cxx

// File:    Law_BSpline.cxx
// Created: Fri Oct 20 17:02:49 1995
// Author:  Laurent BOURESCHE
//          <lbo@phylox>
// Cut and past sauvage depuis Geom!?!?
// 14-Mar-96 : xab implemented MovePointAndTangent 
// 03-02-97 : pmn ->LocateU sur Periodic (PRO6963), 
//            bon appel a LocateParameter (PRO6973) et mise en conformite avec
//            le cdl de LocateU, lorsque U est un noeud (PRO6988)

#include <Law_BSpline.ixx>
#include <gp.hxx>
#include <BSplCLib.hxx>
#include <BSplCLib_KnotDistribution.hxx>
#include <BSplCLib_MultDistribution.hxx>

#include <Standard_DimensionError.hxx>
#include <Standard_OutOfRange.hxx>
#include <Standard_DomainError.hxx>
#include <Standard_RangeError.hxx>
#include <Standard_NotImplemented.hxx>
#include <Standard_ConstructionError.hxx>

#define  POLES    (poles->Array1())
#define  KNOTS    (knots->Array1())
#define  FKNOTS   (flatknots->Array1())
#define  FMULTS   (BSplCLib::NoMults())

//=======================================================================
//function : SetPoles
//purpose  : 
//=======================================================================

static void SetPoles(const TColStd_Array1OfReal& Poles,
                 const TColStd_Array1OfReal& Weights,
                 TColStd_Array1OfReal&       FP)
{
  Standard_Integer i,j = FP.Lower();
  for (i = Poles.Lower(); i <= Poles.Upper(); i++) {
    Standard_Real w = Weights(i);
    FP(j) = Poles(i) * w;
    j++;
    FP(j) = w;
    j++;
  }
}


//=======================================================================
//function : GetPoles
//purpose  : 
//=======================================================================

static void GetPoles(const TColStd_Array1OfReal& FP,
                 TColStd_Array1OfReal&       Poles,
                 TColStd_Array1OfReal&       Weights)
     
{
  Standard_Integer i,j = FP.Lower();
  for (i = Poles.Lower(); i <= Poles.Upper(); i++) {
    Standard_Real w = FP(j+1);
    Weights(i) = w;
    Poles(i) = FP(j) /w;
    j+=2;
  }
}


//=======================================================================
//function : CheckCurveData
//purpose  : Internal use only
//=======================================================================

static void CheckCurveData
(const TColStd_Array1OfReal&       CPoles,
 const TColStd_Array1OfReal&       CKnots,
 const TColStd_Array1OfInteger&    CMults,
 const Standard_Integer            Degree,
 const Standard_Boolean            Periodic)
{
  if (Degree < 1 || Degree > Law_BSpline::MaxDegree()) {
    Standard_ConstructionError::Raise();  
  }
  
  if (CPoles.Length() < 2)                Standard_ConstructionError::Raise();
  if (CKnots.Length() != CMults.Length()) Standard_ConstructionError::Raise();
  
  for (Standard_Integer I = CKnots.Lower(); I < CKnots.Upper(); I++) {
    if (CKnots (I+1) - CKnots (I) <= Epsilon (Abs(CKnots (I)))) {
      Standard_ConstructionError::Raise();
    }
  }
  
  if (CPoles.Length() != BSplCLib::NbPoles(Degree,Periodic,CMults))
    Standard_ConstructionError::Raise();
}


//=======================================================================
//function : KnotAnalysis
//purpose  : Internal use only
//=======================================================================

static void 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 : Rational
//purpose  : check rationality of an array of weights
//=======================================================================

static Standard_Boolean Rational(const TColStd_Array1OfReal& W)
{
  Standard_Integer i, n = W.Length();
  Standard_Boolean rat = Standard_False;
  for (i = 1; i < n; i++) {
    rat =  Abs(W(i) - W(i+1)) > gp::Resolution();
    if (rat) break;
  }
  return rat;
}

//=======================================================================
//function : Copy
//purpose  : 
//=======================================================================

Handle(Law_BSpline) Law_BSpline::Copy() const
{
  Handle(Law_BSpline) C;
  if (IsRational()) 
    C = new Law_BSpline(poles->Array1(),
                  weights->Array1(),
                  knots->Array1(),
                  mults->Array1(),
                  deg,periodic);
  else
    C = new Law_BSpline(poles->Array1(),
                  knots->Array1(),
                  mults->Array1(),
                  deg,periodic);
  return C;
}



//=======================================================================
//function : Law_BSpline
//purpose  : 
//=======================================================================

Law_BSpline::Law_BSpline
00203 (const TColStd_Array1OfReal&       Poles,
 const TColStd_Array1OfReal&     Knots,
 const TColStd_Array1OfInteger&  Mults,
 const Standard_Integer          Degree,
 const Standard_Boolean          Periodic) :
 rational(Standard_False),periodic(Periodic), deg(Degree)  
{
  // check
  
  CheckCurveData (Poles,
              Knots,
              Mults,
              Degree,
              Periodic);
  
  
  // copy arrays
  
  poles =  new TColStd_HArray1OfReal(1,Poles.Length());
  poles->ChangeArray1() = Poles;
  
  
  knots = new TColStd_HArray1OfReal(1,Knots.Length());
  knots->ChangeArray1() = Knots;
  
  mults = new TColStd_HArray1OfInteger(1,Mults.Length());
  mults->ChangeArray1() = Mults;
  
  UpdateKnots();
}



//=======================================================================
//function : Law_BSpline
//purpose  : 
//=======================================================================

Law_BSpline::Law_BSpline
00242 (const TColStd_Array1OfReal&      Poles,
 const TColStd_Array1OfReal&    Weights,
 const TColStd_Array1OfReal&    Knots,
 const TColStd_Array1OfInteger& Mults,
 const Standard_Integer         Degree,
 const Standard_Boolean         Periodic)  :
 rational(Standard_True),  periodic(Periodic), deg(Degree)
     
{
  
  // check
  
  CheckCurveData (Poles,
              Knots,
              Mults,
              Degree,
              Periodic);
  
  if (Weights.Length() != Poles.Length())
    Standard_ConstructionError::Raise("Law_BSpline");
  
  Standard_Integer i;
  for (i = Weights.Lower(); i <= Weights.Upper(); i++) {
    if (Weights(i) <= gp::Resolution())  
      Standard_ConstructionError::Raise("Law_BSpline");
  }
  
  // check really rational
  rational = Rational(Weights);
  
  // copy arrays
  
  poles =  new TColStd_HArray1OfReal(1,Poles.Length());
  poles->ChangeArray1() = Poles;
  if (rational) {
    weights =  new TColStd_HArray1OfReal(1,Weights.Length());
    weights->ChangeArray1() = Weights;
  }
  
  knots = new TColStd_HArray1OfReal(1,Knots.Length());
  knots->ChangeArray1() = Knots;
  
  mults = new TColStd_HArray1OfInteger(1,Mults.Length());
  mults->ChangeArray1() = Mults;
  
  UpdateKnots();
}


//=======================================================================
//function : MaxDegree
//purpose  : 
//=======================================================================

00296 Standard_Integer Law_BSpline::MaxDegree () 
{ 
  return BSplCLib::MaxDegree(); 
}


//=======================================================================
//function : IncreaseDegree
//purpose  : 
//=======================================================================

00307 void Law_BSpline::IncreaseDegree  (const Standard_Integer Degree)
{
  if (Degree == deg) return;
  
  if (Degree < deg || Degree > Law_BSpline::MaxDegree()) {
    Standard_ConstructionError::Raise();
  }
  
  Standard_Integer FromK1 = FirstUKnotIndex ();
  Standard_Integer ToK2   = LastUKnotIndex  ();
  
  Standard_Integer Step   = Degree - deg;
  
  Handle(TColStd_HArray1OfReal) npoles = new
    TColStd_HArray1OfReal(1,poles->Length() + Step * (ToK2-FromK1));
  
  Standard_Integer nbknots = BSplCLib::IncreaseDegreeCountKnots
    (deg,Degree,periodic,mults->Array1());
  
  Handle(TColStd_HArray1OfReal) nknots = 
    new TColStd_HArray1OfReal(1,nbknots);
  
  Handle(TColStd_HArray1OfInteger) nmults = 
    new TColStd_HArray1OfInteger(1,nbknots);
  
  Handle(TColStd_HArray1OfReal) nweights;
  
  if (IsRational()) {
    nweights = new TColStd_HArray1OfReal(1,npoles->Upper());
    TColStd_Array1OfReal adimpol(1,2*poles->Upper());
    SetPoles(poles->Array1(),weights->Array1(),adimpol);
    TColStd_Array1OfReal adimnpol(1,2*npoles->Upper());
    BSplCLib::IncreaseDegree
      (deg,Degree, periodic,2,adimpol,
       knots->Array1(),mults->Array1(),adimnpol,
       nknots->ChangeArray1(),nmults->ChangeArray1());
    GetPoles(adimnpol,npoles->ChangeArray1(),nweights->ChangeArray1());
  }
  else {
    BSplCLib::IncreaseDegree
      (deg,Degree, periodic,1,poles->Array1(),
       knots->Array1(),mults->Array1(),npoles->ChangeArray1(),
       nknots->ChangeArray1(),nmults->ChangeArray1());
  }
  
  deg     = Degree;
  poles   = npoles;
  weights = nweights;
  knots   = nknots;
  mults   = nmults;
  UpdateKnots();
  
}


//=======================================================================
//function : IncreaseMultiplicity
//purpose  : 
//=======================================================================

00367 void Law_BSpline::IncreaseMultiplicity  (const Standard_Integer Index,
                               const Standard_Integer M)
{
  TColStd_Array1OfReal k(1,1);
  k(1) = knots->Value(Index);
  TColStd_Array1OfInteger m(1,1);
  m(1) = M - mults->Value(Index);
  InsertKnots(k,m,Epsilon(1.));
}


//=======================================================================
//function : IncreaseMultiplicity
//purpose  : 
//=======================================================================

00383 void Law_BSpline::IncreaseMultiplicity  (const Standard_Integer I1,
                               const Standard_Integer I2,
                               const Standard_Integer M)
{
  Handle(TColStd_HArray1OfReal)  tk = knots;
  TColStd_Array1OfReal k((knots->Array1())(I1),I1,I2);
  TColStd_Array1OfInteger m(I1,I2);
  Standard_Integer i;
  for (i = I1; i <= I2; i++)
    m(i) = M - mults->Value(i);
  InsertKnots(k,m,Epsilon(1.));
}

//=======================================================================
//function : IncrementMultiplicity
//purpose  : 
//=======================================================================

void Law_BSpline::IncrementMultiplicity
00402 (const Standard_Integer I1,
 const Standard_Integer I2,
 const Standard_Integer Step)
{
  Handle(TColStd_HArray1OfReal) tk = knots;
  TColStd_Array1OfReal    k((knots->Array1())(I1),I1,I2);
  TColStd_Array1OfInteger m(I1,I2) ;
  m.Init(Step);
  InsertKnots(k,m,Epsilon(1.));
}


//=======================================================================
//function : InsertKnot
//purpose  : 
//=======================================================================

void Law_BSpline::InsertKnot
00420 (const Standard_Real U, 
 const Standard_Integer M, 
 const Standard_Real ParametricTolerance,
 const Standard_Boolean Add)
{
  TColStd_Array1OfReal k(1,1);
  k(1) = U;
  TColStd_Array1OfInteger m(1,1);
  m(1) = M;
  InsertKnots(k,m,ParametricTolerance,Add);
}

//=======================================================================
//function : InsertKnots
//purpose  : 
//=======================================================================

00437 void  Law_BSpline::InsertKnots(const TColStd_Array1OfReal& Knots, 
                         const TColStd_Array1OfInteger& Mults,
                         const Standard_Real Epsilon,
                         const Standard_Boolean Add)
{
  // Check and compute new sizes
  Standard_Integer nbpoles,nbknots;
  
  if (!BSplCLib::PrepareInsertKnots(deg,periodic,
                            knots->Array1(),mults->Array1(),
                            Knots,Mults,nbpoles,nbknots,Epsilon,Add))
    Standard_ConstructionError::Raise("Law_BSpline::InsertKnots");
  
  if (nbpoles == poles->Length()) return;
  
  Handle(TColStd_HArray1OfReal) npoles = new TColStd_HArray1OfReal(1,nbpoles);
  Handle(TColStd_HArray1OfReal) nknots = knots;
  Handle(TColStd_HArray1OfInteger) nmults = mults;
  
  if (nbknots != knots->Length()) {
    nknots = new TColStd_HArray1OfReal(1,nbknots);
    nmults = new TColStd_HArray1OfInteger(1,nbknots);
  }
  
  if (rational) {
    Handle(TColStd_HArray1OfReal) nweights = 
      new TColStd_HArray1OfReal(1,nbpoles);
    TColStd_Array1OfReal adimpol(1,2*poles->Upper());
    SetPoles(poles->Array1(),weights->Array1(),adimpol);
    TColStd_Array1OfReal adimnpol(1,2*npoles->Upper());
    BSplCLib::InsertKnots(deg,periodic,2,adimpol,
                    knots->Array1(), mults->Array1(),
                    Knots, Mults,adimnpol,
                    nknots->ChangeArray1(), nmults->ChangeArray1(),
                    Epsilon, Add);
    GetPoles(adimnpol,npoles->ChangeArray1(),nweights->ChangeArray1());
    weights = nweights;
  }
  else {
    BSplCLib::InsertKnots(deg,periodic,1,poles->Array1(), 
                    knots->Array1(), mults->Array1(),
                    Knots, Mults,
                    npoles->ChangeArray1(), 
                    nknots->ChangeArray1(), nmults->ChangeArray1(),
                    Epsilon, Add);
  }
  
  poles = npoles;
  knots = nknots;
  mults = nmults;
  UpdateKnots();
  
}

//=======================================================================
//function : RemoveKnot
//purpose  : 
//=======================================================================

00496 Standard_Boolean  Law_BSpline::RemoveKnot(const Standard_Integer Index,
                                const Standard_Integer M, 
                                const Standard_Real Tolerance)
{
  if (M < 0) return Standard_True;
  
  Standard_Integer I1  = FirstUKnotIndex ();
  Standard_Integer I2  = LastUKnotIndex  ();
  
  if ( !periodic && (Index <= I1 || Index >= I2) ) {
    Standard_OutOfRange::Raise();
  }
  else if ( periodic  && (Index < I1 || Index > I2)) {
    Standard_OutOfRange::Raise();
  }
  
  const TColStd_Array1OfReal   & oldpoles   = poles->Array1();
#ifdef DEB
  const TColStd_Array1OfReal & oldknots   = 
#endif
    knots->Array1();
  Standard_Integer step = mults->Value(Index) - M;
  if (step <= 0) return Standard_True;
  
  Handle(TColStd_HArray1OfReal) npoles =
    new TColStd_HArray1OfReal(1,oldpoles.Length()-step);
  
  Handle(TColStd_HArray1OfReal)    nknots  = knots;
  Handle(TColStd_HArray1OfInteger) nmults  = mults;
  
  if (M == 0) {
    nknots = new TColStd_HArray1OfReal(1,knots->Length()-1);
    nmults = new TColStd_HArray1OfInteger(1,knots->Length()-1);
  }
  
  if (IsRational()) {
    Handle(TColStd_HArray1OfReal) nweights = 
      new TColStd_HArray1OfReal(1,npoles->Length());
    TColStd_Array1OfReal adimpol(1,2*poles->Upper());
    SetPoles(poles->Array1(),weights->Array1(),adimpol);
    TColStd_Array1OfReal adimnpol(1,2*npoles->Upper());
    if (!BSplCLib::RemoveKnot(Index, M, deg, periodic,2,adimpol,
                        knots->Array1(),mults->Array1(),adimnpol,
                        nknots->ChangeArray1(),
                        nmults->ChangeArray1(),Tolerance))
      return Standard_False;
    GetPoles(adimnpol,npoles->ChangeArray1(),nweights->ChangeArray1());
    weights = nweights;
  }
  else {
    if (!BSplCLib::RemoveKnot(Index, M, deg, periodic,1,poles->Array1(), 
                        knots->Array1(),mults->Array1(),
                        npoles->ChangeArray1(), nknots->ChangeArray1(),
                        nmults->ChangeArray1(),Tolerance))
      return Standard_False;
  }
  
  poles = npoles;
  knots = nknots;
  mults = nmults;
  
  UpdateKnots();
  return Standard_True;
}

//----------------------------------------------------------------------
//----------------------------------------------------------------------

# if 0  

--- methodes otees du CDL -> spec trop vagues : on ne sait pas ou rajouter
le noeud

//=======================================================================
//function : InsertPoleAfter
//purpose  : 
//=======================================================================

void Law_BSpline::InsertPoleAfter
(const Standard_Integer Index,
 const Standard_Real& P)
{
  InsertPoleAfter(Index,P,1.);
}



//=======================================================================
//function : InsertPoleAfter
//purpose  : 
//=======================================================================

void Law_BSpline::InsertPoleAfter
(const Standard_Integer Index,
 const Standard_Real& P,
 const Standard_Real Weight)
{
  if (Index < 0 || Index > poles->Length())  Standard_OutOfRange::Raise();
  
  if (Weight <= gp::Resolution())     Standard_ConstructionError::Raise();
  
  
  // find the spans which are modified with the inserting pole
  //   --> evaluate NewKnot & KnotIndex : Value of the new knot to insert.
  Standard_Integer KnotIndex, k, sigma;
  Standard_Real    NewKnot;
  
  if (periodic) {
    sigma = 0;
    k     = 1;
    while ( sigma < Index) {
      sigma += mults->Value(k);
      k++;
    }
    KnotIndex = k - 1;
    NewKnot   = ( knots->Value(KnotIndex) + knots->Value(KnotIndex+1)) / 2.;
  }
  else {
    sigma = 0;
    k     = 1;
    while ( sigma < Index) {
      sigma += mults->Value(k);
      k++;
    }
    Standard_Integer first = k - 1;
    sigma -= Index;
    while ( sigma < (deg+1)) {
      sigma += mults->Value(k);
      k++;
    }
    Standard_Integer last = k - 1;
    
    KnotIndex = first + (( last - first) / 2);
    NewKnot = ( knots->Value(KnotIndex) + knots->Value(KnotIndex+1)) / 2.;
  }
  
  Standard_Integer nbknots = knots->Length();
  Handle(TColStd_HArray1OfReal) nknots = 
    new TColStd_HArray1OfReal(1,nbknots+1);
  TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
  Handle(TColStd_HArray1OfInteger) nmults =
    new TColStd_HArray1OfInteger(1,nbknots+1);
  TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
  
  // insert the knot
  
  Standard_Integer i;
  for ( i = 1; i<= KnotIndex; i++) { 
    newknots(i) = knots->Value(i);
    newmults(i) = mults->Value(i);
  }
  newknots(KnotIndex+1) = NewKnot;
  newmults(KnotIndex+1) = 1;
  for ( i = KnotIndex+1; i <= nbknots; i++) {
    newknots(i+1) = knots->Value(i);
    newmults(i+1) = mults->Value(i);
  }
  
  Standard_Integer nbpoles = poles->Length();
  Handle(TColStd_HArray1OfReal) npoles = 
    new TColStd_HArray1OfReal(1,nbpoles+1);
  TColStd_Array1OfReal& newpoles = npoles->ChangeArray1();
  
  // insert the pole
  
  for (i = 1; i <= Index; i++)
    newpoles(i) = poles->Value(i);
  
  newpoles(Index+1) = P;
  
  for (i = Index+1; i <= nbpoles; i++)
    newpoles(i+1) = poles->Value(i);
  
  // insert the weight 
  
  Handle(TColStd_HArray1OfReal) nweights;
  Standard_Boolean rat = IsRational() || Abs(Weight-1.) > gp::Resolution();
  
  if (rat) {
    nweights = new TColStd_HArray1OfReal(1,nbpoles+1);
    TColStd_Array1OfReal& newweights = nweights->ChangeArray1();
    
    for (i = 1; i <= Index; i++)
      if (IsRational())
      newweights(i) = weights->Value(i);
      else
      newweights(i) = 1.;
    
    newweights(Index+1) = Weight;
    
    for (i = Index+1; i <= nbpoles; i++)
      if (IsRational())
      newweights(i+1) = weights->Value(i);
      else
      newweights(i+1) = 1.;
  }
  
  poles   = npoles;
  weights = nweights;
  knots   = nknots;
  mults   = nmults;
  UpdateKnots();
}


//=======================================================================
//function : InsertPoleBefore
//purpose  : 
//=======================================================================

void Law_BSpline::InsertPoleBefore
(const Standard_Integer Index,
 const Standard_Real& P )
{
  InsertPoleAfter(Index-1,P,1.);
}



//=======================================================================
//function : InsertPoleBefore
//purpose  : 
//=======================================================================

void Law_BSpline::InsertPoleBefore
(const Standard_Integer Index,
 const Standard_Real& P,
 const Standard_Real Weight)
{
  InsertPoleAfter(Index-1,P,Weight);
}

//=======================================================================
//function : RemovePole
//purpose  : 
//=======================================================================

void Law_BSpline::RemovePole
(const Standard_Integer Index)
{
  if (Index < 1 || Index > poles->Length())  Standard_OutOfRange::Raise();
  
  if (poles->Length() <= 2)           Standard_ConstructionError::Raise();
  
  if (knotSet == GeomAbs_NonUniform || knotSet == GeomAbs_PiecewiseBezier) 
    Standard_ConstructionError::Raise();
  
  Standard_Integer i;
  Handle(TColStd_HArray1OfReal) nknots =
    new TColStd_HArray1OfReal(1,knots->Length()-1);
  TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
  
  Handle(TColStd_HArray1OfInteger) nmults =
    new TColStd_HArray1OfInteger(1,mults->Length()-1);
  TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
  
  for (i = 1; i < newknots.Length(); i++) {
    newknots (i) = knots->Value (i);
    newmults (i) = 1;
  }
  newmults(1) = mults->Value(1);
  newknots(newknots.Upper()) = knots->Value (knots->Upper());
  newmults(newmults.Upper()) = mults->Value (mults->Upper());
  
  
  Handle(TColStd_HArray1OfReal) npoles =
    new TColStd_HArray1OfReal(1, poles->Upper()-1);
  TColStd_Array1OfReal& newpoles = npoles->ChangeArray1();
  
  for (i = 1; i < Index; i++)
    newpoles(i) = poles->Value(i);
  for (i = Index; i < newpoles.Length(); i++)
    newpoles(i) = poles->Value(i+1);
  
  Handle(TColStd_HArray1OfReal) nweights;
  if (IsRational()) {
    nweights = new TColStd_HArray1OfReal(1,newpoles.Length());
    TColStd_Array1OfReal& newweights = nweights->ChangeArray1();
    for (i = 1; i < Index; i++)
      newweights(i) = weights->Value(i);
    for (i = Index; i < newweights.Length(); i++)
      newweights(i) = weights->Value(i+1);
  }
  
  poles   = npoles;
  weights = nweights;
  knots   = nknots;
  mults   = nmults;
  UpdateKnots();
}




#endif


//=======================================================================
//function : Reverse
//purpose  : 
//=======================================================================

00798 void Law_BSpline::Reverse ()
{ 
  BSplCLib::Reverse(knots->ChangeArray1());
  BSplCLib::Reverse(mults->ChangeArray1());
  Standard_Integer last;
  if (periodic)
    last = flatknots->Upper() - deg - 1;
  else
    last = poles->Upper();
  BSplCLib::Reverse(poles->ChangeArray1(),last);
  if (rational)
    BSplCLib::Reverse(weights->ChangeArray1(),last);
  UpdateKnots();
}


//=======================================================================
//function : ReversedParameter
//purpose  : 
//=======================================================================

Standard_Real Law_BSpline::ReversedParameter
00820 (const Standard_Real U) const
{
  return (FirstParameter() + LastParameter() - U);
}


//=======================================================================
//function : Segment
//purpose  : 
//=======================================================================

00831 void Law_BSpline::Segment(const Standard_Real U1,
                    const Standard_Real U2)
{
  Standard_DomainError_Raise_if ( U2 < U1,
                         "Law_BSpline::Segment");
  Standard_Real Eps = Epsilon(Max(Abs(U1),Abs(U2)));
  Standard_Real delta = U2 - U1;
  
  Standard_Real NewU1, NewU2;
  Standard_Real U;
  Standard_Integer index;
  
  TColStd_Array1OfReal    Knots(1,2);
  TColStd_Array1OfInteger Mults(1,2);
  
  index = 0;
  BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
                      U1,periodic,knots->Lower(),knots->Upper(),
                      index,NewU1);
  index = 0;
  BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
                      U2,periodic,knots->Lower(),knots->Upper(),
                      index,NewU2);
  Knots( 1) = Min( NewU1, NewU2);
  Knots( 2) = Max( NewU1, NewU2);
  Mults( 1) = Mults( 2) = deg;
  InsertKnots( Knots, Mults, Eps);
  
  if (periodic) { // set the origine at NewU1
    Standard_Integer index = 0;
    BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
                        U1,periodic,knots->Lower(),knots->Upper(),
                        index,U);
    if ( Abs(knots->Value(index+1)-U) < Eps)
      index++;
    SetOrigin(index);
    SetNotPeriodic();
  }
  
  // compute index1 and index2 to set the new knots and mults 
  Standard_Integer index1 = 0, index2 = 0;
  Standard_Integer FromU1 = knots->Lower();
  Standard_Integer ToU2   = knots->Upper();
  BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
                      NewU1,periodic,FromU1,ToU2,index1,U);
  BSplCLib::LocateParameter(deg,knots->Array1(),mults->Array1(),
                      NewU1 + delta,periodic,FromU1,ToU2,index2,U);
  if ( Abs(knots->Value(index2+1)-U) < Eps)
    index2++;
  
  Standard_Integer nbknots = index2 - index1 + 1;
  
  Handle(TColStd_HArray1OfReal) 
    nknots = new TColStd_HArray1OfReal(1,nbknots);
  Handle(TColStd_HArray1OfInteger) 
    nmults = new TColStd_HArray1OfInteger(1,nbknots);
  
  Standard_Integer i , k = 1;
  for ( i = index1; i<= index2; i++) {
    nknots->SetValue(k, knots->Value(i));
    nmults->SetValue(k, mults->Value(i));
    k++;
  }
  nmults->SetValue(      1, deg + 1);
  nmults->SetValue(nbknots, deg + 1);
  
  
  // compute index1 and index2 to set the new poles and weights
  Standard_Integer pindex1 
    = BSplCLib::PoleIndex(deg,index1,periodic,mults->Array1());
  Standard_Integer pindex2 
    = BSplCLib::PoleIndex(deg,index2,periodic,mults->Array1());
  
  pindex1++;
  pindex2 = Min( pindex2+1, poles->Length());
  
  Standard_Integer nbpoles  = pindex2 - pindex1 + 1;
  
  Handle(TColStd_HArray1OfReal) 
    nweights = new TColStd_HArray1OfReal(1,nbpoles);
  Handle(TColStd_HArray1OfReal)
    npoles = new TColStd_HArray1OfReal(1,nbpoles);
  
  k = 1;
  if ( rational) {
    nweights = new TColStd_HArray1OfReal( 1, nbpoles);
    for ( i = pindex1; i <= pindex2; i++) {
      npoles->SetValue(k, poles->Value(i));
      nweights->SetValue(k, weights->Value(i));
      k++;
    }
  }
  else {
    for ( i = pindex1; i <= pindex2; i++) {
      npoles->SetValue(k, poles->Value(i));
      k++;
    }
  }
  
  knots = nknots;
  mults = nmults;
  poles = npoles;
  if ( rational) 
    weights = nweights;
  
  UpdateKnots();
}


//=======================================================================
//function : SetKnot
//purpose  : 
//=======================================================================

void Law_BSpline::SetKnot
00946 (const Standard_Integer Index,
 const Standard_Real K)
{
  if (Index < 1 || Index > knots->Length())     Standard_OutOfRange::Raise();
  Standard_Real DK = Abs(Epsilon (K));
  if (Index == 1) { 
    if (K >= knots->Value(2) - DK) Standard_ConstructionError::Raise();
  }
  else if (Index == knots->Length()) {
    if (K <= knots->Value (knots->Length()-1) + DK)  {
      Standard_ConstructionError::Raise();
    }
  }
  else {
    if (K <= knots->Value(Index-1) + DK ||
      K >= knots->Value(Index+1) - DK ) {
      Standard_ConstructionError::Raise();
    }
  }
  if (K != knots->Value (Index)) {
    knots->SetValue (Index, K);
    UpdateKnots();
  }
}


//=======================================================================
//function : SetKnots
//purpose  : 
//=======================================================================

void Law_BSpline::SetKnots
00978 (const TColStd_Array1OfReal& K)
{
  CheckCurveData(poles->Array1(),K,mults->Array1(),deg,periodic);
  knots->ChangeArray1() = K;
  UpdateKnots();
}


//=======================================================================
//function : SetKnot
//purpose  : 
//=======================================================================

void Law_BSpline::SetKnot
00992 (const Standard_Integer Index,
 const Standard_Real K,
 const Standard_Integer M)
{
  IncreaseMultiplicity (Index, M);
  SetKnot (Index, K);
}


//=======================================================================
//function : SetPeriodic
//purpose  : 
//=======================================================================

01006 void Law_BSpline::SetPeriodic ()
{
  Standard_Integer first = FirstUKnotIndex();
  Standard_Integer last  = LastUKnotIndex();
  
  Handle(TColStd_HArray1OfReal) tk = knots;
  TColStd_Array1OfReal    cknots((knots->Array1())(first),first,last);
  knots = new TColStd_HArray1OfReal(1,cknots.Length());
  knots->ChangeArray1() = cknots;
  
  Handle(TColStd_HArray1OfInteger) tm = mults;
  TColStd_Array1OfInteger cmults((mults->Array1())(first),first,last);
  cmults(first) = cmults(last) = Max( cmults(first), cmults(last));
  mults = new TColStd_HArray1OfInteger(1,cmults.Length());
  mults->ChangeArray1() = cmults;
  
  // compute new number of poles;
  Standard_Integer nbp = BSplCLib::NbPoles(deg,Standard_True,cmults);
  
  Handle(TColStd_HArray1OfReal) tp = poles;
  TColStd_Array1OfReal cpoles((poles->Array1())(1),1,nbp);
  poles = new TColStd_HArray1OfReal(1,nbp);
  poles->ChangeArray1() = cpoles;
  
  if (rational) {
    Handle(TColStd_HArray1OfReal) tw = weights;
    TColStd_Array1OfReal cweights((weights->Array1())(1),1,nbp);
    weights = new TColStd_HArray1OfReal(1,nbp);
    weights->ChangeArray1() = cweights;
  }
  
  periodic = Standard_True;
  
  UpdateKnots();
}


//=======================================================================
//function : SetOrigin
//purpose  : 
//=======================================================================

01048 void Law_BSpline::SetOrigin(const Standard_Integer Index)
{
  Standard_NoSuchObject_Raise_if( !periodic,
                         "Law_BSpline::SetOrigin");
  Standard_Integer i,k;
  Standard_Integer first = FirstUKnotIndex();
  Standard_Integer last  = LastUKnotIndex();
  
  Standard_DomainError_Raise_if( (Index < first) || (Index > last),
                        "Law_BSpline::SetOrigine");
  
  Standard_Integer nbknots = knots->Length();
  Standard_Integer nbpoles = poles->Length();
  
  Handle(TColStd_HArray1OfReal) nknots = 
    new TColStd_HArray1OfReal(1,nbknots);
  TColStd_Array1OfReal& newknots = nknots->ChangeArray1();
  
  Handle(TColStd_HArray1OfInteger) nmults =
    new TColStd_HArray1OfInteger(1,nbknots);
  TColStd_Array1OfInteger& newmults = nmults->ChangeArray1();
  
  // set the knots and mults
  Standard_Real period = knots->Value(last) - knots->Value(first);
  k = 1;
  for ( i = Index; i <= last ; i++) {
    newknots(k) = knots->Value(i);
    newmults(k) = mults->Value(i);
    k++;
  }
  for ( i = first+1; i <= Index; i++) {
    newknots(k) = knots->Value(i) + period;
    newmults(k) = mults->Value(i);
    k++;
  }
  
  Standard_Integer index = 1;
  for (i = first+1; i <= Index; i++) 
    index += mults->Value(i);
  
  // set the poles and weights
  Handle(TColStd_HArray1OfReal) npoles =
    new TColStd_HArray1OfReal(1,nbpoles);
  Handle(TColStd_HArray1OfReal) nweights =
    new TColStd_HArray1OfReal(1,nbpoles);
  TColStd_Array1OfReal   & newpoles   = npoles->ChangeArray1();
  TColStd_Array1OfReal & newweights = nweights->ChangeArray1();
  first = poles->Lower();
  last  = poles->Upper();
  if ( rational) {
    k = 1;
    for ( i = index; i <= last; i++) {
      newpoles(k)   = poles->Value(i);
      newweights(k) = weights->Value(i);
      k++;
    }
    for ( i = first; i < index; i++) {
      newpoles(k)   = poles->Value(i);
      newweights(k) = weights->Value(i);
      k++;
    }
  }
  else {
    k = 1;
    for ( i = index; i <= last; i++) {
      newpoles(k) = poles->Value(i);
      k++;
    }
    for ( i = first; i < index; i++) {
      newpoles(k) = poles->Value(i);
      k++;
    }
  }
  
  poles = npoles;
  knots = nknots;
  mults = nmults;
  if (rational) 
    weights = nweights;
  UpdateKnots();
}



//=======================================================================
//function : SetNotPeriodic
//purpose  : 
//=======================================================================

01137 void Law_BSpline::SetNotPeriodic () 
{ 
  if ( periodic) {
    Standard_Integer NbKnots, NbPoles;
    BSplCLib::PrepareUnperiodize( deg, mults->Array1(),NbKnots,NbPoles);
    
    Handle(TColStd_HArray1OfReal) npoles 
      = new TColStd_HArray1OfReal(1,NbPoles);
    
    Handle(TColStd_HArray1OfReal) nknots 
      = new TColStd_HArray1OfReal(1,NbKnots);
    
    Handle(TColStd_HArray1OfInteger) nmults
      = new TColStd_HArray1OfInteger(1,NbKnots);
    
    Handle(TColStd_HArray1OfReal) nweights;
    
    if (IsRational()) {
      
      nweights = new TColStd_HArray1OfReal(1,NbPoles);
      
      TColStd_Array1OfReal adimpol(1,2*poles->Upper());
      SetPoles(poles->Array1(),weights->Array1(),adimpol);
      TColStd_Array1OfReal adimnpol(1,2*npoles->Upper());
      BSplCLib::Unperiodize
      (deg,1,mults->Array1(),knots->Array1(),adimpol,
       nmults->ChangeArray1(),nknots->ChangeArray1(),
       adimnpol);
      GetPoles(adimnpol,npoles->ChangeArray1(),nweights->ChangeArray1());
    }
    else {
      
      BSplCLib::Unperiodize(deg,1,mults->Array1(),knots->Array1(),
                      poles->Array1(),nmults->ChangeArray1(), 
                      nknots->ChangeArray1(),npoles->ChangeArray1());
      
    }
    poles   = npoles;
    weights = nweights;
    mults   = nmults;
    knots   = nknots;
    periodic = Standard_False;
    
    UpdateKnots();
  }
}


//=======================================================================
//function : SetPole
//purpose  : 
//=======================================================================

void Law_BSpline::SetPole
01191 (const Standard_Integer Index,
 const Standard_Real P)
{
  if (Index < 1 || Index > poles->Length()) Standard_OutOfRange::Raise();
  poles->SetValue (Index, P);
}


//=======================================================================
//function : SetPole
//purpose  : 
//=======================================================================

void Law_BSpline::SetPole
01205 (const Standard_Integer Index,
 const Standard_Real P,
 const Standard_Real W)
{
  SetPole(Index,P);
  SetWeight(Index,W);
}

//=======================================================================
//function : SetWeight
//purpose  : 
//=======================================================================

void Law_BSpline::SetWeight
01219 (const Standard_Integer Index,
 const Standard_Real W)
{
  if (Index < 1 || Index > poles->Length())   Standard_OutOfRange::Raise();
  
  if (W <= gp::Resolution ())     Standard_ConstructionError::Raise();
  
  
  Standard_Boolean rat = IsRational() || (Abs(W - 1.) > gp::Resolution());
  
  if ( rat) {
    if (rat && !IsRational())
      weights = new TColStd_HArray1OfReal(1,poles->Length(),1.);
    
    weights->SetValue (Index, W);
    
    if (IsRational()) {
      rat = Rational(weights->Array1());
      if (!rat) weights.Nullify();
    }
    
    rational = !weights.IsNull();
  }
}


//=======================================================================
//function : UpdateKnots
//purpose  : 
//=======================================================================


01251 void Law_BSpline::UpdateKnots()
{
  
  rational = !weights.IsNull();
  
  Standard_Integer MaxKnotMult = 0;
  KnotAnalysis (deg, 
            periodic,
            knots->Array1(), 
            mults->Array1(), 
            knotSet, MaxKnotMult);
  
  if (knotSet == GeomAbs_Uniform && !periodic)  {
    flatknots = knots;
  }
  else {
    flatknots = new TColStd_HArray1OfReal 
      (1, BSplCLib::KnotSequenceLength(mults->Array1(),deg,periodic));
    
    BSplCLib::KnotSequence (knots->Array1(), 
                      mults->Array1(),
                      deg,periodic,
                      flatknots->ChangeArray1());
  }
  
  if (MaxKnotMult == 0)  smooth = GeomAbs_CN;
  else {
    switch (deg - MaxKnotMult) {
    case 0:   smooth = GeomAbs_C0;   break;
    case 1:   smooth = GeomAbs_C1;   break;
    case 2:   smooth = GeomAbs_C2;   break;
    case 3:   smooth = GeomAbs_C3;   break;
    default:  smooth = GeomAbs_C3;   break;
    }
  }
}


//=======================================================================
//function : Normalizes the parameters if the curve is periodic
//purpose  : that is compute the cache so that it is valid
//=======================================================================

01294 void Law_BSpline::PeriodicNormalization(Standard_Real&  Parameter) const 
{
  Standard_Real Period ;
  
  if (periodic){
    Period = flatknots->Value(flatknots->Upper() - deg) - 
      flatknots->Value (deg + 1) ;
    while (Parameter > flatknots->Value(flatknots->Upper()-deg)){
      Parameter -= Period ;
    }
    while (Parameter < flatknots->Value((deg + 1))){
      Parameter +=  Period ;
    }
  }
}


//=======================================================================
//function : IsCN
//purpose  : 
//=======================================================================

01316 Standard_Boolean Law_BSpline::IsCN ( const Standard_Integer N) const
{
  Standard_RangeError_Raise_if
    (N < 0, "Law_BSpline::IsCN");
#ifndef DEB
  Standard_Boolean Cn = Standard_False;
#else
  Standard_Boolean Cn;
#endif
  switch (smooth) {
  case GeomAbs_CN :  Cn = Standard_True; break;
  case GeomAbs_C0 :  Cn = (N <= 0);      break;
  case GeomAbs_C1 :  Cn = (N <= 1);      break;
  case GeomAbs_C2 :  Cn = (N <= 2);      break;
  case GeomAbs_C3 :
    if (N <= 3) 
      Cn = Standard_True;
    else {
      Standard_Integer Index = mults->Lower() + 1;
      Standard_Integer Upper = mults->Upper() - 1;
      Standard_Integer MaxMultiplicity = mults->Value (Index);
      while (Index <= Upper) {
      if (mults->Value (Index) > MaxMultiplicity) {
        MaxMultiplicity = mults->Value (Index);
      }
      Index++;
      }
      Cn = (N <= deg - MaxMultiplicity);
    }
    break;
#ifndef DEB
  default:
    break;
#endif
  }
  return Cn;
}



//=======================================================================
//function : IsClosed
//purpose  : 
//=======================================================================

01361 Standard_Boolean Law_BSpline::IsClosed () const
{ return (Abs(StartPoint()-EndPoint())) <= gp::Resolution (); }



//=======================================================================
//function : IsPeriodic
//purpose  : 
//=======================================================================

01371 Standard_Boolean Law_BSpline::IsPeriodic () const
{ return periodic; }

//=======================================================================
//function : Continuity
//purpose  : 
//=======================================================================

01379 GeomAbs_Shape Law_BSpline::Continuity () const
{ return smooth; }

//=======================================================================
//function : Degree
//purpose  : 
//=======================================================================

01387 Standard_Integer Law_BSpline::Degree () const
{ return deg; }


//=======================================================================
//function : Value
//purpose  : 
//=======================================================================

Standard_Real Law_BSpline::Value(const Standard_Real U)const 
{
  Standard_Real  P;
  D0(U,P);
  return P;
}


//=======================================================================
//function : D0
//purpose  : 
//=======================================================================

void Law_BSpline::D0 (const Standard_Real U, 
                  Standard_Real& P)  const 
{
  Standard_Real  NewU = U ;
  PeriodicNormalization(NewU) ;
  if (rational) {
    BSplCLib::D0(NewU,0,deg,periodic,POLES, weights->Array1(),FKNOTS,FMULTS,P);
  }
  else {
    BSplCLib::D0(NewU,0,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,P);
  }
}




//=======================================================================
//function : D1
//purpose  : 
//=======================================================================

void Law_BSpline::D1 (const Standard_Real U,
                  Standard_Real& P,
                  Standard_Real& V1) const
{
  Standard_Real  NewU = U ;
  PeriodicNormalization(NewU) ;
  if (rational) {
    BSplCLib::D1(NewU,0,deg,periodic,POLES, weights->Array1(),FKNOTS,FMULTS,
             P,V1) ;
  }
  else {
    BSplCLib::D1(NewU,0,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,
             P,V1) ;
  }
}



//=======================================================================
//function : D2
//purpose  : 
//=======================================================================

void Law_BSpline::D2(const Standard_Real U ,
                 Standard_Real& P ,
                 Standard_Real& V1,
                 Standard_Real& V2 ) const
{
  Standard_Real  NewU = U ;
  PeriodicNormalization(NewU) ;
  if (rational) {
    BSplCLib::D2(NewU,0,deg,periodic,POLES,weights->Array1(),FKNOTS,FMULTS,
             P, V1, V2) ;
  }
  else {
    BSplCLib::D2(NewU,0,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,
             P, V1, V2) ;
  }
}



//=======================================================================
//function : D3
//purpose  : 
//=======================================================================

void Law_BSpline::D3(const Standard_Real U ,
                 Standard_Real& P ,
                 Standard_Real& V1,
                 Standard_Real& V2,
                 Standard_Real& V3 ) const
{
  Standard_Real  NewU = U ;
  PeriodicNormalization(NewU) ;
  if (rational) {
    BSplCLib::D3(NewU,0,deg,periodic,POLES,weights->Array1(),FKNOTS,FMULTS,
             P, V1, V2, V3) ;
  }
  else {
    BSplCLib::D3(NewU,0,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,
             P, V1, V2, V3) ;
  }
}



//=======================================================================
//function : DN
//purpose  : 
//=======================================================================

01502 Standard_Real Law_BSpline::DN(const Standard_Real    U,
                        const Standard_Integer N ) const
{
  Standard_Real V;
  if (rational) {
    BSplCLib::DN(U,N,0,deg,periodic,POLES,weights->Array1(),FKNOTS,FMULTS,V);
  }
  else {
    BSplCLib::DN(U,N,0,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,V);
  }
  return V;
}



//=======================================================================
//function : EndPoint
//purpose  : 
//=======================================================================

01522 Standard_Real Law_BSpline::EndPoint () const
{ 
  if (mults->Value (knots->Upper ()) == deg + 1) 
    return poles->Value (poles->Upper());
  else
    return Value(LastParameter());
}


//=======================================================================
//function : FirstUKnotIndex
//purpose  : 
//=======================================================================

01536 Standard_Integer Law_BSpline::FirstUKnotIndex () const
{ 
  if (periodic) return 1;
  else return BSplCLib::FirstUKnotIndex (deg, mults->Array1()); 
}


//=======================================================================
//function : FirstParameter
//purpose  : 
//=======================================================================

01548 Standard_Real Law_BSpline::FirstParameter () const
{
  return flatknots->Value (deg+1); 
}


//=======================================================================
//function : Knot
//purpose  : 
//=======================================================================

01559 Standard_Real Law_BSpline::Knot (const Standard_Integer Index) const
{
  Standard_OutOfRange_Raise_if
    (Index < 1 || Index > knots->Length(), "Law_BSpline::Knot");
  return knots->Value (Index);
}



//=======================================================================
//function : KnotDistribution
//purpose  : 
//=======================================================================

01573 GeomAbs_BSplKnotDistribution Law_BSpline::KnotDistribution () const
{ 
  return knotSet; 
}


//=======================================================================
//function : Knots
//purpose  : 
//=======================================================================

01584 void Law_BSpline::Knots (TColStd_Array1OfReal& K) const
{
  Standard_DimensionError_Raise_if
    (K.Length() != knots->Length(), "Law_BSpline::Knots");
  K = knots->Array1();
}


//=======================================================================
//function : KnotSequence
//purpose  : 
//=======================================================================

01597 void Law_BSpline::KnotSequence (TColStd_Array1OfReal& K) const
{
  Standard_DimensionError_Raise_if
    (K.Length() != flatknots->Length(), "Law_BSpline::KnotSequence");
  K = flatknots->Array1();
}



//=======================================================================
//function : LastUKnotIndex
//purpose  : 
//=======================================================================

01611 Standard_Integer Law_BSpline::LastUKnotIndex() const
{
  if (periodic) return knots->Length();
  else return BSplCLib::LastUKnotIndex (deg, mults->Array1()); 
}


//=======================================================================
//function : LastParameter
//purpose  : 
//=======================================================================

01623 Standard_Real Law_BSpline::LastParameter () const
{
  return flatknots->Value (flatknots->Upper()-deg); 
}


//=======================================================================
//function : LocalValue
//purpose  : 
//=======================================================================

Standard_Real Law_BSpline::LocalValue
(const Standard_Real    U,
 const Standard_Integer FromK1,
 const Standard_Integer ToK2)   const
{
  Standard_Real P;
  LocalD0(U,FromK1,ToK2,P);
  return P;
}

//=======================================================================
//function : LocalD0
//purpose  : 
//=======================================================================

void  Law_BSpline::LocalD0
(const Standard_Real    U,
 const Standard_Integer FromK1,
 const Standard_Integer ToK2,
 Standard_Real& P)   const
{
  Standard_DomainError_Raise_if (FromK1 == ToK2,
                         "Law_BSpline::LocalValue");
#ifdef DEB  
  const TColStd_Array1OfInteger & cmults = 
#endif
    mults->Array1();
  Standard_Real u = U;
  Standard_Integer index = 0;
  BSplCLib::LocateParameter(deg, FKNOTS, U, periodic,FromK1,ToK2, index,u);
  index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
  if (rational) {
    BSplCLib::D0(u,index,deg,periodic,POLES,weights->Array1(),FKNOTS,FMULTS,P);
  }
  else {
    BSplCLib::D0(u,index,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,P);
  }
}

//=======================================================================
//function : LocalD1
//purpose  : 
//=======================================================================

void Law_BSpline::LocalD1 (const Standard_Real    U,
                     const Standard_Integer FromK1,
                     const Standard_Integer ToK2,
                     Standard_Real&    P, 
                     Standard_Real&    V1)    const
{
  Standard_DomainError_Raise_if (FromK1 == ToK2,
                         "Law_BSpline::LocalD1");
#ifdef DEB
  const TColStd_Array1OfInteger & cmults = 
#endif
    mults->Array1();
  Standard_Real u = U;
  Standard_Integer index = 0;
  BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
  index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
  if (rational) {
    BSplCLib::D1(u,index,deg,periodic,POLES,weights->Array1(),FKNOTS,FMULTS,P,V1);
  }
  else {
    BSplCLib::D1(u,index,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,P,V1);
  }
}


//=======================================================================
//function : LocalD2
//purpose  : 
//=======================================================================

void Law_BSpline::LocalD2
(const Standard_Real    U,
 const Standard_Integer FromK1,
 const Standard_Integer ToK2, 
 Standard_Real&    P,
 Standard_Real&    V1,
 Standard_Real&    V2) const
{
  Standard_DomainError_Raise_if (FromK1 == ToK2,
                         "Law_BSpline::LocalD2");
#ifdef DEB
  const TColStd_Array1OfInteger & cmults = 
#endif
    mults->Array1();
  Standard_Real u = U;
  Standard_Integer index = 0;
  BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
  index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
  if (rational) {
    BSplCLib::D2(u,index,deg,periodic,POLES, weights->Array1(),FKNOTS,FMULTS,P,V1,V2);
  }
  else {
    BSplCLib::D2(u,index,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,P,V1,V2);
  }
}


//=======================================================================
//function : LocalD3
//purpose  : 
//=======================================================================

void Law_BSpline::LocalD3
(const Standard_Real    U,
 const Standard_Integer FromK1,
 const Standard_Integer ToK2, 
 Standard_Real&    P,
 Standard_Real&    V1,
 Standard_Real&    V2,
 Standard_Real&    V3) const
{
  Standard_DomainError_Raise_if (FromK1 == ToK2,
                         "Law_BSpline::LocalD3");
#ifdef DEB
  const TColStd_Array1OfInteger & cmults = 
#endif
    mults->Array1();
  Standard_Real u = U;
  Standard_Integer index = 0;
  BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
  index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
  if (rational) {
    BSplCLib::D3(u,index,deg,periodic,POLES,weights->Array1(),FKNOTS,FMULTS,P,V1,V2,V3);
  }
  else {
    BSplCLib::D3(u,index,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,P,V1,V2,V3);
  }
}



//=======================================================================
//function : LocalDN
//purpose  : 
//=======================================================================

Standard_Real Law_BSpline::LocalDN
(const Standard_Real    U,
 const Standard_Integer FromK1,
 const Standard_Integer ToK2,
 const Standard_Integer N      ) const
{
  Standard_DomainError_Raise_if (FromK1 == ToK2,
                         "Law_BSpline::LocalD3");
#ifdef DEB
  const TColStd_Array1OfInteger & cmults = 
#endif
    mults->Array1();
  Standard_Real u = U;
  Standard_Integer index = 0;
  BSplCLib::LocateParameter(deg, FKNOTS, U, periodic, FromK1,ToK2, index, u);
  index = BSplCLib::FlatIndex(deg,index,mults->Array1(),periodic);
  
  Standard_Real V;
  if (rational) {
    BSplCLib::DN(u,N,index,deg,periodic,POLES,weights->Array1(),FKNOTS,FMULTS,V);
  }
  else {
    BSplCLib::DN(u,N,index,deg,periodic,POLES,BSplCLib::NoWeights(),FKNOTS,FMULTS,V);
  }
  return V;
}



//=======================================================================
//function : Multiplicity
//purpose  : 
//=======================================================================

Standard_Integer Law_BSpline::Multiplicity 
01809 (const Standard_Integer Index) const
{
  Standard_OutOfRange_Raise_if (Index < 1 || Index > mults->Length(),
                        "Law_BSpline::Multiplicity");
  return mults->Value (Index);
}


//=======================================================================
//function : Multiplicities
//purpose  : 
//=======================================================================

01822 void Law_BSpline::Multiplicities (TColStd_Array1OfInteger& M) const
{
  Standard_DimensionError_Raise_if (M.Length() != mults->Length(),
                            "Law_BSpline::Multiplicities");
  M = mults->Array1();
}


//=======================================================================
//function : NbKnots
//purpose  : 
//=======================================================================

01835 Standard_Integer Law_BSpline::NbKnots () const
{ return knots->Length(); }

//=======================================================================
//function : NbPoles
//purpose  : 
//=======================================================================

01843 Standard_Integer Law_BSpline::NbPoles () const
{ return poles->Length(); }


//=======================================================================
//function : Pole
//purpose  : 
//=======================================================================

01852 Standard_Real Law_BSpline::Pole (const Standard_Integer Index) const
{
  Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
                        "Law_BSpline::Pole");
  return poles->Value (Index);      
}


//=======================================================================
//function : Poles
//purpose  : 
//=======================================================================

01865 void Law_BSpline::Poles (TColStd_Array1OfReal& P) const
{
  Standard_DimensionError_Raise_if (P.Length() != poles->Length(),
                            "Law_BSpline::Poles");
  P = poles->Array1();
}


//=======================================================================
//function : StartPoint
//purpose  : 
//=======================================================================

01878 Standard_Real Law_BSpline::StartPoint () const
{
  if (mults->Value (1) == deg + 1)  
    return poles->Value (1);
  else 
    return Value(FirstParameter());
}

//=======================================================================
//function : Weight
//purpose  : 
//=======================================================================

Standard_Real Law_BSpline::Weight
01892 (const Standard_Integer Index) const
{
  Standard_OutOfRange_Raise_if (Index < 1 || Index > poles->Length(),
                        "Law_BSpline::Weight");
  if (IsRational())
    return weights->Value (Index);
  else
    return 1.;
}



//=======================================================================
//function : Weights
//purpose  : 
//=======================================================================

void Law_BSpline::Weights
01910 (TColStd_Array1OfReal& W) const
{
  Standard_DimensionError_Raise_if (W.Length() != poles->Length(),
                            "Law_BSpline::Weights");
  if (IsRational())
    W = weights->Array1();
  else {
    Standard_Integer i;
    for (i = W.Lower(); i <= W.Upper(); i++)
      W(i) = 1.;
  }
}



//=======================================================================
//function : IsRational
//purpose  : 
//=======================================================================

01930 Standard_Boolean Law_BSpline::IsRational () const
{ 
  return !weights.IsNull(); 
} 


//=======================================================================
//function : LocateU
//purpose  : 
//=======================================================================

void Law_BSpline::LocateU
01942 (const Standard_Real    U, 
 const Standard_Real    ParametricTolerance, 
 Standard_Integer&      I1,
 Standard_Integer&      I2,
 const Standard_Boolean WithKnotRepetition) const
{
  Standard_Real NewU = U;
  Handle(TColStd_HArray1OfReal) TheKnots;
  if (WithKnotRepetition)  TheKnots = flatknots;
  else                     TheKnots = knots;
  
  PeriodicNormalization(NewU); //Attention a la periode

  const TColStd_Array1OfReal & CKnots = TheKnots->Array1();
  Standard_Real UFirst = CKnots (1);
  Standard_Real ULast  = CKnots (CKnots.Length());
  if (Abs (U - UFirst) <= Abs(ParametricTolerance)) { I1 = I2 = 1; }
  else if (Abs (U - ULast) <= Abs(ParametricTolerance)) { 
    I1 = I2 = CKnots.Length();
  }
  else if (NewU < UFirst - Abs(ParametricTolerance)) {
    I2 = 1;
    I1 = 0;
  }
  else if (NewU > ULast + Abs(ParametricTolerance)) {
    I1 = CKnots.Length();
    I2 = I1 + 1;
  }
  else {
    I1 = 1;
    BSplCLib::Hunt (CKnots, NewU, I1);
    while ( Abs( CKnots(I1+1) - NewU) <= Abs(ParametricTolerance)) I1++;
    if ( Abs( CKnots(I1) - NewU) <= Abs(ParametricTolerance)) {
      I2 = I1;
    }
    else {
      I2 = I1 + 1;
    }   
  }
}
//=======================================================================
//function : MovePointAndTangent
//purpose  : 
//=======================================================================

void Law_BSpline::
01988   MovePointAndTangent(const Standard_Real    U,
                  const Standard_Real    P,
                  const Standard_Real    Tangent,
                  const Standard_Real    Tolerance,
                  const Standard_Integer StartingCondition,
                  const Standard_Integer EndingCondition,
                  Standard_Integer&      ErrorStatus) 
{
  TColStd_Array1OfReal new_poles(1, poles->Length());
  Standard_Real delta,
  *poles_array,
  *new_poles_array,
  delta_derivative;
  const Standard_Integer dimension = 1 ;
  D1(U, 
     delta,
     delta_derivative) ;
  delta = P - delta  ;
  
  delta_derivative = Tangent - delta_derivative ;
  poles_array = (Standard_Real *)
    &poles->Array1()(1) ;
  new_poles_array = (Standard_Real *) 
    &new_poles(1) ;
  BSplCLib::MovePointAndTangent(U,
                        dimension,
                        delta,
                        delta_derivative,
                        Tolerance,
                        deg,
                        rational,
                        StartingCondition,
                        EndingCondition,
                        poles_array[0],
                        weights->Array1(), 
                        flatknots->Array1(), 
                        new_poles_array[0],
                        ErrorStatus) ;
  if (!ErrorStatus) {
    poles->ChangeArray1() = new_poles;
  }
}
      

//=======================================================================
//function : Resolution
//purpose  : 
//=======================================================================

02037 void Law_BSpline::Resolution(const Standard_Real Tolerance3D,
                       Standard_Real &     UTolerance) const 
{
  void* bid = (void*)(&(poles->Value(1)));
  Standard_Real* bidr = (Standard_Real*)bid;
  if (rational) {
    BSplCLib::Resolution(*bidr,1,poles->Length(),
                   weights->Array1(),FKNOTS,deg,
                   Tolerance3D,
                   UTolerance) ;
  }
  else {

    BSplCLib::Resolution(*bidr,1,poles->Length(),
                   BSplCLib::NoWeights(),FKNOTS,deg,
                   Tolerance3D,
                   UTolerance) ;
  } 
}

Generated by  Doxygen 1.6.0   Back to index