0025929: Make Approx_ComputeLine algorithm adaptive
[occt.git] / src / ApproxInt / ApproxInt_Approx.gxx
index 23d4b03..911e90f 100644 (file)
 #include <gp_Trsf2d.hxx>
 #include <IntSurf_PntOn2S.hxx>
 #include <Precision.hxx>
+#include <ApproxInt_KnotTools.hxx>
 
 const Standard_Integer LimRajout = 5;
-const Standard_Integer NbPntMaxDecoupage = 30 ;
-const Standard_Real RatioTol = 1.5 ;
+const Standard_Integer NbPntMaxDecoupage = 30;
+const Standard_Real RatioTol = 1.5;
 
-static Standard_Real MINABS3(Standard_Real a, Standard_Real b,Standard_Real c) { 
+//=======================================================================
+//function : MINABS3
+//purpose  : Compute minimal absolute distance to 0 from 3 values.
+//=======================================================================
+static Standard_Real MINABS3(Standard_Real a, Standard_Real b,Standard_Real c)
+{
   if(a<0.0) a=-a;
   if(b<0.0) b=-b;
   if(c<0.0) c=-c;
@@ -35,7 +41,12 @@ static Standard_Real MINABS3(Standard_Real a, Standard_Real b,Standard_Real c) {
   return(a);
 }
 
-static Standard_Real MINABS4(Standard_Real a, Standard_Real b,Standard_Real c,Standard_Real d) { 
+//=======================================================================
+//function : MINABS4
+//purpose  : Compute minimal absolute distance to 0 from 4 values.
+//=======================================================================
+static Standard_Real MINABS4(Standard_Real a, Standard_Real b,Standard_Real c,Standard_Real d)
+{
   if(a<0.0) a=-a;
   if(b<0.0) b=-b;
   if(c<0.0) c=-c;
@@ -46,1161 +57,991 @@ static Standard_Real MINABS4(Standard_Real a, Standard_Real b,Standard_Real c,St
   return(a);
 }
 
-static void  ComputeTrsf3d(const Handle(TheWLine)& theline,
-                          Standard_Real& Xo, Standard_Real& Ax,
-                          Standard_Real& Yo, Standard_Real& Ay,
-                          Standard_Real& Zo, Standard_Real& Az) {
-  Standard_Integer nbp = theline->NbPnts();
-  Standard_Real z0,z1,x0,x1,y0,y1;
-  z0=y0=x0=RealLast();
-  z1=y1=x1=RealFirst();
-  for(Standard_Integer i=1;i<=nbp;i++) { 
-    const gp_Pnt& P = theline->Point(i).Value();
-    Standard_Real  X = P.X();
-    Standard_Real  Y = P.Y();
-    Standard_Real  Z = P.Z();
-    if(X<x0) x0=X;
-    if(X>x1) x1=X;
-    if(Y<y0) y0=Y;
-    if(Y>y1) y1=Y;
-    if(Z<z0) z0=Z;
-    if(Z>z1) z1=Z;
-  }
-//-deb-  cout << "ComputeTrsf3d -- NbPnt = " << nbp << endl ;
-//-deb-  cout << "ComputeTrsf3d -- Xm = " << x0 << " Ym = " << y0 << " Zm = " << z0 << endl ;
-//-deb-  cout << "ComputeTrsf3d -- XM = " << x1 << " YM = " << y1 << " ZM = " << z1 << endl ;
-  Standard_Real dx = x1-x0;
-  Standard_Real dy = y1-y0;
-  Standard_Real dz = z1-z0;
-  Standard_Real MaxD = dx; 
-  if(MaxD < dy) MaxD=dy;
-  if(MaxD < dz) MaxD=dz;
-  Standard_Real MaxDF = 0.01*MaxD;
-
-  //-- lbr le 22 fev99 : FPE 
-  if(MaxDF<1e-12) 
-    MaxDF=1.0;
-
-
-  if(dx > MaxDF) { Ax = 1.0 / dx;    Xo = -Ax * x0;  }
-  else {     Ax = 1.0/( MaxDF) ; Xo = -Ax*x0;   }
-  if(dy > MaxDF) { Ay = 1.0 / dy;    Yo = -Ay * y0;  }
-  else {     Ay = 1.0/( MaxDF); Yo = -Ay*y0;   }
-  if(dz > MaxDF) { Az = 1.0 / dz;    Zo = -Az * z0;    }
-  else {     Az = 1.0/(MaxDF); Zo = -Az*z0;   } 
+//=======================================================================
+//function : ComputeTrsf3d
+//purpose  : 
+//=======================================================================
+static void ComputeTrsf3d(const Handle(TheWLine)& theline,
+                          Standard_Real& Xo, Standard_Real& Ax,
+                          Standard_Real& Yo, Standard_Real& Ay,
+                          Standard_Real& Zo, Standard_Real& Az)
+{
+    Standard_Integer nbp = theline->NbPnts();
+    Standard_Real z0,z1,x0,x1,y0,y1;
+    z0=y0=x0=RealLast();
+    z1=y1=x1=RealFirst();
+    for(Standard_Integer i=1;i<=nbp;i++) { 
+      const gp_Pnt& P = theline->Point(i).Value();
+      Standard_Real  X = P.X();
+      Standard_Real  Y = P.Y();
+      Standard_Real  Z = P.Z();
+      if(X<x0) x0=X;
+      if(X>x1) x1=X;
+      if(Y<y0) y0=Y;
+      if(Y>y1) y1=Y;
+      if(Z<z0) z0=Z;
+      if(Z>z1) z1=Z;
+    }
+    Standard_Real dx = x1-x0;
+    Standard_Real dy = y1-y0;
+    Standard_Real dz = z1-z0;
+    Standard_Real MaxD = dx; 
+    if(MaxD < dy) MaxD=dy;
+    if(MaxD < dz) MaxD=dz;
+    Standard_Real MaxDF = 0.01*MaxD;
+
+    if(MaxDF<1e-12) 
+      MaxDF=1.0;
+
+    if(dx > MaxDF) { Ax = 1.0 / dx;    Xo = -Ax * x0;  }
+    else {     Ax = 1.0/( MaxDF) ; Xo = -Ax*x0;   }
+    if(dy > MaxDF) { Ay = 1.0 / dy;    Yo = -Ay * y0;  }
+    else {     Ay = 1.0/( MaxDF); Yo = -Ay*y0;   }
+    if(dz > MaxDF) { Az = 1.0 / dz;    Zo = -Az * z0;  }
+    else {     Az = 1.0/(MaxDF); Zo = -Az*z0;   } 
 }
 
-static void  ComputeTrsf2d(const Handle(TheWLine)& theline,
-                          Standard_Real& Uo, Standard_Real& Au,
-                          Standard_Real& Vo, Standard_Real& Av,
-                          const Standard_Boolean onFirst,
-                          const Standard_Real UVResRatio = 1.) { 
-  Standard_Integer nbp = theline->NbPnts();
-  Standard_Real u0,u1,v0,v1;
-  u0 = v0 = RealLast();
-  u1 = v1 = RealFirst();
-  // pointer to a member-function
-  void (IntSurf_PntOn2S::* pfunc)(Standard_Real&,Standard_Real&) const;
-  if (onFirst)
-    pfunc = &IntSurf_PntOn2S::ParametersOnS1;
-  else
-    pfunc = &IntSurf_PntOn2S::ParametersOnS2;
-  for(Standard_Integer i=1;i<=nbp;i++) { 
-    const IntSurf_PntOn2S&  POn2S = theline->Point(i);
-    Standard_Real  U,V;
-    (POn2S.*pfunc)(U,V);
-    if(U<u0) u0=U;
-    if(U>u1) u1=U;
-    if(V<v0) v0=V;
-    if(V>v1) v1=V;
-  }
+//=======================================================================
+//function : ComputeTrsf2d
+//purpose  :
+//=======================================================================
+static void ComputeTrsf2d(const Handle(TheWLine)& theline,
+                          Standard_Real& Uo, Standard_Real& Au,
+                          Standard_Real& Vo, Standard_Real& Av,
+                          const Standard_Boolean onFirst,
+                          const Standard_Real UVResRatio = 1.0)
+{
+    Standard_Integer nbp = theline->NbPnts();
+    Standard_Real u0,u1,v0,v1;
+    u0 = v0 = RealLast();
+    u1 = v1 = RealFirst();
+    // pointer to a member-function
+    void (IntSurf_PntOn2S::* pfunc)(Standard_Real&,Standard_Real&) const;
+    if (onFirst)
+      pfunc = &IntSurf_PntOn2S::ParametersOnS1;
+    else
+      pfunc = &IntSurf_PntOn2S::ParametersOnS2;
+    for(Standard_Integer i=1;i<=nbp;i++) { 
+      const IntSurf_PntOn2S&  POn2S = theline->Point(i);
+      Standard_Real  U,V;
+      (POn2S.*pfunc)(U,V);
+      if(U<u0) u0=U;
+      if(U>u1) u1=U;
+      if(V<v0) v0=V;
+      if(V>v1) v1=V;
+    }
 
-  Standard_Real du = (u1-u0);
-  Standard_Real dv = (v1-v0);
+    Standard_Real du = (u1-u0);
+    Standard_Real dv = (v1-v0);
 
-  if (UVResRatio > 1.)
-    du *= UVResRatio;
-  else if (UVResRatio < 1.)
-    dv /= UVResRatio;
+    if (UVResRatio > 1.)
+      du *= UVResRatio;
+    else if (UVResRatio < 1.)
+      dv /= UVResRatio;
 
-  Standard_Real MaxUV=du;
-  if(MaxUV<dv) MaxUV=dv;
+    Standard_Real MaxUV=du;
+    if(MaxUV<dv) MaxUV=dv;
 
-  Standard_Real MaxUVF=0.01*MaxUV;
+    Standard_Real MaxUVF=0.01*MaxUV;
 
-  //-- lbr le 22 fev 99 (FPE) 
-  if(MaxUVF<1e-12) 
-    MaxUVF=1.0;
+    //-- lbr le 22 fev 99 (FPE) 
+    if(MaxUVF<1e-12) 
+      MaxUVF=1.0;
 
-  if(du > MaxUVF) { Au = 1.0 / du;    Uo = -Au * u0;  }
-  else {     Au = 1.0/(MaxUVF); Uo = -Au*u0;  }
-  if(dv > MaxUVF) { Av = 1.0 / dv;    Vo = -Av * v0;  }
-  else {     Av = 1.0/(MaxUVF); Vo = -Av*v0;  }
+    if(du > MaxUVF) { Au = 1.0 / du;    Uo = -Au * u0;  }
+    else {     Au = 1.0/(MaxUVF); Uo = -Au*u0;  }
+    if(dv > MaxUVF) { Av = 1.0 / dv;    Vo = -Av * v0;  }
+    else {     Av = 1.0/(MaxUVF); Vo = -Av*v0;  }
 }
 
+//=======================================================================
+//function : Parameters
+//purpose  :
+//=======================================================================
+static void Parameters(const ApproxInt_TheMultiLine& Line,
+                       const Standard_Integer firstP,
+                       const Standard_Integer lastP,
+                       const Approx_ParametrizationType Par,
+                       math_Vector& TheParameters)
+{
+  Standard_Integer i, j, nbP2d, nbP3d;
+  Standard_Real dist;
+  gp_Pnt P1, P2;
+  gp_Pnt2d P12d, P22d;
+
+  if (Par == Approx_ChordLength || Par == Approx_Centripetal) {
+    nbP3d = ApproxInt_TheMultiLineTool::NbP3d(Line);
+    nbP2d = ApproxInt_TheMultiLineTool::NbP2d(Line);
+    Standard_Integer mynbP3d=nbP3d, mynbP2d=nbP2d;
+    if (nbP3d == 0) mynbP3d = 1;
+    if (nbP2d == 0) mynbP2d = 1;
+
+    TheParameters(firstP) = 0.0;
+    dist = 0.0;
+    TColgp_Array1OfPnt tabP(1, mynbP3d);
+    TColgp_Array1OfPnt tabPP(1, mynbP3d);
+    TColgp_Array1OfPnt2d tabP2d(1, mynbP2d);
+    TColgp_Array1OfPnt2d tabPP2d(1, mynbP2d);
 
+    for (i = firstP+1; i <= lastP; i++) {
+      if (nbP3d != 0 && nbP2d != 0) ApproxInt_TheMultiLineTool::Value(Line, i-1, tabP, tabP2d);
+      else if (nbP2d != 0)          ApproxInt_TheMultiLineTool::Value(Line, i-1, tabP2d);
+      else if (nbP3d != 0)          ApproxInt_TheMultiLineTool::Value(Line, i-1, tabP);
 
-ApproxInt_Approx::ApproxInt_Approx():
-       myComputeLine(4,
-                    8,
-                    0.001,
-                    0.001,
-                    5,
-                    Standard_True),
-       myComputeLineBezier(4,
-                          8,
-                          0.001,
-                          0.001,
-                          5,
-                          Standard_True)
-{ 
+      if (nbP3d != 0 && nbP2d != 0) ApproxInt_TheMultiLineTool::Value(Line, i, tabPP, tabPP2d);
+      else if (nbP2d != 0)          ApproxInt_TheMultiLineTool::Value(Line, i, tabPP2d);
+      else if (nbP3d != 0)          ApproxInt_TheMultiLineTool::Value(Line, i, tabPP);
+      dist = 0;
+      for (j = 1; j <= nbP3d; j++) {
+        P1 = tabP(j);
+        P2 = tabPP(j);
+        dist += P2.Distance(P1);
+      }
+      for (j = 1; j <= nbP2d; j++) {
+        P12d = tabP2d(j);
+        P22d = tabPP2d(j);
+        dist += P22d.Distance(P12d);
+      }
+      if(Par == Approx_ChordLength)
+        TheParameters(i) = TheParameters(i-1) + dist;
+      else {// Par == Approx_Centripetal
+        TheParameters(i) = TheParameters(i-1) + Sqrt(dist);
+      }
+    }
+    for (i = firstP; i <= lastP; i++) TheParameters(i) /= TheParameters(lastP);
+  }
+  else {
+    for (i = firstP; i <= lastP; i++) {
+      TheParameters(i) = (Standard_Real(i)-firstP)/
+        (Standard_Real(lastP)-Standard_Real(firstP));
+    }
+  }
+}
+
+//=======================================================================
+//function : ApproxInt_Approx
+//purpose  : Constructor.
+//=======================================================================
+ApproxInt_Approx::ApproxInt_Approx()
+: myComputeLine(4, 8, 0.001, 0.001, 5, Standard_True),
+  myComputeLineBezier(4, 8, 0.001, 0.001, 5, Standard_True)
+{
   myComputeLine.SetContinuity(2);
-  //-- myComputeLineBezier.SetContinuity(2);
-  myApproxBez = Standard_True;
-  
-  myRelativeTol = Standard_True ;
-  myNbPntMax = NbPntMaxDecoupage ;
-  myMinFactorXYZ = 0.0;
-  myMinFactorUV  = 0.0;
-  myTolReached3d = myTolReached2d = 0.;
+  myData.myBezierApprox = Standard_True;
+
+  myRelativeTol = Standard_True;
+  myNbPntMax = NbPntMaxDecoupage;
+  myData.myMinFactorXYZ = 0.0;
+  myData.myMinFactorUV  = 0.0;
+  myTolReached3d = myTolReached2d = 0.0;
+  myUVRes1 = myUVRes2 = 1.0;
 }
-  
 
+//=======================================================================
+//function : Perform
+//purpose  : Build without surfaces information.
+//=======================================================================
 void ApproxInt_Approx::Perform(const Handle(TheWLine)& theline,
-                              const Standard_Boolean ApproxXYZ,
-                              const Standard_Boolean ApproxU1V1,
-                              const Standard_Boolean ApproxU2V2,
-                              const Standard_Integer indicemin,
-                              const Standard_Integer indicemax) { 
-  
-  myMinFactorXYZ = 0.0;
-  myMinFactorUV  = 0.0;
-  myTolReached3d = myTolReached2d = 0.;
-  
-  
+                               const Standard_Boolean ApproxXYZ,
+                               const Standard_Boolean ApproxU1V1,
+                               const Standard_Boolean ApproxU2V2,
+                               const Standard_Integer indicemin,
+                               const Standard_Integer indicemax)
+{
+  // Prepare DS.
+  prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax);
+
   Standard_Integer nbpntbez = indicemax-indicemin;
-  Standard_Integer nbpntmax = myNbPntMax;
-  Standard_Boolean OtherInter = Standard_False;
   if(nbpntbez < LimRajout) 
-    myApproxBez = Standard_False;
+    myData.myBezierApprox = Standard_False;
   else 
-    myApproxBez = Standard_True;
-  if(myApproxBez) {
-    myBezToBSpl.Reset();
-    Standard_Integer nbi = (indicemax-indicemin)/nbpntmax;
-    if(nbi>1)  { 
-      nbpntbez = (indicemax-indicemin)/nbi;
-    }
-  }
-  Standard_Integer imin = indicemin;
-  Standard_Integer imax = imin + nbpntbez;
-  myTolReached = Standard_True;
-  
-  Standard_Real Xo,Ax,Yo,Ay,Zo,Az,U1o,A1u,V1o,A1v,U2o,A2u,V2o,A2v;
-  if(ApproxXYZ) { 
-    ComputeTrsf3d(theline,Xo,Ax,Yo,Ay,Zo,Az);
-  }
-  else { 
-    Xo=Yo=Zo=0.0; Ax=Ay=Az=1.0;;
-  }
-  if(ApproxU1V1) { 
-    ComputeTrsf2d(theline,U1o,A1u,V1o,A1v,Standard_True);
-  }
-  else { 
-    U1o=V1o=0.0; A1u=A1v=1.0;
-  }
-  if(ApproxU2V2) { 
-    ComputeTrsf2d(theline,U2o,A2u,V2o,A2v,Standard_False);
-  }
-  else { 
-    U2o=V2o=0.0; A2u=A2v=1.0;
-  }
-  
-  //-deb-  cout << "ApproxInt_Approx -- NbPntMax = " << myNbPntMax    << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- Tol3D    = " << myTol3d       << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- Tol2D    = " << myTol2d       << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- RelTol   = " << (myRelativeTol ? "RELATIVE" : "ABSOLUTE") << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- Xo = " << Xo << " Yo = " << Yo << " Zo = " << Zo << endl ;
-  //-deb-  cout << "ApproxInt_Approx -- Ax = " << Ax << " Ay = " << Ay << " Az = " << Az << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- U1o = " << U1o << " V1o = " << V1o << " A1u = " << A1u << " A1v = " << A1v << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- U2o = " << U2o << " V2o = " << V2o << " A2u = " << A2u << " A2v = " << A2v << endl ; 
-  
-  Standard_Real A3d = MINABS3(Ax,Ay,Az);
-  if((A3d < myMinFactorXYZ) || (myMinFactorXYZ == 0.0)) { 
-    myMinFactorXYZ = A3d;
-  }
-  
-  Standard_Real A2d = MINABS4(A1u,A1v,A2u,A2v);
-  if((A2d < myMinFactorUV) || (myMinFactorUV == 0.0)) { 
-    myMinFactorUV = A2d;
-  }
-  
-  Standard_Boolean cut=Standard_True;
-  Approx_ParametrizationType parametrization;
-  myComputeLineBezier.Parametrization(parametrization);
+    myData.myBezierApprox = Standard_True;
+
+  // Fill data structure.
+  fillData(theline, ApproxXYZ, ApproxU1V1, ApproxU2V2);
+
+  // Build knots.
+  buildKnots(theline, NULL);
 
-  if(myRelativeTol==Standard_False) { 
-    
+  Standard_Boolean cut = Standard_True;
+  if(myRelativeTol==Standard_False)
+  {
     myComputeLine.Init(myDegMin,
-                      myDegMax,
-                      myTol3d*myMinFactorXYZ,
-                      myTol2d*myMinFactorUV,
-                      myNbIterMax,
-                      cut,
-                      parametrization);
+      myDegMax,
+      myTol3d*myData.myMinFactorXYZ,
+      myTol2d*myData.myMinFactorUV,
+      myNbIterMax,
+      cut,
+      myData.parametrization);
     myComputeLineBezier.Init(myDegMin,
-                            myDegMax,
-                            myTol3d*myMinFactorXYZ,
-                            myTol2d*myMinFactorUV,
-                            myNbIterMax,
-                            cut,
-                            parametrization);
-  }
-  
-  do {
-    ApproxInt_TheMultiLine myMultiLine(theline,
-                                      ((ApproxXYZ)? 1 : 0),
-                                      ((ApproxU1V1)? 1: 0) + ((ApproxU2V2)? 1: 0),
-                                      Xo,Ax,Yo,Ay,Zo,Az,U1o,A1u,V1o,A1v,U2o,A2u,V2o,A2v,
-                                      ApproxU1V1,
-                                      imin,
-                                      imax);
-    
-    if(myApproxBez) { 
-      myComputeLineBezier.Perform(myMultiLine);
-      if (myComputeLineBezier.NbMultiCurves() == 0)
-       return;
-      myTolReached&=myComputeLineBezier.IsToleranceReached();
-    }
-    else { 
-      myComputeLine.Perform(myMultiLine);
-    }
-    UpdateTolReached();
-    
-    Standard_Integer indice3d,indice2d1,indice2d2;
-    indice3d = 1; 
-    indice2d1= 2;
-    indice2d2= 3;
-    if(!ApproxXYZ)  { indice2d1--; indice2d2--; } 
-    if(!ApproxU1V1) { indice2d2--; } 
-    if(ApproxXYZ) { 
-      Standard_Real ax,bx,ay,by,az,bz;
-      ax = 1.0/Ax;   bx = -Xo*ax;
-      ay = 1.0/Ay;   by = -Yo*ay;
-      az = 1.0/Az;   bz = -Zo*az;
-      if(myApproxBez) {
-       for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--) { 
-         myComputeLineBezier.ChangeValue(nbmc).Transform(indice3d,bx,ax,by,ay,bz,az);
-       }
-      }
-      else { 
-       myComputeLine.ChangeValue().Transform(indice3d,bx,ax,by,ay,bz,az);
-      }
-    }
-    if(ApproxU1V1) { 
-      Standard_Real ax,bx,ay,by;
-      ax = 1.0/A1u;   bx = -U1o*ax;
-      ay = 1.0/A1v;   by = -V1o*ay;
-      if(myApproxBez) {
-       for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--) { 
-         myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d1,bx,ax,by,ay);
-       }
-      }
-      else { 
-       myComputeLine.ChangeValue().Transform2d(indice2d1,bx,ax,by,ay);
-      }
-    }
-    if(ApproxU2V2) { 
-      Standard_Real ax,bx,ay,by;
-      ax = 1.0/A2u;   bx = -U2o*ax;
-      ay = 1.0/A2v;   by = -V2o*ay;
-      if(myApproxBez) { 
-       for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--) { 
-         myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d2,bx,ax,by,ay);
-       }
-      }
-      else { 
-       myComputeLine.ChangeValue().Transform2d(indice2d2,bx,ax,by,ay);
-      }
-    }
-    
-    OtherInter = Standard_False;
-    if(myApproxBez) {
-      for(Standard_Integer nbmc = 1; 
-         nbmc <= myComputeLineBezier.NbMultiCurves() ;
-         nbmc++) { 
-       myBezToBSpl.Append(myComputeLineBezier.Value(nbmc));
-      }
-      if(imax<indicemax) { 
-       imin = imax;    
-       imax = imin+nbpntbez;
-       OtherInter = Standard_True;
-       if((indicemax-imax)<(nbpntbez/2)) { 
-         imax = indicemax;
-       }
-      }
-    }
-  }
-  while(OtherInter);
-  if(myApproxBez) { 
-    myBezToBSpl.Perform();
+      myDegMax,
+      myTol3d*myData.myMinFactorXYZ,
+      myTol2d*myData.myMinFactorUV,
+      myNbIterMax,
+      cut,
+      myData.parametrization);
   }
+
+  buildCurve(theline, NULL);
 }
 
