]> OCCT Git - occt-copy.git/commitdiff
0029711: General Fuse operation produces invalid result
authoremv <emv@opencascade.com>
Wed, 16 May 2018 09:12:09 +0000 (12:12 +0300)
committeremv <emv@opencascade.com>
Fri, 29 Jun 2018 10:55:30 +0000 (13:55 +0300)
Boolean Operations algorithm improvements:
1. To be able to add/remove elements into the tree of bounding boxes UBTree is replaced with EBTree in Boolean operations.
2. Perform repeated (nested) intersection of sub-shapes of the arguments with vertices which tolerances have been increased during the operation.
3. Edge/Edge and Edge/Face intersection point creation improvement for the cases when intersection point is located close to the edge's boundaries.
4. Forced Edge/Face intersection procedure to ensure common blocks creation.
5. Face/Face intersection post treatment stage improvements.
6. Avoid extension of the planar faces for Plane/Plane intersection.
7. Builder Face algorithm - improve classification of the potentially internal edges relatively new faces by adding filtering by bounding boxes.

Side effect changes:
1. IntTools_ShrunkRange is now keeps the length of the valid range of the edge.
2. The method BOPDS_DS::UpdateEdgeTolerance() has been removed as unused (replaced by the BOPAlgo_PaveFiller::UpdateEdgeTolerance()).

Test case for the issue 0029900.
Test case for the issue 0029711.
Adjustments of the existing test cases.

53 files changed:
src/BOPAlgo/BOPAlgo.msg
src/BOPAlgo/BOPAlgo_Alerts.hxx
src/BOPAlgo/BOPAlgo_BOPAlgo_msg.pxx
src/BOPAlgo/BOPAlgo_BuilderFace.cxx
src/BOPAlgo/BOPAlgo_BuilderSolid.cxx
src/BOPAlgo/BOPAlgo_Builder_2.cxx
src/BOPAlgo/BOPAlgo_PaveFiller.cxx
src/BOPAlgo/BOPAlgo_PaveFiller.hxx
src/BOPAlgo/BOPAlgo_PaveFiller_1.cxx
src/BOPAlgo/BOPAlgo_PaveFiller_10.cxx
src/BOPAlgo/BOPAlgo_PaveFiller_2.cxx
src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx
src/BOPAlgo/BOPAlgo_PaveFiller_4.cxx
src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx
src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx
src/BOPAlgo/BOPAlgo_PaveFiller_7.cxx
src/BOPAlgo/BOPAlgo_Tools.cxx
src/BOPAlgo/BOPAlgo_Tools.hxx
src/BOPCol/BOPCol_BoxBndTree.hxx
src/BOPDS/BOPDS_CommonBlock.cxx
src/BOPDS/BOPDS_CommonBlock.hxx
src/BOPDS/BOPDS_DS.cxx
src/BOPDS/BOPDS_DS.hxx
src/BOPDS/BOPDS_DS.lxx
src/BOPDS/BOPDS_Iterator.cxx
src/BOPDS/BOPDS_Iterator.hxx
src/BOPTest/BOPTest_DebugCommands.cxx
src/BOPTools/BOPTools_AlgoTools.cxx
src/IntTools/IntTools_Context.cxx
src/IntTools/IntTools_EdgeFace.cxx
src/IntTools/IntTools_FaceFace.cxx
src/IntTools/IntTools_ShrunkRange.cxx
src/IntTools/IntTools_ShrunkRange.hxx
tests/boolean/bcut_complex/F2
tests/boolean/bfuse_complex/E4
tests/boolean/bfuse_complex/F5
tests/boolean/bfuse_complex/Q2
tests/boolean/bsection/N2
tests/boolean/bsection/R8
tests/bugs/modalg_1/buc60462_2
tests/bugs/modalg_1/buc60703_3
tests/bugs/modalg_2/bug472_1
tests/bugs/modalg_2/bug472_2
tests/bugs/modalg_2/bug472_3
tests/bugs/modalg_6/bug26619
tests/bugs/modalg_7/bug23660 [new file with mode: 0644]
tests/bugs/modalg_7/bug26933
tests/bugs/modalg_7/bug27049
tests/bugs/modalg_7/bug28393_1 [new file with mode: 0644]
tests/bugs/modalg_7/bug29711 [new file with mode: 0644]
tests/bugs/modalg_7/bug29900 [new file with mode: 0644]
tests/bugs/moddata_2/bug2442
tests/bugs/moddata_2/bug26_2

index d89a53c3321b57861feff9f2a5a5d33e7888bb01..2f1d7c03a7410735a1e55ce0044c5c8ce9096fd6 100644 (file)
@@ -79,3 +79,6 @@ Warning: Some sub-shapes of some of the argument become connected through other
 
 .BOPAlgo_AlertSolidBuilderUnusedFaces
 Warning: Some of the faces passed to the Solid Builder algorithm have not been classified and not used for solids creation
+
+.BOPAlgo_AlertFaceBuilderUnusedEdges
+Warning: Some of the edges passed to the Face Builder algorithm have not been classified and not used for faces creation
index 05fffbce8b3f810641468c243eac8a3ac27f9ddf..6a10f86b45f4151c663b79077ac860a67d3b7fbe 100644 (file)
@@ -92,4 +92,8 @@ DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertAcquiredSelfIntersection)
 //! and not used for solids creation
 DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertSolidBuilderUnusedFaces)
 
+//! Some of the edges passed to the Face Builder algorithm have not been classified
+//! and not used for faces creation
+DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertFaceBuilderUnusedEdges)
+
 #endif // _BOPAlgo_Alerts_HeaderFile
index adb19e9e987195ffa3c65d1c215e22c223453c35..60d70c999a51cef942d22c61663ffeff31ff36f2 100644 (file)
@@ -81,4 +81,7 @@ static const char BOPAlgo_BOPAlgo_msg[] =
   "Warning: Some sub-shapes of some of the argument become connected through other shapes and the argument became self-interfered\n"
   "\n"
   ".BOPAlgo_AlertSolidBuilderUnusedFaces\n"
-  "Warning: Some of the faces passed to the Solid Builder algorithm have not been classified and not used for solids creation\n";
+  "Warning: Some of the faces passed to the Solid Builder algorithm have not been classified and not used for solids creation\n"
+  "\n"
+  ".BOPAlgo_AlertFaceBuilderUnusedEdges\n"
+  "Warning: Some of the edges passed to the Face Builder algorithm have not been classified and not used for faces creation\n";
index 7c6d8136ef510f3e93408a52406567b488183c9a..b0487970813cf8de505df312c46608d84ecb4f03 100644 (file)
@@ -46,7 +46,7 @@
 #include <IntTools_FClass2d.hxx>
 #include <NCollection_DataMap.hxx>
 #include <NCollection_UBTreeFiller.hxx>
-#include <TColStd_MapIntegerHasher.hxx>
+#include <TColStd_MapOfInteger.hxx>
 #include <TopAbs.hxx>
 #include <TopExp.hxx>
 #include <TopExp_Explorer.hxx>
@@ -446,6 +446,7 @@ void BOPAlgo_BuilderFace::PerformAreas()
   {
     // No holes, stop the analysis
     myAreas.Append(aNewFaces);
+    return;
   }
 
   // Classify holes relatively faces
@@ -580,76 +581,132 @@ void BOPAlgo_BuilderFace::PerformAreas()
 //=======================================================================
 void BOPAlgo_BuilderFace::PerformInternalShapes()
 {
-  if (myAvoidInternalShapes) {
+  if (myAvoidInternalShapes)
+    // User-defined option to avoid internal edges
+    // in the result is in force.
     return;
-  }
-  //
-  Standard_Integer aNbWI=myLoopsInternal.Extent();
-  if (!aNbWI) {// nothing to do
+
+  if (myLoopsInternal.IsEmpty())
+    // No edges left for classification
     return;
-  }
-  // 
-  //Standard_Real aTol;
-  Standard_Integer i;
-  BRep_Builder aBB;
-  BOPCol_ListIteratorOfListOfShape aIt1, aIt2;
-  TopoDS_Iterator aIt; 
-  BOPCol_IndexedMapOfShape aME1, aME2, aMEP;
-  BOPCol_IndexedDataMapOfShapeListOfShape aMVE;
-  BOPCol_ListOfShape aLSI;
-  //
-  // 1. All internal edges
-  aIt1.Initialize(myLoopsInternal);
-  for (; aIt1.More(); aIt1.Next()) {
-    const TopoDS_Shape& aWire=aIt1.Value();
-    aIt.Initialize(aWire);
-    for (; aIt.More(); aIt.Next()) {
-      const TopoDS_Shape& aE=aIt.Value();
-      aME1.Add(aE);
+
+  // Prepare tree filler with the boxes of the edges to classify
+  NCollection_UBTree<Standard_Integer, Bnd_Box2d> aBBTree;
+  NCollection_UBTreeFiller <Standard_Integer, Bnd_Box2d> aTreeFiller(aBBTree);
+
+  // Map of edges to classify
+  TopTools_IndexedMapOfShape anEdgesMap;
+
+  // Fill the tree and the map
+  TopTools_ListIteratorOfListOfShape itLE(myLoopsInternal);
+  for (; itLE.More(); itLE.Next())
+  {
+    TopoDS_Iterator itE(itLE.Value());
+    for (; itE.More(); itE.Next())
+    {
+      const TopoDS_Edge& aE = TopoDS::Edge(itE.Value());
+      if (!anEdgesMap.Contains(aE))
+      {
+        Bnd_Box2d aBoxE;
+        BRepTools::AddUVBounds(myFace, aE, aBoxE);
+        // Make sure the index of edge in the map and
+        // of the box in the tree is the same
+        aTreeFiller.Add(anEdgesMap.Add(aE), aBoxE);
+      }
     }
   }
-  //
-  // 2 Process faces
-  aIt2.Initialize(myAreas);
-  for ( ; aIt2.More(); aIt2.Next()) {
-    TopoDS_Face& aF=(*(TopoDS_Face *)(&aIt2.Value()));
-    //
-    aMVE.Clear();
-    BOPTools::MapShapesAndAncestors(aF, TopAbs_VERTEX, TopAbs_EDGE, aMVE);
-    //
-    // 2.1 Separate faces to process aMEP
-    aME2.Clear();
-    aMEP.Clear();
-    aNbWI = aME1.Extent();
-    for (i = 1; i <= aNbWI; ++i) {
-      const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aME1(i)));
-      if (IsInside(aE, aF, myContext)) {
-        aMEP.Add(aE);
-      }
-      else {
-        aME2.Add(aE);
+
+  // Shake the tree
+  aTreeFiller.Fill();
+
+  // Fence map
+  TColStd_MapOfInteger aMEDone;
+
+  // Classify edges relatively faces
+  TopTools_ListIteratorOfListOfShape itLF(myAreas);
+  for (; itLF.More(); itLF.Next())
+  {
+    TopoDS_Face& aF = *(TopoDS_Face*)&itLF.Value();
+
+    // Build box
+    Bnd_Box2d aBoxF;
+    BRepTools::AddUVBounds(aF, aBoxF);
+
+    // Select edges for the classification
+    BOPCol_Box2DBndTreeSelector aSelector;
+    aSelector.SetBox(aBoxF);
+    if (!aBBTree.Select(aSelector))
+      continue;
+
+    // Collect edges inside the face
+    TopTools_IndexedMapOfShape anEdgesInside;
+
+    const BOPCol_ListOfInteger& aLI = aSelector.Indices();
+    BOPCol_ListIteratorOfListOfInteger itLI(aLI);
+    for (; itLI.More(); itLI.Next())
+    {
+      const Standard_Integer nE = itLI.Value();
+      if (aMEDone.Contains(nE))
+        continue;
+
+      const TopoDS_Edge& aE = TopoDS::Edge(anEdgesMap(nE));
+      if (IsInside(aE, aF, myContext))
+      {
+        anEdgesInside.Add(aE);
+        aMEDone.Add(nE);
       }
     }
-    //
-    // 2.2 Make Internal Wires
-    aLSI.Clear();
-    MakeInternalWires(aMEP, aLSI);
-    //
-    // 2.3 Add them to aF
-    aIt1.Initialize(aLSI);
-    for (; aIt1.More(); aIt1.Next()) {
-      const TopoDS_Shape& aSI=aIt1.Value();
-      aBB.Add (aF, aSI);
-    }
-    //
-    // 2.4 Remove faces aMFP from aMF
-    aME1 = aME2;
-    //
-    aNbWI = aME1.Extent();
-    if (!aNbWI) {
-      break;
+
+    if (anEdgesInside.IsEmpty())
+      continue;
+
+    // Make internal wires
+    TopTools_ListOfShape aLSI;
+    MakeInternalWires(anEdgesInside, aLSI);
+
+    // Add wires to a face
+    TopTools_ListIteratorOfListOfShape itLSI(aLSI);
+    for (; itLSI.More(); itLSI.Next())
+    {
+      const TopoDS_Shape& aWI = itLSI.Value();
+      BRep_Builder().Add(aF, aWI);
     }
-  } //for ( ; aIt2.More(); aIt2.Next()) {
+
+    // Condition of early exit
+    if (aMEDone.Extent() == anEdgesMap.Extent())
+      // All edges are classified and added into the faces
+      return;
+  }
+
+  // Some edges are left unclassified - warn user about them
+  TopTools_IndexedMapOfShape anEdgesUnUsed;
+  for (Standard_Integer i = 1; i <= anEdgesMap.Extent(); ++i)
+  {
+    if (!aMEDone.Contains(i))
+      anEdgesUnUsed.Add(anEdgesMap(i));
+  }
+
+  // Make internal wires
+  TopTools_ListOfShape aLSI;
+  MakeInternalWires(anEdgesUnUsed, aLSI);
+
+  // Make compound
+  TopoDS_Compound aWShape;
+  BRep_Builder().MakeCompound(aWShape);
+  BRep_Builder().Add(aWShape, myFace);
+  if (aLSI.Extent() == 1)
+    BRep_Builder().Add(aWShape, aLSI.First());
+  else
+  {
+    TopoDS_Compound aCE;
+    BRep_Builder().MakeCompound(aCE);
+    for (TopTools_ListIteratorOfListOfShape it(aLSI); it.More(); it.Next())
+      BRep_Builder().Add(aCE, it.Value());
+    BRep_Builder().Add(aWShape, aCE);
+  }
+
+  // Add warning
+  AddWarning(new BOPAlgo_AlertFaceBuilderUnusedEdges(aWShape));
 }
 //=======================================================================
 //function : MakeInternalWires
index 2d59eac59513858712c75572f9854fbba99d6cde..dce5cad1fa001b9d286720d69d9a4234491d53dd 100644 (file)
@@ -688,7 +688,8 @@ void BOPAlgo_BuilderSolid::PerformInternalShapes()
         aBB.Add(aWShape, aItLS.Value());
     }
 
-    AddWarning(new BOPAlgo_AlertSolidBuilderUnusedFaces(aWShape));  }
+    AddWarning(new BOPAlgo_AlertSolidBuilderUnusedFaces(aWShape));
+  }
 }
 //=======================================================================
 //function : MakeInternalShells
index 5855705ab0245fb848043dfcc46efd05fef55128..dde7e18436985639c52c8993c18b631e9b98dec3 100644 (file)
@@ -311,8 +311,8 @@ void BOPAlgo_Builder::BuildSplitFaces()
 
       // 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
+      // If the original face has any internal edges or multi-connected vertices,
+      // the draft face will be null, as such sub-shapes 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);
@@ -464,6 +464,7 @@ void BOPAlgo_Builder::BuildSplitFaces()
   {
     BOPAlgo_BuilderFace& aBF = aVBF(k);
     aFacesIm.Add(myDS->Index(aBF.Face()), aBF.Areas());
+    myReport->Merge(aBF.GetReport());
   }
 
   aNbBF = aFacesIm.Extent();
@@ -813,6 +814,36 @@ void BOPAlgo_Builder::FillInternalVertices()
   }
 }
 //=======================================================================
+//function : HasMultiConnected
+//purpose  : Checks if the edge has multi-connected vertices.
+//=======================================================================
+static Standard_Boolean HasMultiConnected(const TopoDS_Edge& theEdge,
+                                          BOPCol_DataMapOfShapeListOfShape& theMap)
+{
+  TopoDS_Iterator itV(theEdge);
+  for (; itV.More(); itV.Next())
+  {
+    const TopoDS_Shape& aV = itV.Value();
+    TopTools_ListOfShape *pList = theMap.ChangeSeek(aV);
+    if (!pList)
+    {
+      pList = theMap.Bound(aV, TopTools_ListOfShape());
+      pList->Append(theEdge);
+    }
+    else
+    {
+      // The list is expected to be 1-2 elements long,
+      // thus using "Contains" is safe.
+      if (!pList->Contains(theEdge))
+        pList->Append(theEdge);
+
+      if (pList->Extent() > 2)
+        return Standard_True;
+    }
+  }
+  return Standard_False;
+}
+//=======================================================================
 //function : BuildDraftFace
 //purpose  : Build draft faces, updating the bounding edges,
 //           according to the information stored into the <theImages> map
@@ -830,6 +861,13 @@ TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
   TopoDS_Face aDraftFace;
   aBB.MakeFace(aDraftFace, aS, aLoc, aTol);
 
+  // Check if the thin face can be split by a vertex - in this case
+  // this vertex will be contained in more than two edges. Thus, count
+  // the vertices appearance, and if the multi-connexity is met return
+  // the null face to use the BuilderFace algorithm for checking the
+  // possibility of split.
+  BOPCol_DataMapOfShapeListOfShape aVerticesCounter;
+
   // Update wires of the original face and add them to draft face
   TopoDS_Iterator aItW(theFace.Oriented(TopAbs_FORWARD));
   for (; aItW.More(); aItW.Next())
@@ -855,19 +893,24 @@ TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
       {
         // 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;
+        return TopoDS_Face();
       }
 
-      const BOPCol_ListOfShape* pLEIm = theImages.Seek(aE);
+      // Check if the original edge is degenerated
+      Standard_Boolean bIsDegenerated = BRep_Tool::Degenerated(aE);
+
+      // Check for the splits of the edge
+      const TopTools_ListOfShape* pLEIm = theImages.Seek(aE);
       if (!pLEIm)
       {
+        // Check if the edge has multi-connected vertices
+        if (!bIsDegenerated && HasMultiConnected(aE, aVerticesCounter))
+          return TopoDS_Face();
+
         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);
 
@@ -876,6 +919,10 @@ TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
       {
         TopoDS_Edge& aSp = TopoDS::Edge(aItLEIm.Value());
 
+        // Check if the split has multi-connected vertices
+        if (!bIsDegenerated && HasMultiConnected(aSp, aVerticesCounter))
+          return TopoDS_Face();
+
         aSp.Orientation(anOriE);
         if (bIsDegenerated)
         {
@@ -883,8 +930,8 @@ TopoDS_Face BuildDraftFace(const TopoDS_Face& theFace,
           continue;
         }
 
-        // Check closeness of the split edge and if it is not
-        // make the second PCurve
+        // If the original edge is closed on the face check closeness
+        // of the split edge and if it is not closed make the second PCurve
         if (bIsClosed && !BRep_Tool::IsClosed(aSp, theFace))
           BOPTools_AlgoTools3D::DoSplitSEAMOnFace(aSp, theFace);
 
index 6efe3f104ebe46767bf38d71287d17ccb112d70c..6a5194a8fb827b70cccec51934a17dc06efef99c 100644 (file)
@@ -54,7 +54,10 @@ BOPAlgo_PaveFiller::BOPAlgo_PaveFiller()
 BOPAlgo_PaveFiller::BOPAlgo_PaveFiller
   (const Handle(NCollection_BaseAllocator)& theAllocator)
 :
-  BOPAlgo_Algo(theAllocator)
+  BOPAlgo_Algo(theAllocator),
+  myFPBDone(1, theAllocator),
+  myIncreasedSS(1, theAllocator),
+  myVertsToAvoidExtension(1, theAllocator)
 {
   myDS = NULL;
   myIterator = NULL;
@@ -134,6 +137,7 @@ void BOPAlgo_PaveFiller::Clear()
     delete myDS;
     myDS=NULL;
   }
+  myIncreasedSS.Clear();
 }
 //=======================================================================
 //function : DS
@@ -286,9 +290,17 @@ void BOPAlgo_PaveFiller::PerformInternal()
   UpdatePaveBlocksWithSDVertices();
   UpdateInterfsWithSDVertices();
 
+  // Repeat Intersection with increased vertices
+  RepeatIntersection();
+  if (HasErrors())
+    return;
+
   // Force intersection of edges after increase
   // of the tolerance values of their vertices
   ForceInterfEE();
+  // Force Edge/Face intersection after increase
+  // of the tolerance values of their vertices
+  ForceInterfEF();
   //
   // 22
   PerformFF();
@@ -326,3 +338,58 @@ void BOPAlgo_PaveFiller::PerformInternal()
     return; 
   }
 }
+
+//=======================================================================
+// function: RepeatIntersection
+// purpose: 
+//=======================================================================
+void BOPAlgo_PaveFiller::RepeatIntersection()
+{
+  // Find all vertices with increased tolerance
+  BOPCol_MapOfInteger anExtraInterfMap;
+  const Standard_Integer aNbS = myDS->NbSourceShapes();
+  for (Standard_Integer i = 0; i < aNbS; ++i)
+  {
+    const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
+    if (aSI.ShapeType() != TopAbs_VERTEX)
+      continue;
+    // Check if the tolerance of the original vertex has been increased
+    if (myIncreasedSS.Contains(i))
+    {
+      anExtraInterfMap.Add(i);
+      continue;
+    }
+
+    // Check if the vertex created a new vertex with greater tolerance
+    Standard_Integer nVSD;
+    if (!myDS->HasShapeSD(i, nVSD))
+      continue;
+
+    if (myIncreasedSS.Contains(nVSD))
+      anExtraInterfMap.Add(i);
+  }
+
+  if (anExtraInterfMap.IsEmpty())
+    return;
+
+  // Update iterator of pairs of shapes with interfering boxes
+  myIterator->PrepareExt(anExtraInterfMap);
+
+  // Perform intersections with vertices
+  PerformVV();
+  if (HasErrors())
+    return;
+  UpdatePaveBlocksWithSDVertices();
+
+  PerformVE();
+  if (HasErrors())
+    return;
+  UpdatePaveBlocksWithSDVertices();
+
+  PerformVF();
+  if (HasErrors())
+    return;
+
+  UpdatePaveBlocksWithSDVertices();
+  UpdateInterfsWithSDVertices();
+}
index 545718e558b0e027387c7674e441b885853fd0d6..c03897e26a857035cfa96e1b75985ca31a340f95 100644 (file)
@@ -173,6 +173,14 @@ protected:
              Bnd_Box,
              TColStd_MapTransientHasher> BOPAlgo_DataMapOfPaveBlockBndBox;
 
+  typedef NCollection_DataMap
+            <Handle(BOPDS_PaveBlock),
+             BOPCol_ListOfInteger,
+             TColStd_MapTransientHasher> BOPAlgo_DataMapOfPaveBlockListOfInteger;
+
+  typedef NCollection_DataMap
+            <Standard_Integer,
+             BOPDS_MapOfPaveBlock> BOPAlgo_DataMapOfIntegerMapOfPaveBlock;
 
   //! Sets non-destructive mode automatically if an argument 
   //! contains a locked sub-shape (see TopoDS_Shape::Locked()).
@@ -265,7 +273,8 @@ protected:
                                 BOPCol_DataMapOfIntegerReal& theMVTol,
                                 BOPCol_DataMapOfIntegerListOfInteger& aDMVLV);
 
-  Standard_EXPORT void FilterPavesOnCurves(const BOPDS_VectorOfCurve& theVNC);
+  Standard_EXPORT void FilterPavesOnCurves(const BOPDS_VectorOfCurve& theVNC,
+                                           BOPCol_DataMapOfIntegerReal& theMVTol);
 
   //! Depending on the parameter aType it checks whether
   //! the vertex nV was created in EE or EF intersections.
@@ -281,23 +290,32 @@ protected:
                                            const TopoDS_Face& theF2,
                                            BOPDS_Curve& theNC,
                                            BOPCol_ListOfInteger& theLBV);
-  
+
+  //! Checks if the given pave block (created on section curve)
+  //! coincides with any of the pave blocks of the faces
+  //! created the section curve.
   Standard_EXPORT Standard_Boolean IsExistingPaveBlock
     (const Handle(BOPDS_PaveBlock)& thePB, const BOPDS_Curve& theNC,
      const Standard_Real theTolR3D, const BOPDS_IndexedMapOfPaveBlock& theMPB,
      const BOPDS_MapOfPaveBlock& theMPBCommon,
      Handle(BOPDS_PaveBlock)& thePBOut, Standard_Real& theTolNew);
