0026310: Very slow boolean cut operations on cylinders
authornbv <nbv@opencascade.com>
Wed, 22 Jul 2015 13:10:27 +0000 (16:10 +0300)
committerbugmaster <bugmaster@opencascade.com>
Wed, 22 Jul 2015 13:11:31 +0000 (16:11 +0300)
1. JoinWLines algorithm has been improved.
2. Reference to the V-boundaries is deleted when computing step.
3. Decreasing the tolerance when computing parameters of WLine.
4. Adding boundary point is forbidden if it lies in prolongation of found ones.
5. Possible reason of exception has been eliminated.
6. Processing of critical point has been improved.

Test cases for this issue have been created.
Correction of some test case(s).

Test case bugs/modalg_6/bug26310_4 is added

Update of test-cases for issue #26310

src/IntPatch/IntPatch_ImpImpIntersection_4.gxx
src/IntPatch/IntPatch_Intersection.cxx
src/IntTools/IntTools_FaceFace.cxx
tests/bugs/modalg_5/bug24915
tests/bugs/modalg_5/bug25292_11
tests/bugs/modalg_5/bug25292_12
tests/bugs/modalg_6/bug26310_1 [new file with mode: 0644]
tests/bugs/modalg_6/bug26310_2 [new file with mode: 0644]
tests/bugs/modalg_6/bug26310_3 [new file with mode: 0644]
tests/bugs/modalg_6/bug26310_4 [new file with mode: 0644]

index f35ad6b..705840d 100644 (file)
@@ -14,6 +14,8 @@
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
+#include <algorithm>
+#include <Standard_DivideByZero.hxx>
 #include <IntAna_ListOfCurve.hxx>
 #include <IntAna_ListIteratorOfListOfCurve.hxx>
 #include <IntPatch_WLine.hxx>
