0027772: Foundation Classes - define Standard_Boolean using C++ type "bool" instead...
[occt.git] / src / IntTools / IntTools_EdgeEdge.cxx
index 47c6a47..a3bb33b 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <IntTools_EdgeEdge.ixx> 
-
-#include <NCollection_UBTreeFiller.hxx>
-
-#include <gp_Dir.hxx>
-#include <gp_Lin.hxx>
-
-#include <ElCLib.hxx>
-
-#include <TopoDS_Iterator.hxx>
 
 #include <Bnd_Box.hxx>
 #include <BndLib_Add3dCurve.hxx>
-
-#include <GeomAPI_ProjectPointOnCurve.hxx>
-
+#include <BOPCol_MapOfInteger.hxx>
 #include <BRep_Tool.hxx>
 #include <BRepAdaptor_Curve.hxx>
-
-#include <BOPCol_MapOfInteger.hxx>
-#include <BOPCol_BoxBndTree.hxx>
-
-#include <IntTools_Tools.hxx>
+#include <ElCLib.hxx>
+#include <Geom_BezierCurve.hxx>
+#include <Geom_BSplineCurve.hxx>
+#include <Geom_Line.hxx>
+#include <Geom_Circle.hxx>
+#include <Geom_Curve.hxx>
+#include <Geom_Ellipse.hxx>
+#include <Geom_OffsetCurve.hxx>
+#include <GeomAPI_ProjectPointOnCurve.hxx>
+#include <gp_Dir.hxx>
+#include <gp_Lin.hxx>
 #include <IntTools_CommonPrt.hxx>
+#include <IntTools_EdgeEdge.hxx>
+#include <IntTools_Range.hxx>
+#include <IntTools_Tools.hxx>
+#include <TopoDS_Edge.hxx>
+#include <TopoDS_Iterator.hxx>
 
-static
-  Standard_Boolean BndCommon(const Bnd_Box& theB1,
-                             const Bnd_Box& theB2,
-                             Bnd_Box& theBOut);
 static 
   void BndBuildBox(const BRepAdaptor_Curve& theBAC,
                    const Standard_Real aT1,
                    const Standard_Real aT2,
                    const Standard_Real theTol,
                    Bnd_Box& theBox);
+static
+  Standard_Real PointBoxDistance(const Bnd_Box& aB,
+                                 const gp_Pnt& aP);
 static 
-  Standard_Boolean SplitRangeOnSegments(const Standard_Real aT1, 
+  Standard_Integer SplitRangeOnSegments(const Standard_Real aT1, 
                                         const Standard_Real aT2,
                                         const Standard_Real theResolution,
                                         const Standard_Integer theNbSeg,
                                         IntTools_SequenceOfRanges& theSegments);
-static 
-  void SplitRangeOnTwo(const Standard_Real aT1, 
-                       const Standard_Real aT2,
-                       IntTools_SequenceOfRanges& theSegments);
 static
  Standard_Integer DistPC(const Standard_Real aT1, 
                          const Handle(Geom_Curve)& theC1,
@@ -87,6 +81,23 @@ static
                               Standard_Real& aT1max,
                               Standard_Real& aT2max,
                               const Standard_Boolean bMaxDist = Standard_True);
+static
+  Standard_Real ResolutionCoeff(const BRepAdaptor_Curve& theBAC,
+                                const IntTools_Range& theRange);
+static
+  Standard_Real Resolution(const Handle(Geom_Curve)& theCurve,
+                           const GeomAbs_CurveType theCurveType,
+                           const Standard_Real theResCoeff,
+                           const Standard_Real theR3D);
+static
+  Standard_Real CurveDeflection(const BRepAdaptor_Curve& theBAC,
+                                const IntTools_Range& theRange);
+static 
+  Standard_Boolean IsClosed(const Handle(Geom_Curve)& theCurve,
+                            const Standard_Real aT1,
+                            const Standard_Real aT2,
+                            const Standard_Real theTol,
+                            const Standard_Real theRes);
 static 
   Standard_Integer TypeToInteger(const GeomAbs_CurveType theCType);
 
@@ -121,31 +132,11 @@ void IntTools_EdgeEdge::Prepare()
   if (iCT1 == iCT2) {
     if (iCT1 != 0) {
       //compute deflection
-      Standard_Integer i;
-      Standard_Real aDt, aT, aT1, aT2;
-      gp_Vec aV1, aV2;
-      gp_Pnt aP;
+      Standard_Real aC1, aC2;
       //
-      Standard_Real aC1(0.), aC2(0.);
-      for (i = 0; i < 2; ++i) {
-        Standard_Real &aC = !i ? aC1 : aC2;
-        IntTools_Range aR = !i ? myRange1 : myRange2;
-        const BRepAdaptor_Curve& aBAC = !i ? myCurve1 : myCurve2;
-        aR.Range(aT1, aT2);
-        aDt = (aT2 - aT1) / 10.;
-        aT = aT1;
-        aBAC.D1(aT, aP, aV1);
-        while (aT < aT2) {
-          aT += aDt;
-          aBAC.D1(aT, aP, aV2);
-          if (aV1.Magnitude() > gp::Resolution() &&
-              aV2.Magnitude() > gp::Resolution()) {
-            gp_Dir aD1(aV1), aD2(aV2);
-            aC += aD1.Angle(aD2);
-          }
-          aV1 = aV2;
-        }
-      }
+      aC2 = CurveDeflection(myCurve2, myRange2);
+      aC1 = (aC2 > Precision::Confusion()) ? 
+        CurveDeflection(myCurve1, myRange1) : 1.;
       //
       if (aC1 < aC2) {
         --iCT1;
@@ -169,17 +160,34 @@ void IntTools_EdgeEdge::Prepare()
     mySwap = Standard_True;
   }
   //
-  myTol1 = myCurve1.Tolerance();
-  myTol2 = myCurve2.Tolerance();
+  Standard_Real aTolAdd = Precision::Confusion() / 2.;
+  myTol1 = myCurve1.Tolerance() + aTolAdd;
+  myTol2 = myCurve2.Tolerance() + aTolAdd;
   myTol = myTol1 + myTol2;
   //
-  myRes1 = myCurve1.Resolution(myTol);
-  myRes2 = myCurve2.Resolution(myTol);
-  //
   if (iCT1 != 0 || iCT2 != 0) {
-    Standard_Real f, l;
+    Standard_Real f, l, aTM;
+    //
     myGeom1 = BRep_Tool::Curve(myEdge1, f, l);
     myGeom2 = BRep_Tool::Curve(myEdge2, f, l);
+    //
+    myResCoeff1 = ResolutionCoeff(myCurve1, myRange1);
+    myResCoeff2 = ResolutionCoeff(myCurve2, myRange2);
+    //
+    myRes1 = Resolution(myCurve1.Curve().Curve(), myCurve1.GetType(), myResCoeff1, myTol1);
+    myRes2 = Resolution(myCurve2.Curve().Curve(), myCurve2.GetType(), myResCoeff2, myTol2);
+    //
+    myPTol1 = 5.e-13;
+    aTM = Max(fabs(myRange1.First()), fabs(myRange1.Last()));
+    if (aTM > 999.) {
+      myPTol1 = 5.e-16 * aTM;
+    }
+    //
+    myPTol2 = 5.e-13;
+    aTM = Max(fabs(myRange2.First()), fabs(myRange2.Last()));
+    if (aTM > 999.) {
+      myPTol2 = 5.e-16 * aTM;
+    }
   }
 }
 
@@ -205,61 +213,125 @@ void IntTools_EdgeEdge::Perform()
     return;
   }
   //
-  //3.2. Find solutions
+  if (myQuickCoincidenceCheck) {
+    if (IsCoincident()) {
+      Standard_Real aT11, aT12, aT21, aT22;
+      //
+      myRange1.Range(aT11, aT12);
+      myRange2.Range(aT21, aT22);
+      AddSolution(aT11, aT12, aT21, aT22, TopAbs_EDGE);
+      return;
+    }
+  }
+  //
   IntTools_SequenceOfRanges aRanges1, aRanges2;
   //
-  FindSolutions(aRanges1, aRanges2);
+  //3.2. Find ranges containig solutions
+  Standard_Boolean bSplit2;
+  FindSolutions(aRanges1, aRanges2, bSplit2);
   //
   //4. Merge solutions and save common parts
-  MergeSolutions(aRanges1, aRanges2);
+  MergeSolutions(aRanges1, aRanges2, bSplit2);
 }
 