-  
-  Standard_EXPORT Standard_Boolean IsExistingPaveBlock (const Handle(BOPDS_PaveBlock)& thePB, const BOPDS_Curve& theNC, const BOPCol_ListOfInteger& theLSE);
-  
+
+  //! Checks if the given pave block (created on section curve)
+  //! coincides with any of the edges shared between the faces
+  //! created the section curve.
+  Standard_EXPORT Standard_Boolean IsExistingPaveBlock(const Handle(BOPDS_PaveBlock)& thePB,
+                                                       const BOPDS_Curve& theNC,
+                                                       const BOPCol_ListOfInteger& theLSE,
+                                                       Standard_Integer& theNEOut,
+                                                       Standard_Real& theTolNew);
 
   //! Treatment of section edges.
   Standard_EXPORT void PostTreatFF (BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMSCPB,
                                     BOPDS_DataMapOfPaveBlockListOfPaveBlock& theDMExEdges,
                                     BOPCol_DataMapOfIntegerInteger& theDMNewSD,
-                                    const BOPCol_IndexedMapOfShape& theMicroEdges,
+                                    const BOPDS_IndexedMapOfPaveBlock& theMicroPB,
                                     const BOPCol_IndexedMapOfShape& theVertsOnRejectedPB,
-                                    const BOPCol_BaseAllocator& theAllocator);
+                                    const Handle(NCollection_BaseAllocator)& theAllocator);
   
   Standard_EXPORT void FindPaveBlocks (const Standard_Integer theV, const Standard_Integer theF, BOPDS_ListOfPaveBlock& theLPB);
   
@@ -360,14 +378,24 @@ protected:
 
   //! Adds the existing edges from the map <theMPBOnIn> which interfere
   //! with the vertices from <theMVB> map to the post treatment of section edges.
-  Standard_EXPORT void ProcessExistingPaveBlocks (const Standard_Integer theInt, const BOPDS_IndexedMapOfPaveBlock& theMPBOnIn, const BOPCol_DataMapOfIntegerListOfInteger& theDMBV, BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMSCPB, BOPCol_DataMapOfShapeInteger& theMVI, BOPDS_MapOfPaveBlock& theMPB);
+  Standard_EXPORT void ProcessExistingPaveBlocks (const Standard_Integer theInt,
+                                                  const Standard_Integer nF1,
+                                                  const Standard_Integer nF2,
+                                                  const BOPDS_IndexedMapOfPaveBlock& theMPBOnIn,
+                                                  const BOPCol_DataMapOfIntegerListOfInteger& theDMBV,
+                                                  BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMSCPB,
+                                                  BOPCol_DataMapOfShapeInteger& theMVI,
+                                                  BOPAlgo_DataMapOfPaveBlockListOfInteger& thePBFacesMap,
+                                                  BOPDS_MapOfPaveBlock& theMPB);
   
 
   //! Replaces existing pave block <thePB> with new pave blocks <theLPB>.
   //! The list <theLPB> contains images of <thePB> which were created in
   //! the post treatment of section edges.
-  Standard_EXPORT void UpdateExistingPaveBlocks (const Handle(BOPDS_PaveBlock)& thePB, BOPDS_ListOfPaveBlock& theLPB, const Standard_Integer nF1, const Standard_Integer nF2);
-  
+  //! Tries to project the new edges on the faces contained in the <thePBFacesMap>.
+  Standard_EXPORT void UpdateExistingPaveBlocks(const Handle(BOPDS_PaveBlock)& thePB,
+                                                BOPDS_ListOfPaveBlock& theLPB,
+                                                const BOPAlgo_DataMapOfPaveBlockListOfInteger& thePBFacesMap);
 
   //! Treatment of vertices that were created in EE intersections.
   Standard_EXPORT void TreatNewVertices(const BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMVCPB, BOPCol_IndexedDataMapOfShapeListOfShape& theImages);
@@ -382,8 +410,9 @@ protected:
   Standard_EXPORT void PreparePostTreatFF (const Standard_Integer aInt, const Standard_Integer aCur, const Handle(BOPDS_PaveBlock)& aPB, BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& aMSCPB, BOPCol_DataMapOfShapeInteger& aMVI, BOPDS_ListOfPaveBlock& aLPB);
 
   //! Updates the information about faces
-  Standard_EXPORT void UpdateFaceInfo (BOPDS_DataMapOfPaveBlockListOfPaveBlock& theDME, const BOPCol_DataMapOfIntegerInteger& theDMV);
-  
+  Standard_EXPORT void UpdateFaceInfo(BOPDS_DataMapOfPaveBlockListOfPaveBlock& theDME,
+                                      const BOPCol_DataMapOfIntegerInteger& theDMV,
+                                      const BOPAlgo_DataMapOfPaveBlockListOfInteger& thePBFacesMap);
 
   //! Updates tolerance of vertex with index <nV>
   //! to make it interfere with edge.
@@ -485,11 +514,39 @@ protected:
   //! Adds the warning about failed intersection of pair of sub-shapes
   Standard_EXPORT void AddIntersectionFailedWarning(const TopoDS_Shape& theS1, const TopoDS_Shape& theS2);
 
+  //! Repeat intersection of sub-shapes with increased vertices.
+  Standard_EXPORT void RepeatIntersection();
+
+  //! Updates vertices of CommonBlocks with real tolerance of CB.
+  Standard_EXPORT void UpdateVerticesOfCB();
+
   //! The method looks for the additional common blocks among pairs of edges
-  //! which did not participate in edges intersection (PerformEE() method)
-  //! due to being rejected by bounding boxes intersection.
+  //! with the same bounding vertices.
   Standard_EXPORT void ForceInterfEE();
 
+  //! The method looks for the additional edge/face common blocks
+  //! among pairs of edge/face having the same vertices.
+  Standard_EXPORT void ForceInterfEF();
+
+  //! Performs intersection of given pave blocks
+  //! with all faces from arguments.
+  Standard_EXPORT void ForceInterfEF(const BOPDS_IndexedMapOfPaveBlock& theMPB,
+                                     const Standard_Boolean theAddInterf);
+
+  //! When all section edges are created and no increase of the tolerance
+  //! of vertices put on the section edges is expected, make sure that
+  //! the created sections have valid range.
+  //! If any of the section edges do not have valid range, remove them
+  //! from Face/Face intersection info and from the input <theMSCPB> map.
+  //! Put such edges into <MicroPB> map for further unification of their
+  //! vertices in the PostTreatFF method.
+  //!
+  //! All these section edges have already been checked to have valid range.
+  //! Current check is necessary for the edges whose vertices have also
+  //! been put on other section edges with greater tolerance, which has caused
+  //! increase of the tolerance value of the vertices.
+  Standard_EXPORT void RemoveMicroSectionEdges(BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMSCPB,
+                                               BOPDS_IndexedMapOfPaveBlock& theMicroPB);
 
   BOPCol_ListOfShape myArguments;
   BOPDS_PDS myDS;
@@ -501,8 +558,12 @@ protected:
   Standard_Boolean myAvoidBuildPCurve;
   BOPAlgo_GlueEnum myGlue;
 
-
-private:
+  BOPAlgo_DataMapOfIntegerMapOfPaveBlock myFPBDone; //!< Fence map of intersected faces and pave blocks
+  BOPCol_MapOfInteger myIncreasedSS;                //!< Sub-shapes with increased tolerance during the operation
+  BOPCol_MapOfInteger myVertsToAvoidExtension;      //!< Vertices located close to E/E or E/F intersection points
+                                                    //! which has already been extended to cover the real intersection
+                                                    //! points, and should not be extended any longer to be put
+                                                    //! on a section curve.
 
 };
 
index 5b5505c42937c13573d147c5df6efeb7699fa47f..4fb0e8c92f1c33ac3595c36d8725c70a944bdfde 100644 (file)
@@ -71,14 +71,27 @@ void BOPAlgo_PaveFiller::PerformVV()
   for (; myIterator->More(); myIterator->Next()) {
     myIterator->Value(n1, n2);
     //
-    const TopoDS_Vertex& aV1=(*(TopoDS_Vertex *)(&myDS->Shape(n1))); 
-    const TopoDS_Vertex& aV2=(*(TopoDS_Vertex *)(&myDS->Shape(n2))); 
-    //
-    iFlag=BOPTools_AlgoTools::ComputeVV(aV1, aV2, myFuzzyValue);
+    if (myDS->HasInterf(n1, n2))
+    {
+      BOPAlgo_Tools::FillMap<Standard_Integer, TColStd_MapIntegerHasher>(n1, n2, aMILI, aAllocator);
+      continue;
+    }
+
+    // Check for SD vertices
+    Standard_Integer n1SD = n1;
+    myDS->HasShapeSD(n1, n1SD);
+
+    Standard_Integer n2SD = n2;
+    myDS->HasShapeSD(n2, n2SD);
+
+    const TopoDS_Vertex& aV1=(*(TopoDS_Vertex *)(&myDS->Shape(n1SD)));
+    const TopoDS_Vertex& aV2=(*(TopoDS_Vertex *)(&myDS->Shape(n2SD)));
+
+    iFlag = BOPTools_AlgoTools::ComputeVV(aV1, aV2, myFuzzyValue);
     if (!iFlag) {
       BOPAlgo_Tools::FillMap<Standard_Integer, TColStd_MapIntegerHasher>(n1, n2, aMILI, aAllocator);
     }
-  } 
+  }
   //
   // 2. Make blocks
   BOPAlgo_Tools::MakeBlocks<Standard_Integer, TColStd_MapIntegerHasher>(aMILI, aMBlocks, aAllocator);
@@ -185,11 +198,12 @@ Standard_Integer BOPAlgo_PaveFiller::MakeSDVertices
       }
       //
       if (theAddInterfs) {
-        myDS->AddInterf(n1, n2);
-        BOPDS_InterfVV& aVV = aVVs.Append1();
-        //
-        aVV.SetIndices(n1, n2);
-        aVV.SetIndexNew(nV);
+        if (myDS->AddInterf(n1, n2))
+        {
+          BOPDS_InterfVV& aVV = aVVs.Append1();
+          aVV.SetIndices(n1, n2);
+          aVV.SetIndexNew(nV);
+        }
       }
     }
   }
index 37b683ba40be788e4cf2a7d7d15c85cac9e979f8..e48d9d8300b6260313e87867089b4ecaf408c0df 100644 (file)
@@ -63,59 +63,40 @@ void BOPAlgo_PaveFiller::SetNonDestructive()
 //purpose  : 
 //=======================================================================
 void BOPAlgo_PaveFiller::UpdateEdgeTolerance (const Standard_Integer nE,
-                                              const Standard_Real aTol)
+                                              const Standard_Real theTol)
 {
-  Standard_Boolean bIsNewShape, bHasShapeSD;
-  Standard_Integer nV, nVx;
-  Standard_Real aTolV;
-  BRep_Builder aBB;
-  BOPCol_ListIteratorOfListOfInteger aIt;
-  //
-  BOPDS_ShapeInfo& aSIE=myDS->ChangeShapeInfo(nE);
-  const BOPCol_ListOfInteger& aLI=aSIE.SubShapes();
-  //
-  if (myNonDestructive) {
-    bIsNewShape=myDS->IsNewShape(nE);
-    if (!bIsNewShape) {
+  BOPDS_ShapeInfo& aSIE = myDS->ChangeShapeInfo(nE);
+  const BOPCol_ListOfInteger& aLI = aSIE.SubShapes();
+
+  // For the safe input mode avoid modifying the input shapes
+  if (myNonDestructive)
+  {
+    if (!myDS->IsNewShape(nE))
       return;
-    }
-    //
-    aIt.Initialize(aLI);
-    for (; aIt.More(); aIt.Next()) {
-      nV = aIt.Value();
-      bHasShapeSD=myDS->HasShapeSD(nV, nVx);
-      if (bHasShapeSD) {
-        continue;
-      }
-      bIsNewShape=myDS->IsNewShape(nV);
-      if (!bIsNewShape) {
+
+    BOPCol_ListIteratorOfListOfInteger itLI(aLI);
+    for (; itLI.More(); itLI.Next())
+    {
+      Standard_Integer nV = itLI.Value(), nVSD;
+      if (!myDS->IsNewShape(nV) &&
+          !myDS->HasShapeSD(nV, nVSD))
         return;
-      }
     }
   }
-  //
+
+  // Update edge
   const TopoDS_Edge& aE = *(TopoDS_Edge*)&myDS->Shape(nE);
-  aBB.UpdateEdge(aE, aTol);
-  Bnd_Box& aBoxE=aSIE.ChangeBox();
+  BRep_Builder().UpdateEdge(aE, theTol);
+  Bnd_Box& aBoxE = aSIE.ChangeBox();
   BRepBndLib::Add(aE, aBoxE);
   aBoxE.SetGap(aBoxE.GetGap() + Precision::Confusion());
-  //
-  aIt.Initialize(aLI);
-  for (; aIt.More(); aIt.Next()) {
-    nV = aIt.Value();
-    bHasShapeSD=myDS->HasShapeSD(nV, nVx);
-    if (bHasShapeSD) {
-      nV=nVx;
-    }
-    const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&myDS->Shape(nV);
-    aTolV = BRep_Tool::Tolerance(aV);
-    if (aTolV < aTol) {
-      aBB.UpdateVertex(aV, aTol);
-      BOPDS_ShapeInfo& aSIV = myDS->ChangeShapeInfo(nV);
-      Bnd_Box& aBoxV = aSIV.ChangeBox();
-      BRepBndLib::Add(aV, aBoxV);
-      aBoxV.SetGap(aBoxV.GetGap() + Precision::Confusion());
-    }
+
+  // Update vertices
+  BOPCol_ListIteratorOfListOfInteger itLI(aLI);
+  for (; itLI.More(); itLI.Next())
+  {
+    Standard_Integer nV = itLI.Value();
+    UpdateVertex(nV, theTol);
   }
 }
 //=======================================================================
@@ -143,6 +124,7 @@ Standard_Integer BOPAlgo_PaveFiller::UpdateVertex
       Bnd_Box& aBoxV = aSIV.ChangeBox();
       BRepBndLib::Add(aVSD, aBoxV);
       aBoxV.SetGap(aBoxV.GetGap() + Precision::Confusion());
+      myIncreasedSS.Add(nV);
     }
     return nVNew;
   }
@@ -172,7 +154,13 @@ Standard_Integer BOPAlgo_PaveFiller::UpdateVertex
   myDS->AddShapeSD(nV, nVNew);
   //
   myDS->InitPaveBlocksForVertex(nV);
-  //
+
+  // Add new vertex to map of vertices to avoid further extension
+  myVertsToAvoidExtension.Add(nVNew);
+
+  if (aTolV < aTolNew)
+    myIncreasedSS.Add(nV);
+
   return nVNew;
 }
 //=======================================================================
index d4b48b491bbc3b00bf7a28d7b765d3bc31260d59..f7b92b64bf6b8265797d2d324b17f0eb7730efe5 100644 (file)
@@ -179,6 +179,10 @@ void BOPAlgo_PaveFiller::PerformVE()
       continue;
     }
     //
+    if (myDS->HasInterf(nV, nE)) {
+      continue;
+    }
+    //
     if (myDS->HasInterfShapeSubShapes(nV, nE)) {
       continue;
     }
index 120d6794c972457f413e9996564768cf0a26a8a1..16a93c43e3ec78fbf7eff948368ef74fe5f9cbb2 100644 (file)
 #include <BOPDS_PaveBlock.hxx>
 #include <BOPDS_VectorOfInterfEE.hxx>
 #include <BOPTools_AlgoTools.hxx>
+#include <BOPTools_AlgoTools2D.hxx>
 #include <BndLib_Add3dCurve.hxx>
 #include <BRep_Tool.hxx>
 #include <BRep_Builder.hxx>
 #include <BRepAdaptor_Curve.hxx>
+#include <GeomAPI_ProjectPointOnCurve.hxx>
 #include <gp_Pnt.hxx>
 #include <IntTools_CommonPrt.hxx>
 #include <IntTools_Context.hxx>
@@ -312,7 +314,7 @@ void BOPAlgo_PaveFiller::PerformEE()
             continue;
           }
           //
-          Standard_Boolean bIsOnPave[4], bFlag;
+          Standard_Boolean bIsOnPave[4];
           Standard_Integer nV[4], j;
           Standard_Real aT1, aT2, aTol;
           TopoDS_Vertex aVnew;
@@ -343,23 +345,50 @@ void BOPAlgo_PaveFiller::PerformEE()
             continue;
           }
           //
-          bFlag = Standard_False;
-          for (j = 0; j < 4; ++j) {
-            if (bIsOnPave[j]) {
-              //add interf VE(nV[j], nE)
+          Standard_Boolean isVExists = Standard_False;
+          for (j = 0; j < 4; ++j)
+          {
+            if (bIsOnPave[j])
+            {
               Handle(BOPDS_PaveBlock)& aPB = (j < 2) ? aPB2 : aPB1;
-              bFlag = ForceInterfVE(nV[j], aPB, aMEdges);
-              break;
+              bIsOnPave[j] = ForceInterfVE(nV[j], aPB, aMEdges);
+              if (bIsOnPave[j]) isVExists = Standard_True;
             }
           }
-          if (bFlag) {
-            BOPDS_InterfEE& aEE = aEEs.Append1();
-            aEE.SetIndices(nE1, nE2);
-            aEE.SetCommonPart(aCPart);
-            continue;
-          }
-          //
+
           BOPTools_AlgoTools::MakeNewVertex(aE1, aT1, aE2, aT2, aVnew);
+          const gp_Pnt aPnew = BRep_Tool::Pnt(aVnew);
+
+          if (isVExists)
+          {
+            // The found intersection point is located closely to one of the
+            // pave blocks bounds. So, do not create the new vertex in this point.
+            // Check if this point is a real intersection point or just a touching point.
+            // If it is a touching point, do nothing.
+            // If it is an intersection point, update the existing vertex to cover the
+            // intersection point.
+            const gp_Pnt aPOnE1 = BRepAdaptor_Curve(aE1).Value(aT1);
+            const gp_Pnt aPOnE2 = BRepAdaptor_Curve(aE2).Value(aT2);
+            if (aPOnE1.Distance(aPOnE2) > Precision::Intersection())
+              // No intersection point
+              continue;
+
+            // Real intersection is present.
+            // Update the existing vertex to cover the intersection point.
+            for (j = 0; j < 4; ++j)
+            {
+              if (bIsOnPave[j])
+              {
+                const TopoDS_Vertex& aV = TopoDS::Vertex(myDS->Shape(nV[j]));
+                const gp_Pnt aP = BRep_Tool::Pnt(aV);
+                Standard_Real aDistPP = aP.Distance(aPnew);
+                // Just update the vertex
+                UpdateVertex(nV[j], aDistPP);
+                myVertsToAvoidExtension.Add(nV[j]);
+              }
+            }
+          }
+
           Standard_Real aTolVnew = BRep_Tool::Tolerance(aVnew);
           if (bAnalytical) {
             // increase tolerance for Line/Line intersection, but do not update 
@@ -375,7 +404,7 @@ void BOPAlgo_PaveFiller::PerformEE()
             Standard_Integer nVS[2], iFound;
             Standard_Real aTolVx, aD2, aDT2;
             BOPCol_MapOfInteger aMV;
-            gp_Pnt aPnew, aPx;
+            gp_Pnt aPx;
             //
             iFound=0;
             j=-1;
@@ -391,8 +420,6 @@ void BOPAlgo_PaveFiller::PerformEE()
               nVS[j]=nV[3];
             }
             //
-            aPnew=BRep_Tool::Pnt(aVnew);
-            //
             for (Standard_Integer k1=0; k1<=j; ++k1) {
               const TopoDS_Vertex& aVx= *(TopoDS_Vertex*)&(myDS->Shape(nVS[k1]));
               aTolVx=BRep_Tool::Tolerance(aVx);
@@ -459,7 +486,10 @@ void BOPAlgo_PaveFiller::PerformEE()
   //=========================================
   // post treatment
   //=========================================
-  BOPAlgo_Tools::PerformCommonBlocks(aMPBLPB, aAllocator, myDS);
+  BOPAlgo_Tools::PerformCommonBlocks(aMPBLPB, aAllocator, myDS, myContext);
+  // Update vertices of common blocks with real CB tolerances
+  UpdateVerticesOfCB();
+
   PerformNewVertices(aMVCPB, aAllocator);
   //
   if (aMEdges.Extent()) {
@@ -598,8 +628,11 @@ void BOPAlgo_PaveFiller::FillShrunkData(Handle(BOPDS_PaveBlock)& thePB)
   thePB->Indices(nV1, nV2);
   const TopoDS_Vertex& aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1))); 
   const TopoDS_Vertex& aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2))); 
-  // Original edge
+  // Get the edge
   Standard_Integer nE = thePB->OriginalEdge();
+  if (nE < 0 && !thePB->HasEdge(nE))
+    return;
+
   const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE))); 
   // Range
   Standard_Real aT1, aT2;
