0030092: Modeling Algorithms - Invalid result of Section operation
authoremv <emv@opencascade.com>
Wed, 29 Aug 2018 08:51:43 +0000 (11:51 +0300)
committerbugmaster <bugmaster@opencascade.com>
Tue, 11 Sep 2018 17:24:47 +0000 (20:24 +0300)
The following improvements have been made in Boolean operations algorithm in order to fix the problem:
1. Initialization of the pave blocks which vertices have acquired the SD ones.
2. Removing from Data Structure the small edges having the same vertices on both ends (either initially or acquired).
3. Avoid adding empty SD connections when one vertex points to itself.

Test case for the issue.

src/BOPAlgo/BOPAlgo_PaveFiller.cxx
src/BOPAlgo/BOPAlgo_PaveFiller.hxx
src/BOPAlgo/BOPAlgo_PaveFiller_2.cxx
src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx
src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx
tests/bugs/modalg_2/bug472_1
tests/bugs/modalg_2/bug472_3
tests/bugs/modalg_7/bug30092 [new file with mode: 0644]

index 0257af3..421c9fa 100644 (file)
@@ -328,6 +328,8 @@ void BOPAlgo_PaveFiller::PerformInternal()
   myDS->ReleasePaveBlocks();
   myDS->RefineFaceInfoOn();
   //
+  RemoveMicroEdges();
+  //
   MakePCurves();
   if (HasErrors()) {
     return; 
index bc1a277..8baf0fa 100644 (file)
@@ -548,6 +548,8 @@ protected:
   Standard_EXPORT void RemoveMicroSectionEdges(BOPDS_IndexedDataMapOfShapeCoupleOfPaveBlocks& theMSCPB,
                                                BOPDS_IndexedMapOfPaveBlock& theMicroPB);
 
+  //! Check all edges on the micro status and remove the positive ones
+  Standard_EXPORT void RemoveMicroEdges();
 
   TopTools_ListOfShape myArguments;
   BOPDS_PDS myDS;
index 115667a..331c97e 100644 (file)
@@ -368,6 +368,9 @@ void BOPAlgo_PaveFiller::SplitPaveBlocks(const TColStd_MapOfInteger& theMEdges,
                              BOPDS_ListOfPaveBlock,
                              TColStd_MapTransientHasher> aMCBNewPB;
   //
+  // Map of vertices to init the pave blocks for them
+  TColStd_MapOfInteger aMVerticesToInitPB;
+
   TColStd_MapIteratorOfMapOfInteger aItM(theMEdges);
   for (; aItM.More(); aItM.Next()) {
     Standard_Integer nE = aItM.Value();
@@ -429,6 +432,10 @@ void BOPAlgo_PaveFiller::SplitPaveBlocks(const TColStd_MapOfInteger& theMEdges,
               aLV.Append(nV1);
               aLV.Append(nV2);
               MakeSDVertices(aLV, theAddInterfs);
+
+              // Save vertices to init pave blocks
+              aMVerticesToInitPB.Add(nV1);
+              aMVerticesToInitPB.Add(nV2);
             }
             continue;
           }
@@ -531,6 +538,11 @@ void BOPAlgo_PaveFiller::SplitPaveBlocks(const TColStd_MapOfInteger& theMEdges,
       }
     }
   }
+
+  // Init pave blocks for vertices which have acquired SD vertex
+  aItM.Initialize(aMVerticesToInitPB);
+  for (; aItM.More(); aItM.Next())
+    myDS->InitPaveBlocksForVertex(aItM.Value());
 }
 
 //=======================================================================
@@ -547,4 +559,4 @@ void BOPAlgo_PaveFiller::AddIntersectionFailedWarning(const TopoDS_Shape& theS1,
   BRep_Builder().Add(aWC, theS2);
   // Add the warning
   AddWarning(new BOPAlgo_AlertIntersectionOfPairOfShapesFailed(aWC));
-}
\ No newline at end of file
+}
index c9b4d01..43740b6 100644 (file)
@@ -629,9 +629,13 @@ void BOPAlgo_PaveFiller::FillShrunkData(Handle(BOPDS_PaveBlock)& thePB)
   const TopoDS_Vertex& aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1))); 
   const TopoDS_Vertex& aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2))); 
   // Get the edge