+//=======================================================================
+//function : Perform
+//purpose  : Param-Param perform.
+//=======================================================================
 void ApproxInt_Approx::Perform(const ThePSurface& Surf1,
-                              const ThePSurface& Surf2,
-                              const Handle(TheWLine)& theline,
-                              const Standard_Boolean ApproxXYZ,
-                              const Standard_Boolean ApproxU1V1,
-                              const Standard_Boolean ApproxU2V2,
-                              const Standard_Integer indicemin,
-                              const Standard_Integer indicemax) {
-  myMinFactorXYZ = 0.0;
-  myMinFactorUV  = 0.0;
-  myTolReached3d = myTolReached2d = 0.;
+                               const ThePSurface& Surf2,
+                               const Handle(TheWLine)& theline,
+                               const Standard_Boolean ApproxXYZ,
+                               const Standard_Boolean ApproxU1V1,
+                               const Standard_Boolean ApproxU2V2,
+                               const Standard_Integer indicemin,
+                               const Standard_Integer indicemax) 
+{
 
   GeomAbs_SurfaceType typeS1 = ThePSurfaceTool::GetType(Surf1);
   GeomAbs_SurfaceType typeS2 = ThePSurfaceTool::GetType(Surf2);
   if ((typeS1 != GeomAbs_Plane    &&
        typeS1 != GeomAbs_Cylinder &&
        typeS1 != GeomAbs_Sphere   &&
-       typeS1 != GeomAbs_Cone) 
-      &&
+       typeS1 != GeomAbs_Cone)    &&
       (typeS2 != GeomAbs_Plane    &&
        typeS2 != GeomAbs_Cylinder &&
        typeS2 != GeomAbs_Sphere   &&
-       typeS2 != GeomAbs_Cone)) { 
-    
-    //------------------------------------------------------------
-    //-- Construction du SvSurfaces
-    //------------------------------------------------------------
+       typeS2 != GeomAbs_Cone))
+  {
+    // Prepare DS.
+    prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax);
+
+    // Non-analytical case: Param-Param perform.
     ApproxInt_ThePrmPrmSvSurfaces myPrmPrmSvSurfaces(Surf1,Surf2);