@@ -628,7 +661,7 @@ void BOPAlgo_PaveFiller::AnalyzeShrunkData(const Handle(BOPDS_PaveBlock)& thePB,
     BRep_Tool::Range(theSR.Edge(), aEFirst, aELast);
     thePB->Range(aPBFirst, aPBLast);
     bWholeEdge = !(aPBFirst > aEFirst || aPBLast < aELast);
-    if (bWholeEdge) {
+    if (bWholeEdge && thePB->OriginalEdge() >= 0) {
       aWarnShape = theSR.Edge();
     }
     else {
@@ -675,20 +708,20 @@ Standard_Boolean BOPAlgo_PaveFiller::ForceInterfVE(const Standard_Integer nV,
   //
   const BOPDS_ShapeInfo& aSIE=myDS->ShapeInfo(nE);
   if (aSIE.HasSubShape(nV)) {
-    return Standard_False;
+    return Standard_True;
   }
   //
   if (myDS->HasInterf(nV, nE)) {
-    return Standard_False;
+    return Standard_True;
   }
   //
   if (myDS->HasInterfShapeSubShapes(nV, nE)) {
-    return Standard_False;
+    return Standard_True;
   }
   //
   if (aPB->Pave1().Index() == nV || 
       aPB->Pave2().Index() == nV) {
-    return Standard_False;
+    return Standard_True;
   }
   //
   nVx = nV;
@@ -784,6 +817,41 @@ Standard_Boolean BOPAlgo_PaveFiller::GetPBBox(const TopoDS_Edge& theE,
   return bValid;
 }
 
+//=======================================================================
+//function : UpdateVerticesOfCB
+//purpose  : 
+//=======================================================================
+void BOPAlgo_PaveFiller::UpdateVerticesOfCB()
+{
+  // Fence map to avoid checking same Common block twice
+  BOPDS_MapOfPaveBlock aMPBFence;
+
+  BOPDS_VectorOfListOfPaveBlock& aPBP = myDS->ChangePaveBlocksPool();
+  const Standard_Integer aNbPBP = aPBP.Length();
+  for (Standard_Integer i = 0; i < aNbPBP; ++i)
+  {
+    const BOPDS_ListOfPaveBlock& aLPB = aPBP(i);
+    BOPDS_ListIteratorOfListOfPaveBlock itPB(aLPB);
+    for (; itPB.More(); itPB.Next())
+    {
+      const Handle(BOPDS_CommonBlock)& aCB = myDS->CommonBlock(itPB.Value());
+      if (aCB.IsNull())
+        continue;
+
+      const Handle(BOPDS_PaveBlock)& aPBR = aCB->PaveBlock1();
+      if (!aMPBFence.Add(aPBR))
+        continue;
+
+      Standard_Real aTolCB = aCB->Tolerance();
+      if (aTolCB > 0.)
+      {
+        UpdateVertex(aPBR->Pave1().Index(), aTolCB);
+        UpdateVertex(aPBR->Pave2().Index(), aTolCB);
+      }
+    }
+  }
+}
+
 //=======================================================================
 //function : ForceInterfEE
 //purpose  : 
@@ -791,28 +859,27 @@ Standard_Boolean BOPAlgo_PaveFiller::GetPBBox(const TopoDS_Edge& theE,
 void BOPAlgo_PaveFiller::ForceInterfEE()
 {
   // Now that we have vertices increased and unified, try to find additional
-  // common blocks among the pairs of edges that did not participate in
-  // intersection (PerformEE() method) due to being rejected by bounding boxes.
-  // Here, we are interested in common blocks only, as all real intersections
-  // should have happened already. Thus, we need to look only for the same
-  // vertices in the pairs of pave blocks and check the coincidence of such pave blocks.
+  // common blocks among the pairs of edges.
+  // Since all real intersections should have already happened, here we
+  // are interested in common blocks only, thus we need to check only
+  // those pairs of pave blocks with the same bounding vertices.
 
   Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
 
-  // Initialize pave blocks for all SD vertices
+  // Initialize pave blocks for all vertices which participated in intersections
   const Standard_Integer aNbS = myDS->NbSourceShapes();
   for (Standard_Integer i = 0; i < aNbS; ++i)
   {
     const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
     if (aSI.ShapeType() == TopAbs_VERTEX)
     {
-      Standard_Integer nVSD;
-      if (myDS->HasShapeSD(i, nVSD))
+      if (myDS->HasInterf(i))
         myDS->InitPaveBlocksForVertex(i);
     }
   }
 
-  // Find all Pave Blocks with both paves being SD vertices.
+  // Fill the connection map from bounding vertices to pave blocks
+  // having those bounding vertices
   NCollection_IndexedDataMap<BOPDS_Pair,
                              BOPDS_ListOfPaveBlock,
                              BOPDS_PairMapHasher> aPBMap(1, anAlloc);
@@ -860,8 +927,7 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
   if (!aNbPB)
     return;
 
-  // Find pairs of Pave Blocks having the same SD vertices
-  // and put them into the vector for parallel intersection.
+  // Prepare pave blocks with the same vertices for intersection.
   BOPAlgo_VectorOfEdgeEdge aVEdgeEdge;
 
   for (Standard_Integer i = 1; i <= aNbPB; ++i)
@@ -889,9 +955,16 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
       const Handle(BOPDS_PaveBlock)& aPB1 = aItLPB1.Value();
       const Handle(BOPDS_CommonBlock)& aCB1 = myDS->CommonBlock(aPB1);
       const Standard_Integer nE1 = aPB1->OriginalEdge();
+      const Standard_Integer iR1 = myDS->Rank(nE1);
       const TopoDS_Edge& aE1 = TopoDS::Edge(myDS->Shape(nE1));
       Standard_Real aT11, aT12;
       aPB1->Range(aT11, aT12);
+      BRepAdaptor_Curve aBAC1(aE1);
+      gp_Pnt aPm;
+      gp_Vec aVTgt1;
+      aBAC1.D1((aT11 + aT12) * 0.5, aPm, aVTgt1);
+      if (aVTgt1.SquareMagnitude() < gp::Resolution())
+        continue;
 
       BOPDS_ListIteratorOfListOfPaveBlock aItLPB2 = aItLPB1;
       for (aItLPB2.Next(); aItLPB2.More(); aItLPB2.Next())
@@ -899,10 +972,18 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
         const Handle(BOPDS_PaveBlock)& aPB2 = aItLPB2.Value();
         const Handle(BOPDS_CommonBlock)& aCB2 = myDS->CommonBlock(aPB2);
         const Standard_Integer nE2 = aPB2->OriginalEdge();
+        const Standard_Integer iR2 = myDS->Rank(nE2);
 
-        // Make sure that the edges came from different arguments
-        if (myDS->Rank(nE1) == myDS->Rank(nE2))
-          continue;
+        // Check that the edges came from different arguments
+        if (iR1 == iR2)
+        {
+          // If the sharing of the vertices is not original, but has been acquired
+          // during the operation, check the coincidence of the edges even if
+          // they came from the same argument
+          if (!myDS->IsNewShape(nV1) && (myDS->Rank(nV1) == iR1) ||
+              !myDS->IsNewShape(nV2) && (myDS->Rank(nV2) == iR2))
+            continue;
+        }
 
         // Check that the Pave blocks do not form the Common block already
         if (!aCB1.IsNull() && !aCB2.IsNull())
@@ -915,6 +996,28 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
         Standard_Real aT21, aT22;
         aPB2->Range(aT21, aT22);
 
+        // Check the angle between edges in the middle point.
+        // If the angle is more than 10 degrees, do not use the additional
+        // tolerance, as it may lead to undesired unification of edges
+        Standard_Boolean bUseAddTol = Standard_True;
+        {
+          GeomAPI_ProjectPointOnCurve& aProjPC = myContext->ProjPC(aE2);
+          aProjPC.Perform(aPm);
+          if (!aProjPC.NbPoints())
+            continue;
+
+          BRepAdaptor_Curve aBAC2(aE2);
+          gp_Pnt aPm2;
+          gp_Vec aVTgt2;
+          aBAC2.D1(aProjPC.LowerDistanceParameter(), aPm2, aVTgt2);
+          if (aVTgt2.SquareMagnitude() < gp::Resolution())
+            continue;
+          // The angle should be close to zero
+          Standard_Real aCos = aVTgt1.Dot(aVTgt2);
+          if (Abs(aCos) < 0.984)
+            bUseAddTol = Standard_False;
+        }
+
         // Add pair for intersection
         BOPAlgo_EdgeEdge& anEdgeEdge = aVEdgeEdge.Append1();
         anEdgeEdge.UseQuickCoincidenceCheck(Standard_True);
@@ -922,7 +1025,10 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
         anEdgeEdge.SetPaveBlock2(aPB2);
         anEdgeEdge.SetEdge1(aE1, aT11, aT12);
         anEdgeEdge.SetEdge2(aE2, aT21, aT22);
-        anEdgeEdge.SetFuzzyValue(myFuzzyValue + aTolAdd);
+        if (bUseAddTol)
+          anEdgeEdge.SetFuzzyValue(myFuzzyValue + aTolAdd);
+        else
+          anEdgeEdge.SetFuzzyValue(myFuzzyValue);
         anEdgeEdge.SetProgressIndicator(myProgressIndicator);
       }
     }
@@ -972,6 +1078,16 @@ void BOPAlgo_PaveFiller::ForceInterfEE()
     const Standard_Integer nE1 = aPB[0]->OriginalEdge();
     const Standard_Integer nE2 = aPB[1]->OriginalEdge();
 
+    if (myDS->Rank(nE1) == myDS->Rank(nE2))
+    {
+      // Add acquired self-interference warning
+      TopoDS_Compound aWC;
+      BRep_Builder().MakeCompound(aWC);
+      BRep_Builder().Add(aWC, myDS->Shape(nE1));
+      BRep_Builder().Add(aWC, myDS->Shape(nE2));
+      AddWarning(new BOPAlgo_AlertAcquiredSelfIntersection(aWC));
+    }
+
     BOPDS_InterfEE& aEE = aEEs.Append1();
     aEE.SetIndices(nE1, nE2);
     aEE.SetCommonPart(aCP);
index 900d363bbbee35b25d82ef74707c278153e46732..2249c5b43b5bbdc4be6c6bf1db6469384f1172a2 100644 (file)
@@ -184,6 +184,10 @@ void BOPAlgo_PaveFiller::PerformVF()
   //
   aVFs.SetIncrement(iSize);
   //
+  // Avoid repeated intersection of the same vertex with face in case
+  // the group of vertices formed a single SD vertex
+  NCollection_DataMap<BOPDS_Pair, BOPCol_MapOfInteger, BOPDS_PairMapHasher> aMVFPairs;
+
   for (; myIterator->More(); myIterator->Next()) {
     myIterator->Value(nV, nF);
     //
@@ -191,6 +195,10 @@ void BOPAlgo_PaveFiller::PerformVF()
       continue;
     }
     //
+    if (myDS->HasInterf(nV, nF)) {
+      continue;
+    }
+    //
     myDS->ChangeFaceInfo(nF);
     if (myDS->HasInterfShapeSubShapes(nV, nF)) {
       continue;
@@ -201,12 +209,23 @@ void BOPAlgo_PaveFiller::PerformVF()
       nVx=nVSD;
     }
     //
+    BOPDS_Pair aVFPair(nVx, nF);
+    BOPCol_MapOfInteger* pMV = aMVFPairs.ChangeSeek(aVFPair);
+    if (pMV)
+    {
+      pMV->Add(nV);
+      continue;
+    }
+
+    pMV = aMVFPairs.Bound(aVFPair, BOPCol_MapOfInteger());
+    pMV->Add(nV);
+
     const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&myDS->Shape(nVx))); 
     const TopoDS_Face& aF=(*(TopoDS_Face *)(&myDS->Shape(nF))); 
     //
     BOPAlgo_VertexFace& aVertexFace=aVVF.Append1();
     //
-    aVertexFace.SetIndices(nV, nF);
+    aVertexFace.SetIndices(nVx, nF);
     aVertexFace.SetVertex(aV);
     aVertexFace.SetFace(aF);
     aVertexFace.SetFuzzyValue(myFuzzyValue);
@@ -231,22 +250,30 @@ void BOPAlgo_PaveFiller::PerformVF()
       continue;
     }
     //
-    aVertexFace.Indices(nV, nF);
+    aVertexFace.Indices(nVx, nF);
     aVertexFace.Parameters(aT1, aT2);
-    // 1
-    BOPDS_InterfVF& aVF=aVFs.Append1();
-    aVF.SetIndices(nV, nF);
-    aVF.SetUV(aT1, aT2);
-    // 2
-    myDS->AddInterf(nV, nF);
-    //
-    // 3 update vertex V/F if necessary
     Standard_Real aTolVNew = aVertexFace.VertexNewTolerance();
-    nVx=UpdateVertex(nV, aTolVNew);
-    //
-    // 4
-    if (myDS->IsNewShape(nVx)) {
-      aVF.SetIndexNew(nVx);
+
+    BOPDS_Pair aVFPair(nVx, nF);
+    const BOPCol_MapOfInteger& aMV = aMVFPairs.Find(aVFPair);
+    BOPCol_MapIteratorOfMapOfInteger itMV(aMV);
+    for (; itMV.More(); itMV.Next())
+    {
+      nV = itMV.Value();
+      // 1
+      BOPDS_InterfVF& aVF = aVFs.Append1();
+      aVF.SetIndices(nV, nF);
+      aVF.SetUV(aT1, aT2);
+      // 2
+      myDS->AddInterf(nV, nF);
+      //
+      // 3 update vertex V/F if necessary
+      nVx = UpdateVertex(nV, aTolVNew);
+      //
+      // 4
+      if (myDS->IsNewShape(nVx)) {
+        aVF.SetIndexNew(nVx);
+      }
     }
     // 5 update FaceInfo
     BOPDS_FaceInfo& aFI=myDS->ChangeFaceInfo(nF);
index 717e4789201074e96ceb27451f12dcc809876b73..9fc1c4a4a17b23e970df7204ed52b8f0ee207a6f 100644 (file)
 #include <BOPDS_Pave.hxx>
 #include <BOPDS_PaveBlock.hxx>
 #include <BOPTools_AlgoTools.hxx>
+#include <BOPTools_AlgoTools2D.hxx>
+#include <BOPCol_BoxBndTree.hxx>
 #include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
 #include <BRepAdaptor_Curve.hxx>
+#include <GeomAPI_ProjectPointOnSurf.hxx>
 #include <gp_Pnt.hxx>
 #include <IntTools_CommonPrt.hxx>
 #include <IntTools_Context.hxx>
@@ -43,6 +46,7 @@
 #include <IntTools_Range.hxx>
 #include <IntTools_SequenceOfCommonPrts.hxx>
 #include <IntTools_Tools.hxx>
+#include <NCollection_IncAllocator.hxx>
 #include <Precision.hxx>
 #include <TopoDS.hxx>
 #include <TopoDS_Edge.hxx>
@@ -256,7 +260,11 @@ void BOPAlgo_PaveFiller::PerformEF()
       BOPTools_AlgoTools::CorrectRange(aE, aF, aSR, aPBRange);
       aEdgeFace.SetRange (aPBRange);
       aEdgeFace.SetProgressIndicator(myProgressIndicator);
-      //
+      // Save the pair to avoid their forced intersection
+      BOPDS_MapOfPaveBlock* pMPB = myFPBDone.ChangeSeek(nF);
+      if (!pMPB)
+        pMPB = myFPBDone.Bound(nF, BOPDS_MapOfPaveBlock());
+      pMPB->Add(aPB);
     }//for (; aIt.More(); aIt.Next()) {
   }//for (; myIterator->More(); myIterator->Next()) {
   //
@@ -359,72 +367,86 @@ void BOPAlgo_PaveFiller::PerformEF()
             continue;
           }
           //
-          for (j=0; j<2; ++j) {
-            if (bIsOnPave[j]) {
-              bV[j]=CheckFacePaves(nV[j], aMIFOn, aMIFIn);
-              if (bV[j]) {
-                const TopoDS_Vertex& aV=
-                  (*(TopoDS_Vertex *)(&myDS->Shape(nV[j])));
-                //
-                Standard_Real f, l, aTolVnew, aDistPP, aTolPC, aTolV;
-                //
-                const Handle(Geom_Curve)& aCur = BRep_Tool::Curve(aE, f, l);
-                //
-                gp_Pnt aP1 = BRep_Tool::Pnt(aV);
-                gp_Pnt aP2 = aCur->Value(aT);
-                //
-                aDistPP=aP1.Distance(aP2);
-                //
-                aTolPC=Precision::PConfusion();
-                aTolV=BRep_Tool::Tolerance(aV);
-                if (aDistPP > (aTolV+aTolPC)) {
-                  aTolVnew=Max(aTolE, aDistPP);
-                  UpdateVertex(nV[j], aTolVnew);
-                }
-              }
-              else {
+          for (j = 0; j < 2; ++j)
+          {
+            if (bIsOnPave[j])
+            {
+              bV[j] = CheckFacePaves(nV[j], aMIFOn, aMIFIn);
+              if (!bV[j])
                 bIsOnPave[j] = ForceInterfVF(nV[j], nF);
-              }
             }
           }
-          //
-          if (!bIsOnPave[0] && !bIsOnPave[1]) {
-            if (CheckFacePaves(aVnew, aMIFOn)) {
-              continue;
-            }
-            //
-            Standard_Real aTolVnew = BRep_Tool::Tolerance(aVnew);
-            aTolVnew = Max(aTolVnew, Max(aTolE, aTolF));
-            BRep_Builder().UpdateVertex(aVnew, aTolVnew);
-            if (bLinePlane) {
-              // increase tolerance for Line/Plane intersection, but do not update 
-              // the vertex till its intersection with some other shape
-              IntTools_Range aCR = aCPart.Range1();
-              aTolVnew = Max(aTolVnew, (aCR.Last() - aCR.First()) / 2.);
-            }
-            //
-            const gp_Pnt& aPnew = BRep_Tool::Pnt(aVnew);
-            //
-            if (!myContext->IsPointInFace(aPnew, aF, aTolVnew)) {
+
+          if (bIsOnPave[0] || bIsOnPave[1])
+          {
+            // The found intersection point is located closely to one of the pave block's
+            // bounds. So, do not create the new vertex in this point.
+            // Check if this point is a real intersection, or just a touching point.
+            // If it is a touching point, do nothing.
+            // If it is an intersection point, update the existing vertex to cover the
+            // intersection point.
+            GeomAPI_ProjectPointOnSurf& aProjPS = myContext->ProjPS(aF);
+            const gp_Pnt aPnew = BRep_Tool::Pnt(aVnew);
+            aProjPS.Perform(aPnew);
+            Standard_Real aMinDistEF = (aProjPS.IsDone() && aProjPS.NbPoints()) ?
+                                        aProjPS.LowerDistance() : Precision::Infinite();
+            Standard_Boolean hasRealIntersection = aMinDistEF < Precision::Intersection();
+
+            if (!hasRealIntersection)
+              // no intersection point
               continue;
+
+            // Real intersection is present.
+            // Update the existing vertex to cover the intersection point.
+            for (j = 0; j < 2; ++j)
+            {
+              if (bIsOnPave[j])
+              {
+                const TopoDS_Vertex& aV = TopoDS::Vertex(myDS->Shape(nV[j]));
+                const gp_Pnt aP = BRep_Tool::Pnt(aV);
+                Standard_Real aDistPP = aP.Distance(aPnew);
+                UpdateVertex(nV[j], aDistPP);
+                myVertsToAvoidExtension.Add(nV[j]);
+              }
             }
-            //
-            aMIEFC.Add(nF);
-            // 1
-            BOPDS_InterfEF& aEF=aEFs.Append1();
-            iX=aEFs.Extent()-1;
-            aEF.SetIndices(nE, nF);
-            aEF.SetCommonPart(aCPart);
-            // 2
-            myDS->AddInterf(nE, nF);
-            // 3
-            BOPDS_CoupleOfPaveBlocks aCPB;
-            //
-            aCPB.SetPaveBlocks(aPB, aPB);
-            aCPB.SetIndexInterf(iX);
-            aCPB.SetTolerance(aTolVnew);
-            aMVCPB.Add(aVnew, aCPB);
+            continue;
+          }
+
+          if (CheckFacePaves(aVnew, aMIFOn)) {
+            continue;
+          }
+          //
+          Standard_Real aTolVnew = BRep_Tool::Tolerance(aVnew);
+          aTolVnew = Max(aTolVnew, Max(aTolE, aTolF));
+          BRep_Builder().UpdateVertex(aVnew, aTolVnew);
+          if (bLinePlane) {
+            // increase tolerance for Line/Plane intersection, but do not update 
+            // the vertex till its intersection with some other shape
+            IntTools_Range aCR = aCPart.Range1();
+            aTolVnew = Max(aTolVnew, (aCR.Last() - aCR.First()) / 2.);
           }
+          //
+          const gp_Pnt& aPnew = BRep_Tool::Pnt(aVnew);
+          //
+          if (!myContext->IsPointInFace(aPnew, aF, aTolVnew)) {
+            continue;
+          }
+          //
+          aMIEFC.Add(nF);
+          // 1
+          BOPDS_InterfEF& aEF = aEFs.Append1();
+          iX = aEFs.Length() - 1;
+          aEF.SetIndices(nE, nF);
+          aEF.SetCommonPart(aCPart);
+          // 2
+          myDS->AddInterf(nE, nF);
+          // 3
+          BOPDS_CoupleOfPaveBlocks aCPB;
+          //
+          aCPB.SetPaveBlocks(aPB, aPB);
+          aCPB.SetIndexInterf(iX);
+          aCPB.SetTolerance(aTolVnew);
+          aMVCPB.Add(aVnew, aCPB);
         }
           break;
         case TopAbs_EDGE:  {
@@ -458,7 +480,8 @@ void BOPAlgo_PaveFiller::PerformEF()
   //=========================================
   // post treatment
   //=========================================
-  BOPAlgo_Tools::PerformCommonBlocks(aMPBLI, aAllocator, myDS);
+  BOPAlgo_Tools::PerformCommonBlocks(aMPBLI, aAllocator, myDS, myContext);
+  UpdateVerticesOfCB();
   PerformNewVertices(aMVCPB, aAllocator, Standard_False);
   //
   // Update FaceInfoIn for all faces having EF common parts
@@ -667,3 +690,343 @@ void BOPAlgo_PaveFiller::ReduceIntersectionRange(const Standard_Integer theV1,
     }
   }
 }
+
+//=======================================================================
+//function : ForceInterfEF
+//purpose  : 
+//=======================================================================
+void BOPAlgo_PaveFiller::ForceInterfEF()
+{
+  if (!myIsPrimary)
+    return;
+
+  // Now that we have vertices increased and unified, try to find additional
+  // edge/face common blocks among the pairs of edge/face.
+  // Here, we are interested in common blocks only, as all real intersections
+  // should have happened already. Thus, we need to check only those pairs
+  // of edge/face which have the same vertices.
+
+  // Collect all pave blocks
+  BOPDS_IndexedMapOfPaveBlock aMPB;
+  const Standard_Integer aNbS = myDS->NbSourceShapes();
+  for (Standard_Integer nE = 0; nE < aNbS; ++nE)
+  {
+    const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nE);
+    if (aSI.ShapeType() != TopAbs_EDGE)
+      // Not an edge
+      continue;
+
+    if (!aSI.HasReference())
+      // Edge has no pave blocks
+      continue;
+
+    if (aSI.HasFlag())
+      // Degenerated edge
+      continue;
+
+    const BOPDS_ListOfPaveBlock& aLPB = myDS->PaveBlocks(nE);
+    BOPDS_ListIteratorOfListOfPaveBlock aItLPB(aLPB);
+    for (; aItLPB.More(); aItLPB.Next())
+    {
+      const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
+      const Handle(BOPDS_PaveBlock)& aPBR = myDS->RealPaveBlock(aPB);
+      aMPB.Add(aPBR);
+    }
+  }
+
+  // Perform intersection of collected pave blocks with faces
+  ForceInterfEF(aMPB, Standard_True);
+}
+
+//=======================================================================
+//function : ForceInterfEF
+//purpose  : 
+//=======================================================================
+void BOPAlgo_PaveFiller::ForceInterfEF(const BOPDS_IndexedMapOfPaveBlock& theMPB,
+                                       const Standard_Boolean theAddInterf)
+{
+  if (theMPB.IsEmpty())
+    return;
+
+  // Fill the tree with bounding boxes of the pave blocks
+  NCollection_UBTree<Standard_Integer, Bnd_Box> aBBTree;
+  NCollection_UBTreeFiller<Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
+
+  Handle(NCollection_IncAllocator) anAlloc = new NCollection_IncAllocator;
+  BOPDS_IndexedMapOfPaveBlock aPBMap(1, anAlloc);
+
+  Standard_Integer aNbPB = theMPB.Extent();
+  for (Standard_Integer iPB = 1; iPB <= aNbPB; ++iPB)
+  {
+    Handle(BOPDS_PaveBlock) aPB = theMPB(iPB);
+    if (!aPB->HasShrunkData() || !myDS->IsValidShrunkData(aPB))
+    {
+      FillShrunkData(aPB);
+      if (!aPB->HasShrunkData())
+        continue;
+    }
+
+    Standard_Real f, l;
+    Bnd_Box aPBBox;
+    Standard_Boolean isSplit;
+    aPB->ShrunkData(f, l, aPBBox, isSplit);
+
+    aTreeFiller.Add(aPBMap.Add(aPB), aPBBox);
+  }
+
+  // Shake the tree
+  aTreeFiller.Fill();
+
+  // Find pairs of Face/PaveBlock containing the same vertices
+  // and prepare those pairs for intersection.
+  BOPAlgo_VectorOfEdgeFace aVEdgeFace;
+
+  const Standard_Integer aNbS = myDS->NbSourceShapes();
+  for (Standard_Integer nF = 0; nF < aNbS; ++nF)
+  {
+    const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nF);
+    if (aSI.ShapeType() != TopAbs_FACE)
+      // Not a face
+      continue;
+
+    if (!aSI.HasReference())
+      // Face has no face info
+      continue;
+
+    const Bnd_Box& aBoxF = aSI.Box();
+    BOPCol_BoxBndTreeSelector aSelector;
+    aSelector.SetBox(aBoxF);
+
+    if (!aBBTree.Select(aSelector))
+      continue;
+
+    const TopoDS_Face& aF = TopoDS::Face(aSI.Shape());
+    const BOPDS_FaceInfo& aFI = myDS->FaceInfo(nF);
+    // Vertices of the face
+    BOPCol_MapOfInteger aMVF;
+    const BOPCol_MapOfInteger* pMVF[] = { &aFI.VerticesOn(),
+                                           &aFI.VerticesIn(),
+                                           &aFI.VerticesSc() };
+    for (Standard_Integer iM = 0; iM < 3; ++iM)
+    {
+      BOPCol_MapIteratorOfMapOfInteger itM(*pMVF[iM]);
+      for (; itM.More(); itM.Next())
+        aMVF.Add(itM.Value());
+    }
+
+    // Pave Blocks of the face
+    const BOPDS_IndexedMapOfPaveBlock* pMPBF[] = { &aFI.PaveBlocksOn(),
+                                                   &aFI.PaveBlocksIn(),
+                                                   &aFI.PaveBlocksSc() };
+    for (Standard_Integer iM = 0; iM < 3; ++iM)
+    {
+      const Standard_Integer aNb = pMPBF[iM]->Extent();
+      for (Standard_Integer iPB = 1; iPB <= aNb; ++iPB)
+      {
+        const Handle(BOPDS_PaveBlock)& aPB = pMPBF[iM]->FindKey(iPB);
+        aMVF.Add(aPB->Pave1().Index());
+        aMVF.Add(aPB->Pave2().Index());
+      }
+    }
+
+    // Projection tool
+    GeomAPI_ProjectPointOnSurf& aProjPS = myContext->ProjPS(aF);
+
+    // Iterate on pave blocks and combine pairs containing
+    // the same vertices
+    const BOPCol_ListOfInteger& aLIPB = aSelector.Indices();
+    BOPCol_ListOfInteger::Iterator itLIPB(aLIPB);
+    for (; itLIPB.More(); itLIPB.Next())
+    {
+      const Handle(BOPDS_PaveBlock)& aPB = aPBMap(itLIPB.Value());
+      if (pMPBF[0]->Contains(aPB) ||
+          pMPBF[1]->Contains(aPB) ||
+          pMPBF[2]->Contains(aPB))
+        continue;
+
+      // Check if the face contains both vertices of the pave block
+      Standard_Integer nV1, nV2;
+      aPB->Indices(nV1, nV2);
+      if (!aMVF.Contains(nV1) || !aMVF.Contains(nV2))
+        // Face does not contain the vertices
+        continue;
+
+      // Get the edge
+      Standard_Integer nE;
+      if (!aPB->HasEdge(nE))
+      {
+        nE = aPB->OriginalEdge();
+        if (nE < 0)
+          continue;
+
+        // Make sure that the edge and face came from different arguments
+        if (myDS->Rank(nF) == myDS->Rank(nE))
+          continue;
+      }
+
+      const TopoDS_Edge& aE = TopoDS::Edge(myDS->Shape(nE));
+      BRepAdaptor_Curve aBAC(aE);
+
+      // Check directions coincidence at middle point on the edge
+      // and projection of that point on the face.
+      // If the angle between tangent vector to the curve and normal
+      // of the face is not in the range of 80 - 100 degrees, do not use the additional
+      // tolerance, as it may lead to undesired unification of edge with the face.
+      Standard_Boolean bUseAddTol = Standard_True;
+
+      Standard_Real aTS[2];
+      Bnd_Box aPBBox;
+      Standard_Boolean isSplit;
+      aPB->ShrunkData(aTS[0], aTS[1], aPBBox, isSplit);
+
+      // Middle point
+      gp_Pnt aPOnE;
+      // Tangent vector in the middle point
+      gp_Vec aVETgt;
+      aBAC.D1(BOPTools_AlgoTools2D::IntermediatePoint(aTS[0], aTS[1]), aPOnE, aVETgt);
+      if (aVETgt.SquareMagnitude() < gp::Resolution())
+        continue;
+
+      aProjPS.Perform(aPOnE);
+      if (!aProjPS.NbPoints())
+        continue;
+
+      // Check the distance in the middle point, using the max vertices
+      // tolerance as the criteria.
+      const TopoDS_Vertex& aV1 = TopoDS::Vertex(myDS->Shape(nV1));
+      const TopoDS_Vertex& aV2 = TopoDS::Vertex(myDS->Shape(nV2));
+      Standard_Real aTolCheck = 2 * Max(BRep_Tool::Tolerance(aV1),
+                                        BRep_Tool::Tolerance(aV2));
+
+      if (aProjPS.LowerDistance() > aTolCheck + myFuzzyValue)
+        continue;
+
+      Standard_Real U, V;
+      aProjPS.LowerDistanceParameters(U, V);
+      if (!myContext->IsPointInFace(aF, gp_Pnt2d(U, V)))
+        continue;
+
+      gp_Pnt aPOnS = aProjPS.NearestPoint();
+      gp_Vec aVFNorm(aPOnS, aPOnE);
+      if (aVFNorm.SquareMagnitude() > gp::Resolution())
+      {
+        // Angle between vectors should be close to 90 degrees.
+        // We allow deviation of 10 degrees.
+        Standard_Real aCos = aVFNorm.Dot(aVETgt);
+        if (Abs(aCos) > 0.174)
+          bUseAddTol = Standard_False;
+      }
+
+      // Compute an addition to Fuzzy value
+      Standard_Real aTolAdd = 0.0;
+      if (bUseAddTol)
+      {
+        // Compute the distance from the bounding points of the edge
+        // to the face and use the maximal of these distances as a
+        // fuzzy tolerance for the intersection.
+        // Use the maximal tolerance of the pave block's vertices
+        // as a max criteria for the computed distance.
+
+        for (Standard_Integer iP = 0; iP < 2; ++iP)
+        {
+          gp_Pnt aP = aBAC.Value(aTS[iP]);
+          aProjPS.Perform(aP);
+          if (aProjPS.NbPoints())
+          {
+            Standard_Real aDistEF = aProjPS.LowerDistance();
+            if (aDistEF < aTolCheck && aDistEF > aTolAdd)
+              aTolAdd = aDistEF;
+          }
+        }
+        if (aTolAdd > 0.)
+        {
+          aTolAdd -= (BRep_Tool::Tolerance(aE) + BRep_Tool::Tolerance(aF));
+          if (aTolAdd < 0.)
+            aTolAdd = 0.;
+        }
+      }
+
+      Standard_Boolean bIntersect = aTolAdd > 0;
+      if (!bIntersect)
+      {
+        const BOPDS_MapOfPaveBlock* pMPB = myFPBDone.Seek(nF);
+        bIntersect = !pMPB || !(pMPB->Contains(aPB));
+      }
+
+      if (bIntersect)
+      {
+        // Prepare pair for intersection
+        BOPAlgo_EdgeFace& aEdgeFace = aVEdgeFace.Append1();
+        aEdgeFace.SetIndices(nE, nF);
+        aEdgeFace.SetPaveBlock(aPB);
+        aEdgeFace.SetEdge(aE);
+        aEdgeFace.SetFace(aF);
+        aEdgeFace.SetFuzzyValue(myFuzzyValue + aTolAdd);
+        aEdgeFace.UseQuickCoincidenceCheck(Standard_True);
+        aEdgeFace.SetRange(IntTools_Range(aPB->Pave1().Parameter(), aPB->Pave2().Parameter()));
+        aEdgeFace.SetProgressIndicator(myProgressIndicator);
+      }
+    }
+  }
+
+  Standard_Integer aNbEFs = aVEdgeFace.Extent();
+  if (!aNbEFs)
+    return;
+
+  aPBMap.Clear();
+  anAlloc->Reset();
+
+  // Perform intersection of the found pairs
+  BOPAlgo_EdgeFaceCnt::Perform(myRunParallel, aVEdgeFace, myContext);
+
+  BOPDS_VectorOfInterfEF& aEFs = myDS->InterfEF();
+  if (theAddInterf && aEFs.IsEmpty())
+    aEFs.SetIncrement(10);
+
+  // Analyze the results of intersection looking for TopAbs_EDGE
+  // intersection type only.
+
+  // Collect all pairs for common block creation
+  BOPDS_IndexedDataMapOfPaveBlockListOfInteger aMPBLI(1, anAlloc);
+
+  for (Standard_Integer i = 0; i < aNbEFs; ++i)
+  {
+    BOPAlgo_EdgeFace& anEdgeFace = aVEdgeFace(i);
+    if (!anEdgeFace.IsDone() || anEdgeFace.HasErrors())
+    {
+      // Warn about failed intersection of sub-shapes
+      AddIntersectionFailedWarning(anEdgeFace.Edge(), anEdgeFace.Face());
+      continue;
+    }
+
+    const IntTools_SequenceOfCommonPrts& aCParts = anEdgeFace.CommonParts();
+    if (aCParts.Length() != 1)
+      continue;
+
+    const IntTools_CommonPrt& aCP = aCParts(1);
+    if (aCP.Type() != TopAbs_EDGE)
+      continue;
+
+    Standard_Integer nE, nF;
+    anEdgeFace.Indices(nE, nF);
+    if (theAddInterf)
+    {
+      // Add interference
+      BOPDS_InterfEF& aEF = aEFs.Append1();
+      aEF.SetIndices(nE, nF);
+      aEF.SetCommonPart(aCP);
+      myDS->AddInterf(nE, nF);
+    }
+
+    const Handle(BOPDS_PaveBlock)& aPB = anEdgeFace.PaveBlock();
+    // Update face information with new IN pave block
+    myDS->ChangeFaceInfo(nF).ChangePaveBlocksIn().Add(aPB);
+    if (theAddInterf)
+      // Fill map for common blocks creation
+      BOPAlgo_Tools::FillMap(aPB, nF, aMPBLI, anAlloc);
+  }
+
+  if (aMPBLI.Extent())
+    // Create new common blocks for coinciding pairs
+    BOPAlgo_Tools::PerformCommonBlocks(aMPBLI, anAlloc, myDS);
+}
index 664ff652b5e72ac56ea0e45043b61029672f54e4..100419091cd8711eb640492f0a3d3113af439195 100644 (file)
@@ -362,6 +362,28 @@ void BOPAlgo_PaveFiller::PerformFF()
     }
   }
 }
