]> OCCT Git - occt.git/commitdiff
0026132: Invalid result of boolean operation
authornbv <nbv@opencascade.com>
Tue, 19 Jan 2016 11:05:25 +0000 (14:05 +0300)
committerabv <abv@opencascade.com>
Thu, 21 Jan 2016 12:50:29 +0000 (15:50 +0300)
1. The procedures for check of coincidence between Edge-Edge and Edge-Face have been added. These methods are used instead of searching interferences between corresponding sub-shapes. In most cases (including case for this issue), new methods are more reliable and faster than intersections. However, its use should be avoided in case when the edge is not coincide with edge/face of another argument evidently (e.g. if edge vertices are not in another edge/face).

2. Interface of both IntTools_EdgeFace and IntTools_EdgeEdge has been changed (adding/deleted some field and methods).

Some test cases have been corrected in accordance with their new behavior.
Test case for issue CR26132.

12 files changed:
src/ApproxInt/ApproxInt_KnotTools.cxx
src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx
src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx
src/IntTools/IntTools_EdgeEdge.cxx
src/IntTools/IntTools_EdgeEdge.hxx
src/IntTools/IntTools_EdgeEdge.lxx
src/IntTools/IntTools_EdgeFace.cxx
src/IntTools/IntTools_EdgeFace.hxx
src/IntTools/IntTools_FaceFace.cxx
tests/bugs/modalg_1/buc60462_1
tests/bugs/modalg_1/buc60462_2
tests/bugs/modalg_6/bug26132 [new file with mode: 0755]

index f155c8797777fadaaa8929a860c0b1fa1dd508fb..0fa204370440d7eb1c40298e3a2a85426b15fc7c 100644 (file)
@@ -201,7 +201,7 @@ void ApproxInt_KnotTools::ComputeKnotInds(const NCollection_LocalArray<Standard_
     theInds.Append(aCurv.Upper());
   }
 
