Integration of OCCT 6.5.0 from SVN
[occt.git] / src / Geom2dAPI / Geom2dAPI_Interpolate.cxx
diff --git a/src/Geom2dAPI/Geom2dAPI_Interpolate.cxx b/src/Geom2dAPI/Geom2dAPI_Interpolate.cxx
new file mode 100755 (executable)
index 0000000..869c242
--- /dev/null
@@ -0,0 +1,915 @@
+// File:       GeomAPI_Interpolate.cxx
+// Created:    Thu Aug 18 15:53:59 1994
+// Author:     Laurent PAINNOT
+//             <lpa@metrox>
+// 8-Aug-95 : xab : interpolation uses BSplCLib::Interpolate
+//
+
+#include <Geom2dAPI_Interpolate.ixx>
+#include <Standard_ConstructionError.hxx>
+#include <PLib.hxx>
+#include <BSplCLib.hxx>
+#include <gp_Vec2d.hxx>
+#include <TColgp_Array1OfPnt2d.hxx>
+#include <TColStd_HArray1OfReal.hxx>
+#include <TColStd_Array1OfBoolean.hxx>
+#include <TColStd_Array1OfInteger.hxx>
+#include <TColStd_HArray1OfBoolean.hxx>
+
+//=======================================================================
+//function : CheckPoints
+//purpose  : 
+//=======================================================================
+
+static Standard_Boolean CheckPoints(const TColgp_Array1OfPnt2d& PointArray,
+                                   const Standard_Real    Tolerance) 
+{
+  Standard_Integer ii ;
+  Standard_Real tolerance_squared = Tolerance * Tolerance,
+  distance_squared ;
+  Standard_Boolean result = Standard_True ;
+  for (ii = PointArray.Lower() ; result && ii < PointArray.Upper() ; ii++) {
+    distance_squared = 
+      PointArray.Value(ii).SquareDistance(PointArray.Value(ii+1)) ;
+    result = (distance_squared >= tolerance_squared) ;
+  }
+ return result ;
+
+}
+//=======================================================================
+//function : CheckTangents
+//purpose  : 
+//=======================================================================
+static Standard_Boolean CheckTangents(
+                               const TColgp_Array1OfVec2d&      Tangents,
+                               const TColStd_Array1OfBoolean& TangentFlags,
+                               const Standard_Real            Tolerance) 
+{
+  Standard_Integer ii,
+  index ;
+  Standard_Real tolerance_squared = Tolerance * Tolerance,
+  distance_squared ;
+  Standard_Boolean result = Standard_True ;
+  index = TangentFlags.Lower() ;
+  for (ii = Tangents.Lower(); result && ii <= Tangents.Upper() ; ii++) {
+    if(TangentFlags.Value(index)) {
+      distance_squared = 
+       Tangents.Value(ii).SquareMagnitude() ;
+      result = (distance_squared >= tolerance_squared) ;
+    }
+    index += 1 ;
+  }
+ return result ;
+
+}
+//=======================================================================
+//function : CheckParameters
+//purpose  : 
+//=======================================================================
+static Standard_Boolean CheckParameters(const 
+                                       TColStd_Array1OfReal&   Parameters) 
+{
+  Standard_Integer ii ;
+  Standard_Real distance ;
+  Standard_Boolean result = Standard_True ;
+  for (ii = Parameters.Lower() ; result && ii < Parameters.Upper() ; ii++) {
+    distance = 
+      Parameters.Value(ii+1) - Parameters.Value(ii) ;
+    result = (distance >= RealSmall()) ;
+  }
+ return result ;
+}      
+//=======================================================================
+//function : BuildParameters
+//purpose  : 
+//=======================================================================                    
+static void  BuildParameters(const Standard_Boolean        PeriodicFlag,
+                            const TColgp_Array1OfPnt2d&     PointsArray,
+                            Handle_TColStd_HArray1OfReal& ParametersPtr) 
+{
+  Standard_Integer ii,
+  index ;
+  Standard_Real distance ;
+  Standard_Integer 
+    num_parameters = PointsArray.Length() ;
+  if (PeriodicFlag) {
+    num_parameters += 1 ;
+  }
+  ParametersPtr =
+    new TColStd_HArray1OfReal(1,
+                             num_parameters) ;
+  ParametersPtr->SetValue(1,0.0e0) ;
+  index = 2 ;
+  for (ii = PointsArray.Lower() ; ii < PointsArray.Upper() ; ii++) {
+    distance = 
+      PointsArray.Value(ii).Distance(PointsArray.Value(ii+1)) ;
+    ParametersPtr->SetValue(index,
+                           ParametersPtr->Value(ii) + distance) ;
+    index += 1 ;
+  }
+  if (PeriodicFlag) {
+    distance = 
+      PointsArray.Value(PointsArray.Upper()).
+       Distance(PointsArray.Value(PointsArray.Lower())) ;
+    ParametersPtr->SetValue(index,
+                           ParametersPtr->Value(ii) + distance) ;
+  }
+}
+//=======================================================================
+//function : BuildPeriodicTangents
+//purpose  : 
+//=======================================================================
+               
+static void BuildPeriodicTangent(
+                     const TColgp_Array1OfPnt2d&      PointsArray,
+                     TColgp_Array1OfVec2d&            TangentsArray,
+                     TColStd_Array1OfBoolean&       TangentFlags,
+                     const TColStd_Array1OfReal&    ParametersArray)
+{
+  Standard_Integer 
+    ii,
+    degree ;
+  Standard_Real *point_array,
+  *parameter_array,
+  eval_result[2][2] ;
+  
+  gp_Vec2d a_vector ;
+  
+  if (PointsArray.Length() < 3) {
+    Standard_ConstructionError::Raise(); 
+    }   
+  if (!TangentFlags.Value(1)) {
+    degree = 3 ;
+    if (PointsArray.Length() == 3) {
+      degree = 2 ;
+    }
+    point_array = (Standard_Real *) &PointsArray.Value(PointsArray.Lower()) ; 
+    parameter_array =
+      (Standard_Real *) &ParametersArray.Value(1) ;
+    TangentFlags.SetValue(1,Standard_True) ;
+    PLib::EvalLagrange(ParametersArray.Value(1),
+                      1,
+                      degree,
+                      2,
+                      point_array[0],
+                      parameter_array[0],
+                      eval_result[0][0]) ;
+    for (ii = 1 ; ii <= 2 ; ii++) {
+      a_vector.SetCoord(ii,eval_result[1][ii-1]) ;
+    }
+    TangentsArray.SetValue(1,a_vector) ;
+  }
+ } 
+//=======================================================================
+//function : BuildTangents
+//purpose  : 
+//=======================================================================
+               
+static void BuildTangents(const TColgp_Array1OfPnt2d&      PointsArray,
+                         TColgp_Array1OfVec2d&            TangentsArray,
+                         TColStd_Array1OfBoolean&       TangentFlags,
+                         const TColStd_Array1OfReal&    ParametersArray)
+{
+ Standard_Integer ii,
+ degree ;
+ Standard_Real *point_array,
+ *parameter_array,
+ eval_result[2][2] ;
+ gp_Vec2d a_vector ;
+ degree = 3 ;
+
+ if ( PointsArray.Length() < 3) {
+   Standard_ConstructionError::Raise(); 
+   }   
+ if (PointsArray.Length() == 3) {
+   degree = 2 ;
+ }
+ if (!TangentFlags.Value(1)) {
+   point_array = (Standard_Real *) &PointsArray.Value(PointsArray.Lower()) ; 
+   parameter_array =
+     (Standard_Real *) &ParametersArray.Value(1) ;
+   TangentFlags.SetValue(1,Standard_True) ;
+   PLib::EvalLagrange(ParametersArray.Value(1),
+                     1,
+                     degree,
+                     2,
+                     point_array[0],
+                     parameter_array[0],
+                     eval_result[0][0]) ;
+   for (ii = 1 ; ii <= 2 ; ii++) {
+     a_vector.SetCoord(ii,eval_result[1][ii-1]) ;
+   }
+   TangentsArray.SetValue(1,a_vector) ;
+ }
+ if (! TangentFlags.Value(TangentFlags.Upper())) {
+   point_array = 
+     (Standard_Real *) &PointsArray.Value(PointsArray.Upper() - degree) ;
+   TangentFlags.SetValue(TangentFlags.Upper(),Standard_True) ;
+   parameter_array =
+    (Standard_Real *)&ParametersArray.Value(ParametersArray.Upper() - degree) ;
+   PLib::EvalLagrange(ParametersArray.Value(ParametersArray.Upper()),
+                     1,
+                     degree,
+                     2,
+                     point_array[0],
+                     parameter_array[0],
+                     eval_result[0][0]) ;
+   for (ii = 1 ; ii <= 2 ; ii++) {
+     a_vector.SetCoord(ii,eval_result[1][ii-1]) ; 
+   }
+   TangentsArray.SetValue(TangentsArray.Upper(),a_vector) ;
+ }
+} 
+//=======================================================================
+//function : BuildTangents
+//purpose  : scale the given tangent so that they have the length of
+// the size of the derivative of the lagrange interpolation 
+//
+//=======================================================================    
+static void ScaleTangents(const TColgp_Array1OfPnt2d&      PointsArray,
+                         TColgp_Array1OfVec2d&            TangentsArray,
+                         const TColStd_Array1OfBoolean& TangentFlags,
+                         const TColStd_Array1OfReal&     ParametersArray)
+{
+ Standard_Integer ii,
+ jj,
+ degree=0,
+ index,
+ num_points ;
+
+ Standard_Real *point_array,
+ *parameter_array,
+ value[2],
+ ratio,
+ eval_result[2][2] ;
+
+ gp_Vec2d a_vector ;
+
+ num_points = PointsArray.Length() ; 
+ if (num_points == 2) {
+    degree = 1 ;
+  }
+ else if (num_points >= 3) {
+   degree = 2 ;
+ }
+ index = PointsArray.Lower() ;
+ for (ii = TangentFlags.Lower()  ; ii <=  TangentFlags.Upper() ; ii++) {
+   if (TangentFlags.Value(ii)) {
+     point_array = 
+       (Standard_Real *) &PointsArray.Value(index) ; 
+     parameter_array =
+       (Standard_Real *) &ParametersArray.Value(index) ;
+     PLib::EvalLagrange(ParametersArray.Value(ii),
+                       1,
+                       degree,
+                       2,
+                       point_array[0],
+                       parameter_array[0],
+                       eval_result[0][0]) ;
+     value[0] = 
+       value[1] = 0.0e0 ;
+     for (jj = 1 ; jj <= 2 ; jj++) {
+       value[0] += Abs(TangentsArray.Value(ii).Coord(jj)) ;
+       value[1] += Abs(eval_result[1][jj-1]) ;
+     }
+     ratio = value[1] / value[0] ;
+     for (jj = 1 ; jj <= 2 ; jj++) {
+       a_vector.SetCoord(jj, ratio *
+                        TangentsArray.Value(ii).Coord(jj)) ;
+     }
+     TangentsArray.SetValue(ii, a_vector) ;
+     if (ii != TangentFlags.Lower()) {
+       index += 1 ;
+     }
+     if (index > PointsArray.Upper() - degree) {
+       index = PointsArray.Upper() - degree ;
+     } 
+     
+   }
+ }
+}
+//=======================================================================
+//function : Geom2dAPI_Interpolate
+//purpose  : 
+//=======================================================================
+
+Geom2dAPI_Interpolate::Geom2dAPI_Interpolate
+   (const Handle_TColgp_HArray1OfPnt2d& PointsPtr,
+    const Standard_Boolean            PeriodicFlag,
+    const Standard_Real               Tolerance) :
+myTolerance(Tolerance),
+myPoints(PointsPtr),
+myIsDone(Standard_False),
+myPeriodic(PeriodicFlag),
+myTangentRequest(Standard_False) 
+
+{
+ Standard_Integer ii ;
+ Standard_Boolean result = 
+   CheckPoints(PointsPtr->Array1(),
+              Tolerance) ;
+ myTangents = 
+     new TColgp_HArray1OfVec2d(myPoints->Lower(),
+                             myPoints->Upper()) ;
+ myTangentFlags =
+      new TColStd_HArray1OfBoolean(myPoints->Lower(),
+                                  myPoints->Upper()) ;
+
+ if (!result) {
+   Standard_ConstructionError::Raise();
+   }
+ BuildParameters(PeriodicFlag,
+                PointsPtr->Array1(),
+                myParameters) ;
+
+  for (ii = myPoints->Lower() ; ii <= myPoints->Upper() ; ii++) {
+    myTangentFlags->SetValue(ii,Standard_False) ;
+  }
+
+                
+}
+
+//=======================================================================
+//function : Geom2dAPI_Interpolate
+//purpose  : 
+//=======================================================================
+
+Geom2dAPI_Interpolate::Geom2dAPI_Interpolate
+   (const Handle_TColgp_HArray1OfPnt2d&    PointsPtr,
+    const Handle_TColStd_HArray1OfReal&  ParametersPtr,
+    const Standard_Boolean               PeriodicFlag,
+    const Standard_Real                  Tolerance) :
+myTolerance(Tolerance),
+myPoints(PointsPtr),
+myIsDone(Standard_False),
+myParameters(ParametersPtr),
+myPeriodic(PeriodicFlag),
+myTangentRequest(Standard_False) 
+{
+ Standard_Integer ii ;
+    
+     
+ Standard_Boolean result = 
+   CheckPoints(PointsPtr->Array1(),
+              Tolerance) ;
+
+ if (PeriodicFlag) {
+   if ((PointsPtr->Length()) + 1 != ParametersPtr->Length()) {
+     Standard_ConstructionError::Raise();
+   }
+ }
+ myTangents = 
+     new TColgp_HArray1OfVec2d(myPoints->Lower(),
+                             myPoints->Upper()) ;
+ myTangentFlags =
+      new TColStd_HArray1OfBoolean(myPoints->Lower(),
+                                   myPoints->Upper()) ;
+ if (!result) {
+   Standard_ConstructionError::Raise();
+   }
+               
+ result =
+ CheckParameters(ParametersPtr->Array1()) ;
+ if (!result) {
+   Standard_ConstructionError::Raise();
+   }
+       
+ for (ii = myPoints->Lower() ; ii <= myPoints->Upper() ; ii++) {
+   myTangentFlags->SetValue(ii,Standard_False) ;
+ }
+        
+}
+//=======================================================================
+//function : Load
+//purpose  : 
+//=======================================================================
+
+void Geom2dAPI_Interpolate::Load( 
+   const TColgp_Array1OfVec2d&              Tangents,
+   const Handle_TColStd_HArray1OfBoolean& TangentFlagsPtr) 
+
+{
+ Standard_Boolean result ;
+ Standard_Integer ii ;
+ myTangentRequest = Standard_True ;
+ myTangentFlags = TangentFlagsPtr ;
+ if (Tangents.Length() != myPoints->Length() ||
+     TangentFlagsPtr->Length() != myPoints->Length()) {
+   Standard_ConstructionError::Raise();
+   }
+ result  = 
+   CheckTangents(Tangents,
+                TangentFlagsPtr->Array1(),
+                myTolerance) ;
+ if (result) {
+    myTangents = 
+      new TColgp_HArray1OfVec2d(Tangents.Lower(),Tangents.Upper()) ;
+    for (ii = Tangents.Lower() ; ii <= Tangents.Upper() ; ii++ ) {
+      myTangents->SetValue(ii,Tangents.Value(ii)) ;
+    }
+    ScaleTangents(myPoints->Array1(),
+                 myTangents->ChangeArray1(),
+                 TangentFlagsPtr->Array1(),
+                 myParameters->Array1()) ; 
+  }
+ else {
+   Standard_ConstructionError::Raise();
+   }
+  
+}
+
+//=======================================================================
+//function : Load
+//purpose  : 
+//=======================================================================
+
+void Geom2dAPI_Interpolate::Load(const gp_Vec2d& InitialTangent,
+                              const gp_Vec2d& FinalTangent) 
+{
+  Standard_Boolean result ;
+  myTangentRequest = Standard_True ;
+  myTangentFlags->SetValue(1,Standard_True) ;
+  myTangentFlags->SetValue(myPoints->Length(),Standard_True) ;
+  myTangents->SetValue(1,InitialTangent) ;
+  myTangents->SetValue(myPoints->Length(),FinalTangent);
+  result = 
+    CheckTangents(myTangents->Array1(),
+                 myTangentFlags->Array1(),
+                 myTolerance) ;
+  if (!result) {
+    Standard_ConstructionError::Raise();
+    }
+  ScaleTangents(myPoints->Array1(),
+               myTangents->ChangeArray1(),
+               myTangentFlags->Array1(),
+               myParameters->Array1()) ;
+}
+//=======================================================================
+//function : Perform
+//purpose  : 
+//=======================================================================
+
+void Geom2dAPI_Interpolate::Perform() 
+{
+  if (myPeriodic) {
+    PerformPeriodic() ;
+  }
+  else {
+    PerformNonPeriodic() ;
+  }
+}
+//=======================================================================
+//function : PerformPeriodic
+//purpose  : 
+//=======================================================================
+
+void Geom2dAPI_Interpolate::PerformPeriodic()
+{ 
+  Standard_Integer degree,
+  ii,
+  jj,
+  index,
+  index1,
+//  index2,
+  mult_index,
+  half_order,
+  inversion_problem,
+  num_points,
+  num_distinct_knots,
+  num_poles  ;
+  Standard_Real period ;
+
+  gp_Pnt2d a_point ;
+
+  num_points = myPoints->Length() ;
+  period = myParameters->Value(myParameters->Upper()) -
+   myParameters->Value(myParameters->Lower())  ;
+  num_poles = num_points + 1 ;
+  if (num_points == 2 && !myTangentRequest) {
+//
+// build a periodic curve of degree 1
+//  
+
+    degree = 1 ;
+    TColStd_Array1OfInteger  deg1_mults(1,num_poles) ;    
+    for (ii = 1 ; ii <= num_poles ; ii++) {
+      deg1_mults.SetValue(ii,1) ;
+    }
+
+    myCurve =
+      new Geom2d_BSplineCurve(myPoints->Array1(),
+                           myParameters->Array1(),
+                           deg1_mults,
+                           degree,
+                           myPeriodic) ;
+    myIsDone = Standard_True ;
+
+  }
+  else {
+    num_distinct_knots = num_points + 1 ;
+    half_order = 2 ;  
+    degree = 3 ;
+    num_poles += 2 ;
+    if (myTangentRequest) 
+      for (ii = myTangentFlags->Lower() + 1 ; 
+          ii <= myTangentFlags->Upper() ; ii++) {
+       if (myTangentFlags->Value(ii)) {
+         num_poles += 1 ;
+       }
+      }
+  
+    TColStd_Array1OfReal     parameters(1,num_poles) ;  
+    TColStd_Array1OfReal     flatknots(1,num_poles + degree + 1) ;
+    TColStd_Array1OfInteger  mults(1,num_distinct_knots) ;
+    TColStd_Array1OfInteger  contact_order_array(1, num_poles) ;
+    TColgp_Array1OfPnt2d       poles(1,num_poles) ;
+
+    for (ii = 1 ; ii <= half_order ; ii++) {
+      flatknots.SetValue(ii,myParameters->Value(myParameters->Upper() -1) -
+                        period) ;
+      flatknots.SetValue(ii + half_order,myParameters->
+                        Value(myParameters->Lower())) ;
+      flatknots.SetValue(num_poles + ii,
+                        myParameters->Value(myParameters->Upper())) ;
+      flatknots.SetValue(num_poles + half_order + ii,
+                        myParameters->Value(half_order) + period)  ;
+    }
+    for (ii = 1 ; ii <= num_poles ; ii++) {
+      contact_order_array.SetValue(ii,0)  ;
+    }
+    for (ii = 2 ; ii < num_distinct_knots ; ii++) {
+      mults.SetValue(ii,1) ; 
+    }
+    mults.SetValue(1,half_order) ;
+    mults.SetValue(num_distinct_knots ,half_order) ;
+    if (num_points >= 3) {
+     
+//
+//   only enter here if there are more than 3 points otherwise
+//   it means we have already the tangent
+// 
+      BuildPeriodicTangent(myPoints->Array1(),
+                          myTangents->ChangeArray1(),
+                          myTangentFlags->ChangeArray1(),
+                          myParameters->Array1()) ;
+    }
+    contact_order_array.SetValue(2,1)  ;
+    parameters.SetValue(1,myParameters->Value(1)) ;
+    parameters.SetValue(2,myParameters->Value(1)) ;
+    poles.SetValue(1,myPoints->Value(1)) ;
+    for (jj = 1 ; jj <= 2 ; jj++) {
+      a_point.SetCoord(jj,myTangents->Value(1).Coord(jj)) ;
+    }
+    poles.SetValue(2,a_point) ;
+  
+    mult_index = 2 ;
+    index = 3 ;
+    index1 = degree + 2 ;
+    if (myTangentRequest) {
+      for (ii = myTangentFlags->Lower() + 1 ; 
+          ii <= myTangentFlags->Upper() ; ii++) {
+       parameters.SetValue(index,myParameters->Value(ii)) ;
+       flatknots.SetValue(index1,myParameters->Value(ii)) ;
+       poles.SetValue(index,myPoints->Value(ii)) ;
+       index += 1  ;
+        index1 += 1 ;
+       if (myTangentFlags->Value(ii)) {
+         mults.SetValue(mult_index,mults.Value(mult_index)  + 1)   ;
+         contact_order_array(index) = 1 ;
+
+         parameters.SetValue(index,
+                             myParameters->Value(ii)) ;
+          flatknots.SetValue(index1,myParameters->Value(ii)) ;
+         for (jj = 1 ; jj <= 2 ; jj++) {
+           a_point.SetCoord(jj,myTangents->Value(ii).Coord(jj)) ;
+         }
+         poles.SetValue(index,a_point) ;
+         index  += 1 ;
+         index1 += 1 ;
+       }
+       mult_index += 1 ;
+      }
+    }
+    else {
+      index = degree + 1 ;
+      index1 = 2 ;
+      for(ii = myParameters->Lower()  ; ii <= myParameters->Upper()  ; ii++) {
+       parameters.SetValue(index1, 
+                           myParameters->Value(ii)) ;
+        flatknots.SetValue(index,
+                          myParameters->Value(ii)) ;
+       index += 1 ;
+       index1 += 1 ;
+      }
+      index = 3 ;
+      for (ii = myPoints->Lower() + 1 ; ii <= myPoints->Upper() ; ii++) {
+//
+// copy all the given points since the last one will be initialized
+// below by the first point in the array myPoints
+//
+       poles.SetValue(index,
+                      myPoints->Value(ii)) ;
+       index += 1 ;
+      }
+   
+    }
+    contact_order_array.SetValue(num_poles - 1, 1)  ;
+    parameters.SetValue(num_poles-1,
+                       myParameters->Value(myParameters->Upper())) ;
+//
+// for the periodic curve ONLY  the tangent of the first point
+// will be used since the curve should close itself at the first
+// point See BuildPeriodicTangent
+//
+    for (jj = 1 ; jj <= 2 ; jj++) {
+      a_point.SetCoord(jj,myTangents->Value(1).Coord(jj)) ;
+    }
+    poles.SetValue(num_poles-1,a_point) ;
+
+    parameters.SetValue(num_poles,
+                       myParameters->Value(myParameters->Upper())) ;
+
+    poles.SetValue(num_poles,
+                    myPoints->Value(1)) ;
+
+    
+    BSplCLib::Interpolate(degree,
+                         flatknots,
+                         parameters,
+                         contact_order_array,
+                         poles,
+                         inversion_problem) ;
+    if (!inversion_problem) {
+      TColgp_Array1OfPnt2d   newpoles(poles.Value(1),
+                                   1,
+                                   num_poles - 2) ;
+      myCurve =
+       new Geom2d_BSplineCurve(newpoles,
+                             myParameters->Array1(),
+                             mults,
+                             degree,
+                             myPeriodic) ;
+      myIsDone = Standard_True ;
+  }
+ }
+}
+   
+
+//=======================================================================
+//function : PerformNonPeriodic
+//purpose  : 
+//=======================================================================
+
+void Geom2dAPI_Interpolate::PerformNonPeriodic() 
+{
+  Standard_Integer degree,
+  ii,
+  jj,
+  index,
+  index1,
+  index2,
+  index3,
+  mult_index,
+  inversion_problem,
+  num_points,
+  num_distinct_knots,
+  num_poles  ;
+  
+  gp_Pnt2d a_point ;
+
+  num_points =
+  num_distinct_knots =
+  num_poles = myPoints->Length() ;
+  if (num_poles == 2 &&   !myTangentRequest)  {
+    degree = 1 ;
+  } 
+  else if (num_poles == 3 && !myTangentRequest) {
+    degree = 2 ;
+    num_distinct_knots = 2 ;
+  }
+  else {
+    degree = 3 ;
+    num_poles += 2 ;
+    if (myTangentRequest) 
+      for (ii = myTangentFlags->Lower() + 1 ; 
+          ii < myTangentFlags->Upper() ; ii++) {
+       if (myTangentFlags->Value(ii)) {
+         num_poles += 1 ;
+       }
+      }
+    }
+  
+  
+  TColStd_Array1OfReal     parameters(1,num_poles) ;  
+  TColStd_Array1OfReal     flatknots(1,num_poles + degree + 1) ;
+  TColStd_Array1OfInteger  mults(1,num_distinct_knots) ;
+  TColStd_Array1OfReal     knots(1,num_distinct_knots) ;
+  TColStd_Array1OfInteger  contact_order_array(1, num_poles) ;
+  TColgp_Array1OfPnt2d       poles(1,num_poles) ;
+
+  for (ii = 1 ; ii <= degree + 1 ; ii++) {
+    flatknots.SetValue(ii,myParameters->Value(1)) ;
+    flatknots.SetValue(ii + num_poles,
+                      myParameters->Value(num_points)) ;
+  }
+  for (ii = 1 ; ii <= num_poles ; ii++) {
+    contact_order_array.SetValue(ii,0)  ;
+  }
+  for (ii = 2 ; ii < num_distinct_knots ; ii++) {
+    mults.SetValue(ii,1) ; 
+  }
+  mults.SetValue(1,degree + 1) ;
+  mults.SetValue(num_distinct_knots ,degree + 1) ;
+  
+  switch (degree) {
+  case 1:
+    for (ii = 1 ; ii <= num_poles ; ii++) {
+      poles.SetValue(ii ,myPoints->Value(ii)) ;
+    }
+    myCurve =
+      new Geom2d_BSplineCurve(poles,
+                           myParameters->Array1(),
+                           mults,
+                           degree) ;
+    myIsDone = Standard_True ;
+    break ;
+  case 2:
+    knots.SetValue(1,myParameters->Value(1)) ;
+    knots.SetValue(2,myParameters->Value(3)) ;
+    for (ii = 1 ; ii <= num_poles ; ii++) {
+      poles.SetValue(ii,myPoints->Value(ii)) ;
+      
+    }
+    BSplCLib::Interpolate(degree,
+                         flatknots,
+                         myParameters->Array1(),
+                         contact_order_array,
+                         poles,
+                         inversion_problem) ;
+    if (!inversion_problem) {
+      myCurve =
+       new Geom2d_BSplineCurve(poles,
+                             knots,
+                             mults,
+                             degree) ;
+      myIsDone = Standard_True ;
+    }
+    break ;
+  case 3:
+//
+// check if the boundary conditions are set
+//
+    if (num_points >= 3) {
+//
+// cannot build the tangents with degree 3 with only 2 points
+// if those where not given in advance 
+//
+      BuildTangents(myPoints->Array1(),
+                   myTangents->ChangeArray1(),
+                   myTangentFlags->ChangeArray1(),
+                   myParameters->Array1()) ;
+    }
+    contact_order_array.SetValue(2,1)  ;
+    parameters.SetValue(1,myParameters->Value(1)) ;
+    parameters.SetValue(2,myParameters->Value(1)) ;
+    poles.SetValue(1,myPoints->Value(1)) ;
+    for (jj = 1 ; jj <= 2 ; jj++) {
+      a_point.SetCoord(jj,myTangents->Value(1).Coord(jj)) ;
+
+    }
+    poles.SetValue(2,a_point) ;
+    mult_index = 2 ;
+    index = 3 ;
+    index1 = 2 ;
+    index2 = myPoints->Lower() + 1 ;
+    index3 = degree + 2 ;
+    if (myTangentRequest) {
+      for (ii = myParameters->Lower() + 1 ; 
+          ii < myParameters->Upper() ; ii++) {
+       parameters.SetValue(index,myParameters->Value(ii)) ;
+       poles.SetValue(index,myPoints->Value(index2)) ;
+        flatknots.SetValue(index3,myParameters->Value(ii)) ; 
+       index += 1 ;
+        index3 += 1 ;
+       if (myTangentFlags->Value(index1)) {
+//
+// set the multiplicities, the order of the contact, the 
+// the flatknots,
+//
+         mults.SetValue(mult_index,mults.Value(mult_index) + 1) ;
+         contact_order_array(index) = 1 ;
+          flatknots.SetValue(index3, myParameters->Value(ii)) ;
+         parameters.SetValue(index,
+                             myParameters->Value(ii)) ;
+         for (jj = 1 ; jj <= 2 ; jj++) {
+            a_point.SetCoord(jj,myTangents->Value(ii).Coord(jj)) ;
+         }
+         poles.SetValue(index,a_point) ;
+         index += 1  ;
+         index3 += 1 ;
+       }
+       mult_index += 1 ;
+       index1 += 1 ;
+       index2 += 1 ;
+
+      }
+    }
+    else {
+      index1 = 2 ;
+      for(ii = myParameters->Lower()  ; ii <= myParameters->Upper()  ; ii++) {
+       parameters.SetValue(index1, 
+                           myParameters->Value(ii)) ;
+       index1 += 1 ;
+      }
+      index = 3 ;
+      for (ii = myPoints->Lower() + 1 ; ii <= myPoints->Upper() - 1 ; ii++) {
+       poles.SetValue(index,
+                      myPoints->Value(ii)) ;
+       index += 1 ;
+      }
+   
+   
+      index = degree + 1 ;
+      for(ii = myParameters->Lower()  ; ii <= myParameters->Upper()  ; ii++) {
+       flatknots.SetValue(index,
+                          myParameters->Value(ii)) ;
+       index += 1 ;
+      }
+    }
+    for (jj = 1 ; jj <= 2 ; jj++) {
+      a_point.SetCoord(jj,
+                      myTangents->Value(num_points).Coord(jj)) ;
+    }
+    poles.SetValue(num_poles-1 ,a_point) ;
+
+    contact_order_array.SetValue(num_poles - 1,1) ;
+    parameters.SetValue(num_poles,
+                       myParameters->Value(myParameters->Upper())) ;
+    parameters.SetValue(num_poles -1,
+                       myParameters->Value(myParameters->Upper())) ;
+
+    poles.SetValue(num_poles,
+                  myPoints->Value(num_points)) ;
+
+    BSplCLib::Interpolate(degree,
+                         flatknots,
+                         parameters,
+                         contact_order_array,
+                         poles,
+                         inversion_problem) ;
+    if (!inversion_problem) {
+      myCurve =
+       new Geom2d_BSplineCurve(poles,
+                             myParameters->Array1(),
+                             mults,
+                             degree) ;
+      myIsDone = Standard_True ;
+    }
+    break ;
+  }
+}
+//=======================================================================
+//function : Handle_Geom2d_BSplineCurve&
+//purpose  : 
+//=======================================================================
+
+const Handle(Geom2d_BSplineCurve)& Geom2dAPI_Interpolate::Curve() const 
+{
+  if ( !myIsDone) 
+    StdFail_NotDone::Raise(" ");
+  return myCurve;
+}
+
+
+
+//=======================================================================
+//function : Geom2d_BSplineCurve
+//purpose  : 
+//=======================================================================
+
+Geom2dAPI_Interpolate::operator Handle(Geom2d_BSplineCurve)() const
+{
+  return myCurve;
+}
+
+
+//=======================================================================
+//function : IsDone
+//purpose  : 
+//=======================================================================
+
+Standard_Boolean Geom2dAPI_Interpolate::IsDone() const
+{
+  return myIsDone;
+}