+//=======================================================================
+//function :  IsCoincident
+//purpose  : 
+//=======================================================================
+Standard_Boolean IntTools_EdgeEdge::IsCoincident() 
+{
+  Standard_Integer i, iCnt, aNbSeg, aNbP2;
+  Standard_Real dT, aT1, aCoeff, aTresh, aD;
+  Standard_Real aT11, aT12, aT21, aT22;
+  GeomAPI_ProjectPointOnCurve aProjPC;
+  gp_Pnt aP1;
+  //
+  aTresh=0.5;
+  aNbSeg=23;
+  myRange1.Range(aT11, aT12);
+  myRange2.Range(aT21, aT22);
+  //
+  aProjPC.Init(myGeom2, aT21, aT22);
+  //
+  dT=(aT12-aT11)/aNbSeg;
+  //
+  iCnt=0;
+  for(i=0; i <= aNbSeg; ++i) {
+    aT1 = aT11+i*dT;
+    myGeom1->D0(aT1, aP1);
+    //
+    aProjPC.Perform(aP1);
+    aNbP2=aProjPC.NbPoints();
+    if (!aNbP2) {
+      continue;
+    }
+    //
+    aD=aProjPC.LowerDistance();
+    if(aD < myTol) {
+      ++iCnt; 
+    }
+  }
+  //
+  aCoeff=(Standard_Real)iCnt/((Standard_Real)aNbSeg+1);
+  return aCoeff > aTresh;
+}
 //=======================================================================
 //function : FindSolutions
 //purpose  : 
 //=======================================================================
 void IntTools_EdgeEdge::FindSolutions(IntTools_SequenceOfRanges& theRanges1,
-                                      IntTools_SequenceOfRanges& theRanges2)
+                                      IntTools_SequenceOfRanges& theRanges2,
+                                      Standard_Boolean& bSplit2)
 {
-  // According to the common box of the edges decide which method to use
+  Standard_Boolean bIsClosed2;
   Standard_Real aT11, aT12, aT21, aT22;
-  Bnd_Box aB1, aB2, aBC;
+  Bnd_Box aB2;
   //
+  bSplit2 = Standard_False;
   myRange1.Range(aT11, aT12);
   myRange2.Range(aT21, aT22);
   //
-  BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1);
-  BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2);
+  bIsClosed2 = IsClosed(myGeom2, aT21, aT22, myTol2, myRes2);
   //
-  if (!BndCommon(aB1, aB2, aBC)) {
-    // No intersections at all
+  if (bIsClosed2) {
+    Bnd_Box aB1;
+    BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1);
+    //
+    gp_Pnt aP = myGeom2->Value(aT21);
+    bIsClosed2 = !aB1.IsOut(aP);
+  }
+  //
+  if (!bIsClosed2) {
+    BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2);
+    FindSolutions(myRange1, myRange2, aB2, theRanges1, theRanges2);
     return;
   }
   //