-#if defined(APPROXINT_KNOTTOOLS_DEBUG) || defined(OCCT_DEBUG)
+#if defined(APPROXINT_KNOTTOOLS_DEBUG)
   {
     cout << "Feature indices new: " << endl;
     i;
@@ -597,7 +597,7 @@ void ApproxInt_KnotTools::BuildKnots(const TColgp_Array1OfPnt& thePntsXYZ,
   // II: Build draft knot sequence.
   ComputeKnotInds(aCoords, aDim, thePars, aKnots);
 
-#if defined(APPROXINT_KNOTTOOLS_DEBUG) || defined(OCCT_DEBUG)
+#if defined(APPROXINT_KNOTTOOLS_DEBUG)
     cout << "Draft knot sequence: " << endl;
     for(i = aKnots.Lower(); i <= aKnots.Upper();  ++i)
     {
@@ -608,7 +608,7 @@ void ApproxInt_KnotTools::BuildKnots(const TColgp_Array1OfPnt& thePntsXYZ,
   // III: Build output knot sequence.
   FilterKnots(aKnots, theMinNbPnts, theKnots);
 
-#if defined(APPROXINT_KNOTTOOLS_DEBUG) || defined(OCCT_DEBUG)
+#if defined(APPROXINT_KNOTTOOLS_DEBUG)
     cout << "Result knot sequence: " << endl;
     for(i = theKnots.Lower(); i <= theKnots.Upper();  ++i)
     {
index 12ea5ff92fb3e5c95ff580a4b1a70de5e85206d0..6f36c6fa935603941696ec379e1c02660de204bb 100644 (file)
@@ -281,8 +281,9 @@ void BOPAlgo_PaveFiller::PerformEE()
     return; 
   }
   //
-  Standard_Boolean bJustAdd;
+  Standard_Boolean bJustAdd, bExpressCompute;
   Standard_Integer i, iX, nE1, nE2, aNbCPrts, k, aNbFdgeEdge;
+  Standard_Integer nV11, nV12, nV21, nV22;
   Standard_Real aTS11, aTS12, aTS21, aTS22, aT11, aT12, aT21, aT22;
   TopAbs_ShapeEnum aType;
   BOPDS_ListIteratorOfListOfPaveBlock aIt1, aIt2;
@@ -330,6 +331,8 @@ void BOPAlgo_PaveFiller::PerformEE()
       }
       aPB1->ShrunkData(aTS11, aTS12, aBB1);
       //
+      aPB1->Indices(nV11, nV12);
+      //
       aIt2.Initialize(aLPB2);
       for (; aIt2.More(); aIt2.Next()) {
         Bnd_Box aBB2;
@@ -347,8 +350,15 @@ void BOPAlgo_PaveFiller::PerformEE()
         aPB1->Range(aT11, aT12);
         aPB2->Range(aT21, aT22);
         //
+        aPB2->Indices(nV21, nV22);
+        //
+        bExpressCompute=((nV11==nV21 && nV12==nV22) ||
+                         (nV12==nV21 && nV11==nV22));
+        //
         BOPAlgo_EdgeEdge& anEdgeEdge=aVEdgeEdge.Append1();
-        // 
+        //
+        anEdgeEdge.UseQuickCoincidenceCheck(bExpressCompute);
+        //
         anEdgeEdge.SetPaveBlock1(aPB1);
         anEdgeEdge.SetPaveBlock2(aPB2);
         //
index f142aa2b269159bcb1d6bc570f811e1483c4b4b7..f7643cbc45fbd2f048befc2d747d731823a2f186 100644 (file)
@@ -147,6 +147,8 @@ void BOPAlgo_PaveFiller::PerformEF()
   }
   //
   Standard_Boolean bJustAdd, bV[2];
+  Standard_Boolean bV1, bV2, bExpressCompute;
+  Standard_Integer nV1, nV2;
   Standard_Integer nE, nF, aDiscretize, i, aNbCPrts, iX, nV[2];
   Standard_Integer aNbEdgeFace, k;
   Standard_Real aTolE, aTolF, aTS1, aTS2, aT1, aT2, aDeflection;
@@ -186,6 +188,9 @@ void BOPAlgo_PaveFiller::PerformEF()
     BOPDS_FaceInfo& aFI=myDS->ChangeFaceInfo(nF);
     const BOPDS_IndexedMapOfPaveBlock& aMPBF=aFI.PaveBlocksOn();
     //
+    const BOPCol_MapOfInteger& aMVIn=aFI.VerticesIn();
+    const BOPCol_MapOfInteger& aMVOn=aFI.VerticesOn();
+    //
     aTolE=BRep_Tool::Tolerance(aE);
     aTolF=BRep_Tool::Tolerance(aF);
     //
@@ -210,6 +215,11 @@ void BOPAlgo_PaveFiller::PerformEF()
         continue;
       }
       //
+      aPBR->Indices(nV1, nV2);
+      bV1=aMVIn.Contains(nV1) || aMVOn.Contains(nV1);
+      bV2=aMVIn.Contains(nV2) || aMVOn.Contains(nV2);
+      bExpressCompute=bV1 && bV2;
+      //
       BOPAlgo_EdgeFace& aEdgeFace=aVEdgeFace.Append1();
       //
       aEdgeFace.SetIndices(nE, nF);
@@ -221,6 +231,7 @@ void BOPAlgo_PaveFiller::PerformEF()
       aEdgeFace.SetTolF (aTolF);
       aEdgeFace.SetDiscretize (aDiscretize);
       aEdgeFace.SetDeflection (aDeflection);
+      aEdgeFace.UseQuickCoincidenceCheck(bExpressCompute);
       //
       IntTools_Range aSR(aTS1, aTS2);
       IntTools_Range anewSR=aSR;
index b27f96ce3f97c6759b4b2dce424fd2a28124d2cc..6d212df5d43f83af6ae4ba1baf4989dd4d201e91 100644 (file)
@@ -211,6 +211,17 @@ void IntTools_EdgeEdge::Perform()
     return;
   }
   //
+  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;
   //
   //3.2. Find ranges containig solutions
@@ -221,6 +232,47 @@ void IntTools_EdgeEdge::Perform()
   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  : 
index bc8c852f64933aa8cc4d863d0df8e7dc19139a0b..a9a432a954efeb2baccc61c27f6f2cd1e54ff834 100644 (file)
@@ -106,7 +106,15 @@ public:
   const IntTools_SequenceOfCommonPrts& CommonParts() const;
 
 
+  //! Sets the flag myQuickCoincidenceCheck
+  void UseQuickCoincidenceCheck (const Standard_Boolean bFlag) {
+    myQuickCoincidenceCheck=bFlag;
+  }
 
+  //! Returns the flag myQuickCoincidenceCheck
+  Standard_Boolean IsCoincidenceCheckedQuickly () {
+    return myQuickCoincidenceCheck;
+  }
 
 protected:
 
@@ -170,6 +178,8 @@ protected:
   Standard_EXPORT Standard_Boolean IsIntersection (const Standard_Real aT11,
     const Standard_Real aT12, const Standard_Real aT21, const Standard_Real aT22);
 
+  //! Checks if the edges are coincident really.
+  Standard_EXPORT Standard_Boolean IsCoincident();
 
   TopoDS_Edge myEdge1;
   TopoDS_Edge myEdge2;
@@ -192,6 +202,14 @@ protected:
   Standard_Integer myErrorStatus;
   IntTools_SequenceOfCommonPrts myCommonParts;
 
+  //! Allows avoiding use Edge-Edge intersection
+  //! algorithm (i.e. speeding up the Boolean algorithm)
+  //! if the edges are coincided really.
+  //! If it is not evidently set of this flag should
+  //! be avoided (otherwise, the performance of
+  //! Boolean algorithm will be slower).
+  Standard_Boolean myQuickCoincidenceCheck;
+
 private:
 
 };
index 2508d533bd46d72db21c2d96252438a479f96abc..398afc7756bd4f7c14fc6c1653ef7c992e54ff53 100644 (file)
@@ -33,7 +33,8 @@ inline IntTools_EdgeEdge::IntTools_EdgeEdge()
   myRange1(0., 0.),
   myRange2(0., 0.),
   mySwap(Standard_False),
-  myErrorStatus(0)
+  myErrorStatus(0),
+  myQuickCoincidenceCheck(Standard_False)
 {
 }
 //=======================================================================
