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

Geom_BSplineSurface_1.cxx

// File:    Geom_BSplineSurface_1.cxx
// Created: Tue Mar  9 19:45:52 1993
// Author:  JCV
//          <fid@phylox>
// Copyright:     Matra Datavision 1993

// File Geom_BSplineSurface.cxx jcv - Juillet 1991
//
// xab : 30-Mar-95 introduced cache mechanism for surfaces
// xab : 21-Jun-95 in remove knots sync size of weights and poles
// pmn : 28-Jun-96 Distinction entre la continuite en U et V (bug PRO4625)
// pmn : 07-Jan-97 Centralisation des verif rational (PRO6834)
//       et ajout des InvalideCache() dans les SetPole* (PRO6833)
// pmn : 03-Feb-97 Prise en compte de la periode dans Locate(U/V) (PRO6963)
//                 + bon appel a LocateParameter (PRO6973).
// RBD : 15/10/98 ; Le cache est desormais defini sur [-1,1] (pro15537).
//

#define No_Standard_OutOfRange
#define No_Standard_DimensionError

#include <Geom_BSplineSurface.jxx>

#include <gp.hxx>
#include <BSplSLib.hxx>
#include <BSplCLib.hxx>
#include <Precision.hxx>
#include <TColgp_Array1OfXYZ.hxx>

#include <Geom_BSplineCurve.hxx>

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

#define  POLES    (poles->Array2())
#define  WEIGHTS  (weights->Array2())
#define  UKNOTS   (uknots->Array1())
#define  VKNOTS   (vknots->Array1())
#define  UFKNOTS  (ufknots->Array1())
#define  VFKNOTS  (vfknots->Array1())
#define  FMULTS   (BSplCLib::NoMults())

//=======================================================================
//function : IsCNu
//purpose  : 
//=======================================================================

Standard_Boolean Geom_BSplineSurface::IsCNu
00054   (const Standard_Integer N) const
{
  Standard_RangeError_Raise_if (N < 0, " ");
  switch (Usmooth) {
  case GeomAbs_CN : return Standard_True;
  case GeomAbs_C0 : return N <= 0;
  case GeomAbs_G1 : return N <= 0;
  case GeomAbs_C1 : return N <= 1;
  case GeomAbs_G2 : return N <= 1;
  case GeomAbs_C2 : return N <= 2;
  case GeomAbs_C3 :
    if (N <= 3) { return Standard_True; }
    else {
      Standard_Integer Index = umults->Lower() + 1;
      Standard_Integer Upper = umults->Upper() - 1;
      Standard_Integer MaxMultiplicity = umults->Value (Index);
      while (Index <= Upper) {
      if (umults->Value (Index) > MaxMultiplicity) {
        MaxMultiplicity = umults->Value (Index);
      }
      Index++;
      }
      return N <= udeg - MaxMultiplicity;
    }
  }
  // pour WNT
  return Standard_False;
}

//=======================================================================
//function : IsCNv
//purpose  : 
//=======================================================================

Standard_Boolean Geom_BSplineSurface::IsCNv
00089   (const Standard_Integer N) const
{
  Standard_RangeError_Raise_if (N < 0, " ");
  
  switch (Vsmooth) {
  case GeomAbs_CN : return Standard_True;
  case GeomAbs_C0 : return N <= 0;
  case GeomAbs_G1 : return N <= 0;
  case GeomAbs_C1 : return N <= 1;
  case GeomAbs_G2 : return N <= 1;
  case GeomAbs_C2 : return N <= 2;
  case GeomAbs_C3 :
    if (N <= 3) { return Standard_True; }
    else {
      Standard_Integer Index = vmults->Lower() + 1;
      Standard_Integer Upper = vmults->Upper() - 1;
      Standard_Integer MaxMultiplicity = vmults->Value (Index);
      while (Index <= Upper) {
      if (vmults->Value (Index) > MaxMultiplicity) {
        MaxMultiplicity = vmults->Value (Index);
      }
      Index++;
      }
      return N <= vdeg - MaxMultiplicity;
    }
  }
  // pour WNT
  return Standard_False;
}

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

00124 void Geom_BSplineSurface::D0 (const Standard_Real U, 
                        const Standard_Real V, 
                              gp_Pnt&       P ) const 
{
  Standard_Real  new_u = U,
                 new_v = V ;
  PeriodicNormalization(new_u,
                  new_v) ;
  if (!IsCacheValid(new_u,
                    new_v))
    {
     Geom_BSplineSurface * my_surface = (Geom_BSplineSurface *) this ;
     my_surface->ValidateCache(new_u,
                         new_v) ;
   }
 Standard_Real uparameter_11 = (2*ucacheparameter + ucachespanlenght)/2,
               uspanlenght_11 = ucachespanlenght/2,
               vparameter_11 = (2*vcacheparameter + vcachespanlenght)/2,
               vspanlenght_11 = vcachespanlenght/2 ; 
 if (cacheweights.IsNull()) {
      
   BSplSLib::CacheD0(new_u,
                 new_v,
                 udeg,
                 vdeg,
                 uparameter_11,
                 vparameter_11,
                 uspanlenght_11,
                 vspanlenght_11,
                 cachepoles->Array2(),
                 *((TColStd_Array2OfReal*) NULL),
                 P) ;
 }
 else {
   BSplSLib::CacheD0(new_u,
                 new_v,
                 udeg,
                 vdeg,
                 uparameter_11,
                 vparameter_11,
                 uspanlenght_11,
                 vspanlenght_11,
                 cachepoles->Array2(),
                 cacheweights->Array2(),
                 P) ;
 }
}

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

00177 void Geom_BSplineSurface::D1 (const Standard_Real U, 
                        const Standard_Real V, 
                              gp_Pnt&       P,
                              gp_Vec&       D1U,
                              gp_Vec&       D1V) const
{
  Standard_Real  new_u = U,
                 new_v = V ;
  PeriodicNormalization(new_u,
                  new_v) ;
  if (!IsCacheValid(new_u,
                    new_v))
    {
     Geom_BSplineSurface * my_surface = (Geom_BSplineSurface *) this ;
     my_surface->ValidateCache(new_u,
                         new_v) ;
   }

  Standard_Real uparameter_11 = (2*ucacheparameter + ucachespanlenght)/2,
                uspanlenght_11 = ucachespanlenght/2,
                vparameter_11 = (2*vcacheparameter + vcachespanlenght)/2,
                vspanlenght_11 = vcachespanlenght/2 ;

  if (cacheweights.IsNull()) {
    
    BSplSLib::CacheD1(new_u,
                  new_v,
                  udeg,
                  vdeg,
                  uparameter_11,
                  vparameter_11,
                  uspanlenght_11,
                  vspanlenght_11,
                  cachepoles->Array2(),
                  *((TColStd_Array2OfReal*) NULL),
                  P,
                  D1U,
                  D1V) ;
  }
  else {
    
    BSplSLib::CacheD1(new_u,
                  new_v,
                  udeg,
                  vdeg,
                  uparameter_11,
                  vparameter_11,
                  uspanlenght_11,
                  vspanlenght_11,
                  cachepoles->Array2(),
                  cacheweights->Array2(),
                  P,
                  D1U,
                  D1V) ;
  }
}

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

00239 void Geom_BSplineSurface::D2 (const Standard_Real U, 
                        const Standard_Real V,
                              gp_Pnt&       P,
                              gp_Vec&       D1U,
                              gp_Vec&       D1V,
                              gp_Vec&       D2U,
                              gp_Vec&       D2V,
                              gp_Vec&       D2UV) const
{

    Standard_Real  new_u = U,
                   new_v = V ;
  PeriodicNormalization(new_u,
                  new_v) ;
  if (!IsCacheValid(new_u,
                    new_v))
    {
     Geom_BSplineSurface * my_surface = (Geom_BSplineSurface *) this ;
     my_surface->ValidateCache(new_u,
                         new_v) ;
   }

  Standard_Real uparameter_11 = (2*ucacheparameter + ucachespanlenght)/2,
                uspanlenght_11 = ucachespanlenght/2,
                vparameter_11 = (2*vcacheparameter + vcachespanlenght)/2,
                vspanlenght_11 = vcachespanlenght/2 ;
  if (cacheweights.IsNull()) {
      BSplSLib::CacheD2(new_u,
                  new_v,
                  udeg,
                  vdeg,
                  uparameter_11,
                  vparameter_11,
                  uspanlenght_11,
                  vspanlenght_11,
                  cachepoles->Array2(),
                  *((TColStd_Array2OfReal*) NULL),
                  P,
                  D1U,
                  D1V,
                  D2U,
                  D2UV,
                  D2V); 
    }
    else {
      BSplSLib::CacheD2(new_u,
                  new_v,
                  udeg,
                  vdeg,
                  uparameter_11,
                  vparameter_11,
                  uspanlenght_11,
                  vspanlenght_11,
                  cachepoles->Array2(),
                  cacheweights->Array2(),
                  P,
                  D1U,
                  D1V,
                  D2U,
                  D2UV,
                  D2V); 
    }
  }

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