+
+//=======================================================================
+//function : UpdateSavedTolerance
+//purpose  : Updates the saved tolerance of the vertices of the edge
+//           with new tolerance of edge
+//=======================================================================
+static void UpdateSavedTolerance(const BOPDS_PDS& theDS,
+                                 const Standard_Integer theNE,
+                                 const Standard_Real theTolNew,
+                                 BOPCol_DataMapOfIntegerReal& theMVTol)
+{
+  const BOPCol_ListOfInteger& aSubShapes = theDS->ShapeInfo(theNE).SubShapes();
+  BOPCol_ListIteratorOfListOfInteger itSS(aSubShapes);
+  for (; itSS.More(); itSS.Next())
+  {
+    const Standard_Integer nV = itSS.Value();
+    Standard_Real *pTolSaved = theMVTol.ChangeSeek(nV);
+    if (pTolSaved && *pTolSaved < theTolNew)
+      *pTolSaved = theTolNew;
+  }
+}
+
 //=======================================================================
 //function : MakeBlocks
 //purpose  : 
@@ -406,8 +428,10 @@ void BOPAlgo_PaveFiller::MakeBlocks()
   BOPCol_DataMapOfIntegerListOfInteger aDMVLV;
   BOPCol_DataMapOfIntegerListOfInteger aDMBV(100, aAllocator);
   BOPCol_DataMapIteratorOfDataMapOfIntegerReal aItMV;
-  BOPCol_IndexedMapOfShape aMicroEdges(100, aAllocator);
+  BOPDS_IndexedMapOfPaveBlock aMicroPB(100, aAllocator);
   BOPCol_IndexedMapOfShape aVertsOnRejectedPB;