@@ -57,7 +58,8 @@ inline IntTools_EdgeEdge::IntTools_EdgeEdge(const TopoDS_Edge&  theEdge1,
   myRange1(0., 0.),
   myRange2(0., 0.),
   mySwap(Standard_False),
-  myErrorStatus(0)
+  myErrorStatus(0),
+  myQuickCoincidenceCheck(Standard_False)
 {
 }
 //=======================================================================
@@ -85,7 +87,8 @@ inline IntTools_EdgeEdge::IntTools_EdgeEdge(const TopoDS_Edge&  theEdge1,
   myRange1(aT11, aT12),
   myRange2(aT21, aT22),
   mySwap(Standard_False),
-  myErrorStatus(0)
+  myErrorStatus(0),
+  myQuickCoincidenceCheck(Standard_False)
 {
 }
 //=======================================================================
index 90a397c5f79a7b2a7599bce67a963f6bc359b52c..3d6749d801d583480f916454b45e93b66e0d9700 100644 (file)
@@ -76,12 +76,10 @@ static
   myTolF=1.e-7;
   myDiscret=30;
   myEpsT   =1e-12;
-  myEpsNull=1e-12;
   myDeflection=0.01;
   myIsDone=Standard_False;
   myErrorStatus=1;
-  myParallel=Standard_False;
-  myPar1=0.;
+  myQuickCoincidenceCheck=Standard_False;
 }
 //=======================================================================
 //function : SetContext
@@ -188,15 +186,6 @@ void IntTools_EdgeFace::SetEpsilonT(const Standard_Real anEpsT)
 {
   myEpsT=anEpsT;
 } 
-//=======================================================================
-//function : SetEpsilonNull
-//purpose  : 
-//=======================================================================
-void IntTools_EdgeFace::SetEpsilonNull(const Standard_Real anEpsNull) 
-{
-  myEpsNull=anEpsNull;
-} 
-
 //=======================================================================
 //function : SetRange
 //purpose  : 
@@ -214,8 +203,7 @@ void IntTools_EdgeFace::SetRange(const Standard_Real aFirst,
 //=======================================================================
 void IntTools_EdgeFace::SetRange(const IntTools_Range& aRange) 
 {
-  myRange.SetFirst (aRange.First());
-  myRange.SetLast  (aRange.Last());
+  SetRange(aRange.First(), aRange.Last());
 } 
 //=======================================================================
 //function : IsDone
@@ -249,7 +237,84 @@ const IntTools_Range&  IntTools_EdgeFace::Range() const
 {
   return myRange;
 } 
+//=======================================================================
+//function :  IsCoincident
+//purpose  : 
+//=======================================================================
+Standard_Boolean IntTools_EdgeFace::IsCoincident() 
+{
+  Standard_Integer i, iCnt;
+  Standard_Real dT, aT, aD, aT1, aT2, aU, aV;
+
+  gp_Pnt aP;
+  TopAbs_State aState;
+  gp_Pnt2d aP2d;
+  //
+  GeomAPI_ProjectPointOnSurf& aProjector=myContext->ProjPS(myFace);
+
+  const Standard_Integer aNbSeg=23;
+  const Standard_Real aTresh=0.5;
+  const Standard_Integer aTreshIdxF = RealToInt((aNbSeg+1)*0.25),
+                         aTreshIdxL = RealToInt((aNbSeg+1)*0.75);
+  const Handle(Geom_Surface) aSurf = BRep_Tool::Surface(myFace);
+
+  aT1=myRange.First();
+  aT2=myRange.Last();
+  dT=(aT2-aT1)/aNbSeg;
+  //
+  Standard_Boolean isClassified = Standard_False;
+  iCnt=0;
+  for(i=0; i <= aNbSeg; ++i) {
+    aT = aT1+i*dT;
+    aP=myC.Value(aT);
+    //
+    aProjector.Perform(aP);
+    if (!aProjector.IsDone()) {
+      continue;
+    }
+    //
+    
+    aD=aProjector.LowerDistance();
+    if (aD>myCriteria) {
+      continue;
+    }
+    //
+
+    ++iCnt; 
+
+    //We classify only three points: in the begin, in the 
+    //end and in the middle of the edge.
+    //However, exact middle point (when i == (aNbSeg + 1)/2)
+    //can be unprojectable. Therefore, it will not be able to
+    //be classified. Therefore, points with indexes in 
+    //[aTreshIdxF, aTreshIdxL] range are made available 
+    //for classification.
+    //isClassified == TRUE if MIDDLE point has been choosen and
+    //classified correctly.
+
+    if(((0 < i) && (i < aTreshIdxF)) || ((aTreshIdxL < i ) && (i < aNbSeg)))
+      continue;
+
+    if(isClassified && (i != aNbSeg))
+      continue;
+
+    aProjector.LowerDistanceParameters(aU, aV);
+    aP2d.SetX(aU);
+    aP2d.SetY(aV);
+
+    IntTools_FClass2d& aClass2d=myContext->FClass2d(myFace);
+    aState = aClass2d.Perform(aP2d);
+    
+    if(aState == TopAbs_OUT)
+      return Standard_False;
 
+    if(i != 0)
+      isClassified = Standard_True;
+  }
+  //
+  const Standard_Real aCoeff=(Standard_Real)iCnt/((Standard_Real)aNbSeg+1);
+  return (aCoeff > aTresh);
+}
 //=======================================================================
 //function : CheckData
 //purpose  : 
@@ -270,6 +335,7 @@ void IntTools_EdgeFace::CheckData()
 void IntTools_EdgeFace::Prepare() 
 {
   Standard_Integer pri;
+  Standard_Real aTmin, aTmax;
   IntTools_CArray1OfReal aPars;
  
   //
@@ -280,15 +346,15 @@ void IntTools_EdgeFace::Prepare()
   //
   // 2.Prepare myCriteria
   if (aCurveType==GeomAbs_BSplineCurve||
- aCurveType==GeomAbs_BezierCurve) {
   aCurveType==GeomAbs_BezierCurve) {
     myCriteria=1.5*myTolE+myTolF;
   }
   else {
     myCriteria = myTolE + myTolF + Precision::Confusion();
   }
   // 2.a myTmin, myTmax
-  myTmin=myRange.First();
-  myTmax=myRange.Last();
+  aTmin=myRange.First();
+  aTmax=myRange.Last();
   // 2.b myFClass2d
   myS.Initialize (myFace,Standard_True);
   myFClass2d.Init(myFace, 1.e-6);
@@ -298,7 +364,7 @@ void IntTools_EdgeFace::Prepare()
   //
   //
   // 3.Prepare myPars 
-  pri = IntTools::PrepareArgs(myC, myTmax, myTmin, 
+  pri = IntTools::PrepareArgs(myC, aTmax, aTmin, 
                               myDiscret, myDeflection, aPars);
   if (pri) {
     myErrorStatus=6;
@@ -543,300 +609,6 @@ Standard_Boolean IntTools_EdgeFace::IsEqDistance
   return !bRetFlag; 
 }
 //
-//=======================================================================
-//function : PrepareArgsFuncArrays
-//purpose  : Obtain 
-//           myFuncArray and myArgsArray for the interval [ta, tb]
-//=======================================================================  
-void IntTools_EdgeFace::PrepareArgsFuncArrays(const Standard_Real ta,
-                                              const Standard_Real tb)
-{
-  IntTools_CArray1OfReal anArgs, aFunc;
-  Standard_Integer i, aNb, pri;
-  Standard_Real t, f, f1;
-  //
-  // Prepare values of arguments for the interval [ta, tb]
-  pri=IntTools::PrepareArgs (myC, tb, ta, myDiscret, myDeflection, anArgs);
-  
-  if (pri) {
-    myErrorStatus=8;
-    return;
-  }
-  //...
-  aNb=anArgs.Length();
-
-  if (!aNb){
-    myErrorStatus=9;
-    return;
-  }
-  //
-  // Prepare values of functions for the interval [ta, tb]
-  aFunc.Resize(aNb);
-  for (i=0; i<aNb; i++) {
-    t=anArgs(i);
-    f1=DistanceFunction(t);
-    f=f1+myCriteria; 
-
-    if (myErrorStatus==11)
-      return;
-    
-    if (f1 < myEpsNull) { 
-      f=0.;
-    }
-    aFunc(i)=f;
-  }
-  //
-  // Add points where the derivative = 0  
-  AddDerivativePoints(anArgs, aFunc);
-
-}
-
-//=======================================================================
-
-namespace {
-  // Auxiliary: comparator function for sorting ranges
-  bool IntTools_RangeComparator (const IntTools_Range& theLeft, const IntTools_Range& theRight)
-  {
-    return theLeft.First() < theRight.First();
-  }
-}
-
-//=======================================================================
-//function : AddDerivativePoints
-//purpose  : 
-//=======================================================================
-void IntTools_EdgeFace::AddDerivativePoints
-  (const IntTools_CArray1OfReal& t,
-   const IntTools_CArray1OfReal& f)  
-{
-  Standard_Integer i, j, n, k, nn=100;
-  Standard_Real fr, tr, tr1, dEpsNull=10.*myEpsNull;
-  IntTools_CArray1OfReal fd;
-  TColStd_SequenceOfReal aTSeq, aFSeq;  
-
-  n=t.Length();
-  fd.Resize(n+1);
-  //
-  // Table of derivatives
-  Standard_Real dfx, tx, tx1, fx, fx1, dt=1.e-6;
-  // Left limit
-  tx=t(0);
-  tx1=tx+dt;
-  fx=f(0);
-  fx1=DistanceFunction(tx1);
-  fx1=fx1+myCriteria;
-  if (fx1 < myEpsNull) { 
-    fx1=0.;
-  }
-  dfx=(fx1-fx)/dt;
-  fd(0)=dfx;
-  
-  if (fabs(fd(0)) < dEpsNull){
-    fd(0)=0.;
-  }
-  
-
-  k=n-1;
-  for (i=1; i<k; i++) {
-    fd(i)=.5*(f(i+1)-f(i-1))/(t(i)-t(i-1));
-    if (fabs(fd(i)) < dEpsNull){
-      fd(i)=0.;
-    }
-  }
-  // Right limit
-  tx=t(n-1);
-  tx1=tx-dt;
-  fx=f(n-1);
-  fx1=DistanceFunction(tx1);
-  fx1=fx1+myCriteria;
-  if (fx1 < myEpsNull) { 
-    fx1=0.;
-  }
-  dfx=(fx-fx1)/dt;
-  fd(n-1)=dfx;
-  
-  if (fabs(fd(n-1)) < dEpsNull){
-    fd(n-1)=0.;
-  }
-  //
-  // Finding the range where the derivatives have different signs
-  // for neighbouring points
-  for (i=1; i<n; i++) {
-    Standard_Real fd1, fd2, t1, t2;
-    t1 =t(i-1);
-    t2 =t(i);
-    fd1=fd(i-1);
-    fd2=fd(i);
-
-    if (fd1*fd2 < 0.) {
-      if (fabs(fd1) < myEpsNull) {
- tr=t1;
- fr=DistanceFunction(tr);//fd1;
-      }
-      else if (fabs(fd2) < myEpsNull) {
- tr=t2;
- fr=DistanceFunction(tr);
-      }
-      else {
- tr=FindSimpleRoot(2, t1, t2, fd1);
- fr=DistanceFunction(tr);
-      }
-      
-      aTSeq.Append(tr);
-      aFSeq.Append(fr);
-    }
-  } // end of for (i=1; i<n; i++)
-  //
-  // remove identical t, f
-  nn=aTSeq.Length();
-  if (nn) {
-    for (i=1; i<=aTSeq.Length(); i++) {
-      tr=aTSeq(i);
-      for (j=0; j<n; j++) {
- tr1=t(j);
- if (fabs (tr1-tr) < myEpsT) {
-   aTSeq.Remove(i);
-   aFSeq.Remove(i);
- }
-      }
-    }
-    nn=aTSeq.Length();
-  }
-  //
-  // sorting args and funcs in increasing order
-  if (nn) {
-    k=nn+n;
-    IntTools_Array1OfRange anArray1OfRange(1, k);
-    for (i=1; i<=n; i++) {
-      anArray1OfRange(i).SetFirst(t(i-1));
-      anArray1OfRange(i).SetLast (f(i-1));
-    }
-    for (i=1; i<=nn; i++) {
-      anArray1OfRange(n+i).SetFirst(aTSeq(i));
-      anArray1OfRange(n+i).SetLast (aFSeq(i));
-    }
-    
-    std::sort (anArray1OfRange.begin(), anArray1OfRange.end(), IntTools_RangeComparator);
-    
-    // filling the  output arrays
-    myArgsArray.Resize(k);
-    myFuncArray.Resize(k);
-    for (i=1; i<=k; i++) {
-      myArgsArray(i-1)=anArray1OfRange(i).First();
-      myFuncArray(i-1)=anArray1OfRange(i).Last ();
-    }
-  }
-  
-  else { // nn=0
-    myArgsArray.Resize(n);
-    myFuncArray.Resize(n);
-    for (i=0; i<n; i++) {
-      myArgsArray(i)=t(i); 
-      myFuncArray(i)=f(i); 
-    }
-  }
-}
-
-//=======================================================================
-//function : DerivativeFunction
-//purpose  : 
-//=======================================================================
-Standard_Real IntTools_EdgeFace::DerivativeFunction
-  (const Standard_Real t2)
-{
-  Standard_Real t1, t3, aD1, aD2, aD3;
-  Standard_Real dt=1.e-9;
-  t1=t2-dt;
-  aD1=DistanceFunction(t1);
-  t3=t2+dt;
-  aD3=DistanceFunction(t3);
-  
-  aD2=.5*(aD3-aD1)/dt;
-  return aD2; 
-}
-
-//=======================================================================
-//function : FindSimpleRoot
-//purpose  : [private]
-//=======================================================================
-Standard_Real IntTools_EdgeFace::FindSimpleRoot 
-  (const Standard_Integer IP,
-   const Standard_Real tA,
-   const Standard_Real tB,
-   const Standard_Real fA)
-{
-  Standard_Real r, a, b, y, x0, s;
-  
-  a=tA; b=tB; r=fA;
-  
-  for(;;) {
-    x0=.5*(a+b);
-
-    if (IP==1)
-      y=DistanceFunction(x0);
-    else 
-      y=DerivativeFunction(x0);
-    
-    if (fabs(b-a) < myEpsT || y==0.) {
-      return x0;
-    }
-    
-        
-    s=y*r;
-
-    if (s<0.) {
-      b=x0;
-      continue;
-    }
-
-    if (s>0.) {
-      a=x0; r=y;
-    }
-  }
-}
-//=======================================================================
-//function : FindGoldRoot
-//purpose  : [private]
-//=======================================================================
-Standard_Real IntTools_EdgeFace::FindGoldRoot
-  (const Standard_Real tA,
-   const Standard_Real tB,
-   const Standard_Real coeff)
-{
-  Standard_Real gs=0.61803399;
-  Standard_Real a, b, xp, xl, yp, yl;
-
-  a=tA;  b=tB;
-  
-  xp=a+(b-a)*gs;
-  xl=b-(b-a)*gs;
-  yp=coeff*DistanceFunction(xp);
-  yl=coeff*DistanceFunction(xl);
-  
-  for(;;) {
-    
-    if (fabs(b-a) < myEpsT) {
-      return .5*(b+a);
-    }
-    
-    if (yp < yl) {
-      a=xl;
-      xl=xp;
-      xp=a+(b-a)*gs;
-      yp=coeff*DistanceFunction(xp);
-    }
-    
-    else {
-      b=xp;
-      xp=xl;
-      yp=yl;
-      xl=b-(b-a)*gs;
-      yl=coeff*DistanceFunction(xl);
-    }
-  }
-}  
-
 //=======================================================================
 //function : MakeType
 //purpose  : 
@@ -893,183 +665,6 @@ Standard_Integer IntTools_EdgeFace::MakeType
 }
 
 
-//=======================================================================
-//function : IsIntersection
-//purpose  : 
-//=======================================================================
-void IntTools_EdgeFace::IsIntersection (const Standard_Real ta, 
-                                        const Standard_Real tb) 
-{
-  IntTools_CArray1OfReal anArgs, aFunc;
-  Standard_Integer i, aNb, aCnt=0;
-  //
-  Standard_Integer aCntIncreasing=1, aCntDecreasing=1;
-  Standard_Real t, f, f1;
-  //
-  // Prepare values of arguments for the interval [ta, tb]
-  IntTools::PrepareArgs (myC, tb, ta, myDiscret, myDeflection, anArgs);
-  aNb=anArgs.Length();
-  
-  aFunc.Resize(aNb);
-  for (i=0; i<aNb; i++) {
-    t=anArgs(i);
-    
-    f1=DistanceFunction(t);
-    f=f1+myCriteria; 
-
-    if (fabs(f1) < myEpsNull) { 
-      aCnt++;
-      f=0.;
-    }
-    aFunc(i)=f;
-    //
-    if (i) {
-      if (aFunc(i)>aFunc(i-1)) {
- aCntIncreasing++;
-      }
-      if (aFunc(i)<aFunc(i-1)) {
- aCntDecreasing++;
-      }
-    }
-    //
-  }
-
-  if (aCnt==aNb) {
-    myParallel=Standard_True;
-    return;
-  }
-  
-  FindDerivativeRoot(anArgs, aFunc);
-
-  //
-  if (myParallel) {
-    if (!(myC.GetType()==GeomAbs_Line 
-   && 
-   myS.GetType()==GeomAbs_Cylinder)) {
-      if (aCntDecreasing==aNb) {
- myPar1=anArgs(aNb-1);
- myParallel=Standard_False;
-      }
-      if (aCntIncreasing==aNb) {
- myPar1=anArgs(0);
- myParallel=Standard_False;
-      }
-    }
-  }
-  //
-  return ;
-}
-
-//=======================================================================
-//function : FindDerivativeRoot
-//purpose  : 
-//=======================================================================
-void IntTools_EdgeFace::FindDerivativeRoot
-  (const IntTools_CArray1OfReal& t,
-   const IntTools_CArray1OfReal& f)  
-{
-  Standard_Integer i, n, k;
-  Standard_Real tr;
-  IntTools_CArray1OfReal fd;
-  TColStd_SequenceOfReal aTSeq, aFSeq;  
-  
-  myPar1=0.;
-  myParallel=Standard_True;
-  
-  n=t.Length();
-  fd.Resize(n+1);
-  //
-  // Table of derivatives
-  fd(0)=(f(1)-f(0))/(t(1)-t(0));
-  if (fabs(fd(0)) < myEpsNull) {
-    fd(0)=0.;
-  }
-
-  k=n-1;
-  for (i=1; i<k; i++) {
-    fd(i)=.5*(f(i+1)-f(i-1))/(t(i)-t(i-1));
-    if (fabs(fd(i)) < myEpsNull) {
-      fd(i)=0.;
-    }
-  }
-
-  fd(n-1)=(f(n-1)-f(n-2))/(t(n-1)-t(n-2));
-  if (fabs(fd(n-1)) < myEpsNull) {
-    fd(n-1)=0.;
-  }
-  //
-  // Finding the range where the derivatives have different signs
-  // for neighbouring points
-  for (i=1; i<n; i++) {
-    Standard_Real fd1, fd2, t1, t2, fabsfd1, fabsfd2;
-    Standard_Boolean bF1, bF2;
-    t1 =t(i-1);
-    t2 =t(i);
-    fd1=fd(i-1);
-    fd2=fd(i);
-
-    fabsfd1=fabs(fd1);
-    bF1=fabsfd1 < myEpsNull;
-    
-    fabsfd2=fabs(fd2);
-    bF2=fabsfd2 < myEpsNull;
-    //
-    if (fd1*fd2 < 0.) {
-      tr=FindSimpleRoot(2, t1, t2, fd1);
-      DistanceFunction(tr);
-      myPar1=tr;
-      myParallel=Standard_False;
-      break;
-    }
-    
-    if (!bF1 && bF2) {
-      tr=t2;
-      myPar1=tr;
-      myParallel=Standard_False;
-      break;
-    }
-    
-    if (bF1 && !bF2) {
-      tr=t1;
-      myPar1=tr;
-      myParallel=Standard_False;
-      break;
-    }
-
-  }
-}
-//=======================================================================
-//function : RemoveIdenticalRoots 
-//purpose  : 
-//=======================================================================
-void IntTools_EdgeFace::RemoveIdenticalRoots()
-{
-  Standard_Integer aNbRoots, j, k;
-
-  aNbRoots=mySequenceOfRoots.Length();
-  for (j=1; j<=aNbRoots; j++) { 
-    const IntTools_Root& aRj=mySequenceOfRoots(j);
-    for (k=j+1; k<=aNbRoots; k++) {
-      const IntTools_Root& aRk=mySequenceOfRoots(k);
-      
-      Standard_Real aTj, aTk, aDistance;
-      gp_Pnt aPj, aPk;
-
-      aTj=aRj.Root();
-      aTk=aRk.Root();
-
-      myC.D0(aTj, aPj);
-      myC.D0(aTk, aPk);
-
-      aDistance=aPj.Distance(aPk);
-      if (aDistance < myCriteria) {
- mySequenceOfRoots.Remove(k);
- aNbRoots=mySequenceOfRoots.Length();
-      }
-    }
-  }
-}
-
 //=======================================================================
 //function : CheckTouch 
 //purpose  : 
@@ -1197,6 +792,7 @@ Standard_Boolean IntTools_EdgeFace::CheckTouch
 
   return theflag;
 }
+
 //=======================================================================
 //function : Perform
 //purpose  : 
@@ -1239,15 +835,23 @@ void IntTools_EdgeFace::Perform()
     myCriteria = myTolE + myTolF + Precision::Confusion();
   }
   
-  myTmin=myRange.First();
-  myTmax=myRange.Last();
-  
   myS.Initialize (myFace,Standard_True);
   
   if(myContext.IsNull()) {
     myFClass2d.Init(myFace, 1.e-6);
   }
-  
+  //
+  if (myQuickCoincidenceCheck) {
+    if (IsCoincident()) {
+      aCommonPrt.SetType(TopAbs_EDGE);
+      aCommonPrt.SetRange1(myRange.First(), myRange.Last());
+      MakeType (aCommonPrt); 
+      mySeqOfCommonPrts.Append(aCommonPrt);
+      myIsDone=Standard_True;
+      return;
+    }
+  }
+  //
   IntTools_BeanFaceIntersector anIntersector(myC, myS, myTolE, myTolF);
   anIntersector.SetBeanParameters(myRange.First(), myRange.Last());
   //
@@ -1544,7 +1148,6 @@ Standard_Integer AdaptiveDiscret (const Standard_Integer iDiscret,
   return iDiscretNew;
 }
 
-
 #ifdef _MSC_VER
 #pragma warning ( default : 4101 )
 #endif
index 360c1805d399aab483835bdcfb2d10417f1b8d7f..08458ffa61448a05b5b5d37e78a83181ec9a2eeb 100644 (file)
@@ -30,7 +30,6 @@
 #include <IntTools_SequenceOfRanges.hxx>
 #include <IntTools_FClass2d.hxx>
 #include <IntTools_CArray1OfReal.hxx>
-#include <IntTools_SequenceOfRoots.hxx>
 #include <IntTools_SequenceOfCommonPrts.hxx>
 #include <IntTools_Range.hxx>
 class IntTools_Context;
@@ -101,11 +100,6 @@ public:
   //! Initializes algorithm by parameter tolerance
   Standard_EXPORT void SetEpsilonT (const Standard_Real anEpsT);
   
-
-  //! Initializes algorithm by distance tolerance
-  Standard_EXPORT void SetEpsilonNull (const Standard_Real anEpsNull);
-  
-
   //! Sets boundaries for edge.
   //! The algorithm processes edge inside these boundaries.
   Standard_EXPORT void SetRange (const IntTools_Range& aRange);
@@ -149,15 +143,20 @@ public:
 
   //! Returns boundaries for edge
   Standard_EXPORT const IntTools_Range& Range() const;
-  
-  Standard_EXPORT static Standard_Boolean IsEqDistance (const gp_Pnt& aP, const BRepAdaptor_Surface& aS, const Standard_Real aT, Standard_Real& aD);
 
+  //! Sets the flag myQuickCoincidenceCheck
+  void UseQuickCoincidenceCheck(const Standard_Boolean bFlag) {
+    myQuickCoincidenceCheck=bFlag;
+  }
 
+  //! Returns the flag myQuickCoincidenceCheck
+  Standard_Boolean IsCoincidenceCheckedQuickly () {
+    return myQuickCoincidenceCheck;
+  }
 
 
 protected:
-
-  
+  Standard_EXPORT static Standard_Boolean IsEqDistance (const gp_Pnt& aP, const BRepAdaptor_Surface& aS, const Standard_Real aT, Standard_Real& aD);
   Standard_EXPORT void CheckData();
   
   Standard_EXPORT void Prepare();
@@ -168,28 +167,14 @@ protected:
   
   Standard_EXPORT Standard_Real DistanceFunction (const Standard_Real t);
   
-  Standard_EXPORT Standard_Real DerivativeFunction (const Standard_Real t);
-  
-  Standard_EXPORT void PrepareArgsFuncArrays (const Standard_Real t1, const Standard_Real t2);
-  
-  Standard_EXPORT void AddDerivativePoints (const IntTools_CArray1OfReal& t, const IntTools_CArray1OfReal& f);
-  
-  Standard_EXPORT Standard_Real FindSimpleRoot (const Standard_Integer IP, const Standard_Real ta, const Standard_Real tb, const Standard_Real fA);
-  
-  Standard_EXPORT Standard_Real FindGoldRoot (const Standard_Real ta, const Standard_Real tb, const Standard_Real coeff);
-  
   Standard_EXPORT Standard_Integer MakeType (IntTools_CommonPrt& aCP);
-  
-  Standard_EXPORT void IsIntersection (const Standard_Real ta, const Standard_Real tb);
-  
-  Standard_EXPORT void FindDerivativeRoot (const IntTools_CArray1OfReal& t, const IntTools_CArray1OfReal& f);
-  
-  Standard_EXPORT void RemoveIdenticalRoots();
-  
+   
   Standard_EXPORT Standard_Boolean CheckTouch (const IntTools_CommonPrt& aCP, Standard_Real& aTX);
   
   Standard_EXPORT Standard_Boolean CheckTouchVertex (const IntTools_CommonPrt& aCP, Standard_Real& aTX);
 
+  //! Checks if the edge is in the face really.
+  Standard_EXPORT Standard_Boolean IsCoincident();
 
 
 
@@ -203,11 +188,8 @@ private:
   Standard_Real myTolF;
   Standard_Integer myDiscret;
   Standard_Real myEpsT;
-  Standard_Real myEpsNull;
   Standard_Real myDeflection;
   BRepAdaptor_Curve myC;
-  Standard_Real myTmin;
-  Standard_Real myTmax;
   BRepAdaptor_Surface myS;
   Standard_Real myCriteria;
   Standard_Boolean myIsDone;
@@ -215,15 +197,16 @@ private:
   Handle(IntTools_Context) myContext;
   IntTools_SequenceOfRanges myProjectableRanges;
   IntTools_FClass2d myFClass2d;
-  IntTools_CArray1OfReal myFuncArray;
-  IntTools_CArray1OfReal myArgsArray;
-  IntTools_SequenceOfRoots mySequenceOfRoots;
   IntTools_SequenceOfCommonPrts mySeqOfCommonPrts;
-  Standard_Real myPar1;
-  Standard_Boolean myParallel;
   IntTools_Range myRange;
 
-
+  //! Allows avoiding use Edge-Face intersection
+  //! algorithm (i.e. speeding up the Boolean algorithm)
+  //! if the edges are coincided really.
+  //! If it is not evidently set of this flag should
+  //! be avoided (otherwise, the performance of
+  //! Boolean algorithm will be slower).
+  Standard_Boolean myQuickCoincidenceCheck;
 };
 
 
