0026621: Boolean Cut does not work on two solids
[occt.git] / src / IntTools / IntTools_FaceFace.cxx
index f31df2a..10bde06 100644 (file)
@@ -13,7 +13,7 @@
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <IntTools_FaceFace.ixx>
+#include <IntTools_FaceFace.hxx>
 
 #include <Precision.hxx>
 
@@ -87,6 +87,7 @@
 
 #include <Geom2dAPI_InterCurveCurve.hxx>
 #include <Geom2dInt_GInter.hxx>
+#include <Geom2dAdaptor.hxx>
 #include <GeomAdaptor_Curve.hxx>
 #include <GeomAdaptor_HSurface.hxx>
 #include <GeomAdaptor_Surface.hxx>
 #include <IntTools_PntOn2Faces.hxx>
 #include <IntTools_Context.hxx>
 #include <IntSurf_ListIteratorOfListOfPntOn2S.hxx>
+#include <GeomInt.hxx>
+
+#include <Approx_CurveOnSurface.hxx>
+#include <GeomAdaptor.hxx>
+#include <GeomInt_IntSS.hxx>
 
 static
   void RefineVector(gp_Vec2d& aV2D);
-#ifdef DEB_DUMPWLINE
+#ifdef OCCT_DEBUG_DUMPWLINE
 static
   void DumpWLine(const Handle(IntPatch_WLine)& aWLine);
 #endif
@@ -139,12 +145,6 @@ static
                   Standard_Real&,
                   Standard_Real&);
 
-static 
-  void BuildPCurves (Standard_Real f,Standard_Real l,Standard_Real& Tol,
-                     const Handle (Geom_Surface)& S,
-                     const Handle (Geom_Curve)&   C,
-                     Handle (Geom2d_Curve)& C2d);
-
 static 
   void CorrectSurfaceBoundaries(const TopoDS_Face&  theFace,
                                 const Standard_Real theTolerance,
@@ -152,6 +152,7 @@ static
                                 Standard_Real&      theumax, 
                                 Standard_Real&      thevmin, 
                                 Standard_Real&      thevmax);
+
 static
   Standard_Boolean NotUseSurfacesForApprox
           (const TopoDS_Face& aF1,
@@ -161,7 +162,9 @@ static
            const Standard_Integer ilprm);
 
 static 
-  Handle(IntPatch_WLine) ComputePurgedWLine(const Handle(IntPatch_WLine)& theWLine);
+  Handle(IntPatch_WLine) ComputePurgedWLine(const Handle(IntPatch_WLine)       &theWLine,
+                                            const Handle(GeomAdaptor_HSurface) &theS1,
+                                            const Handle(GeomAdaptor_HSurface) &theS2);
 
 static 
   Handle(Geom2d_BSplineCurve) MakeBSpline2d(const Handle(IntPatch_WLine)& theWLine,
@@ -175,7 +178,7 @@ static
                                         const Handle(GeomAdaptor_HSurface)&            theSurface2,
                                         const TopoDS_Face&                             theFace1,
                                         const TopoDS_Face&                             theFace2,
-                                        const IntTools_LineConstructor&                theLConstructor,
+                                        const GeomInt_LineConstructor&                 theLConstructor,
                                         const Standard_Boolean                         theAvoidLConstructor,
                                         IntPatch_SequenceOfLine&                       theNewLines,
                                         Standard_Real&                                 theReachedTol3d,
@@ -280,34 +283,34 @@ static
   Standard_Integer IndexType(const GeomAbs_SurfaceType aType);
 
 //
-static
-  Standard_Real MaxSquareDistance (const Standard_Real aT,
-                                   const Handle(Geom_Curve)& aC3D,
-                                   const Handle(Geom2d_Curve)& aC2D1,
-                                   const Handle(Geom2d_Curve)& aC2D2,
-                                   const Handle(GeomAdaptor_HSurface) myHS1,
-                                   const Handle(GeomAdaptor_HSurface) myHS2,
-                                   const TopoDS_Face& aF1,
-                                   const TopoDS_Face& aF2,
-                                   const Handle(IntTools_Context)& aCtx);
-
 static
   Standard_Boolean CheckPCurve(const Handle(Geom2d_Curve)& aPC, 
                                const TopoDS_Face& aFace);
 
-//
 static
-  Standard_Real FindMaxSquareDistance (const Standard_Real aA,
-                                       const Standard_Real aB,
-                                       const Standard_Real aEps,
-                                       const Handle(Geom_Curve)& aC3D,
-                                       const Handle(Geom2d_Curve)& aC2D1,
-                                       const Handle(Geom2d_Curve)& aC2D2,
-                                       const Handle(GeomAdaptor_HSurface)& myHS1,
-                                       const Handle(GeomAdaptor_HSurface)& myHS2,
-                                       const TopoDS_Face& aF1,
-                                       const TopoDS_Face& aF2,
-                                       const Handle(IntTools_Context)& aCtx);
+  Standard_Real MaxDistance(const Handle(Geom_Curve)& theC,
+                            const Standard_Real aT,
+                            GeomAPI_ProjectPointOnSurf& theProjPS);
+
+static
+  Standard_Real FindMaxDistance(const Handle(Geom_Curve)& theC,
+                                const Standard_Real theFirst,
+                                const Standard_Real theLast,
+                                GeomAPI_ProjectPointOnSurf& theProjPS,
+                                const Standard_Real theEps);
+
+static
+  Standard_Real FindMaxDistance(const Handle(Geom_Curve)& theCurve,
+                                const Standard_Real theFirst,
+                                const Standard_Real theLast,
+                                const TopoDS_Face& theFace,
+                                const Handle(IntTools_Context)& theContext);
+
+static
+  void CorrectPlaneBoundaries(Standard_Real& aUmin,
+                              Standard_Real& aUmax, 
+                              Standard_Real& aVmin, 
+                              Standard_Real& aVmax);
 
 //=======================================================================
 //function : 
@@ -509,7 +512,7 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
 //function : Perform
 //purpose  : intersect surfaces of the faces
 //=======================================================================
-  void IntTools_FaceFace::Perform(const TopoDS_Face& aF1,
+void IntTools_FaceFace::Perform(const TopoDS_Face& aF1,
                                 const TopoDS_Face& aF2)
 {
   Standard_Boolean RestrictLine = Standard_False, hasCone = Standard_False;
@@ -553,6 +556,10 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
         aP2S.SetValue(aU2,aV2,aU1,aV1);
       }
     }
+    //
+    Standard_Boolean anAproxTmp = myApprox1;
+    myApprox1 = myApprox2;
+    myApprox2 = anAproxTmp;
   }
 
 