-    //------------------------------------------------------------
-    //-- Construction de la MultiLine
-    //------------------------------------------------------------
+
     Standard_Integer nbpntbez = indicemax-indicemin;
-    Standard_Integer nbpntmax = myNbPntMax;
-    Standard_Boolean OtherInter = Standard_False;
-    
     if(nbpntbez < LimRajout) 
-      myApproxBez = Standard_False;
+      myData.myBezierApprox = Standard_False;
     else 
-      myApproxBez = Standard_True;
-    
-    Standard_Address ptrsvsurf = NULL;
+      myData.myBezierApprox = Standard_True;
+
     Standard_Boolean cut = Standard_True;
-    if(nbpntbez < LimRajout) {   
+    if(nbpntbez < LimRajout)
+    {
       cut = Standard_False;
-      //-- cout<<" ApproxInt : Nb de points = "<<nbpntbez<<" Pas de rajout "<<endl;
-    }
-    ptrsvsurf = &myPrmPrmSvSurfaces;
-    
-
-    if(myApproxBez) { 
-      myBezToBSpl.Reset();
-      Standard_Integer nbi = (indicemax-indicemin)/nbpntmax;
-      if(nbi>1)  { 
-       nbpntbez = (indicemax-indicemin)/nbi;
-      }
     }
-    Standard_Integer imin = indicemin;
-    Standard_Integer imax = imin + nbpntbez;
-    myTolReached = Standard_True;
 
+    Standard_Real aS1URes = ThePSurfaceTool::UResolution(Surf1, 1.0),
+                  aS1VRes = ThePSurfaceTool::VResolution(Surf1, 1.0),
+                  aS2URes = ThePSurfaceTool::UResolution(Surf2, 1.0),
+                  aS2VRes = ThePSurfaceTool::VResolution(Surf2, 1.0);
+    if(ApproxU1V1)
+      myUVRes1 = aS1URes / aS1VRes;
+    if(ApproxU2V2)
+      myUVRes2 = aS2URes / aS2VRes;
 
-    Standard_Real Xo,Ax,Yo,Ay,Zo,Az,U1o,A1u,V1o,A1v,U2o,A2u,V2o,A2v;
-    if(ApproxXYZ) { 
-      ComputeTrsf3d(theline,Xo,Ax,Yo,Ay,Zo,Az);
-    }
-    else { 
-      Xo=Yo=Zo=0.0; Ax=Ay=Az=1.0;;
-    }
-    if(ApproxU1V1) { 
-      Standard_Real UVResRatio = ThePSurfaceTool::UResolution(Surf1,1.)/
-                                 ThePSurfaceTool::VResolution(Surf1,1.);
-      ComputeTrsf2d(theline,U1o,A1u,V1o,A1v,Standard_True,UVResRatio);
-    }
-    else { 
-      U1o=V1o=0.0; A1u=A1v=1.0;
-    }      
-    if(ApproxU2V2) { 
-      Standard_Real UVResRatio = ThePSurfaceTool::UResolution(Surf2,1.)/
-                                 ThePSurfaceTool::VResolution(Surf2,1.);
-      ComputeTrsf2d(theline,U2o,A2u,V2o,A2v,Standard_False,UVResRatio);
-    }
-    else { 
-      U2o=V2o=0.0; A2u=A2v=1.0;
-    }
+    // Fill data structure.
+    fillData(theline, ApproxXYZ, ApproxU1V1, ApproxU2V2);
 
-//-deb-  cout << "ApproxInt_Approx -- NbPntMax = " << myNbPntMax    << endl ; 
-//-deb-  cout << "ApproxInt_Approx -- Tol3D    = " << myTol3d       << endl ; 
-//-deb-  cout << "ApproxInt_Approx -- Tol2D    = " << myTol2d       << endl ; 
-//-deb-  cout << "ApproxInt_Approx -- RelTol   = " << (myRelativeTol ? "RELATIVE" : "ABSOLUTE") << endl ; 
-//-deb-  cout << "ApproxInt_Approx -- Xo = " << Xo << " Yo = " << Yo << " Zo = " << Zo << endl ;
-//-deb-  cout << "ApproxInt_Approx -- Ax = " << Ax << " Ay = " << Ay << " Az = " << Az << endl ; 
-//-deb-  cout << "ApproxInt_Approx -- U1o = " << U1o << " V1o = " << V1o << " A1u = " << A1u << " A1v = " << A1v << endl ; 
-//-deb-  cout << "ApproxInt_Approx -- U2o = " << U2o << " V2o = " << V2o << " A2u = " << A2u << " A2v = " << A2v << endl ; 
-    
-    
-    Standard_Real A3d = MINABS3(Ax,Ay,Az);
-    if((A3d < myMinFactorXYZ) || (myMinFactorXYZ == 0.0)) { 
-      myMinFactorXYZ = A3d;
-    }
-    
-    Standard_Real A2d = MINABS4(A1u,A1v,A2u,A2v);
-    if((A2d < myMinFactorUV) || (myMinFactorUV == 0.0)) { 
-      myMinFactorUV = A2d;
-    }
-    
+    // Build knots.
+    Standard_Address ptrsvsurf = &myPrmPrmSvSurfaces;
+    buildKnots(theline, ptrsvsurf);
 
-    Approx_ParametrizationType parametrization;
-    myComputeLineBezier.Parametrization(parametrization);
-
-    if(myRelativeTol==Standard_False) { 
+    if(myRelativeTol==Standard_False)
+    {
       myComputeLine.Init(myDegMin,
-                        myDegMax,
-                        myTol3d*myMinFactorXYZ,
-                        myTol2d*myMinFactorUV,
-                        myNbIterMax,
-                        cut,
-                        parametrization);
+        myDegMax,
+        myTol3d*myData.myMinFactorXYZ,
+        myTol2d*myData.myMinFactorUV,
+        myNbIterMax,
+        cut,
+        myData.parametrization);
       myComputeLineBezier.Init(myDegMin,
-                              myDegMax,
-                              myTol3d*myMinFactorXYZ,
-                              myTol2d*myMinFactorUV,
-                              myNbIterMax,
-                              cut,
-                              parametrization);
+        myDegMax,
+        myTol3d*myData.myMinFactorXYZ,
+        myTol2d*myData.myMinFactorUV,
+        myNbIterMax,
+        cut,
+        myData.parametrization);
     }
