0024879: Wrong result of General Fuse operation
authoremv <emv@opencascade.com>
Thu, 22 May 2014 14:12:35 +0000 (18:12 +0400)
committerapn <apn@opencascade.com>
Thu, 22 May 2014 14:13:24 +0000 (18:13 +0400)
Modifications:
1. class BOPAlgo_WireSplitter
  1.1. Removed static method RecomputeAngles(...).
  1.2. Minor corrections.
2. class BOPTools_AlgoTools
  2.1 method GetFaceOff
  For definition of an angles between faces the same step in 3D space has been used for all faces in the list.
  To define that step new static function MinStep3D has been implemented.

Added test case bugs/modalg_5/bug24879
Deleted unnecessary TODOs in test case bugs/modalg_2/bug497_3

src/BOPAlgo/BOPAlgo_WireSplitter_1.cxx
src/BOPTools/BOPTools_AlgoTools.cxx
tests/bugs/modalg_2/bug497_3
tests/bugs/modalg_5/bug24879 [new file with mode: 0644]

index 7581938..e047142 100644 (file)
 
 #include <BOPTools_AlgoTools2D.hxx>
 
+typedef NCollection_DataMap \
+  <TopoDS_Shape, Standard_Boolean, TopTools_ShapeMapHasher> \
+  BOPCol_DataMapOfShapeBoolean; 
+//
+
 static
   Standard_Real Angle (const gp_Dir2d& aDir2D);
 
@@ -88,8 +93,7 @@ static
                     const TopoDS_Edge& aE1,
                     const TopoDS_Face& aF);
 
-
-static
+static 
   Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
                                const Standard_Real aAngleOut);
 
@@ -103,14 +107,9 @@ static
              BOPCol_SequenceOfShape& aVertVa,
              BOPCol_SequenceOfPnt2d& aCoordVa,
              BOPTools_ConnexityBlock& aCB,
-             BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo& mySmartMap);
-             
-static
-  Standard_Real Angle2D (const TopoDS_Vertex& aV,
-                         const TopoDS_Edge& anEdge,
-                         const TopoDS_Face& myFace,
-                         const GeomAdaptor_Surface& aGAS,
-                         const Standard_Boolean aFlag);
+             BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo& mySmartMap,
+             BOPCol_DataMapOfShapeBoolean aVertMap);
+
 static
   Standard_Real Angle (const gp_Dir2d& aDir2D);
 
@@ -128,17 +127,6 @@ static
                               const GeomAdaptor_Surface& aGAS);
 
 static
-  Standard_Boolean RecomputeAngles(const BOPAlgo_ListOfEdgeInfo& aLEInfo, 
-                                   const TopoDS_Face&            theFace, 
-                                   const gp_Pnt2d&               thePb, 
-                                   const TopoDS_Vertex&          theVb,
-                                   const GeomAdaptor_Surface&    theGAS,
-                                   const TopoDS_Edge&            theEOuta, 
-                                   const Standard_Boolean&       bHasClosed,
-                                   const Standard_Real&          theTol2D,
-                                   BOPCol_SequenceOfReal&        theRecomputedAngles);
-
-static
   void RefineAngles(const TopoDS_Face& myFace,
                     const BOPCol_ListOfShape&,
                     BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo&);