-  Standard_Integer nE = thePB->OriginalEdge();
-  if (nE < 0 && !thePB->HasEdge(nE))
-    return;
+  Standard_Integer nE = -1;
+  if (!thePB->HasEdge(nE))
+  {
+    nE = thePB->OriginalEdge();
+    if (nE < 0)
+      return;
+  }
 
   const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&myDS->Shape(nE))); 
   // Range
index aed0a2f..d56ec95 100644 (file)
@@ -900,7 +900,7 @@ void BOPAlgo_PaveFiller::PostTreatFF
   //
   // 1 prepare arguments
   TopTools_MapOfShape anAddedSD;
-  for (k=1; k<=aNbS; ++k) {
+  for (k = aNbS; k > 0; --k) {
     const TopoDS_Shape& aS=theMSCPB.FindKey(k);
     aLS.Append(aS);
     // add vertices-candidates for SD from the map aDMNewSD,
@@ -1025,8 +1025,11 @@ void BOPAlgo_PaveFiller::PostTreatFF
       if (!bIntersectionPoint) {
         // save SD connection
         nSx = myDS->Index(aSx);
-        aDMNewSD.Bind(nSx, iV);
-        myDS->AddShapeSD(nSx, iV);
+        if (nSx != iV)
+        {
+          aDMNewSD.Bind(nSx, iV);
+          myDS->AddShapeSD(nSx, iV);
+        }
       }
       else {
         // update FF interference
@@ -1075,8 +1078,7 @@ void BOPAlgo_PaveFiller::PostTreatFF
         // note we check not the edge aSx itself, but its image in aPDS
         const BOPDS_ListOfPaveBlock& aLPBx = aPDS->PaveBlocks(nSx);
         aNbLPBx = aLPBx.Extent();
-        if (aPDS->HasPaveBlocks(nSx) &&
-            (aNbLPBx == 0 || (aNbLPBx == 1 && !aLPBx.First()->HasShrunkData()))) {
+        if (aNbLPBx == 0 || (aNbLPBx == 1 && !aLPBx.First()->HasShrunkData())) {
           BOPDS_ListIteratorOfListOfPaveBlock it(aLPBC);
           for (; it.More(); it.Next()) {
             if (it.Value() == aPB1) {
@@ -1084,6 +1086,12 @@ void BOPAlgo_PaveFiller::PostTreatFF
               break;
             }
           }
+
+          // The edge became micro edge, check vertices for SD
+          TopoDS_Iterator itV(aSx);
+          for (; itV.More(); itV.Next())
+            aLS.Append(itV.Value());
+
           continue;
         }
         //
@@ -2302,21 +2310,21 @@ void BOPAlgo_PaveFiller::GetFullShapeMap(const Standard_Integer nF,
 void BOPAlgo_PaveFiller::RemoveUsedVertices(const BOPDS_Curve& aNC,
                                             TColStd_MapOfInteger& aMV)
 {
-  if (!aMV.Extent()) {
+  if (aMV.IsEmpty())
     return;
-  }
 
   const BOPDS_ListOfPaveBlock& aLPBC = aNC.PaveBlocks();
   BOPDS_ListIteratorOfListOfPaveBlock itPB(aLPBC);
   for (; itPB.More(); itPB.Next())
   {
-    const BOPDS_ListOfPave& aLP = itPB.Value()->ExtPaves();
-    BOPDS_ListIteratorOfListOfPave aItLP(aLP);
-    for (;aItLP.More();aItLP.Next()) {
-      BOPDS_Pave aPave = aItLP.Value();
-      Standard_Integer nV = aPave.Index();
-      aMV.Remove(nV);
-    }
+    const Handle(BOPDS_PaveBlock)& aPB = itPB.Value();
+    const BOPDS_ListOfPave& aLP = aPB->ExtPaves();
+    BOPDS_ListIteratorOfListOfPave itLP(aLP);
+    for (; itLP.More(); itLP.Next())
+      aMV.Remove(itLP.Value().Index());
+
+    aMV.Remove(aPB->Pave1().Index());
+    aMV.Remove(aPB->Pave2().Index());
   }
 }
 
@@ -2919,79 +2927,46 @@ 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]);
-          // 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]);
+          aPave.SetIndex(nV[j]);
+          aPave.SetParameter(aT[j]);
           //
           bRebuild = Standard_True;
+          if (!j) {
+            aPB->SetPave1(aPave);
+          }
+          else {
+            aPB->SetPave2(aPave);
+          }
         }
       }
-
+      //
       if (bRebuild) {
-        if (aT[0] < aT[1])
-        {
-          // It seems the parameters have been recomputed successfully
-          aPave[0].SetParameter(aT[0]);
-          aPave[1].SetParameter(aT[1]);
+        Standard_Integer nE = aPB->Edge();
+        // Check if the Pave Block has the edge set
+        if (nE < 0) {
+          // untouched edge
+          nE = aPB->OriginalEdge();
         }
-
-        aPB->SetPave1(aPave[0]);
-        aPB->SetPave2(aPave[1]);
-
+        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.
           FillShrunkData(aPB);
           if (!aPB->HasShrunkData())
           {
-            Standard_Integer nEMicro = aPB->Edge();
-            if (nEMicro < 0)
-              nEMicro = aPB->OriginalEdge();
             // micro edge, so mark it for removal
-            aMicroEdges.Add(nEMicro);
+            aMicroEdges.Add(nE);
             continue;
           }
         }
-        aPB->Range(aT[0], aT[1]);
         nSp = SplitEdge(nE, nV[0], aT[0], nV[1], aT[1]);
         if (bCB)
           aCB->SetEdge(nSp);
@@ -3029,41 +3004,12 @@ void BOPAlgo_PaveFiller::RemovePaveBlocks(const TColStd_MapOfInteger theEdges)
     }
   }
 