-  if (aBC.IsThin(10*myTol)) {
-    // As soon as the common box of the edges is thin,
-    // find exact solution at once
-    FindSolutions(myRange1, myRange2, aBC, theRanges1, theRanges2);
+  if (!CheckCoincidence(aT11, aT12, aT21, aT22, myTol, myRes1)) {
+    theRanges1.Append(myRange1);
+    theRanges2.Append(myRange2);
+    return;
   }
-  else {
-    // First find the rough ranges containing solutions, 
-    // than find exact ranges
-    IntTools_SequenceOfRanges aSegments1;
-    Standard_Integer i, aNb;
-    //
-    // Find rough ranges
-    FindRoughRanges(myRange1, myRange2, aSegments1);
-    aNb = aSegments1.Length();
-    // Find exact ranges
-    for (i = 1; i <= aNb; ++i) {
-      const IntTools_Range& aR1 = aSegments1(i);
-      aR1.Range(aT11, aT12);
-      BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1);
-      if (BndCommon(aB1, aB2, aBC)) {
-        FindSolutions(aR1, myRange2, aBC, theRanges1, theRanges2);
-      }
+  //
+  Standard_Integer i, j, aNb1, aNb2;
+  IntTools_SequenceOfRanges aSegments1, aSegments2;
+  //
+  aNb1 = IsClosed(myGeom1, aT11, aT12, myTol1, myRes1) ? 2 : 1;
+  aNb2 = 2;
+  //
+  aNb1 = SplitRangeOnSegments(aT11, aT12, myRes1, aNb1, aSegments1);
+  aNb2 = SplitRangeOnSegments(aT21, aT22, myRes2, aNb2, aSegments2);
+  //
+  for (i = 1; i <= aNb1; ++i) {
+    const IntTools_Range& aR1 = aSegments1(i);
+    for (j = 1; j <= aNb2; ++j) {
+      const IntTools_Range& aR2 = aSegments2(j);
+      BndBuildBox(myCurve2, aR2.First(), aR2.Last(), myTol2, aB2);
+      FindSolutions(aR1, aR2, aB2, theRanges1, theRanges2);
     }
   }
+  //
+  bSplit2 = aNb2 > 1;
 }
 
 //=======================================================================
@@ -268,78 +340,84 @@ void IntTools_EdgeEdge::FindSolutions(IntTools_SequenceOfRanges& theRanges1,
 //=======================================================================
 void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1,
                                       const IntTools_Range& theR2,
-                                      const Bnd_Box& theBC,
-                                      IntTools_SequenceOfRanges& theRanges1, 
+                                      const Bnd_Box& theBox2,
+                                      IntTools_SequenceOfRanges& theRanges1,
                                       IntTools_SequenceOfRanges& theRanges2)
 {
   Standard_Boolean bOut, bStop, bThin;
   Standard_Real aT11, aT12, aT21, aT22;
   Standard_Real aTB11, aTB12, aTB21, aTB22;
-  Standard_Real aTol, aSmallStep1, aSmallStep2;
+  Standard_Real aSmallStep1, aSmallStep2;
   Standard_Integer iCom;
   Bnd_Box aB1, aB2;
   //
   theR1.Range(aT11, aT12);
   theR2.Range(aT21, aT22);
-  aB1 = theBC;
   //
-  bOut  = Standard_False;
+  aB2 = theBox2;
+  //
   bThin = Standard_False;
   bStop = Standard_False;
-  aTol  = 2*myTol;
   iCom  = 1;
   //
   do {
-    bOut = !FindParameters(myCurve2, aT21, aT22, myRes2, aB1, aTB21, aTB22);
+    aTB11 = aT11;
+    aTB12 = aT12;
+    aTB21 = aT21;
+    aTB22 = aT22;
+    //
+    //1. Build box for first edge and find parameters 
+    //   of the second one in that box
+    BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1);
+    bOut = aB1.IsOut(aB2);
     if (bOut) {
       break;
     }
     //
-    bThin = (aTB22 - aTB21) < myRes2;
-    if (bThin) {
-      bOut = !FindParameters(myCurve1, aT11, aT12, myRes1, aB1, aTB11, aTB12);
+    bThin = ((aT12 - aT11) < myRes1) ||
+      (aB1.IsXThin(myTol) && aB1.IsYThin(myTol) && aB1.IsZThin(myTol));
+    //
+    bOut = !FindParameters(myCurve2, aTB21, aTB22, myTol2, myRes2, myPTol2, 
+                           myResCoeff2, aB1, aT21, aT22);
+    if (bOut || bThin) {
       break;
     }
     //
-    BndBuildBox(myCurve2, aTB21, aTB22, myTol2, aB2);
-    BndCommon(aB1, aB2, aB2);
-    //
-    bOut = !FindParameters(myCurve1, aT11, aT12, myRes1, aB2, aTB11, aTB12);
+    //2. Build box for second edge and find parameters 
+    //   of the first one in that box
+    BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2);
+    bOut = aB1.IsOut(aB2);
     if (bOut) {
       break;
     }
     //
-    bThin = ((aTB12 - aTB11) < myRes1) ||
-      (aB2.IsXThin(aTol) && aB2.IsYThin(aTol) && aB2.IsZThin(aTol));
+    bThin = ((aT22 - aT21) < myRes2) ||
+      (aB2.IsXThin(myTol) && aB2.IsYThin(myTol) && aB2.IsZThin(myTol));
     //
-    if (!bThin) {
-      aSmallStep1 = (aT12 - aT11) / 250.;
-      aSmallStep2 = (aT22 - aT21) / 250.;
-      //
-      if (aSmallStep1 < myRes1) {
-        aSmallStep1 = myRes1;
-      }
-      if (aSmallStep2 < myRes2) {
-        aSmallStep2 = myRes2;
-      }
-      //
-      if (((aTB11 - aT11) < aSmallStep1) && ((aT12 - aTB12) < aSmallStep1) &&
-          ((aTB21 - aT21) < aSmallStep2) && ((aT22 - aTB22) < aSmallStep2)) {
-        bStop = Standard_True;
-      } else {
-        BndBuildBox(myCurve1, aTB11, aTB12, myTol1, aB1);
-        bOut = !BndCommon(aB1, aB2, aB1);
-        if (bOut) {
-          break;
-        }
-      }
+    bOut = !FindParameters(myCurve1, aTB11, aTB12, myTol1, myRes1, myPTol1,
+                           myResCoeff1, aB2, aT11, aT12);
+    //
+    if (bOut || bThin) {
+      break;
     }
     //
-    aT11 = aTB11;
-    aT12 = aTB12;
-    aT21 = aTB21;
-    aT22 = aTB22;
-  } while (!bThin && !bStop);
+    //3. Check if it makes sense to continue
+    aSmallStep1 = (aTB12 - aTB11) / 250.;
+    aSmallStep2 = (aTB22 - aTB21) / 250.;
+    //
+    if (aSmallStep1 < myRes1) {
+      aSmallStep1 = myRes1;
+    }
+    if (aSmallStep2 < myRes2) {
+      aSmallStep2 = myRes2;
+    }
+    //
+    if (((aT11 - aTB11) < aSmallStep1) && ((aTB12 - aT12) < aSmallStep1) &&
+        ((aT21 - aTB21) < aSmallStep2) && ((aTB22 - aT22) < aSmallStep2)) {
+      bStop = Standard_True;
+    }
+    //
+  } while (!bStop);
   //
   if (bOut) {
     //no intersection;
@@ -351,23 +429,37 @@ void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1,
     iCom = CheckCoincidence(aT11, aT12, aT21, aT22, myTol, myRes1);
     if (!iCom) {
       bThin = Standard_True;
-    } 
+    }
   }
   //
   if (bThin) {
     if (iCom != 0) {
       //check intermediate points
-      Standard_Real aT1, aT2, aDist;
-      gp_Pnt aP1, aP2;
+      Standard_Boolean bSol;
+      Standard_Real aT1;
+      gp_Pnt aP1;
+      GeomAPI_ProjectPointOnCurve aProjPC;
       //
-      aT1 = IntTools_Tools::IntermediatePoint(aT11, aT12);
-      aT2 = IntTools_Tools::IntermediatePoint(aT21, aT22);
+      aT1 = (aT11 + aT12) * .5;
+      myGeom1->D0(aT1, aP1);
       //
-      aP1 = myGeom1->Value(aT1);
-      aP2 = myGeom2->Value(aT2);
+      aProjPC.Init(myGeom2, aT21, aT22);
+      aProjPC.Perform(aP1);
       //
-      aDist = aP1.Distance(aP2);
-      if (aDist > myTol) {
+      if (aProjPC.NbPoints()) {
+        bSol = aProjPC.LowerDistance() <= myTol;
+      }
+      else {
+        Standard_Real aT2;
+        gp_Pnt aP2;
+        //
+        aT2 = (aT21 + aT22) * .5;
+        myGeom2->D0(aT2, aP2);
+        //
+        bSol = aP1.IsEqual(aP2, myTol);
+      }
+      //
+      if (!bSol) {
         return;
       }
     }
@@ -390,15 +482,10 @@ void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1,
   IntTools_Range aR2(aT21, aT22);
   BndBuildBox(myCurve2, aT21, aT22, myTol2, aB2);
   //
-  SplitRangeOnSegments(aT11, aT12, myRes1, 3, aSegments1);
-  aNb1 = aSegments1.Length();
+  aNb1 = SplitRangeOnSegments(aT11, aT12, myRes1, 3, aSegments1);
   for (i = 1; i <= aNb1; ++i) {
     const IntTools_Range& aR1 = aSegments1(i);
-    aR1.Range(aT11, aT12);
-    BndBuildBox(myCurve1, aT11, aT12, myTol1, aB1);
-    if (BndCommon(aB1, aB2, aB1)) {
-      FindSolutions(aR1, aR2, aB1, theRanges1, theRanges2);
-    }
+    FindSolutions(aR1, aR2, aB2, theRanges1, theRanges2);
   }
 }
 
@@ -408,27 +495,32 @@ void IntTools_EdgeEdge::FindSolutions(const IntTools_Range& theR1,
 //=======================================================================
 Standard_Boolean IntTools_EdgeEdge::FindParameters(const BRepAdaptor_Curve& theBAC,
                                                    const Standard_Real aT1, 
-                                                   const Standard_Real aT2, 
+                                                   const Standard_Real aT2,
+                                                   const Standard_Real theTol,
                                                    const Standard_Real theRes,
+                                                   const Standard_Real thePTol,
+                                                   const Standard_Real theResCoeff,
                                                    const Bnd_Box& theCBox,
                                                    Standard_Real& aTB1, 
                                                    Standard_Real& aTB2)
 {
   Standard_Boolean bRet;
   Standard_Integer aC, i, k;
-  Standard_Real aCf, aDiff, aDt, aT, aTB, aTOut, aTIn, aPTol, aTol,
-                aDist, aDistP;
+  Standard_Real aCf, aDiff, aDt, aT, aTB, aTOut, aTIn;
+  Standard_Real aDist, aDistP, aDistTol;
   gp_Pnt aP;
   Bnd_Box aCBx;
   //
   bRet = Standard_False;
   aCf = 0.6180339887498948482045868343656;// =0.5*(1.+sqrt(5.))/2.;
   aDt = theRes;
-  aPTol = theRes * 0.001;
-  aTol = theBAC.Tolerance();
   aDistP = 0.;
+  aDistTol = 1e-9;
   aCBx = theCBox;
-  aCBx.Enlarge(aTol);
+  aCBx.Enlarge(theTol);
+  //
+  const Handle(Geom_Curve)& aCurve = theBAC.Curve().Curve();
+  const GeomAbs_CurveType aCurveType = theBAC.GetType();
   //
   for (i = 0; i < 2; ++i) {
     aTB = !i ? aT1 : aT2;
@@ -438,13 +530,15 @@ Standard_Boolean IntTools_EdgeEdge::FindParameters(const BRepAdaptor_Curve& theB
     k = 0;
     //looking for the point on the edge which is in the box;
     while (aC*(aT-aTB) >= 0) {
-      aP = theBAC.Value(aTB);
-      Bnd_Box aBP;
-      aBP.Add(aP);
-      aDist = aBP.Distance(theCBox);
-      k = (fabs(aDist - aDistP) < Precision::PConfusion()) ? k+1 : 0;
-      if (aDist > aTol) {
-        aDt = theBAC.Resolution(aDist*Max(k, 1));
+      theBAC.D0(aTB, aP);
+      aDist = PointBoxDistance(theCBox, aP);
+      if (aDist > theTol) {
+        if (fabs(aDist - aDistP) < aDistTol) {
+          aDt = Resolution(aCurve, aCurveType, theResCoeff, (++k)*aDist);
+        } else {
+          k = 0;
+          aDt = Resolution(aCurve, aCurveType, theResCoeff, aDist);
+        }
         aTB += aC*aDt;
       } else {
         bRet = Standard_True;
@@ -470,9 +564,9 @@ Standard_Boolean IntTools_EdgeEdge::FindParameters(const BRepAdaptor_Curve& theB
       aTIn = aTB;
       aTOut = aTB - aC*aDt;
       aDiff = aTIn - aTOut;
-      while (fabs(aDiff) > aPTol) {
+      while (fabs(aDiff) > thePTol) {
         aTB = aTOut + aDiff*aCf;
-        aP = theBAC.Value(aTB);
+        theBAC.D0(aTB, aP);
         if (aCBx.IsOut(aP)) {
           aTOut = aTB;
         } else {
@@ -495,48 +589,94 @@ Standard_Boolean IntTools_EdgeEdge::FindParameters(const BRepAdaptor_Curve& theB
 //purpose  : 
 //=======================================================================
 void IntTools_EdgeEdge::MergeSolutions(const IntTools_SequenceOfRanges& theRanges1, 
-                                       const IntTools_SequenceOfRanges& theRanges2)
+                                       const IntTools_SequenceOfRanges& theRanges2,
+                                       const Standard_Boolean bSplit2)
 {
+  Standard_Integer aNbCP = theRanges1.Length();
+  if (aNbCP == 0) {
+    return;
+  }
+  //
   IntTools_Range aRi1, aRi2, aRj1, aRj2;
-  Standard_Integer aNbCP, i, j;
+  Standard_Boolean bCond;
+  Standard_Integer i, j;
   TopAbs_ShapeEnum aType;
-  Standard_Real aTi11, aTi12, aTi21, aTi22,
-                aTj11, aTj12, aTj21, aTj22;
+  Standard_Real aT11, aT12, aT21, aT22;
+  Standard_Real aTi11, aTi12, aTi21, aTi22;
+  Standard_Real aTj11, aTj12, aTj21, aTj22;
+  Standard_Real aRes1, aRes2, dTR1, dTR2;
+  BOPCol_MapOfInteger aMI;
+  //
+  aRes1 = Resolution(myCurve1.Curve().Curve(), 
+                     myCurve1.GetType(), myResCoeff1, myTol);
+  aRes2 = Resolution(myCurve2.Curve().Curve(), 
+                     myCurve2.GetType(), myResCoeff2, myTol);
   //
-  aNbCP = theRanges1.Length();
+  myRange1.Range(aT11, aT12);
+  myRange2.Range(aT21, aT22);
+  dTR1 = 20*aRes1;
+  dTR2 = 20*aRes2;
   aType = TopAbs_VERTEX;
   //
-  for (i = 1; i <= aNbCP; ) {
+  for (i = 1; i <= aNbCP;) {
+    if (aMI.Contains(i)) {
+      ++i;
+      continue;
+    }
+    //
     aRi1 = theRanges1(i);
     aRi2 = theRanges2(i);
     //
     aRi1.Range(aTi11, aTi12);
     aRi2.Range(aTi21, aTi22);
     //
+    aMI.Add(i);
+    //
     for (j = i+1; j <= aNbCP; ++j) {
+      if (aMI.Contains(j)) {
+        continue;
+      }
+      //
       aRj1 = theRanges1(j);
       aRj2 = theRanges2(j);
       //
       aRj1.Range(aTj11, aTj12);
       aRj2.Range(aTj21, aTj22);
-      if (fabs(aTi12 - aTj11) < 10*myRes1 ||
-          fabs(aTi22 - aTj21) < 10*myRes2) {
+      //
+      bCond = (fabs(aTi12 - aTj11) < dTR1) ||
+        (bSplit2 && (fabs(aTj12 - aTi11) < dTR1));
+      if (bCond && bSplit2) {
+        bCond = (fabs((Max(aTi22, aTj22) - Min(aTi21, aTj21)) - 
+                      ((aTi22 - aTi21) + (aTj22 - aTj21))) < dTR2);
+      }
+      //
+      if (bCond) {
         aTi11 = Min(aTi11, aTj11);
         aTi12 = Max(aTi12, aTj12);
         aTi21 = Min(aTi21, aTj21);
         aTi22 = Max(aTi22, aTj22);
-      } else {
+        aMI.Add(j);
+      }
+      else if (!bSplit2) {
+        i = j;
         break;
       }
     }
-    i = j;
     //
-    if (aTi11 == myRange1.First() && aTi12 == myRange1.Last() &&
-        aTi21 == myRange2.First() && aTi22 == myRange2.Last()) {
+    if (((fabs(aT11 - aTi11) < myRes1) && (fabs(aT12 - aTi12) < myRes1)) ||
+        ((fabs(aT21 - aTi21) < myRes2) && (fabs(aT22 - aTi22) < myRes2))) {
       aType = TopAbs_EDGE;
+      myCommonParts.Clear();
     }
     //
     AddSolution(aTi11, aTi12, aTi21, aTi22, aType);
+    if (aType == TopAbs_EDGE) {
+      break;
+    }
+    //
+    if (bSplit2) {
+      ++i;
+    }
   }
 }
 
@@ -593,40 +733,64 @@ void IntTools_EdgeEdge::FindBestSolution(const Standard_Real aT11,
                                          Standard_Real& aT2)
 {
   Standard_Integer i, aNbS, iErr;
-  Standard_Real aDMin, aD, aCrit, aMinStep, aTMax;
-  Standard_Real aT1x, aT2x, aT1p, aT2p;
-  GeomAPI_ProjectPointOnCurve aProj;
-  IntTools_SequenceOfRanges aSeg1;
-  //
-  aT1 = IntTools_Tools::IntermediatePoint(aT11, aT12);
-  aT2 = IntTools_Tools::IntermediatePoint(aT21, aT22);
-  //
-  aDMin = 100.;
-  aD = 100.;
-  aCrit = 1.e-16;
-  aMinStep = 5.e-13;
-  aTMax = Max(fabs(aT11), fabs(aT12));
-  if (aTMax > 999.) {
-    aMinStep = 5.e-16 * aTMax;
-  }
+  Standard_Real aDMin, aD, aRes1, aSolCriteria, aTouchCriteria;
+  Standard_Real aT1A, aT1B, aT1Min, aT2Min;
+  Standard_Real aT1Im, aT2Im, aT1Touch;
+  GeomAPI_ProjectPointOnCurve aProjPC;
+  IntTools_SequenceOfRanges aRanges;
+  Standard_Boolean bTouch;
+  //
+  aDMin = Precision::Infinite();
+  aSolCriteria   = 5.e-16;
+  aTouchCriteria = 5.e-13;
+  bTouch = Standard_False;
+  aT1Touch = aT11;
   //
+  aRes1 = Resolution(myCurve1.Curve().Curve(), 
+                     myCurve1.GetType(), myResCoeff1, myTol);
   aNbS = 10;
-  SplitRangeOnSegments(aT11, aT12, 3*myRes1, aNbS, aSeg1);
-  aNbS = aSeg1.Length();
+  aNbS = SplitRangeOnSegments(aT11, aT12, 3*aRes1, aNbS, aRanges);
+  //
+  aProjPC.Init(myGeom2, aT21, aT22);
+  //
+  aT1 = (aT11 + aT12) * 0.5;
+  iErr = DistPC(aT1, myGeom1, aSolCriteria, aProjPC, aD, aT2, -1);
+  if (iErr == 1) {
+    aT2 = (aT21 + aT22) * 0.5;
+  }
+  //
+  aT1Im = aT1;
+  aT2Im = aT2;
   //
-  aProj.Init(myGeom2, aT21, aT22);
   for (i = 1; i <= aNbS; ++i) {
-    const IntTools_Range& aR1 = aSeg1(i);
-    aR1.Range(aT1x, aT2x);
+    const IntTools_Range& aR1 = aRanges(i);
+    aR1.Range(aT1A, aT1B);
     //
-    iErr = FindDistPC(aT1x, aT2x, myGeom1, aCrit, aMinStep, 
-                      aProj, aD, aT1p, aT2p, Standard_False);
-    if (iErr != 1 && aD < aDMin) {
-      aT1 = aT1p;
-      aT2 = aT2p;
-      aDMin = aD;
-      if (aDMin < aCrit) {
-        break;
+    aD = myTol;
+    iErr = FindDistPC(aT1A, aT1B, myGeom1, aSolCriteria, myPTol1,
+                      aProjPC, aD, aT1Min, aT2Min, Standard_False);
+    if (iErr != 1) {
+      if (aD < aDMin) {
+        aT1 = aT1Min;
+        aT2 = aT2Min;
+        aDMin = aD;
+      }
+      //
+      if (aD < aTouchCriteria) {
+        if (bTouch) {
+          aT1A = (aT1Touch + aT1Min) * 0.5;
+          iErr = DistPC(aT1A, myGeom1, aTouchCriteria, 
+                        aProjPC, aD, aT2Min, -1);
+          if (aD > aTouchCriteria) {
+            aT1 = aT1Im;
+            aT2 = aT2Im;
+            break;
+          }
+        }
+        else {
+          aT1Touch = aT1Min;
+          bTouch = Standard_True;
+        }
       }
     }
   }
@@ -759,120 +923,22 @@ void IntTools_EdgeEdge::ComputeLineLine()
     return;
   }
   //
-  aCommonPrt.SetRange1(aT1 - myTol, aT1 + myTol);
-  aCommonPrt.AppendRange2(aT2 - myTol, aT2 + myTol);
+  // compute correct range on the edges
+  Standard_Real anAngle, aDt1, aDt2;
+  //
+  anAngle = aD1.Angle(aD2);
+  //
+  aDt1 = IntTools_Tools::ComputeIntRange(myTol1, myTol2, anAngle);
+  aDt2 = IntTools_Tools::ComputeIntRange(myTol2, myTol1, anAngle);
+  //
+  aCommonPrt.SetRange1(aT1 - aDt1, aT1 + aDt1);
+  aCommonPrt.AppendRange2(aT2 - aDt2, aT2 + aDt2);
   aCommonPrt.SetType(TopAbs_VERTEX);
   aCommonPrt.SetVertexParameter1(aT1);
   aCommonPrt.SetVertexParameter2(aT2);
   myCommonParts.Append(aCommonPrt);
 }
 
-//=======================================================================
-//function : FindRoughRanges
-//purpose  : 
-//=======================================================================
-Standard_Integer IntTools_EdgeEdge::FindRoughRanges(const IntTools_Range& theR1,
-                                                    const IntTools_Range& theR2,
-                                                    IntTools_SequenceOfRanges& theSegments1)
-{
-  Standard_Integer iRet, i, j, aNbi, aNbj, aNbSD;
-  Standard_Real aTi1, aTi2, aTj1, aTj2, aDi, aDj;
-  IntTools_SequenceOfRanges aSi, aSj, aNewSi, aNewSj;
-  BOPCol_MapOfInteger aMj;
-  BOPCol_ListIteratorOfListOfInteger aItLI;
-  Bnd_Box aBi, aBj;
-  BOPCol_BoxBndTreeSelector aSelector;
-  BOPCol_BoxBndTree aBBTree;
-  NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
-  //
-  theR1.Range(aTi1, aTi2);
-  theR2.Range(aTj1, aTj2);
-  aDi = (aTi2 - aTi1) / 2.;
-  aDj = (aTj2 - aTj1) / 2.;
-  aNbi = 2;
-  aNbj = 2;
-  //
-  SplitRangeOnTwo(aTi1, aTi2, aSi);
-  SplitRangeOnTwo(aTj1, aTj2, aSj);
-  //
-  while (aDi > myRes1 || aDj > myRes2) {
-    aDi /= 2.;
-    aDj /= 2.;
-    //
-    aBBTree.Clear();
-    aTreeFiller.Reset();
-    for (j = 1; j <= aNbj; ++j) {
-      const IntTools_Range& aRj = aSj(j);
-      aRj.Range(aTj1, aTj2);
-      //
-      BndBuildBox(myCurve2, aTj1, aTj2, myTol2, aBj);
-      //
-      aTreeFiller.Add(j, aBj);
-    }
-    //
-    aTreeFiller.Fill();
-    //
-    for (i = 1; i <= aNbi; ++i) {
-      const IntTools_Range& aRi = aSi(i);
-      aRi.Range(aTi1, aTi2);
-      //
-      BndBuildBox(myCurve1, aTi1, aTi2, myTol1, aBi);
-      //
-      aSelector.Clear();
-      aSelector.SetBox(aBi);
-      //
-      aNbSD = aBBTree.Select(aSelector);
-      if (!aNbSD){
-        continue;
-      }
-      //
-      SplitRangeOnTwo(aTi1, aTi2, aNewSi);
-      //
-      const BOPCol_ListOfInteger& aLI = aSelector.Indices();
-      aItLI.Initialize(aLI);
-      for (; aItLI.More(); aItLI.Next()) {
-        j = aItLI.Value();
-        if (aMj.Add(j)) {
-          const IntTools_Range& aRj = aSj(j);
-          aRj.Range(aTj1, aTj2);
-          SplitRangeOnTwo(aTj1, aTj2, aNewSj);
-        }
-      }
-    }
-    //
-    aSi.Assign(aNewSi);
-    aSj.Assign(aNewSj);
-    aNbi = aSi.Length();
-    aNbj = aSj.Length();
-    //
-    if ((aNbi == 0) || (aNbj == 0) || (aNbi > 500) || (aNbj > 500)) {
-      break;
-    }
-    //
-    aNewSi.Clear();
-    aNewSj.Clear();
-    aMj.Clear();
-  }
-  //
-  iRet = (aNbi && aNbj) ? 1 : 0;
-  if (iRet) {
-    //collect ranges
-    IntTools_Range aRi1 = aSi(1), aRi2;
-    Standard_Real aT1 = aRi1.First();
-    for (i = 2; i <= aNbi; ++i) {
-      aRi2 = aSi(i);
-      if ((aRi2.First() - aRi1.Last()) > myRes1) {
-        theSegments1.Append(IntTools_Range(aT1, aRi1.Last()));
-        aT1 = aRi2.First();
-      }
-      aRi1 = aRi2;
-    }
-    theSegments1.Append(IntTools_Range(aT1, aRi2.Last()));
-  }
-  //
-  return iRet;
-}
-
 //=======================================================================
 //function : IsIntersection
 //purpose  : 
@@ -937,13 +1003,14 @@ Standard_Boolean IntTools_EdgeEdge::IsIntersection(const Standard_Real aT11,
     //
     if (((anAngle1 < anAngleCriteria) || ((M_PI - anAngle1) < anAngleCriteria)) ||
         ((anAngle2 < anAngleCriteria) || ((M_PI - anAngle2) < anAngleCriteria))) {
-      GeomAPI_ProjectPointOnCurve aProj;
+      GeomAPI_ProjectPointOnCurve aProjPC;
       Standard_Integer iErr;
-      Standard_Real aD, aT1p, aT2p;
+      Standard_Real aD, aT1Min, aT2Min;
       //
-      aD = 100.;
-      aProj.Init(myGeom2, aT21, aT22);
-      iErr = FindDistPC(aT11, aT12, myGeom1, myTol, myRes1, aProj, aD, aT1p, aT2p, Standard_False);
+      aD = Precision::Infinite();
+      aProjPC.Init(myGeom2, aT21, aT22);
+      iErr = FindDistPC(aT11, aT12, myGeom1, myTol, myRes1, 
+                        aProjPC, aD, aT1Min, aT2Min, Standard_False);
       bRet = (iErr == 2);
     }
   }
@@ -961,11 +1028,10 @@ Standard_Integer IntTools_EdgeEdge::CheckCoincidence(const Standard_Real aT11,
                                                      const Standard_Real theCriteria,
                                                      const Standard_Real theCurveRes1)
 {
-  Standard_Boolean bSmall;
-  Standard_Integer iErr, aNb, i;
+  Standard_Integer iErr, aNb, aNb1, i;
   Standard_Real aT1A, aT1B, aT1max, aT2max, aDmax;
   GeomAPI_ProjectPointOnCurve aProjPC;
-  IntTools_SequenceOfRanges aSeg1;
+  IntTools_SequenceOfRanges aRanges;
   //
   iErr  = 0;
   aDmax = -1.;
@@ -973,10 +1039,9 @@ Standard_Integer IntTools_EdgeEdge::CheckCoincidence(const Standard_Real aT11,
   //
   // 1. Express evaluation
   aNb = 10; // Number of intervals on the curve #1
-  bSmall = !SplitRangeOnSegments(aT11, aT12, theCurveRes1, aNb, aSeg1);
-  aNb = aSeg1.Length();
-  for (i = 1; i < aNb; ++i) {
-    const IntTools_Range& aR1 = aSeg1(i);
+  aNb1 = SplitRangeOnSegments(aT11, aT12, theCurveRes1, aNb, aRanges);
+  for (i = 1; i < aNb1; ++i) {
+    const IntTools_Range& aR1 = aRanges(i);
     aR1.Range(aT1A, aT1B);
     //
     iErr = DistPC(aT1B, myGeom1, theCriteria, aProjPC, aDmax, aT2max);
@@ -985,15 +1050,15 @@ Standard_Integer IntTools_EdgeEdge::CheckCoincidence(const Standard_Real aT11,
     }
   }
   //
-  // if the ranges in aSeg1 are less than theCurveRes1,
+  // if the ranges in aRanges are less than theCurveRes1,
   // there is no need to do step 2 (deep evaluation)
-  if (bSmall) {
+  if (aNb1 < aNb) {
     return iErr;
   }
   //
   // 2. Deep evaluation
-  for (i = 2; i < aNb; ++i) {
-    const IntTools_Range& aR1 = aSeg1(i);
+  for (i = 2; i < aNb1; ++i) {
+    const IntTools_Range& aR1 = aRanges(i);
     aR1.Range(aT1A, aT1B);
     //
     iErr = FindDistPC(aT1A, aT1B, myGeom1, theCriteria, theCurveRes1, 
@@ -1029,18 +1094,21 @@ Standard_Integer FindDistPC(const Standard_Real aT1A,
   //
   iC = bMaxDist ? 1 : -1;
   iErr = 0;
+  aT1max = aT2max = 0.; // silence GCC warning
   //
   aGS = 0.6180339887498948482045868343656;// =0.5*(1.+sqrt(5.))-1.;
   aA = aT1A;
   aB = aT1B;
   //
   // check bounds
-  iErr = DistPC(aA, theC1, theCriteria, theProjPC, aYP, aT2P, aDmax, aT1max, aT2max, iC);
+  iErr = DistPC(aA, theC1, theCriteria, theProjPC, 
+                aYP, aT2P, aDmax, aT1max, aT2max, iC);
   if (iErr == 2) {
     return iErr;
   }
   //
-  iErr = DistPC(aB, theC1, theCriteria, theProjPC, aYL, aT2L, aDmax, aT1max, aT2max, iC);
+  iErr = DistPC(aB, theC1, theCriteria, theProjPC, 
+                aYL, aT2L, aDmax, aT1max, aT2max, iC);
   if (iErr == 2) {
     return iErr;
   }
@@ -1048,12 +1116,14 @@ Standard_Integer FindDistPC(const Standard_Real aT1A,
   aXP = aA + (aB - aA)*aGS;
   aXL = aB - (aB - aA)*aGS;
   //
-  iErr = DistPC(aXP, theC1, theCriteria, theProjPC, aYP, aT2P, aDmax, aT1max, aT2max, iC);
+  iErr = DistPC(aXP, theC1, theCriteria, theProjPC, 
+                aYP, aT2P, aDmax, aT1max, aT2max, iC);
   if (iErr) {
     return iErr;
   }
   //
-  iErr = DistPC(aXL, theC1, theCriteria, theProjPC, aYL, aT2L, aDmax, aT1max, aT2max, iC);
+  iErr = DistPC(aXL, theC1, theCriteria, theProjPC, 
+                aYL, aT2L, aDmax, aT1max, aT2max, iC);
   if (iErr) {
     return iErr;
   }
@@ -1064,20 +1134,25 @@ Standard_Integer FindDistPC(const Standard_Real aT1A,
       aXL = aXP;
       aYL = aYP;
       aXP = aA + (aB - aA)*aGS;
-      iErr = DistPC(aXP, theC1, theCriteria, theProjPC, aYP, aT2P, aDmax, aT1max, aT2max, iC);
-      if (iErr) {
-        return iErr;
-      }
+      iErr = DistPC(aXP, theC1, theCriteria, theProjPC, 
+                    aYP, aT2P, aDmax, aT1max, aT2max, iC);
     }
     else {
       aB = aXP;
       aXP = aXL;
       aYP = aYL;
       aXL = aB - (aB - aA)*aGS;
-      iErr = DistPC(aXL, theC1, theCriteria, theProjPC, aYL, aT2L, aDmax, aT1max, aT2max, iC);
-      if (iErr) {
-        return iErr;
+      iErr = DistPC(aXL, theC1, theCriteria, theProjPC, 
+                    aYL, aT2L, aDmax, aT1max, aT2max, iC);
+    }
+    //
+    if (iErr) {
+      if ((iErr == 2) && !bMaxDist) {
+        aXP = (aA + aB) * 0.5;
+        DistPC(aXP, theC1, theCriteria, theProjPC, 
+               aYP, aT2P, aDmax, aT1max, aT2max, iC);
       }
+      return iErr;
     }
     //
     if ((aB - aA) < theEps) {
@@ -1105,7 +1180,7 @@ Standard_Integer DistPC(const Standard_Real aT1,
   Standard_Integer iErr;
   //
   iErr = DistPC(aT1, theC1, theCriteria, theProjPC, aD, aT2, iC);
-  if (iErr) {
+  if (iErr == 1) {
     return iErr;
   }
   //
@@ -1155,37 +1230,32 @@ Standard_Integer DistPC(const Standard_Real aT1,
 //function : SplitRangeOnSegments
 //purpose  : 
 //=======================================================================
-Standard_Boolean SplitRangeOnSegments(const Standard_Real aT1, 
+Standard_Integer SplitRangeOnSegments(const Standard_Real aT1, 
                                       const Standard_Real aT2,
                                       const Standard_Real theResolution,
                                       const Standard_Integer theNbSeg,
                                       IntTools_SequenceOfRanges& theSegments)
 {
-  if ((aT2 - aT1) < theResolution) {
+  Standard_Real aDiff = aT2 - aT1;
+  if (aDiff < theResolution || theNbSeg == 1) {
     theSegments.Append(IntTools_Range(aT1, aT2));
-    return Standard_False;
+    return 1;
   }
   //
   Standard_Real aDt, aT1x, aT2x, aSeg;
   Standard_Integer aNbSegments, i;
-  Standard_Boolean bRet;
   //
-  bRet = Standard_True;
   aNbSegments = theNbSeg;
-  aDt = (aT2 - aT1) / aNbSegments;
+  aDt = aDiff / aNbSegments;
   if (aDt < theResolution) {
-    aSeg = (aT2 - aT1) / theResolution;
+    aSeg = aDiff / theResolution;
     aNbSegments = Standard_Integer(aSeg) + 1;
-    bRet = Standard_False;
+    aDt = aDiff / aNbSegments;
   }
   //
-  aDt /= aNbSegments;
   aT1x = aT1;
-  for (i = 1; i <= aNbSegments; ++i) {
+  for (i = 1; i < aNbSegments; ++i) {
     aT2x = aT1x + aDt;
-    if (i==aNbSegments) {
-      aT2x = aT2;
-    }
     //
     IntTools_Range aR(aT1x, aT2x);
     theSegments.Append(aR);
@@ -1193,54 +1263,10 @@ Standard_Boolean SplitRangeOnSegments(const Standard_Real aT1,
     aT1x = aT2x;
   }
   //
-  return bRet;
-}
-
-//=======================================================================
-//function : SplitRangeOnTwo
-//purpose  : 
-//=======================================================================
-void SplitRangeOnTwo(const Standard_Real aT1, 
-                     const Standard_Real aT2,
-                     IntTools_SequenceOfRanges& theSegments)
-{
-  Standard_Real aCf, aT;
-  //
-  aCf=0.5;
-  aT = aT1 + (aT2-aT1)*aCf;
-  //
-  IntTools_Range aR1(aT1, aT), aR2(aT, aT2);
+  IntTools_Range aR(aT1x, aT2);
+  theSegments.Append(aR);
   //
-  theSegments.Append(aR1);
-  theSegments.Append(aR2);
-}
-
-//=======================================================================
-//function : BndCommon
-//purpose  : 
-//=======================================================================
-Standard_Boolean BndCommon(const Bnd_Box& theB1,
-                           const Bnd_Box& theB2,
-                           Bnd_Box& theBOut)
-{
-  Standard_Boolean bRet;
-  //
-  bRet = !theB1.IsOut(theB2);
-  if (bRet) {
-    Standard_Real aXmin1, aYmin1, aZmin1, aXmax1, aYmax1, aZmax1,
-                  aXmin2, aYmin2, aZmin2, aXmax2, aYmax2, aZmax2;
-    Bnd_Box aBCom;
-    //
-    theB1.Get(aXmin1, aYmin1, aZmin1, aXmax1, aYmax1, aZmax1);
-    theB2.Get(aXmin2, aYmin2, aZmin2, aXmax2, aYmax2, aZmax2);
-    //
-    aBCom.Update(Max(aXmin1, aXmin2), Max(aYmin1, aYmin2), Max(aZmin1, aZmin2),
-                 Min(aXmax1, aXmax2), Min(aYmax1, aYmax2), Min(aZmax1, aZmax2));
-    //
-    aBCom.Get(aXmin1, aYmin1, aZmin1, aXmax1, aYmax1, aZmax1);
-    theBOut = aBCom;
-  }
-  return bRet;
+  return aNbSegments;
 }
 
 //=======================================================================
@@ -1258,6 +1284,40 @@ void BndBuildBox(const BRepAdaptor_Curve& theBAC,
   theBox = aB;
 }
 
+//=======================================================================
+//function : PointBoxDistance
+//purpose  : 
+//=======================================================================
+Standard_Real PointBoxDistance(const Bnd_Box& aB,
+                               const gp_Pnt& aP)
+{
+  Standard_Real aPCoord[3];
+  Standard_Real aBMinCoord[3], aBMaxCoord[3];
+  Standard_Real aDist, aR1, aR2;
+  Standard_Integer i;
+  //
+  aP.Coord(aPCoord[0], aPCoord[1], aPCoord[2]);
+  aB.Get(aBMinCoord[0], aBMinCoord[1], aBMinCoord[2], 
+         aBMaxCoord[0], aBMaxCoord[1], aBMaxCoord[2]);
+  //
+  aDist = 0.;
+  for (i = 0; i < 3; ++i) {
+    aR1 = aBMinCoord[i] - aPCoord[i];
+    if (aR1 > 0.) {
+      aDist += aR1*aR1;
+      continue;
+    }
+    //
+    aR2 = aPCoord[i] - aBMaxCoord[i];
+    if (aR2 > 0.) {
+      aDist += aR2*aR2;
+    }
+  }
+  //
+  aDist = Sqrt(aDist);
+  return aDist;
+}
+
 //=======================================================================
 //function : TypeToInteger
 //purpose  : 
@@ -1270,12 +1330,12 @@ Standard_Integer TypeToInteger(const GeomAbs_CurveType theCType)
   case GeomAbs_Line:
     iRet=0;
     break;
-  case GeomAbs_Circle:
+  case GeomAbs_Hyperbola:
+  case GeomAbs_Parabola:
     iRet=1;
     break;
+  case GeomAbs_Circle:
   case GeomAbs_Ellipse:
-  case GeomAbs_Hyperbola:
-  case GeomAbs_Parabola:
     iRet=2;
     break;
   case GeomAbs_BezierCurve:
@@ -1289,3 +1349,178 @@ Standard_Integer TypeToInteger(const GeomAbs_CurveType theCType)
   return iRet;
 }
 
+//=======================================================================
+//function : ResolutionCoeff
+//purpose  : 
+//=======================================================================
+Standard_Real ResolutionCoeff(const BRepAdaptor_Curve& theBAC,
+                              const IntTools_Range& theRange)
+{
+  Standard_Real aResCoeff = 0.;
+  //
+  const Handle(Geom_Curve)& aCurve = theBAC.Curve().Curve();
+  const GeomAbs_CurveType aCurveType = theBAC.GetType();
+  //
+  switch (aCurveType) {
+  case GeomAbs_Circle :
+    aResCoeff = 1. / (2 * Handle(Geom_Circle)::DownCast (aCurve)->Circ().Radius());
+    break;
+  case GeomAbs_Ellipse :
+    aResCoeff =  1. / Handle(Geom_Ellipse)::DownCast (aCurve)->MajorRadius();
+    break;
+  case GeomAbs_OffsetCurve : {
+    const Handle(Geom_OffsetCurve)& anOffsetCurve = Handle(Geom_OffsetCurve)::DownCast(aCurve);
+    const Handle(Geom_Curve)& aBasisCurve = anOffsetCurve->BasisCurve();
+    const GeomAbs_CurveType aBCType = GeomAdaptor_Curve(aBasisCurve).GetType();
+    if (aBCType == GeomAbs_Line) {
+      break;
+    }
+    else if (aBCType == GeomAbs_Circle) {
+      aResCoeff = 1. / (2 * (anOffsetCurve->Offset() +
+        Handle(Geom_Circle)::DownCast (aBasisCurve)->Circ().Radius()));
+      break;
+    }
+    else if (aBCType == GeomAbs_Ellipse) {
+      aResCoeff = 1. / (anOffsetCurve->Offset() +
+        Handle(Geom_Ellipse)::DownCast (aBasisCurve)->MajorRadius());
+      break;
+    }
+  }
+  case GeomAbs_Hyperbola :
+  case GeomAbs_Parabola : 
+  case GeomAbs_OtherCurve :{
+    Standard_Real k, kMin, aDist, aDt, aT1, aT2, aT;
+    Standard_Integer aNbP, i;
+    gp_Pnt aP1, aP2;
+    //
+    aNbP = 30;
+    theRange.Range(aT1, aT2);
+    aDt = (aT2 - aT1) / aNbP;
+    aT = aT1;
+    kMin = 10.;
+    //
+    theBAC.D0(aT1, aP1);
+    for (i = 1; i <= aNbP; ++i) {
+      aT += aDt;
+      theBAC.D0(aT, aP2);
+      aDist = aP1.Distance(aP2);
+      k = aDt / aDist;
+      if (k < kMin) {
+        kMin = k;
+      }
+      aP1 = aP2;
+    }
+    //
+    aResCoeff = kMin;
+    break;
+  }
+  default:
+    break;
+  }
+  //
+  return aResCoeff;
+}
+
+//=======================================================================
+//function : Resolution
+//purpose  : 
+//=======================================================================
+Standard_Real Resolution(const Handle(Geom_Curve)& theCurve,
+                         const GeomAbs_CurveType theCurveType,
+                         const Standard_Real theResCoeff,
+                         const Standard_Real theR3D)
+{
+  Standard_Real aRes;
+  //
+  switch (theCurveType) {
+  case GeomAbs_Line :
+    aRes = theR3D;
+    break;
+  case GeomAbs_Circle: {
+    Standard_Real aDt = theResCoeff * theR3D;
+    aRes = (aDt <= 1.) ? 2*ASin(aDt) : 2*M_PI;
+    break;
+  }
+  case GeomAbs_BezierCurve:
+    Handle(Geom_BezierCurve)::DownCast (theCurve)->Resolution(theR3D, aRes);
+    break;
+  case GeomAbs_BSplineCurve:
+    Handle(Geom_BSplineCurve)::DownCast (theCurve)->Resolution(theR3D, aRes);
+    break;
+  case GeomAbs_OffsetCurve: {
+    const Handle(Geom_Curve)& aBasisCurve = 
+      Handle(Geom_OffsetCurve)::DownCast(theCurve)->BasisCurve();
+    const GeomAbs_CurveType aBCType = GeomAdaptor_Curve(aBasisCurve).GetType();
+    if (aBCType == GeomAbs_Line) {
+      aRes = theR3D;
+      break;
+    }
+    else if (aBCType == GeomAbs_Circle) {
+      Standard_Real aDt = theResCoeff * theR3D;
+      aRes = (aDt <= 1.) ? 2*ASin(aDt) : 2*M_PI;
+      break;
+    }
+  }
+  default:
+    aRes = theResCoeff * theR3D;
+    break;
+  }
+  //
+  return aRes;
+}
+
+//=======================================================================
+//function : CurveDeflection
+//purpose  : 
+//=======================================================================
+Standard_Real CurveDeflection(const BRepAdaptor_Curve& theBAC,
+                              const IntTools_Range& theRange)
+{
+  Standard_Real aDt, aT, aT1, aT2, aDefl;
+  Standard_Integer i, aNbP;
+  gp_Vec aV1, aV2;
+  gp_Pnt aP;
+  //
+  aDefl = 0;
+  aNbP = 10;
+  theRange.Range(aT1, aT2);
+  aDt = (aT2 - aT1) / aNbP;
+  aT = aT1;
+  //
+  theBAC.D1(aT1, aP, aV1);
+  for (i = 1; i <= aNbP; ++i) {
+    aT += aDt;
+    theBAC.D1(aT, aP, aV2);
+    if (aV1.Magnitude() > gp::Resolution() &&
+        aV2.Magnitude() > gp::Resolution()) {
+      gp_Dir aD1(aV1), aD2(aV2);
+      aDefl += aD1.Angle(aD2);
+    }
+    aV1 = aV2;
+  }
+  //
+  return aDefl;
+}
+
+//=======================================================================
+//function : IsClosed
+//purpose  : 
+//=======================================================================
+Standard_Boolean IsClosed(const Handle(Geom_Curve)& theCurve,
+                          const Standard_Real aT1,
+                          const Standard_Real aT2,
+                          const Standard_Real theTol,
+                          const Standard_Real theRes)
+{
+  if (Abs(aT1 - aT2) < theRes)
+  {
+    return Standard_False;
+  }
+
+  gp_Pnt aP1, aP2;
+  theCurve->D0(aT1, aP1);
+  theCurve->D0(aT2, aP2);
+  //
+  Standard_Real aD = aP1.Distance(aP2);
+  return aD < theTol;
+}