-    else { 
+    else
+    {
       myComputeLine.Init(myDegMin,
-                        myDegMax,
-                        myTol3d,
-                        myTol2d,
-                        myNbIterMax,
-                        cut,
-                        parametrization);
+        myDegMax,
+        myTol3d,
+        myTol2d,
+        myNbIterMax,
+        cut,
+        myData.parametrization);
       myComputeLineBezier.Init(myDegMin,
-                              myDegMax,
-                              myTol3d,
-                              myTol2d,
-                              myNbIterMax,
-                              cut,
-                              parametrization);
-    }     
-
-
-
-    
-    do {
-      ApproxInt_TheMultiLine myMultiLine(theline,
-                                        ptrsvsurf,
-                                        ((ApproxXYZ)? 1 : 0),
-                                        ((ApproxU1V1)? 1: 0) + ((ApproxU2V2)? 1: 0),
-                                        Xo,Ax,Yo,Ay,Zo,Az,U1o,A1u,V1o,A1v,U2o,A2u,V2o,A2v,
-                                        ApproxU1V1,
-                                        imin,
-                                        imax);
-      
-      if(myApproxBez) { 
-       myComputeLineBezier.Perform(myMultiLine);
-       if (myComputeLineBezier.NbMultiCurves() == 0)
-         return;
-       myTolReached&=myComputeLineBezier.IsToleranceReached();
-      }
-      else { 
-       myComputeLine.Perform(myMultiLine);
-      }
-      UpdateTolReached();
-      
-      Standard_Integer indice3d,indice2d1,indice2d2;
-      indice3d = 1; 
-      indice2d1= 2;
-      indice2d2= 3;
-      if(!ApproxXYZ)  { indice2d1--; indice2d2--; } 
-      if(!ApproxU1V1) { indice2d2--; } 
-      if(ApproxXYZ) { 
-       Standard_Real ax,bx,ay,by,az,bz;
-       ax = 1.0/Ax;   bx = -Xo*ax;
-       ay = 1.0/Ay;   by = -Yo*ay;
-       az = 1.0/Az;   bz = -Zo*az;
-       if(myApproxBez) { 
-         for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--) { 
-           myComputeLineBezier.ChangeValue(nbmc).Transform(indice3d,bx,ax,by,ay,bz,az);
-         }
-       }
-       else { 
-         myComputeLine.ChangeValue().Transform(indice3d,bx,ax,by,ay,bz,az);
-       }
-      }
-      if(ApproxU1V1) { 
-       Standard_Real ax,bx,ay,by;
-       ax = 1.0/A1u;   bx = -U1o*ax;
-       ay = 1.0/A1v;   by = -V1o*ay;
-       if(myApproxBez) { 
-         for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--) { 
-           myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d1,bx,ax,by,ay);
-         }
-       }
-       else { 
-         myComputeLine.ChangeValue().Transform2d(indice2d1,bx,ax,by,ay);
-       }
-      }
-      if(ApproxU2V2) { 
-       Standard_Real ax,bx,ay,by;
-       ax = 1.0/A2u;   bx = -U2o*ax;
-       ay = 1.0/A2v;   by = -V2o*ay;
-       if(myApproxBez) { 
-         for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--) { 
-           myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d2,bx,ax,by,ay);
-         }
-       }
-       else { 
-         myComputeLine.ChangeValue().Transform2d(indice2d2,bx,ax,by,ay);
-       }
-      }
-      OtherInter = Standard_False;
-      if(myApproxBez) { 
-       for(Standard_Integer nbmc = 1; 
-         nbmc <= myComputeLineBezier.NbMultiCurves() ;
-         nbmc++) { 
-         myBezToBSpl.Append(myComputeLineBezier.Value(nbmc));
-       }
-       if(imax<indicemax) { 
-         imin = imax;    
-         imax = imin+nbpntbez;
-         OtherInter = Standard_True;
-         if((indicemax-imax)<(nbpntbez/2)) { 
-           imax = indicemax;
-         }
-       }
-      }
-    }
-    while(OtherInter);
-    if(myApproxBez) { 
-      myBezToBSpl.Perform();
+        myDegMax,
+        myTol3d,
+        myTol2d,
+        myNbIterMax,
+        cut,
+        myData.parametrization);
     }
 
+    buildCurve(theline, ptrsvsurf);
   }
