]> OCCT Git - occt-copy.git/commitdiff
0029237: Improve performance of Boolean Operations
authoremv <emv@opencascade.com>
Wed, 18 Oct 2017 08:05:24 +0000 (11:05 +0300)
committeremv <emv@opencascade.com>
Thu, 28 Jun 2018 06:45:53 +0000 (09:45 +0300)
In order to improve performance of Boolean Operations on the relatively fast cases the following improvements have been made:
1. Initialization of the FaceInfo information for the faces participating in Face/Face interference, even when the gluing is ON, to take into account intersection of their sub-shapes.
2. Code simplification & duplication removal - the methods BOPAlgo_ShellSplitter::MakeConnexityBlocks and BOPAlgo_WireSplitter::MakeConnexityBlocks have been unified into BOPTools_AlgoTools::MakeConnexityBlocks.
3. Avoid unnecessary bounding box computation for solids during DS initialization. The bounding boxes for solids will be computed during the building stage to find faces located inside solids.
   For the shape self-interference check (performed by the BOPAlgo_CheckerSI), the bounding box is still computed, as it is necessary to resolve Shape/Solid intersections.
4. Use only three sample points to check coincidence of line and plane.
5. Perform necessity of planes intersection only when the gluing is off.
6. Avoid repeated initialization of 2D classifier while building splits of the faces.
7. Post treat stage:
7.1. Method CorrectWires: Save edge's data (PCurve, parameter of the vertex, range) to avoid its recalculation.
7.2. Method CheckEdge: While checking vertices on edges avoid unnecessary calculation of their location.
8. Provide possibility to disable the classification of the input solids on the inverted status (to be the holes in the space).
9. Avoid building of bounding boxes for faces/solids during splitting of the input arguments for their classification relatively hole faces/shells if there are no holes created.
10. Avoid rebuilding of the faces/solids from arguments which does not acquire any inside parts from other arguments during the operation by using their draft versions as their splits.

Test cases for the issue.
Correction of the test cases boolean gdml_public A9 and bugs modalg_7 bug28485 as they are improvements.
Additional test case for the issue #28485 as it is fixed by the current changes.

37 files changed:
dox/user_guides/boolean_operations/boolean_operations.md
src/BOPAlgo/BOPAlgo_BuilderFace.cxx
src/BOPAlgo/BOPAlgo_BuilderSolid.cxx
src/BOPAlgo/BOPAlgo_Builder_2.cxx
src/BOPAlgo/BOPAlgo_Builder_3.cxx
src/BOPAlgo/BOPAlgo_Options.cxx
src/BOPAlgo/BOPAlgo_Options.hxx
src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx
src/BOPAlgo/BOPAlgo_ShellSplitter.cxx
src/BOPAlgo/BOPAlgo_ShellSplitter.hxx
src/BOPAlgo/BOPAlgo_WireSplitter.cxx
src/BOPAlgo/BOPAlgo_WireSplitter.hxx
src/BOPDS/BOPDS_DS.cxx
src/BOPDS/BOPDS_DS.hxx
src/BOPTest/BOPTest_APICommands.cxx
src/BOPTest/BOPTest_BOPCommands.cxx
src/BOPTest/BOPTest_CellsCommands.cxx
src/BOPTest/BOPTest_Objects.cxx
src/BOPTest/BOPTest_Objects.hxx
src/BOPTest/BOPTest_OptionCommands.cxx
src/BOPTest/BOPTest_PartitionCommands.cxx
src/BOPTools/BOPTools.cxx
src/BOPTools/BOPTools_AlgoTools.cxx
src/BOPTools/BOPTools_AlgoTools.hxx
src/BOPTools/BOPTools_AlgoTools2D.cxx
src/BOPTools/BOPTools_AlgoTools_1.cxx
src/BRepAlgoAPI/BRepAlgoAPI_Algo.hxx
src/BRepAlgoAPI/BRepAlgoAPI_BooleanOperation.cxx
src/BRepAlgoAPI/BRepAlgoAPI_BuilderAlgo.cxx
src/BRepAlgoAPI/BRepAlgoAPI_Splitter.cxx
src/IntTools/IntTools_EdgeFace.cxx
tests/boolean/gdml_public/A9
tests/bugs/modalg_7/bug28485 [new file with mode: 0644]
tests/bugs/modalg_7/bug28485_1 [new file with mode: 0644]
tests/perf/modalg/bug29237_1 [new file with mode: 0644]
tests/perf/modalg/bug29237_2 [new file with mode: 0644]
tests/perf/modalg/bug29237_3 [new file with mode: 0644]

index db2db52ad664ee3c510235c7bb8094a8e42de161..f76693658b044785ec4dd979ea4c90f807c176dc 100644 (file)
@@ -2718,6 +2718,38 @@ To enable the safe processing mode for the operation in DRAW, it is necessary to
 bnondestructive 1
 ~~~~
 
+@subsection occt_algorithms_11a_4 Disabling check of the input solids for inverted status
+
+By default, all input solids are checked for inverted status, i.e. the solids are classified to understand if they are holes in the space (negative volumes) or normal solids (positive volumes). The possibility to disable the check of the input solids for inverted status is the advanced option in Boolean Operation component. This option can be applied to all Basic operations such as General Fuse, Splitting, Boolean, Section, Maker Volume, Cells building.
+This option allows avoiding time-consuming classification of the input solids and operate with them as with positive volumes, saving up to 10 percent of time on the cases with big number of input solids.
+
+The classification should be disabled only if the user is sure that there are no negative volumes among the input solids, otherwise the result may be invalid.
+
+@subsubsection occt_algorithms_11a_4_1 Usage
+
+#### API level
+
+To enable/disable the classification of the input solids it is necessary to call *SetCheckInverted()* method with the appropriate value:
+~~~~
+BOPAlgo_Builder aGF;
+//
+....
+// disabling the classification of the input solid
+aGF.SetCheckInverted(Standard_False);
+//
+....
+~~~~
+
+#### TCL level
+To enable/disable the classification of the solids in DRAW, it is necessary to call the *bcheckinverted* command with appropriate value:
+* 0 - disabling the classification;
+* 1 - default value, enabling the classification.
+
+~~~~
+bcheckinverted 0
+~~~~
+
+
 @section occt_algorithms_ers Errors and warnings reporting system
 
 The chapter describes the Error/Warning reporting system of the algorithms in the Boolean Component.
index f576009e91d9a48fe1ec0f6ca7cb982a45c9c7bb..7dfd5c54afb91d17e4e1dd37ea92c7bdf01e2e40 100644 (file)
@@ -25,6 +25,7 @@
 #include <BOPCol_DataMapOfShapeListOfShape.hxx>
 #include <BOPCol_DataMapOfShapeShape.hxx>
 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
+#include <BOPCol_IndexedDataMapOfShapeShape.hxx>
 #include <BOPCol_ListOfShape.hxx>
 #include <BOPCol_MapOfShape.hxx>
 #include <BOPCol_MapOfOrientedShape.hxx>
@@ -50,6 +51,7 @@
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
 #include <TopLoc_Location.hxx>
+#include <TopoDS.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopoDS_Face.hxx>
 #include <TopoDS_Iterator.hxx>
@@ -69,65 +71,7 @@ static
 static
   void MakeInternalWires(const BOPCol_IndexedMapOfShape& ,
                          BOPCol_ListOfShape& );
-static 
-  void GetWire(const TopoDS_Shape& , 
-        TopoDS_Shape& ); 
-//
-
-//
-//=======================================================================
-//class     : BOPAlgo_ShapeBox2D
-//purpose   : Auxiliary class
-//=======================================================================
-class BOPAlgo_ShapeBox2D {
- public:
-  BOPAlgo_ShapeBox2D() {
-    myIsHole=Standard_False;
-  };
-  //
-  ~BOPAlgo_ShapeBox2D() {
-  };
-  //
-  void SetShape(const TopoDS_Shape& aS) {
-    myShape=aS;
-  };
-  //
-  const TopoDS_Shape& Shape()const {
-    return myShape;
-  };
-  //
-  void SetBox2D(const Bnd_Box2d& aBox2D) {
-    myBox2D=aBox2D;
-  };
-  //
-  const Bnd_Box2d& Box2D()const {
-    return myBox2D;
-  };
-  //
-  void SetIsHole(const Standard_Boolean bFlag) {
-    myIsHole=bFlag;
-  };
-  //
-  Standard_Boolean IsHole()const {
-    return myIsHole;
-  };
-  //
- protected:
-  Standard_Boolean myIsHole;
-  TopoDS_Shape myShape;
-  Bnd_Box2d myBox2D;
-};
-//
-typedef NCollection_IndexedDataMap 
-  <Standard_Integer, 
-  BOPAlgo_ShapeBox2D, 
-  TColStd_MapIntegerHasher>  BOPAlgo_IndexedDataMapOfIntegerShapeBox2D; 
 
-typedef NCollection_IndexedDataMap 
-  <TopoDS_Shape, 
-  TopoDS_Shape, 
-  TopTools_ShapeMapHasher> BOPCol_IndexedDataMapOfShapeShape; 
-//
 //=======================================================================
 //function : 
 //purpose  : 