00308 void Geom_BSplineSurface::D3 (const Standard_Real U, 
                        const Standard_Real V,
                              gp_Pnt&       P,
                              gp_Vec&       D1U,
                              gp_Vec&       D1V, 
                              gp_Vec&       D2U,
                              gp_Vec&       D2V,
                              gp_Vec&       D2UV,
                              gp_Vec&       D3U,
                              gp_Vec&       D3V,
                              gp_Vec&       D3UUV,
                              gp_Vec&       D3UVV) const
{
  BSplSLib::D3(U,V,0,0,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
             udeg,vdeg,urational,vrational,uperiodic,vperiodic,
             P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
  }

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

00331 gp_Vec Geom_BSplineSurface::DN (const Standard_Real    U,
                        const Standard_Real    V,
                        const Standard_Integer Nu,
                        const Standard_Integer Nv ) const
{
  gp_Vec Vn;
  BSplSLib::DN(U,V,Nu,Nv,0,0,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
             udeg,vdeg,urational,vrational,uperiodic,vperiodic,
             Vn);
  return Vn;
}

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

00348 gp_Pnt Geom_BSplineSurface::LocalValue (const Standard_Real    U,
                              const Standard_Real    V, 
                              const Standard_Integer FromUK1,
                              const Standard_Integer ToUK2,
                              const Standard_Integer FromVK1, 
                              const Standard_Integer ToVK2)  const
{
  gp_Pnt P;
  LocalD0(U,V,FromUK1,ToUK2,FromVK1,ToVK2,P);
  return P;
}

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

00365 void Geom_BSplineSurface::LocalD0 (const Standard_Real    U,
                           const Standard_Real    V, 
                           const Standard_Integer FromUK1,
                           const Standard_Integer ToUK2,
                           const Standard_Integer FromVK1, 
                           const Standard_Integer ToVK2,
                                 gp_Pnt&          P     )  const
{
  Standard_DomainError_Raise_if (FromUK1 == ToUK2 || FromVK1 == ToVK2, 
                         "Geom_BSplineSurface::LocalD0");

#ifdef DEB
  const TColStd_Array1OfInteger & sumults = umults->Array1();
#else
  umults->Array1();
#endif
#ifdef DEB
  const TColStd_Array1OfInteger & svmults = vmults->Array1();
#else
  vmults->Array1();
#endif

  Standard_Real u = U, v = V;
  Standard_Integer uindex = 0, vindex = 0;

  BSplCLib::LocateParameter(udeg, UFKNOTS, U, uperiodic,FromUK1,ToUK2,
                      uindex,u);
  uindex = BSplCLib::FlatIndex(udeg,uindex,umults->Array1(),uperiodic);

  BSplCLib::LocateParameter(vdeg, VFKNOTS, V, vperiodic,FromVK1,ToVK2,
                      vindex,v);
  vindex = BSplCLib::FlatIndex(vdeg,vindex,vmults->Array1(),vperiodic);

//  BSplSLib::D0(U,V,uindex,vindex,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
  BSplSLib::D0(u,v,uindex,vindex,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
             udeg,vdeg,urational,vrational,uperiodic,vperiodic,
             P);
}

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

00409 void Geom_BSplineSurface::LocalD1 (const Standard_Real    U, 
                           const Standard_Real    V,
                           const Standard_Integer FromUK1, 
                           const Standard_Integer ToUK2,
                           const Standard_Integer FromVK1, 
                           const Standard_Integer ToVK2,
                                 gp_Pnt&          P,
                                 gp_Vec&          D1U, 
                                 gp_Vec&          D1V)     const
{
  Standard_DomainError_Raise_if (FromUK1 == ToUK2 || FromVK1 == ToVK2, 
                         "Geom_BSplineSurface::LocalD1");

#ifdef DEB
  const TColStd_Array1OfInteger & sumults = umults->Array1();
#else
  umults->Array1();
#endif
#ifdef DEB
  const TColStd_Array1OfInteger & svmults = vmults->Array1();
#else
  vmults->Array1();
#endif

  Standard_Real u = U, v = V;
  Standard_Integer uindex = 0, vindex = 0;

  BSplCLib::LocateParameter(udeg, UFKNOTS, U, uperiodic,FromUK1,ToUK2,
                      uindex,u);
  uindex = BSplCLib::FlatIndex(udeg,uindex,umults->Array1(),uperiodic);

  BSplCLib::LocateParameter(vdeg, VFKNOTS, V, vperiodic,FromVK1,ToVK2,
                      vindex,v);
  vindex = BSplCLib::FlatIndex(vdeg,vindex,vmults->Array1(),vperiodic);

//  BSplSLib::D1(U,V,uindex,vindex,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
  BSplSLib::D1(u,v,uindex,vindex,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
             udeg,vdeg,urational,vrational,uperiodic,vperiodic,
             P,D1U,D1V);
}

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

00455 void Geom_BSplineSurface::LocalD2 (const Standard_Real    U,
                           const Standard_Real    V,
                           const Standard_Integer FromUK1,
                           const Standard_Integer ToUK2,
                           const Standard_Integer FromVK1, 
                           const Standard_Integer ToVK2,
                                 gp_Pnt&          P,
                                 gp_Vec&          D1U,
                                 gp_Vec&          D1V,
                                 gp_Vec&          D2U,
                                 gp_Vec&          D2V,
                                 gp_Vec&          D2UV) const
{
  Standard_DomainError_Raise_if (FromUK1 == ToUK2 || FromVK1 == ToVK2, 
                         "Geom_BSplineSurface::LocalD2");

#ifdef DEB
  const TColStd_Array1OfInteger & sumults = umults->Array1();
#else
  umults->Array1();
#endif
#ifdef DEB
  const TColStd_Array1OfInteger & svmults = vmults->Array1();
#else
  vmults->Array1();
#endif

  Standard_Real u = U, v = V;
  Standard_Integer uindex = 0, vindex = 0;

  BSplCLib::LocateParameter(udeg, UFKNOTS, U, uperiodic,FromUK1,ToUK2,
                      uindex,u);
  uindex = BSplCLib::FlatIndex(udeg,uindex,umults->Array1(),uperiodic);

  BSplCLib::LocateParameter(vdeg, VFKNOTS, V, vperiodic,FromVK1,ToVK2,
                      vindex,v);
  vindex = BSplCLib::FlatIndex(vdeg,vindex,vmults->Array1(),vperiodic);

//  BSplSLib::D2(U,V,uindex,vindex,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
  BSplSLib::D2(u,v,uindex,vindex,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
             udeg,vdeg,urational,vrational,uperiodic,vperiodic,
             P,D1U,D1V,D2U,D2V,D2UV);
}

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

00504 void Geom_BSplineSurface::LocalD3 (const Standard_Real    U, 
                           const Standard_Real    V,
                           const Standard_Integer FromUK1, 
                           const Standard_Integer ToUK2,
                           const Standard_Integer FromVK1, 
                           const Standard_Integer ToVK2,
                                 gp_Pnt&          P,
                                 gp_Vec&          D1U,
                                 gp_Vec&          D1V, 
                                 gp_Vec&          D2U, 
                                 gp_Vec&          D2V, 
                                 gp_Vec&          D2UV, 
                                 gp_Vec&          D3U,
                                 gp_Vec&          D3V,
                                 gp_Vec&          D3UUV,
                                 gp_Vec&          D3UVV) const
{
  Standard_DomainError_Raise_if (FromUK1 == ToUK2 || FromVK1 == ToVK2, 
                         "Geom_BSplineSurface::LocalD3");

#ifdef DEB
  const TColStd_Array1OfInteger & sumults = umults->Array1();
#else
  umults->Array1();
#endif
#ifdef DEB
  const TColStd_Array1OfInteger & svmults = vmults->Array1();
#else
  vmults->Array1();
#endif

  Standard_Real u = U, v = V;
  Standard_Integer uindex = 0, vindex = 0;

  BSplCLib::LocateParameter(udeg, UFKNOTS, U, uperiodic,FromUK1,ToUK2,
                      uindex,u);
  uindex = BSplCLib::FlatIndex(udeg,uindex,umults->Array1(),uperiodic);

  BSplCLib::LocateParameter(vdeg, VFKNOTS, V, vperiodic,FromVK1,ToVK2,
                      vindex,v);
  vindex = BSplCLib::FlatIndex(vdeg,vindex,vmults->Array1(),vperiodic);

//  BSplSLib::D3(U,V,uindex,vindex,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
  BSplSLib::D3(u,v,uindex,vindex,POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
             udeg,vdeg,urational,vrational,uperiodic,vperiodic,
             P,D1U,D1V,D2U,D2V,D2UV,D3U,D3V,D3UUV,D3UVV);
}

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

00557 gp_Vec Geom_BSplineSurface::LocalDN  (const Standard_Real    U, 
                              const Standard_Real    V,
                              const Standard_Integer FromUK1,
                              const Standard_Integer ToUK2,
                              const Standard_Integer FromVK1,
                              const Standard_Integer ToVK2,
                              const Standard_Integer Nu,
                              const Standard_Integer Nv) const
{
  Standard_DomainError_Raise_if (FromUK1 == ToUK2 || FromVK1 == ToVK2, 
                         "Geom_BSplineSurface::LocalDN");

#ifdef DEB
  const TColStd_Array1OfInteger & sumults = umults->Array1();
#else
  umults->Array1();
#endif
#ifdef DEB
  const TColStd_Array1OfInteger & svmults = vmults->Array1();
#else
  vmults->Array1();
#endif

  Standard_Real u = U, v = V;
  Standard_Integer uindex = 0, vindex = 0;

  BSplCLib::LocateParameter(udeg, UFKNOTS, U, uperiodic,FromUK1,ToUK2,
                      uindex,u);
  uindex = BSplCLib::FlatIndex(udeg,uindex,umults->Array1(),uperiodic);

  BSplCLib::LocateParameter(vdeg, VFKNOTS, V, vperiodic,FromVK1,ToVK2,
                      vindex,v);
  vindex = BSplCLib::FlatIndex(vdeg,vindex,vmults->Array1(),vperiodic);

  gp_Vec Vn;
//  BSplSLib::DN(U,V,Nu,Nv,uindex,vindex,
  BSplSLib::DN(u,v,Nu,Nv,uindex,vindex,
             POLES,WEIGHTS,UFKNOTS,VFKNOTS,FMULTS,FMULTS,
             udeg,vdeg,urational,vrational,uperiodic,vperiodic,
             Vn);
  return Vn;
}

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

00605 gp_Pnt Geom_BSplineSurface::Pole (const Standard_Integer UIndex,
                          const Standard_Integer VIndex) const
{
  Standard_OutOfRange_Raise_if
    (UIndex < 1 || UIndex > poles->ColLength() ||
     VIndex < 1 || VIndex > poles->RowLength(), " ");
  return poles->Value (UIndex, VIndex);
}

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

00619 void Geom_BSplineSurface::Poles (TColgp_Array2OfPnt& P) const
{
  Standard_DimensionError_Raise_if
    (P.ColLength() != poles->ColLength() ||
     P.RowLength() != poles->RowLength(), " ");
  P = poles->Array2();
}

//=======================================================================
//function : UIso
//purpose  : 
//=======================================================================

Handle(Geom_Curve) Geom_BSplineSurface::UIso (const Standard_Real U) const
{
  TColgp_Array1OfPnt   cpoles(1,poles->RowLength());
  TColStd_Array1OfReal cweights(1,poles->RowLength());

  Handle(Geom_BSplineCurve) C;

  if ( urational || vrational) {
    BSplSLib::Iso(U,Standard_True,POLES,WEIGHTS,UFKNOTS,FMULTS,udeg,uperiodic,
              cpoles,cweights);
    C = new Geom_BSplineCurve(cpoles,cweights,
                        vknots->Array1(),
                        vmults->Array1(),
                        vdeg,vperiodic);
  }
  else {
    BSplSLib::Iso(U,Standard_True,POLES,
              *((TColStd_Array2OfReal*) NULL),
              UFKNOTS,FMULTS,udeg,uperiodic,
              cpoles,cweights);
    C = new Geom_BSplineCurve(cpoles,
                        vknots->Array1(),
                        vmults->Array1(),
                        vdeg,vperiodic);
  }

  return C;
}

//=======================================================================
//function : UIso
//purpose  : If CheckRational=False, no try to make it non-rational
//=======================================================================

Handle(Geom_Curve) Geom_BSplineSurface::UIso (const Standard_Real U,
                                    const Standard_Boolean CheckRational) const
{
  TColgp_Array1OfPnt   cpoles(1,poles->RowLength());
  TColStd_Array1OfReal cweights(1,poles->RowLength());

  Handle(Geom_BSplineCurve) C;

  if ( urational || vrational) {
    BSplSLib::Iso(U,Standard_True,POLES,WEIGHTS,UFKNOTS,FMULTS,udeg,uperiodic,
              cpoles,cweights);
    C = new Geom_BSplineCurve(cpoles,cweights,
                        vknots->Array1(),
                        vmults->Array1(),
                        vdeg,vperiodic,
                        CheckRational);
  }
  else {
    BSplSLib::Iso(U,Standard_True,POLES,
              *((TColStd_Array2OfReal*) NULL),
              UFKNOTS,FMULTS,udeg,uperiodic,
              cpoles,cweights);
    C = new Geom_BSplineCurve(cpoles,
                        vknots->Array1(),
                        vmults->Array1(),
                        vdeg,vperiodic);
  }

  return C;
}

//=======================================================================
//function : UKnot
//purpose  : 
//=======================================================================

00702 Standard_Real Geom_BSplineSurface::UKnot(const Standard_Integer UIndex) const
{
  Standard_OutOfRange_Raise_if (UIndex < 1 || UIndex > uknots->Length(), " ");
  return uknots->Value (UIndex);
}

//=======================================================================
//function : VKnot
//purpose  : 
//=======================================================================

00713 Standard_Real Geom_BSplineSurface::VKnot(const Standard_Integer VIndex) const
{
  Standard_OutOfRange_Raise_if (VIndex < 1 || VIndex > vknots->Length(), " ");
  return vknots->Value (VIndex);
}

//=======================================================================
//function : UKnots
//purpose  : 
//=======================================================================

00724 void Geom_BSplineSurface::UKnots (TColStd_Array1OfReal& Ku) const
{
  Standard_DimensionError_Raise_if (Ku.Length() != uknots->Length(), " ");
  Ku = uknots->Array1();
}

//=======================================================================
//function : VKnots
//purpose  : 
//=======================================================================

00735 void Geom_BSplineSurface::VKnots (TColStd_Array1OfReal& Kv) const
{
  Standard_DimensionError_Raise_if (Kv.Length() != vknots->Length(), " ");
  Kv = vknots->Array1();
}

//=======================================================================
//function : UKnotSequence
//purpose  : 
//=======================================================================

00746 void Geom_BSplineSurface::UKnotSequence (TColStd_Array1OfReal& Ku) const
{
  Standard_DimensionError_Raise_if (Ku.Length() != ufknots->Length(), " ");
  Ku = ufknots->Array1();
}

//=======================================================================
//function : VKnotSequence
//purpose  : 
//=======================================================================

00757 void Geom_BSplineSurface::VKnotSequence (TColStd_Array1OfReal& Kv) const
{
  Standard_DimensionError_Raise_if (Kv.Length() != vfknots->Length(), " ");
  Kv = vfknots->Array1();
}

//=======================================================================
//function : UMultiplicity
//purpose  : 
//=======================================================================

Standard_Integer Geom_BSplineSurface::UMultiplicity 
00769   (const Standard_Integer UIndex) const
{
  Standard_OutOfRange_Raise_if (UIndex < 1 || UIndex > umults->Length()," ");
  return umults->Value (UIndex);
}

//=======================================================================
//function : UMultiplicities
//purpose  : 
//=======================================================================

00780 void Geom_BSplineSurface::UMultiplicities (TColStd_Array1OfInteger& Mu) const
{
  Standard_DimensionError_Raise_if (Mu.Length() != umults->Length(), " ");
  Mu = umults->Array1();
}

//=======================================================================
//function : VIso
//purpose  : 
//=======================================================================

Handle(Geom_Curve) Geom_BSplineSurface::VIso (const Standard_Real V) const
{
  TColgp_Array1OfPnt   cpoles(1,poles->ColLength());
  TColStd_Array1OfReal cweights(1,poles->ColLength());

  Handle(Geom_BSplineCurve) C;

  if ( urational || vrational) {
    BSplSLib::Iso(V,Standard_False,POLES,
              WEIGHTS,
              VFKNOTS,FMULTS,vdeg,vperiodic,
              cpoles,cweights);
    C = new Geom_BSplineCurve(cpoles,cweights,
                        uknots->Array1(),
                        umults->Array1(),
                        udeg,uperiodic);
  }
  else {
    BSplSLib::Iso(V,Standard_False,POLES,
              *((TColStd_Array2OfReal*) NULL),
              VFKNOTS,FMULTS,vdeg,vperiodic,
              cpoles,cweights);
    C = new Geom_BSplineCurve(cpoles,
                        uknots->Array1(),
                        umults->Array1(),
                        udeg,uperiodic);
  }

  return C;
}

//=======================================================================
//function : VIso
//purpose  : If CheckRational=False, no try to make it non-rational
//=======================================================================

Handle(Geom_Curve) Geom_BSplineSurface::VIso (const Standard_Real V,
                                    const Standard_Boolean CheckRational) const
{
  TColgp_Array1OfPnt   cpoles(1,poles->ColLength());
  TColStd_Array1OfReal cweights(1,poles->ColLength());

  Handle(Geom_BSplineCurve) C;

  if ( urational || vrational) {
    BSplSLib::Iso(V,Standard_False,POLES,
              WEIGHTS,
              VFKNOTS,FMULTS,vdeg,vperiodic,
              cpoles,cweights);
    C = new Geom_BSplineCurve(cpoles,cweights,
                        uknots->Array1(),
                        umults->Array1(),
                        udeg,uperiodic,
                        CheckRational);
  }
  else {
    BSplSLib::Iso(V,Standard_False,POLES,
              *((TColStd_Array2OfReal*) NULL),
              VFKNOTS,FMULTS,vdeg,vperiodic,
              cpoles,cweights);
    C = new Geom_BSplineCurve(cpoles,
                        uknots->Array1(),
                        umults->Array1(),
                        udeg,uperiodic);
  }

  return C;
}

//=======================================================================
//function : VMultiplicity
//purpose  : 
//=======================================================================

Standard_Integer Geom_BSplineSurface::VMultiplicity 
00866   (const Standard_Integer VIndex) const
{
  Standard_OutOfRange_Raise_if (VIndex < 1 || VIndex > vmults->Length()," ");
  return vmults->Value (VIndex);
}

//=======================================================================
//function : VMultiplicities
//purpose  : 
//=======================================================================

00877 void Geom_BSplineSurface::VMultiplicities (TColStd_Array1OfInteger& Mv) const
{
  Standard_DimensionError_Raise_if (Mv.Length() != vmults->Length(), " ");
  Mv = vmults->Array1();
}

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

Standard_Real Geom_BSplineSurface::Weight 
00889   (const Standard_Integer UIndex,
   const Standard_Integer VIndex ) const
{
  Standard_OutOfRange_Raise_if
    (UIndex < 1 || UIndex > weights->ColLength() ||
     VIndex < 1 || VIndex > weights->RowLength(), " ");
  return weights->Value (UIndex, VIndex);
}

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

00903 void Geom_BSplineSurface::Weights (TColStd_Array2OfReal& W) const
{
  Standard_DimensionError_Raise_if
    (W.ColLength() != weights->ColLength() ||
     W.RowLength() != weights->RowLength(), " ");
  W = weights->Array2();
}

//=======================================================================
//function : Transform
//purpose  : 
//=======================================================================

00916 void Geom_BSplineSurface::Transform (const gp_Trsf& T)
{
  TColgp_Array2OfPnt & VPoles = poles->ChangeArray2();
  for (Standard_Integer j = VPoles.LowerCol(); j <= VPoles.UpperCol(); j++) {
    for (Standard_Integer i = VPoles.LowerRow(); i <= VPoles.UpperRow(); i++) {
      VPoles (i, j).Transform (T);
    }
  }

  InvalidateCache();
}

//=======================================================================
//function : SetUPeriodic
//purpose  : 
//=======================================================================

00933 void Geom_BSplineSurface::SetUPeriodic ()
{
  Standard_Integer i,j;

  Standard_Integer first = FirstUKnotIndex();
  Standard_Integer last  = LastUKnotIndex();
  
  Handle(TColStd_HArray1OfReal) tk = uknots;
  TColStd_Array1OfReal cknots((uknots->Array1())(first),first,last);
  uknots = new TColStd_HArray1OfReal(1,cknots.Length());
  uknots->ChangeArray1() = cknots;

  Handle(TColStd_HArray1OfInteger) tm = umults;
  TColStd_Array1OfInteger cmults((umults->Array1())(first),first,last);
//  Modified by Sergey KHROMOV - Mon Feb 10 10:59:00 2003 Begin
//   cmults(first) = cmults(last) = Max( cmults(first), cmults(last));
  cmults(first) = cmults(last) = Min(udeg, Max( cmults(first), cmults(last)));
//  Modified by Sergey KHROMOV - Mon Feb 10 10:59:00 2003 End
  umults = new TColStd_HArray1OfInteger(1,cmults.Length());
  umults->ChangeArray1() = cmults;

  // compute new number of poles;
  Standard_Integer nbp = BSplCLib::NbPoles(udeg,Standard_True,cmults);
  
  TColgp_Array2OfPnt cpoles(1,nbp,poles->LowerCol(),poles->UpperCol());
  for (i = 1; i <= nbp; i++) {
    for (j = poles->LowerCol(); j <= poles->UpperCol(); j++) {
      cpoles(i,j) = poles->Value(i,j);
    }
  }
  poles = 
    new TColgp_HArray2OfPnt(1,nbp,cpoles.LowerCol(),cpoles.UpperCol());
  poles->ChangeArray2() = cpoles;

  TColStd_Array2OfReal 
    cweights(1,nbp,weights->LowerCol(),weights->UpperCol());
  if (urational || vrational) {
    for (i = 1; i <= nbp; i++) {
      for (j = weights->LowerCol(); j <= weights->UpperCol(); j++) {
      cweights(i,j) = weights->Value(i,j);
      }
    }
  }
  else { 
    for (i = 1; i <= nbp; i++) {
      for (j = weights->LowerCol(); j <= weights->UpperCol(); j++) {
      cweights(i,j) = 1;
      }
    }
  }
  weights = new 
    TColStd_HArray2OfReal(1,nbp,cweights.LowerCol(),cweights.UpperCol());
  weights->ChangeArray2() = cweights;
  

  uperiodic = Standard_True;

  maxderivinvok = 0;
  UpdateUKnots();
}

//=======================================================================
//function : SetVPeriodic
//purpose  : 
//=======================================================================

00999 void Geom_BSplineSurface::SetVPeriodic ()
{
  Standard_Integer i,j;

  Standard_Integer first = FirstVKnotIndex();
  Standard_Integer last  = LastVKnotIndex();
  
  Handle(TColStd_HArray1OfReal) tk = vknots;
  TColStd_Array1OfReal cknots((vknots->Array1())(first),first,last);
  vknots = new TColStd_HArray1OfReal(1,cknots.Length());
  vknots->ChangeArray1() = cknots;


  Handle(TColStd_HArray1OfInteger) tm = vmults;
  TColStd_Array1OfInteger cmults((vmults->Array1())(first),first,last);
//  Modified by Sergey KHROMOV - Mon Feb 10 11:00:33 2003 Begin
//   cmults(first) = cmults(last) = Max( cmults(first), cmults(last));
  cmults(first) = cmults(last) = Min(vdeg, Max( cmults(first), cmults(last)));
//  Modified by Sergey KHROMOV - Mon Feb 10 11:00:34 2003 End
  vmults = new TColStd_HArray1OfInteger(1,cmults.Length());
  vmults->ChangeArray1() = cmults;

  // compute new number of poles;
  Standard_Integer nbp = BSplCLib::NbPoles(vdeg,Standard_True,cmults);
  
  TColgp_Array2OfPnt cpoles(poles->LowerRow(),poles->UpperRow(),1,nbp);
  for (i = poles->LowerRow(); i <= poles->UpperRow(); i++) {
    for (j = 1; j <= nbp; j++) {
      cpoles(i,j) = poles->Value(i,j);
    }
  }
  poles =
    new TColgp_HArray2OfPnt(cpoles.LowerRow(),cpoles.UpperRow(),1,nbp);
  poles->ChangeArray2() = cpoles;

  if (urational || vrational) {
    TColStd_Array2OfReal 
      cweights(weights->LowerRow(),weights->UpperRow(),1,nbp);
    for (i = weights->LowerRow(); i <= weights->UpperRow(); i++) {
      for (j = 1; j <= nbp; j++) {
      cweights(i,j) = weights->Value(i,j);
      }
    }
    weights = new 
      TColStd_HArray2OfReal(cweights.LowerRow(),cweights.UpperRow(),1,nbp);
    weights->ChangeArray2() = cweights;
  }

  vperiodic = Standard_True;

  maxderivinvok = 0;
  UpdateVKnots();
}

//=======================================================================
//function : SetUOrigin
//purpose  : 
//=======================================================================

01058 void Geom_BSplineSurface::SetUOrigin(const Standard_Integer Index)
{
  Standard_NoSuchObject_Raise_if( !uperiodic,
                         "Geom_BSplineSurface::SetUOrigin");

  Standard_Integer i,j,k;
  Standard_Integer first = FirstUKnotIndex();
  Standard_Integer last  = LastUKnotIndex();

  Standard_DomainError_Raise_if( (Index < first) || (Index > last),
                        "Geom_BSplineCurve::SetUOrigine");

  Standard_Integer nbknots = uknots->Length();
  Standard_Integer nbpoles = poles->ColLength();

  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 = uknots->Value(last) - uknots->Value(first);
  k = 1;
  for ( i = Index; i <= last ; i++) {
    newknots(k) = uknots->Value(i);
    newmults(k) = umults->Value(i);
    k++;
  }
  for ( i = first+1; i <= Index; i++) {
    newknots(k) = uknots->Value(i) + period;
    newmults(k) = umults->Value(i);
    k++;
  }

  Standard_Integer index = 1;
  for (i = first+1; i <= Index; i++) 
    index += umults->Value(i);

  // set the poles and weights
  Standard_Integer nbvp = poles->RowLength();
  Handle(TColgp_HArray2OfPnt) npoles =
    new TColgp_HArray2OfPnt(1,nbpoles,1,nbvp);
  Handle(TColStd_HArray2OfReal) nweights =
    new TColStd_HArray2OfReal(1,nbpoles,1,nbvp);
  TColgp_Array2OfPnt   & newpoles   = npoles->ChangeArray2();
  TColStd_Array2OfReal & newweights = nweights->ChangeArray2();
  first = poles->LowerRow();
  last  = poles->UpperRow();
  if ( urational || vrational) {
    k = 1;
    for ( i = index; i <= last; i++) {
      for ( j = 1; j <= nbvp; j++) {
      newpoles(k,j)   = poles->Value(i,j);
      newweights(k,j) = weights->Value(i,j);
      }
      k++;
    }
    for ( i = first; i < index; i++) {
      for ( j = 1; j <= nbvp; j++) {
      newpoles(k,j)   = poles->Value(i,j);
      newweights(k,j) = weights->Value(i,j);
      }
      k++;
    }
  }
  else {
    k = 1;
    for ( i = index; i <= last; i++) {
      for ( j = 1; j <= nbvp; j++) {
      newpoles(k,j) = poles->Value(i,j);
      }
      k++;
    }
    for ( i = first; i < index; i++) {
      for ( j = 1; j <= nbvp; j++) {
      newpoles(k,j) = poles->Value(i,j);
      }
      k++;
    }
  }

  poles  = npoles;
  uknots = nknots;
  umults = nmults;
  if (urational || vrational) 
    weights = nweights;
  UpdateUKnots();
  
}

//=======================================================================
//function : SetVOrigin
//purpose  : 
//=======================================================================

01156 void Geom_BSplineSurface::SetVOrigin(const Standard_Integer Index)
{
  Standard_NoSuchObject_Raise_if( !vperiodic,
                         "Geom_BSplineSurface::SetVOrigin");

  Standard_Integer i,j,k;
  Standard_Integer first = FirstVKnotIndex();
  Standard_Integer last  = LastVKnotIndex();

  Standard_DomainError_Raise_if( (Index < first) || (Index > last),
                        "Geom_BSplineCurve::SetVOrigine");

  Standard_Integer nbknots = vknots->Length();
  Standard_Integer nbpoles = poles->RowLength();

  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 = vknots->Value(last) - vknots->Value(first);
  k = 1;
  for ( i = Index; i <= last ; i++) {
    newknots(k) = vknots->Value(i);
    newmults(k) = vmults->Value(i);
    k++;
  }
  for ( i = first+1; i <= Index; i++) {
    newknots(k) = vknots->Value(i) + period;
    newmults(k) = vmults->Value(i);
    k++;
  }

  Standard_Integer index = 1;
  for (i = first+1; i <= Index; i++) 
    index += vmults->Value(i);

  // set the poles and weights
  Standard_Integer nbup = poles->ColLength();
  Handle(TColgp_HArray2OfPnt) npoles =
    new TColgp_HArray2OfPnt(1,nbup,1,nbpoles);
  Handle(TColStd_HArray2OfReal) nweights =
    new TColStd_HArray2OfReal(1,nbup,1,nbpoles);
  TColgp_Array2OfPnt   & newpoles   = npoles->ChangeArray2();
  TColStd_Array2OfReal & newweights = nweights->ChangeArray2();
  first = poles->LowerCol();
  last  = poles->UpperCol();
  if ( urational || vrational) {
    k = 1;
    for ( j = index; j <= last; j++) {
      for ( i = 1; i <= nbup; i++) {
      newpoles(i,k)   = poles->Value(i,j);
      newweights(i,k) = weights->Value(i,j);
      }
      k++;
    }
    for ( j = first; j < index; j++) {
      for ( i = 1; i <= nbup; i++) {
      newpoles(i,k)   = poles->Value(i,j);
      newweights(i,k) = weights->Value(i,j);
      }
      k++;
    }
  }
  else {
    k = 1;
    for ( j = index; j <= last; j++) {
      for ( i = 1; i <= nbup; i++) {
      newpoles(i,k)   = poles->Value(i,j);
      }
      k++;
    }
    for ( j = first; j < index; j++) {
      for ( i = 1; i <= nbup; i++) {
      newpoles(i,k)   = poles->Value(i,j);
      }
      k++;
    }
  }

  poles  = npoles;
  vknots = nknots;
  vmults = nmults;
  if (urational || vrational) 
    weights = nweights;
  UpdateVKnots();
  
}

//=======================================================================
//function : SetUNotPeriodic
//purpose  : 
//=======================================================================

void Geom_BSplineSurface::SetUNotPeriodic () 
{ 
  if ( uperiodic) {
    Standard_Integer NbKnots, NbPoles;
    BSplCLib::PrepareUnperiodize( udeg, umults->Array1(), NbKnots, NbPoles);

    Handle(TColgp_HArray2OfPnt) npoles = 
      new TColgp_HArray2OfPnt(1,NbPoles, 1, poles->RowLength());
    
    Handle(TColStd_HArray1OfReal) nknots 
      = new TColStd_HArray1OfReal(1,NbKnots);

    Handle(TColStd_HArray1OfInteger) nmults
      = new TColStd_HArray1OfInteger(1,NbKnots);

    Handle(TColStd_HArray2OfReal) nweights = new TColStd_HArray2OfReal(1,NbPoles, 1, poles->RowLength(), 0);

    if ( urational || vrational) {

      BSplSLib::Unperiodize(Standard_True         , udeg, 
                      umults->Array1()      , uknots->Array1(),
                      poles->Array2()       , weights->Array2(),
                      nmults->ChangeArray1(), nknots->ChangeArray1(),
                      npoles->ChangeArray2(),
                      nweights->ChangeArray2());
    }
    else {

      BSplSLib::Unperiodize(Standard_True         , udeg, 
                      umults->Array1()      , uknots->Array1(),
                      poles->Array2()       , BSplSLib::NoWeights(),
                      nmults->ChangeArray1(), nknots->ChangeArray1(),
                      npoles->ChangeArray2(),
                      *((TColStd_Array2OfReal*) NULL));
    }
    poles     = npoles;
    weights   = nweights;
    umults    = nmults;
    uknots    = nknots;
    uperiodic = Standard_False;
    
    maxderivinvok = 0;
    UpdateUKnots();
    
  }
}

//=======================================================================
//function : SetVNotPeriodic
//purpose  : 
//=======================================================================

01306 void Geom_BSplineSurface::SetVNotPeriodic ()
{
  if ( vperiodic) {
    Standard_Integer NbKnots, NbPoles;
    BSplCLib::PrepareUnperiodize( vdeg, vmults->Array1(), NbKnots, NbPoles);

    Handle(TColgp_HArray2OfPnt) npoles = 
      new TColgp_HArray2OfPnt(1, poles->ColLength(), 1, NbPoles);
    
    Handle(TColStd_HArray1OfReal) nknots 
      = new TColStd_HArray1OfReal(1,NbKnots);

    Handle(TColStd_HArray1OfInteger) nmults
      = new TColStd_HArray1OfInteger(1,NbKnots) ;

    Handle(TColStd_HArray2OfReal) nweights = new TColStd_HArray2OfReal(1, poles->ColLength(), 1, NbPoles, 0);

    if ( urational || vrational) {

      BSplSLib::Unperiodize(Standard_False        , vdeg, 
                      vmults->Array1()      , vknots->Array1(),
                      poles->Array2()       , weights->Array2(),
                      nmults->ChangeArray1(), nknots->ChangeArray1(),
                      npoles->ChangeArray2(),
                      nweights->ChangeArray2());
    }
    else {

      BSplSLib::Unperiodize(Standard_False        , vdeg, 
                      vmults->Array1()      , vknots->Array1(),
                      poles->Array2()       , BSplSLib::NoWeights(),
                      nmults->ChangeArray1(), nknots->ChangeArray1(),
                      npoles->ChangeArray2(),
                      *((TColStd_Array2OfReal*) NULL));
    }
    poles     = npoles;
    weights   = nweights;
    vmults    = nmults;
    vknots    = nknots;
    vperiodic = Standard_False;
    
    maxderivinvok = 0;
    UpdateVKnots();
    
  }
}

//=======================================================================
//function : IsUClosed
//purpose  : 
//=======================================================================

01358 Standard_Boolean Geom_BSplineSurface::IsUClosed () const
{   
  if (uperiodic)
    return Standard_True;

  Standard_Boolean Closed     = Standard_True;
  TColgp_Array2OfPnt & VPoles = poles->ChangeArray2();
  Standard_Integer PLower     = VPoles.LowerRow();
  Standard_Integer PUpper     = VPoles.UpperRow();
  Standard_Integer PLength    = VPoles.RowLength();
  Standard_Integer j = VPoles.LowerCol();
  if ( urational || vrational) {
    TColStd_Array2OfReal & VWeights = weights->ChangeArray2();
    Standard_Integer WLower = VWeights.LowerRow();
    Standard_Integer WUpper = VWeights.UpperRow();
    Standard_Real    Alfa = VWeights(WLower,VWeights.LowerCol());
    Alfa /= VWeights(WUpper,VWeights.LowerCol());

    Standard_Integer k = VWeights.LowerCol();
    while (Closed && j <= PLength) {
      Closed = 
      (VPoles (PLower, j).Distance (VPoles (PUpper, j)) <= Precision::Confusion());
      j++;
      Closed = (Closed &&
             ((VWeights(WLower,k) / VWeights(WUpper,k)) - Alfa) 
             < Epsilon(Alfa));
      k++;
    }
  }
  else {
    while (Closed && j <= PLength) {
      Closed = 
      (VPoles (PLower, j).Distance (VPoles (PUpper, j)) <= Precision::Confusion());
      j++;
    }
  }
  return Closed; 
}

//=======================================================================
//function : IsVClosed
//purpose  : 
//=======================================================================

01402 Standard_Boolean Geom_BSplineSurface::IsVClosed () const
{
  if (vperiodic)
    return Standard_True;

  Standard_Boolean Closed     = Standard_True;
  TColgp_Array2OfPnt & VPoles = poles->ChangeArray2();
  Standard_Integer PLower     = VPoles.LowerCol();
  Standard_Integer PUpper     = VPoles.UpperCol();
  Standard_Integer PLength    = VPoles.ColLength();
  Standard_Integer i = VPoles.LowerRow();
  if ( urational || vrational) {
    TColStd_Array2OfReal & VWeights = weights->ChangeArray2();
    Standard_Integer WLower = VWeights.LowerCol();
    Standard_Integer WUpper = VWeights.UpperCol();
    Standard_Real    Alfa = VWeights(VWeights.LowerRow(),WLower);
    Alfa /= VWeights(VWeights.LowerRow(),WUpper);

    Standard_Integer k = VWeights.LowerRow();
    while (Closed && i <= PLength) {
      Closed = 
      (VPoles (i, PLower).Distance (VPoles (i, PUpper)) <= Precision::Confusion());
      i++;
      Closed = (Closed &&
             ((VWeights(k,WLower) / VWeights(k,WUpper)) - Alfa) 
             < Epsilon(Alfa));
      k++;
    }
  }
  else {
    while (Closed && i <= PLength) {
      Closed = 
      (VPoles (i, PLower).Distance (VPoles (i, PUpper)) <= Precision::Confusion());
      i++;
    }
  }
  return Closed; 
}

//=======================================================================
//function : IsUPeriodic
//purpose  : 
//=======================================================================

01446 Standard_Boolean Geom_BSplineSurface::IsUPeriodic () const 
{
  return uperiodic; 
}

//=======================================================================
//function : IsVPeriodic
//purpose  : 
//=======================================================================

01456 Standard_Boolean Geom_BSplineSurface::IsVPeriodic () const 
{ 
  return vperiodic; 
}

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

01466 Standard_Integer Geom_BSplineSurface::FirstUKnotIndex () const 
{ 
  if (uperiodic) return 1;
  else return BSplCLib::FirstUKnotIndex(udeg,umults->Array1()); 
}

//=======================================================================
//function : FirstVKnotIndex
//purpose  : 
//=======================================================================

01477 Standard_Integer Geom_BSplineSurface::FirstVKnotIndex () const 
{ 
  if (vperiodic) return 1;
  else return BSplCLib::FirstUKnotIndex(vdeg,vmults->Array1()); 
}

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

01488 Standard_Integer Geom_BSplineSurface::LastUKnotIndex() const 
{
  if (uperiodic) return uknots->Length();
  else return BSplCLib::LastUKnotIndex(udeg,umults->Array1()); 
}

//=======================================================================
//function : LastVKnotIndex
//purpose  : 
//=======================================================================

01499 Standard_Integer Geom_BSplineSurface::LastVKnotIndex() const 
{
  if (vperiodic) return vknots->Length();
  else return BSplCLib::LastUKnotIndex(vdeg,vmults->Array1()); 
}

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

void Geom_BSplineSurface::LocateU
01511   (const Standard_Real     U, 
   const Standard_Real     ParametricTolerance, 
         Standard_Integer& I1,
         Standard_Integer& I2,
   const Standard_Boolean  WithKnotRepetition ) const
{
  Standard_Real NewU =U, vbid = vknots->Value(1);
  Handle(TColStd_HArray1OfReal) TheKnots;
  if (WithKnotRepetition) TheKnots = ufknots;
  else                    TheKnots = uknots;

  PeriodicNormalization(NewU, vbid); //Attention a la periode
  
  const TColStd_Array1OfReal & Knots = TheKnots->Array1();
  Standard_Real UFirst = Knots (1);
  Standard_Real ULast  = Knots (Knots.Length());
  if (Abs (NewU - UFirst) <= Abs(ParametricTolerance)) { 
    I1 = I2 = 1; 
  }
  else if (Abs (NewU - ULast) <= Abs(ParametricTolerance)) { 
    I1 = I2 = Knots.Length();
  }
  else if (NewU < UFirst - Abs(ParametricTolerance)) {
    I2 = 1;
    I1 = 0;
  }
  else if (NewU > ULast + Abs(ParametricTolerance)) {
    I1 = Knots.Length();
    I2 = I1 + 1;
  }
  else {
    I1 = 1;
    BSplCLib::Hunt (Knots, NewU, I1);
    while ( Abs( Knots(I1+1) - NewU) <= Abs(ParametricTolerance)) I1++;
    if ( Abs( Knots(I1) - NewU) <= Abs(ParametricTolerance)) {
      I2 = I1;
    }
    else {
      I2 = I1 + 1;
    }
  }
}

//=======================================================================
//function : LocateV
//purpose  : 
//=======================================================================

void Geom_BSplineSurface::LocateV
01560   (const Standard_Real     V, 
   const Standard_Real     ParametricTolerance, 
         Standard_Integer& I1,
         Standard_Integer& I2,
   const Standard_Boolean  WithKnotRepetition ) const
{
  Standard_Real NewV =V, ubid = uknots->Value(1);  
  Handle(TColStd_HArray1OfReal) TheKnots;
  if (WithKnotRepetition) TheKnots = vfknots;
  else                    TheKnots = vknots;

  PeriodicNormalization(ubid, NewV); //Attention a la periode
  
  const TColStd_Array1OfReal & Knots = TheKnots->Array1();
  Standard_Real VFirst = Knots (1);
  Standard_Real VLast  = Knots (Knots.Length());
  if (Abs (NewV - VFirst) <= Abs(ParametricTolerance)) { I1 = I2 = 1; }
  else if (Abs (NewV - VLast) <= Abs(ParametricTolerance)) { 
    I1 = I2 = Knots.Length();
  }
  else if (NewV < VFirst - Abs(ParametricTolerance)) {
    I2 = 1;
    I1 = 0;
  }
  else if (NewV > VLast + Abs(ParametricTolerance)) {
    I1 = Knots.Length();
    I2 = I1 + 1;
  }
  else {
    I1 = 1;
    BSplCLib::Hunt (Knots, NewV, I1);
    while ( Abs( Knots(I1+1) - NewV) <= Abs(ParametricTolerance)) I1++;
    if ( Abs( Knots(I1) - NewV) <= Abs(ParametricTolerance)) {
      I2 = I1;
    }
    else {
      I2 = I1 + 1;
    }
  }
}

//=======================================================================
//function : UReverse
//purpose  : 
//=======================================================================

01606 void Geom_BSplineSurface::UReverse ()
{
  BSplCLib::Reverse(umults->ChangeArray1());
  BSplCLib::Reverse(uknots->ChangeArray1());
  Standard_Integer last;
  if (uperiodic)
    last = ufknots->Upper() - udeg -1;
  else
    last = poles->UpperRow();
  BSplSLib::Reverse(poles->ChangeArray2(),last,Standard_True);
  if (urational || vrational)
    BSplSLib::Reverse(weights->ChangeArray2(),last,Standard_True);
  UpdateUKnots();
}

//=======================================================================
//function : UReversedParameter
//purpose  : 
//=======================================================================

Standard_Real Geom_BSplineSurface::UReversedParameter
01627   ( const Standard_Real U) const 
{
  return ( uknots->Value( 1) + uknots->Value( uknots->Length()) - U);
}

//=======================================================================
//function : VReverse
//purpose  : 
//=======================================================================

01637 void Geom_BSplineSurface::VReverse ()
{
  BSplCLib::Reverse(vmults->ChangeArray1());
  BSplCLib::Reverse(vknots->ChangeArray1());
  Standard_Integer last;
  if (vperiodic)
    last = vfknots->Upper() - vdeg -1;
  else
    last = poles->UpperCol();
  BSplSLib::Reverse(poles->ChangeArray2(),last,Standard_False);
  if (urational || vrational)
    BSplSLib::Reverse(weights->ChangeArray2(),last,Standard_False);
  UpdateVKnots();
}

//=======================================================================
//function : VReversedParameter
//purpose  : 
//=======================================================================

Standard_Real Geom_BSplineSurface::VReversedParameter
01658   ( const Standard_Real V) const 
{
  return ( vknots->Value( 1) + vknots->Value( vknots->Length()) - V);
}

//=======================================================================
//function : SetPoleCol
//purpose  : 
//=======================================================================

01668 void Geom_BSplineSurface::SetPoleCol (const Standard_Integer      VIndex,
                              const TColgp_Array1OfPnt&   CPoles)
{
  if (VIndex < 1 || VIndex > poles->RowLength()) {
    Standard_OutOfRange::Raise();
    }
  if (CPoles.Lower() < 1 || CPoles.Lower() > poles->ColLength() || 
      CPoles.Upper() < 1 || CPoles.Upper() > poles->ColLength()) {
    Standard_ConstructionError::Raise();
    }

  TColgp_Array2OfPnt & Poles = poles->ChangeArray2();

  for (Standard_Integer I = CPoles.Lower(); I <= CPoles.Upper(); I++) {
    Poles (I+Poles.LowerRow()-1, VIndex+Poles.LowerCol()-1) = CPoles(I);
  }

  InvalidateCache();
}

//=======================================================================
//function : SetPoleCol
//purpose  : 
//=======================================================================

01693 void Geom_BSplineSurface::SetPoleCol (const Standard_Integer      VIndex,
                              const TColgp_Array1OfPnt&   CPoles,
                              const TColStd_Array1OfReal& CPoleWeights)
{
  SetPoleCol  (VIndex, CPoles);
  SetWeightCol(VIndex, CPoleWeights); 
}

//=======================================================================
//function : SetPoleRow
//purpose  : 
//=======================================================================

01706 void Geom_BSplineSurface::SetPoleRow (const Standard_Integer    UIndex,
                              const TColgp_Array1OfPnt& CPoles)
{
  if (UIndex < 1 || UIndex > poles->ColLength()  ) {
    Standard_OutOfRange::Raise();
    }
  if (CPoles.Lower() < 1 || CPoles.Lower() > poles->RowLength() || 
      CPoles.Upper() < 1 || CPoles.Upper() > poles->RowLength() ) {
    Standard_ConstructionError::Raise();
    }

  TColgp_Array2OfPnt & Poles = poles->ChangeArray2();

  for (Standard_Integer I = CPoles.Lower(); I <= CPoles.Upper(); I++) {
    Poles (UIndex+Poles.LowerRow()-1, I+Poles.LowerCol()-1) = CPoles (I);
  }

  InvalidateCache();
}

//=======================================================================
//function : SetPoleRow
//purpose  : 
//=======================================================================

01731 void Geom_BSplineSurface::SetPoleRow(const Standard_Integer      UIndex,
                             const TColgp_Array1OfPnt &  CPoles,
                             const TColStd_Array1OfReal& CPoleWeights)
{
  SetPoleRow  (UIndex, CPoles);
  SetWeightRow(UIndex, CPoleWeights);  
}

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

01744 void Geom_BSplineSurface::SetPole (const Standard_Integer UIndex,
                           const Standard_Integer VIndex,
                           const gp_Pnt&          P)
{
  poles->SetValue (UIndex+poles->LowerRow()-1, VIndex+poles->LowerCol()-1, P);
  InvalidateCache();
}

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

01757 void Geom_BSplineSurface::SetPole (const Standard_Integer UIndex,
                           const Standard_Integer VIndex,
                           const gp_Pnt&          P, 
                           const Standard_Real    Weight)
{
  SetWeight(UIndex, VIndex, Weight);
  SetPole  (UIndex, VIndex, P);
}

//=======================================================================
//function : MovePoint
//purpose  : 
//=======================================================================

01771 void Geom_BSplineSurface::MovePoint(const Standard_Real U,
                            const Standard_Real V,
                            const gp_Pnt& P,
                            const Standard_Integer UIndex1,
                            const Standard_Integer UIndex2,
                            const Standard_Integer VIndex1,
                            const Standard_Integer VIndex2,
                            Standard_Integer& UFirstModifiedPole,
                            Standard_Integer& ULastmodifiedPole,
                            Standard_Integer& VFirstModifiedPole,
                            Standard_Integer& VLastmodifiedPole)
{
  if (UIndex1 < 1 || UIndex1 > poles->UpperRow() || 
      UIndex2 < 1 || UIndex2 > poles->UpperRow() || UIndex1 > UIndex2 ||
      VIndex1 < 1 || VIndex1 > poles->UpperCol() || 
      VIndex2 < 1 || VIndex2 > poles->UpperCol() || VIndex1 > VIndex2) {
    Standard_OutOfRange::Raise();
  }

  TColgp_Array2OfPnt npoles(1, poles->UpperRow(), 1, poles->UpperCol());
  gp_Pnt P0;
  D0(U, V, P0);
  gp_Vec Displ(P0, P);
  Standard_Boolean rational = (urational || vrational);
  BSplSLib::MovePoint(U, V, Displ, UIndex1, UIndex2, VIndex1, VIndex2, udeg, vdeg,
                  rational, poles->Array2(), weights->Array2(),
                  ufknots->Array1(), vfknots->Array1(), 
                  UFirstModifiedPole, ULastmodifiedPole,
                  VFirstModifiedPole, VLastmodifiedPole,
                  npoles);
  if (UFirstModifiedPole) {
    poles->ChangeArray2() = npoles;
  }
  maxderivinvok = 0;
  InvalidateCache() ;
}

//=======================================================================
//function : Bounds
//purpose  : 
//=======================================================================

01813 void Geom_BSplineSurface::Bounds (Standard_Real& U1,
                          Standard_Real& U2,
                          Standard_Real& V1,
                          Standard_Real& V2) const
{
  U1 = ufknots->Value (udeg+1);
  U2 = ufknots->Value (ufknots->Upper()-udeg);
  V1 = vfknots->Value (vdeg+1);
  V2 = vfknots->Value (vfknots->Upper()-vdeg);
}

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

01829 Standard_Integer Geom_BSplineSurface::MaxDegree () 
{ 
  return BSplCLib::MaxDegree(); 
}

//=======================================================================
//function : IsURational
//purpose  : 
//=======================================================================

01839 Standard_Boolean Geom_BSplineSurface::IsURational () const 
{
  return urational; 
}

//=======================================================================
//function : IsVRational
//purpose  : 
//=======================================================================

01849 Standard_Boolean Geom_BSplineSurface::IsVRational () const 
{
  return vrational; 
}

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

01859 GeomAbs_Shape Geom_BSplineSurface::Continuity () const 
{
  return ((Usmooth < Vsmooth) ? Usmooth : Vsmooth) ; 
}

//=======================================================================
//function : NbUKnots
//purpose  : 
//=======================================================================

01869 Standard_Integer Geom_BSplineSurface::NbUKnots () const 
{
  return uknots->Length(); 
}

//=======================================================================
//function : NbUPoles
//purpose  : 
//=======================================================================

01879 Standard_Integer Geom_BSplineSurface::NbUPoles () const 
{
  return poles->ColLength(); 
}

//=======================================================================
//function : NbVKnots
//purpose  : 
//=======================================================================

01889 Standard_Integer Geom_BSplineSurface::NbVKnots () const 
{
  return vknots->Length(); 
}

//=======================================================================
//function : NbVPoles
//purpose  : 
//=======================================================================

01899 Standard_Integer Geom_BSplineSurface::NbVPoles () const 
{
  return poles->RowLength(); 
}

//=======================================================================
//function : UDegree
//purpose  : 
//=======================================================================

01909 Standard_Integer Geom_BSplineSurface::UDegree () const 
{
  return udeg; 
}

//=======================================================================
//function : VDegree
//purpose  : 
//=======================================================================

01919 Standard_Integer Geom_BSplineSurface::VDegree () const 
{
  return vdeg; 
}

//=======================================================================
//function : UKnotDistribution
//purpose  : 
//=======================================================================

01929 GeomAbs_BSplKnotDistribution Geom_BSplineSurface::UKnotDistribution() const 
{ 
  return uknotSet; 
}


//=======================================================================
//function : VKnotDistribution
//purpose  : 
//=======================================================================

01940 GeomAbs_BSplKnotDistribution Geom_BSplineSurface::VKnotDistribution() const 
{
  return vknotSet; 
}

//=======================================================================
//function : InsertUKnots
//purpose  : 
//=======================================================================

void  Geom_BSplineSurface::InsertUKnots
  (const TColStd_Array1OfReal&    Knots, 
   const TColStd_Array1OfInteger& Mults,
   const Standard_Real            ParametricTolerance,
   const Standard_Boolean         Add)
{
  // Check and compute new sizes
  Standard_Integer nbpoles, nbknots;

  if ( !BSplCLib::PrepareInsertKnots(udeg,uperiodic,
                             uknots->Array1(),umults->Array1(),
                             Knots,Mults,nbpoles,nbknots,
                             ParametricTolerance,Add))
    Standard_ConstructionError::Raise("Geom_BSplineSurface::InsertUKnots");
  
  if ( nbpoles == poles->ColLength()) return;

  Handle(TColgp_HArray2OfPnt) npoles
    = new TColgp_HArray2OfPnt(1,nbpoles, 1,poles->RowLength());
  Handle(TColStd_HArray2OfReal) nweights =
    new TColStd_HArray2OfReal(1,nbpoles, 
                        1,poles->RowLength(),
                        1.0);
  Handle(TColStd_HArray1OfReal)    nknots = uknots;
  Handle(TColStd_HArray1OfInteger) nmults = umults;

  if ( nbknots != uknots->Length()) {
    nknots = new TColStd_HArray1OfReal(1,nbknots);
    nmults = new TColStd_HArray1OfInteger(1,nbknots);
  }

  if ( urational || vrational) {
    BSplSLib::InsertKnots(Standard_True,
                    udeg, uperiodic,
                    poles->Array2() , weights->Array2(),
                    uknots->Array1(), umults->Array1(),
                    Knots, Mults,
                    npoles->ChangeArray2(),
                    nweights->ChangeArray2(),
                    nknots->ChangeArray1(), nmults->ChangeArray1(),
                    ParametricTolerance, Add);
  }
  else {
    BSplSLib::InsertKnots(Standard_True,
                    udeg, uperiodic,
                    poles->Array2() , BSplSLib::NoWeights(),
                    uknots->Array1(), umults->Array1(),
                    Knots, Mults,
                    npoles->ChangeArray2(),
                    *((TColStd_Array2OfReal*) NULL),
                    nknots->ChangeArray1(), nmults->ChangeArray1(),
                    ParametricTolerance, Add);
  }

  poles = npoles;
  weights = nweights;
  uknots = nknots;
  umults = nmults;
  UpdateUKnots();
                             
}

//=======================================================================
//function : InsertVKnots
//purpose  : 
//=======================================================================

void  Geom_BSplineSurface::InsertVKnots
02018   (const TColStd_Array1OfReal& Knots, 
   const TColStd_Array1OfInteger& Mults, 
   const Standard_Real ParametricTolerance,
   const Standard_Boolean Add)
{
  // Check and compute new sizes
  Standard_Integer nbpoles, nbknots;

  if ( !BSplCLib::PrepareInsertKnots(vdeg,vperiodic,
                             vknots->Array1(),vmults->Array1(),
                             Knots,Mults,nbpoles,nbknots,
                             ParametricTolerance, Add))
    Standard_ConstructionError::Raise("Geom_BSplineSurface::InsertVKnots");
  
  if ( nbpoles == poles->RowLength()) return;

  Handle(TColgp_HArray2OfPnt) npoles
    = new TColgp_HArray2OfPnt(1,poles->ColLength(), 1,nbpoles);
  Handle(TColStd_HArray2OfReal) nweights =
    new TColStd_HArray2OfReal(1,poles->ColLength(),
                        1,nbpoles,
                        1.0);
  Handle(TColStd_HArray1OfReal)    nknots = vknots;
  Handle(TColStd_HArray1OfInteger) nmults = vmults;

  if ( nbknots != vknots->Length()) {
    nknots = new TColStd_HArray1OfReal(1,nbknots);
    nmults = new TColStd_HArray1OfInteger(1,nbknots);
  }

  if ( urational || vrational) {
    BSplSLib::InsertKnots(Standard_False,
                    vdeg, vperiodic,
                    poles->Array2() , weights->Array2(),
                    vknots->Array1(), vmults->Array1(),
                    Knots, Mults,
                    npoles->ChangeArray2(),
                    nweights->ChangeArray2(),
                    nknots->ChangeArray1(), nmults->ChangeArray1(),
                    ParametricTolerance, Add);
  }
  else {
    BSplSLib::InsertKnots(Standard_False,
                    vdeg, vperiodic,
                    poles->Array2() , BSplSLib::NoWeights(),
                    vknots->Array1(), vmults->Array1(),
                    Knots, Mults,
                    npoles->ChangeArray2(),
                    *((TColStd_Array2OfReal*) NULL),
                    nknots->ChangeArray1(), nmults->ChangeArray1(),
                    ParametricTolerance, Add);
  }

  poles = npoles;
  weights = nweights;
  vknots = nknots;
  vmults = nmults;
  UpdateVKnots();
                             
}

//=======================================================================
//function : RemoveUKnot
//purpose  : 
//=======================================================================

Standard_Boolean  Geom_BSplineSurface::RemoveUKnot
  (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 ( !uperiodic && (Index <= I1 || Index >= I2) ) {
    Standard_OutOfRange::Raise();
  }
  else if ( uperiodic  && (Index < I1 || Index > I2)) {
    Standard_OutOfRange::Raise();
  }
  
  const TColgp_Array2OfPnt   & oldpoles = poles->Array2();
#ifdef DEB
  const TColStd_Array1OfReal & oldknots = uknots->Array1();
#else
  uknots->Array1();
#endif

  Standard_Integer step = umults->Value(Index) - M;
  if (step <= 0 ) return Standard_True;

  Handle(TColgp_HArray2OfPnt) npoles = 
    new TColgp_HArray2OfPnt( 1, oldpoles.ColLength() - step,
                       1, oldpoles.RowLength());
  Handle(TColStd_HArray1OfReal)    nknots = uknots;
  Handle(TColStd_HArray1OfInteger) nmults = umults;

  if ( M == 0) {
    nknots = new TColStd_HArray1OfReal(1,uknots->Length()-1);
    nmults = new TColStd_HArray1OfInteger(1,uknots->Length()-1);
  }
  Handle(TColStd_HArray2OfReal) nweights ;
  if (urational || vrational) {
    nweights = 
      new TColStd_HArray2OfReal( 1, npoles->ColLength(),
                        1, npoles->RowLength());
    if (!BSplSLib::RemoveKnot(Standard_True,
                        Index,M,udeg,uperiodic,
                        poles->Array2(),weights->Array2(),
                        uknots->Array1(),umults->Array1(),
                        npoles->ChangeArray2(),
                        nweights->ChangeArray2(),
                        nknots->ChangeArray1(),nmults->ChangeArray1(),
                        Tolerance))
      return Standard_False;
  }
  else {
//
// sync the size of the weights
//
    nweights = 
      new TColStd_HArray2OfReal(1, npoles->ColLength(),
                        1, npoles->RowLength(),
                        1.0e0 );
    if (!BSplSLib::RemoveKnot(Standard_True,
                        Index,M,udeg,uperiodic,
                        poles->Array2(),BSplSLib::NoWeights(),
                        uknots->Array1(),umults->Array1(),
                        npoles->ChangeArray2(),
                        *((TColStd_Array2OfReal*) NULL),
                        nknots->ChangeArray1(),nmults->ChangeArray1(),
                        Tolerance))
      return Standard_False;
  }
  
  poles = npoles;
  weights = nweights;
  uknots = nknots;
  umults = nmults;

  maxderivinvok = 0;
  UpdateUKnots();
  return Standard_True;
}

//=======================================================================
//function : RemoveVKnot
//purpose  : 
//=======================================================================

Standard_Boolean  Geom_BSplineSurface::RemoveVKnot
02171   (const Standard_Integer Index, 
   const Standard_Integer M,
   const Standard_Real Tolerance)
{
  if ( M < 0 ) return Standard_True;
  
  Standard_Integer I1 = FirstVKnotIndex ();
  Standard_Integer I2 = LastVKnotIndex  ();
  
  if ( !vperiodic && (Index <= I1 || Index >= I2) ) {
    Standard_OutOfRange::Raise();
  }
  else if ( vperiodic  && (Index < I1 || Index > I2)) {
    Standard_OutOfRange::Raise();
  }
  
  const TColgp_Array2OfPnt   & oldpoles = poles->Array2();
#ifdef DEB
  const TColStd_Array1OfReal & oldknots = vknots->Array1();
#else
  vknots->Array1();
#endif

  Standard_Integer step = vmults->Value(Index) - M;
  if (step <= 0 ) return Standard_True;

  Handle(TColgp_HArray2OfPnt) npoles = 
    new TColgp_HArray2OfPnt( 1, oldpoles.ColLength(),
                       1, oldpoles.RowLength() - step);
  Handle(TColStd_HArray1OfReal)    nknots = vknots;
  Handle(TColStd_HArray1OfInteger) nmults = vmults;

  if ( M == 0) {
    nknots = new TColStd_HArray1OfReal(1,vknots->Length()-1);
    nmults = new TColStd_HArray1OfInteger(1,vknots->Length()-1);
  }
  Handle(TColStd_HArray2OfReal) nweights ;
  if (urational || vrational) {
    nweights = 
      new TColStd_HArray2OfReal( 1, npoles->ColLength(),
                         1, npoles->RowLength()) ;


    if (!BSplSLib::RemoveKnot(Standard_False,
                        Index,M,vdeg,vperiodic,
                        poles->Array2(),weights->Array2(),
                        vknots->Array1(),vmults->Array1(),
                        npoles->ChangeArray2(),
                        nweights->ChangeArray2(),
                        nknots->ChangeArray1(),nmults->ChangeArray1(),
                        Tolerance))
      return Standard_False;
  }
  else {
//
// sync the size of the weights array
//
    nweights = 
      new TColStd_HArray2OfReal(1, npoles->ColLength(),
                        1, npoles->RowLength(),
                        1.0e0 );
    if (!BSplSLib::RemoveKnot(Standard_False,
                        Index,M,vdeg,vperiodic,
                        poles->Array2(),BSplSLib::NoWeights(),
                        vknots->Array1(),vmults->Array1(),
                        npoles->ChangeArray2(),
                        *((TColStd_Array2OfReal*) NULL),
                        nknots->ChangeArray1(),nmults->ChangeArray1(),
                        Tolerance))
      return Standard_False;
  }
  
  poles = npoles;
  vknots = nknots;
  vmults = nmults;
  weights = nweights;
  maxderivinvok = 0;
  UpdateVKnots();
  return Standard_True;
}

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

02257 void   Geom_BSplineSurface::Resolution( const Standard_Real  Tolerance3D,
                               Standard_Real&        UTolerance,
                               Standard_Real&        VTolerance)
{
  if(!maxderivinvok){
    BSplSLib::Resolution(poles  ->Array2(),
                   weights->Array2(),
                   uknots ->Array1(),
                   vknots ->Array1(),
                   umults ->Array1(),
                   vmults ->Array1(),
                   udeg,
                   vdeg,
                   urational,
                   vrational,
                   uperiodic,
                   vperiodic,
                   1.,
                   umaxderivinv,
                   vmaxderivinv) ;
    maxderivinvok = 1;
  }
  UTolerance = Tolerance3D * umaxderivinv;
  VTolerance = Tolerance3D * vmaxderivinv;
}
                   




Generated by  Doxygen 1.6.0   Back to index