index bbd68793f0048e2477530f4e235146d1c6d928ca..e6ead52fca666eea17167b749b352f7573f99cd3 100644 (file)
@@ -888,10 +888,27 @@ void IntTools_FaceFace::MakeCurve(const Standard_Integer Index,
     }
     L = aWLine;
 
-    //
-    //if(!myListOfPnts.IsEmpty()) {
-    //  bAvoidLineConstructor = Standard_True;
-    //}
+#ifdef INTTOOLS_FACEFACE_DEBUG
+    if(!myListOfPnts.IsEmpty()) {
+      char aBuff[10000];
+      const IntSurf_PntOn2S& aPt = myListOfPnts.First();
+      Standard_Real u1, v1, u2, v2;
+      aPt.Parameters(u1, v1, u2, v2);
+
+      Sprintf(aBuff,"bopcurves <face1 face2> -2d");
+      IntSurf_ListIteratorOfListOfPntOn2S IterLOP1(myListOfPnts);
+      for(;IterLOP1.More(); IterLOP1.Next())
+      {
+        const IntSurf_PntOn2S& aPt = IterLOP1.Value();
+        Standard_Real u1, v1, u2, v2;
+        aPt.Parameters(u1, v1, u2, v2);
+
+        Sprintf(aBuff, "%s -p %+10.20f %+10.20f %+10.20f %+10.20f", aBuff, u1, v1, u2, v2);
+      }
+
+      cout << aBuff << endl;
+    }
+#endif
 
     Standard_Integer nbp = aWLine->NbPnts();
     const IntSurf_PntOn2S& p1 = aWLine->Point(1);