@@ -436,239 +380,198 @@ void BOPAlgo_BuilderFace::PerformLoops()
 //=======================================================================
 void BOPAlgo_BuilderFace::PerformAreas()
 {
-  Standard_Boolean bIsGrowth, bIsHole;
-  Standard_Integer k, aNbS, aNbHoles, aNbDMISB, m, aNbMSH, aNbInOutMap;
-  Standard_Real aTol;
-  TopLoc_Location aLoc;
-  Handle(Geom_Surface) aS;
-  BRep_Builder aBB;
-  TopoDS_Face aFace;
-  BOPCol_ListIteratorOfListOfInteger aItLI;
-  BOPCol_IndexedMapOfShape aMHE;
-  BOPCol_ListIteratorOfListOfShape aIt1;
-  BOPCol_IndexedDataMapOfShapeListOfShape aMSH;
-  BOPCol_IndexedDataMapOfShapeShape aInOutMap;
-  BOPAlgo_IndexedDataMapOfIntegerShapeBox2D aDMISB(100);
-  //
-  BOPCol_Box2DBndTreeSelector aSelector;
-  BOPCol_Box2DBndTree aBBTree;
-  NCollection_UBTreeFiller <Standard_Integer, Bnd_Box2d> aTreeFiller(aBBTree);
-  //
-  aNbHoles=0;
-  //
-  aTol=BRep_Tool::Tolerance(myFace);
-  aS=BRep_Tool::Surface(myFace, aLoc);
-  //
   myAreas.Clear();
-  //
-  if (myLoops.IsEmpty()) {
-    if (myContext->IsInfiniteFace(myFace)) {
+  BRep_Builder aBB;
+  // Location of the myFace
+  TopLoc_Location aLoc;
+  // Get surface from myFace
+  const Handle(Geom_Surface)& aS = BRep_Tool::Surface(myFace, aLoc);
+  // Get tolerance of myFace
+  Standard_Real aTol = BRep_Tool::Tolerance(myFace);
+
+  // Check if there are no loops at all
+  if (myLoops.IsEmpty())
+  {
+    if (myContext->IsInfiniteFace(myFace))
+    {
+      TopoDS_Face aFace;
       aBB.MakeFace(aFace, aS, aLoc, aTol);
-      if (BRep_Tool::NaturalRestriction(myFace)) {
+      if (BRep_Tool::NaturalRestriction(myFace))
         aBB.NaturalRestriction(aFace, Standard_True);
-      }
-      myAreas.Append(aFace); 
+      myAreas.Append(aFace);
     }
     return;
   }
-  //
-  // 1. Growthes and Holes -> aDMISB: [Index/ShapeBox2D]
-  aIt1.Initialize(myLoops);
-  for (k=0 ; aIt1.More(); aIt1.Next(), ++k) {
-    Bnd_Box2d aBox2D;
-    //
-    const TopoDS_Shape& aWire=aIt1.Value();
-    //
+
+  // The new faces
+  BOPCol_ListOfShape aNewFaces;
+  // The hole faces which has to be classified relatively new faces
+  BOPCol_IndexedMapOfShape aHoleFaces;
+  // Map of the edges of the hole faces for quick check of the growths.
+  // If the analyzed wire contains any of the edges from the hole faces
+  // it is considered as growth.
+  BOPCol_IndexedMapOfShape aMHE;
+
+  // Analyze the new wires - classify them to be the holes and growths
+  BOPCol_ListIteratorOfListOfShape aItLL(myLoops);
+  for (; aItLL.More(); aItLL.Next())
+  {
+    const TopoDS_Shape& aWire = aItLL.Value();
+
+    TopoDS_Face aFace;
     aBB.MakeFace(aFace, aS, aLoc, aTol);
-    aBB.Add (aFace, aWire);
-    BRepTools::AddUVBounds(aFace, aBox2D);
-    //
-    bIsGrowth=IsGrowthWire(aWire, aMHE);
-    if (bIsGrowth) {
-      bIsHole=Standard_False;
+    aBB.Add(aFace, aWire);
+
+    Standard_Boolean bIsGrowth = IsGrowthWire(aWire, aMHE);
+    if (!bIsGrowth)
+    {
+      // Fast check did not give the result, run classification
+      IntTools_FClass2d& aClsf = myContext->FClass2d(aFace);
+      bIsGrowth = !aClsf.IsHole();
     }
-    else{
-      // check if a wire is a hole 
-      IntTools_FClass2d& aClsf=myContext->FClass2d(aFace);
-      aClsf.Init(aFace, aTol);
-      //
-      bIsHole=aClsf.IsHole();
-      if (bIsHole) {
-        BOPTools::MapShapes(aWire, TopAbs_EDGE, aMHE);
-        //
-        bIsHole=Standard_True;
-      }
-      else {
-        bIsHole=Standard_False;
-      }
+
+    // Save the face
+    if (bIsGrowth)
+    {
+      aNewFaces.Append(aFace);
     }
-    //
-    BOPAlgo_ShapeBox2D aSB2D;
-    //
-    aSB2D.SetShape(aFace);
-    aSB2D.SetBox2D(aBox2D);
-    aSB2D.SetIsHole(bIsHole);
-    //
-    aDMISB.Add(k, aSB2D);
-  }// for (k=0 ; aIt1.More(); aIt1.Next(), ++k) {
-  //
-  // 2. Prepare TreeFiller
-  aNbDMISB=aDMISB.Extent();
-  for (m=1; m<=aNbDMISB; ++m) { 
-    k=aDMISB.FindKey(m);
-    const BOPAlgo_ShapeBox2D& aSB2D=aDMISB.FindFromIndex(m);
-    //
-    bIsHole=aSB2D.IsHole();
-    if (bIsHole) {
-      const Bnd_Box2d& aBox2D=aSB2D.Box2D();
-      aTreeFiller.Add(k, aBox2D);
-      ++aNbHoles;
+    else
+    {
+      aHoleFaces.Add(aFace);
+      BOPTools::MapShapes(aWire, TopAbs_EDGE, aMHE);
     }
   }
-  //
-  // 3. Shake TreeFiller
-  aTreeFiller.Fill();
-  //
-  // 4. Find outer growth shell that is most close 
-  //    to each hole shell
-  for (m=1; m<=aNbDMISB; ++m) {
-    const BOPAlgo_ShapeBox2D& aSB2D=aDMISB.FindFromIndex(m);
-    bIsHole=aSB2D.IsHole();
-    if (bIsHole) {
-      continue;
-    }
-    //
-    const Bnd_Box2d& aBox2DF=aSB2D.Box2D();
-    const TopoDS_Shape aF=aSB2D.Shape();
-    //
-    aSelector.Clear();
-    aSelector.SetBox(aBox2DF);
-    //
-    aNbS = aBBTree.Select(aSelector);
-    if (!aNbS) {
-      continue;
-    }
-    //
-    const BOPCol_ListOfInteger& aLI=aSelector.Indices();
+
+  if (aHoleFaces.IsEmpty())
+  {
+    // No holes, stop the analysis
+    myAreas.Append(aNewFaces);
+  }
+
+  // Classify holes relatively faces
+
+  // Prepare tree filler with the boxes of the hole faces
+  BOPCol_Box2DBndTree aBBTree;
+  NCollection_UBTreeFiller <Standard_Integer, Bnd_Box2d> aTreeFiller(aBBTree);
+
+  Standard_Integer i, aNbH = aHoleFaces.Extent();
+  for (i = 1; i <= aNbH; ++i)
+  {
+    const TopoDS_Face& aHFace = TopoDS::Face(aHoleFaces(i));
     //
-    aItLI.Initialize(aLI);
-    for (; aItLI.More(); aItLI.Next()) {
-      k=aItLI.Value();
-      const BOPAlgo_ShapeBox2D& aSB2Dk=aDMISB.FindFromKey(k);
-      const TopoDS_Shape& aHole=aSB2Dk.Shape();
-      //
-      if (!IsInside(aHole, aF, myContext)){
+    Bnd_Box2d aBox;
+    BRepTools::AddUVBounds(aHFace, aBox);
+    aTreeFiller.Add(i, aBox);
+  }
+
+  // Shake TreeFiller
+  aTreeFiller.Fill();
+
+  // Find outer growth face that is most close to each hole face
+  BOPCol_IndexedDataMapOfShapeShape aHoleFaceMap;
+
+  BOPCol_ListIteratorOfListOfShape aItLS(aNewFaces);
+  for (; aItLS.More(); aItLS.Next())
+  {
+    const TopoDS_Face& aFace = TopoDS::Face(aItLS.Value());
+
+    // Build box
+    Bnd_Box2d aBox;
+    BRepTools::AddUVBounds(aFace, aBox);
+
+    BOPCol_Box2DBndTreeSelector aSelector;
+    aSelector.SetBox(aBox);
+    aBBTree.Select(aSelector);
+
+    const BOPCol_ListOfInteger& aLI = aSelector.Indices();
+    BOPCol_ListIteratorOfListOfInteger aItLI(aLI);
+    for (; aItLI.More(); aItLI.Next())
+    {
+      Standard_Integer k = aItLI.Value();
+      const TopoDS_Shape& aHole = aHoleFaces(k);
+      // Check if it is inside
+      if (!IsInside(aHole, aFace, myContext))
         continue;
-      }
-      //
-      if (aInOutMap.Contains(aHole)){
-        TopoDS_Shape& aF2=aInOutMap.ChangeFromKey(aHole);
-        if (IsInside(aF, aF2, myContext)) {
-          aF2=aF;
+
+      // Save the relation
+      TopoDS_Shape* pFaceWas = aHoleFaceMap.ChangeSeek(aHole);
+      if (pFaceWas)
+      {
+        if (IsInside(aFace, *pFaceWas, myContext))
+        {
+          *pFaceWas = aFace;
         }
       }
-      else{
-        aInOutMap.Add(aHole, aF);
+      else
+      {
+        aHoleFaceMap.Add(aHole, aFace);
       }
     }
-  }// for (m=1; m<=aNbDMISB; ++m)
-  //
-  // 5.1 Map [Face/Holes] -> aMSH 
-  aNbInOutMap=aInOutMap.Extent();
-  for (m=1; m<=aNbInOutMap; ++m) {
-    const TopoDS_Shape& aHole=aInOutMap.FindKey(m);
-    const TopoDS_Shape& aF=aInOutMap.FindFromIndex(m);
+  }
+
+  // Make the back map from faces to holes
+  BOPCol_IndexedDataMapOfShapeListOfShape aFaceHolesMap;
+
+  aNbH = aHoleFaceMap.Extent();
+  for (i = 1; i <= aNbH; ++i)
+  {
+    const TopoDS_Shape& aHole = aHoleFaceMap.FindKey(i);
+    const TopoDS_Shape& aFace = aHoleFaceMap(i);
     //
-    if (aMSH.Contains(aF)) {
-      BOPCol_ListOfShape& aLH=aMSH.ChangeFromKey(aF);
-      aLH.Append(aHole);
-    }
-    else {
-      BOPCol_ListOfShape aLH;
-      aLH.Append(aHole);
-      aMSH.Add(aF, aLH);
-    }
+    BOPCol_ListOfShape* pLHoles = aFaceHolesMap.ChangeSeek(aFace);
+    if (!pLHoles)
+      pLHoles = &aFaceHolesMap(aFaceHolesMap.Add(aFace, BOPCol_ListOfShape()));
+    pLHoles->Append(aHole);
   }
-  //
-  // 5.2. Add unused holes to the original face
-  if (aNbHoles != aNbInOutMap) {
+
+  // Add unused holes to the original face
+  if (aHoleFaces.Extent() != aHoleFaceMap.Extent())
+  {
     Bnd_Box aBoxF;
     BRepBndLib::Add(myFace, aBoxF);
     if (aBoxF.IsOpenXmin() || aBoxF.IsOpenXmax() ||
         aBoxF.IsOpenYmin() || aBoxF.IsOpenYmax() ||
-        aBoxF.IsOpenZmin() || aBoxF.IsOpenZmax()) {
-      //
-      BOPCol_ListOfShape anUnUsedHoles;
-      for (m = 1; m <= aNbDMISB; ++m) {
-        const BOPAlgo_ShapeBox2D& aSB2D=aDMISB.FindFromIndex(m);
-        if (aSB2D.IsHole()) {
-          const TopoDS_Shape& aHole = aSB2D.Shape();
-          if (!aInOutMap.Contains(aHole)) {
-            anUnUsedHoles.Append(aHole);
-          }
-        }
-      }
-      //
-      if (anUnUsedHoles.Extent()) {
-        aBB.MakeFace(aFace, aS, aLoc, aTol);
-        aMSH.Add(aFace, anUnUsedHoles);
-        //
-        BOPAlgo_ShapeBox2D aSB2D;
-        //
-        aSB2D.SetShape(aFace);
-        aSB2D.SetIsHole(Standard_False);
-        //
-        aDMISB.Add(aNbDMISB, aSB2D);
-        ++aNbDMISB;
+        aBoxF.IsOpenZmin() || aBoxF.IsOpenZmax())
+    {
+      TopoDS_Face aFace;
+      aBB.MakeFace(aFace, aS, aLoc, aTol);
+      BOPCol_ListOfShape& anUnUsedHoles = aFaceHolesMap(aFaceHolesMap.Add(aFace, BOPCol_ListOfShape()));
+      aNbH = aHoleFaces.Extent();
+      for (i = 1; i <= aNbH; ++i)
+      {
+        const TopoDS_Shape& aHole = aHoleFaces(i);
+        if (!aHoleFaceMap.Contains(aHole))
+          anUnUsedHoles.Append(aHole);
       }
+      // Save it
+      aNewFaces.Append(aFace);
     }
   }
-  //
-  // 6. Add aHoles to Faces
-  aNbMSH=aMSH.Extent();
-  for (m=1; m<=aNbMSH; ++m) {
-    TopoDS_Face aF=(*(TopoDS_Face *)(&aMSH.FindKey(m)));
-    const BOPCol_ListOfShape& aLH=aMSH.FindFromIndex(m);
-    //
-    aIt1.Initialize(aLH);
-    for (; aIt1.More(); aIt1.Next()) {
-      TopoDS_Shape aWHole;
-      //
-      const TopoDS_Shape& aFHole=aIt1.Value();
-      GetWire(aFHole, aWHole);
-      aBB.Add (aF, aWHole);
-    }
-    //
-    // update classifier 
-    aTol=BRep_Tool::Tolerance(aF);
-    IntTools_FClass2d& aClsf=myContext->FClass2d(aF);
-    aClsf.Init(aF, aTol);
-  }
-  //
-  // 7. Fill myAreas
-  //    NB:These aNewFaces are draft faces that 
-  //    do not contain any internal shapes
-  for (m=1; m<=aNbDMISB; ++m) {
-    const BOPAlgo_ShapeBox2D& aSB2D=aDMISB.FindFromIndex(m);
-    bIsHole=aSB2D.IsHole();
-    if (!bIsHole) {
-      const TopoDS_Shape aF=aSB2D.Shape();
-      myAreas.Append(aF);
+
+  // Add Holes to Faces and add them to myAreas
+  aItLS.Initialize(aNewFaces);
+  for ( ; aItLS.More(); aItLS.Next())
+  {
+    TopoDS_Face& aFace = *(TopoDS_Face*)&aItLS.Value();
+    const BOPCol_ListOfShape* pLHoles = aFaceHolesMap.Seek(aFace);
+    if (pLHoles)
+    {
+      // update faces with the holes
+      BOPCol_ListIteratorOfListOfShape aItLH(*pLHoles);
+      for (; aItLH.More(); aItLH.Next())
+      {
+        const TopoDS_Shape& aFHole = aItLH.Value();
+        // The hole face contains only one wire
+        TopoDS_Iterator aItW(aFHole);
+        aBB.Add(aFace, aItW.Value());
+      }
+
+      // update classifier
+      myContext->FClass2d(aFace).Init(aFace, aTol);
     }
-  }
-}
-//=======================================================================
-//function : GetWire
-//purpose  : 
-//=======================================================================
-void GetWire(const TopoDS_Shape& aF, TopoDS_Shape& aW) 
-{
-  TopoDS_Shape aWx;
-  TopoDS_Iterator aIt;
-  //
-  aIt.Initialize(aF);
-  for (; aIt.More(); aIt.Next()) {
-    aW=aIt.Value();
+
+    // The face is just a draft that does not contain any internal shapes
+    myAreas.Append(aFace);
   }
 }
 //=======================================================================
@@ -851,18 +754,14 @@ Standard_Boolean IsInside(const TopoDS_Shape& theHole,
 Standard_Boolean IsGrowthWire(const TopoDS_Shape& theWire,
                               const BOPCol_IndexedMapOfShape& theMHE)
 {
-  Standard_Boolean bRet;
-  TopoDS_Iterator aIt;
-  // 
-  bRet=Standard_False;
-  if (theMHE.Extent()) {
-    aIt.Initialize(theWire);
-    for(; aIt.More(); aIt.Next()) {
-      const TopoDS_Shape& aE=aIt.Value();
-      if (theMHE.Contains(aE)) {
-        return !bRet;
-      }
+  if (theMHE.Extent())
+  {
+    TopoDS_Iterator aIt(theWire);
+    for(; aIt.More(); aIt.Next())
+    {
+      if (theMHE.Contains(aIt.Value()))
+        return Standard_True;
     }
   }
-  return bRet;
+  return Standard_False;
 }
index fa19419e773f4c7576d0f365d345b526a1be81cb..ce3ac3236e0c1ceff331d54dc45f717f1642d7cb 100644 (file)
@@ -77,57 +77,6 @@ static
   void MakeInternalShells(const BOPCol_IndexedMapOfShape& ,
                           BOPCol_ListOfShape& );
 
-//=======================================================================
-//class     : BOPAlgo_BuilderSolid_ShapeBox
-//purpose   : Auxiliary class
-//=======================================================================
-class BOPAlgo_BuilderSolid_ShapeBox {
- public:
-  BOPAlgo_BuilderSolid_ShapeBox() {
-    myIsHole=Standard_False;
-  };
-  //
-  ~BOPAlgo_BuilderSolid_ShapeBox() {
-  };
-  //
-  void SetShape(const TopoDS_Shape& aS) {
-    myShape=aS;
-  };
-  //
-  const TopoDS_Shape& Shape()const {
-    return myShape;
-  };
-  //
-  void SetBox(const Bnd_Box& aBox) {
-    myBox=aBox;
-  };
-  //
-  const Bnd_Box& Box()const {
-    return myBox;
-  };
-  //
-  void SetIsHole(const Standard_Boolean bFlag) {
-    myIsHole=bFlag;
-  };
-  //
-  Standard_Boolean IsHole()const {
-    return myIsHole;
-  };
-  //
- protected:
-  Standard_Boolean myIsHole;
-  TopoDS_Shape myShape;
-  Bnd_Box myBox;
-};
-//
-typedef NCollection_DataMap
-  <Standard_Integer, 
-  BOPAlgo_BuilderSolid_ShapeBox, 
-  TColStd_MapIntegerHasher> BOPAlgo_DataMapOfIntegerBSSB; 
-//
-typedef BOPAlgo_DataMapOfIntegerBSSB::Iterator 
-  BOPAlgo_DataMapIteratorOfDataMapOfIntegerBSSB; 
-//
 //=======================================================================
 //function : BOPAlgo_FacePnt
 //purpose  : 
@@ -300,6 +249,9 @@ void BOPAlgo_BuilderSolid::Perform()
 {
   GetReport()->Clear();
   //
+  if (myShapes.IsEmpty())
+    return;
+
   if (myContext.IsNull()) {
     myContext=new IntTools_Context;
   }
@@ -572,178 +524,158 @@ void BOPAlgo_BuilderSolid::PerformLoops()
 //=======================================================================
 void BOPAlgo_BuilderSolid::PerformAreas()
 {
-  Standard_Boolean bIsGrowth, bIsHole;
-  Standard_Integer i, k, aNbInOut, aNbMSH;
-  BRep_Builder aBB; 
-  BOPCol_ListIteratorOfListOfShape aItLS;
-  BOPCol_ListOfShape aNewSolids, aHoleShells; 
-  BOPCol_IndexedDataMapOfShapeShape aInOutMap;
-  BOPCol_IndexedMapOfShape aMHF;
-  BOPCol_ListIteratorOfListOfInteger aItLI;
-  BOPCol_BoxBndTreeSelector aSelector;
-  BOPCol_BoxBndTree aBBTree;
-  NCollection_UBTreeFiller 
-    <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
-  BOPAlgo_DataMapOfIntegerBSSB aDMISB(100);
-  BOPCol_IndexedDataMapOfShapeListOfShape aMSH;
-  BOPAlgo_DataMapIteratorOfDataMapOfIntegerBSSB aItDMISB;
-  //
   myAreas.Clear();
-  //
-  //  Draft solids [aNewSolids]
-  aItLS.Initialize(myLoops);
-  for (k=0; aItLS.More(); aItLS.Next(), ++k) {
-    TopoDS_Solid aSolid;
-    Bnd_Box aBox;
-    BOPAlgo_BuilderSolid_ShapeBox aSB;
-    //
-    const TopoDS_Shape& aShell = aItLS.Value();
-    aSB.SetShape(aShell);
-    //
-    BRepBndLib::Add(aShell, aBox);
-    bIsHole=Standard_False;
-    //
-    bIsGrowth=IsGrowthShell(aShell, aMHF);
-    if (bIsGrowth) {
-      // make a growth solid from a shell
+  BRep_Builder aBB;
+  // The new solids
+  BOPCol_ListOfShape aNewSolids;
+  // The hole shells which has to be classified relatively new solids
+  BOPCol_IndexedMapOfShape aHoleShells;
+  // Map of the faces of the hole shells for quick check of the growths.
+  // If the analyzed shell contains any of the hole faces, it is considered as growth.
+  BOPCol_IndexedMapOfShape aMHF;
+
+  // Analyze the shells
+  BOPCol_ListIteratorOfListOfShape aItLL(myLoops);
+  for (; aItLL.More(); aItLL.Next())
+  {
+    const TopoDS_Shape& aShell = aItLL.Value();
+
+    Standard_Boolean bIsGrowth = IsGrowthShell(aShell, aMHF);
+    if (!bIsGrowth)
+    {
+      // Fast check did not give the result, run classification
+      bIsGrowth = !IsHole(aShell, myContext);
+    }
+
+    // Save the solid
+    if (bIsGrowth)
+    {
+      TopoDS_Solid aSolid;
       aBB.MakeSolid(aSolid);
       aBB.Add (aSolid, aShell);
-      //
       aNewSolids.Append (aSolid);
-      aSB.SetShape(aSolid);
     }
-    else{
-      // check if a shell is a hole
-      bIsHole=IsHole(aShell, myContext);
-      if (bIsHole) {
-        aHoleShells.Append(aShell);
-        BOPTools::MapShapes(aShell, TopAbs_FACE, aMHF);
-        aSB.SetShape(aShell);
-      }
-      else {
-        // make a growth solid from a shell
-        aBB.MakeSolid(aSolid);
-        aBB.Add (aSolid, aShell);
-        //
-        aNewSolids.Append (aSolid);
-        aSB.SetShape(aSolid);
-      }
+    else
+    {
+      aHoleShells.Add(aShell);
+      BOPTools::MapShapes(aShell, TopAbs_FACE, aMHF);
     }
+  }
+
+  if (aHoleShells.IsEmpty())
+  {
+    // No holes, stop the analysis
+    myAreas.Append(aNewSolids);
+    return;
+  }
+
+  // Classify holes relatively solids
+
+  // Prepare tree filler with the boxes of the hole shells
+  BOPCol_BoxBndTree aBBTree;
+  NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
+
+  Standard_Integer i, aNbH = aHoleShells.Extent();
+  for (i = 1; i <= aNbH; ++i)
+  {
+    const TopoDS_Shape& aHShell = aHoleShells(i);
     //
-    aSB.SetBox(aBox);
-    aSB.SetIsHole(bIsHole);
-    aDMISB.Bind(k, aSB);
-  }  
-  //
-  // 2. Prepare TreeFiller
-  aItDMISB.Initialize(aDMISB);
-  for (; aItDMISB.More(); aItDMISB.Next()) {
-    k=aItDMISB.Key();
-    const BOPAlgo_BuilderSolid_ShapeBox& aSB=aItDMISB.Value();
-    //
-    bIsHole=aSB.IsHole();
-    if (bIsHole) {
-      const Bnd_Box& aBox=aSB.Box();
-      aTreeFiller.Add(k, aBox);
-    }
+    Bnd_Box aBox;
+    BRepBndLib::Add(aHShell, aBox);
+    aTreeFiller.Add(i, aBox);
   }
-  //
-  // 3. Shake TreeFiller
+
+  // Shake TreeFiller
   aTreeFiller.Fill();
-  //
-  // 4. Find outer growth shell that is most close 
-  //    to each hole shell
-  aItDMISB.Initialize(aDMISB);
-  for (; aItDMISB.More(); aItDMISB.Next()) {
-    k=aItDMISB.Key();
-    const BOPAlgo_BuilderSolid_ShapeBox& aSB=aItDMISB.Value();
-    bIsHole=aSB.IsHole();
-    if (bIsHole) {
-      continue;
-    }
-    //
-    const TopoDS_Shape aSolid=aSB.Shape();
-    const Bnd_Box& aBoxSolid=aSB.Box();
-    //
-    aSelector.Clear();
-    aSelector.SetBox(aBoxSolid);
-    //
+
+  // Find outer growth shell that is most close to each hole shell
+  BOPCol_IndexedDataMapOfShapeShape aHoleSolidMap;
+
+  BOPCol_ListIteratorOfListOfShape aItLS(aNewSolids);
+  for (; aItLS.More(); aItLS.Next())
+  {
+    const TopoDS_Shape& aSolid = aItLS.Value();
+
+    // Build box
+    Bnd_Box aBox;
+    BRepBndLib::Add(aSolid, aBox);
+
+    BOPCol_BoxBndTreeSelector aSelector;
+    aSelector.SetBox(aBox);
     aBBTree.Select(aSelector);
-    //
-    const BOPCol_ListOfInteger& aLI=aSelector.Indices();
-    //
-    aItLI.Initialize(aLI);
-    for (; aItLI.More(); aItLI.Next()) {
-      k=aItLI.Value();
-      const BOPAlgo_BuilderSolid_ShapeBox& aSBk=aDMISB.Find(k);
-      const TopoDS_Shape& aHole=aSBk.Shape();
-      //
-      if (!IsInside(aHole, aSolid, myContext)){
+
+    const BOPCol_ListOfInteger& aLI = aSelector.Indices();
+    BOPCol_ListIteratorOfListOfInteger aItLI(aLI);
+    for (; aItLI.More(); aItLI.Next())
+    {
+      Standard_Integer k = aItLI.Value();
+      const TopoDS_Shape& aHole = aHoleShells(k);
+      // Check if it is inside
+      if (!IsInside(aHole, aSolid, myContext))
         continue;
-      }
-      //
-      if (aInOutMap.Contains (aHole)){
-        const TopoDS_Shape& aSolidWas = aInOutMap.FindFromKey(aHole);
-        if (IsInside(aSolid, aSolidWas, myContext)) {
-          aInOutMap.ChangeFromKey(aHole) = aSolid;
+
+      // Save the relation
+      TopoDS_Shape* pSolidWas = aHoleSolidMap.ChangeSeek(aHole);
+      if (pSolidWas)
+      {
+        if (IsInside(aSolid, *pSolidWas, myContext))
+        {
+          *pSolidWas = aSolid;
         }
       }
-      else{
-        aInOutMap.Add(aHole, aSolid);
+      else
+      {
+        aHoleSolidMap.Add(aHole, aSolid);
       }
     }
-  }//for (i = 1; i <= aNbDMISB; ++i) {
-  //
-  // 5. Map [Solid/Holes] -> aMSH 
-  aNbInOut = aInOutMap.Extent();
-  for (i = 1; i <= aNbInOut; ++i) {
-    const TopoDS_Shape& aHole = aInOutMap.FindKey(i);
-    const TopoDS_Shape& aSolid = aInOutMap(i);
-    //
-    if (aMSH.Contains(aSolid)) {
-      BOPCol_ListOfShape& aLH = aMSH.ChangeFromKey(aSolid);
-      aLH.Append(aHole);
-    }
-    else {
-      BOPCol_ListOfShape aLH;
-      aLH.Append(aHole);
-      aMSH.Add(aSolid, aLH);
-    }
   }
-  //
-  // 6. Add aHoles to Solids
-  aNbMSH = aMSH.Extent();
-  for (i = 1; i <= aNbMSH; ++i) {
-    TopoDS_Solid aSolid=(*(TopoDS_Solid*)(&(aMSH.FindKey(i))));
-    const BOPCol_ListOfShape& aLH = aMSH(i);
-    //
-    aItLS.Initialize(aLH);
-    for (; aItLS.More(); aItLS.Next()) {
-      const TopoDS_Shape& aHole = aItLS.Value();
-      aBB.Add (aSolid, aHole);
-    }
-    //
-    // update classifier
-    BRepClass3d_SolidClassifier& aSC=
-      myContext->SolidClassifier(aSolid);
-    aSC.Load(aSolid);
+
+  // Make the back map from solids to holes
+  BOPCol_IndexedDataMapOfShapeListOfShape aSolidHolesMap;
+
+  aNbH = aHoleSolidMap.Extent();
+  for (i = 1; i <= aNbH; ++i)
+  {
+    const TopoDS_Shape& aHole = aHoleSolidMap.FindKey(i);
+    const TopoDS_Shape& aSolid = aHoleSolidMap(i);
     //
+    BOPCol_ListOfShape* pLHoles = aSolidHolesMap.ChangeSeek(aSolid);
+    if (!pLHoles)
+      pLHoles = &aSolidHolesMap(aSolidHolesMap.Add(aSolid, BOPCol_ListOfShape()));
+    pLHoles->Append(aHole);
   }
-  //
-  // 7. These aNewSolids are draft solids that 
-  // do not contain any internal shapes
+
+  // Add Holes to Solids and add them to myAreas
   aItLS.Initialize(aNewSolids);
-  for ( ; aItLS.More(); aItLS.Next()) {
-    const TopoDS_Shape& aSx=aItLS.Value();
-    myAreas.Append(aSx);
+  for ( ; aItLS.More(); aItLS.Next())
+  {
+    TopoDS_Solid& aSolid = *(TopoDS_Solid*)&aItLS.Value();
+    const BOPCol_ListOfShape* pLHoles = aSolidHolesMap.Seek(aSolid);
+    if (pLHoles)
+    {
+      // update solid
+      BOPCol_ListIteratorOfListOfShape aItLH(*pLHoles);
+      for (; aItLH.More(); aItLH.Next())
+      {
+        const TopoDS_Shape& aHole = aItLH.Value();
+        aBB.Add(aSolid, aHole);
+      }
+
+      // update classifier
+      myContext->SolidClassifier(aSolid).Load(aSolid);
+    }
+
+    myAreas.Append(aSolid);
   }
+
   // Add holes that outside the solids to myAreas
-  aItLS.Initialize(aHoleShells);
-  for (; aItLS.More(); aItLS.Next()) {
-    const TopoDS_Shape& aHole = aItLS.Value();
-    if (!aInOutMap.Contains(aHole)){
+  aNbH = aHoleShells.Extent();
+  for (i = 1; i <= aNbH; ++i)
+  {
+    const TopoDS_Shape& aHole = aHoleShells(i);
+    if (!aHoleSolidMap.Contains(aHole))
+    {
       TopoDS_Solid aSolid;
-      //
       aBB.MakeSolid(aSolid);
       aBB.Add (aSolid, aHole);
       //
@@ -1073,18 +1005,14 @@ Standard_Boolean IsInside(const TopoDS_Shape& theS1,
 Standard_Boolean IsGrowthShell(const TopoDS_Shape& theShell,
                                const BOPCol_IndexedMapOfShape& theMHF)
 {
-  Standard_Boolean bRet;
-  TopoDS_Iterator aIt;
-  // 
-  bRet=Standard_False;
-  if (theMHF.Extent()) {
-    aIt.Initialize(theShell);
-    for(; aIt.More(); aIt.Next()) {
-      const TopoDS_Shape& aF=aIt.Value();
-      if (theMHF.Contains(aF)) {
-        return !bRet;
-      }
+  if (theMHF.Extent())
+  {
+    TopoDS_Iterator aIt(theShell);
+    for(; aIt.More(); aIt.Next())
+    {
+      if (theMHF.Contains(aIt.Value()))
+        return Standard_True;
     }
   }
-  return bRet;
+  return Standard_False;
 }
index e70c957cea1902425959ac18712552aa1e6d86fb..293841bc3a8aa7b7d673896725e847c31e91a5ce 100644 (file)
@@ -51,6 +51,7 @@
 #include <Precision.hxx>
 #include <IntTools_Context.hxx>
 #include <TopExp_Explorer.hxx>
+#include <TopoDS.hxx>
 #include <TopoDS_Compound.hxx>
 #include <TopoDS_Edge.hxx>
 #include <TopoDS_Face.hxx>
@@ -62,6 +63,11 @@ static
   Standard_Boolean HasPaveBlocksOnIn(const BOPDS_FaceInfo& aFI1,
                                      const BOPDS_FaceInfo& aFI2);
 //
+static
+  TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
+                             const BOPCol_DataMapOfShapeListOfShape& theImages,
+                             Handle(IntTools_Context)& theCtx);
+//
 typedef BOPCol_NCVector<TopoDS_Shape> BOPAlgo_VectorOfShape;
 //
 typedef BOPCol_NCVector<BOPAlgo_VectorOfShape> \
@@ -240,7 +246,6 @@ void BOPAlgo_Builder::BuildSplitFaces()
 {
   Standard_Boolean bHasFaceInfo, bIsClosed, bIsDegenerated, bToReverse;
   Standard_Integer i, j, k, aNbS, aNbPBIn, aNbPBOn, aNbPBSc, aNbAV, nSp;
-  Standard_Size aNbBF;
   TopoDS_Face aFF, aFSD;
   TopoDS_Edge aSp, aEE;
   TopAbs_Orientation anOriF, anOriE;
@@ -249,7 +254,6 @@ void BOPAlgo_Builder::BuildSplitFaces()
   BOPCol_ListOfInteger aLIAV;
   BOPCol_MapOfShape aMFence;
   Handle(NCollection_BaseAllocator) aAllocator;
-  BOPCol_ListOfShape aLFIm(myAllocator);
   BOPAlgo_VectorOfBuilderFace aVBF;
   //
   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~scope f
@@ -259,6 +263,10 @@ void BOPAlgo_Builder::BuildSplitFaces()
   BOPCol_ListOfShape aLE(aAllocator);
   BOPCol_MapOfShape aMDE(100, aAllocator);
   //
+  // Build temporary map of faces images to avoid rebuilding
+  // of the faces without any IN or section edges
+  BOPCol_IndexedDataMapOfShapeListOfShape aFacesIm;
+  //
   aNbS=myDS->NbSourceShapes();
   //
   for (i=0; i<aNbS; ++i) {
@@ -292,17 +300,32 @@ void BOPAlgo_Builder::BuildSplitFaces()
     if (!aNbPBIn && !aNbPBOn && !aNbPBSc && !aNbAV) { // not compete
       continue;
     }
-    //
+
+    if (!aNbPBIn && !aNbPBSc)
+    {
+      // No internal parts for the face, so just build the draft face
+      // and keep it to pass directly into result.
+      // If the original face has any internal edges, the draft face
+      // will be null, as the internal edges may split the face on parts
+      // (as in the case "bugs modalg_5 bug25245_1").
+      // The BuilderFace algorithm will be called in this case.
+      TopoDS_Face aFD = BuildDraftFace(aF, myImages, myContext);
+      if (!aFD.IsNull())
+      {
+        aFacesIm(aFacesIm.Add(aF, BOPCol_ListOfShape())).Append(aFD);
+        continue;
+      }
+    }
+
     aMFence.Clear();
     //
     anOriF=aF.Orientation();
     aFF=aF;
     aFF.Orientation(TopAbs_FORWARD);
     //
-    // 1. Fill the egdes set for the face aFF -> LE
+    // 1. Fill the edges set for the face aFF -> LE
     aLE.Clear();
-    //
-    //
+
     // 1.1 Bounding edges
     aExp.Init(aFF, TopAbs_EDGE);
     for (; aExp.More(); aExp.Next()) {
@@ -426,33 +449,33 @@ void BOPAlgo_Builder::BuildSplitFaces()
     //
   }// for (i=0; i<aNbS; ++i) {
   //
-  aNbBF=aVBF.Extent();
-  //
   //===================================================
   BOPAlgo_BuilderFaceCnt::Perform(myRunParallel, aVBF);
   //===================================================
   //
-  for (k=0; k<(Standard_Integer)aNbBF; ++k) {
-    aLFIm.Clear();
-    //
-    BOPAlgo_BuilderFace& aBF=aVBF(k);
-    TopoDS_Face aF=aBF.Face();
-    anOriF=aBF.Orientation();
-    aF.Orientation(anOriF);
-    //
-    const BOPCol_ListOfShape& aLFR=aBF.Areas();
+  Standard_Integer aNbBF = aVBF.Extent();
+  for (k = 0; k < aNbBF; ++k)
+  {
+    BOPAlgo_BuilderFace& aBF = aVBF(k);
+    aFacesIm.Add(aBF.Face(), aBF.Areas());
+  }
+
+  aNbBF = aFacesIm.Extent();
+  for (k = 1; k <= aNbBF; ++k)
+  {
+    const TopoDS_Face& aF = TopoDS::Face(aFacesIm.FindKey(k));
+    anOriF = aF.Orientation();
+    const BOPCol_ListOfShape& aLFR = aFacesIm(k);
+    //
+    BOPCol_ListOfShape* pLFIm = mySplits.Bound(aF, BOPCol_ListOfShape());
     aIt.Initialize(aLFR);
     for (; aIt.More(); aIt.Next()) {
       TopoDS_Shape& aFR=aIt.ChangeValue();
-      if (anOriF==TopAbs_REVERSED) {
+      if (anOriF==TopAbs_REVERSED)
         aFR.Orientation(TopAbs_REVERSED);
-      }
-      //aFR.Orientation(anOriF);
-      aLFIm.Append(aFR);
+      pLFIm->Append(aFR);
     }
-    //
-    mySplits.Bind(aF, aLFIm); 
-  }// for (k=0; k<aNbBF; ++k) {
+  }
   //
   //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~scope t
 }
@@ -770,3 +793,98 @@ Standard_Boolean HasPaveBlocksOnIn(const BOPDS_FaceInfo& aFI1,
   }
   return bRet;
 }
+
+//=======================================================================
+//function : BuildDraftFace
+//purpose  : Build draft faces, updating the bounding edges,
+//           according to the information stored into the <theImages> map
+//=======================================================================
+TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
+                           const BOPCol_DataMapOfShapeListOfShape& theImages,
+                           Handle(IntTools_Context)& theCtx)
+{
+  BRep_Builder aBB;
+  // Take the information from the original face
+  TopLoc_Location aLoc;
+  const Handle(Geom_Surface)& aS = BRep_Tool::Surface(theFace, aLoc);
+  const Standard_Real aTol = BRep_Tool::Tolerance(theFace);
+  // Make the new face, without any wires
+  TopoDS_Face aDraftFace;
+  aBB.MakeFace(aDraftFace, aS, aLoc, aTol);
+
+  // Update wires of the original face and add them to draft face
+  TopoDS_Iterator aItW(theFace.Oriented(TopAbs_FORWARD));
+  for (; aItW.More(); aItW.Next())
+  {
+    const TopoDS_Shape& aW = aItW.Value();
+    if (aW.ShapeType() != TopAbs_WIRE)
+      continue;
+
+    // Rebuild wire using images of edges
+    TopoDS_Iterator aItE(aW.Oriented(TopAbs_FORWARD));
+    if (!aItE.More())
+      continue;
+
+    TopoDS_Wire aNewWire;
+    aBB.MakeWire(aNewWire);
+
+    for (; aItE.More(); aItE.Next())
+    {
+      const TopoDS_Edge& aE = TopoDS::Edge(aItE.Value());
+
+      TopAbs_Orientation anOriE = aE.Orientation();
+      if (anOriE == TopAbs_INTERNAL)
+      {
+        // The internal edges could split the original face on halves.
+        // Thus, use the BuilderFace algorithm to build the new face.
+        TopoDS_Face aNull;
+        return aNull;
+      }
+
+      const BOPCol_ListOfShape* pLEIm = theImages.Seek(aE);
+      if (!pLEIm)
+      {
+        aBB.Add(aNewWire, aE);
+        continue;
+      }
+
+      // Check if the original edge is degenerated
+      Standard_Boolean bIsDegenerated = BRep_Tool::Degenerated(aE);
+      // Check if the original edge is closed on the face
+      Standard_Boolean bIsClosed = BRep_Tool::IsClosed(aE, theFace);
+
+      BOPCol_ListIteratorOfListOfShape aItLEIm(*pLEIm);
+      for (; aItLEIm.More(); aItLEIm.Next())
+      {
+        TopoDS_Edge& aSp = TopoDS::Edge(aItLEIm.Value());
+
+        aSp.Orientation(anOriE);
+        if (bIsDegenerated)
+        {
+          aBB.Add(aNewWire, aSp);
+          continue;
+        }
+
+        // Check closeness of the split edge and if it is not
+        // make the second PCurve
+        if (bIsClosed && !BRep_Tool::IsClosed(aSp, theFace))
+          BOPTools_AlgoTools3D::DoSplitSEAMOnFace(aSp, theFace);
+
+        // Check if the split should be reversed
+        if (BOPTools_AlgoTools::IsSplitToReverse(aSp, aE, theCtx))
+          aSp.Reverse();
+
+        aBB.Add(aNewWire, aSp);
+      }
+    }
+
+    aNewWire.Orientation(aW.Orientation());
+    aNewWire.Closed(BRep_Tool::IsClosed(aNewWire));
+    aBB.Add(aDraftFace, aNewWire);
+  }
+
+  if (theFace.Orientation() == TopAbs_REVERSED)
+    aDraftFace.Reverse();
+
+  return aDraftFace;
+}
index ca5c985ab283dc1295dd971957a550f2849bee87..a572861ae278981d136305ee63d179ea6a9e83ca 100644 (file)
@@ -222,12 +222,11 @@ class BOPAlgo_FillIn3DParts : public BOPAlgo_Algo  {
      const Handle(NCollection_BaseAllocator)& );
   
   void MakeConnexityBlock 
-    (const BOPCol_ListOfShape& ,
+    (const TopoDS_Face& ,
      const BOPCol_IndexedMapOfShape& ,
-     const BOPCol_MapOfShape& , 
      const BOPCol_IndexedDataMapOfShapeListOfShape& ,
-     BOPCol_ListOfShape& ,
-     const Handle(NCollection_BaseAllocator)& );
+     BOPCol_MapOfShape& ,
+     BOPCol_ListOfShape& );
   //
  protected:
   TopoDS_Solid mySolid;
@@ -257,14 +256,13 @@ void BOPAlgo_FillIn3DParts::Perform()
   //  
   Standard_Integer aNbFP, k, nFP, iIsIN;
   Standard_Real aTolPC;
-  BOPCol_ListIteratorOfListOfInteger aItLI, aItLI1;
+  BOPCol_ListIteratorOfListOfInteger aItLI;
   BOPCol_ListIteratorOfListOfShape aItLS;
   BOPCol_BoxBndTreeSelector aSelector; 
   //
   aAlr1=
     NCollection_BaseAllocator::CommonBaseAllocator();
   //
-  BOPCol_ListOfShape aLFP(aAlr1);
   BOPCol_ListOfShape aLCBF(aAlr1);
   BOPCol_MapOfShape aMFDone(100, aAlr1);
   BOPCol_IndexedMapOfShape aME(100, aAlr1);
@@ -334,28 +332,16 @@ void BOPAlgo_FillIn3DParts::Perform()
     iIsIN=BOPTools_AlgoTools::IsInternalFace
       (aFP, myDraftSolid, aMEF, aTolPC, myContext);
     //
-    aLFP.Clear();
-    aLFP.Append(aFP);
-    //
-    aItLI1.Initialize(aLIFP);
-    for (; aItLI1.More(); aItLI1.Next()) {
-      const TopoDS_Shape& aFx=aVSB(aItLI1.Value()).Shape();
-      if (!aMFDone.Contains(aFx)) {
-        aLFP.Append(aFx);
-      }
-    }
-    //
+    // Make connexity blocks of faces, avoiding passing through the
+    // borders of the solid.
+    // It helps to reduce significantly the number of classified faces.
     aLCBF.Clear();
+    MakeConnexityBlock(aFP, aME, aMEFP, aMFDone, aLCBF);
     //
-    MakeConnexityBlock(aLFP, aME, aMFDone, aMEFP, aLCBF, aAlr1);
-    //
-    aItLS.Initialize(aLCBF);
-    for (; aItLS.More(); aItLS.Next()) {
-      const TopoDS_Shape& aFx=aItLS.Value();
-      aMFDone.Add(aFx);
-      if (iIsIN) {
-        myLFIN.Append(aFx);
-      }
+    if (iIsIN) {
+      aItLS.Initialize(aLCBF);
+      for (; aItLS.More(); aItLS.Next())
+        myLFIN.Append(aItLS.Value());
     }
   } // for (k=0; k<aNbFP; ++k) {
 }
@@ -379,16 +365,10 @@ void BOPAlgo_FillIn3DParts::MapEdgesAndFaces
     for (; myItW.More(); myItW.Next()) {
       const TopoDS_Shape& aE=myItW.Value();
       //
-      if (aMEF.Contains(aE)) {
-        BOPCol_ListOfShape& aLF=aMEF.ChangeFromKey(aE);
-        aLF.Append(aF);
-      }
-      else {
-        BOPCol_ListOfShape aLS(theAllocator);
-        //
-        aLS.Append(aF);
-        aMEF.Add(aE, aLS);
-      } 
+      BOPCol_ListOfShape* pLF = aMEF.ChangeSeek(aE);
+      if (!pLF)
+        pLF = &aMEF(aMEF.Add(aE, BOPCol_ListOfShape(theAllocator)));
+      pLF->Append(aF);
     }
   }
 }
@@ -396,84 +376,44 @@ void BOPAlgo_FillIn3DParts::MapEdgesAndFaces
 // function: MakeConnexityBlock
 // purpose: 
 //=======================================================================
-void BOPAlgo_FillIn3DParts::MakeConnexityBlock 
-  (const BOPCol_ListOfShape& theLFIn,
+void BOPAlgo_FillIn3DParts::MakeConnexityBlock
+  (const TopoDS_Face& theFStart,
    const BOPCol_IndexedMapOfShape& theMEAvoid,
-   const BOPCol_MapOfShape& aMFDone, 
-   const BOPCol_IndexedDataMapOfShapeListOfShape& aMEF,
-   BOPCol_ListOfShape& theLCB,
-   const Handle(NCollection_BaseAllocator)& theAlr)
+   const BOPCol_IndexedDataMapOfShapeListOfShape& theMEF,
+   BOPCol_MapOfShape& theMFDone,
+   BOPCol_ListOfShape& theLCB)
 {
-  Standard_Integer  aNbF, aNbAdd1, aNbAdd, i;
-  BOPCol_ListIteratorOfListOfShape aIt;
-  //
-  BOPCol_IndexedMapOfShape aMCB(100, theAlr);
-  BOPCol_IndexedMapOfShape aMAdd(100, theAlr);
-  BOPCol_IndexedMapOfShape aMAdd1(100, theAlr);
-  //
-  aNbF=theLFIn.Extent();
-  //
-  // 2. aMCB
-  const TopoDS_Shape& aF1=theLFIn.First();
-  aMAdd.Add(aF1);
-  //
-  for(;;) {
-    aMAdd1.Clear();
-    aNbAdd = aMAdd.Extent();
-    for (i=1; i<=aNbAdd; ++i) {
-      const TopoDS_Shape& aF=aMAdd(i);
-      //
-      myItF.Initialize(aF);
-      for (; myItF.More(); myItF.Next()) {
-        const TopoDS_Shape& aW=myItF.Value();
-        if (aW.ShapeType()!=TopAbs_WIRE) {
+  // Add start element
+  theLCB.Append(theFStart);
+
+  BOPCol_ListIteratorOfListOfShape aItCB(theLCB);
+  for (; aItCB.More(); aItCB.Next())
+  {
+    const TopoDS_Shape& aF = aItCB.Value();
+    myItF.Initialize(aF);
+    for (; myItF.More(); myItF.Next())
+    {
+      const TopoDS_Shape& aW = myItF.Value();
+      if (aW.ShapeType() != TopAbs_WIRE)
+        continue;
+
+      myItW.Initialize(aW);
+      for (; myItW.More(); myItW.Next())
+      {
+        const TopoDS_Shape& aE = myItW.Value();
+        if (theMEAvoid.Contains(aE))
           continue;
+
+        const BOPCol_ListOfShape& aLF = theMEF.FindFromKey(aE);
+        BOPCol_ListIteratorOfListOfShape aItLF(aLF);
+        for (; aItLF.More(); aItLF.Next())
+        {
+          const TopoDS_Shape& aFx = aItLF.Value();
+          if (!aFx.IsSame(aF) && theMFDone.Add(aFx))
+            theLCB.Append(aFx);
         }
-        //
-        myItW.Initialize(aW);
-        for (; myItW.More(); myItW.Next()) {
-          const TopoDS_Shape& aE=myItW.Value();
-          if (theMEAvoid.Contains(aE)){
-            continue;
-          }
-          //
-          const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE);
-          aIt.Initialize(aLF);
-          for (; aIt.More(); aIt.Next()) {
-            const TopoDS_Shape& aFx=aIt.Value();
-            if (aFx.IsSame(aF)) {
-              continue;
-            }
-            if (aMCB.Contains(aFx)) {
-              continue;
-            }
-            if (aMFDone.Contains(aFx)) {
-              continue;
-            }
-            aMAdd1.Add(aFx);
-          }
-        }// for (; myItW.More(); myItW.Next()) {
-      }// for (; myItF.More(); myItF.Next()) {
-      aMCB.Add(aF);
-    }// for (i=1; i<=aNbAdd; ++i) {
-    //
-    aNbAdd1=aMAdd1.Extent();
-    if (!aNbAdd1) {
-      break;
-    }
-    //
-    aMAdd.Clear();
-    for (i=1; i<=aNbAdd1; ++i) {
-      const TopoDS_Shape& aFAdd=aMAdd1(i);
-      aMAdd.Add(aFAdd);
+      }
     }
-    //
-  }//while(1) {
-  //
-  aNbF=aMCB.Extent();
-  for (i=1; i<=aNbF; ++i) {
-    const TopoDS_Shape& aF=aMCB(i);
-    theLCB.Append(aF);
   }
 }
 //
@@ -616,7 +556,7 @@ void BOPAlgo_Builder::FillIn3DParts
   BOPAlgo_VectorOfFillIn3DParts aVFIP;
   //
   for (i=0; i<aNbS; ++i) {
-    const BOPDS_ShapeInfo& aSI=myDS->ShapeInfo(i);
+    BOPDS_ShapeInfo& aSI=myDS->ChangeShapeInfo(i);
     if (aSI.ShapeType()!=TopAbs_SOLID) {
       continue;
     }
@@ -636,8 +576,9 @@ void BOPAlgo_Builder::FillIn3DParts
     }
     //
     // 2.1 Bounding box for the solid aS  [ aBoxS ]
-    Bnd_Box aBoxS;
-    aBoxS=aSI.Box();
+    Bnd_Box& aBoxS = aSI.ChangeBox();
+    if (aBoxS.IsVoid())
+      myDS->BuildBndBoxSolid(i, aBoxS, myCheckInverted);
     //
     // 2.2 Build Draft Solid [aSD]
     BOPCol_ListOfShape aLIF;
@@ -830,34 +771,41 @@ void BOPAlgo_Builder::BuildSplitSolids
     //
   } //for (i=1; i<=aNbS; ++i) 
   //
-  // 1. Build solids for interferred source solids
-  for (i=0; i<aNbS; ++i) {
-    const BOPDS_ShapeInfo& aSI=myDS->ShapeInfo(i);
-    //
-    if (aSI.ShapeType()!=TopAbs_SOLID) {
+  // Build temporary map of solids images to avoid rebuilding
+  // of the solids without internal faces
+  BOPCol_IndexedDataMapOfShapeListOfShape aSolidsIm;
+  // 1. Build solids for interfered source solids
+  for (i = 0; i < aNbS; ++i) {
+    const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
+    if (aSI.ShapeType() != TopAbs_SOLID)
       continue;
-    }
-    //
-    const TopoDS_Shape& aS=aSI.Shape();
+
+    const TopoDS_Shape& aS = aSI.Shape();
     const TopoDS_Solid& aSolid=(*(TopoDS_Solid*)(&aS));
-    if(!theDraftSolids.IsBound(aS)) {
+    if (!theDraftSolids.IsBound(aS))
+      continue;
+
+    const TopoDS_Shape& aSD = theDraftSolids.Find(aS);
+    const BOPCol_ListOfShape* pLFIN = theInParts.Seek(aS);
+    if (!pLFIN)
+    {
+      aSolidsIm(aSolidsIm.Add(aS, BOPCol_ListOfShape())).Append(aSD);
       continue;
     }
-    const TopoDS_Shape& aSD=theDraftSolids.Find(aS);
-    const BOPCol_ListOfShape& aLFIN=
-      (theInParts.IsBound(aS)) ? theInParts.Find(aS) : aLSEmpty;
+
+    aSFS.Clear();
     //
     // 1.1 Fill Shell Faces Set
-    aSFS.Clear();
     aExp.Init(aSD, TopAbs_FACE);
     for (; aExp.More(); aExp.Next()) {
-      const TopoDS_Shape& aF=aExp.Current();
+      const TopoDS_Shape& aF = aExp.Current();
       aSFS.Append(aF);
     }
     //
-    aIt.Initialize(aLFIN);
+    // 1.2 Fill internal faces
+    aIt.Initialize(*pLFIN);
     for (; aIt.More(); aIt.Next()) {
-      TopoDS_Shape aF=aIt.Value();
+      TopoDS_Shape aF = aIt.Value();
       //
       aF.Orientation(TopAbs_FORWARD);
       aSFS.Append(aF);
@@ -865,7 +813,7 @@ void BOPAlgo_Builder::BuildSplitSolids
       aSFS.Append(aF);
     }
     //
-    // 1.3 Build new solids  
+    // 1.3 Build new solids
     BOPAlgo_BuilderSolid& aBS=aVBS.Append1();
     aBS.SetSolid(aSolid);
     aBS.SetShapes(aSFS);
@@ -881,10 +829,18 @@ void BOPAlgo_Builder::BuildSplitSolids
   BOPAlgo_BuilderSolidCnt::Perform(myRunParallel, aVBS);
   //===================================================
   //
-  for (k=0; k<aNbBS; ++k) {
-    BOPAlgo_BuilderSolid& aBS=aVBS(k);
-    const TopoDS_Solid& aS=aBS.Solid();
-    const BOPCol_ListOfShape& aLSR=aBS.Areas();
+  for (k = 0; k < aNbBS; ++k)
+  {
+    BOPAlgo_BuilderSolid& aBS = aVBS(k);
+    aSolidsIm.Add(aBS.Solid(), aBS.Areas());
+  }
+  //
+  // Add new solids to images map
+  aNbBS = aSolidsIm.Extent();
+  for (k = 1; k <= aNbBS; ++k)
+  {
+    const TopoDS_Shape& aS = aSolidsIm.FindKey(k);
+    const BOPCol_ListOfShape& aLSR = aSolidsIm(k);
     //
     if (!myImages.IsBound(aS)) {
       BOPCol_ListOfShape* pLSx = myImages.Bound(aS, BOPCol_ListOfShape());
index ddbade6f5351364b1d909be39e226461b03e1e00..ac5445b4d02a19c3d7c1e6339083b5231a0d8150 100644 (file)
@@ -50,7 +50,8 @@ BOPAlgo_Options::BOPAlgo_Options()
   myAllocator(NCollection_BaseAllocator::CommonBaseAllocator()),
   myReport(new Message_Report),
   myRunParallel(myGlobalRunParallel),
-  myFuzzyValue(Precision::Confusion())
+  myFuzzyValue(Precision::Confusion()),
+  myCheckInverted(Standard_True)
 {
   BOPAlgo_LoadMessages();
 }
@@ -65,7 +66,8 @@ BOPAlgo_Options::BOPAlgo_Options
   myAllocator(theAllocator),
   myReport(new Message_Report),
   myRunParallel(myGlobalRunParallel),
-  myFuzzyValue(Precision::Confusion())
+  myFuzzyValue(Precision::Confusion()),
+  myCheckInverted(Standard_True)
 {
   BOPAlgo_LoadMessages();
 }
index 4be0ec063cde269c02476cb6fe141cc06b5b71fb..e10cf0e1ec4b9aa258828c71f50889eef6c8dc51 100644 (file)
@@ -32,6 +32,10 @@ class Message_ProgressIndicator;
 //!                       touching or coinciding cases;
 //! - *Progress indicator* - provides interface to track the progress of
 //!                          operation and stop the operation by user's break.
+//! - *Disabling the check for inverted solids* - Disables/Enables the check of the input solids
+//!                          for inverted status (holes in the space). The default value is TRUE,
+//!                          i.e. the check is performed. Setting this flag to FALSE for inverted solids,
+//!                          most likely will lead to incorrect results.
 //!
 class BOPAlgo_Options
 {
@@ -156,6 +160,22 @@ public:
   //! Set the Progress Indicator object.
   Standard_EXPORT void SetProgressIndicator(const Handle(Message_ProgressIndicator)& theObj);
 
+public:
+  //!@name Check input solids for inverted status
+
+  //! Enables/Disables the check of the input solids for inverted status
+  void SetCheckInverted(const Standard_Boolean theCheck)
+  {
+    myCheckInverted = theCheck;
+  }
+
+  //! Returns the flag defining whether the check for input solids on inverted status
+  //! should be performed or not.
+  Standard_Boolean CheckInverted() const
+  {
+    return myCheckInverted;
+  }
+
 protected:
 
   //! Breaks the execution if the break signal
@@ -169,6 +189,7 @@ protected:
   Standard_Boolean myRunParallel;
   Standard_Real myFuzzyValue;
   Handle(Message_ProgressIndicator) myProgressIndicator;
+  Standard_Boolean myCheckInverted;
 
 };
 
index bbc1b35c91637db6c2330a319094e55a7e95d821..40febda2ca95d3b3214c898a83defdbe816e3855 100644 (file)
@@ -198,34 +198,56 @@ void BOPAlgo_PaveFiller::PerformFF()
   //
   for (; myIterator->More(); myIterator->Next()) {
     myIterator->Value(nF1, nF2);
-    //
-    const TopoDS_Face& aF1=(*(TopoDS_Face *)(&myDS->Shape(nF1)));
-    const TopoDS_Face& aF2=(*(TopoDS_Face *)(&myDS->Shape(nF2)));
-    //
-    if (aMIFence.Add(nF1)) {
-      myDS->UpdateFaceInfoOn(nF1);
-      myDS->UpdateFaceInfoIn(nF1);
+
+    // Update/Initialize FaceInfo structure for first face
+    if (myDS->HasFaceInfo(nF1))
+    {
+      if (aMIFence.Add(nF1))
+      {
+        myDS->UpdateFaceInfoOn(nF1);
+        myDS->UpdateFaceInfoIn(nF1);
+      }
     }
-    if (aMIFence.Add(nF2)) {
-      myDS->UpdateFaceInfoOn(nF2);
-      myDS->UpdateFaceInfoIn(nF2);
-    }
-    //
-    const BRepAdaptor_Surface& aBAS1 = myContext->SurfaceAdaptor(aF1);
-    const BRepAdaptor_Surface& aBAS2 = myContext->SurfaceAdaptor(aF2);
-    if (aBAS1.GetType() == GeomAbs_Plane && 
-        aBAS2.GetType() == GeomAbs_Plane) {
-      // Check if the planes are really interfering
-      Standard_Boolean bToIntersect = CheckPlanes(nF1, nF2);
-      if (!bToIntersect) {
-        BOPDS_InterfFF& aFF=aFFs.Append1();
-        aFF.SetIndices(nF1, nF2);
-        aFF.Init(0, 0);
-        continue;
+    else if (myDS->HasInterfShapeSubShapes(nF2, nF1))
+    {
+      myDS->ChangeFaceInfo(nF1);
+      aMIFence.Add(nF1);
+    }
+
+    // Update/Initialize FaceInfo structure for second face
+    if (myDS->HasFaceInfo(nF2))
+    {
+      if (aMIFence.Add(nF2))
+      {
+        myDS->UpdateFaceInfoOn(nF2);
+        myDS->UpdateFaceInfoIn(nF2);
       }
     }
+    else if (myDS->HasInterfShapeSubShapes(nF1, nF2))
+    {
+      myDS->ChangeFaceInfo(nF2);
+      aMIFence.Add(nF2);
+    }
     //
-    if (myGlue == BOPAlgo_GlueOff) {
+    if (myGlue == BOPAlgo_GlueOff)
+    {
+      const TopoDS_Face& aF1 = (*(TopoDS_Face *)(&myDS->Shape(nF1)));
+      const TopoDS_Face& aF2 = (*(TopoDS_Face *)(&myDS->Shape(nF2)));
+      //
+      const BRepAdaptor_Surface& aBAS1 = myContext->SurfaceAdaptor(aF1);
+      const BRepAdaptor_Surface& aBAS2 = myContext->SurfaceAdaptor(aF2);
+      if (aBAS1.GetType() == GeomAbs_Plane &&
+          aBAS2.GetType() == GeomAbs_Plane) {
+        // Check if the planes are really interfering
+        Standard_Boolean bToIntersect = CheckPlanes(nF1, nF2);
+        if (!bToIntersect) {
+          BOPDS_InterfFF& aFF = aFFs.Append1();
+          aFF.SetIndices(nF1, nF2);
+          aFF.Init(0, 0);
+          continue;
+        }
+      }
+      //
       BOPAlgo_FaceFace& aFaceFace=aVFaceFace.Append1();
       //
       aFaceFace.SetIndices(nF1, nF2);
index 077078227e969b4a718dc4dd8284eb8634dafd9d..fa39aa2064bb77fbceb5247c9d7e75f87b923ab3 100644 (file)
@@ -42,12 +42,6 @@ static
   void RefineShell(TopoDS_Shell& theShell,
                    const BOPCol_IndexedDataMapOfShapeListOfShape& theMEF,
                    BOPCol_ListOfShape& aLShX);
-//
-static
-  void MapEdgesAndFaces
-  (const TopoDS_Shape& aF,
-   BOPCol_IndexedDataMapOfShapeListOfShape& aMEF,
-   const Handle(NCollection_BaseAllocator)& theAllocator);
 
 //=======================================================================
 //class    : BOPAlgo_CBK
@@ -152,162 +146,12 @@ void BOPAlgo_ShellSplitter::Perform()
 {
   GetReport()->Clear();
   //
-  MakeConnexityBlocks();
-  if (HasErrors()) {
-    return;
-  }
+  BOPTools_AlgoTools::MakeConnexityBlocks
+    (myStartShapes, TopAbs_EDGE, TopAbs_FACE, myLCB);
   //
   MakeShells();
 }
-//=======================================================================
-//function : MakeConnexityBlocks
-//purpose  : 
-//=======================================================================
-void BOPAlgo_ShellSplitter::MakeConnexityBlocks()
-{
-  Standard_Boolean bRegular;
-  Standard_Integer i, j, aNbE, aNbES, aNbEP, k, aNbCB;
-  TopoDS_Shape aFR;
-  TopoDS_Iterator aItF, aItW;
-  BOPCol_IndexedDataMapOfShapeListOfShape aMEF(100, myAllocator);
-  BOPCol_IndexedMapOfShape aMEP(100, myAllocator);
-  BOPCol_IndexedMapOfShape aMFC(100, myAllocator);
-  BOPCol_MapOfShape aMER(100, myAllocator);
-  BOPCol_MapOfShape aMFP(100, myAllocator);
-  BOPCol_IndexedMapOfShape aMEAdd(100, myAllocator);
-  BOPCol_MapOfShape aMES(100, myAllocator);
-  BOPCol_ListIteratorOfListOfShape aIt;
-  //
-  myLCB.Clear();
-  //
-  const BOPCol_ListOfShape& aLSE=myStartShapes;
-  aIt.Initialize(aLSE);
-  for (i=1; aIt.More(); aIt.Next(), ++i) {
-    const TopoDS_Shape& aSE=aIt.Value();
-    if (!aMEP.Contains(aSE)) {
-      aMEP.Add(aSE);
-      MapEdgesAndFaces(aSE, aMEF, myAllocator);
-    }
-    else {
-      aMER.Add(aSE);
-    }
-  }
-  //
-  // 2
-  aNbE=aMEF.Extent();
-  for (i=1; i<=aNbE; ++i) {
-    aNbES=aMES.Extent();
-    if (aNbES==aNbE) {
-      break;
-    }
-    //
-    const TopoDS_Shape& aE=aMEF.FindKey(i);
-    //
-    if (!aMES.Add(aE)) {
-      continue;
-    }
-    // aMES - globally processed edges
-    //
-    //------------------------------------- goal: aMEC
-    aMFC.Clear();    // aMEC - edges of CB
-    aMEP.Clear();    // aMVP - edges to process right now 
-    aMEAdd.Clear();  // aMVAdd edges to process on next step of for(;;) {
-    //
-    aMEP.Add(aE);
-    //
-    for(;;) {
-      aNbEP=aMEP.Extent();
-      for (k=1; k<=aNbEP; ++k) {
-        const TopoDS_Shape& aEP=aMEP(k);
-        const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aEP);
-        aIt.Initialize(aLF);
-        for (; aIt.More(); aIt.Next()) {
-          const TopoDS_Shape& aF=aIt.Value();
-          if (aMFC.Add(aF)) {
-            aItF.Initialize(aF);
-            while (aItF.More()) {
-              const TopoDS_Shape& aW=aItF.Value();  
-              if (aW.ShapeType()!=TopAbs_WIRE) {
-                aItF.Next();
-                continue;
-              }
-              //
-              aItW.Initialize(aW);
-              while (aItW.More()) {
-                const TopoDS_Shape& aEF=aItW.Value();  
-                //
-                if (aMES.Add(aEF)) {
-                  aMEAdd.Add(aEF);
-                }
-                //
-                aItW.Next();
-              }
-              //
-              aItF.Next();
-            }
-          }
-        }
-      }
-      //
-      aNbEP=aMEAdd.Extent();
-      if (!aNbEP) {
-        break; // from for(;;) {
-      }
-      //
-      aMEP.Clear();
-      //
-      for (k=1; k<=aNbEP; ++k) {
-        const TopoDS_Shape& aEF=aMEAdd(k);
-        aMEP.Add(aEF);
-      }
-      aMEAdd.Clear();
-    }// for(;;) {
-    //
-    //-------------------------------------
-    BOPTools_ConnexityBlock aCB(myAllocator);
-    //
-    BOPCol_ListOfShape& aLECB=aCB.ChangeShapes();
-    BOPCol_IndexedDataMapOfShapeListOfShape aMEFR(100, myAllocator);
-    //
-    bRegular=Standard_True;
-    aNbCB = aMFC.Extent();
-    for (j=1; j<=aNbCB; ++j) {
-      aFR = aMFC(j);
-      //
-      if (aMER.Contains(aFR)) {
-        aFR.Orientation(TopAbs_FORWARD);
-        aLECB.Append(aFR);
-        aFR.Orientation(TopAbs_REVERSED);
-        aLECB.Append(aFR);
-        bRegular=Standard_False;
-      }
-      else {
-        aLECB.Append(aFR);
-      }
-      //
-      if (bRegular) {
-        MapEdgesAndFaces(aFR, aMEFR, myAllocator);
-      }
-    }
-    //
-    if (bRegular) {
-      Standard_Integer aNbER, aNbFR; 
-      //
-      aNbER=aMEFR.Extent();
-      for (k=1; k<=aNbER; ++k) {
-        const BOPCol_ListOfShape& aLFR=aMEFR(k);
-        aNbFR=aLFR.Extent();
-        if (aNbFR>2) {
-          bRegular=!bRegular;
-          break;
-        }
-      }
-    }
-    //
-    aCB.SetRegular(bRegular);
-    myLCB.Append(aCB);
-  }
-}
+
 //=======================================================================
 //function : SplitBlock
 //purpose  : 
@@ -750,43 +594,3 @@ void MakeShell(const BOPCol_ListOfShape& aLS,
   //
   BOPTools_AlgoTools::OrientFacesOnShell(aShell);
 }
-//=======================================================================
-// function: MapEdgesAndFaces
-// purpose: 
-//=======================================================================
-void MapEdgesAndFaces
-  (const TopoDS_Shape& aF,
-   BOPCol_IndexedDataMapOfShapeListOfShape& aMEF,
-   const Handle(NCollection_BaseAllocator)& theAllocator)
-{
-  TopoDS_Iterator aItF, aItW;
-  //
-  aItF.Initialize(aF);
-  while (aItF.More()) {
-    const TopoDS_Shape& aW=aItF.Value();  
-    if (aW.ShapeType()!=TopAbs_WIRE) {
-      aItF.Next();
-      continue;
-    }
-    //
-    aItW.Initialize(aW);
-    while (aItW.More()) {
-      const TopoDS_Shape& aE=aItW.Value();  
-      //
-      if (aMEF.Contains(aE)) {
-        BOPCol_ListOfShape& aLF=aMEF.ChangeFromKey(aE);
-        aLF.Append(aF);
-      }
-      else {
-        BOPCol_ListOfShape aLS(theAllocator);
-        //
-        aLS.Append(aF);
-        aMEF.Add(aE, aLS);
-      }
-      //
-      aItW.Next();
-    }
-    //
-    aItF.Next();
-  }
-}
index 980fa56f8fb4f7de1392b45d9cc5e6e3249e42eb..fb4a4e0d22146212adfd9e25525f2c299ee4c3be 100644 (file)
@@ -61,8 +61,6 @@ Standard_EXPORT virtual ~BOPAlgo_ShellSplitter();
 
 protected:
 
-  Standard_EXPORT void MakeConnexityBlocks();
-
   Standard_EXPORT void MakeShells();
 
 
index 287593066f3c96dfc802043e108eb449be343e2e..4dffb3f617f6efba7a9ccce8939eaa045472948b 100644 (file)
@@ -24,6 +24,7 @@
 #include <BOPCol_NCVector.hxx>
 #include <BOPCol_Parallel.hxx>
 #include <BOPTools.hxx>
+#include <BOPTools_AlgoTools.hxx>
 #include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
 #include <TopoDS.hxx>
@@ -124,153 +125,12 @@ void BOPAlgo_WireSplitter::Perform()
     myContext = new IntTools_Context;
   }
   //
-  MakeConnexityBlocks();
+  BOPTools_AlgoTools::MakeConnexityBlocks
+    (myWES->StartElements(), TopAbs_VERTEX, TopAbs_EDGE, myLCB);
+
   MakeWires();
 }
 
-//=======================================================================
-//function : MakeConnexityBlocks
-//purpose  : 
-//=======================================================================
-void BOPAlgo_WireSplitter::MakeConnexityBlocks()
-{
-  Standard_Boolean bRegular, bClosed;
-  Standard_Integer i, j, aNbV, aNbVS, aNbVP, k;
-  TopoDS_Iterator aItE;
-  TopoDS_Shape aER;
-  BOPCol_ListIteratorOfListOfShape aIt;
-  //
-  BOPCol_IndexedDataMapOfShapeListOfShape aMVE(100, myAllocator);
-  BOPCol_IndexedMapOfShape aMVP(100, myAllocator);
-  BOPCol_IndexedMapOfShape aMEC(100, myAllocator);
-  BOPCol_MapOfShape aMER(100, myAllocator);
-  BOPCol_MapOfShape aMEP(100, myAllocator);
-  BOPCol_IndexedMapOfShape aMVAdd(100, myAllocator);
-  BOPCol_MapOfShape aMVS(100, myAllocator);
-  //
-  myLCB.Clear();
-  //
-  const BOPCol_ListOfShape& aLSE=myWES->StartElements();
-  aIt.Initialize(aLSE);
-  for (; aIt.More(); aIt.Next()) {
-    const TopoDS_Shape& aE=aIt.Value();
-    if (aMEP.Add(aE)) {
-      BOPTools::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
-    }
-    else {
-      aMER.Add(aE);
-    }
-  }
-  //
-  // 2
-  aNbV=aMVE.Extent();
-  for (i=1; i<=aNbV; ++i) {
-    aNbVS=aMVS.Extent();
-    if (aNbVS==aNbV) {
-      break;
-    }
-    //
-    const TopoDS_Shape& aV=aMVE.FindKey(i);
-    //
-    if (!aMVS.Add(aV)) {
-      continue;
-    }
-        // aMVS - globally processed vertices
-    //
-    //------------------------------------- goal: aMEC
-    aMEC.Clear();    // aMEC - edges of CB
-    aMVP.Clear();    // aMVP - vertices to process right now 
-    aMVAdd.Clear();  // aMVAdd vertices to process on next step of while(1)
-    //
-    aMVP.Add(aV);
-    //
-    for(;;) {
-      aNbVP=aMVP.Extent();
-      for (k=1; k<=aNbVP; ++k) {
-        const TopoDS_Shape& aVP=aMVP(k);
-        const BOPCol_ListOfShape& aLE=aMVE.FindFromKey(aVP);
-        aIt.Initialize(aLE);
-        for (; aIt.More(); aIt.Next()) {
-          const TopoDS_Shape& aE=aIt.Value();
-          if (aMEC.Add(aE)) {
-            aItE.Initialize(aE);
-            for (; aItE.More(); aItE.Next()) {
-              const TopoDS_Shape& aVE=aItE.Value();
-              if (aMVS.Add(aVE)) {
-                aMVAdd.Add(aVE);
-              }
-            }
-          }
-        }
-      }//for (k=1; k<=aNbVP; ++k) {
-      //
-      aNbVP=aMVAdd.Extent();
-      if (!aNbVP) {
-        break; // from while(1)
-      }
-      //
-      aMVP.Clear();
-      //
-      for (k=1; k<=aNbVP; ++k) {
-        const TopoDS_Shape& aVE=aMVAdd(k);
-        aMVP.Add(aVE);
-      }
-      aMVAdd.Clear();
-    }// while(1) {
-
-    //-------------------------------------
-    BOPTools_ConnexityBlock aCB(myAllocator);
-    BOPCol_ListOfShape& aLEC=aCB.ChangeShapes();
-    
-    BOPCol_IndexedDataMapOfShapeListOfShape aMVER(100, myAllocator);
-    //
-    bRegular=Standard_True;
-    Standard_Integer aNbCB = aMEC.Extent();
-    for (j = 1; j <= aNbCB; j++) {
-      aER = aMEC(j);
-      //
-      if (aMER.Contains(aER)) {
-        aER.Orientation(TopAbs_FORWARD);
-        aLEC.Append(aER);
-        aER.Orientation(TopAbs_REVERSED);
-        aLEC.Append(aER);
-        bRegular=Standard_False;
-      }
-      else {
-        aLEC.Append(aER);
-      }
-      //
-      if (bRegular) {
-        BOPTools::MapShapesAndAncestors(aER, TopAbs_VERTEX, TopAbs_EDGE, aMVER);
-      }
-    }
-    //
-    if (bRegular) {
-      Standard_Integer aNbVR, aNbER;
-      //
-      aNbVR=aMVER.Extent();
-      for (k=1; k<=aNbVR; ++k) {
-        const BOPCol_ListOfShape& aLER=aMVER(k);
-        aNbER=aLER.Extent();
-        if (aNbER==1) {
-          const TopoDS_Edge& aEx=TopoDS::Edge(aER);
-          bClosed=BRep_Tool::IsClosed(aEx, myWES->Face());
-          if (!bClosed) {
-            bRegular=!bRegular;
-            break;
-          }
-        }
-        if (aNbER>2) {
-          bRegular=!bRegular;
-          break;
-        }
-      }
-    }
-    //
-    aCB.SetRegular(bRegular);
-    myLCB.Append(aCB);
-  }
-}
 /////////////////////////////////////////////////////////////////////////
 class BOPAlgo_WS_ConnexityBlock {
 public:
index 6b2f6e0842ef4d724daa396d609f7234fc92619c..95ea1b2d9c1fedfc686a3d4a64b338fb7401ba30 100644 (file)
@@ -70,8 +70,6 @@ protected:
 
   Standard_EXPORT virtual void CheckData() Standard_OVERRIDE;
   
-  Standard_EXPORT void MakeConnexityBlocks();
-  
   Standard_EXPORT void MakeWires();
 
   BOPAlgo_PWireEdgeSet myWES;
index c89f7a31b95134fd9db3c39f7cb524bcaa931a18..06eea1c12c5bdad09f9f0b7ad92773ad371dd049 100644 (file)
@@ -545,58 +545,64 @@ void BOPDS_DS::Init(const Standard_Real theFuzz)
     }//if (aTS==TopAbs_FACE) {
   }//for (j=0; j<myNbSourceShapes; ++j) {
   //
-  // 2.4 Solids
-  for (j=0; j<myNbSourceShapes; ++j) {
-    BOPDS_ShapeInfo& aSI=ChangeShapeInfo(j);
-    //
-    aTS=aSI.ShapeType();
-    if (aTS!=TopAbs_SOLID) {
-      continue;
-    }
-    Bnd_Box& aBox=aSI.ChangeBox();
-    BuildBndBoxSolid(j, aBox); 
-    //
-    //
-    // update sub-shapes by BRep comprising ones
-    aMI.Clear();
-    BOPCol_ListOfInteger& aLI1=aSI.ChangeSubShapes();
-    //
-    aIt1.Initialize(aLI1);
-    for (; aIt1.More(); aIt1.Next()) {
-      n1=aIt1.Value();
-      BOPDS_ShapeInfo& aSI1=ChangeShapeInfo(n1);
-      if (aSI1.ShapeType()!=TopAbs_SHELL) {
+  // For the check mode we need to compute the bounding box for solid.
+  // Otherwise, it will be computed on the building stage
+  Standard_Boolean bCheckMode = (myArguments.Extent() == 1);
+  if (bCheckMode)
+  {
+    // 2.4 Solids
+    for (j=0; j<myNbSourceShapes; ++j) {
+      BOPDS_ShapeInfo& aSI=ChangeShapeInfo(j);
+      //
+      aTS=aSI.ShapeType();
+      if (aTS!=TopAbs_SOLID) {
         continue;
       }
+      Bnd_Box& aBox=aSI.ChangeBox();
+      BuildBndBoxSolid(j, aBox); 
       //
-      const BOPCol_ListOfInteger& aLI2=aSI1.SubShapes(); 
-      aIt2.Initialize(aLI2);
-      for (; aIt2.More(); aIt2.Next()) {
-        n2=aIt2.Value();
-        BOPDS_ShapeInfo& aSI2=ChangeShapeInfo(n2);
-        if (aSI2.ShapeType()!=TopAbs_FACE) {
+      //
+      // update sub-shapes by BRep comprising ones
+      aMI.Clear();
+      BOPCol_ListOfInteger& aLI1=aSI.ChangeSubShapes();
+      //
+      aIt1.Initialize(aLI1);
+      for (; aIt1.More(); aIt1.Next()) {
+        n1=aIt1.Value();
+        BOPDS_ShapeInfo& aSI1=ChangeShapeInfo(n1);
+        if (aSI1.ShapeType()!=TopAbs_SHELL) {
           continue;
         }
         //
-        aMI.Add(n2);
-        //
-        const BOPCol_ListOfInteger& aLI3=aSI2.SubShapes(); 
-        aIt3.Initialize(aLI3);
-        for (; aIt3.More(); aIt3.Next()) {
-          n3=aIt3.Value();
-          aMI.Add(n3);
+        const BOPCol_ListOfInteger& aLI2=aSI1.SubShapes(); 
+        aIt2.Initialize(aLI2);
+        for (; aIt2.More(); aIt2.Next()) {
+          n2=aIt2.Value();
+          BOPDS_ShapeInfo& aSI2=ChangeShapeInfo(n2);
+          if (aSI2.ShapeType()!=TopAbs_FACE) {
+            continue;
+          }
+          //
+          aMI.Add(n2);
+          //
+          const BOPCol_ListOfInteger& aLI3=aSI2.SubShapes(); 
+          aIt3.Initialize(aLI3);
+          for (; aIt3.More(); aIt3.Next()) {
+            n3=aIt3.Value();
+            aMI.Add(n3);
+          }
         }
       }
-    }
-    //
-    aLI1.Clear();
-    aItMI.Initialize(aMI);
-    for (; aItMI.More(); aItMI.Next()) {
-      n1=aItMI.Value();
-      aLI1.Append(n1);
-    }
-    aMI.Clear();
-  }//for (j=0; j<myNbSourceShapes; ++j) {
+      //
+      aLI1.Clear();
+      aItMI.Initialize(aMI);
+      for (; aItMI.More(); aItMI.Next()) {
+        n1=aItMI.Value();
+        aLI1.Append(n1);
+      }
+      aMI.Clear();
+    }//for (j=0; j<myNbSourceShapes; ++j) {
+  }
   //
   aMI.Clear();
   //-----------------------------------------------------
@@ -1866,7 +1872,8 @@ Standard_Real ComputeParameter(const TopoDS_Vertex& aV,
 //purpose  : 
 //=======================================================================
 void BOPDS_DS::BuildBndBoxSolid(const Standard_Integer theIndex,
-                                Bnd_Box& aBoxS)
+                                Bnd_Box& aBoxS,
+                                const Standard_Boolean theCheckInverted)
 {
   Standard_Boolean bIsOpenBox, bIsInverted;
   Standard_Integer nSh, nFc;
@@ -1930,7 +1937,7 @@ void BOPDS_DS::BuildBndBoxSolid(const Standard_Integer theIndex,
   if (bIsOpenBox) {
     aBoxS.SetWhole();
   }
-  else {
+  else if (theCheckInverted) {
     bIsInverted=BOPTools_AlgoTools::IsInvertedSolid(aSolid);
     if (bIsInverted) {
       aBoxS.SetWhole(); 
index 6b19debd0e7dca122b0bb7e26bfc3e9a5d693dc1..94e4855d098e2efd1836d8794fa0e3464d440f3c 100644 (file)
@@ -468,6 +468,13 @@ Standard_EXPORT virtual ~BOPDS_DS();
   //! of the existing vertices have been increased.
   Standard_EXPORT Standard_Boolean IsValidShrunkData(const Handle(BOPDS_PaveBlock)& thePB);
 
+  //! Computes bounding box <theBox> for the solid with DS-index <theIndex>.
+  //! The flag <theCheckInverted> enables/disables the check of the solid
+  //! for inverted status. By default the solids will be checked.
+  Standard_EXPORT void BuildBndBoxSolid (const Standard_Integer theIndex,
+                                         Bnd_Box& theBox,
+                                         const Standard_Boolean theCheckInverted = Standard_True);
+
 protected:
 
   
@@ -485,10 +492,6 @@ protected:
                                                      const Standard_Real theFuzz);
 
 
-  //! Computes bouding box <theBox> for the solid with DS-index <theIndex>
-  Standard_EXPORT void BuildBndBoxSolid (const Standard_Integer theIndex, Bnd_Box& theBox);
-
-
   BOPCol_BaseAllocator myAllocator;
   BOPCol_ListOfShape myArguments;
   Standard_Integer myNbShapes;
index d6737c6e584ec4c92ee039ae02238ec391c2cfff..4096800bdfee1d18fa9b438265bd67bae37abb2c 100644 (file)
@@ -133,6 +133,7 @@ Standard_Integer bapibop(Draw_Interpretor& di,
   pBuilder->SetFuzzyValue(aFuzzyValue);
   pBuilder->SetNonDestructive(bNonDestructive);
   pBuilder->SetGlue(aGlue);
+  pBuilder->SetCheckInverted(BOPTest_Objects::CheckInverted());
   //
   pBuilder->Build(); 
   //
@@ -193,6 +194,7 @@ Standard_Integer bapibuild(Draw_Interpretor& di,
   aBuilder.SetFuzzyValue(aFuzzyValue);
   aBuilder.SetNonDestructive(bNonDestructive);
   aBuilder.SetGlue(aGlue);
+  aBuilder.SetCheckInverted(BOPTest_Objects::CheckInverted());
   //
   aBuilder.Build(); 
   //
@@ -257,6 +259,7 @@ Standard_Integer bapisplit(Draw_Interpretor& di,
   aSplitter.SetFuzzyValue(BOPTest_Objects::FuzzyValue());
   aSplitter.SetNonDestructive(BOPTest_Objects::NonDestructive());
   aSplitter.SetGlue(BOPTest_Objects::Glue());
+  aSplitter.SetCheckInverted(BOPTest_Objects::CheckInverted());
   //
   // performing operation
   aSplitter.Build();
index 8475b9261f0e2d62e10b89880dc2154edf336c55..427f052cab30b6706b71a74e7660981e03369760 100644 (file)
@@ -250,6 +250,7 @@ Standard_Integer bopsmt(Draw_Interpretor& di,
   aBOP.AddTool(aS2);
   aBOP.SetOperation(aOp);
   aBOP.SetRunParallel (bRunParallel);
+  aBOP.SetCheckInverted(BOPTest_Objects::CheckInverted());
   //
   aBOP.PerformWithFiller(*pPF);
   BOPTest::ReportAlerts(aBOP);
@@ -310,6 +311,7 @@ Standard_Integer bopsection(Draw_Interpretor& di,
   aBOP.AddArgument(aS1);
   aBOP.AddArgument(aS2);
   aBOP.SetRunParallel (bRunParallel);
+  aBOP.SetCheckInverted(BOPTest_Objects::CheckInverted());
   //
   aBOP.PerformWithFiller(*pPF);
   BOPTest::ReportAlerts(aBOP);
@@ -508,6 +510,7 @@ Standard_Integer bsmt (Draw_Interpretor& di,
   aBOP.AddTool(aS2);
   aBOP.SetOperation(aOp);
   aBOP.SetRunParallel(bRunParallel);
+  aBOP.SetCheckInverted(BOPTest_Objects::CheckInverted());
   // 
   aBOP.PerformWithFiller(aPF);
   BOPTest::ReportAlerts(aBOP);
index 719f57b057e976166fc48c45db25279882029576..037305314611d5963d60d4594427bde18207ff43 100644 (file)
@@ -111,6 +111,7 @@ Standard_Integer bcbuild(Draw_Interpretor& di,
   aCBuilder.SetFuzzyValue(aTol);
   aCBuilder.SetNonDestructive(bNonDestructive);
   aCBuilder.SetGlue(aGlue);
+  aCBuilder.SetCheckInverted(BOPTest_Objects::CheckInverted());
   //
   aCBuilder.PerformWithFiller(aPF); 
   BOPTest::ReportAlerts(aCBuilder);
index d4da66df163a8033ee44d4c0e935cabcfae4691d..61c3416fa2386c24f17bf59f984245db7a1fabcb 100644 (file)
@@ -55,6 +55,7 @@ class BOPTest_Session {
     myFuzzyValue = 0.;
     myGlue = BOPAlgo_GlueOff;
     myDrawWarnShapes = Standard_False;
+    myCheckInverted = Standard_True;
   };
   //
   // Clear
@@ -142,6 +143,14 @@ class BOPTest_Session {
     return myDrawWarnShapes;
   };
   //
+  void SetCheckInverted(const Standard_Boolean bCheck) {
+    myCheckInverted = bCheck;
+  };
+  //
+  Standard_Boolean CheckInverted() const {
+    return myCheckInverted;
+  };
+  //
 protected:
   //
   BOPTest_Session(const BOPTest_Session&);
@@ -160,6 +169,7 @@ protected:
   Standard_Real myFuzzyValue;
   BOPAlgo_GlueEnum myGlue;
   Standard_Boolean myDrawWarnShapes;
+  Standard_Boolean myCheckInverted;
 };
 //
 //=======================================================================
@@ -370,6 +380,22 @@ Standard_Boolean BOPTest_Objects::DrawWarnShapes()
   return GetSession().DrawWarnShapes();
 }
 //=======================================================================
+//function : SetCheckInverted
+//purpose  : 
+//=======================================================================
+void BOPTest_Objects::SetCheckInverted(const Standard_Boolean bCheck)
+{
+  GetSession().SetCheckInverted(bCheck);
+}
+//=======================================================================
+//function : CheckInverted
+//purpose  : 
+//=======================================================================
+Standard_Boolean BOPTest_Objects::CheckInverted()
+{
+  return GetSession().CheckInverted();
+}
+//=======================================================================
 //function : Allocator1
 //purpose  : 
 //=======================================================================
index 48237ad70914bd5dc49919ccc29c801311abc2ee..02911bc0d0df3c0f8bb2eb5f92fbd3685cf2eac7 100644 (file)
@@ -87,6 +87,10 @@ public:
 
   Standard_EXPORT static Standard_Boolean DrawWarnShapes();
 
+  Standard_EXPORT static void SetCheckInverted(const Standard_Boolean bCheck);
+
+  Standard_EXPORT static Standard_Boolean CheckInverted();
+
 protected:
 
 private:
index 6366168a53f69ece7d043a550c658538d6c9c516..b90a40f5ec564ae7f6951cd3825700c8358fa7ff 100644 (file)
@@ -27,6 +27,7 @@ static Standard_Integer bnondestructive(Draw_Interpretor&, Standard_Integer, con
 static Standard_Integer bfuzzyvalue(Draw_Interpretor&, Standard_Integer, const char**);
 static Standard_Integer bGlue(Draw_Interpretor&, Standard_Integer, const char**);
 static Standard_Integer bdrawwarnshapes(Draw_Interpretor&, Standard_Integer, const char**);
+static Standard_Integer bcheckinverted(Draw_Interpretor&, Standard_Integer, const char**);
 
 //=======================================================================
 //function : OptionCommands
@@ -48,6 +49,8 @@ void BOPTest::OptionCommands(Draw_Interpretor& theCommands)
   theCommands.Add("bdrawwarnshapes", "Defines whether to draw warning shapes or not\n"
                   "Usage: bdrawwarnshapes [0 (do not draw) / 1 (draw warning shapes)",
                   __FILE__, bdrawwarnshapes, g);
+  theCommands.Add("bcheckinverted", "Defines whether to check the input solids on inverted status or not\n"
+                                     "Usage: bcheckinverted [0 (off) / 1 (on)]", __FILE__, bcheckinverted, g);
 }
 //=======================================================================
 //function : boptions
@@ -72,6 +75,7 @@ Standard_Integer boptions(Draw_Interpretor& di,
   aFuzzyValue = BOPTest_Objects::FuzzyValue();
   aGlue = BOPTest_Objects::Glue();
   Standard_Boolean bDrawWarnShapes = BOPTest_Objects::DrawWarnShapes();
+  Standard_Boolean bCheckInverted = BOPTest_Objects::CheckInverted();
   //
   Sprintf(buf, " RunParallel: %d\n",  bRunParallel);
   di << buf;
@@ -84,6 +88,8 @@ Standard_Integer boptions(Draw_Interpretor& di,
   di << buf;
   Sprintf(buf, " Draw Warning Shapes: %s\n", bDrawWarnShapes ? "Yes" : "No");
   di << buf;
+  Sprintf(buf, " Check for inverted solids: %s\n", bCheckInverted ? "Yes" : "No");
+  di << buf;
   //
   return 0;
 }
@@ -209,3 +215,21 @@ Standard_Integer bdrawwarnshapes(Draw_Interpretor& di,
   BOPTest_Objects::SetDrawWarnShapes(iDraw != 0);
   return 0;
 }
+
+//=======================================================================
+//function : bcheckinverted
+//purpose  : 
+//=======================================================================
+Standard_Integer bcheckinverted(Draw_Interpretor& di,
+                                Standard_Integer n,
+                                const char** a)
+{
+  if (n != 2) {
+    di.PrintHelp(a[0]);
+    return 1;
+  }
+  //
+  Standard_Integer iCheck = Draw::Atoi(a[1]);
+  BOPTest_Objects::SetCheckInverted(iCheck != 0);
+  return 0;
+}
index 7926a396b67f793488e06e3126fb101e3552ccaf..9cc1cea800da7e6f4bf7a8e2c494f9c90feb4aff 100644 (file)
@@ -188,6 +188,7 @@ Standard_Integer bbuild(Draw_Interpretor& di,
     }
   }
   aBuilder.SetRunParallel(bRunParallel);
+  aBuilder.SetCheckInverted(BOPTest_Objects::CheckInverted());
   //
   //
   OSD_Timer aTimer;
@@ -298,6 +299,7 @@ Standard_Integer bbop(Draw_Interpretor& di,
   }
   //
   pBuilder->SetRunParallel(bRunParallel);
+  pBuilder->SetCheckInverted(BOPTest_Objects::CheckInverted());
   //
   OSD_Timer aTimer;
   aTimer.Start();
@@ -363,6 +365,7 @@ Standard_Integer bsplit(Draw_Interpretor& di,
   pSplitter->SetRunParallel(BOPTest_Objects::RunParallel());
   pSplitter->SetNonDestructive(BOPTest_Objects::NonDestructive());
   pSplitter->SetFuzzyValue(BOPTest_Objects::FuzzyValue());
+  pSplitter->SetCheckInverted(BOPTest_Objects::CheckInverted());
   //
   // measure the time of the operation
   OSD_Timer aTimer;
index 8c1ca98818fde942eb8ee22a8ec5fc951b397bac..9ab835dc431d8898f04dc4e2633e14b491cad46f 100644 (file)
@@ -71,38 +71,28 @@ void BOPTools::MapShapesAndAncestors
   (const TopoDS_Shape& S, 
    const TopAbs_ShapeEnum TS, 
    const TopAbs_ShapeEnum TA, 
-   BOPCol_IndexedDataMapOfShapeListOfShape& aMEF)
+   BOPCol_IndexedDataMapOfShapeListOfShape& Map)
 {
-  TopExp_Explorer aExS, aExA;
-  //
   // visit ancestors
-  aExA.Init(S, TA);
-  while (aExA.More()) {
+  TopExp_Explorer aExA(S, TA);
+  for (; aExA.More(); aExA.Next())
+  {
     // visit shapes
-    const TopoDS_Shape& aF = aExA.Current();
+    const TopoDS_Shape& anAnc = aExA.Current();
     //
-    aExS.Init(aF, TS);
-    while (aExS.More()) {
-      const TopoDS_Shape& aE= aExS.Current();
-      if (aMEF.Contains(aE)) {
-        aMEF.ChangeFromKey(aE).Append(aF);
-      }
-      else {
-        BOPCol_ListOfShape aLS;
-        aLS.Append(aF);
-        aMEF.Add(aE, aLS);
-      }
-      aExS.Next();
+    TopExp_Explorer aExS(anAnc, TS);
+    for (; aExS.More(); aExS.Next())
+    {
+      const TopoDS_Shape& aSS = aExS.Current();
+      BOPCol_ListOfShape* pLA = Map.ChangeSeek(aSS);
+      if (!pLA)
+        pLA = &Map(Map.Add(aSS, BOPCol_ListOfShape()));
+      pLA->Append(anAnc);
     }
-    aExA.Next();
   }
-  //
+
   // visit shapes not under ancestors
-  aExS.Init(S, TS, TA);
-  while (aExS.More()) {
-    const TopoDS_Shape& aE=aExS.Current();
-    BOPCol_ListOfShape aLS;
-    aMEF.Add(aE, aLS);
-    aExS.Next();
-  }
+  TopExp_Explorer aExS(S, TS, TA);
+  for (; aExS.More(); aExS.Next())
+    Map.Add(aExS.Current(), BOPCol_ListOfShape());
 }
index 795686c0935cb16f0c8f51c7f071f02c173a9d56..8e29fc77c3bd5a22fc0806be750b7cae1cccf002 100644 (file)
@@ -120,52 +120,149 @@ static
 //=======================================================================
 void BOPTools_AlgoTools::MakeConnexityBlocks
   (const TopoDS_Shape& theS,
-   const TopAbs_ShapeEnum theType1,
-   const TopAbs_ShapeEnum theType2,
-   BOPCol_ListOfShape& theLCB)
+   const TopAbs_ShapeEnum theConnectionType,
+   const TopAbs_ShapeEnum theElementType,
+   BOPCol_ListOfListOfShape& theLCB,
+   BOPCol_IndexedDataMapOfShapeListOfShape& theConnectionMap)
 {
   // Map shapes to find connected elements
-  BOPCol_IndexedDataMapOfShapeListOfShape aDMSLS;
-  BOPTools::MapShapesAndAncestors(theS, theType1, theType2, aDMSLS);
+  BOPTools::MapShapesAndAncestors(theS, theConnectionType, theElementType, theConnectionMap);
   // Fence map
   BOPCol_MapOfShape aMFence;
-  Standard_Integer i;
-  BRep_Builder aBB;
-  //
-  TopExp_Explorer aExp(theS, theType2);
-  for (; aExp.More(); aExp.Next()) {
+
+  TopExp_Explorer aExp(theS, theElementType);
+  for (; aExp.More(); aExp.Next())
+  {
     const TopoDS_Shape& aS = aExp.Current();
     if (!aMFence.Add(aS)) {
       continue;
     }
     // The block
-    BOPCol_IndexedMapOfShape aMBlock;
-    TopoDS_Compound aBlock;
-    aBB.MakeCompound(aBlock);
+    BOPCol_ListOfShape aLBlock;
     // Start the block
-    aMBlock.Add(aS);
-    aBB.Add(aBlock, aS);
+    aLBlock.Append(aS);
     // Look for connected parts
-    for (i = 1; i <= aMBlock.Extent(); ++i) {
-      const TopoDS_Shape& aS1 = aMBlock(i);
-      TopExp_Explorer aExpSS(aS1, theType1);
-      for (; aExpSS.More(); aExpSS.Next()) {
+    BOPCol_ListIteratorOfListOfShape aItB(aLBlock);
+    for (; aItB.More(); aItB.Next())
+    {
+      const TopoDS_Shape& aS1 = aItB.Value();
+      TopExp_Explorer aExpSS(aS1, theConnectionType);
+      for (; aExpSS.More(); aExpSS.Next())
+      {
         const TopoDS_Shape& aSubS = aExpSS.Current();
-        const BOPCol_ListOfShape& aLS = aDMSLS.FindFromKey(aSubS);
+        const BOPCol_ListOfShape& aLS = theConnectionMap.FindFromKey(aSubS);
         BOPCol_ListIteratorOfListOfShape aItLS(aLS);
-        for (; aItLS.More(); aItLS.Next()) {
+        for (; aItLS.More(); aItLS.Next())
+        {
           const TopoDS_Shape& aS2 = aItLS.Value();
-          if (aMFence.Add(aS2)) {
-            aMBlock.Add(aS2);
-            aBB.Add(aBlock, aS2);
-          }
+          if (aMFence.Add(aS2))
+            aLBlock.Append(aS2);
         }
       }
     }
     // Add the block into result
+    theLCB.Append(aLBlock);
+  }
+}
+
+//=======================================================================
+// function: MakeConnexityBlocks
+// purpose: 
+//=======================================================================
+void BOPTools_AlgoTools::MakeConnexityBlocks
+  (const TopoDS_Shape& theS,
+   const TopAbs_ShapeEnum theConnectionType,
+   const TopAbs_ShapeEnum theElementType,
+   BOPCol_ListOfShape& theLCB)
+{
+  BOPCol_ListOfListOfShape aLBlocks;
+  BOPCol_IndexedDataMapOfShapeListOfShape aCMap;
+  BOPTools_AlgoTools::MakeConnexityBlocks(theS, theConnectionType, theElementType, aLBlocks, aCMap);
+
+  // Make compound from each block
+  BOPCol_ListIteratorOfListOfListOfShape aItB(aLBlocks);
+  for (; aItB.More(); aItB.Next())
+  {
+    const BOPCol_ListOfShape& aLB = aItB.Value();
+
+    TopoDS_Compound aBlock;
+    BRep_Builder().MakeCompound(aBlock);
+    for (BOPCol_ListIteratorOfListOfShape it(aLB); it.More(); it.Next())
+      BRep_Builder().Add(aBlock, it.Value());
+
     theLCB.Append(aBlock);
   }
 }
+
+//=======================================================================
+// function: MakeConnexityBlocks
+// purpose: 
+//=======================================================================
+void BOPTools_AlgoTools::MakeConnexityBlocks
+  (const BOPCol_ListOfShape& theLS,
+   const TopAbs_ShapeEnum theConnectionType,
+   const TopAbs_ShapeEnum theElementType,
+   BOPTools_ListOfConnexityBlock& theLCB)
+{
+  BRep_Builder aBB;
+  // Make connexity blocks from start elements
+  TopoDS_Compound aCStart;
+  aBB.MakeCompound(aCStart);
+
+  BOPCol_MapOfShape aMFence, aMNRegular;
+
+  BOPCol_ListIteratorOfListOfShape aItL(theLS);
+  for (; aItL.More(); aItL.Next())
+  {
+    const TopoDS_Shape& aS = aItL.Value();
+    if (aMFence.Add(aS))
+      aBB.Add(aCStart, aS);
+    else
+      aMNRegular.Add(aS);
+  }
+
+  BOPCol_ListOfListOfShape aLCB;
+  BOPCol_IndexedDataMapOfShapeListOfShape aCMap;
+  BOPTools_AlgoTools::MakeConnexityBlocks(aCStart, theConnectionType, theElementType, aLCB, aCMap);
+
+  // Save the blocks and check their regularity
+  BOPCol_ListIteratorOfListOfListOfShape aItB(aLCB);
+  for (; aItB.More(); aItB.Next())
+  {
+    const BOPCol_ListOfShape& aBlock = aItB.Value();
+
+    BOPTools_ConnexityBlock aCB;
+    BOPCol_ListOfShape& aLCS = aCB.ChangeShapes();
+
+    Standard_Boolean bRegular = Standard_True;
+    for (BOPCol_ListIteratorOfListOfShape it(aBlock); it.More(); it.Next())
+    {
+      TopoDS_Shape aS = it.Value();
+      if (aMNRegular.Contains(aS))
+      {
+        bRegular = Standard_False;
+        aS.Orientation(TopAbs_FORWARD);
+        aLCS.Append(aS);
+        aS.Orientation(TopAbs_REVERSED);
+        aLCS.Append(aS);
+      }
+      else
+      {
+        aLCS.Append(aS);
+        if (bRegular)
+        {
+          // Check if there are no multi-connected shapes
+          for (TopExp_Explorer ex(aS, theConnectionType); ex.More() && bRegular; ex.Next())
+            bRegular = (aCMap.FindFromKey(ex.Current()).Extent() == 2);
+        }
+      }
+    }
+
+    aCB.SetRegular(bRegular);
+    theLCB.Append(aCB);
+  }
+}
+
 //=======================================================================
 // function: OrientEdgesOnWire
 // purpose: Reorient edges on wire for correct ordering
index dddfb07ae2ac80da80ba4585b4afc8cc970a358a..84a75e7eeb19f97a0da79e7a8578d352e32a0563 100644 (file)
@@ -28,7 +28,9 @@
 #include <Standard_Boolean.hxx>
 #include <TopAbs_ShapeEnum.hxx>
 #include <BOPTools_ListOfCoupleOfShape.hxx>
+#include <BOPTools_ListOfConnexityBlock.hxx>
 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
+#include <BOPCol_ListOfListOfShape.hxx>
 #include <TopAbs_State.hxx>
 #include <BOPCol_IndexedMapOfShape.hxx>
 #include <BOPCol_BaseAllocator.hxx>
@@ -188,11 +190,34 @@ public:
   //! theMapAvoid - set of edges to avoid for
   //! the treatment
   Standard_EXPORT static void MakeConnexityBlock (BOPCol_ListOfShape& theLS, BOPCol_IndexedMapOfShape& theMapAvoid, BOPCol_ListOfShape& theLSCB, const BOPCol_BaseAllocator& theAllocator);
-  
-  //! For the compound theS build the blocks
-  //! theLCB (as list of compounds)
-  //! in terms of connexity by the shapes of theType
-  Standard_EXPORT static void MakeConnexityBlocks (const TopoDS_Shape& theS, const TopAbs_ShapeEnum theType1, const TopAbs_ShapeEnum theType2, BOPCol_ListOfShape& theLCB);
+
+  //! For the compound <theS> builds the blocks (compounds) of
+  //! elements of type <theElementType> connected through the shapes
+  //! of the type <theConnectionType>.
+  //! The blocks are stored into the list <theLCB>.
+  Standard_EXPORT static void MakeConnexityBlocks(const TopoDS_Shape& theS,
+                                                  const TopAbs_ShapeEnum theConnectionType,
+                                                  const TopAbs_ShapeEnum theElementType,
+                                                  BOPCol_ListOfShape& theLCB);
+
+  //! For the compound <theS> builds the blocks (compounds) of
+  //! elements of type <theElementType> connected through the shapes
+  //! of the type <theConnectionType>.
+  //! The blocks are stored into the list of lists <theLCB>.
+  //! Returns also the connection map <theConnectionMap>, filled during operation.
+  Standard_EXPORT static void MakeConnexityBlocks(const TopoDS_Shape& theS,
+                                                  const TopAbs_ShapeEnum theConnectionType,
+                                                  const TopAbs_ShapeEnum theElementType,
+                                                  BOPCol_ListOfListOfShape& theLCB,
+                                                  BOPCol_IndexedDataMapOfShapeListOfShape& theConnectionMap);
+
+  //! Makes connexity blocks of elements of the given type with the given type of the
+  //! connecting elements. The blocks are checked on regularity (multi-connectivity)
+  //! and stored to the list of blocks <theLCB>.
+  Standard_EXPORT static void MakeConnexityBlocks(const BOPCol_ListOfShape& theLS,
+                                                  const TopAbs_ShapeEnum theConnectionType,
+                                                  const TopAbs_ShapeEnum theElementType,
+                                                  BOPTools_ListOfConnexityBlock& theLCB);
 
   //! Correctly orients edges on the wire
   Standard_EXPORT static void OrientEdgesOnWire (TopoDS_Shape& theWire);
index 9697b92f561c0d37a9d62568ee3731cef13d58ad..744ca527f26f98a4b51a2c1c74ca0b578f6af836 100644 (file)
@@ -66,9 +66,6 @@
 #include <TopoDS_Edge.hxx>
 #include <TopoDS_Face.hxx>
 
-static 
-  Standard_Boolean CheckEdgeLength (const TopoDS_Edge& );
-
 static
   Handle(Geom2d_Curve) BRep_Tool_CurveOnSurface(const TopoDS_Edge& , 
                                                 const TopoDS_Face& ,
@@ -132,9 +129,6 @@ Standard_Boolean BOPTools_AlgoTools2D::EdgeTangent
   if (isdgE) {
     return Standard_False;
   }
-  if (!CheckEdgeLength(anEdge)) {
-    return Standard_False;
-  }
 
   Handle(Geom_Curve) aC=BRep_Tool::Curve(anEdge, first, last);
   gp_Pnt aP;
@@ -686,44 +680,6 @@ void BOPTools_AlgoTools2D::MakePCurveOnFace
   }
 }
 
-//=======================================================================
-//function : CheckEdgeLength
-//purpose  : 
-//=======================================================================
-Standard_Boolean CheckEdgeLength (const TopoDS_Edge& E)
-{
-  BRepAdaptor_Curve BC(E);
-
-  BOPCol_IndexedMapOfShape aM;
-  BOPTools::MapShapes(E, TopAbs_VERTEX, aM);
-  Standard_Integer i, anExtent, aN=10;
-  Standard_Real ln=0., d, t, f, l, dt; 
-  anExtent=aM.Extent();
-
-  if (anExtent!=1) 
-    return Standard_True;
-    
-  gp_Pnt p1, p2;
-  f = BC.FirstParameter();
-  l = BC.LastParameter();
-  dt=(l-f)/aN;
-  
-  BC.D0(f, p1);
-  for (i=1; i<=aN; i++) {
-    t=f+i*dt;
-    
-    if (i==aN) 
-      BC.D0(l, p2);
-    else 
-      BC.D0(t, p2);
-    
-    d=p1.Distance(p2);
-    ln+=d;
-    p1=p2;
-  }
-  //
-  return (ln > Precision::Confusion()); 
-}
 //=======================================================================
 //function : BRep_Tool_CurveOnSurface
 //purpose  : 
index f10a2812131a908abb536f85ee35c39ef44c7d12..34ce166e405fa467cb712a76df9323591fe5863b 100644 (file)
@@ -113,14 +113,6 @@ static
                    const Standard_Real aTol,
                    const BOPCol_IndexedMapOfShape& aMapToAvoid);
 
-static 
-  Standard_Real IntersectCurves2d(const TopoDS_Vertex& theV,
-                                  const TopoDS_Face& theF,
-                                  const Handle(Geom_Surface)& theS,
-                                  const TopoDS_Edge& theE1,
-                                  const TopoDS_Edge& theE2,
-                   NCollection_DataMap<TopoDS_Shape, Standard_Real>& theMapEdgeLen);
-
 //=======================================================================
 //class    : BOPTools_CPC
 //purpose  : 
@@ -477,55 +469,43 @@ void CheckEdge (const TopoDS_Edge& Ed,
                 const Standard_Real aMaxTol,
                 const BOPCol_IndexedMapOfShape& aMapToAvoid)
 {
-  Standard_Real aTolE, aTol, aD2, aNewTolerance, dd;
-  gp_Pnt aPC;
-  TopLoc_Location L;
-  TopoDS_Edge aE;
-  TopoDS_Vertex aV;
-  TopoDS_Iterator aItS;
-  //
-  TopAbs_Orientation aOrV;
-  BRep_ListIteratorOfListOfPointRepresentation aItPR;
-  BRep_ListIteratorOfListOfCurveRepresentation aItCR;
-  //
-  aE=Ed;
+  TopoDS_Edge aE = Ed;
   aE.Orientation(TopAbs_FORWARD);
-  aTolE=BRep_Tool::Tolerance(aE);
+  Standard_Real aTolE = BRep_Tool::Tolerance(aE);
   //
   Handle(BRep_TEdge)& TE = *((Handle(BRep_TEdge)*)&aE.TShape());
   //
-  aItS.Initialize(aE);
+  const TopLoc_Location& Eloc = aE.Location();
+
+  TopoDS_Iterator aItS(aE);
   for (; aItS.More(); aItS.Next()) {
-    aV= TopoDS::Vertex(aItS.Value());
+    const TopoDS_Vertex& aV= TopoDS::Vertex(aItS.Value());
     //
     Handle(BRep_TVertex)& TV=*((Handle(BRep_TVertex)*)&aV.TShape());
     const gp_Pnt& aPV = TV->Pnt();
     //
-    aTol=BRep_Tool::Tolerance(aV);
+    Standard_Real aTol=BRep_Tool::Tolerance(aV);
     aTol=Max(aTol, aTolE);
-    dd=0.1*aTol;
+    Standard_Real dd=0.1*aTol;
     aTol*=aTol;
     //
-    const TopLoc_Location& Eloc = aE.Location();
-    //
-    aItCR.Initialize(TE->Curves());
+    BRep_ListIteratorOfListOfCurveRepresentation aItCR(TE->Curves());
     while (aItCR.More()) {
       const Handle(BRep_CurveRepresentation)& aCR = aItCR.Value();
-      const TopLoc_Location& loc = aCR->Location();
-      L = (Eloc * loc).Predivided(aV.Location());
       //
       if (aCR->IsCurve3D()) {
         const Handle(Geom_Curve)& aC = aCR->Curve3D();
         if (!aC.IsNull()) {
-          aItPR.Initialize(TV->Points());
+          TopLoc_Location L = (Eloc * aCR->Location()).Predivided(aV.Location());
+          BRep_ListIteratorOfListOfPointRepresentation aItPR(TV->Points());
           while (aItPR.More()) {
             const Handle(BRep_PointRepresentation)& aPR=aItPR.Value();
             if (aPR->IsPointOnCurve(aC, L)) {
-              aPC = aC->Value(aPR->Parameter());
+              gp_Pnt aPC = aC->Value(aPR->Parameter());
               aPC.Transform(L.Transformation());
-              aD2=aPV.SquareDistance(aPC);
+              Standard_Real aD2=aPV.SquareDistance(aPC);
               if (aD2 > aTol) {
-                aNewTolerance=sqrt(aD2)+dd;
+                Standard_Real aNewTolerance=sqrt(aD2)+dd;
                 if (aNewTolerance<aMaxTol)
                   UpdateShape(aV, aNewTolerance, aMapToAvoid);
               }
@@ -533,10 +513,10 @@ void CheckEdge (const TopoDS_Edge& Ed,
             aItPR.Next();
           }
           //
-          aOrV=aV.Orientation();
+          TopAbs_Orientation aOrV=aV.Orientation();
           if (aOrV==TopAbs_FORWARD || aOrV==TopAbs_REVERSED) {
             Handle(BRep_GCurve) aGC (Handle(BRep_GCurve)::DownCast (aCR));
-            
+            gp_Pnt aPC;
             if (aOrV==TopAbs_FORWARD) {
               aPC=aC->Value(aGC->First());
             }
@@ -545,9 +525,9 @@ void CheckEdge (const TopoDS_Edge& Ed,
             }
             aPC.Transform(L.Transformation());
             //
-            aD2=aPV.SquareDistance(aPC);
+            Standard_Real aD2=aPV.SquareDistance(aPC);
             if (aD2 > aTol) {
-              aNewTolerance=sqrt(aD2)+dd;
+              Standard_Real aNewTolerance=sqrt(aD2)+dd;
               if (aNewTolerance<aMaxTol) 
                 UpdateShape(aV, aNewTolerance, aMapToAvoid);
             }
@@ -558,80 +538,6 @@ void CheckEdge (const TopoDS_Edge& Ed,
     }//  while (itcr.More()) {  
   } // for (; aVExp.More(); aVExp.Next()) {
 }
-//=======================================================================
-// Function : CorrectWires
-// purpose : 
-//=======================================================================
-void CorrectWires(const TopoDS_Face& aFx,
-                  const BOPCol_IndexedMapOfShape& aMapToAvoid)
-{
-  Standard_Integer i, aNbV;
-  Standard_Real aTol, aTol2, aD2, aD2max, aT1, aT2, aT;
-  gp_Pnt aP, aPV;
-  gp_Pnt2d aP2D;
-  TopoDS_Face aF;
-  TopTools_IndexedDataMapOfShapeListOfShape aMVE;
-  TopTools_ListIteratorOfListOfShape aIt, aIt1;
-  //
-  aF=aFx;
-  aF.Orientation(TopAbs_FORWARD);
-  const Handle(Geom_Surface)& aS=BRep_Tool::Surface(aFx);
-  //
-  TopExp::MapShapesAndAncestors(aF, 
-                                TopAbs_VERTEX, 
-                                TopAbs_EDGE, 
-                                aMVE);
-  NCollection_DataMap<TopoDS_Shape, Standard_Real> aMapEdgeLen;
-  aNbV=aMVE.Extent();
-  for (i=1; i<=aNbV; ++i) {
-    const TopoDS_Vertex& aV=*((TopoDS_Vertex*)&aMVE.FindKey(i));
-    aPV=BRep_Tool::Pnt(aV);
-    aTol=BRep_Tool::Tolerance(aV);
-    aTol2=aTol*aTol;
-    //
-    aD2max=-1.;
-    const TopTools_ListOfShape& aLE=aMVE.FindFromIndex(i);
-    aIt.Initialize(aLE);
-    for (; aIt.More(); aIt.Next()) {
-      const TopoDS_Edge& aE=*(TopoDS_Edge*)(&aIt.Value());
-      const Handle(Geom2d_Curve)& aC2D=
-        BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
-      aT=BRep_Tool::Parameter(aV, aE);
-      //
-      aC2D->D0(aT, aP2D);
-      aS->D0(aP2D.X(), aP2D.Y(), aP);
-      aD2=aPV.SquareDistance(aP);
-      if (aD2>aD2max) {
-        aD2max=aD2;
-      }
-    }
-    //
-    //check wires on self interference by intersecting 2d curves of the edges
-    aIt.Initialize(aLE);
-    for (; aIt.More(); aIt.Next()) {
-      const TopoDS_Edge& aE1 = *(TopoDS_Edge*)&aIt.Value();
-      //
-      aIt1 = aIt;
-      for (aIt1.Next(); aIt1.More(); aIt1.Next()) {
-        const TopoDS_Edge& aE2 = *(TopoDS_Edge*)&aIt1.Value();
-        //
-        if (aE1.IsSame(aE2)) {
-          continue;
-        }
-        //
-        aD2 = IntersectCurves2d(aV, aF, aS, aE1, aE2, aMapEdgeLen);
-        if (aD2 > aD2max) {
-          aD2max = aD2;
-        }
-      }
-    }
-    //
-    if (aD2max>aTol2) {
-      aTol = 1.01 * sqrt(aD2max);
-      UpdateShape(aV, aTol, aMapToAvoid);
-    }
-  }// for (i=1; i<=aNbV; ++i) {
-}
 
 //=======================================================================
 // Function : MapEdgeLength
@@ -653,35 +559,48 @@ static Standard_Real MapEdgeLength(const TopoDS_Edge& theEdge,
   }
   return *pLen;
 }
+
+//=======================================================================
+// Function : EdgeData
+// purpose : Structure to store edge data
+//=======================================================================
+namespace {
+  struct EdgeData {
+    const TopoDS_Edge* Edge; // Edge
+    Standard_Real VParameter; // Parameter of the vertex on the edge
+    Geom2dAdaptor_Curve GAdaptor; // 2D adaptor for PCurve of the edge on the face
+    Standard_Real First; // First parameter in the range
+    Standard_Real Last; // Last parameter in the rage
+  };
+}
 //=======================================================================
 // Function : IntersectCurves2d
 // purpose  : Intersect 2d curves of edges
 //=======================================================================
-Standard_Real IntersectCurves2d(const TopoDS_Vertex& theV,
-                                const TopoDS_Face& theF,
-                                const Handle(Geom_Surface)& theS,
-                                const TopoDS_Edge& theE1,
-                                const TopoDS_Edge& theE2,
-                                NCollection_DataMap<TopoDS_Shape, Standard_Real>& theMapEdgeLen)
+static
+  Standard_Real IntersectCurves2d(const TopoDS_Vertex& theV,
+                                  const Handle(Geom_Surface)& theS,
+                                  const EdgeData& theEData1,
+                                  const EdgeData& theEData2,
+                                  NCollection_DataMap<TopoDS_Shape, Standard_Real>& theMapEdgeLen)
 {
-  Standard_Real aT11, aT12, aT21, aT22, aTol2d, aMaxDist;
   Geom2dInt_GInter anInter;
+  // Range of the first edge
+  Standard_Real aT11 = theEData1.First;
+  Standard_Real aT12 = theEData1.Last;
+  // Range of the second edge
+  Standard_Real aT21 = theEData2.First;
+  Standard_Real aT22 = theEData2.Last;
+
+  Standard_Real aMaxDist = 0.;
+  Standard_Real aTol2d = 1.e-10;
   //
-  aMaxDist = 0.;
-  aTol2d = 1.e-10;
-  //
-  const Handle(Geom2d_Curve)& aC2D1=
-    BRep_Tool::CurveOnSurface(theE1, theF, aT11, aT12);
-  const Handle(Geom2d_Curve)& aC2D2=
-    BRep_Tool::CurveOnSurface(theE2, theF, aT21, aT22);
-  //
-  Geom2dAdaptor_Curve aGAC1(aC2D1), aGAC2(aC2D2);
-  IntRes2d_Domain aDom1(aC2D1->Value(aT11), aT11, aTol2d, 
-                        aC2D1->Value(aT12), aT12, aTol2d);
-  IntRes2d_Domain aDom2(aC2D2->Value(aT21), aT21, aTol2d, 
-                        aC2D2->Value(aT22), aT22, aTol2d);
+  IntRes2d_Domain aDom1(theEData1.GAdaptor.Value(aT11), aT11, aTol2d,
+                        theEData1.GAdaptor.Value(aT12), aT12, aTol2d);
+  IntRes2d_Domain aDom2(theEData2.GAdaptor.Value(aT21), aT21, aTol2d,
+                        theEData2.GAdaptor.Value(aT22), aT22, aTol2d);
   //
-  anInter.Perform(aGAC1, aDom1, aGAC2, aDom2, aTol2d, aTol2d);
+  anInter.Perform(theEData1.GAdaptor, aDom1, theEData2.GAdaptor, aDom2, aTol2d, aTol2d);
   if (!anInter.IsDone() || (!anInter.NbSegments() && !anInter.NbPoints())) {
     return aMaxDist;
   }
@@ -694,8 +613,8 @@ Standard_Real IntersectCurves2d(const TopoDS_Vertex& theV,
   NCollection_List<IntRes2d_IntersectionPoint>::Iterator aItLP;
   //
   aPV = BRep_Tool::Pnt(theV);
-  aT1 = BRep_Tool::Parameter(theV, theE1);
-  aT2 = BRep_Tool::Parameter(theV, theE2);
+  aT1 = theEData1.VParameter;
+  aT2 = theEData2.VParameter;
   //
   aHalfR1 = (aT12 - aT11) / 2.;
   aHalfR2 = (aT22 - aT21) / 2.;
@@ -716,8 +635,8 @@ Standard_Real IntersectCurves2d(const TopoDS_Vertex& theV,
   }
   //
   // evaluate the length of the smallest edge, so that not to return too large distance
-  Standard_Real aLen1 = MapEdgeLength(theE1, theMapEdgeLen);
-  Standard_Real aLen2 = MapEdgeLength(theE2, theMapEdgeLen);
+  Standard_Real aLen1 = MapEdgeLength(*theEData1.Edge, theMapEdgeLen);
+  Standard_Real aLen2 = MapEdgeLength(*theEData1.Edge, theMapEdgeLen);
   const Standard_Real MaxEdgePartCoveredByVertex = 0.3;
   Standard_Real aMaxThresDist = Min(aLen1, aLen2) * MaxEdgePartCoveredByVertex;
   aMaxThresDist *= aMaxThresDist;
@@ -750,6 +669,86 @@ Standard_Real IntersectCurves2d(const TopoDS_Vertex& theV,
   //
   return aMaxDist;
 }
+//=======================================================================
+// Function : CorrectWires
+// purpose : 
+//=======================================================================
+void CorrectWires(const TopoDS_Face& aFx,
+                  const BOPCol_IndexedMapOfShape& aMapToAvoid)
+{
+  Standard_Integer i, aNbV;
+  Standard_Real aTol, aTol2, aD2, aD2max, aT1, aT2, aT;
+  gp_Pnt aP, aPV;
+  gp_Pnt2d aP2D;
+  TopoDS_Face aF;
+  TopTools_IndexedDataMapOfShapeListOfShape aMVE;
+  TopTools_ListIteratorOfListOfShape aIt;
+  //
+  aF=aFx;
+  aF.Orientation(TopAbs_FORWARD);
+  const Handle(Geom_Surface)& aS=BRep_Tool::Surface(aFx);
+  //
+  TopExp::MapShapesAndAncestors(aF, 
+                                TopAbs_VERTEX, 
+                                TopAbs_EDGE, 
+                                aMVE);
+  NCollection_DataMap<TopoDS_Shape, Standard_Real> aMapEdgeLen;
+  aNbV=aMVE.Extent();
+  for (i=1; i<=aNbV; ++i) {
+    const TopoDS_Vertex& aV=*((TopoDS_Vertex*)&aMVE.FindKey(i));
+    aPV=BRep_Tool::Pnt(aV);
+    aTol=BRep_Tool::Tolerance(aV);
+    aTol2=aTol*aTol;
+    //
+    aD2max=-1.;
+    // Save edge's data to avoid its recalculation during intersection of 2d curves
+    NCollection_List<EdgeData> aLEPars;
+    const TopTools_ListOfShape& aLE=aMVE.FindFromIndex(i);
+    aIt.Initialize(aLE);
+    for (; aIt.More(); aIt.Next()) {
+      const TopoDS_Edge& aE=*(TopoDS_Edge*)(&aIt.Value());
+      const Handle(Geom2d_Curve)& aC2D=
+        BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
+      aT=BRep_Tool::Parameter(aV, aE);
+      //
+      aC2D->D0(aT, aP2D);
+      aS->D0(aP2D.X(), aP2D.Y(), aP);
+      aD2=aPV.SquareDistance(aP);
+      if (aD2>aD2max) {
+        aD2max=aD2;
+      }
+      EdgeData anEData = {&aE, aT, Geom2dAdaptor_Curve(aC2D), aT1, aT2};
+      aLEPars.Append(anEData);
+    }
+    //
+    //check wires on self interference by intersecting 2d curves of the edges
+    NCollection_List<EdgeData>::Iterator aItE1(aLEPars);
+    for (; aItE1.More(); aItE1.Next()) {
+      const EdgeData& aEData1 = aItE1.Value();
+      const TopoDS_Shape& aE1 = *aEData1.Edge;
+
+      NCollection_List<EdgeData>::Iterator aItE2 = aItE1;
+      for (aItE2.Next(); aItE2.More(); aItE2.Next()) {
+        const EdgeData& aEData2 = aItE2.Value();
+        const TopoDS_Shape& aE2 = *aEData2.Edge;
+
+        if (aE1.IsSame(aE2))
+          continue;
+
+        aD2 = IntersectCurves2d(aV, aS, aEData1, aEData2, aMapEdgeLen);
+        if (aD2 > aD2max) {
+          aD2max = aD2;
+        }
+      }
+    }
+    //
+    if (aD2max>aTol2) {
+      aTol = 1.01 * sqrt(aD2max);
+      UpdateShape(aV, aTol, aMapToAvoid);
+    }
+  }// for (i=1; i<=aNbV; ++i) {
+}
+
 //=======================================================================
 // Function : CorrectEdgeTolerance
 // purpose :  Correct tolerances for Edge 
index 4758f382638475aa1a0f9dfd86138cd4fcdcd5e8..1850e0e7dc7e8cd52a22c781d12ccb99c15d0f5f 100644 (file)
@@ -55,6 +55,7 @@ public:
   using BOPAlgo_Options::ClearWarnings;
   using BOPAlgo_Options::GetReport;
   using BOPAlgo_Options::SetProgressIndicator;
+  using BOPAlgo_Options::SetCheckInverted;
 
 protected:
 
index 6fe309ed9ca9212b7082835a7bdf113abcab12fb..dbddf3dd9363bd94e8c3341d1551fe12c540180c 100644 (file)
@@ -353,6 +353,7 @@ void BRepAlgoAPI_BooleanOperation::Build()
   //
   myBuilder->SetRunParallel(myRunParallel);
   myBuilder->SetProgressIndicator(myProgressIndicator);
+  myBuilder->SetCheckInverted(myCheckInverted);
   //
   myBuilder->PerformWithFiller(*myDSFiller);
   //
index 824b5f47de4a94c3abd877f2745067d7e068fd09..f0c565f770c07e1e6a8ca3c08476c0fcf3918636 100644 (file)
@@ -163,6 +163,7 @@ void BRepAlgoAPI_BuilderAlgo::Build()
   //
   myBuilder->SetRunParallel(myRunParallel);
   myBuilder->SetProgressIndicator(myProgressIndicator);
+  myBuilder->SetCheckInverted(myCheckInverted);
   //
   myBuilder->PerformWithFiller(*myDSFiller);
   //
index c2290932aaa8c2675bd7a2f9cb678b3fdb62f40e..b28fb2f37331cd95b090c2841bc4a80d78a8ba09 100644 (file)
@@ -121,6 +121,7 @@ void BRepAlgoAPI_Splitter::Build()
   //
   myBuilder->SetRunParallel(myRunParallel);
   myBuilder->SetProgressIndicator(myProgressIndicator);
+  myBuilder->SetCheckInverted(myCheckInverted);
   //
   myBuilder->PerformWithFiller(*myDSFiller);
   //
index 61c60d1b9eb45acd330909824fc521b6e2404293..2ce57e0529365c592a21aab193a709e94b20beab 100644 (file)
@@ -222,7 +222,11 @@ Standard_Boolean IntTools_EdgeFace::IsCoincident()
   //
   GeomAPI_ProjectPointOnSurf& aProjector=myContext->ProjPS(myFace);
 
-  const Standard_Integer aNbSeg=23;
+  Standard_Integer aNbSeg=23;
+  if (myC.GetType() == GeomAbs_Line &&
+      myS.GetType() == GeomAbs_Plane)
+    aNbSeg = 2; // Check only three points for Line/Plane intersection
+
   const Standard_Real aTresh=0.5;
   const Standard_Integer aTreshIdxF = RealToInt((aNbSeg+1)*0.25),
                          aTreshIdxL = RealToInt((aNbSeg+1)*0.75);
index a13cbbf25bced44ee734f2a0beda42f49ffc3760..ee8d31e96bbfdc0f79fb647c7454a851fef65211 100644 (file)
@@ -1,5 +1,3 @@
-puts "TODO ?OCC26018 ALL: Faulty shapes in variables faulty_1 to faulty_"
-
 # test script for freeform_revol_01.prt.1.gdml file
 compound result
 
diff --git a/tests/bugs/modalg_7/bug28485 b/tests/bugs/modalg_7/bug28485
new file mode 100644 (file)
index 0000000..2cb8553
--- /dev/null
@@ -0,0 +1,28 @@
+puts "========"
+puts "OCC28485"
+puts "========"
+puts ""
+##################################################################################
+# Fuse of two shapes using gluing and non-destructive options gives invalid result
+##################################################################################
+
+restore [locate_data_file bug28485_parts.brep] a
+explode a
+
+bnondestructive 1
+brunparallel 1
+bfuzzyvalue 0
+bglue 1
+
+bclearobjects
+bcleartools
+baddobjects a_1
+baddtools a_2
+bfillds
+bbop result 1
+
+checkshape result
+checknbshapes result -wire 324 -face 310 -shell 1 -solid 1
+checkprops result -s 103610 -v 111128
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/bugs/modalg_7/bug28485_1 b/tests/bugs/modalg_7/bug28485_1
new file mode 100644 (file)
index 0000000..ea05d79
--- /dev/null
@@ -0,0 +1,28 @@
+puts "========"
+puts "OCC28485"
+puts "========"
+puts ""
+##################################################################################
+# Fuse of two shapes using gluing and non-destructive options gives invalid result
+##################################################################################
+
+box b1 10 10 10
+box b2 10 2 2 6 6 6
+nurbsconvert b1 b1
+nurbsconvert b2 b2
+
+bnondestructive 1
+brunparallel 1
+bfuzzyvalue 0
+bglue 1
+
+bclearobjects
+bcleartools
+baddobjects b1
+baddtools b2
+bfillds
+bbop result 1
+
+checkshape result
+checknbshapes result -vertex 16 -edge 24 -wire 12 -face 11 -shell 1 -solid 1
+checkprops result -s 744 -v 1216
diff --git a/tests/perf/modalg/bug29237_1 b/tests/perf/modalg/bug29237_1
new file mode 100644 (file)
index 0000000..37ff7bf
--- /dev/null
@@ -0,0 +1,46 @@
+puts "======="
+puts "0029237"
+puts "======="
+puts ""
+##################################################
+# Improve performance of Boolean Operations
+##################################################
+
+brestore [locate_data_file bug29237_tc_43.1_lhs.brep] a
+brestore [locate_data_file bug29237_tc_43.1_rhs.brep] b
+
+bglue 1
+bcheckinverted 0
+
+bclearobjects
+bcleartools
+baddobjects a
+baddtools b
+
+# start chronometer
+dchrono cpu restart
+bfillds
+
+bcbuild r
+
+# build the result of cut
+bcremoveall
+bcadd rcut a 1 b 0
+
+# build the result of common
+bcremoveall
+bcadd rcommon a 1 b 1
+
+# stop chronometer
+dchrono cpu stop counter OCC29237
+
+
+# check the result of CUT
+checkshape rcut
+checknbshapes rcut -vertex 640 -edge 1760 -wire 842 -face 842 -shell 1 -solid 1
+checkprops rcut -s 3.4136e+006 -v 2.9712e+007
+
+# check the result of COMMON
+checkshape rcommon
+checknbshapes rcommon -vertex 616 -edge 1484 -wire 882 -face 882 -shell 147 -solid 147
+checkprops rcommon -s 2.13392e+006 -v 1.6448e+007
diff --git a/tests/perf/modalg/bug29237_2 b/tests/perf/modalg/bug29237_2
new file mode 100644 (file)
index 0000000..d7024b8
--- /dev/null
@@ -0,0 +1,46 @@
+puts "======="
+puts "0029237"
+puts "======="
+puts ""
+##################################################
+# Improve performance of Boolean Operations
+##################################################
+
+brestore [locate_data_file bug29237_dom8364_s32_c2.lhs.brep] a
+brestore [locate_data_file bug29237_dom8364_s32_c2.rhs.brep] b
+
+bglue 1
+bcheckinverted 0
+
+bclearobjects
+bcleartools
+baddobjects a
+baddtools b
+
+# start chronometer
+dchrono cpu restart
+bfillds
+
+bcbuild r
+
+# build the result of cut
+bcremoveall
+bcadd rcut a 1 b 0
+
+# build the result of common
+bcremoveall
+bcadd rcommon a 1 b 1
+
+# stop chronometer
+dchrono cpu stop counter OCC29237
+
+
+# check the result of CUT
+checkshape rcut
+checknbshapes rcut -vertex 7374 -edge 13894 -wire 4944 -face 4711 -shell 29 -solid 29
+checkprops rcut -s 5.81474e+006 -v 1.32791e+007
+
+# check the result of COMMON
+checkshape rcommon
+checknbshapes rcommon -vertex 6454 -edge 9662 -wire 4462 -face 4462 -shell 627 -solid 627
+checkprops rcommon -s 1.81935e+006 -v 1.6368e+006
diff --git a/tests/perf/modalg/bug29237_3 b/tests/perf/modalg/bug29237_3
new file mode 100644 (file)
index 0000000..1f38f4f
--- /dev/null
@@ -0,0 +1,46 @@
+puts "======="
+puts "0029237"
+puts "======="
+puts ""
+##################################################
+# Improve performance of Boolean Operations
+##################################################
+
+brestore [locate_data_file bug29237_no_overlap.lhs.brep] a
+brestore [locate_data_file bug29237_no_overlap.rhs.brep] b
+
+bglue 1
+bcheckinverted 0
+
+bclearobjects
+bcleartools
+baddobjects a
+baddtools b
+
+# start chronometer
+dchrono cpu restart
+bfillds
+
+bcbuild r
+
+# build the result of cut
+bcremoveall
+bcadd rcut a 1 b 0
+
+# build the result of common
+bcremoveall
+bcadd rcommon a 1 b 1
+
+# stop chronometer
+dchrono cpu stop counter OCC29237
+
+
+# check the result of CUT
+checkshape rcut
+checknbshapes rcut -vertex 1294 -edge 3074 -wire 1842 -face 1842 -shell 301 -solid 301
+checkprops rcut -s 2.59678e+006 -v 1.5346e+007
+
+# check the result of COMMON
+checkshape rcommon
+checknbshapes rcommon -vertex 0 -edge 0 -wire 0 -face 0 -shell 0 -solid 0
+checkprops rcommon -s empty -v empty