@@ -82,8 +84,6 @@ static inline void MinMax(Standard_Real& theParMIN, Standard_Real& theParMAX)
 static void VBoundaryPrecise( const math_Matrix& theMatr,
                               const Standard_Real theV1AfterDecrByDelta,
                               const Standard_Real theV2AfterDecrByDelta,
-                              const Standard_Real theV1f,
-                              const Standard_Real theV2f,
                               Standard_Real& theV1Set,
                               Standard_Real& theV2Set)
 {
@@ -108,12 +108,12 @@ static void VBoundaryPrecise( const math_Matrix& theMatr,
 
   if(aDet*aDet1 > 0.0)
   {
-    theV1Set = Max(theV1AfterDecrByDelta, theV1f);
+    theV1Set = theV1AfterDecrByDelta;
   }
 
   if(aDet*aDet2 > 0.0)
   {
-    theV2Set = Max(theV2AfterDecrByDelta, theV2f);
+    theV2Set = theV2AfterDecrByDelta;
   }
 }
 
@@ -160,15 +160,25 @@ static Standard_Boolean StepComputing(const math_Matrix& theMatr,
                                       const Standard_Real theV2Cur,
                                       const Standard_Real theDeltaV1,
                                       const Standard_Real theDeltaV2,
-                                      const Standard_Real theV1f,
-                                      const Standard_Real theV1l,
-                                      const Standard_Real theV2f,
-                                      const Standard_Real theV2l,
                                       Standard_Real& theDeltaU1Found/*,
                                       Standard_Real& theDeltaU2Found,
                                       Standard_Real& theV1Found,
                                       Standard_Real& theV2Found*/)
 {
+#ifdef OCCT_DEBUG
+  bool flShow = false;
+
+  if(flShow)
+  {
+    printf("{%+10.20f*V1 + %+10.20f*V2 + %+10.20f*dU1 + %+10.20f*dU2 = %+10.20f\n",
+              theMatr(1,1), theMatr(1,2), theMatr(1,3), theMatr(1,4), theMatr(1,5));
+    printf("{%+10.20f*V1 + %+10.20f*V2 + %+10.20f*dU1 + %+10.20f*dU2 = %+10.20f\n",
+              theMatr(2,1), theMatr(2,2), theMatr(2,3), theMatr(2,4), theMatr(2,5));
+    printf("{%+10.20f*V1 + %+10.20f*V2 + %+10.20f*dU1 + %+10.20f*dU2 = %+10.20f\n",
+              theMatr(3,1), theMatr(3,2), theMatr(3,3), theMatr(3,4), theMatr(3,5));
+  }
+#endif
+
   Standard_Boolean isSuccess = Standard_False;
   theDeltaU1Found/* = theDeltaU2Found*/ = RealLast();
   //theV1Found = theV1set;
@@ -180,12 +190,12 @@ static Standard_Boolean StepComputing(const math_Matrix& theMatr,
 
   //By default, increasing V1(U1) and V2(U1) functions is
   //considered
-  Standard_Real aV1Set = Min(theV1Cur + theDeltaV1, theV1l),
-                aV2Set = Min(theV2Cur + theDeltaV2, theV2l);
+  Standard_Real aV1Set = theV1Cur + theDeltaV1,
+                aV2Set = theV2Cur + theDeltaV2;
 
-  //However, what is indead?
-  VBoundaryPrecise( theMatr, theV1Cur - theDeltaV1, theV2Cur - theDeltaV2,
-                    theV1f, theV2f, aV1Set, aV2Set);
+  //However, what is indeed?
+  VBoundaryPrecise( theMatr, theV1Cur - theDeltaV1,
+                    theV2Cur - theDeltaV2, aV1Set, aV2Set);
 
   aSyst.SetCol(2, theMatr.Col(3));
   aSyst.SetCol(3, theMatr.Col(4));
@@ -1213,37 +1223,81 @@ static Standard_Boolean CylCylMonotonicity( const Standard_Real theU1par,
   return Standard_True;
 }
 
+//=======================================================================
+//function : CylCylComputeParameters
+//purpose  : Computes U2 (U-parameter of the 2nd cylinder) and, if theDelta != 0,
+//            esimates the tolerance of U2-computing (estimation result is
+//            assigned to *theDelta value).
+//=======================================================================
 static Standard_Boolean CylCylComputeParameters(const Standard_Real theU1par,
                                                 const Standard_Integer theWLIndex,
                                                 const stCoeffsValue& theCoeffs,
-                                                Standard_Real& theU2)
+                                                Standard_Real& theU2,
+                                                Standard_Real* const theDelta = 0)
 {
-  Standard_Real aSign = 0.0;
+  //This formula is got from some experience and can be changed.
+  const Standard_Real aTol0 = Min(10.0*Epsilon(1.0)*theCoeffs.mB, aNulValue);
+  const Standard_Real aTol = 1.0 - aTol0;
 
-  switch(theWLIndex)
-  {
-  case 0: 
-    aSign = 1.0;
-    break;
-  case 1:
-    aSign = -1.0;
-    break;
-  default:
-    //Standard_Failure::Raise("Error. Range Error!!!!");
+  if(theWLIndex < 0 || theWLIndex > 1)
     return Standard_False;
-  }
 
-  Standard_Real anArg = theCoeffs.mB * 
-                        cos(theU1par - theCoeffs.mFI1) +
-                        theCoeffs.mC;
+  const Standard_Real aSign = theWLIndex ? -1.0 : 1.0;
+
+  Standard_Real anArg = cos(theU1par - theCoeffs.mFI1);
+  anArg = theCoeffs.mB*anArg + theCoeffs.mC;
+
+  if(anArg > aTol)
+  {
+    if(theDelta)
+      *theDelta = 0.0;
 
-  if(aNulValue > 1.0 - anArg)
     anArg = 1.0;
+  }
+  else if(anArg < -aTol)
+  {
+    if(theDelta)
+      *theDelta = 0.0;
 
-  if(anArg + 1.0 < aNulValue)
     anArg = -1.0;
+  }
+  else if(theDelta)
+  {
+    //There is a case, when
+    //  const double aPar = 0.99999999999721167;
+    //  const double aFI2 = 2.3593296083566181e-006;
 
-  theU2 = theCoeffs.mFI2 + aSign*acos(anArg);
+    //Then
+    //  aPar - cos(aFI2) == -5.10703e-015 ==> cos(aFI2) == aPar. 
+    //Theoreticaly, in this case 
+    //  aFI2 == +/- acos(aPar).
+    //However,
+    //  acos(aPar) - aFI2 == 2.16362e-009.
+    //Error is quite big.
+
+    //This error should be estimated. Let use following way, which is based
+    //on expanding to Taylor series.
+
+    //  acos(p)-acos(p+x) = x/sqrt(1-p*p).
+
+    //If p == (1-d) (when p > 0) or p == (-1+d) (when p < 0) then
+    //  acos(p)-acos(p+x) = x/sqrt(d*(2-d)).
+
+    //Here always aTol0 <= d <= 1. Max(x) is considered (!) to be equal to aTol0.
+    //In this case
+    //  8*aTol0 <= acos(p)-acos(p+x) <= sqrt(2/(2-aTol0)-1),
+    //                                              because 0 < aTol0 < 1.
+    //E.g. when aTol0 = 1.0e-11,
+    //   8.0e-11 <= acos(p)-acos(p+x) < 2.24e-6.
+
+    const Standard_Real aDelta = Min(1.0-anArg, 1.0+anArg);
+    Standard_DivideByZero_Raise_if((aDelta*aDelta < RealSmall()) || (aDelta >= 2.0), 
+          "IntPatch_ImpImpIntersection_4.gxx, CylCylComputeParameters()");
+    *theDelta = aTol0/sqrt(aDelta*(2.0-aDelta));
+  }
+
+  theU2 = acos(anArg);
+  theU2 = theCoeffs.mFI2 + aSign*theU2;
 
   return Standard_True;
 }
@@ -1436,6 +1490,11 @@ Standard_Boolean InscribePoint( const Standard_Real theUfTarget,
                                 const Standard_Real thePeriod,
                                 const Standard_Boolean theFlForce)
 {
+  if(Precision::IsInfinite(theUGiven))
+  {
+    return Standard_False;
+  }
+
   if((theUfTarget - theUGiven <= theTol2D) &&
               (theUGiven - theUlTarget <= theTol2D))
   {//it has already inscribed
@@ -1471,6 +1530,9 @@ Standard_Boolean InscribePoint( const Standard_Real theUfTarget,
     return Standard_False;
   }
 
+  //Make theUGiven nearer to theUfTarget (in order to avoid
+  //excess iterations)
+  theUGiven += thePeriod*Floor((theUfTarget-theUGiven)/thePeriod);
   Standard_Real aDU = theUGiven - theUfTarget;
 
   if(aDU > 0.0)
@@ -1478,12 +1540,15 @@ Standard_Boolean InscribePoint( const Standard_Real theUfTarget,
   else
     aDU = +thePeriod;
 
-  while(((theUGiven - theUfTarget)*aDU < 0.0) && !((theUfTarget - theUGiven <= theTol2D) && (theUGiven - theUlTarget <= theTol2D)))
+  while(((theUGiven - theUfTarget)*aDU < 0.0) && 
+        !((theUfTarget - theUGiven <= theTol2D) &&
+        (theUGiven - theUlTarget <= theTol2D)))
   {
     theUGiven += aDU;
   }
   
-  return ((theUfTarget - theUGiven <= theTol2D) && (theUGiven - theUlTarget <= theTol2D));
+  return ((theUfTarget - theUGiven <= theTol2D) &&
+          (theUGiven - theUlTarget <= theTol2D));
 }
 
 //=======================================================================
@@ -1524,41 +1589,44 @@ static Standard_Boolean InscribeInterval(const Standard_Real theUfTarget,
 }
 
 //=======================================================================
-//function : InscribeAndSortArray
-//purpose  : Sort from Min to Max value
+//function : ExcludeNearElements
+//purpose  : Checks if theArr contains two almost equal elements.
+//            If it is true then one of equal elements will be excluded
+//            (made infinite).
+//           Returns TRUE if at least one element of theArr has been changed.
+//ATTENTION!!!
+//           1. Every not infinite element of theArr is considered to be 
+//            in [0, T] interval (where T is the period);
+//           2. theArr must be sorted in ascending order.
 //=======================================================================
-static void InscribeAndSortArray( Standard_Real theArr[],
-                                  const Standard_Integer theNOfMembers,
-                                  const Standard_Real theUf,
-                                  const Standard_Real theUl,
-                                  const Standard_Real theTol2D,
-                                  const Standard_Real thePeriod)
+static Standard_Boolean ExcludeNearElements(Standard_Real theArr[],
+                                            const Standard_Integer theNOfMembers,
+                                            const Standard_Real theTol)
 {
-  for(Standard_Integer i = 0; i < theNOfMembers; i++)
+  Standard_Boolean aRetVal = Standard_False;
+  for(Standard_Integer i = 1; i < theNOfMembers; i++)
   {
-    if(Precision::IsInfinite(theArr[i]))
-    {
-      if(theArr[i] < 0.0)
-        theArr[i] = -theArr[i];
+    Standard_Real &anA = theArr[i],
+                  &anB = theArr[i-1];
 
-      continue;
-    }
+    //Here, anA >= anB
 
-    InscribePoint(theUf, theUl, theArr[i], theTol2D, thePeriod, Standard_False);
+    if(Precision::IsInfinite(anA))
+      break;
 
-    for(Standard_Integer j = i - 1; j >= 0; j--)
+    if((anA-anB) < theTol)
     {
+      anA = (anA + anB)/2.0;
 
-      if(theArr[j+1] < theArr[j])
-      {
-        Standard_Real anUtemp = theArr[j+1];
-        theArr[j+1] = theArr[j];
-        theArr[j] = anUtemp;
-      }
+      //Make this element infinite an forget it
+      //(we will not use it in next iterations).
+      anB = Precision::Infinite();
+      aRetVal = Standard_True;
     }
   }
-}
 
+  return aRetVal;
+}
 
 //=======================================================================
 //function : AddPointIntoWL
@@ -1768,9 +1836,12 @@ static Standard_Boolean AddBoundaryPoint( const IntSurf_Quadric& theQuad1,
   if(!isTheFound1 && !isTheFound2)
     return Standard_True;
 
+  //We increase U1 parameter. Therefore, added point must have U1 parameter less than
+  //or equal to current (conditions "(anUpar1 < theU1)" and "(anUpar2 < theU1)").
+
   if(anUpar1 < anUpar2)
   {
-    if(isTheFound1)
+    if(isTheFound1 && (anUpar1 < theU1))
     {
       Standard_Real aU2 = theU2, aV1 = theV1, aV2 = theV2;
       if(!CylCylComputeParameters(anUpar1, theWLIndex, theCoeffs, aU2, aV1, aV2))
@@ -1794,8 +1865,12 @@ static Standard_Boolean AddBoundaryPoint( const IntSurf_Quadric& theQuad1,
         isTheFound1 = Standard_False;
       }
     }
+    else
+    {
+      isTheFound1 = Standard_False;
+    }
 
-    if(isTheFound2)
+    if(isTheFound2 && (anUpar2 < theU1))
     {
       Standard_Real aU2 = theU2, aV1 = theV1, aV2 = theV2;
       if(!CylCylComputeParameters(anUpar2, theWLIndex, theCoeffs, aU2, aV1, aV2))
@@ -1819,10 +1894,14 @@ static Standard_Boolean AddBoundaryPoint( const IntSurf_Quadric& theQuad1,
         isTheFound2 = Standard_False;
       }
     }
+    else
+    {
+      isTheFound2 = Standard_False;
+    }
   }
   else
   {
-    if(isTheFound2)
+    if(isTheFound2 && (anUpar2 < theU1))
     {
       Standard_Real aU2 = theU2, aV1 = theV1, aV2 = theV2;
       if(!CylCylComputeParameters(anUpar2, theWLIndex, theCoeffs, aU2, aV1, aV2))
@@ -1846,8 +1925,12 @@ static Standard_Boolean AddBoundaryPoint( const IntSurf_Quadric& theQuad1,
         isTheFound2 = Standard_False;
       }
     }
+    else
+    {
+      isTheFound2 = Standard_False;
+    }
 
-    if(isTheFound1)
+    if(isTheFound1 && (anUpar1 < theU1))
     {
       Standard_Real aU2 = theU2, aV1 = theV1, aV2 = theV2;
       if(!CylCylComputeParameters(anUpar1, theWLIndex, theCoeffs, aU2, aV1, aV2))
@@ -1871,6 +1954,10 @@ static Standard_Boolean AddBoundaryPoint( const IntSurf_Quadric& theQuad1,
         isTheFound1 = Standard_False;
       }
     }
+    else
+    {
+      isTheFound1 = Standard_False;
+    }
   }
 
   return Standard_True;
@@ -2001,7 +2088,7 @@ static void SeekAdditionalPoints( const IntSurf_Quadric& theQuad1,
 
 //=======================================================================
 //function : CriticalPointsComputing
-//purpose  : 
+//purpose  : theNbCritPointsMax contains true number of critical points
 //=======================================================================
 static void CriticalPointsComputing(const stCoeffsValue& theCoeffs,
                                     const Standard_Real theUSurf1f,
@@ -2010,9 +2097,19 @@ static void CriticalPointsComputing(const stCoeffsValue& theCoeffs,
                                     const Standard_Real theUSurf2l,
                                     const Standard_Real thePeriod,
                                     const Standard_Real theTol2D,
-                                    const Standard_Integer theNbCritPointsMax,
+                                    Standard_Integer& theNbCritPointsMax,
                                     Standard_Real theU1crit[])
 {
+  //[0...1] - in these points parameter U1 goes through
+  //          the seam-edge of the first cylinder.
+  //[2...3] - First and last U1 parameter.
+  //[4...5] - in these points parameter U2 goes through
+  //          the seam-edge of the second cylinder.
+  //[6...9] - in these points an intersection line goes through
+  //          U-boundaries of the second surface.
+
+  theNbCritPointsMax = 10;
+
   theU1crit[0] = 0.0;
   theU1crit[1] = thePeriod;
   theU1crit[2] = theUSurf1f;
@@ -2029,31 +2126,86 @@ static void CriticalPointsComputing(const stCoeffsValue& theCoeffs,
       anArg = -1.0;
 
     theU1crit[4] = -acos(anArg) + theCoeffs.mFI1;
-    theU1crit[5] = acos(anArg) + theCoeffs.mFI1;
+    theU1crit[5] =  acos(anArg) + theCoeffs.mFI1;
   }
 
   Standard_Real aSf = cos(theUSurf2f - theCoeffs.mFI2);
   Standard_Real aSl = cos(theUSurf2l - theCoeffs.mFI2);
   MinMax(aSf, aSl);
 
-  theU1crit[6] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ? -acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 : -Precision::Infinite();
-  theU1crit[7] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ? -acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 : Precision::Infinite();
-  theU1crit[8] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?  acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 : -Precision::Infinite();
-  theU1crit[9] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?  acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 : Precision::Infinite();
+  //In accorance with pure mathematic, theU1crit[6] and [8]
+  //must be -Precision::Infinite() instead of used +Precision::Infinite()
+  theU1crit[6] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?
+                  -acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 :
+                  Precision::Infinite();
+  theU1crit[7] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?
+                  -acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 :
+                  Precision::Infinite();
+  theU1crit[8] = Abs((aSf - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?
+                  acos((aSf - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 :
+                  Precision::Infinite();
+  theU1crit[9] = Abs((aSl - theCoeffs.mC) / theCoeffs.mB) < 1.0 ?
+                  acos((aSl - theCoeffs.mC) / theCoeffs.mB) + theCoeffs.mFI1 :
+                  Precision::Infinite();
+
+  //preparative treatment of array. This array must have faled to contain negative
+  //infinity number
+
+  for(Standard_Integer i = 0; i < theNbCritPointsMax; i++)
+  {
+    if(Precision::IsInfinite(theU1crit[i]))
+    {
+      continue;
+    }
+
+    theU1crit[i] = fmod(theU1crit[i], thePeriod);
+    if(theU1crit[i] < 0.0)
+      theU1crit[i] += thePeriod;
+  }
 
-  //preparative treatment of array
-  InscribeAndSortArray(theU1crit, theNbCritPointsMax, 0.0, thePeriod, theTol2D, thePeriod);
-  for(Standard_Integer i = 1; i < theNbCritPointsMax; i++)
+  //Here all not infinite elements of theU1crit are in [0, thePeriod) range
+
+  do
   {
-    Standard_Real &a = theU1crit[i],
-                  &b = theU1crit[i-1];
-    const Standard_Real aRemain = fmod(Abs(a - b), thePeriod); // >= 0, because Abs(a - b) >= 0
-    if((Abs(a - b) < theTol2D) || (aRemain < theTol2D) || (Abs(aRemain - thePeriod) < theTol2D))
+    std::sort(theU1crit, theU1crit + theNbCritPointsMax);
+  }
+  while(ExcludeNearElements(theU1crit, theNbCritPointsMax, theTol2D));
+
+  //Here all not infinite elements in theU1crit are different and sorted.
+
+  while(theNbCritPointsMax > 0)
+  {
+    Standard_Real &anB = theU1crit[theNbCritPointsMax-1];
+    if(Precision::IsInfinite(anB))
     {
-      a = (a + b)/2.0;
-      b = Precision::Infinite();
+      theNbCritPointsMax--;
+      continue;
+    }
+
+    //1st not infinte element is found
+
+    if(theNbCritPointsMax == 1)
+      break;
+
+    //Here theNbCritPointsMax > 1
+
+    Standard_Real &anA = theU1crit[0];
+
+    //Compare 1st and last significant elements of theU1crit
+    //They may still differs by period.
+
+    if (Abs(anB - anA - thePeriod) < theTol2D)
+    {//E.g. anA == 2.0e-17, anB == (thePeriod-1.0e-18)
+      anA = (anA + anB - thePeriod)/2.0;
+      anB = Precision::Infinite();
+      theNbCritPointsMax--;
     }
+
+    //Out of "while(theNbCritPointsMax > 0)" cycle.
+    break;
   }
+
+  //Attention! Here theU1crit may be unsorted.
 }
 
 //=======================================================================
@@ -2110,7 +2262,10 @@ Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
                       RealToInt(20.0*aCyl1.Radius())), aNbMaxPoints);
   const Standard_Real aPeriod = 2.0*M_PI;
   const Standard_Real aStepMin = theTol2D, 
-                      aStepMax = (aUSurf1l-aUSurf1f)/IntToReal(aNbPoints);
+                      aStepMax =  (aUSurf1l-aUSurf1f > M_PI/100.0) ?
+                                  (aUSurf1l-aUSurf1f)/IntToReal(aNbPoints) :
+                                  aUSurf1l-aUSurf1f;
+
   const Standard_Integer aNbWLines = 2;
 
   const stCoeffsValue anEquationCoeffs(aCyl1, aCyl2);
@@ -2289,13 +2444,6 @@ Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
   }
 
   //Critical points
-  //[0...1] - in these points parameter U1 goes through
-  //          the seam-edge of the first cylinder.
-  //[2...3] - First and last U1 parameter.
-  //[4...5] - in these points parameter U2 goes through
-  //          the seam-edge of the second cylinder.
-  //[6...9] - in these points an intersection line goes through
-  //          U-boundaries of the second surface.
   const Standard_Integer aNbCritPointsMax = 10;
   Standard_Real anU1crit[aNbCritPointsMax] = {Precision::Infinite(),
                                               Precision::Infinite(),
@@ -2308,9 +2456,9 @@ Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
                                               Precision::Infinite(),
                                               Precision::Infinite()};
 
+  Standard_Integer aNbCritPoints = aNbCritPointsMax;
   CriticalPointsComputing(anEquationCoeffs, aUSurf1f, aUSurf1l, aUSurf2f, aUSurf2l,
-                                      aPeriod, theTol2D, aNbCritPointsMax, anU1crit);
-
+                                      aPeriod, theTol2D, aNbCritPoints, anU1crit);
 
   //Getting Walking-line
 
@@ -2334,7 +2482,12 @@ Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
     const Standard_Boolean isDeltaPeriod  = IsEqual(anUl-anUf, aPeriod);
 
     //Inscribe and sort critical points
-    InscribeAndSortArray(anU1crit, aNbCritPointsMax, anUf, anUl, theTol2D, aPeriod);
+    for(Standard_Integer i = 0; i < aNbCritPoints; i++)
+    {
+      InscribePoint(anUf, anUl, anU1crit[i], theTol2D, aPeriod, Standard_False);
+    }
+
+    std::sort(anU1crit, anU1crit + aNbCritPoints);
 
     while(anUf < anUl)
     {
@@ -2357,17 +2510,20 @@ Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
         anUexpect[i] = anUf;
       }
       
-      Standard_Real anU1 = anUf;
-
       Standard_Real aCriticalDelta[aNbCritPointsMax];
-      for(Standard_Integer i = 0; i < aNbCritPointsMax; i++)
-        aCriticalDelta[i] = anU1 - anU1crit[i];
+      for(Standard_Integer aCritPID = 0; aCritPID < aNbCritPoints; aCritPID++)
+      { //We are not intersted in elements of aCriticalDelta array
+        //if their index is greater than or equal to aNbCritPoints
+
+        aCriticalDelta[aCritPID] = anUf - anU1crit[aCritPID];
+      }
 
+      Standard_Real anU1 = anUf;
       Standard_Boolean isFirst = Standard_True;
 
       while(anU1 <= anUl)
       {
-        for(Standard_Integer i = 0; i < aNbCritPointsMax; i++)
+        for(Standard_Integer i = 0; i < aNbCritPoints; i++)
         {
           if((anU1 - anU1crit[i])*aCriticalDelta[i] < 0.0)
           {
@@ -2392,7 +2548,7 @@ Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
 
             if(isDeltaPeriod)
             {
-              //if isAddedIntoWL* == TRUE WLine contains only one point
+              //if isAddedIntoWL[i] == TRUE WLine contains only one point
               //(which was end point of previous WLine). If we will
               //add point found on the current step WLine will contain only
               //two points. At that both these points will be equal to the
@@ -2422,11 +2578,33 @@ Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
         {
           const Standard_Integer aNbPntsWL =  aWLine[i].IsNull() ? 0 :
                                               aWLine[i]->Curve()->NbPoints();
+          
+          if( (aWLFindStatus[i] == WLFStatus_Broken) ||
+              (aWLFindStatus[i] == WLFStatus_Absent))
+          {//Begin and end of WLine must be on boundary point
+           //or on seam-edge strictly (if it is possible).
 
-          CylCylComputeParameters(anU1, i, anEquationCoeffs, aU2[i]);
+            Standard_Real aTol = theTol2D;
+            CylCylComputeParameters(anU1, i, anEquationCoeffs, aU2[i], &aTol);
+            InscribePoint(aUSurf2f, aUSurf2l, aU2[i], theTol2D, aPeriod, Standard_False);
 
-          InscribePoint(aUSurf2f, aUSurf2l, aU2[i], theTol2D, aPeriod, Standard_False);
+            aTol = Max(aTol, theTol2D);
 
+            if(Abs(aU2[i]) <= aTol)
+              aU2[i] = 0.0;
+            else if(Abs(aU2[i] - aPeriod) <= aTol)
+              aU2[i] = aPeriod;
+            else if(Abs(aU2[i] - aUSurf2f) <= aTol)
+              aU2[i] = aUSurf2f;
+            else if(Abs(aU2[i] - aUSurf2l) <= aTol)
+              aU2[i] = aUSurf2l;
+          }
+          else
+          {
+            CylCylComputeParameters(anU1, i, anEquationCoeffs, aU2[i]);
+            InscribePoint(aUSurf2f, aUSurf2l, aU2[i], theTol2D, aPeriod, Standard_False);
+          }
+          
           if(aNbPntsWL == 0)
           {//the line has not contained any points yet
             if(((aUSurf2f + aPeriod - aUSurf2l) <= 2.0*theTol2D) && 
@@ -2477,20 +2655,6 @@ Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
             }
           }
 
-          if( (aWLFindStatus[i] == WLFStatus_Broken) ||
-              (aWLFindStatus[i] == WLFStatus_Absent))
-          {//Begin and end of WLine must be on boundary point
-           //or on seam-edge strictly (if it is possible).
-            if(Abs(aU2[i]) <= theTol2D)
-              aU2[i] = 0.0;
-            else if(Abs(aU2[i] - aPeriod) <= theTol2D)
-              aU2[i] = aPeriod;
-            else if(Abs(aU2[i] - aUSurf2f) <= theTol2D)
-              aU2[i] = aUSurf2f;
-            else if(Abs(aU2[i] - aUSurf2l) <= theTol2D)
-              aU2[i] = aUSurf2l;
-          }
-
           CylCylComputeParameters(anU1, aU2[i], anEquationCoeffs, aV1[i], aV2[i]);
 
           if(isFirst)
@@ -2530,9 +2694,6 @@ Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
               isBoundIntersect = Standard_True;
             }
 
-            aV1Prev[i] = aV1[i];
-            aV2Prev[i] = aV2[i];
-
             if(aWLFindStatus[i] == WLFStatus_Broken)
               isBroken = Standard_True;
 
@@ -2587,6 +2748,10 @@ Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
                                                  (Abs(aV2Prev[i] - aVSurf2f) <= theTol2D) ||
                                                  (Abs(aV2Prev[i] - aVSurf2l) <= theTol2D));
 
+
+          aV1Prev[i] = aV1[i];
+          aV2Prev[i] = aV2[i];
+
           if((aWLFindStatus[i] == WLFStatus_Exist) && (isFound1 || isFound2) && !isPrevVBound)
           {
             aWLFindStatus[i] = WLFStatus_Broken; //start a new line
@@ -2651,9 +2816,6 @@ Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
             }
           }
           
-          aV1Prev[i] = aV1[i];
-          aV2Prev[i] = aV2[i];
-
           if(aWLFindStatus[i] == WLFStatus_Broken)
             isBroken = Standard_True;
         }//for(Standard_Integer i = 0; i < aNbWLines; i++)
@@ -2723,15 +2885,29 @@ Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
           if(!isAdded)
           {
             Standard_Real anUmaxAdded = RealFirst();
-            for(Standard_Integer i = 0; i < aNbWLines; i++)
+            
             {
-              Standard_Real aU1c = 0.0, aV1c = 0.0;
-              if(isTheReverse)
-                aWLine[i]->Curve()->Value(aWLine[i]->NbPnts()).ParametersOnS2(aU1c, aV1c);
-              else
-                aWLine[i]->Curve()->Value(aWLine[i]->NbPnts()).ParametersOnS1(aU1c, aV1c);
+              Standard_Boolean isChanged = Standard_False;
+              for(Standard_Integer i = 0; i < aNbWLines; i++)
+              {
+                if(aWLFindStatus[i] == WLFStatus_Absent)
+                  continue;
 
-              anUmaxAdded = Max(anUmaxAdded, aU1c);
+                Standard_Real aU1c = 0.0, aV1c = 0.0;
+                if(isTheReverse)
+                  aWLine[i]->Curve()->Value(aWLine[i]->NbPnts()).ParametersOnS2(aU1c, aV1c);
+                else
+                  aWLine[i]->Curve()->Value(aWLine[i]->NbPnts()).ParametersOnS1(aU1c, aV1c);
+
+                anUmaxAdded = Max(anUmaxAdded, aU1c);
+                isChanged = Standard_True;
+              }
+
+              if(!isChanged)
+              { //If anUmaxAdded were not changed in previous cycle then
+                //we would break existing WLines.
+                break;
+              }
             }
 
             for(Standard_Integer i = 0; i < aNbWLines; i++)
@@ -2794,7 +2970,7 @@ Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
                             anEquationCoeffs.mVecA2*aCosU2 + anEquationCoeffs.mVecB2*aSinU2 +
                             anEquationCoeffs.mVecD);
 
-            if(!StepComputing(aMatr, aV1[i], aV2[i], aDeltaV1, aDeltaV2, aVSurf1f, aVSurf1l, aVSurf2f, aVSurf2l, aStepTmp))
+            if(!StepComputing(aMatr, aV1[i], aV2[i], aDeltaV1, aDeltaV2, aStepTmp))
             {
               //To avoid cycling-up
               anUexpect[i] += aStepMax;
@@ -2887,8 +3063,8 @@ Standard_Boolean IntCyCyTrim( const IntSurf_Quadric& theQuad1,
   }
 
 
-//Delete the points in theSPnt, which
-//lie at least in one of the line in theSlin.
+  //Delete the points in theSPnt, which
+  //lie at least in one of the line in theSlin.
   for(Standard_Integer aNbPnt = 1; aNbPnt <= theSPnt.Length(); aNbPnt++)
   {
     for(Standard_Integer aNbLin = 1; aNbLin <= theSlin.Length(); aNbLin++)
index c9cfb06..0dec3fe 100644 (file)
 static const Standard_Integer aNbPointsInALine = 200;
 
 //=======================================================================
+//function : MinMax
+//purpose  : Replaces theParMIN = MIN(theParMIN, theParMAX),
+//                    theParMAX = MAX(theParMIN, theParMAX).
+//=======================================================================
+static inline void MinMax(Standard_Real& theParMIN, Standard_Real& theParMAX)
+{
+  if(theParMIN > theParMAX)
+  {
+    const Standard_Real aTmp = theParMAX;
+    theParMAX = theParMIN;
+    theParMIN = aTmp;
+  }
+}
+
+//=======================================================================
+//function : IsSeam
+//purpose  : Returns:
+//            0 - if interval [theU1, theU2] does not intersect the "seam-edge"
+//                or if "seam-edge" do not exist;
+//            1 - if interval (theU1, theU2) intersect the "seam-edge".
+//            2 - if theU1 or/and theU2 lie ON the "seam-edge"
+//
+//ATTENTION!!!
+//  If (theU1 == theU2) then this function will return only both 0 or 2.
+//=======================================================================
+static Standard_Integer IsSeam( const Standard_Real theU1,
+                                const Standard_Real theU2,
+                                const Standard_Real thePeriod)
+{
+  if(IsEqual(thePeriod, 0.0))
+    return 0;
+
+  //If interval [theU1, theU2] intersect seam-edge then there exists an integer
+  //number N such as 
+  //    (theU1 <= T*N <= theU2) <=> (theU1/T <= N <= theU2/T),
+  //where T is the period.
+  //I.e. the inerval [theU1/T, theU2/T] must contain at least one
+  //integer number. In this case, Floor(theU1/T) and Floor(theU2/T)
+  //return different values or theU1/T is strictly integer number.
+  //Examples:
+  //  1. theU1/T==2.8, theU2/T==3.5 => Floor(theU1/T) == 2, Floor(theU2/T) == 3.
+  //  2. theU1/T==2.0, theU2/T==2.6 => Floor(theU1/T) == Floor(theU2/T) == 2.
+
+  const Standard_Real aVal1 = theU1/thePeriod,
+                      aVal2 = theU2/thePeriod;
+  const Standard_Integer aPar1 = static_cast<Standard_Integer>(Floor(aVal1));
+  const Standard_Integer aPar2 = static_cast<Standard_Integer>(Floor(aVal2));
+  if(aPar1 != aPar2)
+  {//Interval (theU1, theU2] intersects seam-edge
+    if(IsEqual(aVal2, static_cast<Standard_Real>(aPar2)))
+    {//aVal2 is an integer number => theU2 lies ON the "seam-edge"
+      return 2;
+    }
+
+    return 1;
+  }
+
+  //Here, aPar1 == aPar2. 
+
+  if(IsEqual(aVal1, static_cast<Standard_Real>(aPar1)))
+  {//aVal1 is an integer number => theU1 lies ON the "seam-edge"
+    return 2;
+  }
+
+  //If aVal2 is a true integer number then always (aPar1 != aPar2).
+
+  return 0;
+}
+
+//=======================================================================
 //function : IsSeamOrBound
-//purpose  : Returns TRUE if point thePt1 lies in seam-edge
-//            (if it exists) or surface boundaries;
+//purpose  : Returns TRUE if segment [thePtf, thePtl] intersects "seam-edge"
+//            (if it exist) or surface boundaries and both thePtf and thePtl do
+//            not match "seam-edge" or boundaries.
+//           Point thePtmid lies in this segment. If thePtmid match
+//            "seam-edge" or boundaries strictly (without any tolerance) then
+//            the function will return TRUE.
+//            See comments in function body for detail information.
 //=======================================================================
-static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePt1,
+static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePtf,
+                                      const IntSurf_PntOn2S& thePtl,
+                                      const IntSurf_PntOn2S& thePtmid,
                                       const Standard_Real theU1Period,
                                       const Standard_Real theU2Period,
                                       const Standard_Real theV1Period,
@@ -56,26 +133,112 @@ static Standard_Boolean IsSeamOrBound(const IntSurf_PntOn2S& thePt1,
                                       const Standard_Real theVlSurf2)
 {
   Standard_Real aU11 = 0.0, aU12 = 0.0, aV11 = 0.0, aV12 = 0.0;
-  thePt1.Parameters(aU11, aV11, aU12, aV12);
+  Standard_Real aU21 = 0.0, aU22 = 0.0, aV21 = 0.0, aV22 = 0.0;
+  thePtf.Parameters(aU11, aV11, aU12, aV12);
+  thePtl.Parameters(aU21, aV21, aU22, aV22);
+
+  MinMax(aU11, aU21);
+  MinMax(aV11, aV21);
+  MinMax(aU12, aU22);
+  MinMax(aV12, aV22);
+
+  if((aU11 - theUfSurf1)*(aU21 - theUfSurf1) < 0.0)
+  {//Interval [aU11, aU21] intersects theUfSurf1
+    return Standard_True;
+  }
+
+  if((aU11 - theUlSurf1)*(aU21 - theUlSurf1) < 0.0)
+  {//Interval [aU11, aU21] intersects theUlSurf1
+    return Standard_True;
+  }
+
+  if((aV11 - theVfSurf1)*(aV21 - theVfSurf1) < 0.0)
+  {//Interval [aV11, aV21] intersects theVfSurf1
+    return Standard_True;
+  }
+
+  if((aV11 - theVlSurf1)*(aV21 - theVlSurf1) < 0.0)
+  {//Interval [aV11, aV21] intersects theVlSurf1
+    return Standard_True;
+  }
+
+  if((aU12 - theUfSurf2)*(aU22 - theUfSurf2) < 0.0)
+  {//Interval [aU12, aU22] intersects theUfSurf2
+    return Standard_True;
+  }
+
+  if((aU12 - theUlSurf2)*(aU22 - theUlSurf2) < 0.0)
+  {//Interval [aU12, aU22] intersects theUlSurf2
+    return Standard_True;
+  }
+
+  if((aV12 - theVfSurf2)*(aV22 - theVfSurf2) < 0.0)
+  {//Interval [aV12, aV22] intersects theVfSurf2
+    return Standard_True;
+  }
+
+  if((aV12 - theVlSurf2)*(aV22 - theVlSurf2) < 0.0)
+  {//Interval [aV12, aV22] intersects theVlSurf2
+    return Standard_True;
+  }
+
+  if(IsSeam(aU11, aU21, theU1Period))
+    return Standard_True;
+
+  if(IsSeam(aV11, aV21, theV1Period))
+    return Standard_True;
+
+  if(IsSeam(aU12, aU22, theU2Period))
+    return Standard_True;
+
+  if(IsSeam(aV12, aV22, theV2Period))
+    return Standard_True;
+
+  /*
+    The segment [thePtf, thePtl] does not intersect the boundaries and
+    the seam-edge of the surfaces.
+    Nevertheless, following situation is possible:
+
+                  seam or
+                   bound
+                     |
+        thePtf  *    |
+                     |
+                     * thePtmid
+          thePtl  *  |
+                     |
+
+    This case must be processed, too.
+  */
+
+  Standard_Real aU1 = 0.0, aU2 = 0.0, aV1 = 0.0, aV2 = 0.0;
+  thePtmid.Parameters(aU1, aV1, aU2, aV2);
+
+  if(IsEqual(aU1, theUfSurf1) || IsEqual(aU1, theUlSurf1))
+    return Standard_True;
+
+  if(IsEqual(aU2, theUfSurf2) || IsEqual(aU2, theUlSurf2))
+    return Standard_True;
+
+  if(IsEqual(aV1, theVfSurf1) || IsEqual(aV1, theVlSurf1))
+    return Standard_True;
+
+  if(IsEqual(aV2, theVfSurf2) || IsEqual(aV2, theVlSurf2))
+    return Standard_True;
 
-  Standard_Boolean aCond = Standard_False;
-  aCond = aCond || (!IsEqual(theU1Period, 0.0) &&
-                    IsEqual(fmod(aU11, theU1Period), 0.0));
+  if(IsSeam(aU1, aU1, theU1Period))
+    return Standard_True;
 
-  aCond = aCond || (!IsEqual(theU2Period, 0.0) &&
-                    IsEqual(fmod(aU12, theU2Period), 0.0));
+  if(IsSeam(aU2, aU2, theU2Period))
+    return Standard_True;
 
-  aCond = aCond || (!IsEqual(theV1Period, 0.0) &&
-                    IsEqual(fmod(aV11, theV1Period), 0.0));
+  if(IsSeam(aV1, aV1, theV1Period))
+    return Standard_True;
 
-  aCond = aCond || (!IsEqual(theV2Period, 0.0) &&
-                    IsEqual(fmod(aV12, theV2Period), 0.0));
+  if(IsSeam(aV2, aV2, theV2Period))
+    return Standard_True;
 
-  return  aCond ||
-          IsEqual(aU11, theUfSurf1) || IsEqual(aU11, theUlSurf1) ||
-          IsEqual(aU12, theUfSurf2) || IsEqual(aU12, theUlSurf2) ||
-          IsEqual(aV11, theVfSurf1) || IsEqual(aV11, theVlSurf1) ||
-          IsEqual(aV12, theVfSurf2) || IsEqual(aV12, theVlSurf2);
+  return Standard_False;
 }
 
 //=======================================================================
@@ -139,7 +302,6 @@ static void JoinWLines(IntPatch_SequenceOfLine& theSlin,
     {
       Handle(IntPatch_WLine) aWLine2 (Handle(IntPatch_WLine)::DownCast(theSlin.Value(aNumOfLine2)));
 
-      const Standard_Integer aNbPntsWL1 = aWLine1->NbPnts();
       const Standard_Integer aNbPntsWL2 = aWLine2->NbPnts();
 
       const IntSurf_PntOn2S& aPntFWL1 = aWLine1->Point(1);
@@ -150,7 +312,9 @@ static void JoinWLines(IntPatch_SequenceOfLine& theSlin,
 
       if(aPntFWL1.IsSame(aPntFWL2, Precision::Confusion()))
       {
-        if(!IsSeamOrBound(aPntFWL1, theU1Period, theU2Period,
+        const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
+        const IntSurf_PntOn2S& aPt2 = aWLine2->Point(2);
+        if(!IsSeamOrBound(aPt1, aPt2, aPntFWL1, theU1Period, theU2Period,
                           theV1Period, theV2Period, theUfSurf1, theUlSurf1,
                           theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
                           theVfSurf2, theVlSurf2))
@@ -174,7 +338,9 @@ static void JoinWLines(IntPatch_SequenceOfLine& theSlin,
 
       if(aPntFWL1.IsSame(aPntLWL2, Precision::Confusion()))
       {
-        if(!IsSeamOrBound(aPntFWL1, theU1Period, theU2Period,
+        const IntSurf_PntOn2S& aPt1 = aWLine1->Point(2);
+        const IntSurf_PntOn2S& aPt2 = aWLine2->Point(aNbPntsWL2-1);
+        if(!IsSeamOrBound(aPt1, aPt2, aPntFWL1, theU1Period, theU2Period,
                           theV1Period, theV2Period, theUfSurf1, theUlSurf1,
                           theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
                           theVfSurf2, theVlSurf2))
@@ -198,7 +364,9 @@ static void JoinWLines(IntPatch_SequenceOfLine& theSlin,
 
       if(aPntLWL1.IsSame(aPntFWL2, Precision::Confusion()))
       {
-        if(!IsSeamOrBound(aPntLWL1, theU1Period, theU2Period,
+        const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1-1);
+        const IntSurf_PntOn2S& aPt2 = aWLine2->Point(2);
+        if(!IsSeamOrBound(aPt1, aPt2, aPntLWL1, theU1Period, theU2Period,
                           theV1Period, theV2Period, theUfSurf1, theUlSurf1,
                           theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
                           theVfSurf2, theVlSurf2))
@@ -222,7 +390,9 @@ static void JoinWLines(IntPatch_SequenceOfLine& theSlin,
 
       if(aPntLWL1.IsSame(aPntLWL2, Precision::Confusion()))
       {
-        if(!IsSeamOrBound(aPntLWL1, theU1Period, theU2Period,
+        const IntSurf_PntOn2S& aPt1 = aWLine1->Point(aNbPntsWL1-1);
+        const IntSurf_PntOn2S& aPt2 = aWLine2->Point(aNbPntsWL2-1);
+        if(!IsSeamOrBound(aPt1, aPt2, aPntLWL1, theU1Period, theU2Period,
                           theV1Period, theV2Period, theUfSurf1, theUlSurf1,
                           theVfSurf1, theVlSurf1, theUfSurf2, theUlSurf2,
                           theVfSurf2, theVlSurf2))
index 77709c3..7759fda 100644 (file)
@@ -644,7 +644,7 @@ void IntTools_FaceFace::Perform(const TopoDS_Face& aF1,
   {
     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()) || 
@@ -1672,6 +1672,11 @@ Standard_Real IntTools_FaceFace::ComputeTolerance()
   case IntPatch_Walking:{
     Handle(IntPatch_WLine) WL = 
       Handle(IntPatch_WLine)::DownCast(L);
+
+#ifdef OCCT_DEBUG
+    //WL->Dump();
+#endif
+
     //
     Standard_Integer ifprm, ilprm;
     //
index b3b6fa6..f33a47d 100755 (executable)
@@ -1,5 +1,4 @@
 puts "TODO OCC25929 ALL: Error: Tolerance is too big!"
-puts "TODO OCC25929 ALL: Error : T=0.818182"
 puts "========="
 puts "CR24915"
 puts "========="
index cd6294e..1c667ef 100644 (file)
@@ -29,7 +29,7 @@ set log [bopcurves f1 f2 -2d]
 regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} ${log} full Toler NbCurv
 
 #This value must be equal to the analogical value in bug25292_11 and bug25292_12 of "bugs modalg_5" testgrid. 
-set MaxTol 1.e-7
+set MaxTol 1.5e-7
 
 #This value must be equal to the analogical value in bug25292_11, bug25292_12, bug25292_15 and bug25292_16 of "bugs modalg_5" testgrid. 
 set GoodNbCurv 4
index f9fdf52..dfc8dad 100644 (file)
@@ -29,7 +29,7 @@ set log [bopcurves f2 f1 -2d]
 regexp {Tolerance Reached=+([-0-9.+eE]+)\n+([-0-9.+eE]+)} ${log} full Toler NbCurv
 
 #This value must be equal to the analogical value in bug25292_11 and bug25292_12 of "bugs modalg_5" testgrid. 
-set MaxTol 1.e-7
+set MaxTol 1.5e-7
 
 #This value must be equal to the analogical value in bug25292_11, bug25292_12, bug25292_15 and bug25292_16 of "bugs modalg_5" testgrid. 
 set GoodNbCurv 4
diff --git a/tests/bugs/modalg_6/bug26310_1 b/tests/bugs/modalg_6/bug26310_1
new file mode 100644 (file)
index 0000000..394cfad
--- /dev/null
@@ -0,0 +1,44 @@
+puts "========"
+puts "OCC26310"
+puts "========"
+puts ""
+#################################################
+# Very slow boolean cut operations on cylinders
+#################################################
+
+if { [regexp {Debug mode} [dversion]] } {
+    set max_time 0.3
+} else {
+    set max_time 0.15
+}
+
+set maxToler 1.5e-5
+
+restore [locate_data_file OCC26310-b1.brep] b1 
+restore [locate_data_file OCC26310-b2.brep] b2 
+
+explode b1 f
+explode b2 f
+
+dchrono cr reset
+dchrono cr start
+set log1 [bopcurves b1_1 b2_1 -2d]
+dchrono cr stop
+
+regexp {Tolerance Reached=+([-0-9.+eE]+)} ${log1} full Toler
+
+puts "TolReached = $Toler"
+
+if { $Toler > $maxToler } {
+  puts "Error: Tolerance is too big ($Toler > $maxToler)"
+}
+
+set log2 [dchrono cr show]
+
+regexp {CPU user time: ([-0-9.+eE]+) seconds} $log2 full sec
+
+if { $sec > ${max_time} } {
+    puts "Error: CPU user time is more than ${max_time} seconds"
+} else {
+    puts "OK: CPU user time is less than ${max_time} seconds"
+}
diff --git a/tests/bugs/modalg_6/bug26310_2 b/tests/bugs/modalg_6/bug26310_2
new file mode 100644 (file)
index 0000000..8ade905
--- /dev/null
@@ -0,0 +1,26 @@
+puts "========"
+puts "OCC26310"
+puts "========"
+puts ""
+#################################################
+# Very slow boolean cut operations on cylinders
+#################################################
+
+restore [locate_data_file OCC26310-b1.brep] b1 
+restore [locate_data_file OCC26310-b2.brep] b2 
+
+bsection result b1 b2
+
+smallview
+donly result
+
+set log [checksection result]
+
+if { [string compare -nocase $log " nb alone Vertices : 0\n\n"] } {
+  puts "ERROR: the section is not closed"
+} else {
+  puts "The section is OK"
+}
+
+fit
+set only_screen_axo 1
diff --git a/tests/bugs/modalg_6/bug26310_3 b/tests/bugs/modalg_6/bug26310_3
new file mode 100644 (file)
index 0000000..3879f7c
--- /dev/null
@@ -0,0 +1,37 @@
+puts "========"
+puts "OCC26310"
+puts "========"
+puts ""
+#################################################
+# Very slow boolean cut operations on cylinders
+#################################################
+
+restore [locate_data_file OCC26310-b1.brep] b1 
+restore [locate_data_file OCC26310-b2.brep] b2 
+
+bop b1 b2
+
+bopcut res1
+boptuc res2
+
+checkshape res1
+checkshape res2
+
+set log1 [bopargcheck res1 #F]
+set log2 [bopargcheck res2 #F]
+
+if { [string compare -nocase $log1 "Shape(s) seem(s) to be valid for BOP.\n"] } {
+  puts "ERROR. res1 is not valid for BOP"
+}
+
+if { [string compare -nocase $log2 "Shape(s) seem(s) to be valid for BOP.\n"] } {
+  puts "ERROR. res2 is not valid for BOP"
+}
+
+smallview
+donly res1
+fit
+xwd ${imagedir}/${casename}_1.png
+donly res2
+fit
+xwd ${imagedir}/${casename}_2.png
diff --git a/tests/bugs/modalg_6/bug26310_4 b/tests/bugs/modalg_6/bug26310_4
new file mode 100644 (file)
index 0000000..57c6dfa
--- /dev/null
@@ -0,0 +1,50 @@
+puts "TODO OCC25929 ALL: ERROR in bopargcheck res1"
+puts "TODO OCC25929 ALL: ERROR. res1 with continuity C0"
+puts "TODO OCC25929 ALL: ERROR in bopargcheck res2"
+puts "TODO OCC25929 ALL: ERROR. res2 with continuity C0"
+
+puts "========"
+puts "OCC26310"
+puts "========"
+puts ""
+#################################################
+# Very slow boolean cut operations on cylinders
+#################################################
+
+restore [locate_data_file OCC26310-b1.brep] b1 
+restore [locate_data_file OCC26310-b2.brep] b2 
+
+bop b2 b1
+
+bopcut res1
+boptuc res2
+
+checkshape res1
+checkshape res2
+
+set log1 [bopargcheck res1 #F]
+set log2 [bopargcheck res2 #F]
+
+if { [string first "Faulties for FIRST  shape found : 2" $log1] >= 0 } {
+  puts "ERROR in bopargcheck res1"
+}
+
+if { [string first "Shapes with Continuity C0       : YES  Cases(2)  Total shapes(2)" $log1] >= 0 } {
+  puts "ERROR. res1 with continuity C0."
+}
+
+if { [string first "Faulties for FIRST  shape found : 2" $log2] >= 0 } {
+  puts "ERROR in bopargcheck res2"
+}
+
+if { [string first "Shapes with Continuity C0       : YES  Cases(2)  Total shapes(2)" $log2] >= 0 } {
+  puts "ERROR. res2 with continuity C0."
+}
+
+smallview
+donly res1
+fit
+xwd ${imagedir}/${casename}_1.png
+donly res2
+fit
+xwd ${imagedir}/${casename}_2.png