@@ -575,24 +582,13 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
 
   if(aType1==GeomAbs_Plane && aType2==GeomAbs_Plane)  {
     Standard_Real umin, umax, vmin, vmax;
-    Standard_Real dU, dV;
     //
     BRepTools::UVBounds(myFace1, umin, umax, vmin, vmax);
-    dU=0.1*(umax-umin);
-    dV=0.1*(vmax-vmin);
-    umin=umin-dU;
-    umax=umax+dU;
-    vmin=vmin-dV;
-    vmax=vmax+dV;
+    CorrectPlaneBoundaries(umin, umax, vmin, vmax);
     myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
     //
     BRepTools::UVBounds(myFace2, umin, umax, vmin, vmax);
-    dU=0.1*(umax-umin);
-    dV=0.1*(vmax-vmin);
-    umin=umin-dU;
-    umax=umax+dU;
-    vmin=vmin-dV;
-    vmax=vmax+dV;
+    CorrectPlaneBoundaries(umin, umax, vmin, vmax);
     myHS2->ChangeSurface().Load(S2, umin, umax, vmin, vmax);
     //
     Standard_Real TolAng = 1.e-8;
@@ -632,18 +628,10 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
 
   if ((aType1==GeomAbs_Plane) && isFace2Quad)
   {
-    Standard_Real dU, dV;
-
-    // F1
     Standard_Real umin, umax, vmin, vmax;
-    BRepTools::UVBounds(myFace1, umin, umax, vmin, vmax);
-
-    dU=0.1*(umax-umin);
-    dV=0.1*(vmax-vmin);
-    umin=umin-dU;
-    umax=umax+dU;
-    vmin=vmin-dV;
-    vmax=vmax+dV;
+    // F1
+    BRepTools::UVBounds(myFace1, umin, umax, vmin, vmax); 
+    CorrectPlaneBoundaries(umin, umax, vmin, vmax);
     myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
     // F2
     BRepTools::UVBounds(myFace2, umin, umax, vmin, vmax);
@@ -657,21 +645,14 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
   }
   else if ((aType2==GeomAbs_Plane) && isFace1Quad)
   {
-    Standard_Real dU, dV;
-
-    //F1
     Standard_Real umin, umax, vmin, vmax;
+    //F1
     BRepTools::UVBounds(myFace1, umin, umax, vmin, vmax);
     CorrectSurfaceBoundaries(myFace1, (aTolF1 + aTolF2) * 2., umin, umax, vmin, vmax);
     myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
     // F2
     BRepTools::UVBounds(myFace2, umin, umax, vmin, vmax);
-    dU=0.1*(umax-umin);
-    dV=0.1*(vmax-vmin);
-    umin=umin-dU;
-    umax=umax+dU;
-    vmin=vmin-dV;
-    vmax=vmax+dV;
+    CorrectPlaneBoundaries(umin, umax, vmin, vmax);
     myHS2->ChangeSurface().Load(S2, umin, umax, vmin, vmax);
     //
     if( aType1==GeomAbs_Cone ) {
@@ -701,7 +682,7 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
   {
     const Standard_Real UVMaxStep = 0.001;
     const Standard_Real Deflection = (hasCone) ? 0.085 : 0.1;
-  myIntersector.SetTolerances(TolArc, TolTang, UVMaxStep, Deflection); 
+    myIntersector.SetTolerances(TolArc, TolTang, UVMaxStep, Deflection); 
   }
   
   if((myHS1->IsUClosed() && !myHS1->IsUPeriodic()) || 
@@ -788,6 +769,7 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
     }
 
     // Points
+    Standard_Boolean bValid2D1, bValid2D2;
     Standard_Real U1,V1,U2,V2;
     IntTools_PntOnFace aPntOnF1, aPntOnF2;
     IntTools_PntOn2Faces aPntOn2Faces;
@@ -798,6 +780,19 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
       const IntSurf_PntOn2S& aISPnt=myIntersector.Point(i).PntOn2S();
       const gp_Pnt& aPnt=aISPnt.Value();
       aISPnt.Parameters(U1,V1,U2,V2);
+      //
+      // check the validity of the intersection point for the faces
+      bValid2D1 = myContext->IsPointInOnFace(myFace1, gp_Pnt2d(U1, V1));
+      if (!bValid2D1) {
+        continue;
+      }
+      //
+      bValid2D2 = myContext->IsPointInOnFace(myFace2, gp_Pnt2d(U2, V2));
+      if (!bValid2D2) {
+        continue;
+      }
+      //
+      // add the intersection point
       aPntOnF1.Init(myFace1, aPnt, U1, V1);
       aPntOnF2.Init(myFace2, aPnt, U2, V2);
       //
@@ -817,14 +812,75 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
   }
 }
 
+//=======================================================================
+//function : ComputeTolerance
+//purpose  : 
+//=======================================================================
+Standard_Real IntTools_FaceFace::ComputeTolerance()
+{
+  Standard_Integer i, j, aNbLin;
+  Standard_Real aFirst, aLast, aD, aDMax, aT;
+  Handle(Geom_Surface) aS1, aS2;
+  //
+  aDMax = 0;
+  aNbLin = mySeqOfCurve.Length();
+  //
+  aS1 = myHS1->ChangeSurface().Surface();
+  aS2 = myHS2->ChangeSurface().Surface();
+  //
+  for (i = 1; i <= aNbLin; ++i)
+  {
+    const IntTools_Curve& aIC = mySeqOfCurve(i);
+    const Handle(Geom_Curve)& aC3D = aIC.Curve();
+    if (aC3D.IsNull())
+    {
+      continue;
+    }
+    //
+    aFirst = aC3D->FirstParameter();
+    aLast  = aC3D->LastParameter();
+    //
+    const Handle(Geom2d_Curve)& aC2D1 = aIC.FirstCurve2d();
+    const Handle(Geom2d_Curve)& aC2D2 = aIC.SecondCurve2d();
+    //
+    for (j = 0; j < 2; ++j)
+    {
+      const Handle(Geom2d_Curve)& aC2D = !j ? aC2D1 : aC2D2;
+      const Handle(Geom_Surface)& aS = !j ? aS1 : aS2;
+      //
+      if (!aC2D.IsNull())
+      {
+        if (IntTools_Tools::ComputeTolerance
+            (aC3D, aC2D, aS, aFirst, aLast, aD, aT))
+        {
+          if (aD > aDMax)
+          {
+            aDMax = aD;
+          }
+        }
+      }
+      else
+      {
+        const TopoDS_Face& aF = !j ? myFace1 : myFace2;
+        aD = FindMaxDistance(aC3D, aFirst, aLast, aF, myContext);
+        if (aD > aDMax)
+        {
+          aDMax = aD;
+        }
+      }
+    }
+  }
+  //
+  return aDMax;
+}
+
 //=======================================================================
 //function :ComputeTolReached3d 
 //purpose  : 
 //=======================================================================
   void IntTools_FaceFace::ComputeTolReached3d()
 {
-  Standard_Boolean bCase1;
-  Standard_Integer aNbLin, i;
+  Standard_Integer aNbLin;
   GeomAbs_SurfaceType aType1, aType2;
   //
   aNbLin=myIntersector.NbLines();
@@ -835,11 +891,10 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
   aType1=myHS1->Surface().GetType();
   aType2=myHS2->Surface().GetType();
   //
-  bCase1=((aType1==GeomAbs_Plane && aType2==GeomAbs_SurfaceOfExtrusion) ||
-          (aType2==GeomAbs_Plane && aType1==GeomAbs_SurfaceOfExtrusion));
-  //
-  if (aType1==GeomAbs_Cylinder && aType2==GeomAbs_Cylinder) {
-    if (aNbLin==2){ 
+  if (aType1==GeomAbs_Cylinder && aType2==GeomAbs_Cylinder)
+  {
+    if (aNbLin==2)
+    { 
       Handle(IntPatch_Line) aIL1, aIL2;
       IntPatch_IType aTL1, aTL2;
       //
@@ -858,311 +913,22 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
         aL2=Handle(IntPatch_GLine)::DownCast(aIL2)->Line();
         aD=aL1.Distance(aL2);
         aD=0.5*aD;
-        if (aD<aDTresh) {
+        if (aD<aDTresh)
+        {//In order to avoid creation too thin face
           myTolReached3d=aD+dTol;
         }
-        return;
       }
     }
-    //ZZ
-    if (aNbLin) {// Check the distances
-      Standard_Integer  aNbP, j ;
-      Standard_Real aT1, aT2, dT, aD2, aD2Max, aEps, aT11, aT12;
-      //
-      aD2Max=0.;
-      aNbP=10;
-      aNbLin=mySeqOfCurve.Length();
-      //
-      for (i=1; i<=aNbLin; ++i) {
-        const IntTools_Curve& aIC=mySeqOfCurve(i);
-        const Handle(Geom_Curve)& aC3D=aIC.Curve();
-        const Handle(Geom2d_Curve)& aC2D1=aIC.FirstCurve2d();
-        const Handle(Geom2d_Curve)& aC2D2=aIC.SecondCurve2d();
-        //
-        if (aC3D.IsNull()) {
-          continue;
-        }
-        const Handle(Geom_BSplineCurve)& aBC=
-          Handle(Geom_BSplineCurve)::DownCast(aC3D);
-        if (aBC.IsNull()) {
-          continue;
-        }
-        //
-        aT1=aBC->FirstParameter();
-        aT2=aBC->LastParameter();
-        //
-        aEps=0.01*(aT2-aT1);
-        dT=(aT2-aT1)/aNbP;
-        for (j=1; j<aNbP; ++j) {
-          aT11=aT1+j*dT;
-          aT12=aT11+dT;
-          aD2=FindMaxSquareDistance(aT11, aT12, aEps, aC3D, aC2D1, aC2D2,
-                                    myHS1, myHS2, myFace1, myFace2, myContext);
-          if (aD2>aD2Max) {
-            aD2Max=aD2;
-          }
-        }
-      }//for (i=1; i<=aNbLin; ++i) {
-      //
-      myTolReached3d=sqrt(aD2Max);
-    }// if (aNbLin) 
   }// if (aType1==GeomAbs_Cylinder && aType2==GeomAbs_Cylinder) {
   //
-  //904/G3 f
-  else if (aType1==GeomAbs_Plane && aType2==GeomAbs_Plane) {
-    Standard_Real aTolF1, aTolF2, aTolFMax, aTolTresh;
-    //
-    aTolTresh=1.e-7;
-    //
-    aTolF1 = BRep_Tool::Tolerance(myFace1);
-    aTolF2 = BRep_Tool::Tolerance(myFace2);
-    aTolFMax=Max(aTolF1, aTolF2);
-    //
-    if (aTolFMax>aTolTresh) {
-      myTolReached3d=aTolFMax;
-    }
-  }//if (aType1==GeomAbs_Plane && aType2==GeomAbs_Plane) {
-  //t
-  //IFV Bug OCC20297 
-  else if((aType1 == GeomAbs_Cylinder && aType2 == GeomAbs_Plane) ||
-          (aType2 == GeomAbs_Cylinder && aType1 == GeomAbs_Plane)) {
-    if(aNbLin == 1) {
-      const Handle(IntPatch_Line)& aIL1 = myIntersector.Line(1);
-      if(aIL1->ArcType() == IntPatch_Circle) {
-        gp_Circ aCir = Handle(IntPatch_GLine)::DownCast(aIL1)->Circle();
-        gp_XYZ aCirDir = aCir.Axis().Direction().XYZ();
-        gp_XYZ aPlDir;
-        gp_Pln aPln;
-        if(aType1 == GeomAbs_Plane) {
-          aPln = myHS1->Surface().Plane();
-        }
-        else {
-          aPln = myHS2->Surface().Plane();
-        }
-        aPlDir = aPln.Axis().Direction().XYZ();
-        Standard_Real cs = aCirDir*aPlDir;
-        if(cs < 0.) aPlDir.Reverse();
-        Standard_Real eps = 1.e-14;
-        if(!aPlDir.IsEqual(aCirDir, eps)) {
-          Standard_Integer aNbP = 11;
-          Standard_Real dt = 2.*M_PI / (aNbP - 1), t;
-          for(t = 0.; t < 2.*M_PI; t += dt) {
-            Standard_Real d = aPln.Distance(ElCLib::Value(t, aCir)); 
-            if(myTolReached3d < d) myTolReached3d = d;
-          }
-          myTolReached3d *= 1.1;
-        }
-      } //aIL1->ArcType() == IntPatch_Circle
-    } //aNbLin == 1
-  } // aType1 == GeomAbs_Cylinder && aType2 == GeomAbs_Plane) 
-  //End IFV Bug OCC20297
-  //
-  else if ((aType1==GeomAbs_Plane && aType2==GeomAbs_Torus) ||
-           (aType2==GeomAbs_Plane && aType1==GeomAbs_Torus)) {
-    aNbLin=mySeqOfCurve.Length();
-    if (aNbLin!=1) {
-      return;
-    }
-    //
-    Standard_Integer aNbP;
-    Standard_Real aT, aT1, aT2, dT, aUT, aVT, aUP, aVP;
-    Standard_Real aDP, aDT, aDmax;
-    gp_Pln aPln;
-    gp_Torus aTorus;
-    gp_Pnt aP, aPP, aPT;
-    //
-    const IntTools_Curve& aIC=mySeqOfCurve(1);
-    const Handle(Geom_Curve)& aC3D=aIC.Curve();
-    const Handle(Geom_BSplineCurve)& aBS=
-      Handle(Geom_BSplineCurve)::DownCast(aC3D);
-    if (aBS.IsNull()) {
-      return;
-    }
-    //
-    aT1=aBS->FirstParameter();
-    aT2=aBS->LastParameter();
-    //
-    aPln  =(aType1==GeomAbs_Plane) ? myHS1->Plane() : myHS2->Plane();
-    aTorus=(aType1==GeomAbs_Plane) ? myHS2->Torus() : myHS1->Torus();
-    //
-    aDmax=-1.;
-    aNbP=11;
-    dT=(aT2-aT1)/(aNbP-1);
-    for (i=0; i<aNbP; ++i) {
-      aT=aT1+i*dT;
-      if (i==aNbP-1) {
-        aT=aT2;
-      }
-      //
-      aC3D->D0(aT, aP);
-      //
-      ElSLib::Parameters(aPln, aP, aUP, aVP);
-      aPP=ElSLib::Value(aUP, aVP, aPln);
-      aDP=aP.SquareDistance(aPP);
-      if (aDP>aDmax) {
-        aDmax=aDP;
-      }
-      //
-      ElSLib::Parameters(aTorus, aP, aUT, aVT);
-      aPT=ElSLib::Value(aUT, aVT, aTorus);
-      aDT=aP.SquareDistance(aPT);
-      if (aDT>aDmax) {
-        aDmax=aDT;
-      }
-    }
-    //
-    if (aDmax > myTolReached3d*myTolReached3d) {
-      myTolReached3d=sqrt(aDmax);
-      myTolReached3d=1.1*myTolReached3d;
-    }
-  }// if ((aType1==GeomAbs_Plane && aType2==GeomAbs_Torus) ||
-  //
-  else if ((aType1==GeomAbs_SurfaceOfRevolution && aType2==GeomAbs_Cylinder) ||
-           (aType2==GeomAbs_SurfaceOfRevolution && aType1==GeomAbs_Cylinder)) {
-    Standard_Integer j, aNbP;
-    Standard_Real aT, aT1, aT2, dT, aD2max, aD2;
-    //
-    aNbLin=mySeqOfCurve.Length();
-    aD2max=0.;
-    aNbP=11;
-    //
-    for (i=1; i<=aNbLin; ++i) {
-      const IntTools_Curve& aIC=mySeqOfCurve(i);
-      const Handle(Geom_Curve)& aC3D=aIC.Curve();
-      const Handle(Geom2d_Curve)& aC2D1=aIC.FirstCurve2d();
-      const Handle(Geom2d_Curve)& aC2D2=aIC.SecondCurve2d();
-      //
-      if (aC3D.IsNull()) {
-        continue;
-      }
-      const Handle(Geom_BSplineCurve)& aBC=
-        Handle(Geom_BSplineCurve)::DownCast(aC3D);
-      if (aBC.IsNull()) {
-        return;
-      }
-      //
-      aT1=aBC->FirstParameter();
-      aT2=aBC->LastParameter();
-      //
-      dT=(aT2-aT1)/(aNbP-1);
-      for (j=0; j<aNbP; ++j) {
-        aT=aT1+j*dT;
-        if (j==aNbP-1) {
-          aT=aT2;
-        }
-        //
-        aD2=MaxSquareDistance(aT, aC3D, aC2D1, aC2D2,
-                              myHS1, myHS2, myFace1, myFace2, myContext);
-        if (aD2>aD2max) {
-          aD2max=aD2;
-        }
-      }//for (j=0; j<aNbP; ++j) {
-     
-    }//for (i=1; i<=aNbLin; ++i) {
-    //
-    aD2=myTolReached3d*myTolReached3d;
-    if (aD2max > aD2) {
-      myTolReached3d=sqrt(aD2max);
-    }
-  }//if((aType1==GeomAbs_SurfaceOfRevolution ...
-  else if ((aType1==GeomAbs_Plane && aType2==GeomAbs_Sphere) ||
-           (aType2==GeomAbs_Plane && aType1==GeomAbs_Sphere)) {
-    Standard_Integer  j, aNbP;
-    Standard_Real aT1, aT2, dT, aD2max, aD2, aEps, aT11, aT12;
-    //
-    aNbLin=mySeqOfCurve.Length();
-    aD2max=0.;
-    aNbP=10;
-    //
-    for (i=1; i<=aNbLin; ++i) {
-      const IntTools_Curve& aIC=mySeqOfCurve(i);
-      const Handle(Geom_Curve)& aC3D=aIC.Curve();
-      const Handle(Geom2d_Curve)& aC2D1=aIC.FirstCurve2d();
-      const Handle(Geom2d_Curve)& aC2D2=aIC.SecondCurve2d();
-      //
-      const Handle(Geom2d_BSplineCurve)& aBC2D1=
-        Handle(Geom2d_BSplineCurve)::DownCast(aC2D1);
-      const Handle(Geom2d_BSplineCurve)& aBC2D2=
-        Handle(Geom2d_BSplineCurve)::DownCast(aC2D2);
-      //
-      if (aBC2D1.IsNull() && aBC2D2.IsNull()) {
-        return;
-      }
-      //
-      if (!aBC2D1.IsNull()) {
-        aT1=aBC2D1->FirstParameter();
-        aT2=aBC2D1->LastParameter();
-      }
-      else {
-        aT1=aBC2D2->FirstParameter();
-        aT2=aBC2D2->LastParameter();
-      }
-      //
-      aEps=0.01*(aT2-aT1);
-      dT=(aT2-aT1)/aNbP;
-      for (j=0; j<aNbP; ++j) {
-        aT11=aT1+j*dT;
-        aT12=aT11+dT;
-        if (j==aNbP-1) {
-          aT12=aT2;
-        }
-        //
-        aD2=FindMaxSquareDistance(aT11, aT12, aEps, aC3D, aC2D1, aC2D2,
-                                  myHS1, myHS2, myFace1, myFace2, myContext);
-        if (aD2>aD2max) {
-          aD2max=aD2;
-        }
-      }//for (j=0; j<aNbP; ++j) {
-     
-    }//for (i=1; i<=aNbLin; ++i) {
-    //
-    aD2=myTolReached3d*myTolReached3d;
-    if (aD2max > aD2) {
-      myTolReached3d=sqrt(aD2max);
+
+  Standard_Real aDMax = ComputeTolerance();
+  if (aDMax > myTolReached3d)
+  {
+      myTolReached3d = aDMax;
     }
-  }//else if ((aType1==GeomAbs_Plane && aType2==GeomAbs_Sphere) ...
-  else if (!myApprox || bCase1) {
-  //else if (!myApprox) {
-    Standard_Integer aNbP, j;
-    Standard_Real aT1, aT2, dT, aD2, aD2Max, aEps, aT11, aT12;
-    //
-    aD2Max=0.;
-    aNbLin=mySeqOfCurve.Length();
-    //
-    for (i=1; i<=aNbLin; ++i) {
-      const IntTools_Curve& aIC=mySeqOfCurve(i);
-      const Handle(Geom_Curve)& aC3D=aIC.Curve();
-      const Handle(Geom2d_Curve)& aC2D1=aIC.FirstCurve2d();
-      const Handle(Geom2d_Curve)& aC2D2=aIC.SecondCurve2d();
-      //
-      if (aC3D.IsNull()) {
-        continue;
-}
-      const Handle(Geom_BSplineCurve)& aBC=
-        Handle(Geom_BSplineCurve)::DownCast(aC3D);
-      if (aBC.IsNull()) {
-        continue;
-      }
-      //
-      aT1=aBC->FirstParameter();
-      aT2=aBC->LastParameter();
-      //
-      aEps=0.0001*(aT2-aT1);
-      aNbP=11;
-      dT=(aT2-aT1)/aNbP;
-      for (j=1; j<aNbP-1; ++j) {
-        aT11=aT1+j*dT;
-        aT12=aT11+dT;
-        aD2=FindMaxSquareDistance(aT11, aT12, aEps, aC3D, aC2D1, aC2D2,
-                                  myHS1, myHS2, myFace1, myFace2, myContext);
-        if (aD2>aD2Max) {
-          aD2Max=aD2;
-        }
-      }
-    }//for (i=1; i<=aNbLin; ++i) {
-    myTolReached3d=sqrt(aD2Max);
   }
-}
+
 //=======================================================================
 //function : MakeCurve
 //purpose  : 
@@ -1198,17 +964,14 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
   if(typl==IntPatch_Walking) {
     Handle(IntPatch_Line) anewL;
     //
-    const Handle(IntPatch_WLine)& aWLine=
-      Handle(IntPatch_WLine)::DownCast(L);
-    //DumpWLine(aWLine);
-
-    anewL = ComputePurgedWLine(aWLine);
+    Handle(IntPatch_WLine) aWLine (Handle(IntPatch_WLine)::DownCast(L));
+    anewL = ComputePurgedWLine(aWLine, myHS1, myHS2);
     if(anewL.IsNull()) {
       return;
     }
     L = anewL;
-    
-    //const Handle(IntPatch_WLine)& aWLineX = Handle(IntPatch_WLine)::DownCast(L);
+
+    //Handle(IntPatch_WLine) aWLineX (Handle(IntPatch_WLine)::DownCast(L));
     //DumpWLine(aWLineX);
 
     //
@@ -1227,21 +990,32 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
       bAvoidLineConstructor = Standard_False;
     }
   }
+
+  typl=L->ArcType();
+
   //
   // Line Constructor
   if(!bAvoidLineConstructor) {
     myLConstruct.Perform(L);
     //
     bDone=myLConstruct.IsDone();
-    aNbParts=myLConstruct.NbParts();
-    if (!bDone|| !aNbParts) {
+    if(!bDone)
+    {
       return;
     }
+
+    if(typl != IntPatch_Restriction)
+    {
+      aNbParts=myLConstruct.NbParts();
+      if (aNbParts <= 0)
+      {
+        return;
+      }
+    }
   }
   // Do the Curve
   
   
-  typl=L->ArcType();
   switch (typl) {
   //########################################  
   // Line, Parabola, Hyperbola
@@ -1271,10 +1045,14 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
     //
     aNbParts=myLConstruct.NbParts();
     for (i=1; i<=aNbParts; i++) {
+      Standard_Boolean bFNIt, bLPIt;
+      //
       myLConstruct.Part(i, fprm, lprm);
-      
-      if (!Precision::IsNegativeInfinite(fprm) && 
-          !Precision::IsPositiveInfinite(lprm)) {
+        //
+      bFNIt=Precision::IsNegativeInfinite(fprm);
+      bLPIt=Precision::IsPositiveInfinite(lprm);
+      //
+      if (!bFNIt && !bLPIt) {
         //
         IntTools_Curve aCurve;
         //
@@ -1292,7 +1070,8 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
         aCurve.SetCurve(new Geom_TrimmedCurve(newc, fprm, lprm));
         if(myApprox1) { 
           Handle (Geom2d_Curve) C2d;
-          BuildPCurves(fprm, lprm, Tolpc, myHS1->ChangeSurface().Surface(), newc, C2d);
+          GeomInt_IntSS::BuildPCurves(fprm, lprm, Tolpc,
+                myHS1->ChangeSurface().Surface(), newc, C2d);
           if(Tolpc>myTolReached2d || myTolReached2d==0.) { 
             myTolReached2d=Tolpc;
           }
@@ -1304,10 +1083,11 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
             //
             aCurve.SetFirstCurve2d(H1);
           }
-        
+        //
         if(myApprox2) { 
           Handle (Geom2d_Curve) C2d;
-          BuildPCurves(fprm,lprm,Tolpc,myHS2->ChangeSurface().Surface(),newc,C2d);
+          GeomInt_IntSS::BuildPCurves(fprm, lprm, Tolpc,
+                    myHS2->ChangeSurface().Surface(), newc, C2d);
           if(Tolpc>myTolReached2d || myTolReached2d==0.) { 
             myTolReached2d=Tolpc;
           }
@@ -1320,25 +1100,24 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
           aCurve.SetSecondCurve2d(H1);
         }
         mySeqOfCurve.Append(aCurve);
-      } // end of if (!Precision::IsNegativeInfinite(fprm) &&  !Precision::IsPositiveInfinite(lprm))
+      } //if (!bFNIt && !bLPIt) {
       else {
         //  on regarde si on garde
         //
-        Standard_Boolean bFNIt, bLPIt;
         Standard_Real aTestPrm, dT=100.;
-
-        bFNIt=Precision::IsNegativeInfinite(fprm);
-        bLPIt=Precision::IsPositiveInfinite(lprm);
-        
+        //
         aTestPrm=0.;
-        
         if (bFNIt && !bLPIt) {
           aTestPrm=lprm-dT;
         }
         else if (!bFNIt && bLPIt) {
           aTestPrm=fprm+dT;
         }
-        
+        else {
+          // i.e, if (bFNIt && bLPIt)
+          aTestPrm=IntTools_Tools::IntermediatePoint(-dT, dT);
+        }
+        //
         gp_Pnt ptref(newc->Value(aTestPrm));
         //
         GeomAbs_SurfaceType typS1 = myHS1->GetType();
@@ -1348,8 +1127,7 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
             typS1 == GeomAbs_SurfaceOfRevolution ||
             typS2 == GeomAbs_SurfaceOfExtrusion ||
             typS2 == GeomAbs_OffsetSurface ||
-            typS2 == GeomAbs_SurfaceOfRevolution) 
-        {
+            typS2 == GeomAbs_SurfaceOfRevolution) {
           Handle(Geom2d_BSplineCurve) H1;
           mySeqOfCurve.Append(IntTools_Curve(newc, H1, H1));
           continue;
@@ -1368,7 +1146,7 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
           mySeqOfCurve.Append(IntTools_Curve(newc, H1, H1));
         }
       }
-    }// end of for (i=1; i<=myLConstruct.NbParts(); i++)
+    }// for (i=1; i<=aNbParts; i++) {
   }// case IntPatch_Lin:  case IntPatch_Parabola:  case IntPatch_Hyperbola:
     break;
 
@@ -1477,7 +1255,8 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
         if (typl == IntPatch_Circle || typl == IntPatch_Ellipse) {//// 
           if(myApprox1) { 
             Handle (Geom2d_Curve) C2d;
-            BuildPCurves(fprm,lprm,Tolpc,myHS1->ChangeSurface().Surface(),newc,C2d);
+            GeomInt_IntSS::BuildPCurves(fprm, lprm, Tolpc, 
+                        myHS1->ChangeSurface().Surface(), newc, C2d);
             if(Tolpc>myTolReached2d || myTolReached2d==0) { 
               myTolReached2d=Tolpc;
             }
@@ -1492,7 +1271,8 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
 
           if(myApprox2) { 
             Handle (Geom2d_Curve) C2d;
-            BuildPCurves(fprm,lprm,Tolpc,myHS2->ChangeSurface().Surface(),newc,C2d);
+            GeomInt_IntSS::BuildPCurves(fprm,lprm,Tolpc,
+                    myHS2->ChangeSurface().Surface(),newc,C2d);
             if(Tolpc>myTolReached2d || myTolReached2d==0) { 
               myTolReached2d=Tolpc;
             }
@@ -1528,7 +1308,8 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
             
             if(myApprox1) { 
               Handle (Geom2d_Curve) C2d;
-              BuildPCurves(fprm,lprm,Tolpc,myHS1->ChangeSurface().Surface(),newc,C2d);
+              GeomInt_IntSS::BuildPCurves(fprm,lprm,Tolpc,
+                    myHS1->ChangeSurface().Surface(),newc,C2d);
               if(Tolpc>myTolReached2d || myTolReached2d==0) { 
                 myTolReached2d=Tolpc;
               }
@@ -1542,7 +1323,8 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
 
             if(myApprox2) { 
               Handle (Geom2d_Curve) C2d;
-              BuildPCurves(fprm,lprm,Tolpc,myHS2->ChangeSurface().Surface(),newc,C2d);
+              GeomInt_IntSS::BuildPCurves(fprm,lprm,Tolpc,
+                    myHS2->ChangeSurface().Surface(),newc,C2d);
               if(Tolpc>myTolReached2d || myTolReached2d==0) { 
                 myTolReached2d=Tolpc;
               }
@@ -1579,7 +1361,8 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
               
               if(myApprox1) { 
                 Handle (Geom2d_Curve) C2d;
-                BuildPCurves(fprm, lprm, Tolpc, myHS1->ChangeSurface().Surface(), newc, C2d);
+                GeomInt_IntSS::BuildPCurves(fprm, lprm, Tolpc, 
+                        myHS1->ChangeSurface().Surface(), newc, C2d);
                 if(Tolpc>myTolReached2d || myTolReached2d==0) { 
                   myTolReached2d=Tolpc;
                 }
@@ -1593,7 +1376,8 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
                 
               if(myApprox2) { 
                 Handle (Geom2d_Curve) C2d;
-                BuildPCurves(fprm, lprm, Tolpc,myHS2->ChangeSurface().Surface(), newc, C2d);
+                GeomInt_IntSS::BuildPCurves(fprm, lprm, Tolpc,
+                        myHS2->ChangeSurface().Surface(), newc, C2d);
                 if(Tolpc>myTolReached2d || myTolReached2d==0) { 
                   myTolReached2d=Tolpc;
                 }
@@ -1807,6 +1591,11 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
   case IntPatch_Walking:{
     Handle(IntPatch_WLine) WL = 
       Handle(IntPatch_WLine)::DownCast(L);
+
+#ifdef OCCT_DEBUG
+    //WL->Dump(0);
+#endif
+
     //
     Standard_Integer ifprm, ilprm;
     //
@@ -2095,9 +1884,11 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
               }
               //
               mySeqOfCurve.Append(aCurve);
+
             }//if(typs1 == GeomAbs_Plane) {
             
-            else if(typs2 == GeomAbs_Plane) { 
+            else if(typs2 == GeomAbs_Plane)
+            {
               const AppParCurves_MultiBSpCurve& mbspc = theapp3d.Value(j);
               nbpoles = mbspc.NbPoles();
               
@@ -2206,6 +1997,7 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
               } else {
                 mySeqOfCurve.Append(aCurve);
               }
+
             }// else if(typs2 == GeomAbs_Plane)
             //
             else { //typs2 != GeomAbs_Plane && typs1 != GeomAbs_Plane
@@ -2258,7 +2050,8 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
 
                   Handle(Geom2d_Curve) C2d;
                   Standard_Real aTol = myTolApprox;
-                  BuildPCurves(fprm, lprm, aTol, myHS1->ChangeSurface().Surface(), BS, C2d);
+                  GeomInt_IntSS::BuildPCurves(fprm, lprm, aTol,
+                            myHS1->ChangeSurface().Surface(), BS, C2d);
                   BS1 = Handle(Geom2d_BSplineCurve)::DownCast(C2d);
                   aCurve.SetFirstCurve2d(BS1);
                 }
@@ -2288,7 +2081,8 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
 
                   Handle(Geom2d_Curve) C2d;
                   Standard_Real aTol = myTolApprox;
-                  BuildPCurves(fprm, lprm, aTol, myHS2->ChangeSurface().Surface(), BS, C2d);
+                  GeomInt_IntSS::BuildPCurves(fprm, lprm, aTol,
+                            myHS2->ChangeSurface().Surface(), BS, C2d);
                   BS2 = Handle(Geom2d_BSplineCurve)::DownCast(C2d);
                   aCurve.SetSecondCurve2d(BS2);
                 }
@@ -2310,104 +2104,90 @@ static Standard_Boolean isTreatAnalityc(const TopoDS_Face& theF1,
     break;
     
   case IntPatch_Restriction: 
-    break;
-  default:
-    break;
+    {
+      Handle(IntPatch_RLine) RL = 
+        Handle(IntPatch_RLine)::DownCast(L);
+      Handle(Geom_Curve) aC3d;
+      Handle(Geom2d_Curve) aC2d1, aC2d2;
+      Standard_Real aTolReached;
+      GeomInt_IntSS::TreatRLine(RL, myHS1, myHS2, aC3d,
+                                  aC2d1, aC2d2, aTolReached);
+
+      if(aC3d.IsNull())
+        break;
 
-  }
-}
+      Bnd_Box2d aBox1, aBox2;
 
-//=======================================================================
-//function : BuildPCurves
-//purpose  : 
-//=======================================================================
-void BuildPCurves (Standard_Real f,
-                   Standard_Real l,
-                   Standard_Real& Tol,
-                   const Handle (Geom_Surface)& S,
-                   const Handle (Geom_Curve)&   C,
-                   Handle (Geom2d_Curve)& C2d)
-{
-  if (!C2d.IsNull()) {
-    return;
-  }
-  //
-  Standard_Real umin,umax,vmin,vmax;
-  // 
-  S->Bounds(umin, umax, vmin, vmax);
-  // in class ProjLib_Function the range of parameters is shrank by 1.e-09
-  if((l - f) > 2.e-09) {
-    C2d = GeomProjLib::Curve2d(C,f,l,S,umin,umax,vmin,vmax,Tol);
-    //
-    if (C2d.IsNull()) {
-      // proj. a circle that goes through the pole on a sphere to the sphere     
-      Tol += Precision::Confusion();
-      C2d = GeomProjLib::Curve2d(C,f,l,S,Tol);
-    }
-  }
-  else {
-    if((l - f) > Epsilon(Abs(f))) {
-      GeomAPI_ProjectPointOnSurf aProjector1, aProjector2;
-      gp_Pnt P1 = C->Value(f);
-      gp_Pnt P2 = C->Value(l);
-      aProjector1.Init(P1, S);
-      aProjector2.Init(P2, S);
-      
-      if(aProjector1.IsDone() && aProjector2.IsDone()) {
-        Standard_Real U=0., V=0.;
-        aProjector1.LowerDistanceParameters(U, V);
-        gp_Pnt2d p1(U, V);
-        
-        aProjector2.LowerDistanceParameters(U, V);
-        gp_Pnt2d p2(U, V);
+      const Standard_Real aU1f = myHS1->FirstUParameter(),
+                          aV1f = myHS1->FirstVParameter(),
+                          aU1l = myHS1->LastUParameter(),
+                          aV1l = myHS1->LastVParameter();
+      const Standard_Real aU2f = myHS2->FirstUParameter(),
+                          aV2f = myHS2->FirstVParameter(),
+                          aU2l = myHS2->LastUParameter(),
+                          aV2l = myHS2->LastVParameter();
+
+      aBox1.Add(gp_Pnt2d(aU1f, aV1f));
+      aBox1.Add(gp_Pnt2d(aU1l, aV1l));
+      aBox2.Add(gp_Pnt2d(aU2f, aV2f));
+      aBox2.Add(gp_Pnt2d(aU2l, aV2l));
+
+      GeomInt_VectorOfReal anArrayOfParameters;
         
-        if(p1.Distance(p2) > gp::Resolution()) {
-          TColgp_Array1OfPnt2d poles(1,2);
-          TColStd_Array1OfReal knots(1,2);
-          TColStd_Array1OfInteger mults(1,2);
-          poles(1) = p1;
-          poles(2) = p2;
-          knots(1) = f;
-          knots(2) = l;
-          mults(1) = mults(2) = 2;
-          
-          C2d = new Geom2d_BSplineCurve(poles,knots,mults,1);
-          
-          // compute reached tolerance.begin
-          gp_Pnt PMid = C->Value((f + l) * 0.5);
-          aProjector1.Perform(PMid);
-          
-          if(aProjector1.IsDone()) {
-            aProjector1.LowerDistanceParameters(U, V);
-            gp_Pnt2d pmidproj(U, V);
-            gp_Pnt2d pmidcurve2d = C2d->Value((f + l) * 0.5);
-            Standard_Real adist = pmidcurve2d.Distance(pmidproj);
-            Tol = (adist > Tol) ? adist : Tol;
-          }
-          // compute reached tolerance.end
+      //We consider here that the intersection line is same-parameter-line
+      anArrayOfParameters.Append(aC3d->FirstParameter());
+      anArrayOfParameters.Append(aC3d->LastParameter());
+
+      GeomInt_IntSS::
+        TrimILineOnSurfBoundaries(aC2d1, aC2d2, aBox1, aBox2, anArrayOfParameters);
+
+      const Standard_Integer aNbIntersSolutionsm1 = anArrayOfParameters.Length() - 1;
+
+      //Trim RLine found.
+      for(Standard_Integer anInd = 0; anInd < aNbIntersSolutionsm1; anInd++)
+      {
+        const Standard_Real aParF = anArrayOfParameters(anInd),
+                            aParL = anArrayOfParameters(anInd+1);
+
+        if((aParL - aParF) <= Precision::PConfusion())
+          continue;
+
+        const Standard_Real aPar = 0.5*(aParF + aParL);
+        gp_Pnt2d aPt;
+
+        Handle(Geom2d_Curve) aCurv2d1, aCurv2d2;
+        if(!aC2d1.IsNull())
+        {
+          aC2d1->D0(aPar, aPt);
+
+          if(aBox1.IsOut(aPt))
+            continue;
+
+          if(myApprox1)
+            aCurv2d1 = new Geom2d_TrimmedCurve(aC2d1, aParF, aParL);
+        }
+
+        if(!aC2d2.IsNull())
+        {
+          aC2d2->D0(aPar, aPt);
+
+          if(aBox2.IsOut(aPt))
+            continue;
+
+          if(myApprox2)
+            aCurv2d2 = new Geom2d_TrimmedCurve(aC2d2, aParF, aParL);
         }
+
+        Handle(Geom_Curve) aCurv3d = new Geom_TrimmedCurve(aC3d, aParF, aParL);
+
+        IntTools_Curve aIC(aCurv3d, aCurv2d1, aCurv2d2);
+        mySeqOfCurve.Append(aIC);
       }
     }
-  }
-  //
-  if (S->IsUPeriodic() && !C2d.IsNull()) {
-    // Recadre dans le domaine UV de la face
-    Standard_Real aTm, U0, aEps, period, du, U0x;
-    Standard_Boolean bAdjust;
-    //
-    aEps = Precision::PConfusion();
-    period = S->UPeriod();
-    //
-    aTm = .5*(f + l);
-    gp_Pnt2d pm = C2d->Value(aTm);
-    U0 = pm.X();
-    //
-    bAdjust = 
-      IntTools_Tools::AdjustPeriodic(U0, umin, umax, period, U0x, du, aEps);
-    if (bAdjust) {
-      gp_Vec2d T1(du, 0.);
-      C2d->Translate(T1);
-    }
+    break;
+  default:
+    break;
+
   }
 }
 
@@ -2656,26 +2436,30 @@ Handle(Geom2d_BSplineCurve) MakeBSpline2d(const Handle(IntPatch_WLine)& theWLine
   //
   if(!isuperiodic && enlarge) {
 
-    if((theumin - uinf) > delta )
+    if(!Precision::IsInfinite(theumin) &&
+        ((theumin - uinf) > delta))
       theumin -= delta;
     else {
       theumin = uinf;
     }
 
-    if((usup - theumax) > delta )
+    if(!Precision::IsInfinite(theumax) &&
+        ((usup - theumax) > delta))
       theumax += delta;
     else
       theumax = usup;
   }
   //
   if(!isvperiodic && enlarge) {
-    if((thevmin - vinf) > delta ) {
+    if(!Precision::IsInfinite(thevmin) &&
+        ((thevmin - vinf) > delta)) {
       thevmin -= delta;
     }
     else { 
       thevmin = vinf;
     }
-    if((vsup - thevmax) > delta ) {
+    if(!Precision::IsInfinite(thevmax) &&
+        ((vsup - thevmax) > delta)) {
       thevmax += delta;
     }
     else {
@@ -3007,15 +2791,53 @@ Standard_Boolean IsDegeneratedZone(const gp_Pnt2d& aP2d,
   return !bFlag;
 }
 
+// Check if aNextPnt lies inside of tube build on aBasePnt and aBaseVec.
+// In 2d space.
+static Standard_Boolean IsInsideIn2d(const gp_Pnt2d& aBasePnt,
+                                     const gp_Vec2d& aBaseVec,
+                                     const gp_Pnt2d& aNextPnt,
+                                     const Standard_Real aSquareMaxDist)
+{
+  gp_Vec2d aVec2d(aBasePnt, aNextPnt);
+
+  //d*d = (basevec^(nextpnt-basepnt))**2 / basevec**2
+  Standard_Real aCross = aVec2d.Crossed(aBaseVec);
+  Standard_Real aSquareDist = aCross * aCross
+                            / aBaseVec.SquareMagnitude();
+
+  return (aSquareDist <= aSquareMaxDist);
+}
+
+// Check if aNextPnt lies inside of tube build on aBasePnt and aBaseVec.
+// In 3d space.
+static Standard_Boolean IsInsideIn3d(const gp_Pnt& aBasePnt,
+                                     const gp_Vec& aBaseVec,
+                                     const gp_Pnt& aNextPnt,
+                                     const Standard_Real aSquareMaxDist)
+{
+  gp_Vec aVec(aBasePnt, aNextPnt);
+
+  //d*d = (basevec^(nextpnt-basepnt))**2 / basevec**2
+  Standard_Real aSquareDist = aVec.CrossSquareMagnitude(aBaseVec)
+                            / aBaseVec.SquareMagnitude();
+
+  return (aSquareDist <= aSquareMaxDist);
+}
+
 //=========================================================================
 // static function : ComputePurgedWLine
 // purpose : Removes equal points (leave one of equal points) from theWLine
 //           and recompute vertex parameters.
+//           Removes exceed points using tube criteria:
+//           delete 7D point if it lies near to expected lines in 2d and 3d.
+//           Each task (2d, 2d, 3d) have its own tolerance and checked separately.
 //           Returns new WLine or null WLine if the number
 //           of the points is less than 2.
 //=========================================================================
-Handle(IntPatch_WLine) ComputePurgedWLine(const Handle(IntPatch_WLine)& theWLine) {
+Handle(IntPatch_WLine) ComputePurgedWLine(const Handle(IntPatch_WLine)       &theWLine,
+                                          const Handle(GeomAdaptor_HSurface) &theS1,
+                                          const Handle(GeomAdaptor_HSurface) &theS2)
+{
   Standard_Integer i, k, v, nb, nbvtx;
   Handle(IntPatch_WLine) aResult;
   nbvtx = theWLine->NbVertex();
@@ -3039,7 +2861,6 @@ Handle(IntPatch_WLine) ComputePurgedWLine(const Handle(IntPatch_WLine)& theWLine
   for(v = 1; v <= nbvtx; v++) {
     aLocalWLine->AddVertex(theWLine->Vertex(v));
   }
-  
   for(i = 1; i <= aLineOn2S->NbPoints(); i++) {
     Standard_Integer aStartIndex = i + 1;
     Standard_Integer anEndIndex = i + 5;
@@ -3057,10 +2878,24 @@ Handle(IntPatch_WLine) ComputePurgedWLine(const Handle(IntPatch_WLine)& theWLine
         IntSurf_PntOn2S p1 = aLineOn2S->Value(i);
         IntSurf_PntOn2S p2 = aLineOn2S->Value(k);
         
-        if(p1.Value().IsEqual(p2.Value(), gp::Resolution())) {
+        Standard_Real UV[8];
+        p1.Parameters(UV[0], UV[1], UV[2], UV[3]);
+        p2.Parameters(UV[4], UV[5], UV[6], UV[7]);
+
+        Standard_Real aMax = Abs(UV[0]);
+        for(Standard_Integer anIdx = 1; anIdx < 8; anIdx++)
+        {
+          if (aMax < Abs(UV[anIdx]))
+            aMax = Abs(UV[anIdx]);
+        }
+
+        if(p1.Value().IsEqual(p2.Value(), gp::Resolution()) ||
+           Abs(UV[0] - UV[4]) + Abs(UV[1] - UV[5]) < 1.0e-16 * aMax ||
+           Abs(UV[2] - UV[6]) + Abs(UV[3] - UV[7]) < 1.0e-16 * aMax )
+        {
           aTmpWLine = aLocalWLine;
           aLocalWLine = new IntPatch_WLine(aLineOn2S, Standard_False);
-
+          
           for(v = 1; v <= aTmpWLine->NbVertex(); v++) {
             IntPatch_Point aVertex = aTmpWLine->Vertex(v);
             Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
@@ -3079,7 +2914,211 @@ Handle(IntPatch_WLine) ComputePurgedWLine(const Handle(IntPatch_WLine)& theWLine
     }
   }
 
-  if(aLineOn2S->NbPoints() > 1) {
+  if (aLineOn2S->NbPoints() <= 2)
+  {
+    if (aLineOn2S->NbPoints() == 2)
+      return aLocalWLine;
+    else
+      return aResult;
+  }
+
+  const Standard_Integer aMinNbBadDistr = 15;
+  const Standard_Integer aNbSingleBezier = 30;
+  // Avoid purge in case of C0 continuity:
+  // Intersection approximator may produce invalid curve after purge, example:
+  // bugs modalg_5 bug24731,
+  // Do not run purger when base number of points is too small.
+  if (theS1->UContinuity() == GeomAbs_C0 ||
+      theS1->VContinuity() == GeomAbs_C0 ||
+      theS2->UContinuity() == GeomAbs_C0 ||
+      theS2->VContinuity() == GeomAbs_C0 ||
+      nb < aNbSingleBezier)
+  {
+    return aLocalWLine;
+  }
+
+  // 1 - Delete point.
+  // 0 - Store point.
+  // -1 - Vertex point (not delete).
+  NCollection_Array1<Standard_Integer> aNewPointsHash(1, aLineOn2S->NbPoints());
+  for(i = 1; i <= aLineOn2S->NbPoints(); i++)
+    aNewPointsHash.SetValue(i, 0);
+
+  for(v = 1; v <= aLocalWLine->NbVertex(); v++) 
+  {
+    IntPatch_Point aVertex = aLocalWLine->Vertex(v);
+    Standard_Integer avertexindex = (Standard_Integer)aVertex.ParameterOnLine();
+    aNewPointsHash.SetValue(avertexindex, -1);
+  }
+
+  // Workaround to handle case of small amount points after purge.
+  // Test "boolean boptuc_complex B5" and similar.
+  Standard_Integer aNbPnt = 0;
+
+  // Inital computations.
+  Standard_Real UonS1[3], VonS1[3], UonS2[3], VonS2[3];
+  aLineOn2S->Value(1).ParametersOnS1(UonS1[0], VonS1[0]);
+  aLineOn2S->Value(2).ParametersOnS1(UonS1[1], VonS1[1]);
+  aLineOn2S->Value(1).ParametersOnS2(UonS2[0], VonS2[0]);
+  aLineOn2S->Value(2).ParametersOnS2(UonS2[1], VonS2[1]);
+
+  gp_Pnt2d aBase2dPnt1(UonS1[0], VonS1[0]);
+  gp_Pnt2d aBase2dPnt2(UonS2[0], VonS2[0]);
+  gp_Vec2d aBase2dVec1(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0]);
+  gp_Vec2d aBase2dVec2(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0]);
+  gp_Pnt   aBase3dPnt = aLineOn2S->Value(1).Value();
+  gp_Vec   aBase3dVec(aLineOn2S->Value(1).Value(), aLineOn2S->Value(2).Value());
+
+  // Choose base tolerance and scale it to pipe algorithm.
+  const Standard_Real aBaseTolerance = Precision::Approximation();
+  Standard_Real aResS1Tol = Min(theS1->UResolution(aBaseTolerance),
+                                theS1->VResolution(aBaseTolerance));
+  Standard_Real aResS2Tol = Min(theS2->UResolution(aBaseTolerance),
+                                theS2->VResolution(aBaseTolerance));
+  Standard_Real aTol1 = aResS1Tol * aResS1Tol;
+  Standard_Real aTol2 = aResS2Tol * aResS2Tol;
+  Standard_Real aTol3d = aBaseTolerance * aBaseTolerance;
+
+  const Standard_Real aLimitCoeff = 0.99 * 0.99;
+  for(i = 3; i <= aLineOn2S->NbPoints(); i++)
+  {
+    Standard_Boolean isDeleteState = Standard_False;
+
+    aLineOn2S->Value(i).ParametersOnS1(UonS1[2], VonS1[2]);
+    aLineOn2S->Value(i).ParametersOnS2(UonS2[2], VonS2[2]);
+    gp_Pnt2d aPnt2dOnS1(UonS1[2], VonS1[2]);
+    gp_Pnt2d aPnt2dOnS2(UonS2[2], VonS2[2]);
+    const gp_Pnt& aPnt3d = aLineOn2S->Value(i).Value();
+
+    if (aNewPointsHash(i - 1) != - 1 &&
+        IsInsideIn2d(aBase2dPnt1, aBase2dVec1, aPnt2dOnS1, aTol1) &&
+        IsInsideIn2d(aBase2dPnt2, aBase2dVec2, aPnt2dOnS2, aTol2) &&
+        IsInsideIn3d(aBase3dPnt, aBase3dVec, aPnt3d, aTol3d) )
+    {
+      // Handle possible uneven parametrization on one of 2d subspaces.
+      // Delete point only when expected lengths are close to each other (aLimitCoeff).
+      // Example:
+      // c2d1 - line
+      // c3d - line
+      // c2d2 - geometrically line, but have uneven parametrization -> c2d2 is bspline.
+      gp_XY aPntOnS1[2]= { gp_XY(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0])
+                         , gp_XY(UonS1[2] - UonS1[1], VonS1[2] - VonS1[1])};
+      gp_XY aPntOnS2[2]= { gp_XY(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0])
+                         , gp_XY(UonS2[2] - UonS2[1], VonS2[2] - VonS2[1])};
+
+      Standard_Real aStepOnS1 = aPntOnS1[0].SquareModulus() / aPntOnS1[1].SquareModulus();
+      Standard_Real aStepOnS2 = aPntOnS2[0].SquareModulus() / aPntOnS2[1].SquareModulus();
+
+      Standard_Real aStepCoeff = Min(aStepOnS1, aStepOnS2) / Max(aStepOnS1, aStepOnS2);
+
+      if (aStepCoeff > aLimitCoeff)
+      {
+        // Set hash flag to "Delete" state.
+        isDeleteState = Standard_True;
+        aNewPointsHash.SetValue(i - 1, 1);
+
+        // Change middle point.
+        UonS1[1] = UonS1[2];
+        UonS2[1] = UonS2[2];
+        VonS1[1] = VonS1[2];
+        VonS2[1] = VonS2[2];
+      }
+    }
+
+    if (!isDeleteState)
+    {
+      // Compute new pipe parameters.
+      UonS1[0] = UonS1[1];
+      VonS1[0] = VonS1[1];
+      UonS2[0] = UonS2[1];
+      VonS2[0] = VonS2[1];
+
+      UonS1[1] = UonS1[2];
+      VonS1[1] = VonS1[2];
+      UonS2[1] = UonS2[2];
+      VonS2[1] = VonS2[2];
+
+      aBase2dPnt1.SetCoord(UonS1[0], VonS1[0]);
+      aBase2dPnt2.SetCoord(UonS2[0], VonS2[0]);
+      aBase2dVec1.SetCoord(UonS1[1] - UonS1[0], VonS1[1] - VonS1[0]);
+      aBase2dVec2.SetCoord(UonS2[1] - UonS2[0], VonS2[1] - VonS2[0]);
+      aBase3dPnt = aLineOn2S->Value(i - 1).Value();
+      aBase3dVec = gp_Vec(aLineOn2S->Value(i - 1).Value(), aLineOn2S->Value(i).Value());
+
+      aNbPnt++;
+    }
+  }
+
+  // Workaround to handle case of small amount of points after purge.
+  // Test "boolean boptuc_complex B5" and similar.
+  // This is possible since there are at least two points.
+  if (aNewPointsHash(1) == -1 &&
+      aNewPointsHash(2) == -1 &&
+      aNbPnt <= 3)
+  {
+    // Delete first.
+    aNewPointsHash(1) = 1;
+  }
+  if (aNewPointsHash(aLineOn2S->NbPoints() - 1) == -1 &&
+      aNewPointsHash(aLineOn2S->NbPoints()    ) == -1 &&
+      aNbPnt <= 3)
+  {
+    // Delete last.
+    aNewPointsHash(aLineOn2S->NbPoints() ) = 1;
+  }
+
+  // Purgre when too small amount of points left.
+  if (aNbPnt <= 2)
+  {
+    for(i = aNewPointsHash.Lower(); i <= aNewPointsHash.Upper(); i++)
+    {
+      if (aNewPointsHash(i) != -1)
+      {
+        aNewPointsHash(i) = 1;
+      }
+    }
+  }
+
+  // Handle possible bad distribution of points, 
+  // which are will converted into one single bezier curve (less than 30 points).
+  // Make distribution more even:
+  // max step will be nearly to 0.1 of param distance.
+  if (aNbPnt + 2 > aMinNbBadDistr &&
+      aNbPnt + 2 < aNbSingleBezier )
+  {
+    for(Standard_Integer anIdx = 1; anIdx <= 8; anIdx++)
+    {
+      Standard_Integer aHashIdx = 
+        Standard_Integer(anIdx * aLineOn2S->NbPoints() / 9);
+
+      //Store this point.
+      aNewPointsHash(aHashIdx) = 0;
+    }
+  }
+
+  aTmpWLine = aLocalWLine;
+  Handle(IntSurf_LineOn2S) aPurgedLineOn2S = new IntSurf_LineOn2S();
+  aLocalWLine = new IntPatch_WLine(aPurgedLineOn2S, Standard_False);
+  Standard_Integer anOldLineIdx = 1, aVertexIdx = 1;
+  for(i = 1; i <= aNewPointsHash.Upper(); i++)
+  {
+    if (aNewPointsHash(i) == 0)
+    {
+      // Store this point.
+      aPurgedLineOn2S->Add(aLineOn2S->Value(i));
+      anOldLineIdx++;
+    }
+    else if (aNewPointsHash(i) == -1)
+    {
+      // Add vertex.
+      IntPatch_Point aVertex = aTmpWLine->Vertex(aVertexIdx++);
+      aVertex.SetParameter(anOldLineIdx++);
+      aLocalWLine->AddVertex(aVertex);
+      aPurgedLineOn2S->Add(aLineOn2S->Value(i));
+    }
+  }
+
+  if(aPurgedLineOn2S->NbPoints() > 1) {
     aResult = aLocalWLine;
   }
   return aResult;
@@ -3557,7 +3596,7 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
                                       const Handle(GeomAdaptor_HSurface)&            theSurface2,
                                       const TopoDS_Face&                             theFace1,
                                       const TopoDS_Face&                             theFace2,
-                                      const IntTools_LineConstructor&                theLConstructor,
+                                      const GeomInt_LineConstructor&                 theLConstructor,
                                       const Standard_Boolean                         theAvoidLConstructor,
                                       IntPatch_SequenceOfLine&                       theNewLines,
                                       Standard_Real&                                 theReachedTol3d,
@@ -3645,7 +3684,7 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
           aParameter=V;
         }
         
-        IntTools_Tools::AdjustPeriodic(aParameter, 
+        GeomInt::AdjustPeriodic(aParameter, 
                                        alowerboundary, 
                                        aupperboundary, 
                                        aPeriod,
@@ -3722,9 +3761,6 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
       continue;
     }
     const TColStd_ListOfInteger& aListOfIndex = anArrayOfLines.Value(i);
-    if(aListOfIndex.Extent() < 2) {
-      continue;
-    }
     TColStd_ListOfInteger aListOfFLIndex;
 
     for(j = 0; j < 2; j++) {
@@ -3740,7 +3776,15 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
       const IntSurf_PntOn2S& aPoint = theWLine->Point(anIndex);
 
       IntSurf_PntOn2S aNewP = aPoint;
-      
+      if(aListOfIndex.Extent() < 2) {
+        aSeqOfPntOn2S->Add(aNewP);
+        aListOfFLIndex.Append(aSeqOfPntOn2S->NbPoints());
+        continue;
+      }
+      //
+      Standard_Integer iFirst = aListOfIndex.First();
+      Standard_Integer iLast  = aListOfIndex.Last();
+      //
       for(Standard_Integer surfit = 0; surfit < 2; surfit++) {
 
         Handle(GeomAdaptor_HSurface) aGASurface = (surfit == 0) ? theSurface1 : theSurface2;
@@ -3782,7 +3826,7 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
           else {
             Standard_Real aPeriod     = (parit == 0) ? aGASurface->UPeriod() : aGASurface->VPeriod();
             Standard_Real anoffset, anAdjustPar;
-            IntTools_Tools::AdjustPeriodic(aParameter, alowerboundary, aupperboundary,
+            GeomInt::AdjustPeriodic(aParameter, alowerboundary, aupperboundary,
                                            aPeriod, anAdjustPar, anoffset);
 
             bIsPointOnBoundary=
@@ -3793,11 +3837,11 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
               nbboundaries++;
             }
             else {
-              //check neighbourhood of boundary
-              Standard_Real anEpsilon = aResolution * 100.;
-              Standard_Real aPart = ( aupperboundary - alowerboundary ) * 0.1;
-              anEpsilon = ( anEpsilon > aPart ) ? aPart : anEpsilon;
-                
+            //check neighbourhood of boundary
+            Standard_Real anEpsilon = aResolution * 100.;
+            Standard_Real aPart = ( aupperboundary - alowerboundary ) * 0.1;
+            anEpsilon = ( anEpsilon > aPart ) ? aPart : anEpsilon;
+            
               bIsNearBoundary = IsPointOnBoundary(anAdjustPar, alowerboundary, aupperboundary, 
                                                   anEpsilon, bIsOnFirstBoundary);
 
@@ -3810,7 +3854,7 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
           gp_Pnt2d aPZone = (surfit == 0) ? aTanZoneS1->Value(zIt) : aTanZoneS2->Value(zIt);
           Standard_Real aZoneRadius = aTanZoneRadius->Value(zIt);
 
-          Standard_Integer aneighbourpointindex1 = (j == 0) ? aListOfIndex.First() : aListOfIndex.Last();
+          Standard_Integer aneighbourpointindex1 = (j == 0) ? iFirst : iLast;
           const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
           Standard_Real nU1, nV1;
             
@@ -3847,7 +3891,7 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
             Standard_Real aPeriod     = (bIsUBoundary) ? aGASurface->UPeriod() : aGASurface->VPeriod();
             Standard_Real aParameter = (bIsUBoundary) ? U : V;
             Standard_Real anoffset, anAdjustPar;
-            IntTools_Tools::AdjustPeriodic(aParameter, alowerboundary, aupperboundary, 
+            GeomInt::AdjustPeriodic(aParameter, alowerboundary, aupperboundary, 
                                            aPeriod, anAdjustPar, anoffset);
 
             Standard_Real adist = (bIsFirstBoundary) ? fabs(anAdjustPar - alowerboundary) : fabs(anAdjustPar - aupperboundary);
@@ -3876,7 +3920,7 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
               bCheckAngle1 = Standard_True;
               aNewVec = gp_Vec2d(gp_Pnt2d(nU1, nV1), gp_Pnt2d(anewU, anewV));
 
-              if(aNewVec.SquareMagnitude() < (gp::Resolution() * gp::Resolution())) {
+              if(aNewVec.SquareMagnitude() < gp::Resolution()) {
                 aNewP.SetValue((surfit == 0), anewU, anewV);
                 bCheckAngle1 = Standard_False;
               }
@@ -3885,7 +3929,7 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
               bCheckAngle2 = Standard_True;
               aNewVec = gp_Vec2d(gp_Pnt2d(nU1, nV1), gp_Pnt2d(U, V));
 
-              if(aNewVec.SquareMagnitude() < (gp::Resolution() * gp::Resolution())) {
+              if(aNewVec.SquareMagnitude() < gp::Resolution()) {
                 bCheckAngle2 = Standard_False;
               }
             }
@@ -3894,7 +3938,7 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
               // assume there are at least two points in line (see "if" above)
               Standard_Integer anindexother = aneighbourpointindex;
 
-              while((anindexother <= aListOfIndex.Last()) && (anindexother >= aListOfIndex.First())) {
+              while((anindexother <= iLast) && (anindexother >= iFirst)) {
                 anindexother = (j == 0) ? (anindexother + 1) : (anindexother - 1);
                 const IntSurf_PntOn2S& aPrevNeighbourPoint = theWLine->Point(anindexother);
                 Standard_Real nU2, nV2;
@@ -3905,7 +3949,7 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
                   aPrevNeighbourPoint.ParametersOnS2(nU2, nV2);
                 gp_Vec2d aVecOld(gp_Pnt2d(nU2, nV2), gp_Pnt2d(nU1, nV1));
 
-                if(aVecOld.SquareMagnitude() <= (gp::Resolution() * gp::Resolution())) {
+                if(aVecOld.SquareMagnitude() <= gp::Resolution()) {
                   continue;
                 }
                 else {
@@ -3958,7 +4002,7 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
             else
               anewpoint = gp_Pnt2d( u2, v2 );
             
-            Standard_Integer aneighbourpointindex1 = (j == 0) ? aListOfIndex.First() : aListOfIndex.Last();
+            Standard_Integer aneighbourpointindex1 = (j == 0) ? iFirst : iLast;
             const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
             Standard_Real nU1, nV1;
             
@@ -3998,7 +4042,7 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
           }
           else {
 
-            Standard_Integer aneighbourpointindex1 = (j == 0) ? aListOfIndex.First() : aListOfIndex.Last();
+            Standard_Integer aneighbourpointindex1 = (j == 0) ? iFirst : iLast;
             const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneighbourpointindex1);
             Standard_Real nU1, nV1;
 
@@ -4010,7 +4054,7 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
             gp_Pnt2d ap2(nU1, nV1);
             Standard_Integer aneighbourpointindex2 = aneighbourpointindex1;
 
-            while((aneighbourpointindex2 <= aListOfIndex.Last()) && (aneighbourpointindex2 >= aListOfIndex.First())) {
+            while((aneighbourpointindex2 <= iLast) && (aneighbourpointindex2 >= iFirst)) {
               aneighbourpointindex2 = (j == 0) ? (aneighbourpointindex2 + 1) : (aneighbourpointindex2 - 1);
               const IntSurf_PntOn2S& aPrevNeighbourPoint = theWLine->Point(aneighbourpointindex2);
               Standard_Real nU2, nV2;
@@ -4022,7 +4066,7 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
               ap2.SetX(nU2);
               ap2.SetY(nV2);
 
-              if(ap1.SquareDistance(ap2) > (gp::Resolution() * gp::Resolution())) {
+              if(ap1.SquareDistance(ap2) > gp::Resolution()) {
                 break;
               }
             }  
@@ -4048,7 +4092,7 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
 
                 //Correction of projected coordinates. Begin
                 //Note, it may be shifted on a period
-                Standard_Integer aneindex1 = (j == 0) ? aListOfIndex.First() : aListOfIndex.Last();
+                Standard_Integer aneindex1 = (j == 0) ? iFirst : iLast;
                 const IntSurf_PntOn2S& aNeighbourPoint = theWLine->Point(aneindex1);
                 Standard_Real nUn, nVn;
                 
@@ -4131,10 +4175,6 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
         continue;
       }
       const TColStd_ListOfInteger& aListOfIndex = anArrayOfLines.Value(i);
-
-      if(aListOfIndex.Extent() < 2) {
-        continue;
-      }
       const TColStd_ListOfInteger& aListOfFLIndex = anArrayOfLineEnds.Value(i);
       Standard_Boolean bhasfirstpoint = (aListOfFLIndex.Extent() == 2);
       Standard_Boolean bhaslastpoint = (aListOfFLIndex.Extent() == 2);
@@ -4146,25 +4186,31 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
       if(!bhaslastpoint && !aListOfFLIndex.IsEmpty()) {
         bhaslastpoint = (i != nblines);
       }
-      Standard_Boolean bIsFirstInside = ((ifprm >= aListOfIndex.First()) && (ifprm <= aListOfIndex.Last()));
-      Standard_Boolean bIsLastInside =  ((ilprm >= aListOfIndex.First()) && (ilprm <= aListOfIndex.Last()));
+      
+      Standard_Integer iFirst = aListOfIndex.First();
+      Standard_Integer iLast  = aListOfIndex.Last();
+      Standard_Boolean bIsFirstInside = ((ifprm >= iFirst) && (ifprm <= iLast));
+      Standard_Boolean bIsLastInside =  ((ilprm >= iFirst) && (ilprm <= iLast));
 
       if(!bIsFirstInside && !bIsLastInside) {
-        if((ifprm < aListOfIndex.First()) && (ilprm > aListOfIndex.Last())) {
+        if((ifprm < iFirst) && (ilprm > iLast)) {
           // append whole line, and boundaries if neccesary
           if(bhasfirstpoint) {
-            const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(aListOfFLIndex.First());
+            pit = aListOfFLIndex.First();
+            const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
             aLineOn2S->Add(aP);
           }
           TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
 
           for(; anIt.More(); anIt.Next()) {
-            const IntSurf_PntOn2S& aP = theWLine->Point(anIt.Value());
+            pit = anIt.Value();
+            const IntSurf_PntOn2S& aP = theWLine->Point(pit);
             aLineOn2S->Add(aP);
           }
 
           if(bhaslastpoint) {
-            const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(aListOfFLIndex.Last());
+            pit = aListOfFLIndex.Last();
+            const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
             aLineOn2S->Add(aP);
           }
 
@@ -4199,9 +4245,10 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
         TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
 
         for(; anIt.More(); anIt.Next()) {
-          if((anIt.Value() < ifprm) || (anIt.Value() > ilprm))
+          pit = anIt.Value();
+          if((pit < ifprm) || (pit > ilprm))
             continue;
-          const IntSurf_PntOn2S& aP = theWLine->Point(anIt.Value());
+          const IntSurf_PntOn2S& aP = theWLine->Point(pit);
           aLineOn2S->Add(aP);
         }
       }
@@ -4212,14 +4259,16 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
           TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
 
           for(; anIt.More(); anIt.Next()) {
-            if(anIt.Value() < ifprm)
+            pit = anIt.Value();
+            if(pit < ifprm)
               continue;
-            const IntSurf_PntOn2S& aP = theWLine->Point(anIt.Value());
+            const IntSurf_PntOn2S& aP = theWLine->Point(pit);
             aLineOn2S->Add(aP);
           }
 
           if(bhaslastpoint) {
-            const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(aListOfFLIndex.Last());
+            pit = aListOfFLIndex.Last();
+            const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
             aLineOn2S->Add(aP);
           }
           // check end of split line (end is almost always)
@@ -4249,15 +4298,17 @@ Standard_Boolean DecompositionOfWLine(const Handle(IntPatch_WLine)& theWLine,
         if(bIsLastInside) {
           // append points from first boundary point to ilprm
           if(bhasfirstpoint) {
-            const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(aListOfFLIndex.First());
+            pit = aListOfFLIndex.First();
+            const IntSurf_PntOn2S& aP = aSeqOfPntOn2S->Value(pit);
             aLineOn2S->Add(aP);
           }
           TColStd_ListIteratorOfListOfInteger anIt(aListOfIndex);
 
           for(; anIt.More(); anIt.Next()) {
-            if(anIt.Value() > ilprm)
+            pit = anIt.Value();
+            if(pit > ilprm)
               continue;
-            const IntSurf_PntOn2S& aP = theWLine->Point(anIt.Value());
+            const IntSurf_PntOn2S& aP = theWLine->Point(pit);
             aLineOn2S->Add(aP);
           }
         }
@@ -4851,7 +4902,7 @@ Standard_Integer IndexType(const GeomAbs_SurfaceType aType)
   } 
   return aIndex;
 }
-#ifdef DEB_DUMPWLINE
+#ifdef OCCT_DEBUG_DUMPWLINE
 //=======================================================================
 //function : DumpWLine
 //purpose  : 
@@ -4906,119 +4957,116 @@ void RefineVector(gp_Vec2d& aV2D)
   }
   aV2D.SetCoord(aC[0], aC[1]);
 }
+
 //=======================================================================
-//function : FindMaxSquareDistance
-//purpose  : 
+// Function : FindMaxDistance
+// purpose : 
 //=======================================================================
-Standard_Real FindMaxSquareDistance (const Standard_Real aT1,
-                                     const Standard_Real aT2,
-                                     const Standard_Real aEps,
-                                     const Handle(Geom_Curve)& aC3D,
-                                     const Handle(Geom2d_Curve)& aC2D1,
-                                     const Handle(Geom2d_Curve)& aC2D2,
-                                     const Handle(GeomAdaptor_HSurface)& myHS1,
-                                     const Handle(GeomAdaptor_HSurface)& myHS2,
-                                     const TopoDS_Face& myFace1,
-                                     const TopoDS_Face& myFace2,
-                                     const Handle(IntTools_Context)& myContext)
+Standard_Real FindMaxDistance(const Handle(Geom_Curve)& theCurve,
+                              const Standard_Real theFirst,
+                              const Standard_Real theLast,
+                              const TopoDS_Face& theFace,
+                              const Handle(IntTools_Context)& theContext)
 {
-  Standard_Real aA, aB, aCf, aX1, aX2, aF1, aF2, aX, aF;
+  Standard_Integer aNbS;
+  Standard_Real aT1, aT2, aDt, aD, aDMax, anEps;
   //
-  aCf=1.6180339887498948482045868343656;// =0.5*(1.+sqrt(5.));
-  aA=aT1;
-  aB=aT2;
-  aX1=aB-(aB-aA)/aCf;  
-  aF1=MaxSquareDistance(aX1, 
-                        aC3D, aC2D1, aC2D2, myHS1, myHS2, myFace1, myFace2, myContext);
-  aX2=aA+(aB-aA)/aCf;
-  aF2=MaxSquareDistance(aX2, 
-                        aC3D, aC2D1, aC2D2, myHS1, myHS2, myFace1, myFace2, myContext);
+  aNbS = 11;
+  aDt = (theLast - theFirst) / aNbS;
+  aDMax = 0.;
+  anEps = 1.e-4 * aDt;
   //
-  for(;;) {
+  GeomAPI_ProjectPointOnSurf& aProjPS = theContext->ProjPS(theFace);
+  aT2 = theFirst;
+  for (;;) {
+    aT1 = aT2;
+    aT2 += aDt;
     //
-    if (fabs(aA-aB)<aEps) {
-      aX=0.5*(aA+aB);
-      aF=MaxSquareDistance(aX, 
-                        aC3D, aC2D1, aC2D2, myHS1, myHS2, myFace1, myFace2, myContext);
+    if (aT2 > theLast) {
       break;
     }
-    if (aF1<aF2){
-      aA=aX1;
-      aX1=aX2;
-      aF1=aF2;
-      aX2=aA+(aB-aA)/aCf;
-      aF2=MaxSquareDistance(aX2, 
-                            aC3D, aC2D1, aC2D2, myHS1, myHS2, myFace1, myFace2, myContext);
-      
-    }
-    else {
-      aB=aX2;
-      aX2=aX1;
-      aF2=aF1;
-      aX1=aB-(aB-aA)/aCf; 
-      aF1=MaxSquareDistance(aX1, 
-                            aC3D, aC2D1, aC2D2, myHS1, myHS2, myFace1, myFace2, myContext);
+    //
+    aD = FindMaxDistance(theCurve, aT1, aT2, aProjPS, anEps);
+    if (aD > aDMax) {
+      aDMax = aD;
     }
   }
-  return aF;
+  //
+  return aDMax;
 }
+
 //=======================================================================
-//function : MaxSquareDistance
-//purpose  : 
+// Function : FindMaxDistance
+// purpose : 
 //=======================================================================
-Standard_Real MaxSquareDistance (const Standard_Real aT,
-                                 const Handle(Geom_Curve)& aC3D,
-                                 const Handle(Geom2d_Curve)& aC2D1,
-                                 const Handle(Geom2d_Curve)& aC2D2,
-                                 const Handle(GeomAdaptor_HSurface) myHS1,
-                                 const Handle(GeomAdaptor_HSurface) myHS2,
-                                 const TopoDS_Face& aF1,
-                                 const TopoDS_Face& aF2,
-                                 const Handle(IntTools_Context)& aCtx)
+Standard_Real FindMaxDistance(const Handle(Geom_Curve)& theC,
+                              const Standard_Real theFirst,
+                              const Standard_Real theLast,
+                              GeomAPI_ProjectPointOnSurf& theProjPS,
+                              const Standard_Real theEps)
 {
-  Standard_Boolean bIsDone;
-  Standard_Integer i;
-  Standard_Real aU, aV, aD2Max, aD2;
-  gp_Pnt2d aP2D;
-  gp_Pnt aP, aPS;
+  Standard_Real aA, aB, aCf, aX, aX1, aX2, aF1, aF2, aF;
   //
-  aD2Max=0.;
+  aCf = 0.61803398874989484820458683436564;//(sqrt(5.)-1)/2.;
+  aA = theFirst;
+  aB = theLast;
   //
-  aC3D->D0(aT, aP);
-  if (aC3D.IsNull()) {
-    return aD2Max;
-  }
+  aX1 = aB - aCf * (aB - aA);
+  aF1 = MaxDistance(theC, aX1, theProjPS);
+  aX2 = aA + aCf * (aB - aA);
+  aF2 = MaxDistance(theC, aX2, theProjPS);
   //
-  for (i=0; i<2; ++i) {
-    const Handle(GeomAdaptor_HSurface)& aGHS=(!i) ? myHS1 : myHS2;
-    const TopoDS_Face &aF=(!i) ? aF1 : aF2;
-    const Handle(Geom2d_Curve)& aC2D=(!i) ? aC2D1 : aC2D2;
-    //
-    if (!aC2D.IsNull()) {
-      aC2D->D0(aT, aP2D);
-      aP2D.Coord(aU, aV);
-      aGHS->D0(aU, aV, aPS);
-      aD2=aP.SquareDistance(aPS);
-      if (aD2>aD2Max) {
-        aD2Max=aD2;
-      }
+  for (;;) {
+    if ((aB - aA) < theEps) {
+      break;
     }
     //
-    GeomAPI_ProjectPointOnSurf& aProjector=aCtx->ProjPS(aF);
-    //
-    aProjector.Perform(aP);
-    bIsDone=aProjector.IsDone();
-    if (bIsDone) {
-      aProjector.LowerDistanceParameters(aU, aV);
-      aGHS->D0(aU, aV, aPS);
-      aD2=aP.SquareDistance(aPS);
-      if (aD2>aD2Max) {
-        aD2Max=aD2;
-      }
+    if (aF1 > aF2) {
+      aB = aX2;
+      aX2 = aX1;
+      aF2 = aF1;
+      aX1 = aB - aCf * (aB - aA); 
+      aF1 = MaxDistance(theC, aX1, theProjPS);
+    }
+    else {
+      aA = aX1;
+      aX1 = aX2;
+      aF1 = aF2;
+      aX2 = aA + aCf * (aB - aA);
+      aF2 = MaxDistance(theC, aX2, theProjPS);
     }
   }
   //
-  return aD2Max;
+  aX = 0.5 * (aA + aB);
+  aF = MaxDistance(theC, aX, theProjPS);
+  //
+  if (aF1 > aF) {
+    aF = aF1;
+  }
+  //
+  if (aF2 > aF) {
+    aF = aF2;
+  }
+  //
+  return aF;
+}
+
+//=======================================================================
+// Function : MaxDistance
+// purpose : 
+//=======================================================================
+Standard_Real MaxDistance(const Handle(Geom_Curve)& theC,
+                          const Standard_Real aT,
+                          GeomAPI_ProjectPointOnSurf& theProjPS)
+{
+  Standard_Real aD;
+  gp_Pnt aP;
+  //
+  theC->D0(aT, aP);
+  theProjPS.Perform(aP);
+  aD = theProjPS.NbPoints() ? theProjPS.LowerDistance() : 0.;
+  //
+  return aD;
 }
 
 //=======================================================================
@@ -5094,3 +5142,29 @@ Standard_Real MaxSquareDistance (const Standard_Real aT,
   }
   return !bRet;
 }
+//=======================================================================
+//function : CorrectPlaneBoundaries
+//purpose  : 
+//=======================================================================
+ void CorrectPlaneBoundaries(Standard_Real& aUmin,
+                             Standard_Real& aUmax, 
+                             Standard_Real& aVmin, 
+                             Standard_Real& aVmax) 
+{
+  if (!(Precision::IsInfinite(aUmin) ||
+        Precision::IsInfinite(aUmax))) { 
+    Standard_Real dU;
+    //
+    dU=0.1*(aUmax-aUmin);
+    aUmin=aUmin-dU;
+    aUmax=aUmax+dU;
+  }
+  if (!(Precision::IsInfinite(aVmin) ||
+        Precision::IsInfinite(aVmax))) { 
+    Standard_Real dV;
+    //
+    dV=0.1*(aVmax-aVmin);
+    aVmin=aVmin-dV;
+    aVmax=aVmax+dV;
+  }
+}