+  // Map of PaveBlocks with the faces to which it has to be added
+  BOPAlgo_DataMapOfPaveBlockListOfInteger aPBFacesMap;
   //
   for (i=0; i<aNbFF; ++i) {
     //
@@ -477,7 +501,7 @@ void BOPAlgo_PaveFiller::MakeBlocks()
     // if some E-F vertex was put on a curve due to large E-F intersection range,
     // and it also was put on another curve correctly then remove this vertex from
     // the first curve. Detect such case if the distance to curve exceeds aTolR3D.
-    FilterPavesOnCurves(aVC);
+    FilterPavesOnCurves(aVC, aMVTol);
 
     for (j = 0; j<aNbC; ++j) {
       BOPDS_Curve& aNC=aVC.ChangeValue(j);
@@ -531,32 +555,44 @@ void BOPAlgo_PaveFiller::MakeBlocks()
         if (fabs(aT1 - aT2) < Precision::PConfusion()) {
           continue;
         }
-        //
-        bValid2D=myContext->IsValidBlockForFaces(aT1, aT2, aIC, 
+
+        // Check validity of the block for the faces:
+        // classify bounding and middle points on the curve
+        // relatively both faces
+        bValid2D=myContext->IsValidBlockForFaces(aT1, aT2, aIC,
                                                  aF1, aF2, aTolR3D);
         if (!bValid2D) {
           continue;
         }
         //
-        bExist=IsExistingPaveBlock(aPB, aNC, aLSE);
-        if (bExist) {
+        Standard_Integer nEOut;
+        Standard_Real aTolNew;
+        bExist = IsExistingPaveBlock(aPB, aNC, aLSE, nEOut, aTolNew);
+        if (bExist)
+        {
+          // Update edge with new tolerance
+          UpdateEdgeTolerance(nEOut, aTolNew);
+          // Update aMVTol map with new tolerances of vertices
+          UpdateSavedTolerance(myDS, nEOut, aTolNew, aMVTol);
           continue;
         }
         //
         const TopoDS_Vertex& aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
         const TopoDS_Vertex& aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
         //
-        // Make Edge
-        BOPTools_AlgoTools::MakeEdge (aIC, aV1, aT1, aV2, aT2, aTolR3D, aES);
-        //
-        // check for micro edge
-        if (BOPTools_AlgoTools::IsMicroEdge(aES, myContext, Standard_False)) {
-          // If the section edge is a micro edge, i.e. the whole edge is
+        // check if the pave block has a valid range
+        Standard_Real aFirst, aLast;
+        if (!BRepLib::FindValidRange(GeomAdaptor_Curve(aIC.Curve()), aTolR3D,
+                                     aT1, BRep_Tool::Pnt(aV1), BRep_Tool::Tolerance(aV1),
+                                     aT2, BRep_Tool::Pnt(aV2), BRep_Tool::Tolerance(aV2),
+                                     aFirst, aLast))
+        {
+          // If the pave block does not have valid range, i.e. it is completely
           // covered by the tolerance spheres of its vertices, it will be
           // passed into post treatment process to fuse its vertices.
-          // The edge itself will not be kept.
+          // The pave block itself will not be kept.
           if (!aMVBounds.Contains(nV1) && !aMVBounds.Contains(nV2)) {
-            aMicroEdges.Add(aES);
+            aMicroPB.Add(aPB);
             // keep vertices for post treatment
             aMVI.Bind(aV1, nV1);
             aMVI.Bind(aV2, nV2);
@@ -564,33 +600,39 @@ void BOPAlgo_PaveFiller::MakeBlocks()
           continue;
         }
         //
-        Standard_Real aTolNew;
-        bExist=IsExistingPaveBlock(aPB, aNC, aTolR3D, aMPBOnIn, aMPBCommon, aPBOut, aTolNew);
-        if (bExist) {
-          if (!aMPBAdd.Contains(aPBOut)) {
-            Standard_Boolean bInBothFaces = Standard_True;
-            if (!myDS->IsCommonBlock(aPBOut)) {
-              Standard_Integer nE;
-              Standard_Real aTolE;
-              //
-              nE = aPBOut->Edge();
-              const TopoDS_Edge& aE = *(TopoDS_Edge*)&myDS->Shape(nE);
-              aTolE = BRep_Tool::Tolerance(aE);
-              if (aTolNew < aNC.Tolerance())
-                aTolNew = aNC.Tolerance();  // use real tolerance of intersection
-              if (aTolNew > aTolE) {
-                UpdateEdgeTolerance(nE, aTolNew);
-              }
-              bInBothFaces = Standard_False;
-            } 
-            else {
-              bInBothFaces = (aFI1.PaveBlocksOn().Contains(aPBOut) ||
-                              aFI1.PaveBlocksIn().Contains(aPBOut))&&
-                             (aFI2.PaveBlocksOn().Contains(aPBOut) ||
-                              aFI2.PaveBlocksIn().Contains(aPBOut));
+        bExist = IsExistingPaveBlock(aPB, aNC, aTolR3D, aMPBOnIn, aMPBCommon, aPBOut, aTolNew);
+        if (bExist)
+        {
+          Standard_Boolean bInF1 = (aFI1.PaveBlocksOn().Contains(aPBOut) ||
+                                    aFI1.PaveBlocksIn().Contains(aPBOut));
+          Standard_Boolean bInF2 = (aFI2.PaveBlocksOn().Contains(aPBOut) ||
+                                    aFI2.PaveBlocksIn().Contains(aPBOut));
+          if (!bInF1 || !bInF2)
+          {
+            // Update edge to touch both faces
+            Standard_Integer nE = aPBOut->Edge();
+            const TopoDS_Edge& aE = *(TopoDS_Edge*)&myDS->Shape(nE);
+            Standard_Real aTolE = BRep_Tool::Tolerance(aE);
+            if (aTolNew < aNC.Tolerance())
+              aTolNew = aNC.Tolerance();  // use real tolerance of intersection
+            if (aTolNew > aTolE) {
+              UpdateEdgeTolerance(nE, aTolNew);
+              // Update aMVTol map with new tolerances of vertices
+              UpdateSavedTolerance(myDS, nE, aTolNew, aMVTol);
             }
-            if (!bInBothFaces) {
-              aMPBAdd.Add(aPBOut);
+
+            // Face without pave block
+            const Standard_Integer nF = bInF1 ? nF2 : nF1;
+            BOPCol_ListOfInteger* pFaces = aPBFacesMap.ChangeSeek(aPBOut);
+            if (!pFaces)
+              pFaces = aPBFacesMap.Bound(aPBOut, BOPCol_ListOfInteger());
+            // List is expected to be short, so we allow the check here
+            if (pFaces->IsEmpty() || !pFaces->Contains(nF))
+              pFaces->Append(nF);
+
+            if (aMPBAdd.Add(aPBOut))
+            {
+              // Add edge for processing as the section edge
               PreparePostTreatFF(i, j, aPBOut, aMSCPB, aMVI, aLPBC);
               // Try fusing the vertices of the existing pave block
               // with the vertices put on the real section curve (except
@@ -610,6 +652,8 @@ void BOPAlgo_PaveFiller::MakeBlocks()
           continue;
         }
         //
+        // Make Edge
+        BOPTools_AlgoTools::MakeEdge (aIC, aV1, aT1, aV2, aT2, aTolR3D, aES);
         // Make p-curves
         BOPTools_AlgoTools::MakePCurve(aES, aF1, aF2, aIC, 
                                        mySectionAttribute.PCurveOnS1(),
@@ -660,7 +704,7 @@ void BOPAlgo_PaveFiller::MakeBlocks()
         aDMVLV.UnBind(nV1);
     }
     //
-    ProcessExistingPaveBlocks(i, aMPBOnIn, aDMBV, aMSCPB, aMVI, aMPBAdd);
+    ProcessExistingPaveBlocks(i, nF1, nF2, aMPBOnIn, aDMBV, aMSCPB, aMVI, aPBFacesMap, aMPBAdd);
     //
     // If the pair of faces has produced any real section edges
     // it is necessary to check if these edges do not intersect
@@ -684,10 +728,13 @@ void BOPAlgo_PaveFiller::MakeBlocks()
       }
     }
   }//for (i=0; i<aNbFF; ++i) {
-  // 
+
+  // Remove "micro" section edges
+  RemoveMicroSectionEdges(aMSCPB, aMicroPB);
+
   // post treatment
   MakeSDVerticesFF(aDMVLV, aDMNewSD);
-  PostTreatFF(aMSCPB, aDMExEdges, aDMNewSD, aMicroEdges, aVertsOnRejectedPB, aAllocator);
+  PostTreatFF(aMSCPB, aDMExEdges, aDMNewSD, aMicroPB, aVertsOnRejectedPB, aAllocator);
   if (HasErrors()) {
     return;
   }
@@ -695,7 +742,7 @@ void BOPAlgo_PaveFiller::MakeBlocks()
   CorrectToleranceOfSE();
   //
   // update face info
-  UpdateFaceInfo(aDMExEdges, aDMNewSD);
+  UpdateFaceInfo(aDMExEdges, aDMNewSD, aPBFacesMap);
   //Update all pave blocks
   UpdatePaveBlocks(aDMNewSD);
   //
@@ -744,7 +791,7 @@ void BOPAlgo_PaveFiller::PostTreatFF
     (BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMSCPB,
      BOPDS_DataMapOfPaveBlockListOfPaveBlock& aDMExEdges,
      BOPCol_DataMapOfIntegerInteger& aDMNewSD,
-     const BOPCol_IndexedMapOfShape& theMicroEdges,
+     const BOPDS_IndexedMapOfPaveBlock& theMicroPB,
      const BOPCol_IndexedMapOfShape& theVertsOnRejectedPB,
      const Handle(NCollection_BaseAllocator)& theAllocator)
 {
@@ -772,7 +819,7 @@ void BOPAlgo_PaveFiller::PostTreatFF
   //
   BOPDS_VectorOfInterfFF& aFFs=myDS->InterfFF();
   //
-  Standard_Integer aNbME = theMicroEdges.Extent();
+  Standard_Integer aNbME = theMicroPB.Extent();
   Standard_Integer aNbVOnRPB = theVertsOnRejectedPB.Extent();
   // 0
   if (aNbS==1 && (aNbME == 0) && (aNbVOnRPB == 0)) {
@@ -839,20 +886,14 @@ void BOPAlgo_PaveFiller::PostTreatFF
   //
   BRep_Builder aBB;
   for (k = 1; k <= aNbME; ++k) {
-    const TopoDS_Edge& aEM = TopoDS::Edge(theMicroEdges(k));
-    //
+    Standard_Integer nVerts[2];
+    theMicroPB(k)->Indices(nVerts[0], nVerts[1]);
     TopoDS_Vertex aVerts[2];
-    TopExp::Vertices(aEM, aVerts[0], aVerts[1]);
     for (Standard_Integer i = 0; i < 2; ++i) {
-      nV = myDS->Index(aVerts[i]);
-      const Standard_Integer* pSD = aDMNewSD.Seek(nV);
-      if (pSD) {
-        aVerts[i] = TopoDS::Vertex(myDS->Shape(*pSD));
-      }
-      //
-      if (anAddedSD.Add(aVerts[i])) {
+      const Standard_Integer* pSD = aDMNewSD.Seek(nVerts[i]);
+      aVerts[i] = TopoDS::Vertex(myDS->Shape(pSD ? *pSD : nVerts[i]));
+      if (anAddedSD.Add(aVerts[i]))
         aLS.Append(aVerts[i]);
-      }
     }
     //
     if (aVerts[0].IsSame(aVerts[1])) {
@@ -983,7 +1024,7 @@ void BOPAlgo_PaveFiller::PostTreatFF
         BOPDS_Curve& aNC=aVNC(iC);
         BOPDS_ListOfPaveBlock& aLPBC=aNC.ChangePaveBlocks();
         //
-        // check if edge occured to be micro edge;
+        // check if edge occurred to be micro edge;
         // note we check not the edge aSx itself, but its image in aPDS
         const BOPDS_ListOfPaveBlock& aLPBx = aPDS->PaveBlocks(nSx);
         aNbLPBx = aLPBx.Extent();
@@ -1126,16 +1167,19 @@ void BOPAlgo_PaveFiller::PostTreatFF
 //=======================================================================
 void BOPAlgo_PaveFiller::UpdateFaceInfo
   (BOPDS_DataMapOfPaveBlockListOfPaveBlock& theDME,
-   const BOPCol_DataMapOfIntegerInteger& theDMV)
+   const BOPCol_DataMapOfIntegerInteger& theDMV,
+   const BOPAlgo_DataMapOfPaveBlockListOfInteger& thePBFacesMap)
 {
   Standard_Integer i, j, nV1, nF1, nF2, 
                    aNbFF, aNbC, aNbP;
   BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
   BOPCol_MapOfInteger aMF;
-  //
+
+  // Unify pave blocks of the existing edges united on the post-treat stage
+  NCollection_DataMap<Standard_Integer, BOPDS_ListOfPaveBlock> anEdgeLPB;
+
   BOPDS_VectorOfInterfFF& aFFs=myDS->InterfFF();
   aNbFF=aFFs.Extent();
-  //
   //1. Sections (curves, points);
   for (i=0; i<aNbFF; ++i) {
     BOPDS_InterfFF& aFF=aFFs(i);
@@ -1159,13 +1203,32 @@ void BOPAlgo_PaveFiller::UpdateFaceInfo
         // Treat existing pave blocks
         if (theDME.IsBound(aPB)) {
           BOPDS_ListOfPaveBlock& aLPB=theDME.ChangeFind(aPB);
-          UpdateExistingPaveBlocks(aPB, aLPB, nF1, nF2);
+          UpdateExistingPaveBlocks(aPB, aLPB, thePBFacesMap);
+
+          BOPDS_ListIteratorOfListOfPaveBlock itLPB(aLPB);
+          for (; itLPB.More(); itLPB.Next())
+          {
+            const Handle(BOPDS_PaveBlock)& aPB = itLPB.Value();
+            const Standard_Integer nE = aPB->Edge();
+            BOPDS_ListOfPaveBlock* pLPBOnE = anEdgeLPB.ChangeSeek(nE);
+            if (!pLPBOnE)
+              pLPBOnE = anEdgeLPB.Bound(nE, BOPDS_ListOfPaveBlock());
+            pLPBOnE->Append(aPB);
+          }
+
           aLPBC.Remove(aItLPB);
           continue;
         }
         //
         aFI1.ChangePaveBlocksSc().Add(aPB);
         aFI2.ChangePaveBlocksSc().Add(aPB);
+        // Add edge-PB connection
+        const Standard_Integer nE = aPB->Edge();
+        BOPDS_ListOfPaveBlock* pLPBOnE = anEdgeLPB.ChangeSeek(nE);
+        if (!pLPBOnE)
+          pLPBOnE = anEdgeLPB.Bound(nE, BOPDS_ListOfPaveBlock());
+        pLPBOnE->Append(aPB);
+
         aItLPB.Next();
       }
     }
@@ -1186,11 +1249,91 @@ void BOPAlgo_PaveFiller::UpdateFaceInfo
     aMF.Add(nF1);
     aMF.Add(nF2);
   }
-  //
-  Standard_Boolean bVerts, bEdges;
-  //
-  bVerts = theDMV.Extent() > 0;
-  bEdges = theDME.Extent() > 0;
+
+  Standard_Boolean bNewCB = Standard_False;
+  {
+    // Unify pave blocks of the existing edges united on the post-treat stage
+    // by making new Common blocks from them
+    NCollection_DataMap<Standard_Integer,
+                        BOPDS_ListOfPaveBlock>::Iterator itDM(anEdgeLPB);
+    for (; itDM.More(); itDM.Next())
+    {
+      const BOPDS_ListOfPaveBlock& aLPB = itDM.Value();
+      if (aLPB.Extent() == 1)
+        continue;
+
+      bNewCB = Standard_True;
+
+      // Find or create common block
+      Handle(BOPDS_CommonBlock) aCB;
+      // Collect all faces attached to common blocks
+      BOPCol_MapOfInteger aMFaces;
+      // Collect all pave blocks attached to common blocks
+      BOPDS_IndexedMapOfPaveBlock aMPaveBlocks;
+
+      BOPDS_ListIteratorOfListOfPaveBlock itLPB(aLPB);
+      for (; itLPB.More(); itLPB.Next())
+      {
+        const Handle(BOPDS_PaveBlock)& aPB = itLPB.Value();
+        aMPaveBlocks.Add(aPB);
+
+        if (myDS->IsCommonBlock(aPB))
+        {
+          Handle(BOPDS_CommonBlock) aPBCB = myDS->CommonBlock(aPB);
+          // Get pave blocks
+          const BOPDS_ListOfPaveBlock& aLPBOnCB = aPBCB->PaveBlocks();
+          for (BOPDS_ListOfPaveBlock::Iterator it(aLPBOnCB); it.More(); it.Next())
+            aMPaveBlocks.Add(it.Value());
+
+          // Get faces
+          const BOPCol_ListOfInteger& aLFacesOnCB = aPBCB->Faces();
+          for (BOPCol_ListOfInteger::Iterator it(aLFacesOnCB); it.More(); it.Next())
+            aMFaces.Add(it.Value());
+
+          if (aCB.IsNull())
+            aCB = aPBCB;
+        }
+      }
+
+      if (aCB.IsNull())
+      {
+        // None of the pave blocks in the list is a common block,
+        // so create the new one.
+        aCB = new BOPDS_CommonBlock;
+        aCB->SetPaveBlocks(aLPB);
+        itLPB.Initialize(aLPB);
+        for (; itLPB.More(); itLPB.Next())
+        {
+          const Handle(BOPDS_PaveBlock)& aPB = itLPB.Value();
+          myDS->SetCommonBlock(aPB, aCB);
+        }
+      }
+      else
+      {
+        // Update common block with new pave blocks
+        BOPDS_ListOfPaveBlock aLPBNew;
+        {
+          const Standard_Integer aNbPB = aMPaveBlocks.Extent();
+          for (Standard_Integer i = 1; i <= aNbPB; ++i)
+          {
+            const Handle(BOPDS_PaveBlock)& aPB = aMPaveBlocks(i);
+            myDS->SetCommonBlock(aPB, aCB);
+            aLPBNew.Append(aPB);
+          }
+        }
+        aCB->SetPaveBlocks(aLPBNew);
+
+        // Update faces of the common block
+        BOPCol_ListOfInteger aLFaces;
+        for (BOPCol_MapOfInteger::Iterator it(aMFaces); it.More(); it.Next())
+          aLFaces.Append(it.Value());
+        aCB->SetFaces(aLFaces);
+      }
+    }
+  }
+
+  Standard_Boolean bVerts = theDMV.Extent() > 0;
+  Standard_Boolean bEdges = theDME.Extent() > 0 || bNewCB;
   //
   if (!bVerts && !bEdges) {
     return;
@@ -1198,7 +1341,7 @@ void BOPAlgo_PaveFiller::UpdateFaceInfo
   //
   // 2. Update Face Info information with new vertices and new
   //    pave blocks created in PostTreatFF from existing ones
-  Standard_Integer nV2, aNbPB;
+  Standard_Integer nV2;
   BOPCol_MapIteratorOfMapOfInteger aItMF;
   BOPCol_DataMapIteratorOfDataMapOfIntegerInteger aItMV;
   //
@@ -1209,54 +1352,57 @@ void BOPAlgo_PaveFiller::UpdateFaceInfo
     BOPDS_FaceInfo& aFI = myDS->ChangeFaceInfo(nF1);
     //
     // 2.1. Update information about vertices
-    if (bVerts) {
+    if (bVerts)
+    {
       BOPCol_MapOfInteger& aMVOn = aFI.ChangeVerticesOn();
       BOPCol_MapOfInteger& aMVIn = aFI.ChangeVerticesIn();
       //
       aItMV.Initialize(theDMV);
-      for (; aItMV.More(); aItMV.Next()) {
+      for (; aItMV.More(); aItMV.Next())
+      {
         nV1 = aItMV.Key();
         nV2 = aItMV.Value();
         //
-        if (aMVOn.Remove(nV1)) {
+        if (aMVOn.Remove(nV1))
           aMVOn.Add(nV2);
-        }
         //
-        if (aMVIn.Remove(nV1)) {
+        if (aMVIn.Remove(nV1))
           aMVIn.Add(nV2);
-        }
       } // for (; aItMV.More(); aItMV.Next()) {
     } // if (bVerts) {
     //
     // 2.2. Update information about pave blocks
-    if (bEdges) {
-      BOPDS_IndexedMapOfPaveBlock& aMPBOn = aFI.ChangePaveBlocksOn();
-      BOPDS_IndexedMapOfPaveBlock& aMPBIn = aFI.ChangePaveBlocksIn();
-      //
-      BOPDS_IndexedMapOfPaveBlock aMPBCopy;
-      for (i = 0; i < 2; ++i) {
-        BOPDS_IndexedMapOfPaveBlock& aMPBOnIn = !i ? aMPBOn : aMPBIn;
-        aMPBCopy = aMPBOnIn;
-        aMPBOnIn.Clear();
-        //
-        aNbPB = aMPBCopy.Extent();
-        for (j = 1; j <= aNbPB; ++j) {
+    if (bEdges)
+    {
+      BOPDS_MapOfPaveBlock aMPBFence;
+      BOPDS_IndexedMapOfPaveBlock* pMPB[] = { &aFI.ChangePaveBlocksOn(),
+                                              &aFI.ChangePaveBlocksIn(),
+                                              &aFI.ChangePaveBlocksSc() };
+      for (i = 0; i < 3; ++i)
+      {
+        BOPDS_IndexedMapOfPaveBlock aMPBCopy = *pMPB[i];
+        pMPB[i]->Clear();
+        const Standard_Integer aNbPB = aMPBCopy.Extent();
+        for (j = 1; j <= aNbPB; ++j)
+        {
           const Handle(BOPDS_PaveBlock)& aPB = aMPBCopy(j);
-          if (theDME.IsBound(aPB)) {
-            const BOPDS_ListOfPaveBlock& aLPB = theDME.Find(aPB);
-            if (aLPB.IsEmpty()) {
-              aMPBOnIn.Add(aPB);
-              continue;
-            }
-            //
-            aItLPB.Initialize(aLPB);
-            for (; aItLPB.More(); aItLPB.Next()) {
+          const BOPDS_ListOfPaveBlock* pLPB = theDME.Seek(aPB);
+          if (pLPB && !pLPB->IsEmpty())
+          {
+            aItLPB.Initialize(*pLPB);
+            for (; aItLPB.More(); aItLPB.Next())
+            {
               const Handle(BOPDS_PaveBlock)& aPB1 = aItLPB.Value();
-              aMPBOnIn.Add(aPB1);
+              const Handle(BOPDS_PaveBlock)& aPBR = myDS->RealPaveBlock(aPB1);
+              if (aMPBFence.Add(aPBR))
+                pMPB[i]->Add(aPBR);
             }
           }
-          else {
-            aMPBOnIn.Add(aPB);
+          else
+          {
+            const Handle(BOPDS_PaveBlock)& aPBR = myDS->RealPaveBlock(aPB);
+            if (aMPBFence.Add(aPBR))
+              pMPB[i]->Add(aPBR);
           }
         } // for (j = 1; j <= aNbPB; ++j) {
       } // for (i = 0; i < 2; ++i) {
@@ -1308,14 +1454,13 @@ Standard_Boolean BOPAlgo_PaveFiller::IsExistingVertex
 Standard_Boolean BOPAlgo_PaveFiller::IsExistingPaveBlock
   (const Handle(BOPDS_PaveBlock)& thePB,
    const BOPDS_Curve& theNC,
-   const BOPCol_ListOfInteger& theLSE)
+   const BOPCol_ListOfInteger& theLSE,
+   Standard_Integer& theNEOut,
+   Standard_Real& theTolNew)
 {
-  Standard_Boolean bRet=Standard_True;
-  //
-  if (theLSE.IsEmpty()) {
-    return !bRet;
-  } 
-  //
+  if (theLSE.IsEmpty())
+    return Standard_False;
+
   Standard_Real aT1, aT2, aTm, aTx, aTolE, aTolCheck, aTol, aDist;
   Standard_Integer nE, iFlag, nV1, nV2;
   gp_Pnt aPm;
@@ -1348,15 +1493,15 @@ Standard_Boolean BOPAlgo_PaveFiller::IsExistingPaveBlock
       aTolE = BRep_Tool::Tolerance(aE);
       aTolCheck = Max(aTolE, aTol) + myFuzzyValue;
       iFlag = myContext->ComputePE(aPm, aTolCheck, aE, aTx, aDist);
-      if (!iFlag) {
-        if (aDist > aTolE)
-          // Update tolerance of the edge
-          UpdateEdgeTolerance(nE, aDist);
-        return bRet;
+      if (!iFlag)
+      {
+        theNEOut = nE;
+        theTolNew = aDist;
+        return Standard_True;
       }
     }
   }
-  return !bRet;
+  return Standard_False;
 }
 
 //=======================================================================
@@ -1401,7 +1546,9 @@ Standard_Boolean BOPAlgo_PaveFiller::IsExistingPaveBlock
   aBoxP2.Add(aP2);
   aBoxP2.Enlarge(aTolV12);
   //
-  theTolNew = 0.;
+  // Look for the existing pave block closest to the section curve
+  theTolNew = ::RealLast();
+
   aNbPB = theMPBOnIn.Extent();
   for (i = 1; i <= aNbPB; ++i) {
     const Handle(BOPDS_PaveBlock)& aPB = theMPBOnIn(i);
@@ -1436,29 +1583,34 @@ Standard_Boolean BOPAlgo_PaveFiller::IsExistingPaveBlock
       aBoxTmp = aBoxPm;
       aBoxTmp.Enlarge(aRealTol);
 
+      Standard_Real aDistToSp = 0.;
       if (aBoxSp.IsOut(aBoxTmp) || myContext->ComputePE(aPm, 
                                                         aRealTol,
                                                         aSp, 
-                                                        aTx, theTolNew)) {
+                                                        aTx, aDistToSp)) {
         continue;
       }
       //
       if (iFlag1 == 1) {
         iFlag1 = !myContext->ComputePE(aP1, aRealTol, aSp, aTx, aDist);
-        if (iFlag1 && theTolNew < aDist)
-          theTolNew = aDist;
+        if (iFlag1 && aDistToSp < aDist)
+          aDistToSp = aDist;
       }
       //
       if (iFlag2 == 1) {
         iFlag2 = !myContext->ComputePE(aP2, aRealTol, aSp, aTx, aDist);
-        if (iFlag2 && theTolNew < aDist)
-          theTolNew = aDist;
+        if (iFlag2 && aDistToSp < aDist)
+          aDistToSp = aDist;
       }
       //
-      if (iFlag1 && iFlag2) {
-        aPBOut = aPB;
-        bRet=Standard_True;
-        break;
+      if (iFlag1 && iFlag2)
+      {
+        if (aDistToSp < theTolNew)
+        {
+          aPBOut = aPB;
+          theTolNew = aDistToSp;
+          bRet = Standard_True;
+        }
       }
     }
   }
@@ -1632,13 +1784,14 @@ void BOPAlgo_PaveFiller::PutPavesOnCurve
 namespace {
   struct PaveBlockDist {
     Handle(BOPDS_PaveBlock) PB;
-    Standard_Real Dist; // square distance from vertex to the paveblock
+    Standard_Real SquareDist; // square distance from vertex to the paveblock
     Standard_Real SinAngle; // sinus of angle between projection vector 
     // and tangent at projection point
     Standard_Real Tolerance; // tolerance of the section curve
   };
 }
-void BOPAlgo_PaveFiller::FilterPavesOnCurves(const BOPDS_VectorOfCurve& theVNC)
+void BOPAlgo_PaveFiller::FilterPavesOnCurves(const BOPDS_VectorOfCurve& theVNC,
+                                             BOPCol_DataMapOfIntegerReal& theMVTol)
 {
   // For each vertex found in ExtPaves of pave blocks of section curves
   // collect list of pave blocks with distance to the curve
@@ -1692,9 +1845,9 @@ void BOPAlgo_PaveFiller::FilterPavesOnCurves(const BOPDS_VectorOfCurve& theVNC)
     for (; itL.More(); itL.Next())
     {
       const PaveBlockDist& aPBD = itL.Value();
-      if (aPBD.Dist < aMinDist)
+      if (aPBD.SquareDist < aMinDist)
       {
-        aMinDist = aPBD.Dist;
+        aMinDist = aPBD.SquareDist;
         aPBMinDist = aPBD.PB;
       }
     }
@@ -1702,13 +1855,32 @@ void BOPAlgo_PaveFiller::FilterPavesOnCurves(const BOPDS_VectorOfCurve& theVNC)
     // and there are other pave blocks for which the distance is less than the current.
     // Do not remove a vertex if it is projected on the curve with quite large angle
     // (see test bugs modalg_6 bug27761).
+
+    // Reduce tolerance for the vertex to the value of maximal distance to
+    // to section curve on which it will be kept.
+    Standard_Real aMaxDistKept = -1;
+    Standard_Boolean isRemoved = Standard_False;
     for (itL.Init(aList); itL.More(); itL.Next())
     {
       const PaveBlockDist& aPBD = itL.Value();
       Standard_Real aCheckDist = 100. * Max(aPBD.Tolerance*aPBD.Tolerance, aMinDist);
-      if (aPBD.Dist > aCheckDist && aPBD.SinAngle < aSinAngleMin)
+      if (aPBD.SquareDist > aCheckDist && aPBD.SinAngle < aSinAngleMin)
       {
         aPBD.PB->RemoveExtPave(nV);
+        isRemoved = Standard_True;
+      }
+      else if (aPBD.SquareDist > aMaxDistKept)
+        aMaxDistKept = aPBD.SquareDist;
+    }
+
+    if (isRemoved && aMaxDistKept > 0)
+    {
+      const Standard_Real* pTol = theMVTol.Seek(nV);
+      if (pTol)
+      {
+        const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&myDS->Shape(nV);
+        const Standard_Real aRealTol = Max(*pTol, sqrt(aMaxDistKept) + Precision::Confusion());
+        (*(Handle(BRep_TVertex)*)&aV.TShape())->Tolerance(aRealTol);
       }
     }
   }
@@ -2112,9 +2284,17 @@ void BOPAlgo_PaveFiller::PutPaveOnCurve
   Standard_Real aTolV = (aMVTol.IsBound(nV) ? aMVTol(nV) : BRep_Tool::Tolerance(aV));
 
   bIsVertexOnLine = myContext->IsVertexOnLine(aV, aTolV, aIC, aTolR3D + myFuzzyValue, aT);
-  if (!bIsVertexOnLine && iCheckExtend) {
-    ExtendedTolerance(nV, aMI, aTolV, iCheckExtend);
-    bIsVertexOnLine = myContext->IsVertexOnLine(aV, aTolV, aIC, aTolR3D + myFuzzyValue, aT);
+  if (!bIsVertexOnLine && iCheckExtend && !myVertsToAvoidExtension.Contains(nV))
+  {
+    Standard_Real anExtraTol;
+    ExtendedTolerance(nV, aMI, anExtraTol, iCheckExtend);
+    bIsVertexOnLine = myContext->IsVertexOnLine(aV, anExtraTol, aIC, aTolR3D + myFuzzyValue, aT);
+    if (bIsVertexOnLine)
+    {
+      gp_Pnt aPOnC;
+      aIC.D0(aT, aPOnC);
+      aTolV = aPOnC.Distance(BRep_Tool::Pnt(aV));
+    }
   }
   //
   if (bIsVertexOnLine) {
@@ -2190,10 +2370,13 @@ void BOPAlgo_PaveFiller::PutPaveOnCurve
 //=======================================================================
 void BOPAlgo_PaveFiller::ProcessExistingPaveBlocks
     (const Standard_Integer theInt,
+     const Standard_Integer nF1,
+     const Standard_Integer nF2,
      const BOPDS_IndexedMapOfPaveBlock& aMPBOnIn,
      const BOPCol_DataMapOfIntegerListOfInteger& aDMBV,
      BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& aMSCPB,
      BOPCol_DataMapOfShapeInteger& aMVI,
+     BOPAlgo_DataMapOfPaveBlockListOfInteger& thePBFacesMap,
      BOPDS_MapOfPaveBlock& aMPB)
 {
   if (aDMBV.IsEmpty()) {
@@ -2209,6 +2392,9 @@ void BOPAlgo_PaveFiller::ProcessExistingPaveBlocks
   BOPDS_InterfFF& aFF = aFFs(theInt);
   BOPDS_VectorOfCurve& aVC = aFF.ChangeCurves();
   //
+  const BOPDS_FaceInfo& aFI1 = myDS->FaceInfo(nF1);
+  const BOPDS_FaceInfo& aFI2 = myDS->FaceInfo(nF2);
+  //
   aNbPB = aMPBOnIn.Extent();
   //
   aItBV.Initialize(aDMBV);
@@ -2256,6 +2442,23 @@ void BOPAlgo_PaveFiller::ProcessExistingPaveBlocks
         if (!iFlag) {
           aMPB.Add(aPB);
           PreparePostTreatFF(theInt, iC, aPB, aMSCPB, aMVI, aLPBC);
+
+          // Add faces to PB
+          Standard_Boolean bInF1 = (aFI1.PaveBlocksOn().Contains(aPB) ||
+                                    aFI1.PaveBlocksIn().Contains(aPB));
+          Standard_Boolean bInF2 = (aFI2.PaveBlocksOn().Contains(aPB) ||
+                                    aFI2.PaveBlocksIn().Contains(aPB));
+          if (!bInF1 || !bInF2)
+          {
+            // Face without pave block
+            const Standard_Integer nF = bInF1 ? nF2 : nF1;
+            BOPCol_ListOfInteger* pFaces = thePBFacesMap.ChangeSeek(aPB);
+            if (!pFaces)
+              pFaces = thePBFacesMap.Bound(aPB, BOPCol_ListOfInteger());
+            // List is expected to be short, so we allow the check here
+            if (pFaces->IsEmpty() || !pFaces->Contains(nF))
+              pFaces->Append(nF);
+          }
         }
       }
     }
@@ -2268,8 +2471,7 @@ void BOPAlgo_PaveFiller::ProcessExistingPaveBlocks
 void BOPAlgo_PaveFiller::UpdateExistingPaveBlocks
   (const Handle(BOPDS_PaveBlock)& aPBf,
    BOPDS_ListOfPaveBlock& aLPB,
-   const Standard_Integer nF1,
-   const Standard_Integer nF2) 
+   const BOPAlgo_DataMapOfPaveBlockListOfInteger& thePBFacesMap)
 {
   if (!aLPB.Extent()) {
     return;
@@ -2281,14 +2483,6 @@ void BOPAlgo_PaveFiller::UpdateExistingPaveBlocks
   Handle(BOPDS_CommonBlock) aCB;
   BOPDS_ListIteratorOfListOfPaveBlock aIt, aIt1, aIt2;
   //
-  BOPDS_FaceInfo& aFI1 = myDS->ChangeFaceInfo(nF1);
-  BOPDS_FaceInfo& aFI2 = myDS->ChangeFaceInfo(nF2);
-  //
-  BOPDS_IndexedMapOfPaveBlock& aMPBOn1 = aFI1.ChangePaveBlocksOn();
-  BOPDS_IndexedMapOfPaveBlock& aMPBIn1 = aFI1.ChangePaveBlocksIn();
-  BOPDS_IndexedMapOfPaveBlock& aMPBOn2 = aFI2.ChangePaveBlocksOn();
-  BOPDS_IndexedMapOfPaveBlock& aMPBIn2 = aFI2.ChangePaveBlocksIn();
-  //
   // 1. Remove old pave blocks
   const Handle(BOPDS_CommonBlock)& aCB1 = myDS->CommonBlock(aPBf);
   bCB = !aCB1.IsNull();
@@ -2398,7 +2592,7 @@ void BOPAlgo_PaveFiller::UpdateExistingPaveBlocks
     }
     //
     aLPB = aLPBNew;
-  } 
+  }
   else {
     nE = aPBf->OriginalEdge();
     BOPDS_ListOfPaveBlock& aLPBE = myDS->ChangePaveBlocks(nE);
@@ -2408,56 +2602,53 @@ void BOPAlgo_PaveFiller::UpdateExistingPaveBlocks
       aLPBE.Append(aPB);
     }
   }
-  //
-  Standard_Boolean bIn1, bIn2;
-  //
-  bIn1 = aMPBOn1.Contains(aPBf) || aMPBIn1.Contains(aPBf);
-  bIn2 = aMPBOn2.Contains(aPBf) || aMPBIn2.Contains(aPBf);
-  //
-  if (bIn1 && bIn2) {
+
+  // Try to project the edge on the faces
+  const BOPCol_ListOfInteger* pLFaces = thePBFacesMap.Seek(aPBf);
+  if (!pLFaces)
     return;
-  }
-  //
-  // 3. Check new pave blocks for coincidence 
-  //    with the opposite face.
-  //    In case of coincidence create common blocks
-  Standard_Integer nF;
-  //
-  nF = bIn1 ? nF2 : nF1;
-  const TopoDS_Face& aF = *(TopoDS_Face*)&myDS->Shape(nF);
-  BOPDS_IndexedMapOfPaveBlock& aMPBIn = bIn1 ? aMPBIn2 : aMPBIn1;
-  //
-  aIt.Initialize(aLPB);
-  for (; aIt.More(); aIt.Next()) {
-    Handle(BOPDS_PaveBlock)& aPBChangeValue = aIt.ChangeValue();
-    const TopoDS_Edge& aE = *(TopoDS_Edge*)&myDS->Shape(aPBChangeValue->Edge());
-    //
-    IntTools_EdgeFace anEF;
-    anEF.SetEdge(aE);
-    anEF.SetFace(aF);
-    anEF.SetFuzzyValue(myFuzzyValue);
-    anEF.SetRange(aPBChangeValue->Pave1().Parameter(), aPBChangeValue->Pave2().Parameter());
-    anEF.SetContext(myContext);
-    anEF.Perform();
-    //
-    const IntTools_SequenceOfCommonPrts& aCPrts=anEF.CommonParts();
-    if (aCPrts.Length() == 1) {
-      Standard_Boolean bCoinc = (aCPrts(1).Type() == TopAbs_EDGE);
-      if (bCoinc) {
-        if (bCB) {
-          aCB = myDS->CommonBlock(aPBChangeValue);
-        } else {
+  BOPCol_ListIteratorOfListOfInteger itLF(*pLFaces);
+  for (; itLF.More(); itLF.Next())
+  {
+    const Standard_Integer nF = itLF.Value();
+    BOPDS_FaceInfo& aFI = myDS->ChangeFaceInfo(nF);
+    const TopoDS_Face& aF = TopoDS::Face(myDS->Shape(nF));
+
+    aIt.Initialize(aLPB);
+    for (; aIt.More(); aIt.Next())
+    {
+      aPB = aIt.ChangeValue();
+      if (aFI.PaveBlocksOn().Contains(aPB) || aFI.PaveBlocksIn().Contains(aPB))
+        continue;
+
+      const TopoDS_Edge& aE = *(TopoDS_Edge*)&myDS->Shape(aPB->Edge());
+      //
+      IntTools_EdgeFace anEF;
+      anEF.SetEdge(aE);
+      anEF.SetFace(aF);
+      anEF.SetFuzzyValue(myFuzzyValue);
+      anEF.SetRange(aPB->Pave1().Parameter(), aPB->Pave2().Parameter());
+      anEF.SetContext(myContext);
+      anEF.Perform();
+      //
+      const IntTools_SequenceOfCommonPrts& aCPrts = anEF.CommonParts();
+      Standard_Boolean bCoincide = (aCPrts.Length() == 1 && aCPrts(1).Type() == TopAbs_EDGE);
+      if (bCoincide)
+      {
+        aCB = myDS->CommonBlock(aPB);
+        if (aCB.IsNull())
+        {
           aCB = new BOPDS_CommonBlock;
-          aCB->AddPaveBlock(aPBChangeValue);
-          myDS->SetCommonBlock(aPBChangeValue, aCB);
+          aCB->AddPaveBlock(aPB);
+          myDS->SetCommonBlock(aPB, aCB);
         }
         aCB->AddFace(nF);
-        //
-        aMPBIn.Add(aPBChangeValue);
+        aFI.ChangePaveBlocksIn().Add(aPB);
       }
     }
   }
 }
+
 //=======================================================================
 // function: PutClosingPaveOnCurve
 // purpose:
@@ -2667,26 +2858,60 @@ void BOPAlgo_PaveFiller::UpdatePaveBlocks
       bRebuild = Standard_False;
       aPB->Indices(nV[0], nV[1]);
       aPB->Range(aT[0], aT[1]);
+
+      Standard_Integer nE = aPB->OriginalEdge();
+      if (nE < 0)
+        // new edge
+        nE = aPB->Edge();
+
       // remember the fact if the edge had different vertices before substitution
       Standard_Boolean wasRegularEdge = (nV[0] != nV[1]);
+
+      const TopoDS_Edge& aE = TopoDS::Edge(myDS->Shape(nE));
+      TopoDS_Vertex aVE1, aVE2;
+      TopExp::Vertices(aE, aVE1, aVE2);
+      Standard_Boolean isClosedE = !aVE1.IsNull() && !aVE2.IsNull() && aVE1.IsSame(aVE2);
+      Standard_Boolean isDegEdge = myDS->ShapeInfo(nE).HasFlag();
       //
+      BOPDS_Pave aPave[2] = {aPB->Pave1(), aPB->Pave2()};
+
       for (j = 0; j < 2; ++j) {
         if (aDMNewSD.IsBound(nV[j])) {
-          BOPDS_Pave aPave;
           //
           nV[j] = aDMNewSD.Find(nV[j]);
-          aPave.SetIndex(nV[j]);
-          aPave.SetParameter(aT[j]);
+          // recompute the parameter
+          if (!isDegEdge)
+          {
+            const TopoDS_Vertex& aV = TopoDS::Vertex(myDS->Shape(nV[j]));
+            if (!isClosedE ||
+                BRep_Tool::Pnt(aV).Distance(BRep_Tool::Pnt(aVE1)) > BRep_Tool::Tolerance(aV) + myFuzzyValue)
+            {
+              Standard_Real aDummy, aTnew;
+              Standard_Integer iErr = myContext->ComputeVE(aV, aE, aTnew, aDummy, myFuzzyValue);
+              if (!iErr)
+                aT[j] = aTnew;
+            }
+            else
+            {
+              // choose the correct boundary parameter
+              Standard_Real f, l;
+              BRep_Tool::Range(aE, f, l);
+              aT[j] = Abs(aT[j] - f) < Abs(aT[j] - l) ? f : l;
+            }
+          }
+          aPave[j].SetIndex(nV[j]);
           //
           bRebuild = Standard_True;
-          if (!j) {
-            aPB->SetPave1(aPave);
-          }
-          else {
-            aPB->SetPave2(aPave);
-          }
         }
       }
+      if (aT[0] < aT[1])
+      {
+        aPave[0].SetParameter(aT[0]);
+        aPave[1].SetParameter(aT[1]);
+      }
+
+      aPB->SetPave1(aPave[0]);
+      aPB->SetPave2(aPave[1]);
       //
       if (bRebuild) {
         Standard_Integer nE = aPB->Edge();
@@ -2695,7 +2920,6 @@ void BOPAlgo_PaveFiller::UpdatePaveBlocks
           // untouched edge
           nE = aPB->OriginalEdge();
         }
-        Standard_Boolean isDegEdge = myDS->ShapeInfo(nE).HasFlag();
         if (wasRegularEdge && !isDegEdge && nV[0] == nV[1]) {
           // now edge has the same vertex on both ends;
           // check if it is not a regular closed curve.
@@ -2709,6 +2933,7 @@ void BOPAlgo_PaveFiller::UpdatePaveBlocks
             continue;
           }
         }
+        aPB->Range(aT[0], aT[1]);
         nSp = SplitEdge(nE, nV[0], aT[0], nV[1], aT[1]);
         if (bCB)
           aCB->SetEdge(nSp);
@@ -3056,6 +3281,8 @@ void BOPAlgo_PaveFiller::CorrectToleranceOfSE()
           else if (aTolE > *aMaxTol) {
             *aMaxTol = aTolE;
           }
+          BOPDS_ListOfPaveBlock& aPBList = aMVIPBs.ChangeFromKey(nV[j]);
+          aPBList.Append(aPB);
         }
       }
     }
@@ -3125,107 +3352,100 @@ void BOPAlgo_PaveFiller::PutSEInOtherFaces()
 {
   // Try to intersect each section edge with the faces
   // not participated in its creation
-  //
-  // 1. Get all section edges
+
+  // Get all section edges
   BOPDS_IndexedMapOfPaveBlock aMPBScAll;
-  //
+
   BOPDS_VectorOfInterfFF& aFFs = myDS->InterfFF();
-  Standard_Integer i, j, aNbFF = aFFs.Extent();
-  //
-  for (i = 0; i < aNbFF; ++i) {
+  const Standard_Integer aNbFF = aFFs.Extent();
+  for (Standard_Integer i = 0; i < aNbFF; ++i)
+  {
     const BOPDS_VectorOfCurve& aVNC = aFFs(i).Curves();
-    Standard_Integer aNbC = aVNC.Extent();
-    for (j = 0; j < aNbC; ++j) {
+    const Standard_Integer aNbC = aVNC.Extent();
+    for (Standard_Integer j = 0; j < aNbC; ++j)
+    {
       const BOPDS_ListOfPaveBlock& aLPBC = aVNC(j).PaveBlocks();
       BOPDS_ListIteratorOfListOfPaveBlock aItPB(aLPBC);
-      for (; aItPB.More(); aItPB.Next()) {
+      for (; aItPB.More(); aItPB.Next())
         aMPBScAll.Add(aItPB.Value());
-      }
     }
   }
-  //
-  Standard_Integer aNbPBSc = aMPBScAll.Extent();
-  //
-  // 2. Loop for all faces and check each section curve
-  Standard_Integer aNbS = myDS->NbSourceShapes();
-  for (i = 0; i < aNbS; ++i) {
-    const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
-    if (aSI.ShapeType() != TopAbs_FACE) {
+  // Perform intersection of collected pave blocks
+  ForceInterfEF(aMPBScAll, Standard_False);
+}
+
+//=======================================================================
+//function : RemoveMicroSectionEdges
+//purpose  : 
+//=======================================================================
+void BOPAlgo_PaveFiller::RemoveMicroSectionEdges
+  (BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMSCPB,
+   BOPDS_IndexedMapOfPaveBlock& theMicroPB)
+{
+  if (theMSCPB.IsEmpty())
+    // no section edges
+    return;
+
+  // Get all F/F interferences
+  BOPDS_VectorOfInterfFF& aFFs = myDS->InterfFF();
+
+  // Build the new map of section edges avoiding the micro edges
+  BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks aSEPBMap;
+  // Analyze all section edges
+  Standard_Integer aNbCPB = theMSCPB.Extent();
+  for (Standard_Integer i = 1; i <= aNbCPB; ++i)
+  {
+    const TopoDS_Shape& aSI = theMSCPB.FindKey(i);
+    const BOPDS_CoupleOfPaveBlocks& aCPB = theMSCPB(i);
+
+    if (aSI.ShapeType() != TopAbs_EDGE)
+    {
+      // Not an edge
+      aSEPBMap.Add(aSI, aCPB);
       continue;
     }
-    //
-    const TopoDS_Face& aF = (*(TopoDS_Face*)(&aSI.Shape()));
-    BOPDS_FaceInfo& aFI = myDS->ChangeFaceInfo(i);
-    //
-    // IN edges to add new ones
-    BOPDS_IndexedMapOfPaveBlock& aMFPBIn = aFI.ChangePaveBlocksIn();
-    // Section edges to check the participation of the face
-    const BOPDS_IndexedMapOfPaveBlock& aMFPBSc = aFI.PaveBlocksSc();
-    //
-    // Get vertices of the face to check that vertices of the
-    // processed section edge belong to the face
-    BOPCol_MapOfInteger aMFVerts;
-    // Get vertices from ON, IN and Sc pave blocks of the face
-    for (j = 0; j < 3; ++j) {
-      const BOPDS_IndexedMapOfPaveBlock& aMPB =
-        !j ? aFI.PaveBlocksOn() : (j == 1 ? aMFPBIn : aMFPBSc);
-      Standard_Integer aNbPB = aMPB.Extent();
-      for (Standard_Integer k = 1; k <= aNbPB; ++k) {
-        const Handle(BOPDS_PaveBlock)& aPB = aMPB(k);
-        aMFVerts.Add(aPB->Pave1().Index());
-        aMFVerts.Add(aPB->Pave2().Index());
-      }
-    }
-    // Add ON, IN and Sc vertices of the face
-    for (j = 0; j < 3; ++j) {
-      const BOPCol_MapOfInteger& aMFV = !j ? aFI.VerticesOn() :
-        (j == 1 ? aFI.VerticesIn() : aFI.VerticesSc());
-      BOPCol_MapIteratorOfMapOfInteger aItMI(aMFV);
-      for (; aItMI.More(); aItMI.Next()) {
-        aMFVerts.Add(aItMI.Value());
-      }
+
+    // Get pave block for analysis
+    const Handle(BOPDS_PaveBlock)& aPB = aCPB.PaveBlock1();
+    if (aPB->HasEdge())
+    {
+      // Not a real section edge
+      aSEPBMap.Add(aSI, aCPB);
+      continue;
     }
-    //
-    // Check each section edge for possible belonging to the face
-    for (j = 1; j <= aNbPBSc; ++j) {
-      const Handle(BOPDS_PaveBlock)& aPB = aMPBScAll(j);
-      if (aMFPBSc.Contains(aPB)) {
-        continue;
-      }
-      //
-      // Both vertices of the section edge should belong to the face
-      if (!aMFVerts.Contains(aPB->Pave1().Index()) ||
-        !aMFVerts.Contains(aPB->Pave2().Index())) {
-        continue;
-      }
-      //
-      // Perform intersection
-      const TopoDS_Edge& aE = TopoDS::Edge(myDS->Shape(aPB->Edge()));
-      //
-      IntTools_EdgeFace anEFInt;
-      anEFInt.SetEdge(aE);
-      anEFInt.SetFace(aF);
-      anEFInt.SetFuzzyValue(myFuzzyValue);
-      anEFInt.SetRange(aPB->Pave1().Parameter(), aPB->Pave2().Parameter());
-      anEFInt.SetContext(myContext);
-      anEFInt.UseQuickCoincidenceCheck(Standard_True);
-      anEFInt.Perform();
-      //
-      const IntTools_SequenceOfCommonPrts& aCPrts = anEFInt.CommonParts();
-      if ((aCPrts.Length() == 1) && (aCPrts(1).Type() == TopAbs_EDGE)) {
-        Handle(BOPDS_CommonBlock) aCB;
-        if (myDS->IsCommonBlock(aPB)) {
-          aCB = myDS->CommonBlock(aPB);
-        }
-        else {
-          aCB = new BOPDS_CommonBlock;
-          aCB->AddPaveBlock(aPB);
-        }
-        //
-        aCB->AddFace(i);
-        //
-        aMFPBIn.Add(aPB);
+
+    if (!BOPTools_AlgoTools::IsMicroEdge(TopoDS::Edge(aSI), myContext, Standard_False))
+    {
+      // Normal edge
+      aSEPBMap.Add(aSI, aCPB);
+      continue;
+    }
+
+    // Micro edge is found, avoid it in the <theMSCPB> map
+    // and remove from the F/F Intersection info structure
+
+    // Get F/F interference which created this micro edge
+    BOPDS_InterfFF& aFF = aFFs(aCPB.IndexInterf());
+    // Get curve from which this edge has been created
+    BOPDS_Curve& aCurve = aFF.ChangeCurves().ChangeValue(aCPB.Index());
+    // Get all section pave blocks created from this curve
+    BOPDS_ListOfPaveBlock& aLPBC = aCurve.ChangePaveBlocks();
+    // Remove pave block from the list
+    for (BOPDS_ListIteratorOfListOfPaveBlock it(aLPBC); it.More(); it.Next())
+    {
+      if (it.Value() == aPB)
+      {
+        aLPBC.Remove(it);
+        break;
       }
     }
+
+    // Add the pave block of "micro" edge into outgoing map for
+    // unification of its vertices in the PostTreatFF method
+    theMicroPB.Add(aPB);
   }
+
+  // Overwrite the old map if necessary
+  if (aSEPBMap.Extent() != theMSCPB.Extent())
+    theMSCPB = aSEPBMap;
 }
index 7ca8499ee7331770c09b3a04e5b6a6ebdf0de0d5..0a5b42a18898127a409dab29bc29350db10fc467 100644 (file)
@@ -478,7 +478,7 @@ void BOPAlgo_PaveFiller::MakeSplitEdges()
                 aCB->SetEdge(nE);
                 // Compute tolerance of the common block and update the edge
                 Standard_Real aTol = BOPAlgo_Tools::ComputeToleranceOfCB(aCB, myDS, myContext);
-                myDS->UpdateEdgeTolerance(nE, aTol);
+                UpdateEdgeTolerance(nE, aTol);
               }
             }
             else if (aLPB.Extent() == 1)
@@ -527,10 +527,6 @@ void BOPAlgo_PaveFiller::MakeSplitEdges()
   BOPAlgo_SplitEdgeCnt::Perform(myRunParallel, aVBSE, myContext);
   //======================================================
   //
-  BOPDS_ShapeInfo aSI;
-  //
-  aSI.SetShapeType(TopAbs_EDGE);
-  //
   for (k=0; k < aNbVBSE; ++k) {
     BOPAlgo_SplitEdge& aBSE=aVBSE(k);
     //
@@ -540,13 +536,18 @@ void BOPAlgo_PaveFiller::MakeSplitEdges()
     Handle(BOPDS_PaveBlock) aPBk=aBSE.PaveBlock();
     Handle(BOPDS_CommonBlock)& aCBk=aBSE.CommonBlock();
     //
+    BOPDS_ShapeInfo aSI;
+    aSI.SetShapeType(TopAbs_EDGE);
     aSI.SetShape(aSp);
     aSI.ChangeBox()=aBox;
+    BOPCol_ListOfInteger& aSubShapes = aSI.ChangeSubShapes();
+    aSubShapes.Append(aPBk->Pave1().Index());
+    aSubShapes.Append(aPBk->Pave2().Index());
     //
     nSp=myDS->Append(aSI);
     //
     if (!aCBk.IsNull()) {
-      myDS->UpdateEdgeTolerance(nSp, aBSE.Tolerance());
+      UpdateEdgeTolerance(nSp, aBSE.Tolerance());
       aCBk->SetEdge(nSp);
     }
     else {
@@ -644,54 +645,53 @@ void BOPAlgo_PaveFiller::MakePCurves()
         continue;
       }
       //
-      Handle(BOPDS_CommonBlock) aCB=myDS->CommonBlock(aPB);
-      if (aCB.IsNull()) {
-        continue;
-      }
-      //
-      const BOPDS_ListOfPaveBlock& aLPB=aCB->PaveBlocks();
-      if (aLPB.Extent()<2) {
-        continue;
-      }
-      //
-      BOPAlgo_MPC& aMPC=aVMPC.Append1();
-      //
-      aItLPB.Initialize(aLPB);
-      for(; aItLPB.More(); aItLPB.Next()) {
-        const Handle(BOPDS_PaveBlock)& aPBx=aItLPB.Value();
-        if (aPBx==aPB) {
-          continue;
-        }
-        //
-        nEx=aPBx->OriginalEdge();
-        const TopoDS_Edge& aEx=(*(TopoDS_Edge *)(&myDS->Shape(nEx))); 
-        bHasPC=BOPTools_AlgoTools2D::HasCurveOnSurface (aEx, aF1F);
-        if (!bHasPC) {
-          continue;
+      BOPAlgo_MPC& aMPC = aVMPC.Append1();
+
+      Handle(BOPDS_CommonBlock) aCB = myDS->CommonBlock(aPB);
+
+      if (!aCB.IsNull())
+      {
+        const BOPDS_ListOfPaveBlock& aLPB = aCB->PaveBlocks();
+        if (aLPB.Extent() >= 2)
+        {
+          aItLPB.Initialize(aLPB);
+          for(; aItLPB.More(); aItLPB.Next()) {
+            const Handle(BOPDS_PaveBlock)& aPBx=aItLPB.Value();
+            if (aPBx==aPB) {
+              continue;
+            }
+            //
+            nEx=aPBx->OriginalEdge();
+            const TopoDS_Edge& aEx=(*(TopoDS_Edge *)(&myDS->Shape(nEx))); 
+            bHasPC=BOPTools_AlgoTools2D::HasCurveOnSurface (aEx, aF1F);
+            if (!bHasPC) {
+              continue;
+            }
+            //
+            Standard_Integer nV1x, nV2x;
+            Standard_Real aT1x, aT2x;
+            TopoDS_Vertex aV1x, aV2x;
+            TopoDS_Edge aEz;
+            //
+            aEz=aEx;
+            aEz.Orientation(TopAbs_FORWARD);
+            //
+            aPBx->Indices(nV1x, nV2x);
+            aPBx->Range(aT1x, aT2x);
+            //
+            aV1x=(*(TopoDS_Vertex *)(&myDS->Shape(nV1x)));
+            aV1x.Orientation(TopAbs_FORWARD); 
+            //
+            aV2x=(*(TopoDS_Vertex *)(&myDS->Shape(nV2x)));
+            aV2x.Orientation(TopAbs_REVERSED); 
+            //
+            aMPC.SetData(aEz, aV1x, aT1x, aV2x, aT2x);
+            //
+            break;
+          }
         }
-        //
-        Standard_Integer nV1x, nV2x;
-        Standard_Real aT1x, aT2x;
-        TopoDS_Vertex aV1x, aV2x;
-        TopoDS_Edge aEz;
-        //
-        aEz=aEx;
-        aEz.Orientation(TopAbs_FORWARD);
-        //
-        aPBx->Indices(nV1x, nV2x);
-        aPBx->Range(aT1x, aT2x);
-        //
-        aV1x=(*(TopoDS_Vertex *)(&myDS->Shape(nV1x)));
-        aV1x.Orientation(TopAbs_FORWARD); 
-        //
-        aV2x=(*(TopoDS_Vertex *)(&myDS->Shape(nV2x)));
-        aV2x.Orientation(TopAbs_REVERSED); 
-        //
-        aMPC.SetData(aEz, aV1x, aT1x, aV2x, aT2x);
-        //
-        break;
       }
-      //
+
       aMPC.SetEdge(aE);
       aMPC.SetFace(aF1F);
       aMPC.SetProgressIndicator(myProgressIndicator);
index 38de815795fb5d9cd240a74c09dd4797dab60424..03b117ff070d9b59b8ed40b7b5c1078ffe37fa0b 100644 (file)
@@ -126,7 +126,8 @@ void BOPAlgo_Tools::FillMap(const Handle(BOPDS_PaveBlock)& aPB,
 //=======================================================================
 void BOPAlgo_Tools::PerformCommonBlocks(BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock& aMPBLPB,
                                         const Handle(NCollection_BaseAllocator)& aAllocator,
-                                        BOPDS_PDS& pDS)
+                                        BOPDS_PDS& pDS,
+                                        const Handle(IntTools_Context)& theContext)
 {
   Standard_Integer aNbCB;
   //
@@ -185,6 +186,10 @@ void BOPAlgo_Tools::PerformCommonBlocks(BOPDS_IndexedDataMapOfPaveBlockListOfPav
     aCB->SetFaces(aLFaces);
     for (aItLPB.Initialize(aLPB); aItLPB.More(); aItLPB.Next())
       pDS->SetCommonBlock(aItLPB.Value(), aCB);
+
+    // Compute tolerance for Common Block
+    Standard_Real aTolCB = BOPAlgo_Tools::ComputeToleranceOfCB(aCB, pDS, theContext);
+    aCB->SetTolerance(aTolCB);
   }
 }
 //=======================================================================
@@ -193,7 +198,8 @@ void BOPAlgo_Tools::PerformCommonBlocks(BOPDS_IndexedDataMapOfPaveBlockListOfPav
 //=======================================================================
 void BOPAlgo_Tools::PerformCommonBlocks(const BOPDS_IndexedDataMapOfPaveBlockListOfInteger& aMPBLI,
                                         const Handle(NCollection_BaseAllocator)& ,//aAllocator
-                                        BOPDS_PDS& pDS)
+                                        BOPDS_PDS& pDS,
+                                        const Handle(IntTools_Context)& theContext)
 {
   Standard_Integer nF, i, aNb;
   BOPCol_ListIteratorOfListOfInteger aItLI;
@@ -230,6 +236,9 @@ void BOPAlgo_Tools::PerformCommonBlocks(const BOPDS_IndexedDataMapOfPaveBlockLis
     }
     aCB->AppendFaces(aNewFaces);
     pDS->SetCommonBlock(aPB, aCB);
+    // Compute tolerance for Common Block
+    Standard_Real aTolCB = BOPAlgo_Tools::ComputeToleranceOfCB(aCB, pDS, theContext);
+    aCB->SetTolerance(aTolCB);
   }
 }
 //=======================================================================
@@ -267,6 +276,10 @@ Standard_Real BOPAlgo_Tools::ComputeToleranceOfCB
   aPBR->Range(aT1, aT2);
   aDt = (aT2 - aT1) / (aNbPnt + 1);
   //
+  Handle(IntTools_Context) aCtx = theContext;
+  if (aCtx.IsNull())
+    aCtx = new IntTools_Context();
+
   // compute max tolerance for common blocks on edges
   if (aLPB.Extent() > 1) {
     // compute max distance between edges
@@ -284,7 +297,7 @@ Standard_Real BOPAlgo_Tools::ComputeToleranceOfCB
       const TopoDS_Edge& aE = *(TopoDS_Edge*)&theDS->Shape(nE);
       aTol = BRep_Tool::Tolerance(aE);
       //
-      aProjPC = theContext->ProjPC(aE);
+      aProjPC = aCtx->ProjPC(aE);
       //
       aT = aT1;
       for (Standard_Integer i=1; i <= aNbPnt; i++) {
@@ -313,7 +326,7 @@ Standard_Real BOPAlgo_Tools::ComputeToleranceOfCB
       const TopoDS_Face& aF = *(TopoDS_Face*)&theDS->Shape(nF);
       aTol = BRep_Tool::Tolerance(aF);
       //
-      aProjPS = theContext->ProjPS(aF);
+      aProjPS = aCtx->ProjPS(aF);
       //
       aT = aT1;
       for (Standard_Integer i=1; i <= aNbPnt; i++) {
index b310ab62f3b327063ef6d8deb177021fa61ce6da..06a822d0aec570ed39590993448214642a30f1ac 100644 (file)
@@ -100,14 +100,19 @@ public:
                                       const Standard_Integer theF,
                                       BOPDS_IndexedDataMapOfPaveBlockListOfInteger& theMILI,
                                       const BOPCol_BaseAllocator& theAllocator);
-  
+
+  //! Create Common Blocks from the groups of pave blocks of <theMBlocks>
+  //! connection map.
   Standard_EXPORT static void PerformCommonBlocks(BOPDS_IndexedDataMapOfPaveBlockListOfPaveBlock& theMBlocks,
                                                   const BOPCol_BaseAllocator& theAllocator,
-                                                  BOPDS_PDS& theDS);
+                                                  BOPDS_PDS& theDS,
+                                                  const Handle(IntTools_Context)& theContext = Handle(IntTools_Context)());
 
+  //! Create Common Blocks on faces using the PB->Faces connection map <theMBlocks>.
   Standard_EXPORT static void PerformCommonBlocks(const BOPDS_IndexedDataMapOfPaveBlockListOfInteger& theMBlocks,
                                                   const BOPCol_BaseAllocator& theAllocator,
-                                                  BOPDS_PDS& pDS);
+                                                  BOPDS_PDS& pDS,
+                                                  const Handle(IntTools_Context)& theContext = Handle(IntTools_Context)());
 
   Standard_EXPORT static Standard_Real ComputeToleranceOfCB
                                         (const Handle(BOPDS_CommonBlock)& theCB,
index 394bb37c329b220ac19523bde14eb709ca777ed3..1098e139abc48d28fcaaa3f08dd965d7c2c682af 100644 (file)
@@ -18,7 +18,7 @@
 #ifndef NMTDS_BoxBndTree_HeaderFile
 #define NMTDS_BoxBndTree_HeaderFile
 
-#include <NCollection_UBTree.hxx>
+#include <NCollection_EBTree.hxx>
 #include <Bnd_Box.hxx>
 #include <BOPCol_ListOfInteger.hxx>
 /**
@@ -26,7 +26,7 @@
  * of overlapped bounding boxes.
  *
 */
-typedef NCollection_UBTree <Standard_Integer , Bnd_Box> BOPCol_BoxBndTree;
+typedef NCollection_EBTree <Standard_Integer , Bnd_Box> BOPCol_BoxBndTree;
 
   class BOPCol_BoxBndTreeSelector : public BOPCol_BoxBndTree::Selector {
     public:
index 71c7eab9c62d58ea43d697aaec9deed156d108a6..ed57f6dfad857cbf93fea719ff7e6be35d227b1a 100644 (file)
@@ -23,7 +23,9 @@ IMPLEMENT_STANDARD_RTTIEXT(BOPDS_CommonBlock,Standard_Transient)
 // function:  
 // purpose: 
 //=======================================================================
-  BOPDS_CommonBlock::BOPDS_CommonBlock()
+BOPDS_CommonBlock::BOPDS_CommonBlock()
+:
+  myTolerance(0.0)
 {
 }
 //=======================================================================
@@ -33,7 +35,8 @@ IMPLEMENT_STANDARD_RTTIEXT(BOPDS_CommonBlock,Standard_Transient)
   BOPDS_CommonBlock::BOPDS_CommonBlock(const Handle(NCollection_BaseAllocator)& theAllocator)
 :
   myPaveBlocks(theAllocator),
-  myFaces(theAllocator)
+  myFaces(theAllocator),
+  myTolerance(0.0)
 {
 }
 //=======================================================================
index 81572222a97d96ee5c082663849d0a4697e692b6..7f61aa6615ddbf90431c52026fa51b3a22bcd215 100644 (file)
@@ -61,9 +61,7 @@ public:
   
 
   //! Modifier
-  //! Adds the list of pave blocks <aLPB>
-  //! to the list of pave blocks
-  //! of the common block
+  //! Sets the list of pave blocks for the common block
   Standard_EXPORT void SetPaveBlocks (const BOPDS_ListOfPaveBlock& aLPB);
   
 
@@ -154,13 +152,25 @@ public:
   //! It will be representative for the whole group.
   Standard_EXPORT void SetRealPaveBlock(const Handle(BOPDS_PaveBlock)& thePB);
 
+  //! Sets the tolerance for the common block
+  void SetTolerance(const Standard_Real theTol)
+  {
+    myTolerance = theTol;
+  }
+
+  //! Return the tolerance of common block
+  Standard_Real Tolerance() const
+  {
+    return myTolerance;
+  }
 
   DEFINE_STANDARD_RTTIEXT(BOPDS_CommonBlock,Standard_Transient)
 
 protected:
 
-  BOPDS_ListOfPaveBlock myPaveBlocks;
-  BOPCol_ListOfInteger myFaces;
+  BOPDS_ListOfPaveBlock myPaveBlocks; //!< Pave blocks of the common block
+  BOPCol_ListOfInteger myFaces;       //!< Faces on which the pave blocks are lying
+  Standard_Real myTolerance;          //!< Tolerance of the common block
 
 private:
 
index 443587d931ae6c9ebeb5a101e440fd9d0545951c..feeb7dbc3884f2bf4bc721029ed492273d9bd3d7 100644 (file)
@@ -90,7 +90,8 @@ BOPDS_DS::BOPDS_DS()
   myInterfVZ(0, myAllocator),
   myInterfEZ(0, myAllocator),
   myInterfFZ(0, myAllocator),
-  myInterfZZ(0, myAllocator)
+  myInterfZZ(0, myAllocator),
+  myInterfered(100, myAllocator)
 {
   myNbShapes=0;
   myNbSourceShapes=0;
@@ -121,7 +122,8 @@ BOPDS_DS::BOPDS_DS(const Handle(NCollection_BaseAllocator)& theAllocator)
   myInterfVZ(0, myAllocator),
   myInterfEZ(0, myAllocator),
   myInterfFZ(0, myAllocator),
-  myInterfZZ(0, myAllocator)
+  myInterfZZ(0, myAllocator),
+  myInterfered(100, myAllocator)
 {
   myNbShapes=0;
   myNbSourceShapes=0;
@@ -163,6 +165,7 @@ void BOPDS_DS::Clear()
   myInterfEZ.Clear();
   myInterfFZ.Clear();
   myInterfZZ.Clear();
+  myInterfered.Clear();
 }
 //=======================================================================
 //function : SetArguments
@@ -680,30 +683,6 @@ void BOPDS_DS::InitShape
   }
 }
 
-//=======================================================================
-//function : HasInterf
-//purpose  : 
-//=======================================================================
-Standard_Boolean BOPDS_DS::HasInterf(const Standard_Integer theI) const
-{
-  Standard_Integer n1, n2;
-  Standard_Boolean bRet;
-  BOPDS_MapIteratorOfMapOfPair aIt;
-  //
-  bRet = Standard_False;
-  //
-  aIt.Initialize(myInterfTB);
-  for (; aIt.More(); aIt.Next()) {
-    const BOPDS_Pair& aPK = aIt.Value();
-    aPK.Indices(n1, n2);
-    if (n1 == theI || n2 == theI) {
-      bRet = Standard_True;
-      break;
-    }
-  }
-  //
-  return bRet;
-}
 //=======================================================================
 //function : HasInterfShapeSubShapes
 //purpose  : 
@@ -1758,43 +1737,6 @@ void BOPDS_DS::Paves(const Standard_Integer theEdge,
   }
 }
 //=======================================================================
-// function: UpdateTolerance
-// purpose:
-//=======================================================================
-void BOPDS_DS::UpdateEdgeTolerance(const Standard_Integer nE,
-                                   const Standard_Real aTol,
-                                   const Standard_Real theFuzz)
-{
-  Standard_Integer nV;
-  Standard_Real aTolV;
-  BRep_Builder aBB;
-  BOPCol_ListIteratorOfListOfInteger aIt;
-  //
-  Standard_Real aTolAdd = Max(theFuzz, Precision::Confusion()) * 0.5;
-
-  const TopoDS_Edge& aE = *(TopoDS_Edge*)&Shape(nE);
-  aBB.UpdateEdge(aE, aTol);
-  BOPDS_ShapeInfo& aSIE=ChangeShapeInfo(nE);
-  Bnd_Box& aBoxE=aSIE.ChangeBox();
-  BRepBndLib::Add(aE, aBoxE);
-  aBoxE.SetGap(aBoxE.GetGap() + aTolAdd);
-  //
-  const BOPCol_ListOfInteger& aLI = aSIE.SubShapes();
-  aIt.Initialize(aLI);
-  for (; aIt.More(); aIt.Next()) {
-    nV = aIt.Value();
-    const TopoDS_Vertex& aV = *(TopoDS_Vertex*)&Shape(nV);
-    aTolV = BRep_Tool::Tolerance(aV);
-    if (aTolV < aTol) {
-      aBB.UpdateVertex(aV, aTol);
-      BOPDS_ShapeInfo& aSIV = ChangeShapeInfo(nV);
-      Bnd_Box& aBoxV = aSIV.ChangeBox();
-      BRepBndLib::Add(aV, aBoxV);
-      aBoxV.SetGap(aBoxV.GetGap() + aTolAdd);
-    }
-  }
-}
-//=======================================================================
 //function : TotalShapes
 //purpose  : 
 //=======================================================================
index 94e4855d098e2efd1836d8794fa0e3464d440f3c..edfc4a4e8bf88f8b93689fa8300a879f0bb7221e 100644 (file)
@@ -392,27 +392,23 @@ Standard_EXPORT virtual ~BOPDS_DS();
   
 
   //! Returns the number of types of the interferences
-    static Standard_Integer NbInterfTypes();
-  
+  static Standard_Integer NbInterfTypes();
 
   //! Modifier
   //! Adds the information about an interference between
   //! shapes with indices theI1, theI2 to the summary
   //! table of interferences
-    void AddInterf (const Standard_Integer theI1, const Standard_Integer theI2);
-  
+  Standard_Boolean AddInterf (const Standard_Integer theI1, const Standard_Integer theI2);
 
   //! Query
   //! Returns true if the shape with index theI
   //! is interferred
-  Standard_EXPORT Standard_Boolean HasInterf (const Standard_Integer theI) const;
-  
+  Standard_Boolean HasInterf (const Standard_Integer theI) const;
 
   //! Query
   //! Returns true if the shapes with indices theI1, theI2
   //! are interferred
-    Standard_Boolean HasInterf (const Standard_Integer theI1, const Standard_Integer theI2) const;
-  
+  Standard_Boolean HasInterf (const Standard_Integer theI1, const Standard_Integer theI2) const;
 
   //! Query
   //! Returns true if the shape with index theI1 is interfered
@@ -441,12 +437,6 @@ Standard_EXPORT virtual ~BOPDS_DS();
   //! Fills theLP with sorted paves
   //! of the shape with index theIndex
   Standard_EXPORT void Paves (const Standard_Integer theIndex, BOPDS_ListOfPave& theLP);
-  
-
-  //! Updates tolerance of the sub-shapes of the shape with index <theIndex>.
-  Standard_EXPORT void UpdateEdgeTolerance (const Standard_Integer theIndex,
-                                            const Standard_Real theTolerance,
-                                            const Standard_Real theFuzz = Precision::Confusion());
 
   //! Update the pave blocks for all shapes in data structure
   Standard_EXPORT void UpdatePaveBlocksWithSDVertices();
@@ -515,6 +505,7 @@ protected:
   BOPDS_VectorOfInterfEZ myInterfEZ;
   BOPDS_VectorOfInterfFZ myInterfFZ;
   BOPDS_VectorOfInterfZZ myInterfZZ;
+  BOPCol_MapOfInteger myInterfered;
 
 
 private:
index 160a4db2d2a0eba43abf757f84412afba502aa28..25634a899ceb142cfe61a0f22aed47d158096b8f 100644 (file)
@@ -104,11 +104,24 @@ inline Standard_Integer BOPDS_DS::NbInterfTypes()
 //function : AddInterf
 //purpose  : 
 //=======================================================================
-inline void BOPDS_DS::AddInterf(const Standard_Integer theI1,
-                                const Standard_Integer theI2)
+inline Standard_Boolean BOPDS_DS::AddInterf(const Standard_Integer theI1,
+                                            const Standard_Integer theI2)
 {
-  BOPDS_Pair aPK(theI1, theI2);
-  myInterfTB.Add(aPK);
+  if (myInterfTB.Add(BOPDS_Pair(theI1, theI2)))
+  {
+    myInterfered.Add(theI1);
+    myInterfered.Add(theI2);
+    return Standard_True;
+  }
+  return Standard_False;
+}
+//=======================================================================
+//function : HasInterf
+//purpose  : 
+//=======================================================================
+inline Standard_Boolean BOPDS_DS::HasInterf(const Standard_Integer theI) const
+{
+  return myInterfered.Contains(theI);
 }
 //=======================================================================
 //function : HasInterf
index b274569442e3331e549716933a841d887cd13732..12f80e17a1f1f5267b84bf9f14c96cd1b8dd8b52 100644 (file)
@@ -42,8 +42,8 @@ class BOPDS_TSR : public BOPCol_BoxBndTreeSelector{
   BOPDS_TSR() : 
     BOPCol_BoxBndTreeSelector(), 
     myHasBRep(Standard_False), 
-    myTree(NULL) {
-  }
+    myTree(NULL),
+    myIndex(-1) {}
   //
   virtual ~BOPDS_TSR() {
   }
@@ -56,6 +56,10 @@ class BOPDS_TSR : public BOPCol_BoxBndTreeSelector{
     myTree=&aTree;
   }
   //
+  void SetIndex(const Standard_Integer theIndex) { myIndex = theIndex; }
+  //
+  Standard_Integer Index() const { return myIndex; }
+  //
   void Perform() {
     if (myHasBRep) {
       myTree->Select(*this);
@@ -65,6 +69,7 @@ class BOPDS_TSR : public BOPCol_BoxBndTreeSelector{
  protected:
   Standard_Boolean myHasBRep;
   BOPCol_BoxBndTree *myTree;
+  Standard_Integer myIndex;
 };
 //
 //=======================================================================
@@ -81,11 +86,12 @@ typedef BOPCol_Cnt <BOPDS_TSRFunctor, BOPDS_VectorOfTSR> BOPDS_TSRCnt;
 BOPDS_Iterator::BOPDS_Iterator()
 :
   myAllocator(NCollection_BaseAllocator::CommonBaseAllocator()),
-  myRunParallel(Standard_False)
+  myRunParallel(Standard_False),
+  myUseExt(Standard_False)
 {
   Standard_Integer i, aNb;
   //
-  myDS=NULL; 
+  myDS=NULL;
   myLength=0;
   //
   aNb=BOPDS_DS::NbInterfTypes();
@@ -93,6 +99,12 @@ BOPDS_Iterator::BOPDS_Iterator()
   for (i=0; i<aNb; ++i) {
     myLists.Append1();
   }
+
+  const Standard_Integer aNbExt = BOPDS_Iterator::NbExtInterfs();
+  myExtLists.SetIncrement(aNbExt);
+  for (i = 0; i < aNbExt; ++i) {
+    myExtLists.Append1();
+  }
 }
 //=======================================================================
 //function : 
@@ -103,7 +115,9 @@ BOPDS_Iterator::BOPDS_Iterator
 :
   myAllocator(theAllocator),
   myLists(0, theAllocator),
-  myRunParallel(Standard_False)
+  myRunParallel(Standard_False),
+  myExtLists(0, theAllocator),
+  myUseExt(Standard_False)
 {
   Standard_Integer i, aNb;
   //
@@ -115,6 +129,12 @@ BOPDS_Iterator::BOPDS_Iterator
   for (i=0; i<aNb; ++i) {
     myLists.Append1();
   }
+
+  const Standard_Integer aNbExt = BOPDS_Iterator::NbExtInterfs();
+  myExtLists.SetIncrement(aNbExt);
+  for (i = 0; i < aNbExt; ++i) {
+    myExtLists.Append1();
+  }
 }
 //=======================================================================
 //function : ~
@@ -192,12 +212,15 @@ void BOPDS_Iterator::Initialize(const TopAbs_ShapeEnum aType1,
   //
   myLength=0;
   iX=BOPDS_Tools::TypeToInteger(aType1, aType2);
-  if (iX>=0) {
+  if (iX >= 0)
+  {
+    BOPDS_VectorOfPair& aPairs = (myUseExt && iX < BOPDS_Iterator::NbExtInterfs()) ?
+      myExtLists(iX) : myLists(iX);
     // sort interfering pairs for constant order of intersection
-    std::stable_sort(myLists(iX).begin(), myLists(iX).end());
+    std::stable_sort(aPairs.begin(), aPairs.end());
     // initialize iterator to access the pairs
-    myIterator.Init(myLists(iX));
-    myLength = myLists(iX).Extent();
+    myIterator.Init(aPairs);
+    myLength = aPairs.Extent();
   }
 }
 //=======================================================================
@@ -272,8 +295,8 @@ void BOPDS_Iterator::Intersect(const Handle(IntTools_Context)& theCtx,
   Standard_Integer iTi, iTj;
   TopAbs_ShapeEnum aTi, aTj;
   //
-  BOPCol_BoxBndTree aBBTree;
-  NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
+  myBoxTree.Clear();
+  NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(myBoxTree);
   //
   aNb = myDS->NbSourceShapes();
   BOPDS_VectorOfTSR aVTSR(aNb);
@@ -290,8 +313,9 @@ void BOPDS_Iterator::Intersect(const Handle(IntTools_Context)& theCtx,
     }
     //
     const Bnd_Box& aBoxEx=aSI.Box();
-    aTSR.SetTree(aBBTree);
+    aTSR.SetTree(myBoxTree);
     aTSR.SetBox(aBoxEx);
+    aTSR.SetIndex(i);
     //
     aTreeFiller.Add(i, aBoxEx);
   }
@@ -366,3 +390,115 @@ void BOPDS_Iterator::Intersect(const Handle(IntTools_Context)& theCtx,
   aVTSR.Clear();
   //-----------------------------------------------------scope_1 t
 }
+
+//=======================================================================
+// function: PrepareExt
+// purpose: 
+//=======================================================================
+void BOPDS_Iterator::PrepareExt(const BOPCol_MapOfInteger& theIndices)
+{
+  if (!myDS)
+    return;
+
+  // Update UB tree of bounding boxes with the increased shapes.
+  // It is expected that not too many shapes will be modified during
+  // the intersection, so after updating the tree it should not become
+  // too unbalanced.
+  BOPCol_MapIteratorOfMapOfInteger itM(theIndices);
+  for (; itM.More(); itM.Next())
+  {
+    Standard_Integer nV = itM.Value();
+    myBoxTree.Remove(nV);
+
+    // Add with new box
+    Standard_Integer nVSD = nV;
+    myDS->HasShapeSD(nV, nVSD);
+    const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nVSD);
+    const Bnd_Box& aBox = aSI.Box();
+    myBoxTree.Add(nV, aBox);
+  }
+
+  // Clear the extra lists
+  const Standard_Integer aNbExt = BOPDS_Iterator::NbExtInterfs();
+  myLength = 0;
+  for (Standard_Integer i = 0; i < aNbExt; ++i)
+    myExtLists(i).Clear();
+
+  IntersectExt(theIndices);
+
+  myUseExt = Standard_True;
+}
+
+//=======================================================================
+// function: IntersectExt
+// purpose: 
+//=======================================================================
+void BOPDS_Iterator::IntersectExt(const BOPCol_MapOfInteger& theIndices)
+{
+  // Prepare vector for parallel selection
+  BOPDS_VectorOfTSR aVTSR(theIndices.Extent());
+
+  BOPCol_MapIteratorOfMapOfInteger itM(theIndices);
+  for (; itM.More(); itM.Next())
+  {
+    Standard_Integer nV = itM.Value();
+    Standard_Integer nVSD = nV;
+    myDS->HasShapeSD(nV, nVSD);
+    const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(nVSD);
+    const Bnd_Box& aBox = aSI.Box();
+    BOPDS_TSR& aTSR = aVTSR.Append1();
+    aTSR.SetHasBRep(Standard_True);
+    aTSR.SetTree(myBoxTree);
+    aTSR.SetBox(aBox);
+    aTSR.SetIndex(nV);
+  }
+
+  // Perform selection
+  BOPDS_TSRCnt::Perform(myRunParallel, aVTSR);
+
+  // Treat selections
+
+  // Fence map to avoid duplicating pairs
+  BOPDS_MapOfPair aMPFence;
+
+  const Standard_Integer aNb = aVTSR.Length();
+  for (Standard_Integer k = 0; k < aNb; ++k)
+  {
+    BOPDS_TSR& aTSRi = aVTSR(k);
+    const BOPCol_ListOfInteger& aLI = aTSRi.Indices();
+    if (aLI.IsEmpty())
+      continue;
+
+    const Standard_Integer i = aTSRi.Index();
+    const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
+    const Standard_Integer iRankI = myDS->Rank(i);
+    const TopAbs_ShapeEnum aTI = aSI.ShapeType();
+    const Standard_Integer iTI = BOPDS_Tools::TypeToInteger(aTI);
+
+    BOPCol_ListIteratorOfListOfInteger itLI(aLI);
+    for (; itLI.More(); itLI.Next())
+    {
+      const Standard_Integer j = itLI.Value(); // Index in DS
+      const Standard_Integer iRankJ = myDS->Rank(j);
+      if (iRankI == iRankJ)
+        continue;
+
+      const BOPDS_ShapeInfo& aSJ = myDS->ShapeInfo(j);
+      const TopAbs_ShapeEnum aTJ = aSJ.ShapeType();
+      const Standard_Integer iTJ = BOPDS_Tools::TypeToInteger(aTJ);
+
+      // avoid interfering of the same shapes and shape with its sub-shapes
+      if (((iTI < iTJ) && aSI.HasSubShape(j)) ||
+          ((iTI > iTJ) && aSJ.HasSubShape(i)))
+        continue;
+
+      BOPDS_Pair aPair(i, j);
+      if (aMPFence.Add(aPair))
+      {
+        const Standard_Integer iX = BOPDS_Tools::TypeToInteger(aTI, aTJ);
+        if (iX < BOPDS_Iterator::NbExtInterfs())
+          myExtLists(iX).Append(aPair);
+      }
+    }
+  }
+}
index ef6ed001a9c59e416753861096f1564333174178..6e57b8f3631b917e2f1103496faf1a3c89443cd5 100644 (file)
 #include <BOPDS_PDS.hxx>
 #include <BOPDS_VectorOfPair.hxx>
 #include <BOPDS_VectorOfVectorOfPair.hxx>
+#include <BOPCol_BoxBndTree.hxx>
+#include <NCollection_BaseAllocator.hxx>
 #include <Precision.hxx>
 #include <Standard_Boolean.hxx>
 #include <TopAbs_ShapeEnum.hxx>
 class BOPDS_DS;
 class IntTools_Context;
 
-
 //! The class BOPDS_Iterator is
 //! 1.to compute intersections between BRep sub-shapes
 //! of arguments of an operation (see the class BOPDS_DS)
 //! in terms of theirs bounding boxes
-//! 2.provides interface to iterare the pairs of
+//! 2.provides interface to iterate the pairs of
 //! intersected sub-shapes of given type
 class BOPDS_Iterator 
 {
@@ -86,6 +87,10 @@ public:
                                        const Standard_Boolean theCheckOBB = Standard_False,
                                        const Standard_Real theFuzzyValue = Precision::Confusion());
 
+  //! Updates the tree of Bounding Boxes with increased boxes and
+  //! intersects such elements with the tree.
+  Standard_EXPORT void PrepareExt(const BOPCol_MapOfInteger& theIndicies);
+
   //! Returns the number of intersections founded
   Standard_EXPORT Standard_Integer ExpectedLength() const;
 
@@ -100,20 +105,40 @@ public:
   //! Returns the flag of parallel processing
   Standard_EXPORT Standard_Boolean RunParallel() const;
 
-protected:
 
+public: //! @name Number of extra interfering types
+
+  // Extra lists contain only V/V, V/E, V/F interfering pairs.
+  // Although E/E is also initialized (but never filled) for code simplicity.
+  static Standard_Integer NbExtInterfs() { return 4; }
+
+protected: //! @name Protected methods for bounding boxes intersection
+
+  //! Intersects the Bounding boxes of sub-shapes of the arguments with the tree
+  //! and saves the interfering pairs for further geometrical intersection.
   Standard_EXPORT virtual void Intersect(const Handle(IntTools_Context)& theCtx = Handle(IntTools_Context)(),
                                          const Standard_Boolean theCheckOBB = Standard_False,
                                          const Standard_Real theFuzzyValue = Precision::Confusion());
 
-  BOPCol_BaseAllocator myAllocator;
-  Standard_Integer myLength;
-  BOPDS_PDS myDS;
-  BOPDS_VectorOfVectorOfPair myLists;
-  BOPDS_VectorOfPair::Iterator myIterator;
-  Standard_Boolean myRunParallel;
-
-private:
+  //! Intersects the bounding boxes of the shapes with given indices in DS
+  //! with the tree of bounding boxes and saves the interfering pairs in
+  //! extra lists for further geometrical intersection.
+  Standard_EXPORT void IntersectExt(const BOPCol_MapOfInteger& theIndices);
+
+
+protected: //! @name Fields
+
+  Handle(NCollection_BaseAllocator) myAllocator; //!< Allocator
+  Standard_Integer myLength;                     //!< Length of the intersection vector of
+                                                 //! particular intersection type
+  BOPDS_PDS myDS;                                //!< Data Structure
+  BOPDS_VectorOfVectorOfPair myLists;            //!< Pairs with interfering bounding boxes
+  BOPDS_VectorOfPair::Iterator myIterator;       //!< Iterator on each interfering type
+  Standard_Boolean myRunParallel;                //!< Flag for parallel processing
+  BOPCol_BoxBndTree myBoxTree;                   //!< Unbalanced tree of bounding boxes
+  BOPDS_VectorOfVectorOfPair myExtLists;         //!< Extra pairs of sub-shapes found after
+                                                 //! intersection of increased sub-shapes
+  Standard_Boolean myUseExt;                     //!< Information flag for using the extra lists
 
 };
 
index 6daed55906b5d9eb2fae3e54c8aa0e75a176b1fd..9cd7fec43f58a379b199f430790eb27d9b892814 100644 (file)
@@ -128,7 +128,7 @@ void BOPTest::DebugCommands(Draw_Interpretor& theCommands)
                   __FILE__, bopindex,    g);
   theCommands.Add("bopsd", "Gets the Same domain shape. Use: bopsd #",
                    __FILE__, bopsd,      g);
-  theCommands.Add("bopsc", "Shows the section curves. Use: bopsc [nF1 nF2]",
+  theCommands.Add("bopsc", "Shows the section curves. Use: bopsc [nF1 [nF2]]",
                   __FILE__, bopsc,       g);
   theCommands.Add("boppb", "Shows information about pave blocks. Use: boppb [#e]",
                   __FILE__, boppb,       g);
@@ -637,8 +637,8 @@ Standard_Integer bopsc(Draw_Interpretor& di,
                        Standard_Integer n,
                        const char** a)
 {
-  if (n != 1 && n != 3) {
-    di << "Shows the section curves. Use: bopsc [nF1 nF2]\n";
+  if (n > 3) {
+    di.PrintHelp(a[0]);
     return 1;
   }
   //
@@ -658,11 +658,11 @@ Standard_Integer bopsc(Draw_Interpretor& di,
   BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
   //
   nSF1 = nSF2 = -1;
-  if (n == 3) {
+  if (n > 1)
     nSF1 = Draw::Atoi(a[1]);
+  if (n > 2)
     nSF2 = Draw::Atoi(a[2]);
-  }
-  //
+
   BOPDS_VectorOfInterfFF& aFFs = pDS->InterfFF();
   //
   iCnt = 0;
@@ -676,6 +676,10 @@ Standard_Integer bopsc(Draw_Interpretor& di,
       }
       iPriz = 1;
     }
+    else if (n == 2) {
+      if (!aFF.Contains(nSF1))
+        continue;
+    }
     //
     aFF.Indices(nF1, nF2);
     //
index 8e29fc77c3bd5a22fc0806be750b7cae1cccf002..662e36a9b2c072f42ce8e047df063aa63a2edd48 100644 (file)
@@ -755,7 +755,6 @@ Standard_Boolean BOPTools_AlgoTools::IsInternalFace
    Handle(IntTools_Context)& theContext)
 {
   Standard_Boolean bDegenerated;
-  Standard_Integer aNbF, iRet, iFound;
   TopAbs_Orientation aOr;
   TopoDS_Edge aE1;
   TopExp_Explorer aExp;
@@ -766,14 +765,8 @@ Standard_Boolean BOPTools_AlgoTools::IsInternalFace
   // iRet=0;  - state is not IN
   // iRet=1;  - state is IN
   // iRet=2;  - state can not be found by the method of angles
-  //
-  // For this function the returned value iRet means:
-  // iRet=0;  - state is not IN
-  // iRet=1;  - state is IN
-  //
-  iRet=0; 
+  Standard_Integer iRet = 0;
   // 1 Try to find an edge from theFace in theMEF
-  iFound=0;
   aExp.Init(theFace, TopAbs_EDGE);
   for(; aExp.More(); aExp.Next()) {
     const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
@@ -781,8 +774,6 @@ Standard_Boolean BOPTools_AlgoTools::IsInternalFace
       continue;
     }
     //
-    ++iFound;
-    //
     aOr=aE.Orientation();
     if (aOr==TopAbs_INTERNAL) {
       continue;
@@ -793,18 +784,13 @@ Standard_Boolean BOPTools_AlgoTools::IsInternalFace
     }
     // aE
     BOPCol_ListOfShape& aLF=theMEF.ChangeFromKey(aE);
-    aNbF=aLF.Extent();
-    if (!aNbF) {
-      return iRet != 0; // it can not be so
-    }
-    //
-    else if (aNbF==1) {
+    Standard_Integer aNbF = aLF.Extent();
+    if (aNbF==1) {
       // aE is internal edge on aLF.First()
       const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
       BOPTools_AlgoTools::GetEdgeOnFace(aE, aF1, aE1);
-      if (aE1.Orientation()!=TopAbs_INTERNAL) {
-        iRet=2; 
-        break;
+      if (aE1.Orientation() != TopAbs_INTERNAL) {
+        continue;
       }
       //
       iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF1, 
@@ -815,31 +801,14 @@ Standard_Boolean BOPTools_AlgoTools::IsInternalFace
     else if (aNbF==2) {
       const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
       const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
-      //
-      if (aF2.IsSame(aF1) && BRep_Tool::IsClosed(aE, aF1)) {
-        // treat as it was for 1 face
-        iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF2, 
-                                                theContext);
-        break;
-      }
-    }
-    //
-    if (aNbF%2) {
-      return Standard_False; // it can not be so
-    }
-    else { // aNbF=2,4,6,8,...
-      iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aLF, 
+      iRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF2,
                                               theContext);
       break;
     }
   }//for(; aExp.More(); aExp.Next()) {
   //
-  if (!iFound) {
-    // the face has no shared edges with the solid
-    iRet=2;
-  }
-  //
-  if (iRet!=2) {
+  if (aExp.More() && iRet != 2)
+  {
     return iRet == 1;
   }
   //
index 9323c48bbea181ad4d3183506277ee14e3f0fbdf..e3ae2576dc8f984c376aded9fa184672470806e5 100644 (file)
@@ -593,8 +593,8 @@ Standard_Integer IntTools_Context::ComputePE
       {
         gp_Pnt aPV = BRep_Tool::Pnt(aV);
         aTolSum = aTolP1 + BRep_Tool::Tolerance(aV) + Precision::Confusion();
-        Standard_Real aDist1 = aP1.SquareDistance(aPV);
-        if (aDist1 < aDist && aDist1 < Square(aTolSum))
+        Standard_Real aDist1 = aP1.Distance(aPV);
+        if (aDist1 < aDist && aDist1 < aTolSum)
         {
           aDist = aDist1;
           aT = BRep_Tool::Parameter(aV, aEFwd);
index 2ce57e0529365c592a21aab193a709e94b20beab..d555cb82bad641834dfd0a2e2eabf25ea53d7b5e 100644 (file)
@@ -487,11 +487,6 @@ Standard_Boolean IntTools_EdgeFace::CheckTouch
   (const IntTools_CommonPrt& aCP,
    Standard_Real&            aTx) 
 {
-  if (myC.GetType() == GeomAbs_Line &&
-      myS.GetType() == GeomAbs_Plane) {
-    return Standard_False;
-  }
-  //
   Standard_Real aTF, aTL, Tol, U1f, U1l, V1f, V1l, af, al,aDist2, aMinDist2;
   Standard_Boolean theflag=Standard_False;
   Standard_Integer aNbExt, iLower;
index 5030a3e0c119a589c8be24e138cc95ee603c7cbb..53f188dda6e4be6d7c6c32d4f75e21c7b2fd408f 100644 (file)
@@ -427,11 +427,9 @@ void IntTools_FaceFace::Perform(const TopoDS_Face& aF1,
     Standard_Real umin, umax, vmin, vmax;
     //
     myContext->UVBounds(myFace1, umin, umax, vmin, vmax);
-    CorrectPlaneBoundaries(umin, umax, vmin, vmax);
     myHS1->ChangeSurface().Load(S1, umin, umax, vmin, vmax);
     //
     myContext->UVBounds(myFace2, umin, umax, vmin, vmax);
-    CorrectPlaneBoundaries(umin, umax, vmin, vmax);
     myHS2->ChangeSurface().Load(S2, umin, umax, vmin, vmax);
     //
     Standard_Real TolAng = 1.e-8;
index 7ce4763c6525dede086168db4466ef2c8b2a7006..70133d721483e47c6968b553b2ca73b5bbde1bb3 100644 (file)
@@ -34,6 +34,7 @@
   myTS2=myT1;
   myIsDone=Standard_False;
   myIsSplittable=Standard_False;
+  myLength = 0.0;
 }
 //=======================================================================
 //function : ~
@@ -59,6 +60,7 @@ void IntTools_ShrunkRange::SetData(const TopoDS_Edge& aE,
   myT2=aT2;
   myIsDone=Standard_False;
   myIsSplittable=Standard_False;
+  myLength = 0.0;
 }
 //=======================================================================
 //function : SetContext
@@ -178,9 +180,8 @@ void IntTools_ShrunkRange::Perform()
   if (aPTolE > aPTolEMin) {
     aPTolE = aPTolEMin;
   }
-  Standard_Real anEdgeLength =
-    GCPnts_AbscissaPoint::Length(aBAC, myTS1, myTS2, aPTolE);
-  if (anEdgeLength < aDTol) {
+  myLength = GCPnts_AbscissaPoint::Length(aBAC, myTS1, myTS2, aPTolE);
+  if (myLength < aDTol) {
     // micro edge
     return;
   }
@@ -192,11 +193,10 @@ void IntTools_ShrunkRange::Perform()
   // for the edge to have possibility to be split at least once:
   // 2*TolE - minimal diameter of tolerance sphere of splitting vertex
   // 2*Precision::Confusion() - minimal length of the new edges
-  if (anEdgeLength > (2 * aTolE + 2 * aDTol)) {
+  if (myLength > (2 * aTolE + 2 * aDTol)) {
     myIsSplittable = Standard_True;
   }
   //
   // build bounding box for the edge on the shrunk range
-  BndLib_Add3dCurve::Add(aBAC, myTS1, myTS2,
-      aTolE + aDTol, myBndBox);
+  BndLib_Add3dCurve::Add(aBAC, myTS1, myTS2, aTolE + aDTol, myBndBox);
 }
index 5a08778eb6aa1165dbd5868ab168d77ec4770ab5..cf3a02c65032d7dbf695e7a954745d457c52374a 100644 (file)
@@ -74,6 +74,9 @@ Standard_EXPORT virtual ~IntTools_ShrunkRange();
     return myIsSplittable;
   }
 
+  //! Returns the length of the edge if computed.
+  Standard_Real Length() const { return myLength; }
+
 protected:
 
   TopoDS_Edge myEdge;
@@ -87,6 +90,7 @@ protected:
   Handle(IntTools_Context) myCtx;
   Standard_Boolean myIsDone;
   Standard_Boolean myIsSplittable;
+  Standard_Real myLength;
 
 private:
 
index 7aa2f6f0b780f5fc5df3a370472358a2b4acfcb9..af4deb85285c543314b0d68c217765e44d6c5fa3 100644 (file)
@@ -1,10 +1,44 @@
 # Original bug : buc60127
 # Date : 18mar98
 
-puts "TODO #22911 ALL: Error : The command is not valid. The area is 0."
-
 restore [locate_data_file buc60127-part.rle] part
 restore [locate_data_file buc60127-tool.rle] tool
 
+# fix the part shape
+
+explode part f
+# fix inner cylinder
+mksurface c_in part_1
+trim c_in c_in
+mkface f_in c_in 0 2*pi 0 150
+
+# fix side faces
+mksurface s1 part_3
+mksurface s2 part_4
+mkface f1 s1 -10 10 -10 10
+mkface f2 s2 -10 10 -10 10
+
+# fix solid
+mkvolume r part_2 f_in f1 f2
+
+# find the outher solid - the one containing the outer cylinder (part_2 face)
+foreach s [explode r so] {
+  set found 0
+  foreach f [explode $s f] {
+    if {[regexp "same shapes" [compare part_2 $f]]} {
+      copy $s part
+      set found 1
+      break
+    }
+  }
+  if {$found} {
+    break
+  }
+}
+
 bcut result part tool
-checkprops result -s 0
+checkshape result
+checkprops result -s 5382.41 -v 2643.38
+checknbshapes result -wire 14 -face 11 -shell 1 -solid 1
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
\ No newline at end of file
index 849d1e694dd79d042bfc8e4fc81d4292f943f16c..213442f86e0f753956f2dba17e39e9f202f51393 100644 (file)
@@ -1,8 +1,6 @@
 # Original bug : pro14260
 # Date : 21 Sept 98
 
-puts "TODO OCC27697 ALL: Error :  is WRONG because number of "
-
 restore [locate_data_file CTO900_pro14260c.rle] c
 restore [locate_data_file pro14260d.rle] d
 
index 192bb9641cdc4987dd30b367eb89dfdb30627ea8..06a59bfbb5b93fe1078ab3e8af6635b52f578fdd 100644 (file)
@@ -6,5 +6,8 @@ restore [locate_data_file pro10658b.rle] b
 
 bfuse result a b
 
-checkprops result -s 8636.79
-checkview -display result -2d -otherwise { a b } -s -path ${imagedir}/${test_image}.png
\ No newline at end of file
+checkshape result
+checkprops result -s 8231.06 -v 30472.5
+checknbshapes result -wire 9 -face 9 -shell 1 -solid 1
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
index 4667b47a7847c130c9099c83f5cae716d929ed2d..8e7387c05a71a53f42cd44ab0962519da8f9a087 100644 (file)
@@ -1,9 +1,11 @@
 # pro10658
-puts "TODO ALL: Error : The area of result shape is"
 restore [locate_data_file CTO900_pro10658a.rle] a
 restore [locate_data_file pro10658b.rle] b
 
 bfuse result a b
 
-checkprops result -s 8231.06
-checkview -display result -2d -otherwise { a b } -s -path ${imagedir}/${test_image}.png
\ No newline at end of file
+checkshape result
+checkprops result -s 8231.06 -v 30472.5
+checknbshapes result -wire 9 -face 9 -shell 1 -solid 1
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
\ No newline at end of file
index 8d41796ab45f20b46ca979538800457d6764a385..7da718d3afbe6fdf728fb319eb8f0656d9eacd77 100644 (file)
@@ -3,6 +3,6 @@ plane p 0 0 0 1 0 0
 mkface f p
 bsection result a f
 
-checkprops result -l 18981.2
+checkprops result -l 19044.3
 checksection result
 checkview -display result -2d -otherwise { a f } -l -path ${imagedir}/${test_image}.png
index 8ea1ae823f72eeb122afc786b7bccbc71d14c628..eb3dd899c067eb6324f30bcd729dcbfaa5cbbefd 100644 (file)
@@ -8,6 +8,6 @@ restore [locate_data_file ger61235b.brep] object
 
 bsection result object tool 
 
-checkprops result -l 11.8242
+checkprops result -l 16.4762
 checksection result
 checkview -display result -2d -otherwise { object tool  } -l -path ${imagedir}/${test_image}.png
index a3f18ad7fc40d3dfd10c9811ae3d7dd51177b430..cc03b77507bd74c753c3c45c4305b42ecbc149c2 100755 (executable)
@@ -1,4 +1,6 @@
-puts "TODO OCC27024 ALL: Error : operation bfuse is WRONG because number of SOLID entities in shape"
+puts "TODO OCC27024 ALL: Error : operation bfuse is WRONG because number of"
+puts "TODO OCC27024 ALL: Error : The area of result shape is"
+puts "TODO OCC27024 ALL: Faulty shapes in variables"
 puts "TODO OCC27024 ALL: Faulty shapes in variables faulty_1 to faulty_"
 
 puts "=========="
@@ -6,15 +8,14 @@ puts "BUC60462"
 puts "=========="
 
 restore [locate_data_file buc60462c.brep] a 
-checkshape a
 restore [locate_data_file buc60462d.brep] b
-checkshape b
+
 puts "Fuse begin"
 bfuse result a b
 puts "Fuse end"
 
 checkshape result r
-checknbshapes result -solid 1 -m "operation bfuse"
+checknbshapes result -shell 1 -solid 1 -m "operation bfuse"
 checkprops result -s 93237.9
 checkshape result
 checkview -display result -2d -path ${imagedir}/${test_image}.png
index 338604f7cb272bcc84ef110d529b9033f543ac44..7b68126b243353e73664db52b00a4556978357d3 100755 (executable)
@@ -1,24 +1,14 @@
-
 puts "========================"
 puts "BUC60703"
 puts "========================"
 
 restore [locate_data_file buc60703e.brep] a 
-#maxtolerance a
-checkshape a
 restore [locate_data_file buc60703d.brep] b
-#maxtolerance b
-checkshape b
 
-if [catch {bfuse result a b } catch_result] {
-    puts "Faulty  BUC60703: here is problem with FUSE operation"
-} else {
-    puts "OK OCC348: function FUSE works ok"
-    if [catch {checkshape result} catch_result] {
-       puts "Faulty BUC60703 : here is checking problem. See also OCC438: 919 D3 and D4"
-    } else {
-       puts "BUC60703   : here is NOT checking problem"
-    }
-}
-checkprops result -s 371.259 
+bfuse result a b
+
+checkshape result
+checkprops result -s 307.2 -v 252.773
+checknbshapes result -wire 10 -face 9 -shell 1 -solid 1
+
 checkview -display result -2d -path ${imagedir}/${test_image}.png
index 2e542e85aaea9983c6d0582a96ce691d694cfc40..aafaea4ca8cdc6fee4fe38d97a9c1df94aaa4f6d 100755 (executable)
@@ -1,5 +1,4 @@
-puts "TODO OCC25917 ALL: Faulty shapes in variables faulty_1 to faulty_"
-puts "TODO OCC25917 ALL: Error : The area of result shape is"
+puts "TODO OCC25917 ALL: Error : The command is not valid. The area is 0."
 
 puts "========================"
 puts " OCC472 "
index c1197d01b1c6db22eee01246bd56610a3bfcf837..fb65ed3f6bf75157998f9b2199a6d4a6cb29e127 100755 (executable)
@@ -1,5 +1,4 @@
-#puts "TODO OCC25917 ALL: Faulty shapes in variables faulty_1 to faulty_"
-puts "TODO OCC25917 ALL: Error : The command is not valid. The area is"
+puts "TODO OCC25917 ALL: Faulty shapes in variables faulty_1 to faulty_"
 puts "TODO OCC25917 ALL: Error : The area of result shape is"
 
 puts "========================"
index 95a738b5cb3fe94941c0c7a1851fcef2a326d416..dc7da5915dd15293a11a0ba831263c7dfb8cf406 100755 (executable)
@@ -1,6 +1,6 @@
 puts "TODO OCC25917 ALL: Faulty shapes in variables faulty_1 to faulty_"
-puts "TODO ?OCC25917 ALL: Error : The area of result shape is"
 puts "TODO OCC25917 ALL: Error :  is WRONG because number of "
+puts "TODO OCC25917 ALL: Error : The area of result shape is "
 puts "========================"
 puts " OCC472 "
 puts "(case 3)"
index be7baec534874cf4bc669b9fe83da15fc78afe79..830623200985799b0f6630dd678574bbf1a93d6e 100644 (file)
@@ -1,5 +1,3 @@
-puts "TODO OCC27014 ALL: Error : result is WRONG because number of .* entities in shape"
-
 puts "============"
 puts "OCC26619"
 puts "============"
@@ -22,21 +20,9 @@ bnondestructive 1
 
 bop h0 f0
 bopsection result
-checkprops result -l 142.264
-
-set nbshapes_expected "
-Number of shapes in shape
- VERTEX    : 46
- EDGE      : 46
- WIRE      : 0
- FACE      : 0
- SHELL     : 0
- SOLID     : 0
- COMPSOLID : 0
- COMPOUND  : 1
- SHAPE     : 93
-"
-checknbshapes result -ref ${nbshapes_expected} -t -m "result"
+checkprops result -l 150.232
+
+checknbshapes result -vertex 47 -edge 47 -t -m "result"
 
 regexp {Tolerance +MAX=([-0-9.+eE]+)} [tolerance h0] full MaxTolerance2
 
@@ -46,3 +32,7 @@ set tol_rel_MaxTolerance 0.0001
 checkreal "MaxTolerance" ${MaxTolerance2} ${expected_MaxTolerance} ${tol_abs_MaxTolerance} ${tol_rel_MaxTolerance}
 
 checkview -display result -2d -path ${imagedir}/${test_image}.png
+
+if {[regexp "alone_1" [checksection result]]} {
+  puts "Error: the section is not closed"
+}
\ No newline at end of file
diff --git a/tests/bugs/modalg_7/bug23660 b/tests/bugs/modalg_7/bug23660
new file mode 100644 (file)
index 0000000..bd35482
--- /dev/null
@@ -0,0 +1,24 @@
+puts "========"
+puts "OCC23660"
+puts "========"
+puts ""
+#####################################
+# 'bsection' produces result with gap
+#####################################
+
+restore [locate_data_file bug23660_shell_537.brep] s
+restore [locate_data_file bug23660_face_537.brep] f
+
+bsection r s f -a
+explode r
+
+smallview
+donly r_9 r_10
+fit
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png
+
+checkmaxtol r -min_tol 0.001
+checkprops r -l 19.0858
+if {[regexp "alone_5" [checksection r]]} {
+  puts "Error: section with gap"
+}
\ No newline at end of file
index cdbf211723b3a7a4836df4dc23dd369b6a28e389..e7fbe87e03975451d174f041953aebaf4ac83fdb 100644 (file)
@@ -26,4 +26,4 @@ fit
 
 checkview -screenshot -2d -path ${imagedir}/${test_image}.png
 
-checkprops result -l 945.22 -deps 0.1
+checkprops result -l 2638.31 -deps 0.1
index e5ea7d0077d7529c6bdec7f7aff375c054800662..ef2dc59966138b1cf84800fd054e88c1e528692c 100644 (file)
@@ -1,6 +1,3 @@
-puts "TODO OCC27049 ALL: Error : result is WRONG because number of .* entities in shape"
-puts "TODO OCC27049 ALL: Error: MaxTolerance"
-
 puts "============"
 puts "OCC27049"
 puts "============"
@@ -23,21 +20,8 @@ tolerance f0
 
 bop h0 f0
 bopsection result
-checkprops result -l 142.264
-
-set nbshapes_expected "
-Number of shapes in shape
- VERTEX    : 46
- EDGE      : 46
- WIRE      : 0
- FACE      : 0
- SHELL     : 0
- SOLID     : 0
- COMPSOLID : 0
- COMPOUND  : 1
- SHAPE     : 93
-"
-checknbshapes result -ref ${nbshapes_expected} -t -m "result"
+checkprops result -l 150.23
+checknbshapes result -vertex 47 -edge 47 -t -m "result"
 
 regexp {Tolerance +MAX=([-0-9.+eE]+)} [tolerance h0] full MaxTolerance2
 
@@ -47,3 +31,7 @@ set tol_rel_MaxTolerance 0.0001
 checkreal "MaxTolerance" ${MaxTolerance2} ${expected_MaxTolerance} ${tol_abs_MaxTolerance} ${tol_rel_MaxTolerance}
 
 checkview -display result -2d -path ${imagedir}/${test_image}.png
+
+if {[regexp "alone_1" [checksection result]]} {
+  puts "Error: the section is not closed"
+}
\ No newline at end of file
diff --git a/tests/bugs/modalg_7/bug28393_1 b/tests/bugs/modalg_7/bug28393_1
new file mode 100644 (file)
index 0000000..273decb
--- /dev/null
@@ -0,0 +1,26 @@
+puts "========"
+puts "OCC28393"
+puts "========"
+puts ""
+###################################
+# Boolean cut produce wrong result.
+###################################
+
+restore [locate_data_file bug28393_o.brep] o
+restore [locate_data_file bug28393_t.brep] t
+
+# object is self-interfering shape
+bopcheck o
+
+bcut result o t
+
+checkshape result
+
+# the self-interfering part of the object is not affected
+# by the tool, and passed into result as is
+bopcheck result
+
+checkprops result -s 70266.5 -v 979408
+checknbshapes result -solid 1 -shell 1 -face 42 -wire 44
+
+checkview -display result -2d -path ${imagedir}/${test_image}-result.png
diff --git a/tests/bugs/modalg_7/bug29711 b/tests/bugs/modalg_7/bug29711
new file mode 100644 (file)
index 0000000..244b8e3
--- /dev/null
@@ -0,0 +1,33 @@
+puts "========"
+puts "OCC29711: General Fuse operation produces invalid result"
+puts "========"
+puts ""
+
+
+binrestore [locate_data_file bug29711_faces.bin] cf
+
+bclearobjects
+bcleartools
+eval baddobjects [explode cf f]
+bfillds
+bbuild gf
+
+# check each face on self-interference
+foreach f [explode gf f] {
+  if {![regexp "OK" [bopcheck $f]]} {
+    puts "Error: face $f is self-interfering"
+  }
+}
+
+checkshape gf
+checkprops gf -s 1995.07
+checknbshapes gf -wire 256 -face 256
+
+# make volumes from the faces
+mkvolume result gf -ni
+
+checkshape result
+checkprops result -s 1996.57 -v 674.739
+checknbshapes result -wire 256 -face 256 -shell 12 -solid 9
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/bugs/modalg_7/bug29900 b/tests/bugs/modalg_7/bug29900
new file mode 100644 (file)
index 0000000..1112b1d
--- /dev/null
@@ -0,0 +1,35 @@
+puts "========"
+puts "OCC29900: Invalid result of FUSE operation"
+puts "========"
+puts ""
+
+cpulimit 3000
+
+brestore [locate_data_file bug29900_rotated.brep] s1
+brestore [locate_data_file bug29900_sewedShape.brep] s2
+
+bdrawwarnshapes 1
+bfuzzyvalue 2.1e-5
+brunparallel 1
+
+bclearobjects
+bcleartools
+baddobjects s1
+baddtools s2
+bfillds
+bbop result 1
+
+checkshape result
+checknbshapes result -wire 39 -face 39 -shell 1 -solid 1
+checkprops result -s 0.0199382 -v 3.24449e-005
+
+if {![regexp "Meshing statuses: NoError" [incmesh result 0.00001]]} {
+  puts "Error: Meshing not done"
+}
+
+boptions -default
+
+smallview +Y+Z
+don result
+fit
+checkview -screenshot -2d -path ${imagedir}/${test_image}.png
index acbd668b3f3e0875b880bd142813e228e93c0178..a57fe7ccc4d96a92db9b6d0de43de0833d12029c 100755 (executable)
@@ -1,5 +1,3 @@
-puts "TODO OCC11111 ALL: OCC2442 Faulty"
-
 puts "============"
 puts "OCC2442"
 puts "============"
@@ -8,39 +6,27 @@ puts ""
 # Error in BRepClass3d_SolidClassifier
 ######################################################
 
-set IsGood 1
-
 restore [locate_data_file OCC2442-1.brep] a 
 restore [locate_data_file OCC2442-2.brep] b 
 
 distmini dm1 a b
-set dm1_list [dump dm1_val]
-set dm1_length [llength $dm1_list]
-if {$dm1_length < 6} {
-   puts "Faulty OCC2442"
-   set IsGood 0
-}
+set dist1 [dval dm1_val]
 
 explode a
 explode b
 distmini dm2 a_1 b_1
-set dm2_list [dump dm2_val]
-set dm2_length [llength $dm2_list]
-if {$dm2_length < 6} {
-   puts "Faulty OCC2442"
-   set IsGood 0
-}
+set dist2 [dval dm2_val]
 
-if {$IsGood == 1} {
-    regexp {([-0-9.+eE]+)} $dm1_list full dist1
-    regexp {([-0-9.+eE]+)} $dm2_list full dist2
+set good_dist 18.4816355578064
 
-    set good_dist 18.4816355578064
-    set dist1_percent [expr abs(${dist1} - ${good_dist}) / double(${good_dist}) * 100.]
+set tol_abs 1.e-7
+set tol_rel 1.e-7
 
-    set dist2_percent [expr abs(${dist1} - ${dist2}) / double(${dist2}) * 100.]
+checkreal "Distance 1 " ${dist1} ${good_dist} ${tol_abs} ${tol_rel}
+checkreal "Distance 2 " ${dist2} ${good_dist} ${tol_abs} ${tol_rel}
 
 bounding -s a -save x0 y0 z0 x1 y1 z1 -nodraw
 ttranslate a -x0 -y0 -z0
 ttranslate b -x0 -y0 -z0
+
 checkview -display a -with b -2d -path ${imagedir}/${test_image}.png
index 0eaa5d7ffa3e63951e11d3b8a72eee3263b0cc64..7d655ac7687b63aae54d3d51597fd8345255e2f1 100755 (executable)
@@ -1,5 +1,3 @@
-puts "TODO CR25432 ALL: Error : The area of result shape is"
-
 puts "================"
 puts "OCC26"
 puts "================"
@@ -12,5 +10,6 @@ checkshape a_2
 
 bfuse result a_2 a_1
 
-checkprops result -s 41539.9
+checkprops result -s 41539.9 -v 348665
+checknbshapes result -wire 44 -face 41 -shell 1 -solid 1
 checkview -display result -2d -path ${imagedir}/${test_image}.png