-  else { 
+  else
+  {
     IntSurf_Quadric Quad;
     Standard_Boolean SecondIsImplicit=Standard_False;
-    switch (typeS1) {
-      
+    switch (typeS1)
+    {
+
     case GeomAbs_Plane:
       Quad.SetValue(ThePSurfaceTool::Plane(Surf1));
       break;
-      
+
     case GeomAbs_Cylinder:
       Quad.SetValue(ThePSurfaceTool::Cylinder(Surf1));
       break;
-      
+
     case GeomAbs_Sphere:
       Quad.SetValue(ThePSurfaceTool::Sphere(Surf1));
       break;
-      
+
     case GeomAbs_Cone:
       Quad.SetValue(ThePSurfaceTool::Cone(Surf1));
       break;
 
     default:
       {
-       SecondIsImplicit = Standard_True;
-       switch (typeS2) {
-       case GeomAbs_Plane:
-         Quad.SetValue(ThePSurfaceTool::Plane(Surf2));
-         break;
-         
-       case GeomAbs_Cylinder:
-         Quad.SetValue(ThePSurfaceTool::Cylinder(Surf2));
-         break;
-         
-       case GeomAbs_Sphere:
-         Quad.SetValue(ThePSurfaceTool::Sphere(Surf2));
-         break;
-         
-       case GeomAbs_Cone:
-         Quad.SetValue(ThePSurfaceTool::Cone(Surf2));
-         break;
-         
-       default:
-         break;
-       }
+        SecondIsImplicit = Standard_True;
+        switch (typeS2)
+        {
+        case GeomAbs_Plane:
+          Quad.SetValue(ThePSurfaceTool::Plane(Surf2));
+          break;
+
+        case GeomAbs_Cylinder:
+          Quad.SetValue(ThePSurfaceTool::Cylinder(Surf2));
+          break;
+
+        case GeomAbs_Sphere:
+          Quad.SetValue(ThePSurfaceTool::Sphere(Surf2));
+          break;
+
+        case GeomAbs_Cone:
+          Quad.SetValue(ThePSurfaceTool::Cone(Surf2));
+          break;
+
+        default:
+          break;
+        }
       }
       break;
     } 
-    if(SecondIsImplicit) {
+    if(SecondIsImplicit)
+    {
       Perform(Surf1,Quad,theline,ApproxXYZ,ApproxU1V1,ApproxU2V2,indicemin,indicemax);
     }
-    else {
+    else
+    {
       Perform(Quad,Surf2,theline,ApproxXYZ,ApproxU1V1,ApproxU2V2,indicemin,indicemax);
     }
   }
 }
-//--------------------------------------------------------------------------------
+
+//=======================================================================
+//function : SetParameters
+//purpose  :
+//=======================================================================
 void ApproxInt_Approx::SetParameters(const Standard_Real     Tol3d,
-                                    const Standard_Real     Tol2d,
-                                    const Standard_Integer  DegMin,
-                                    const Standard_Integer  DegMax,
-                                    const Standard_Integer  NbIterMax,
-                                    const Standard_Boolean  ApproxWithTangency,
-                                    const Approx_ParametrizationType Parametrization) {
-  myWithTangency = ApproxWithTangency;
-  myTol3d        = Tol3d / RatioTol;
-  myTol2d        = Tol2d / RatioTol;
-  myDegMin       = DegMin;
-  myDegMax       = DegMax;
-  myNbIterMax    = NbIterMax;
-  myComputeLine.Init(myDegMin,
-                    myDegMax,
-                    myTol3d,
-                    myTol2d,
-                    myNbIterMax,
-                    Standard_True,
-                    Parametrization);
-
-  if(!ApproxWithTangency) { 
-    myComputeLine.SetConstraints(AppParCurves_PassPoint,AppParCurves_PassPoint);
-  }
-  myComputeLineBezier.Init(myDegMin,
-                          myDegMax,
-                          myTol3d,
-                          myTol2d,
-                          myNbIterMax,
-                          Standard_True,
-                          Parametrization);
-  if(!ApproxWithTangency) { 
-    myComputeLineBezier.SetConstraints(AppParCurves_PassPoint,AppParCurves_PassPoint);
-  }
-  myApproxBez = Standard_True;
+                                     const Standard_Real     Tol2d,
+                                     const Standard_Integer  DegMin,
+                                     const Standard_Integer  DegMax,
+                                     const Standard_Integer  NbIterMax,
+                                     const Standard_Boolean  ApproxWithTangency,
+                                     const Approx_ParametrizationType Parametrization)
+{
+    myWithTangency = ApproxWithTangency;
+    myTol3d        = Tol3d / RatioTol;
+    myTol2d        = Tol2d / RatioTol;
+    myDegMin       = DegMin;
+    myDegMax       = DegMax;
+    myNbIterMax    = NbIterMax;
+    myComputeLine.Init(myDegMin,
+      myDegMax,
+      myTol3d,
+      myTol2d,
+      myNbIterMax,
+      Standard_True,
+      Parametrization);
+
+    if(!ApproxWithTangency) { 
+      myComputeLine.SetConstraints(AppParCurves_PassPoint,AppParCurves_PassPoint);
+    }
+    myComputeLineBezier.Init(myDegMin,
+      myDegMax,
+      myTol3d,
+      myTol2d,
+      myNbIterMax,
+      Standard_True,
+      Parametrization);
+    if(!ApproxWithTangency)
+    {
+      myComputeLineBezier.SetConstraints(AppParCurves_PassPoint,AppParCurves_PassPoint);
+    }
+    myData.myBezierApprox = Standard_True;
 }
 
+//=======================================================================
+//function : SetParameters
+//purpose  : Set parameters with RelativeTol flag and NbPntMax value.
+//=======================================================================
 void ApproxInt_Approx::SetParameters(const Standard_Real     Tol3d,
-                                    const Standard_Real     Tol2d,
-                                    const Standard_Boolean  RelativeTol,
-                                    const Standard_Integer  DegMin,
-                                    const Standard_Integer  DegMax,
-                                    const Standard_Integer  NbIterMax,
-                                    const Standard_Integer  NbPntMax,
-                                    const Standard_Boolean  ApproxWithTangency,
-                                    const Approx_ParametrizationType Parametrization) 
+                                     const Standard_Real     Tol2d,
+                                     const Standard_Boolean  RelativeTol,
+                                     const Standard_Integer  DegMin,
+                                     const Standard_Integer  DegMax,
+                                     const Standard_Integer  NbIterMax,
+                                     const Standard_Integer  NbPntMax,
+                                     const Standard_Boolean  ApproxWithTangency,
+                                     const Approx_ParametrizationType Parametrization) 
 {
   myNbPntMax = NbPntMax ;
   myRelativeTol = RelativeTol ;
   SetParameters (Tol3d, Tol2d, DegMin, DegMax, NbIterMax, ApproxWithTangency, Parametrization) ;
 }
 
-//--------------------------------------------------------------------------------
+//=======================================================================
+//function : Perform
+//purpose  : Param-Analytic perform.
+//=======================================================================
 void ApproxInt_Approx::Perform(const ThePSurface& PSurf,
-                              const TheISurface& ISurf,
-                              const Handle(TheWLine)& theline,
-                              const Standard_Boolean ApproxXYZ,
-                              const Standard_Boolean ApproxU1V1,
-                              const Standard_Boolean ApproxU2V2,
-                              const Standard_Integer indicemin,
-                              const Standard_Integer indicemax)
+                               const TheISurface& ISurf,
+                               const Handle(TheWLine)& theline,
+                               const Standard_Boolean ApproxXYZ,
+                               const Standard_Boolean ApproxU1V1,
+                               const Standard_Boolean ApproxU2V2,
+                               const Standard_Integer indicemin,
+                               const Standard_Integer indicemax)
 {
-  myMinFactorXYZ = 0.0;
-  myMinFactorUV  = 0.0;
-  myTolReached3d = myTolReached2d = 0.;
-  
+  // Prepare DS.
+  prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax);
+
+  // Non-analytical case: Param-Analytic perform.
   ApproxInt_TheImpPrmSvSurfaces myImpPrmSvSurfaces(PSurf,ISurf);
+
   Standard_Integer nbpntbez = indicemax-indicemin;
-  Standard_Integer nbpntmax = myNbPntMax;
-  Standard_Boolean OtherInter = Standard_False;
   if(nbpntbez < LimRajout) 
-    myApproxBez = Standard_False;
+    myData.myBezierApprox = Standard_False;
   else 
-    myApproxBez = Standard_True;
-  
-  Standard_Address ptrsvsurf = NULL;
+    myData.myBezierApprox = Standard_True;
+
   Standard_Boolean cut = Standard_True;
-  if(nbpntbez < LimRajout) {   
+  if(nbpntbez < LimRajout)
+  {
     cut = Standard_False;
-    //-- cout<<" ApproxInt : Nb de points = "<<nbpntbez<<" Pas de rajout "<<endl;
   }
 
+  Standard_Real aS1URes = ThePSurfaceTool::UResolution(PSurf, 1.0),
+                aS1VRes = ThePSurfaceTool::VResolution(PSurf, 1.0);
+  if(ApproxU1V1)
+    myUVRes1 = aS1URes / aS1VRes;
 
-  Approx_ParametrizationType parametrization;
-  myComputeLineBezier.Parametrization(parametrization);
-
+  // Fill data structure.
+  fillData(theline, ApproxXYZ, ApproxU1V1, ApproxU2V2);
 
-  ptrsvsurf = &myImpPrmSvSurfaces;  
-  myComputeLine.Init(myDegMin,
-                    myDegMax,
-                    myTol3d,
-                    myTol2d,
-                    myNbIterMax,
-                    cut,
-                    parametrization);
-
-  myComputeLineBezier.Init(myDegMin,
-                          myDegMax,
-                          myTol3d,
-                          myTol2d,
-                          myNbIterMax,
-                          cut,
-                          parametrization);
-  if(myApproxBez) { 
-    myBezToBSpl.Reset();
-    Standard_Integer nbi = (indicemax-indicemin)/nbpntmax;
-    if(nbi>1)  { 
-      nbpntbez = (indicemax-indicemin)/nbi;
-    }
-  }
-  Standard_Integer imin = indicemin;
-  Standard_Integer imax = imin + nbpntbez;
-  myTolReached = Standard_True;
-  Standard_Real Xo,Ax,Yo,Ay,Zo,Az,U1o,A1u,V1o,A1v,U2o,A2u,V2o,A2v;
-  if(ApproxXYZ) { 
-    ComputeTrsf3d(theline,Xo,Ax,Yo,Ay,Zo,Az);
-  }
-  else { 
-    Xo=Yo=Zo=0.0; Ax=Ay=Az=1.0;;
-  }
-  if(ApproxU1V1) { 
-    Standard_Real UVResRatio = ThePSurfaceTool::UResolution(PSurf,1.)/
-                               ThePSurfaceTool::VResolution(PSurf,1.);
-    ComputeTrsf2d(theline,U1o,A1u,V1o,A1v,Standard_True,UVResRatio);
-  }
-  else { 
-    U1o=V1o=0.0; A1u=A1v=1.0;
-  }
-  if(ApproxU2V2) { 
-    ComputeTrsf2d(theline,U2o,A2u,V2o,A2v,Standard_False);
-  }
-  else { 
-    U2o=V2o=0.0; A2u=A2v=1.0;
-  }
-  
-  //-deb-  cout << "ApproxInt_Approx -- NbPntMax = " << myNbPntMax    << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- Tol3D    = " << myTol3d       << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- Tol2D    = " << myTol2d       << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- RelTol   = " << (myRelativeTol ? "RELATIVE" : "ABSOLUTE") << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- Xo = " << Xo << " Yo = " << Yo << " Zo = " << Zo << endl ;
-  //-deb-  cout << "ApproxInt_Approx -- Ax = " << Ax << " Ay = " << Ay << " Az = " << Az << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- U1o = " << U1o << " V1o = " << V1o << " A1u = " << A1u << " A1v = " << A1v << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- U2o = " << U2o << " V2o = " << V2o << " A2u = " << A2u << " A2v = " << A2v << endl ; 
-  
-  
-  Standard_Real A3d = MINABS3(Ax,Ay,Az);
-  if((A3d < myMinFactorXYZ) || (myMinFactorXYZ == 0.0)) { 
-    myMinFactorXYZ = A3d;
-  }
-  
-  Standard_Real A2d = MINABS4(A1u,A1v,A2u,A2v);
-  if((A2d < myMinFactorUV) || (myMinFactorUV == 0.0)) { 
-    myMinFactorUV = A2d;
-  }
-  
-  myComputeLineBezier.Parametrization(parametrization);
+  // Build knots.
+  Standard_Address ptrsvsurf = &myImpPrmSvSurfaces;
+  buildKnots(theline, ptrsvsurf);
 
-  if(myRelativeTol==Standard_False) { 
+  if(myRelativeTol==Standard_False)
+  {
     myComputeLine.Init(myDegMin,
-                      myDegMax,
-                      myTol3d*myMinFactorXYZ,
-                      myTol2d*myMinFactorUV,
-                      myNbIterMax,
-                      cut,
-                      parametrization);
+      myDegMax,
+      myTol3d*myData.myMinFactorXYZ,
+      myTol2d*myData.myMinFactorUV,
+      myNbIterMax,
+      cut,
+      myData.parametrization);
     myComputeLineBezier.Init(myDegMin,
-                            myDegMax,
-                            myTol3d*myMinFactorXYZ,
-                            myTol2d*myMinFactorUV,
-                            myNbIterMax,
-                            cut,
-                            parametrization);
+      myDegMax,
+      myTol3d*myData.myMinFactorXYZ,
+      myTol2d*myData.myMinFactorUV,
+      myNbIterMax,
+      cut,
+      myData.parametrization);
   }
-  else { 
+  else
+  {
     myComputeLine.Init(myDegMin,
-                      myDegMax,
-                      myTol3d,
-                      myTol2d,
-                      myNbIterMax,
-                      cut,
-                      parametrization);
+      myDegMax,
+      myTol3d,
+      myTol2d,
+      myNbIterMax,
+      cut,
+      myData.parametrization);
     myComputeLineBezier.Init(myDegMin,
-                            myDegMax,
-                            myTol3d,
-                            myTol2d,
-                            myNbIterMax,
-                            cut,
-                            parametrization);
-  }     
-  
-  
-  do {
-    
-    ApproxInt_TheMultiLine myMultiLine(theline,
-                                      ptrsvsurf,
-                                      ((ApproxXYZ)? 1 : 0),
-                                      ((ApproxU1V1)? 1: 0) + ((ApproxU2V2)? 1: 0),
-                                      Xo,Ax,Yo,Ay,Zo,Az,U1o,A1u,V1o,A1v,U2o,A2u,V2o,A2v,
-                                      ApproxU1V1,
-                                      imin,
-                                      imax);
-    if(myApproxBez) { 
-      myComputeLineBezier.Perform(myMultiLine);
-      if (myComputeLineBezier.NbMultiCurves() == 0)
-       return;
-      myTolReached&=myComputeLineBezier.IsToleranceReached();
-    }
-    else { 
-      myComputeLine.Perform(myMultiLine);
-    }
-    UpdateTolReached();
-    Standard_Integer indice3d,indice2d1,indice2d2;
-    indice3d = 1; 
-    indice2d1= 2;
-    indice2d2= 3;
-    if(!ApproxXYZ)  { indice2d1--; indice2d2--; } 
-    if(!ApproxU1V1) { indice2d2--; } 
-    if(ApproxXYZ) { 
-      Standard_Real ax,bx,ay,by,az,bz;
-      ax = 1.0/Ax;   bx = -Xo*ax;
-      ay = 1.0/Ay;   by = -Yo*ay;
-      az = 1.0/Az;   bz = -Zo*az;
-      if(myApproxBez) { 
-       for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--) { 
-         myComputeLineBezier.ChangeValue(nbmc).Transform(indice3d,bx,ax,by,ay,bz,az);
-       }
-      }
-      else { 
-       myComputeLine.ChangeValue().Transform(indice3d,bx,ax,by,ay,bz,az);
-      }
-    }
-    if(ApproxU1V1) { 
-      Standard_Real ax,bx,ay,by;
-      ax = 1.0/A1u;   bx = -U1o*ax;
-      ay = 1.0/A1v;   by = -V1o*ay;
-      if(myApproxBez) { 
-       for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--) { 
-         myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d1,bx,ax,by,ay);
-       }
-      }
-      else { 
-       myComputeLine.ChangeValue().Transform2d(indice2d1,bx,ax,by,ay);
-      }
-    }
-    if(ApproxU2V2) { 
-      Standard_Real ax,bx,ay,by;
-      ax = 1.0/A2u;   bx = -U2o*ax;
-      ay = 1.0/A2v;   by = -V2o*ay;
-      if(myApproxBez) { 
-       for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--) { 
-         myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d2,bx,ax,by,ay);
-       }
-      }
-      else { 
-       myComputeLine.ChangeValue().Transform2d(indice2d2,bx,ax,by,ay);
-      }
-    }
-    OtherInter = Standard_False;
-    if(myApproxBez) { 
-      for(Standard_Integer nbmc = 1; 
-         nbmc <= myComputeLineBezier.NbMultiCurves() ;
-         nbmc++) { 
-       myBezToBSpl.Append(myComputeLineBezier.Value(nbmc));
-      }
-      if(imax<indicemax) { 
-       imin = imax;    
-       imax = imin+nbpntbez;
-       OtherInter = Standard_True;
-       if((indicemax-imax)<(nbpntbez/2)) { 
-         imax = indicemax;
-       }
-      }
-    }
-  }
-  while(OtherInter);
-  if(myApproxBez) { 
-    myBezToBSpl.Perform();
+      myDegMax,
+      myTol3d,
+      myTol2d,
+      myNbIterMax,
+      cut,
+      myData.parametrization);
   }