@@ -165,16 +153,18 @@ static
 void BOPAlgo_WireSplitter::SplitBlock(const TopoDS_Face& myFace,
                                       BOPTools_ConnexityBlock& aCB)
 {
-  Standard_Boolean bNothingToDo;
+  Standard_Boolean bNothingToDo, bIsClosed, bIsIN;
   Standard_Integer aIx, aNb, i, aCntIn, aCntOut;
   Standard_Real aAngle;
   TopAbs_Orientation aOr;
   TopoDS_Iterator aItS;
   TopoDS_Vertex aVV;
+  TopoDS_Shape aV1;
   BOPCol_ListIteratorOfListOfShape aIt;
   BOPAlgo_ListIteratorOfListOfEdgeInfo aItLEI;
   //
   BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo mySmartMap(100);
+  BOPCol_DataMapOfShapeBoolean aVertMap;
   //
   const BOPCol_ListOfShape& myEdges=aCB.Shapes();
   //
@@ -188,28 +178,40 @@ void BOPAlgo_WireSplitter::SplitBlock(const TopoDS_Face& myFace,
       continue;
     }
     //
+    bIsClosed = BRep_Tool::Degenerated(aE) || 
+                BRep_Tool::IsClosed(aE, myFace);
+    //
     aItS.Initialize(aE);
-    for(; aItS.More(); aItS.Next()) {
-      const TopoDS_Shape& aV=aItS.Value();
-      aIx=mySmartMap.FindIndex(aV);
+    for(i = 0; aItS.More(); aItS.Next(), ++i) {
+      const TopoDS_Shape& aV = aItS.Value();
+      aIx = mySmartMap.FindIndex(aV);
       if (!aIx) {
         BOPAlgo_ListOfEdgeInfo aLEIx;
-        aIx=mySmartMap.Add(aV, aLEIx);
+        aIx = mySmartMap.Add(aV, aLEIx);
       }
       //
-      BOPAlgo_ListOfEdgeInfo& aLEI=mySmartMap(aIx);
-      //
+      BOPAlgo_ListOfEdgeInfo& aLEI = mySmartMap(aIx);
       BOPAlgo_EdgeInfo aEI;
       //
       aEI.SetEdge(aE);
-      aOr=aV.Orientation();
-      if (aOr==TopAbs_FORWARD) {
-        aEI.SetInFlag(Standard_False);
+      aOr = aV.Orientation();
+      bIsIN = (aOr == TopAbs_REVERSED);
+      aEI.SetInFlag(bIsIN);
+      aLEI.Append(aEI);
+      //
+      if (!i) {
+        aV1 = aV;
+      } else {
+        bIsClosed = bIsClosed || aV1.IsSame(aV);
       }
-      else if (aOr==TopAbs_REVERSED) {
-        aEI.SetInFlag(Standard_True);
+      //
+      if (aVertMap.IsBound(aV)) {
+        if (bIsClosed) {
+          aVertMap.ChangeFind(aV) = bIsClosed;
+        }
+      } else {
+        aVertMap.Bind(aV, bIsClosed);
       }
-      aLEI.Append(aEI);
     }
   }
   //
@@ -299,7 +301,7 @@ void BOPAlgo_WireSplitter::SplitBlock(const TopoDS_Face& myFace,
   const GeomAdaptor_Surface& aGAS=aBAS.Surface();
   //
   for (i=1; i<=aNb; i++) {
-    const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&mySmartMap.FindKey(i))); 
+    const TopoDS_Vertex& aV = (*(TopoDS_Vertex *)(&mySmartMap.FindKey(i))); 
     const BOPAlgo_ListOfEdgeInfo& aLEI= mySmartMap(i);
 
     aItLEI.Initialize(aLEI);
@@ -307,15 +309,11 @@ void BOPAlgo_WireSplitter::SplitBlock(const TopoDS_Face& myFace,
       BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
       const TopoDS_Edge& aE=aEI.Edge();
       //
-      aVV=aV;
-      if (aEI.IsIn()) {
-        aVV.Orientation(TopAbs_REVERSED);
-        aAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_True);
-      }
-      else { // OUT
-        aVV.Orientation(TopAbs_FORWARD);
-        aAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_False);
-      }
+      aVV = aV;
+      bIsIN = aEI.IsIn();
+      aOr = bIsIN ? TopAbs_REVERSED : TopAbs_FORWARD;
+      aVV.Orientation(aOr);
+      aAngle = Angle2D(aVV, aE, myFace, aGAS, bIsIN);
       aEI.SetAngle(aAngle);
     }
   }// for (i=1; i<=aNb; i++) {
@@ -348,7 +346,7 @@ void BOPAlgo_WireSplitter::SplitBlock(const TopoDS_Face& myFace,
         aCoordVa.Clear();
         //
         Path(aGAS, myFace, aVa, aEOuta, aEI, aLS, 
-             aVertVa, aCoordVa, aCB, mySmartMap);
+             aVertVa, aCoordVa, aCB, mySmartMap, aVertMap);
       }
     }
   }// for (i=1; i<=aNb; ++i) {