-  // 2. from Face Info and section curves
+  // 2. from section curves
   TColStd_MapOfInteger aMPassed;
   BOPDS_VectorOfInterfFF& aFFs = myDS->InterfFF();
   Standard_Integer aNbFF = aFFs.Length(), j;
   for (i = 0; i < aNbFF; ++i) {
     BOPDS_InterfFF& aFF = aFFs(i);
-    Standard_Integer nF1, nF2;
-    aFF.Indices(nF1, nF2);
-    //
-    // rebuild pave block maps of face info
-    for (j = 0; j < 2; j++) {
-      Standard_Integer nF = (j == 0 ? nF1 : nF2);
-      if (!aMPassed.Add(nF))
-        continue;
-      BOPDS_FaceInfo& aFI = myDS->ChangeFaceInfo(nF);
-      BOPDS_IndexedMapOfPaveBlock* aIMPB[] = { &aFI.ChangePaveBlocksIn(),
-        &aFI.ChangePaveBlocksOn(), &aFI.ChangePaveBlocksSc() };
-      for (Standard_Integer k = 0; k < 3; k++) {
-        Standard_Integer aNbPB = aIMPB[k]->Extent(), m;
-        for (m = 1; m <= aNbPB; ++m) {
-          const Handle(BOPDS_PaveBlock)& aPB = aIMPB[k]->FindKey(m);
-          if (theEdges.Contains(aPB->Edge()))
-            break;
-        }
-        if (m <= aNbPB) {
-          BOPDS_IndexedMapOfPaveBlock aMPBCopy = *aIMPB[k];
-          aIMPB[k]->Clear();
-          for (m = 1; m <= aNbPB; ++m) {
-            const Handle(BOPDS_PaveBlock)& aPB = aMPBCopy(m);
-            if (!theEdges.Contains(aPB->Edge()))
-              aIMPB[k]->Add(aPB);
-          }
-        }
-      }
-    }
     // remove from Section pave blocks
     BOPDS_VectorOfCurve& aVNC = aFF.ChangeCurves();
     Standard_Integer aNbC = aVNC.Length();
@@ -3080,7 +3026,44 @@ void BOPAlgo_PaveFiller::RemovePaveBlocks(const TColStd_MapOfInteger theEdges)
       }
     }
   }
+
+  // 3. From Face Info
+  for (i = 0; i < myDS->NbSourceShapes(); ++i)
+  {
+    const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
+    if (aSI.ShapeType() != TopAbs_FACE)
+      continue;
+    if (!aSI.HasReference())
+      continue;
+
+    BOPDS_FaceInfo& aFI = myDS->ChangeFaceInfo(i);
+    BOPDS_IndexedMapOfPaveBlock* aIMPB[] = { &aFI.ChangePaveBlocksIn(),
+                                             &aFI.ChangePaveBlocksOn(),
+                                             &aFI.ChangePaveBlocksSc() };
+    for (Standard_Integer k = 0; k < 3; k++)
+    {
+      Standard_Integer aNbPB = aIMPB[k]->Extent(), m;
+      for (m = 1; m <= aNbPB; ++m)
+      {
+        const Handle(BOPDS_PaveBlock)& aPB = aIMPB[k]->FindKey(m);
+        if (theEdges.Contains(aPB->Edge()))
+          break;
+      }
+      if (m <= aNbPB)
+      {
+        BOPDS_IndexedMapOfPaveBlock aMPBCopy = *aIMPB[k];
+        aIMPB[k]->Clear();
+        for (m = 1; m <= aNbPB; ++m)
+        {
+          const Handle(BOPDS_PaveBlock)& aPB = aMPBCopy(m);
+          if (!theEdges.Contains(aPB->Edge()))
+            aIMPB[k]->Add(aPB);
+        }
+      }
+    }
+  }
 }