index 039cd8e7a2539226647cd84c52eeec6709d22e74..1938c3f76a04299f0c9ff32fca78fbf2068e2202 100755 (executable)
@@ -1,4 +1,4 @@
-#puts "TODO OCC12345 ALL: Error : The length of result shape is"
+#puts "TODO OCC27024 ALL: Error : The length of result shape is"
 
 puts "============="
 puts "BUC60462"
index badc77adc4f8764c070a3a03e7b1d9455eb6929f..3465d6599ef13a6d2038d85ddf53e38e03e3649f 100755 (executable)
@@ -1,5 +1,6 @@
-puts "TODO ?OCC26717 ALL: Faulty shapes in variables faulty_1 to faulty_"
-puts "TODO OCC26717 ALL: Error : operation bfuse is WRONG because number of SOLID"
+#puts "TODO OCC27024 ALL: Faulty shapes in variables faulty_1 to faulty_"
+puts "TODO OCC27024 ALL: Tcl Exception: result is not a topological shape!!!"
+puts "TODO OCC27024 All:TEST INCOMPLETE"
 
 puts "=========="
 puts "BUC60462"
diff --git a/tests/bugs/modalg_6/bug26132 b/tests/bugs/modalg_6/bug26132
new file mode 100755 (executable)
index 0000000..5793dc0
--- /dev/null
@@ -0,0 +1,31 @@
+puts "============"
+puts "OCC26132"
+puts "============"
+puts ""
+######################################################
+# Invalid result of boolean operation
+######################################################
+
+restore [locate_data_file bug26132_shape.brep] c
+
+explode c
+
+bcommon result c_1 c_2
+
+set square 947.358
+
+set nbshapes_expected "
+Number of shapes in shape
+ VERTEX    : 6
+ EDGE      : 11
+ WIRE      : 8
+ FACE      : 8
+ SHELL     : 2
+ SOLID     : 2
+ COMPSOLID : 0
+ COMPOUND  : 1
+ SHAPE     : 38
+"
+checknbshapes result -ref ${nbshapes_expected} -t -m "Boolean operations common"
+
+set 3dviewer 1