@@ -366,18 +364,18 @@ void Path (const GeomAdaptor_Surface& aGAS,
            BOPCol_SequenceOfShape& aVertVa,
            BOPCol_SequenceOfPnt2d& aCoordVa,
            BOPTools_ConnexityBlock& aCB,
-           BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo& mySmartMap)
+           BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo& mySmartMap,
+           BOPCol_DataMapOfShapeBoolean aVertMap)
      
 {
   Standard_Integer i, j, aNb, aNbj;
   Standard_Real anAngleIn, anAngleOut, anAngle, aMinAngle;
   Standard_Real aTol2D, aTol2D2, aD2, aTwoPI;
   Standard_Boolean anIsSameV2d, anIsSameV, anIsFound, anIsOut, anIsNotPassed;
-  Standard_Boolean bIsClosed, bRecomputeAngle;
+  Standard_Boolean bIsClosed;
   TopoDS_Vertex aVa, aVb;
   TopoDS_Edge aEOuta;
   BOPAlgo_ListIteratorOfListOfEdgeInfo anIt;
-  BOPCol_SequenceOfReal aRecomputedAngles;
   //
   aVa = aVFirst;
   aEOuta = aEFirst;
@@ -415,23 +413,7 @@ void Path (const GeomAdaptor_Surface& aGAS,
     aTol2D = 2.*Tolerance2D(aVb, aGAS);
     aTol2D2 = aTol2D * aTol2D;
     //
-    bIsClosed = BRep_Tool::Degenerated(aEOuta) || 
-      BRep_Tool::IsClosed(aEOuta, myFace) || aVa.IsSame(aVb);
-    if (!bIsClosed) {
-      TopoDS_Vertex aV1, aV2;
-      //
-      anIt.Initialize(aLEInfo);
-      for (; anIt.More() && !bIsClosed; anIt.Next()) {
-        const BOPAlgo_EdgeInfo& anEI = anIt.Value();
-        const TopoDS_Edge& aE = anEI.Edge();
-        //
-        bIsClosed = BRep_Tool::Degenerated(aE) || BRep_Tool::IsClosed(aE, myFace);
-        if (!bIsClosed) {
-          TopExp::Vertices(aE, aV1, aV2);
-          bIsClosed = aV1.IsNull() || aV2.IsNull() || aV1.IsSame(aV2);
-        }
-      }
-    }
+    bIsClosed = aVertMap.Find(aVb);
     //
     aNb=aLS.Length();
     if (aNb>0) {
@@ -512,11 +494,6 @@ void Path (const GeomAdaptor_Surface& aGAS,
       }
     }
     //
-    aRecomputedAngles.Clear();
-    bRecomputeAngle = 
-      RecomputeAngles(aLEInfo, myFace, aPb, aVb, aGAS, aEOuta, 
-                      bIsClosed, aTol2D, aRecomputedAngles);
-    //
     // aEOutb
     BOPAlgo_EdgeInfo *pEdgeInfo=NULL;
     //
@@ -530,7 +507,7 @@ void Path (const GeomAdaptor_Surface& aGAS,
       const TopoDS_Edge& aE=anEI.Edge();
       anIsOut=!anEI.IsIn();
       anIsNotPassed=!anEI.Passed();
-      
+      //
       if (anIsOut && anIsNotPassed) {
         aCurIndexE++;
         //
@@ -568,12 +545,6 @@ void Path (const GeomAdaptor_Surface& aGAS,
           //
           // Look for minimal angle and make the choice.
           anAngleOut=anEI.Angle();
-          //
-          if(bRecomputeAngle) {
-            if(aCurIndexE <= aRecomputedAngles.Length()) {
-              anAngleOut = aRecomputedAngles.Value(aCurIndexE);
-            }
-          }
           anAngle=ClockWiseAngle(anAngleIn, anAngleOut);
         }
         if (anAngle < aMinAngle) {
@@ -751,7 +722,7 @@ Standard_Integer NbWaysOut(const BOPAlgo_ListOfEdgeInfo& aLEInfo)
                          const TopoDS_Edge& anEdge,
                          const TopoDS_Face& myFace,
                          const GeomAdaptor_Surface& aGAS,
-                         const Standard_Boolean aFlag)
+                         const Standard_Boolean bIsIN)
 {
   Standard_Real aFirst, aLast, aToler, dt, aTV, aTV1, anAngle, aTX;
   gp_Pnt2d aPV, aPV1;
@@ -794,14 +765,7 @@ Standard_Integer NbWaysOut(const BOPAlgo_ListOfEdgeInfo& aLEInfo)
   aC2D->D0 (aTV1, aPV1);
   aC2D->D0 (aTV, aPV);
   //
-  if (aFlag) {//IN
-    gp_Vec2d aV2DIn(aPV1, aPV);
-    aV2D=aV2DIn;
-  }
-  else {
-    gp_Vec2d aV2DOut(aPV, aPV1);
-    aV2D=aV2DOut;
-  }
+  aV2D = bIsIN ? gp_Vec2d(aPV1, aPV) : gp_Vec2d(aPV, aPV1);
   //
   gp_Dir2d aDir2D(aV2D);
   anAngle=Angle(aDir2D);
@@ -876,155 +840,6 @@ Standard_Real VTolerance2D (const TopoDS_Vertex& aV,
 }
 
 //=======================================================================
-// function: RecomputeAngles
-// purpose: 
-//=======================================================================
-Standard_Boolean RecomputeAngles(const BOPAlgo_ListOfEdgeInfo& aLEInfo, 
-                                 const TopoDS_Face&            theFace, 
-                                 const gp_Pnt2d&               thePb, 
-                                 const TopoDS_Vertex&          theVb,
-                                 const GeomAdaptor_Surface&    theGAS,
-                                 const TopoDS_Edge&            theEOuta, 
-                                 const Standard_Boolean&       bIsClosed,
-                                 const Standard_Real&          theTol2D,
-                                 BOPCol_SequenceOfReal&        theRecomputedAngles)
-{
-  Standard_Boolean bRecomputeAngle = Standard_False;
-  BOPAlgo_ListIteratorOfListOfEdgeInfo anIt;
-  anIt.Initialize(aLEInfo);
-
-  for (; anIt.More(); anIt.Next()) {
-    const BOPAlgo_EdgeInfo& anEI=anIt.Value();
-    const TopoDS_Edge& aE=anEI.Edge();
-    Standard_Boolean anIsOut=!anEI.IsIn();
-    Standard_Boolean anIsNotPassed=!anEI.Passed();
-    
-    if (anIsOut && anIsNotPassed) {
-      theRecomputedAngles.Append(anEI.Angle());
-      Standard_Integer acurindex = theRecomputedAngles.Length();
-
-      Standard_Boolean bRecomputeAngleLocal = Standard_False;
-      TopExp_Explorer anExp1(aE, TopAbs_VERTEX);
-
-      for(; anExp1.More(); anExp1.Next()) {
-        TopExp_Explorer anExp2(theEOuta, TopAbs_VERTEX);
-        Standard_Boolean existsInEdge = Standard_False;
-        
-        for(; anExp2.More(); anExp2.Next()) {
-          if(anExp1.Current().IsSame(anExp2.Current())) {
-            existsInEdge = Standard_True;
-            break;
-          }
-        }
-        
-        if(!existsInEdge) {
-          bRecomputeAngleLocal = Standard_False;
-          break;
-        }
-        bRecomputeAngleLocal = Standard_True;
-      }
-      bRecomputeAngle = bRecomputeAngle || bRecomputeAngleLocal;
-
-      if(!bRecomputeAngle) {
-        BOPAlgo_ListIteratorOfListOfEdgeInfo anIt2(aLEInfo);
-        
-        for(; anIt2.More(); anIt2.Next()) {
-          const BOPAlgo_EdgeInfo& anEI2=anIt2.Value();
-          const TopoDS_Edge& aE2=anEI2.Edge();
-          
-          if(aE2.IsSame(aE))
-            continue;
-          Standard_Boolean anIsOut2=!anEI2.IsIn();
-          Standard_Boolean anIsNotPassed2=!anEI2.Passed();
-          
-          if (anIsOut2 && anIsNotPassed2) {
-            anExp1.Init(aE, TopAbs_VERTEX);
-            
-            for(; anExp1.More(); anExp1.Next()) {
-              TopExp_Explorer anExp2(aE2, TopAbs_VERTEX);
-              Standard_Boolean existsInEdge = Standard_False;
-              
-              for(; anExp2.More(); anExp2.Next()) {
-                if(anExp1.Current().IsSame(anExp2.Current())) {
-                  existsInEdge = Standard_True;
-                  break;
-                }
-              }
-              
-              if(!existsInEdge) {
-                bRecomputeAngleLocal = Standard_False;
-                break;
-              }
-              bRecomputeAngleLocal = Standard_True;
-            }
-            bRecomputeAngle = bRecomputeAngle || bRecomputeAngleLocal;
-          }
-        }
-      }
-      
-      bRecomputeAngle = bRecomputeAngle || bRecomputeAngleLocal;
-
-      if(bRecomputeAngle) {
-        gp_Pnt2d aP2Dx;
-        //
-        aP2Dx=Coord2dVf(aE, theFace);
-        Standard_Real aD = aP2Dx.Distance(thePb);
-        
-        TopoDS_Vertex aVf;
-        TopExp_Explorer anExp(aE, TopAbs_VERTEX);
-        
-        for (; anExp.More(); anExp.Next()) {
-          const TopoDS_Vertex& aVx=*(TopoDS_Vertex*)(&anExp.Current());
-          if (aVx.Orientation()==TopAbs_FORWARD) {
-            aVf = aVx;
-          }
-        }
-        Standard_Boolean bIgnore = Standard_False;
-        
-        if(bIsClosed || aVf.IsNull() || !aVf.IsSame(theVb)) {
-          bIgnore = (aD > theTol2D);
-        }
-        
-        if(!bIgnore && (theTol2D > M_PI)) {
-          Standard_Real udist = fabs(aP2Dx.X() - thePb.X());
-          Standard_Real vdist = fabs(aP2Dx.Y() - thePb.Y());
-          Standard_Real aTolU = 2. * UTolerance2D(theVb, theGAS);
-          Standard_Real aTolV = 2. * VTolerance2D(theVb, theGAS);
-          
-          if((udist > aTolU) ||
-             (vdist > aTolV)) {
-            bIgnore = Standard_True;
-          }
-        }
-        
-        if((aD > Precision::Confusion()) && !bIgnore) {
-          Standard_Real f1, l1;
-          Handle(Geom2d_Curve) ac1 = BRep_Tool::CurveOnSurface(aE, theFace, f1, l1);
-          
-          Standard_Real aTV1 = BRep_Tool::Parameter (aVf, aE, theFace);
-          Standard_Real aTV12 = 0.;
-          Standard_Real dt1 = (l1 - f1) * 0.5;
-          
-          if (fabs (aTV1-f1) < fabs(aTV1 - l1)) {
-            aTV12 = aTV1 + dt1;
-          }
-          else {
-            aTV12 = aTV1 - dt1;
-          }
-          
-          gp_Pnt2d aPointNew = ac1->Value(aTV12);
-          gp_Vec2d aV2DOut(thePb, aPointNew);
-          
-          gp_Dir2d aDir2D(aV2DOut);
-          Standard_Real anAngleOut = Angle(aDir2D);
-          theRecomputedAngles.ChangeValue(acurindex) = anAngleOut;
-        }
-      }
-    }
-  }
-  return bRecomputeAngle;
-}
-//=======================================================================
 //function : RefineAngles
 //purpose  : 
 //=======================================================================
@@ -1091,14 +906,15 @@ void RefineAngles(const TopoDS_Vertex& aV,
                   BOPAlgo_ListOfEdgeInfo& aLEI)
 {
   Standard_Boolean bIsIn, bIsBoundary, bRefined; 
-  Standard_Integer iCnt;
+  Standard_Integer iCntBnd, iCntInt;
   Standard_Real aA, aA1, aA2;
   BOPCol_DataMapOfShapeReal aDMSR;
   BOPAlgo_ListIteratorOfListOfEdgeInfo aItLEI;
   //
   aA1=0.;
   aA2=0.;
-  iCnt=0;
+  iCntBnd=0;
+  iCntInt=0;
   aItLEI.Initialize(aLEI);
   for (; aItLEI.More(); aItLEI.Next()) {
     BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
@@ -1107,7 +923,7 @@ void RefineAngles(const TopoDS_Vertex& aV,
     aA=aEI.Angle();
     //
     if (aMBE.Contains(aE)) {
-      ++iCnt;
+      ++iCntBnd;
       if (!bIsIn) {
         aA1=aA;
       }
@@ -1115,9 +931,12 @@ void RefineAngles(const TopoDS_Vertex& aV,
         aA2=aA+M_PI;
       }
     }
+    else {
+      ++iCntInt;
+    }
   }
   //
-  if (iCnt!=2) {
+  if (iCntBnd!=2) {
     return;
   }
   //
@@ -1133,7 +952,7 @@ void RefineAngles(const TopoDS_Vertex& aV,
     }
     //
     aA=aEI.Angle();
-    if (!(aA<aA1 || aA>aA2)) {
+    if (aA>aA1 && aA<aA2) {
       continue;
     }
     //
@@ -1141,6 +960,11 @@ void RefineAngles(const TopoDS_Vertex& aV,
     if (bRefined) {
       aDMSR.Bind(aE, aA);
     }
+    else if (iCntInt == 2) {
+      aA = (aA <= aA1) ? (aA1 + Precision::Angular()) :
+                         (aA2 - Precision::Angular());
+      aDMSR.Bind(aE, aA);
+    }
   }
   
   if (aDMSR.IsEmpty()) {
@@ -1178,8 +1002,8 @@ Standard_Boolean RefineAngle2D(const TopoDS_Vertex& aV,
                                Standard_Real& aA)
 {
   Standard_Boolean bRet;
-  Standard_Integer i, j, aNbP, iSign;
-  Standard_Real aTV, aTol, aT1, aT2, dT, aAngle, aT;
+  Standard_Integer i, j, aNbP;
+  Standard_Real aTV, aTol, aT1, aT2, dT, aAngle, aT, aTOp;
   Standard_Real aTolInt, aAi, aXi, aYi, aT1j, aT2j, aT1max, aT2max, aCf; 
   gp_Pnt2d aPV, aP, aP1, aP2;
   Handle(Geom2d_Curve) aC2D;
@@ -1197,7 +1021,7 @@ Standard_Boolean RefineAngle2D(const TopoDS_Vertex& aV,
   aTV=BRep_Tool::Parameter (aV, aE, myFace);
   aC2D->D0(aTV, aPV);
   //
-  iSign=(fabs(aTV-aT1) < fabs(aTV-aT2)) ? 1 : -1;
+  aTOp = (fabs(aTV-aT1) < fabs(aTV-aT2)) ? aT2 : aT1;
   //
   aGAC1.Load(aC2D, aT1, aT2);
   aC2D->D0(aT1, aP1);
@@ -1237,9 +1061,9 @@ Standard_Boolean RefineAngle2D(const TopoDS_Vertex& aV,
       }
     }
     //
-    dT=(iSign==1) ? aT2-aT1max : aT1max-aT1;
+    dT = aTOp - aT1max;
     //
-    aT=aT1max+aCf*dT;
+    aT=aT1max + aCf*dT;
     aC2D->D0(aT, aP);
     gp_Vec2d aV2D(aPV, aP);
     gp_Dir2d aDir2D(aV2D);
index ad698ff..67cba7f 100644 (file)
@@ -90,15 +90,21 @@ static
                   gp_Dir& aDN,
                   gp_Dir& aDB,
                   Handle(BOPInt_Context)& theContext,
-                  GeomAPI_ProjectPointOnSurf& aProjPL);
+                  GeomAPI_ProjectPointOnSurf& aProjPL,
+                  const Standard_Real aDt);
 static
-  Standard_Boolean FindPointInFace(const TopoDS_Edge& aE,
-                                   const TopoDS_Face& aF,
+  Standard_Boolean FindPointInFace(const TopoDS_Face& aF,
                                    const gp_Pnt& aP,
                                    gp_Dir& aDB,
                                    gp_Pnt& aPOut,
                                    Handle(BOPInt_Context)& theContext,
-                                   GeomAPI_ProjectPointOnSurf& aProjPL);
+                                   GeomAPI_ProjectPointOnSurf& aProjPL,
+                                   const Standard_Real aDt);
+static 
+  Standard_Real MinStep3D(const TopoDS_Edge& theE1,
+                          const TopoDS_Face& theF1,
+                          const BOPTools_ListOfCoupleOfShape& theLCS,
+                          const gp_Pnt& aP);
 
 //=======================================================================
 // function: MakeConnexityBlocks
@@ -805,7 +811,7 @@ Standard_Boolean BOPTools_AlgoTools::GetFaceOff
    Handle(BOPInt_Context)& theContext)
 {
   Standard_Boolean bRet;
-  Standard_Real aT, aT1, aT2, aAngle, aTwoPI, aAngleMin;
+  Standard_Real aT, aT1, aT2, aAngle, aTwoPI, aAngleMin, aDt3D;
   Standard_Real aUmin, aUsup, aVmin, aVsup;
   gp_Pnt aPn1, aPn2, aPx;
   gp_Dir aDN1, aDN2, aDBF, aDBF2, aDTF;
@@ -830,8 +836,9 @@ Standard_Boolean BOPTools_AlgoTools::GetFaceOff
   aPL->Bounds(aUmin, aUsup, aVmin, aVsup);
   aProjPL.Init(aPL, aUmin, aUsup, aVmin, aVsup);
   //
+  aDt3D = MinStep3D(theE1, theF1, theLCSOff, aPx);
   GetFaceDir(theE1, theF1, aPx, aT, aDTgt, aDN1, aDBF, theContext, 
-             aProjPL);
+             aProjPL, aDt3D);
   //
   aDTF=aDN1^aDBF;
   //
@@ -844,7 +851,7 @@ Standard_Boolean BOPTools_AlgoTools::GetFaceOff
     //
     aDTgt2 = (aE2.Orientation()==aOr) ? aDTgt : aDTgt.Reversed();
     GetFaceDir(aE2, aF2, aPx, aT, aDTgt2, aDN2, aDBF2, theContext, 
-               aProjPL);
+               aProjPL, aDt3D);
     //Angle
     aAngle=AngleWithRef(aDBF, aDBF2, aDTF);
     //
@@ -1811,7 +1818,8 @@ void GetFaceDir(const TopoDS_Edge& aE,
                 gp_Dir& aDN,
                 gp_Dir& aDB,
                 Handle(BOPInt_Context)& theContext,
-                GeomAPI_ProjectPointOnSurf& aProjPL)
+                GeomAPI_ProjectPointOnSurf& aProjPL,
+                const Standard_Real aDt)
 {
   BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE, aF, aT, aDN);
   if (aF.Orientation()==TopAbs_REVERSED){
@@ -1820,7 +1828,7 @@ void GetFaceDir(const TopoDS_Edge& aE,
   aDB = aDN^aDTgt;
   //
   gp_Pnt aPx;
-  if (!FindPointInFace(aE, aF, aP, aDB, aPx, theContext, aProjPL)) {
+  if (!FindPointInFace(aF, aP, aDB, aPx, theContext, aProjPL, aDt)) {
     BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge(aE, aF, aT, aPx, 
                                                       aDN, theContext);
     aProjPL.Perform(aPx);
@@ -1834,19 +1842,18 @@ void GetFaceDir(const TopoDS_Edge& aE,
 //function : FindPointInFace
 //purpose  : Find a point in the face in direction of <aDB>
 //=======================================================================
-Standard_Boolean FindPointInFace(const TopoDS_Edge& aE,
-                                 const TopoDS_Face& aF,
+Standard_Boolean FindPointInFace(const TopoDS_Face& aF,
                                  const gp_Pnt& aP,
                                  gp_Dir& aDB,
                                  gp_Pnt& aPOut,
                                  Handle(BOPInt_Context)& theContext,
-                                 GeomAPI_ProjectPointOnSurf& aProjPL) 
+                                 GeomAPI_ProjectPointOnSurf& aProjPL,
+                                 const Standard_Real aDt)
 {
   Standard_Integer aNbItMax;
-  Standard_Real aDt, aDtMin, aTolE, aTolF, aDist, aDTol, aPM;
+  Standard_Real aDist, aDTol, aPM;
   Standard_Boolean bRet;
   gp_Pnt aP1;
-  BRepAdaptor_Surface aBAS;
   //
   aDTol = Precision::Angular();
   aPM = aP.XYZ().Modulus();
@@ -1854,49 +1861,9 @@ Standard_Boolean FindPointInFace(const TopoDS_Edge& aE,
     aDTol = 5.e-16 * aPM;
   }
   bRet = Standard_False;
-  aTolE = BRep_Tool::Tolerance(aE);
-  aTolF = BRep_Tool::Tolerance(aF);
-  aDt = 2*(aTolE+aTolF);
-  aBAS.Initialize(aF, Standard_False);
-  //
-  aDtMin=5.e-4;
-  if (aDt < aDtMin) {
-    Standard_Real aR;
-    GeomAbs_SurfaceType aSType=aBAS.GetType();
-    switch (aSType) {
-    case GeomAbs_Cylinder:
-      aR = aBAS.Cylinder().Radius();
-      break;
-    case GeomAbs_Cone: {
-      gp_Lin aL(aBAS.Cone().Axis());
-      aR = aL.Distance(aP);
-      break;
-    }
-    case GeomAbs_Sphere:
-      aR = aBAS.Sphere().Radius();
-      break;
-    case GeomAbs_Torus:
-      aR = aBAS.Torus().MinorRadius();
-      break;
-    case GeomAbs_SurfaceOfRevolution:
-      aR=1.;
-      break;
-    default:
-      aR=0.001;
-    }
-    if (aR < 0.01) {
-      aDtMin=5.e-6;
-    }
-    else if (aR > 100.) {
-      aDtMin*=10;
-    }
-    if (aDt < aDtMin) {
-      aDt=aDtMin;
-    }
-  }
+  aNbItMax = 15;
   //
   GeomAPI_ProjectPointOnSurf& aProj=theContext->ProjPS(aF);
-  aNbItMax = 15;
   //
   do {
     aP1.SetCoord(aP.X()+aDt*aDB.X(),
@@ -1921,6 +1888,74 @@ Standard_Boolean FindPointInFace(const TopoDS_Edge& aE,
   return bRet;
 }
 //=======================================================================
+//function : MinStep3D
+//purpose  : 
+//=======================================================================
+Standard_Real MinStep3D(const TopoDS_Edge& theE1,
+                        const TopoDS_Face& theF1,
+                        const BOPTools_ListOfCoupleOfShape& theLCS,
+                        const gp_Pnt& aP)
+{
+  Standard_Real aDt, aTolE, aTolF, aDtMax, aDtMin, aR;
+  BOPTools_CoupleOfShape aCS1;
+  BOPTools_ListOfCoupleOfShape aLCS;
+  BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
+  BRepAdaptor_Surface aBAS;
+  //
+  aLCS = theLCS;
+  aCS1.SetShape1(theE1);
+  aCS1.SetShape2(theF1);
+  aLCS.Append(aCS1);
+  //
+  aTolE = BRep_Tool::Tolerance(theE1);
+  aDtMax = -1.;
+  aDtMin = 5.e-6;
+  //
+  aIt.Initialize(aLCS);
+  for (; aIt.More(); aIt.Next()) {
+    const BOPTools_CoupleOfShape& aCS = aIt.Value();
+    const TopoDS_Face& aF = (*(TopoDS_Face*)(&aCS.Shape2()));
+    //
+    aTolF = BRep_Tool::Tolerance(aF);
+    aDt = 2*(aTolE + aTolF);
+    //
+    aR = 0.;
+    aBAS.Initialize(aF, Standard_False);
+    GeomAbs_SurfaceType aSType = aBAS.GetType();
+    if (aSType == GeomAbs_Cylinder) {
+      aR = aBAS.Cylinder().Radius();
+    }
+    else if (aSType == GeomAbs_Cone) {
+      gp_Lin aL(aBAS.Cone().Axis());
+      aR = aL.Distance(aP);
+    }
+    else if (aSType == GeomAbs_Sphere) {
+      aR = aBAS.Sphere().Radius();
+    }
+    else if (aSType == GeomAbs_Torus) {
+      aR = aBAS.Torus().MajorRadius();
+    }
+    else if (aSType == GeomAbs_SurfaceOfRevolution) {
+      aDtMin = 5.e-4;
+    }
+    //
+    if (aR > 100.) {
+      Standard_Real d = Precision::PConfusion();
+      aDtMin = sqrt(d*d + 2*d*aR);
+    }
+    //
+    if (aDt > aDtMax) {
+      aDtMax = aDt;
+    }
+  }
+  //
+  if (aDtMax < aDtMin) {
+    aDtMax = aDtMin;
+  }
+  //
+  return aDtMax;
+}
+//=======================================================================
 //function : IsOpenShell
 //purpose  : 
 //=======================================================================
index 1375ba6..d5a7166 100755 (executable)
@@ -1,6 +1,3 @@
-puts "TODO OCC12345 ALL: Faulty shapes in variables faulty_1 to faulty_"
-puts "TODO OCC12345 ALL: Error : The square of result shape is"
-
 puts "========="
 puts " OCC497 "
 puts "(case 3)"
@@ -18,5 +15,5 @@ checkshape a_2
 
 bcut result a_1 a_2
 
-set square 0
+set square 1773.6
 set 2dviewer 0
diff --git a/tests/bugs/modalg_5/bug24879 b/tests/bugs/modalg_5/bug24879
new file mode 100644 (file)
index 0000000..877cd9f
--- /dev/null
@@ -0,0 +1,18 @@
+puts "=========="
+puts "OCC24879"
+puts "=========="
+puts ""
+############################################
+# Wrong result of General Fuse operation
+############################################
+
+restore [locate_data_file bug24879_c.brep] c
+
+bclearobjects
+bcleartools
+baddcompound c
+bfillds -s
+bbuild result
+checkshape result
+
+set 2dviewer 1