+
 //=======================================================================
 //function : ToleranceFF
 //purpose  : Computes the TolFF according to the tolerance value and 
@@ -3507,3 +3490,49 @@ void BOPAlgo_PaveFiller::RemoveMicroSectionEdges
   if (aSEPBMap.Extent() != theMSCPB.Extent())
     theMSCPB = aSEPBMap;
 }
+
+//=======================================================================
+//function : RemoveMicroEdges
+//purpose  : 
+//=======================================================================
+void BOPAlgo_PaveFiller::RemoveMicroEdges()
+{
+  // Fence map
+  BOPDS_MapOfPaveBlock aMPBFence;
+  // Resulting map of micro edges
+  TColStd_MapOfInteger aMicroEdges;
+  // Check all pave blocks from the pool to find the micro edges
+  BOPDS_VectorOfListOfPaveBlock& aPBP = myDS->ChangePaveBlocksPool();
+  Standard_Integer aNbPBP = aPBP.Length();
+  for (Standard_Integer i = 0; i < aNbPBP; ++i)
+  {
+    BOPDS_ListOfPaveBlock& aLPB = aPBP(i);
+    if (aLPB.Extent() < 2)
+      // No splits
+      continue;
+
+    if (myDS->ShapeInfo(aLPB.First()->OriginalEdge()).HasFlag())
+      continue;
+
+    BOPDS_ListOfPaveBlock::Iterator it(aLPB);
+    for (; it.More(); it.Next())
+    {
+      const Handle(BOPDS_PaveBlock)& aPB = it.Value();
+      Handle(BOPDS_PaveBlock) aPBR = myDS->RealPaveBlock(aPB);
+
+      if (aMPBFence.Add(aPBR))
+      {
+        Standard_Integer nV1, nV2;
+        aPBR->Indices(nV1, nV2);
+        if (nV1 == nV2)
+        {
+          // Check if it has the valid range
+          FillShrunkData(aPBR);
+          if (!aPBR->HasShrunkData())
+            aMicroEdges.Add(aPBR->Edge());
+        }
+      }
+    }
+  }
+  RemovePaveBlocks(aMicroEdges);
+}
index 2e542e8..ed20f9a 100755 (executable)
@@ -1,4 +1,3 @@
-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 4e11daf..fc77452 100755 (executable)
@@ -1,6 +1,3 @@
-puts "TODO OCC25917 ALL: Faulty shapes in variables faulty_1 to faulty_"
-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)"
@@ -17,9 +14,9 @@ checkshape b2
 
 bfuse result b1 b2
 
-checknbshapes result -vertex 66 -edge 107
+checknbshapes result -shell 1 -solid 1
 
-checkprops result -s 229.516 
+checkprops result -v -111.22 -s 229.516 
 checkshape result
 checkview -display result -2d -path ${imagedir}/${test_image}.png
 
diff --git a/tests/bugs/modalg_7/bug30092 b/tests/bugs/modalg_7/bug30092
new file mode 100644 (file)
index 0000000..cfa5f88
--- /dev/null
@@ -0,0 +1,32 @@
+puts "========"
+puts "OCC30092: Modeling Algorithms - Invalid result of Section operation"
+puts "========"
+puts ""
+
+
+restore [locate_data_file bug26795_c.brep] c
+explode c f
+
+# modify c_2 face
+line l 20004.7983876926 2164.22470816234 210.858020395251 -0.716336050762455 0.65536108806844 0.239508886314894
+mkedge e l -0.2 0.2
+settolerance e 0.04
+
+bclearobjects
+bcleartools
+baddobjects c_2
+baddtools e
+bfillds
+bsplit c_2
+
+# perform section operation
+bclearobjects
+bcleartools
+baddobjects e c_1
+baddtools c_2
+bfillds
+bbop result 4
+
+checkshape result
+checknbshapes result -vertex 5 -edge 4
+checkprops result -l 1250.44