+
+  buildCurve(theline, ptrsvsurf);
 }
-//--------------------------------------------------------------------------------
+
+//=======================================================================
+//function : Perform
+//purpose  : Analytic-Param perform.
+//=======================================================================
 void ApproxInt_Approx::Perform(const TheISurface& ISurf,
-                              const ThePSurface& PSurf,
-                              const Handle(TheWLine)& theline,
-                              const Standard_Boolean ApproxXYZ,
-                              const Standard_Boolean ApproxU1V1,
-                              const Standard_Boolean ApproxU2V2,
-                              const Standard_Integer indicemin,
-                              const Standard_Integer indicemax)
+                               const ThePSurface& PSurf,
+                               const Handle(TheWLine)& theline,
+                               const Standard_Boolean ApproxXYZ,
+                               const Standard_Boolean ApproxU1V1,
+                               const Standard_Boolean ApproxU2V2,
+                               const Standard_Integer indicemin,
+                               const Standard_Integer indicemax)
 {
+  // Prepare DS.
+  prepareDS(ApproxXYZ, ApproxU1V1, ApproxU2V2, indicemin, indicemax);
+
+  // Non-analytical case: Analytic-Param perform.
+  ApproxInt_TheImpPrmSvSurfaces myImpPrmSvSurfaces(ISurf, PSurf);
 
-  myMinFactorXYZ = 0.0;
-  myMinFactorUV  = 0.0;
-  myTolReached3d = myTolReached2d = 0.;
-  
-  ApproxInt_TheImpPrmSvSurfaces myImpPrmSvSurfaces(ISurf,PSurf);
   Standard_Integer nbpntbez = indicemax-indicemin;
-  
-  Standard_Address ptrsvsurf = NULL;
-  Standard_Boolean cut = Standard_True;
   if(nbpntbez < LimRajout) 
-    myApproxBez = Standard_False;
+    myData.myBezierApprox = Standard_False;
   else 
-    myApproxBez = Standard_True;
-  
-  if(nbpntbez < LimRajout) {   
+    myData.myBezierApprox = Standard_True;
+
+  Standard_Boolean cut = Standard_True;
+  if(nbpntbez < LimRajout)
+  {
     cut = Standard_False;
-    //-- cout<<" ApproxInt : Nb de points = "<<nbpntbez<<" Pas de rajout "<<endl;
   }
-  ptrsvsurf = &myImpPrmSvSurfaces;
-  
-  if(nbpntbez < LimRajout) myApproxBez = Standard_False;
-  
-  Standard_Integer nbpntmax = myNbPntMax;
-  Standard_Boolean OtherInter = Standard_False;
-  if(myApproxBez) { 
-    myBezToBSpl.Reset();
-    Standard_Integer nbi = (indicemax-indicemin)/nbpntmax;
-    if(nbi>1)  { 
-      nbpntbez = (indicemax-indicemin)/nbi;
+
+  Standard_Real aS2URes = ThePSurfaceTool::UResolution(PSurf, 1.0),
+                aS2VRes = ThePSurfaceTool::VResolution(PSurf, 1.0);
+  if(ApproxU2V2)
+    myUVRes2 = aS2URes / aS2VRes;
+
+  // Fill data structure.
+  fillData(theline, ApproxXYZ, ApproxU1V1, ApproxU2V2);
+
+  // Build knots.
+  Standard_Address ptrsvsurf = &myImpPrmSvSurfaces;
+  buildKnots(theline, ptrsvsurf);
+
+  if(myRelativeTol==Standard_False)
+  {
+    myComputeLine.Init(myDegMin,
+      myDegMax,
+      myTol3d*myData.myMinFactorXYZ,
+      myTol2d*myData.myMinFactorUV,
+      myNbIterMax,
+      cut,
+      myData.parametrization);
+    myComputeLineBezier.Init(myDegMin,
+      myDegMax,
+      myTol3d*myData.myMinFactorXYZ,
+      myTol2d*myData.myMinFactorUV,
+      myNbIterMax,
+      cut,
+      myData.parametrization);
+  }
+  else
+  {
+    myComputeLine.Init(myDegMin,
+      myDegMax,
+      myTol3d,
+      myTol2d,
+      myNbIterMax,
+      cut,
+      myData.parametrization);
+    myComputeLineBezier.Init(myDegMin,
+      myDegMax,
+      myTol3d,
+      myTol2d,
+      myNbIterMax,
+      cut,
+      myData.parametrization);
+  }
+
+  buildCurve(theline, ptrsvsurf);
+}
+
+//=======================================================================
+//function : NbMultiCurves
+//purpose  :
+//=======================================================================
+Standard_Integer ApproxInt_Approx::NbMultiCurves() const
+{
+  return 1;
+}
+
+//=======================================================================
+//function : UpdateTolReached
+//purpose  :
+//=======================================================================
+void ApproxInt_Approx::UpdateTolReached()
+{
+  if (myData.myBezierApprox)
+  {
+    Standard_Integer ICur;
+    Standard_Integer NbCurves = myComputeLineBezier.NbMultiCurves();
+    for (ICur = 1 ; ICur <= NbCurves ; ICur++)
+    {
+      Standard_Real Tol3D, Tol2D ;
+      myComputeLineBezier.Error (ICur, Tol3D, Tol2D) ;
+      myTolReached3d = Max(myTolReached3d, Tol3D);
+      myTolReached2d = Max(myTolReached2d, Tol2D);
     }
   }
-  Standard_Integer imin = indicemin;
-  Standard_Integer imax = imin + nbpntbez;
-  myTolReached = Standard_True;
-  
-  Standard_Real Xo,Ax,Yo,Ay,Zo,Az,U1o,A1u,V1o,A1v,U2o,A2u,V2o,A2v;
-  if(ApproxXYZ) { 
-    ComputeTrsf3d(theline,Xo,Ax,Yo,Ay,Zo,Az);
+  else
+  {
+    myComputeLine.Error (myTolReached3d, myTolReached2d);
+  }
+}
+
+//=======================================================================
+//function : TolReached3d
+//purpose  :
+//=======================================================================
+Standard_Real ApproxInt_Approx::TolReached3d() const
+{
+  Standard_Real TheTol3D = RatioTol * myTolReached3d ;
+
+  if (myData.myMinFactorXYZ>1.5e-7)
+    TheTol3D = TheTol3D / myData.myMinFactorXYZ;
+
+  //cout << "Tol 3D: " << TheTol3D << endl;
+  return TheTol3D ;
+}
+
+//=======================================================================
+//function : TolReached2d
+//purpose  :
+//=======================================================================
+Standard_Real ApproxInt_Approx::TolReached2d() const
+{
+  Standard_Real TheTol2D = RatioTol * myTolReached2d ;
+
+  if (myData.myMinFactorUV>1.5e-7)
+    TheTol2D = TheTol2D / myData.myMinFactorUV;
+
+  //cout << "Tol 2D: " << TheTol2D << endl;
+  return TheTol2D ;
+}
+
+//=======================================================================
+//function : IsDone
+//purpose  :
+//=======================================================================
+Standard_Boolean ApproxInt_Approx::IsDone() const
+{
+  if(myData.myBezierApprox)
+  { 
+    return(myComputeLineBezier.NbMultiCurves() > 0);
+    //-- Lorsque la tolerance n est pas atteinte et qu il 
+    //-- faudrait rajouter des points sur la ligne
+    //-- les approx sortent avec la meilleure tolerance
+    //-- atteinte.  ( Pas de rajout de points ds cette version)
+    //-- return(myTolReached);
+  }
+  else
+  {
+    return(myComputeLine.IsToleranceReached());
+  }
+}
+
+//=======================================================================
+//function : Value
+//purpose  :
+//=======================================================================
+const AppParCurves_MultiBSpCurve& ApproxInt_Approx::Value(const Standard_Integer ) const
+{
+  if(myData.myBezierApprox)
+  {
+    return(myBezToBSpl.Value());
   }
-  else { 
-    Xo=Yo=Zo=0.0; Ax=Ay=Az=1.0;;
+  else
+  {
+    return(myComputeLine.Value());
   }
-  if(ApproxU1V1) { 
-    ComputeTrsf2d(theline,U1o,A1u,V1o,A1v,Standard_True);
+}
+
+//=======================================================================
+//function : fillData
+//purpose  : Fill ApproxInt data structure.
+//=======================================================================
+void ApproxInt_Approx::fillData(const Handle(TheWLine)& theline,
+                                const Standard_Boolean ApproxXYZ,
+                                const Standard_Boolean ApproxU1V1,
+                                const Standard_Boolean ApproxU2V2)
+{
+  if(ApproxXYZ)
+  {
+    ComputeTrsf3d(theline, myData.Xo, myData.Ax, myData.Yo, myData.Ay, myData.Zo, myData.Az);
   }
-  else { 
-    U1o=V1o=0.0; A1u=A1v=1.0;
+  else
+  {
+    myData.Xo = myData.Yo = myData.Zo = 0.0;
+    myData.Ax = myData.Ay = myData.Az = 1.0;
   }
-  if(ApproxU2V2) { 
-    Standard_Real UVResRatio = ThePSurfaceTool::UResolution(PSurf,1.)/
-                               ThePSurfaceTool::VResolution(PSurf,1.);
-    ComputeTrsf2d(theline,U2o,A2u,V2o,A2v,Standard_False,UVResRatio);
+
+  if(ApproxU1V1)
+  {
+    ComputeTrsf2d(theline, myData.U1o, myData.A1u, myData.V1o, myData.A1v,Standard_True, myUVRes1);
   }
-  else { 
-    U2o=V2o=0.0; A2u=A2v=1.0;
+  else
+  {
+    myData.U1o = myData.V1o = 0.0;
+    myData.A1u = myData.A1v = 1.0;
   }
-  
-  //-deb-  cout << "ApproxInt_Approx -- NbPntMax = " << myNbPntMax    << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- Tol3D    = " << myTol3d       << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- Tol2D    = " << myTol2d       << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- RelTol   = " << (myRelativeTol ? "RELATIVE" : "ABSOLUTE") << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- Xo = " << Xo << " Yo = " << Yo << " Zo = " << Zo << endl ;
-  //-deb-  cout << "ApproxInt_Approx -- Ax = " << Ax << " Ay = " << Ay << " Az = " << Az << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- U1o = " << U1o << " V1o = " << V1o << " A1u = " << A1u << " A1v = " << A1v << endl ; 
-  //-deb-  cout << "ApproxInt_Approx -- U2o = " << U2o << " V2o = " << V2o << " A2u = " << A2u << " A2v = " << A2v << endl ; 
-  
-  
-  Standard_Real A3d = MINABS3(Ax,Ay,Az);
-  if((A3d < myMinFactorXYZ) || (myMinFactorXYZ == 0.0)) { 
-    myMinFactorXYZ = A3d;
+
+  if(ApproxU2V2)
+  {
+    ComputeTrsf2d(theline, myData.U2o, myData.A2u, myData.V2o, myData.A2v, Standard_False, myUVRes2);
   }
-  
-  Standard_Real A2d = MINABS4(A1u,A1v,A2u,A2v);
-  if((A2d < myMinFactorUV) || (myMinFactorUV == 0.0)) { 
-    myMinFactorUV = A2d;
+  else
+  {
+    myData.U2o = myData.V2o = 0.0;
+    myData.A2u = myData.A2v = 1.0;
   }
 
+  Standard_Real A3d = MINABS3(myData.Ax, myData.Ay, myData.Az);
+  if((A3d < myData.myMinFactorXYZ) || (myData.myMinFactorXYZ == 0.0))
+  {
+    myData.myMinFactorXYZ = A3d;
+  }
+
+  Standard_Real A2d = MINABS4(myData.A1u, myData.A1v, myData.A2u, myData.A2v);
+  if((A2d < myData.myMinFactorUV) || (myData.myMinFactorUV == 0.0))
+  {
+    myData.myMinFactorUV = A2d;
+  }
+}
+
+//=======================================================================
+//function : prepareDS
+//purpose  :
+//=======================================================================
+void ApproxInt_Approx::prepareDS(const Standard_Boolean theApproxXYZ,
+                                 const Standard_Boolean theApproxU1V1,
+                                 const Standard_Boolean theApproxU2V2,
+                                 const Standard_Integer theIndicemin,
+                                 const Standard_Integer theIndicemax)
+{
+  myData.myMinFactorXYZ = 0.0;
+  myData.myMinFactorUV  = 0.0;
+  myTolReached3d = myTolReached2d = 0.0;
+  myUVRes1 = myUVRes2 = 1.0;
+  myData.ApproxU1V1 = theApproxU1V1;
+  myData.ApproxU2V2 = theApproxU2V2;
+  myData.ApproxXYZ = theApproxXYZ;
+  myData.indicemin = theIndicemin;
+  myData.indicemax = theIndicemax;
+  myData.nbpntmax = myNbPntMax;
+
   Approx_ParametrizationType parametrization;
   myComputeLineBezier.Parametrization(parametrization);
-  
-  
-  if(myRelativeTol==Standard_False) { 
-    myComputeLine.Init(myDegMin,
-                      myDegMax,
-                      myTol3d*myMinFactorXYZ,
-                      myTol2d*myMinFactorUV,
-                      myNbIterMax,
-                      cut,
-                      parametrization);
-    myComputeLineBezier.Init(myDegMin,
-                            myDegMax,
-                            myTol3d*myMinFactorXYZ,
-                            myTol2d*myMinFactorUV,
-                            myNbIterMax,
-                            cut,
-                            parametrization);
+  myData.parametrization = parametrization;
+}
+
+//=======================================================================
+//function : buildKnots
+//purpose  :
+//=======================================================================
+void ApproxInt_Approx::buildKnots(const Handle(TheWLine)& theline,
+                                  const Standard_Address thePtrSVSurf)
+{
+  myKnots.Clear();
+  if(myData.myBezierApprox)
+  {
+    ApproxInt_TheMultiLine aTestLine(theline,
+      thePtrSVSurf,
+      ((myData.ApproxXYZ)? 1 : 0),
+      ((myData.ApproxU1V1)? 1: 0) + ((myData.ApproxU2V2)? 1: 0),
+      myData.Xo, myData.Ax, myData.Yo, myData.Ay, myData.Zo, myData.Az,
+      myData.U1o, myData.A1u, 
+      myData.V1o, myData.A1v,
+      myData.U2o, myData.A2u,
+      myData.V2o ,myData.A2v,
+      myData.ApproxU1V1,
+      myData.indicemin,
+      myData.indicemax);
+
+    Standard_Integer nbp3d = aTestLine.NbP3d();
+    Standard_Integer nbp2d = aTestLine.NbP2d();
+    TColgp_Array1OfPnt aTabPnt3d(1, Max(1, nbp3d));
+    TColgp_Array1OfPnt2d aTabPnt2d(1, Max(1, nbp2d));
+    TColgp_Array1OfPnt aPntXYZ(myData.indicemin, myData.indicemax);
+    TColgp_Array1OfPnt2d aPntU1V1(myData.indicemin, myData.indicemax);
+    TColgp_Array1OfPnt2d aPntU2V2(myData.indicemin, myData.indicemax);
+    Standard_Integer i;
+    for(i = myData.indicemin; i <= myData.indicemax; ++i)
+    {
+      if (nbp3d != 0 && nbp2d != 0) aTestLine.Value(i, aTabPnt3d, aTabPnt2d);
+      else if (nbp2d != 0)          aTestLine.Value(i, aTabPnt2d);
+      else if (nbp3d != 0)          aTestLine.Value(i, aTabPnt3d);
+      //
+      if(nbp3d > 0)
+      {
+        aPntXYZ(i) = aTabPnt3d(1);
+      }
+      if(nbp2d > 1)
+      {
+        aPntU1V1(i) = aTabPnt2d(1);
+        aPntU2V2(i) = aTabPnt2d(2);
+      }
+      else if(nbp2d > 0)
+      {
+        if(myData.ApproxU1V1)
+        {
+          aPntU1V1(i) = aTabPnt2d(1);
+        }
+        else
+        {
+          aPntU2V2(i) = aTabPnt2d(1);
+        }
+      }
+    }
+
+    Standard_Integer aMinNbPnts = myData.nbpntmax;
+
+    // Expected parametrization.
+    math_Vector aPars(myData.indicemin, myData.indicemax);
+    Parameters(aTestLine, myData.indicemin, myData.indicemax, myData.parametrization, aPars);
+
+    ApproxInt_KnotTools::BuildKnots(aPntXYZ, aPntU1V1, aPntU2V2, aPars,
+      myData.ApproxXYZ, myData.ApproxU1V1, myData.ApproxU2V2, aMinNbPnts, myKnots);
   }
-  else { 
-    myComputeLine.Init(myDegMin,
-                      myDegMax,
-                      myTol3d,
-                      myTol2d,
-                      myNbIterMax,
-                      cut,
-                      parametrization);
-    myComputeLineBezier.Init(myDegMin,
-                            myDegMax,
-                            myTol3d,
-                            myTol2d,
-                            myNbIterMax,
-                            cut,
-                            parametrization);
-  }     
-  
-  
-  
-  do {
-    
+  else
+  {
+    myKnots.Append(myData.indicemin);
+    myKnots.Append(myData.indicemax);
+  }
+}
+
+//=======================================================================
+//function : buildCurve
+//purpose  :
+//=======================================================================
+void ApproxInt_Approx::buildCurve(const Handle(TheWLine)& theline,
+                                  const Standard_Address thePtrSVSurf)
+{
+  if(myData.myBezierApprox)
+  {
+    myBezToBSpl.Reset();
+  }
+
+  Standard_Integer kind = myKnots.Lower();
+  Standard_Integer imin, imax;
+  myTolReached = Standard_True;
+  Standard_Boolean OtherInter = Standard_False;
+  do
+  {
+    // Base cycle: iterate over knots.
+    imin = myKnots(kind);
+    imax = myKnots(kind+1);
     ApproxInt_TheMultiLine myMultiLine(theline,
-                                      ptrsvsurf,
-                                      ((ApproxXYZ)? 1 : 0),
-                                      ((ApproxU1V1)? 1: 0) + ((ApproxU2V2)? 1: 0),
-                                      Xo,Ax,Yo,Ay,Zo,Az,U1o,A1u,V1o,A1v,U2o,A2u,V2o,A2v,
-                                      ApproxU1V1,
-                                      imin,
-                                      imax);
-    if(myApproxBez) { 
+      thePtrSVSurf,
+      ((myData.ApproxXYZ)? 1 : 0),
+      ((myData.ApproxU1V1)? 1: 0) + ((myData.ApproxU2V2)? 1: 0),
+      myData.Xo, myData.Ax, myData.Yo,myData.Ay, myData.Zo,myData.Az,
+      myData.U1o, myData.A1u, myData.V1o, myData.A1v,
+      myData.U2o, myData.A2u, myData.V2o, myData.A2v,
+      myData.ApproxU1V1,
+      imin,
+      imax);
+
+    if(myData.myBezierApprox)
+    {
       myComputeLineBezier.Perform(myMultiLine);
       if (myComputeLineBezier.NbMultiCurves() == 0)
-       return;
+        return;
       myTolReached&=myComputeLineBezier.IsToleranceReached();
     }
-    else { 
+    else
+    {
       myComputeLine.Perform(myMultiLine);
     }
     UpdateTolReached();
-    
+
     Standard_Integer indice3d,indice2d1,indice2d2;
     indice3d = 1; 
     indice2d1= 2;
     indice2d2= 3;
-    if(!ApproxXYZ)  { indice2d1--; indice2d2--; } 
-    if(!ApproxU1V1) { indice2d2--; } 
-    if(ApproxXYZ) { 
+    if(!myData.ApproxXYZ)  { indice2d1--; indice2d2--; } 
+    if(!myData.ApproxU1V1) { indice2d2--; } 
+    if(myData.ApproxXYZ)
+    { 
       Standard_Real ax,bx,ay,by,az,bz;
-      ax = 1.0/Ax;   bx = -Xo*ax;
-      ay = 1.0/Ay;   by = -Yo*ay;
-      az = 1.0/Az;   bz = -Zo*az;
-      if(myApproxBez) { 
-       for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--) { 
-         myComputeLineBezier.ChangeValue(nbmc).Transform(indice3d,bx,ax,by,ay,bz,az);
-       }
+      ax = 1.0/myData.Ax;   bx = -myData.Xo*ax;
+      ay = 1.0/myData.Ay;   by = -myData.Yo*ay;
+      az = 1.0/myData.Az;   bz = -myData.Zo*az;
+      if(myData.myBezierApprox)
+      {
+        for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--)
+        {
+          myComputeLineBezier.ChangeValue(nbmc).Transform(indice3d,bx,ax,by,ay,bz,az);
+        }
       }
-      else { 
-       myComputeLine.ChangeValue().Transform(indice3d,bx,ax,by,ay,bz,az);
+      else
+      {
+        myComputeLine.ChangeValue().Transform(indice3d,bx,ax,by,ay,bz,az);
       }
     }
-    if(ApproxU1V1) { 
+    if(myData.ApproxU1V1)
+    {
       Standard_Real ax,bx,ay,by;
-      ax = 1.0/A1u;   bx = -U1o*ax;
-      ay = 1.0/A1v;   by = -V1o*ay;
-      if(myApproxBez) { 
-       for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--) { 
-         myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d1,bx,ax,by,ay);
-       }
+      ax = 1.0/myData.A1u;   bx = -myData.U1o*ax;
+      ay = 1.0/myData.A1v;   by = -myData.V1o*ay;
+      if(myData.myBezierApprox) {
+        for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--)
+        {
+          myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d1,bx,ax,by,ay);
+        }
       }
-      else { 
-       myComputeLine.ChangeValue().Transform2d(indice2d1,bx,ax,by,ay);
+      else
+      {
+        myComputeLine.ChangeValue().Transform2d(indice2d1,bx,ax,by,ay);
       }
     }
-    if(ApproxU2V2) { 
+    if(myData.ApproxU2V2)
+    {
       Standard_Real ax,bx,ay,by;
-      ax = 1.0/A2u;   bx = -U2o*ax;
-      ay = 1.0/A2v;   by = -V2o*ay;
-      if(myApproxBez) { 
-       for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--) { 
-         myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d2,bx,ax,by,ay);
-       }
+      ax = 1.0/myData.A2u;   bx = -myData.U2o*ax;
+      ay = 1.0/myData.A2v;   by = -myData.V2o*ay;
+      if(myData.myBezierApprox)
+      {
+        for(Standard_Integer nbmc = myComputeLineBezier.NbMultiCurves() ; nbmc>=1; nbmc--)
+        {
+          myComputeLineBezier.ChangeValue(nbmc).Transform2d(indice2d2,bx,ax,by,ay);
+        }
       }
-      else { 
-       myComputeLine.ChangeValue().Transform2d(indice2d2,bx,ax,by,ay);
+      else
+      {
+        myComputeLine.ChangeValue().Transform2d(indice2d2,bx,ax,by,ay);
       }
     }
+
     OtherInter = Standard_False;
-    if(myApproxBez) { 
+    if(myData.myBezierApprox)
+    {
       for(Standard_Integer nbmc = 1; 
-         nbmc <= myComputeLineBezier.NbMultiCurves() ;
-         nbmc++) { 
-       myBezToBSpl.Append(myComputeLineBezier.Value(nbmc));
+        nbmc <= myComputeLineBezier.NbMultiCurves();
+        nbmc++)
+      {
+          myBezToBSpl.Append(myComputeLineBezier.Value(nbmc));
       }
-      if(imax<indicemax) { 
-       imin = imax;    
-       imax = imin+nbpntbez;
-       OtherInter = Standard_True;
-       if((indicemax-imax)<(nbpntbez/2)) { 
-         imax = indicemax;
-       }
+      kind++;
+      if(kind < myKnots.Upper())
+      {
+        OtherInter = Standard_True;
       }
-    } 
-  }
-  while(OtherInter); 
-  if(myApproxBez) { 
-    myBezToBSpl.Perform();
-  }
-}
-//--------------------------------------------------------------------------------
-Standard_Integer ApproxInt_Approx::NbMultiCurves() const { 
-  //  return(myComputeLine.NbMultiCurves());
-  return 1;
-}
-//--------------------------------------------------------------------------------
-void ApproxInt_Approx::UpdateTolReached() {
-
-  if (myApproxBez) {
-    Standard_Integer ICur ;
-    Standard_Integer NbCurves = myComputeLineBezier.NbMultiCurves() ;
-    for (ICur = 1 ; ICur <= NbCurves ; ICur++) {
-      Standard_Real Tol3D, Tol2D ;
-      myComputeLineBezier.Error (ICur, Tol3D, Tol2D) ;
-      myTolReached3d = Max(myTolReached3d, Tol3D);
-      myTolReached2d = Max(myTolReached2d, Tol2D);
     }
-  } else {
-    myComputeLine.Error (myTolReached3d, myTolReached2d);
-  }
-}
-//--------------------------------------------------------------------------------
-Standard_Real ApproxInt_Approx::TolReached3d() const { 
-
-  Standard_Real TheTol3D = RatioTol * myTolReached3d ;
-  //modified by NIZNHY-PKV Mon Aug 27 14:21:33 2007f
-  //if (myMinFactorXYZ)
-  //TheTol3D = TheTol3D / myMinFactorXYZ ;
-  if (myMinFactorXYZ>1.5e-7) {
-    TheTol3D = TheTol3D / myMinFactorXYZ ;
   }
-  //modified by NIZNHY-PKV Mon Aug 27 14:21:50 2007t
-  return TheTol3D ;
-}
-//--------------------------------------------------------------------------------
-Standard_Real ApproxInt_Approx::TolReached2d() const {
+  while(OtherInter);
 
-  Standard_Real TheTol2D = RatioTol * myTolReached2d ;
-  //modified by NIZNHY-PKV Mon Aug 27 14:20:50 2007f
-  //if (myMinFactorUV)
-  //TheTol2D = TheTol2D / myMinFactorUV ;
-  if (myMinFactorUV>1.5e-7) {
-    TheTol2D = TheTol2D / myMinFactorUV ;
-  }
-  //modified by NIZNHY-PKV Mon Aug 27 14:20:55 2007t
-  return TheTol2D ;
-}
-//--------------------------------------------------------------------------------
-Standard_Boolean ApproxInt_Approx::IsDone() const { 
-  if(myApproxBez) { 
-    return(myComputeLineBezier.NbMultiCurves() > 0);
-                           //-- Lorsque la tolerance n est pas atteinte et qu il 
-                           //-- faudrait rajouter des points sur la ligne
-                           //-- les approx sortent avec la meilleure tolerance
-                           //-- atteinte.  ( Pas de rajout de points ds cette version)
-    //-- return(myTolReached);
-  }
-  else { 
-    return(myComputeLine.IsToleranceReached());
-  }
-}
-//--------------------------------------------------------------------------------
-const AppParCurves_MultiBSpCurve& ApproxInt_Approx::Value(const Standard_Integer ) const { 
-  if(myApproxBez) { 
-    return(myBezToBSpl.Value());
-  }
-  else { 
-    return(myComputeLine.Value());
+  if(myData.myBezierApprox)
+  {
+    myBezToBSpl.Perform();
   }
-}
+}
\ No newline at end of file