From 88af392026f1c4d2e02ecbffa2c35c0d3ef029c3 Mon Sep 17 00:00:00 2001
From: emv <emv@opencascade.com>
Date: Fri, 15 Sep 2017 09:31:40 +0300
Subject: [PATCH] 0029073: Regression: General Cut produces invalid shape

Boolean Operations:
1. Face/Face intersection post treatment - Unify vertices put on the section curves, which were rejected as existing ones, with the vertices of edges by which these section curves have been rejected.

2. Extend Warnings Reporting system of Boolean operations with the new warnings:
- BOPAlgo_AlertIntersectionOfPairOfShapesFailed - to be added when the intersection of pair of sub-shapes of the arguments has failed;
- BOPAlgo_AlertBuildingPCurveFailed - to be added when the building of the 2D curve of the edge on face has failed;
- BOPAlgo_AlertAcquiredSelfIntersection - to be added when the positioning and tolerances of the arguments leads to creation of self-interfered shapes.

These new warnings allow completing the operation even if intersection of some of the sub-shapes or building of some of the PCurves has failed. Moreover, they allow getting the pairs of sub-shapes on which the intersection/projection has failed, providing the user ability to analyze the intersection results.

Note that if some of these warnings appear, the result of the operation should be carefully analyzed for validity.

3. Print messages for the Warnings/Errors met during checking of the shape on self-intersection ("bopcheck" command).
---
 adm/cmake/occt_resources.cmake        |  1 +
 src/BOPAlgo/BOPAlgo.msg               |  9 ++++
 src/BOPAlgo/BOPAlgo_Alerts.hxx        | 10 +++++
 src/BOPAlgo/BOPAlgo_BOPAlgo_msg.pxx   | 11 ++++-
 src/BOPAlgo/BOPAlgo_PaveFiller.hxx    | 19 +++++---
 src/BOPAlgo/BOPAlgo_PaveFiller_11.cxx | 10 +++--
 src/BOPAlgo/BOPAlgo_PaveFiller_2.cxx  | 34 ++++++++++++++-
 src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx  | 17 +++++++-
 src/BOPAlgo/BOPAlgo_PaveFiller_4.cxx  | 19 +++++++-
 src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx  | 15 ++++++-
 src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx  | 49 +++++++++++++++++++--
 src/BOPAlgo/BOPAlgo_PaveFiller_7.cxx  | 62 +++++++++++++++++++--------
 src/BOPTest/BOPTest_CheckCommands.cxx |  2 +
 tests/bugs/modalg_7/bug25879          |  3 +-
 tests/bugs/modalg_7/bug29073          | 34 +++++++++++++++
 tests/bugs/moddata_3/bug25693_1       |  3 +-
 tests/bugs/moddata_3/bug25693_2       |  6 ++-
 17 files changed, 260 insertions(+), 44 deletions(-)
 create mode 100644 tests/bugs/modalg_7/bug29073

diff --git a/adm/cmake/occt_resources.cmake b/adm/cmake/occt_resources.cmake
index 7a88051c7..d51df4d36 100644
--- a/adm/cmake/occt_resources.cmake
+++ b/adm/cmake/occt_resources.cmake
@@ -68,6 +68,7 @@ FILE_TO_LIST ("adm/RESOURCES" RESOURCES)
 foreach (CurrentResource ${RESOURCES})
   get_filename_component (CurrentResource_FileName "${CurrentResource}" NAME)
   if ("${CurrentResource_FileName}" STREQUAL TObj.msg OR
+      "${CurrentResource_FileName}" STREQUAL BOPAlgo.msg OR
       "${CurrentResource_FileName}" STREQUAL Units.dat OR
       "${CurrentResource}" STREQUAL XSMessage OR
       "${CurrentResource}" STREQUAL SHMessage OR
diff --git a/src/BOPAlgo/BOPAlgo.msg b/src/BOPAlgo/BOPAlgo.msg
index 67350fca8..673a39ec4 100644
--- a/src/BOPAlgo/BOPAlgo.msg
+++ b/src/BOPAlgo/BOPAlgo.msg
@@ -67,3 +67,12 @@ Warning: Removal of internal boundaries among Faces has failed
 
 .BOPAlgo_AlertRemovalOfIBForEdgesFailed
 Warning: Removal of internal boundaries among Edges has failed
+
+.BOPAlgo_AlertIntersectionOfPairOfShapesFailed
+Warning: Intersection of pair of shapes has failed
+
+.BOPAlgo_AlertBuildingPCurveFailed
+Warning: Building 2D curve of edge on face has failed
+
+.BOPAlgo_AlertAcquiredSelfIntersection
+Warning: Some sub-shapes of some of the argument become connected through other shapes and the argument became self-interfered
diff --git a/src/BOPAlgo/BOPAlgo_Alerts.hxx b/src/BOPAlgo/BOPAlgo_Alerts.hxx
index 02cec15f8..04ce9c7b4 100644
--- a/src/BOPAlgo/BOPAlgo_Alerts.hxx
+++ b/src/BOPAlgo/BOPAlgo_Alerts.hxx
@@ -78,4 +78,14 @@ DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertShellSplitterFailed)
 //! Some edges are too small and have no valid range
 DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertTooSmallEdge)
 
+//! Intersection of pair of shapes has failed
+DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertIntersectionOfPairOfShapesFailed)
+
+//! Building 2D curve of edge on face has failed
+DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertBuildingPCurveFailed)
+
+//! Some sub-shapes of some of the argument become connected through
+//! other shapes and the argument became self-interfered
+DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertAcquiredSelfIntersection)
+
 #endif // _BOPAlgo_Alerts_HeaderFile
diff --git a/src/BOPAlgo/BOPAlgo_BOPAlgo_msg.pxx b/src/BOPAlgo/BOPAlgo_BOPAlgo_msg.pxx
index c63a53875..feec77880 100644
--- a/src/BOPAlgo/BOPAlgo_BOPAlgo_msg.pxx
+++ b/src/BOPAlgo/BOPAlgo_BOPAlgo_msg.pxx
@@ -69,4 +69,13 @@ static const char BOPAlgo_BOPAlgo_msg[] =
   "Warning: Removal of internal boundaries among Faces has failed\n"
   "\n"
   ".BOPAlgo_AlertRemovalOfIBForEdgesFailed\n"
-  "Warning: Removal of internal boundaries among Edges has failed\n";
+  "Warning: Removal of internal boundaries among Edges has failed\n"
+  "\n"
+  ".BOPAlgo_AlertIntersectionOfPairOfShapesFailed\n"
+  "Warning: Intersection of pair of shapes has failed\n"
+  "\n"
+  ".BOPAlgo_AlertBuildingPCurveFailed\n"
+  "Warning: Building 2D curve of edge on face has failed\n"
+  "\n"
+  ".BOPAlgo_AlertAcquiredSelfIntersection\n"
+  "Warning: Some sub-shapes of some of the argument become connected through other shapes and the argument became self-interfered\n";
diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller.hxx b/src/BOPAlgo/BOPAlgo_PaveFiller.hxx
index ab79f4ec9..bd4e512fa 100644
--- a/src/BOPAlgo/BOPAlgo_PaveFiller.hxx
+++ b/src/BOPAlgo/BOPAlgo_PaveFiller.hxx
@@ -87,13 +87,19 @@ class TopoDS_Face;
 //! - *Gluing options* - allows to speed up the calculation on the special
 //!                      cases, in which some sub-shapes are coincide.<br>
 //!
-//! The algorithm returns the following Warning statuses:<br>
-//! - *BOPAlgo_AlertSelfInterferingShape* - in case some of the argument shapes are self-interfering shapes;<br>
-//! - *BOPAlgo_AlertTooSmallEdge* - in case some edges of the input shapes have no valid range;<br>
+//! The algorithm returns the following Warning statuses:
+//! - *BOPAlgo_AlertSelfInterferingShape* - in case some of the argument shapes are self-interfering shapes;
+//! - *BOPAlgo_AlertTooSmallEdge* - in case some edges of the input shapes have no valid range;
 //! - *BOPAlgo_AlertNotSplittableEdge* - in case some edges of the input shapes has such a small
-//!                         valid range so it cannot be split;<br>
+//!                                      valid range so it cannot be split;
 //! - *BOPAlgo_AlertBadPositioning* - in case the positioning of the input shapes leads to creation
-//!                      of small edges.<br>
+//!                                   of small edges;
+//! - *BOPAlgo_AlertIntersectionOfPairOfShapesFailed* - in case intersection of some of the
+//!                                                     sub-shapes has failed;
+//! - *BOPAlgo_AlertAcquiredSelfIntersection* - in case some sub-shapes of the argument become connected
+//!                                             through other shapes;
+//! - *BOPAlgo_AlertBuildingPCurveFailed* - in case building 2D curve for some of the edges
+//!                                         on the faces has failed.
 //!
 //! The algorithm returns the following Error alerts:
 //! - *BOPAlgo_AlertTooFewArguments* - in case there are no enough arguments to
@@ -290,6 +296,7 @@ protected:
                                     BOPDS_DataMapOfPaveBlockListOfPaveBlock& theDMExEdges,
                                     BOPCol_DataMapOfIntegerInteger& theDMNewSD,
                                     const BOPCol_IndexedMapOfShape& theMicroEdges,
+                                    const BOPCol_IndexedMapOfShape& theVertsOnRejectedPB,
                                     const BOPCol_BaseAllocator& theAllocator);
   
   Standard_EXPORT void FindPaveBlocks (const Standard_Integer theV, const Standard_Integer theF, BOPDS_ListOfPaveBlock& theLPB);
@@ -474,6 +481,8 @@ protected:
   //! In case self-interference is found the warning is added.
   Standard_EXPORT void CheckSelfInterference();
 
+  //! Adds the warning about failed intersection of pair of sub-shapes
+  Standard_EXPORT void AddIntersectionFailedWarning(const TopoDS_Shape& theS1, const TopoDS_Shape& theS2);
 
   BOPCol_ListOfShape myArguments;
   BOPDS_PDS myDS;
diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_11.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_11.cxx
index c8341c5dd..83faf2d12 100644
--- a/src/BOPAlgo/BOPAlgo_PaveFiller_11.cxx
+++ b/src/BOPAlgo/BOPAlgo_PaveFiller_11.cxx
@@ -112,7 +112,8 @@ void BOPAlgo_PaveFiller::CheckSelfInterference()
               }
               //
               if (aLE.Extent() > 1) {
-                // Add warning
+                // Add the acquired self-interference warning:
+                // The same common block contains several edges from one argument
                 TopoDS_Compound aWC;
                 aBB.MakeCompound(aWC);
                 //
@@ -122,7 +123,7 @@ void BOPAlgo_PaveFiller::CheckSelfInterference()
                   aBB.Add(aWC, aE1);
                 }
                 //
-                AddWarning (new BOPAlgo_AlertSelfInterferingShape (aWC));
+                AddWarning (new BOPAlgo_AlertAcquiredSelfIntersection (aWC));
               }
             }
           }
@@ -168,7 +169,8 @@ void BOPAlgo_PaveFiller::CheckSelfInterference()
     for (j = 1; j <= aNbC; ++j) {
       const BOPCol_IndexedMapOfShape& aMCS = aMCSI(j);
       if (aMCS.Extent() > 1) {
-        // Add self-interference warning
+        // Add acquired self-interference warning:
+        // Several faces from one argument contain the same vertex or edge
         TopoDS_Compound aWC;
         aBB.MakeCompound(aWC);
         //
@@ -177,7 +179,7 @@ void BOPAlgo_PaveFiller::CheckSelfInterference()
           const TopoDS_Shape& aSx = aMCS(iS);
           aBB.Add(aWC, aSx);
         }
-        AddWarning (new BOPAlgo_AlertSelfInterferingShape (aWC));
+        AddWarning (new BOPAlgo_AlertAcquiredSelfIntersection (aWC));
       }
     }
   }
diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_2.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_2.cxx
index c4966683d..9ac5e67ae 100644
--- a/src/BOPAlgo/BOPAlgo_PaveFiller_2.cxx
+++ b/src/BOPAlgo/BOPAlgo_PaveFiller_2.cxx
@@ -17,6 +17,7 @@
 
 
 #include <BOPAlgo_PaveFiller.hxx>
+#include <BOPAlgo_Alerts.hxx>
 #include <BOPAlgo_Tools.hxx>
 #include <BOPCol_NCVector.hxx>
 #include <BOPCol_Parallel.hxx>
@@ -27,6 +28,7 @@
 #include <BOPDS_PaveBlock.hxx>
 #include <BOPDS_VectorOfInterfVE.hxx>
 #include <BOPTools_AlgoTools.hxx>
+#include <BRep_Builder.hxx>
 #include <BRep_Tool.hxx>
 #include <gp_Pnt.hxx>
 #include <IntTools_Context.hxx>
@@ -110,7 +112,16 @@ class BOPAlgo_VertexEdge : public BOPAlgo_Algo {
   //
   virtual void Perform() {
     BOPAlgo_Algo::UserBreak();
-    myFlag=myContext->ComputeVE (myV, myE, myT, myTolVNew, myFuzzyValue);
+    try
+    {
+      OCC_CATCH_SIGNALS
+
+      myFlag=myContext->ComputeVE (myV, myE, myT, myTolVNew, myFuzzyValue);
+    }
+    catch (Standard_Failure)
+    {
+      AddError(new BOPAlgo_AlertIntersectionFailed);
+    }
   };
   //
  protected:
@@ -267,6 +278,11 @@ void BOPAlgo_PaveFiller::IntersectVE
   for (i = 0; i < aNbVE; ++i) {
     const BOPAlgo_VertexEdge& aVESolver = aVVE(i);
     if (aVESolver.Flag() != 0) {
+      if (aVESolver.HasErrors())
+      {
+        // Warn about failed intersection of sub-shapes
+        AddIntersectionFailedWarning(aVESolver.Vertex(), aVESolver.Edge());
+      }
       continue;
     }
     //
@@ -491,3 +507,19 @@ void BOPAlgo_PaveFiller::SplitPaveBlocks(const BOPCol_MapOfInteger& theMEdges,
     }
   }
 }
+
+//=======================================================================
+// function: AddIntersectionFailedWarning
+// purpose: 
+//=======================================================================
+void BOPAlgo_PaveFiller::AddIntersectionFailedWarning(const TopoDS_Shape& theS1,
+                                                      const TopoDS_Shape& theS2)
+{
+  // Create the warn shape
+  TopoDS_Compound aWC;
+  BRep_Builder().MakeCompound(aWC);
+  BRep_Builder().Add(aWC, theS1);
+  BRep_Builder().Add(aWC, theS2);
+  // Add the warning
+  AddWarning(new BOPAlgo_AlertIntersectionOfPairOfShapesFailed(aWC));
+}
\ No newline at end of file
diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx
index 3a8892e0b..5db97a8af 100644
--- a/src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx
+++ b/src/BOPAlgo/BOPAlgo_PaveFiller_3.cxx
@@ -93,7 +93,16 @@ class BOPAlgo_EdgeEdge :
   //
   virtual void Perform() {
     BOPAlgo_Algo::UserBreak();
-    IntTools_EdgeEdge::Perform();
+    try
+    {
+      OCC_CATCH_SIGNALS
+
+      IntTools_EdgeEdge::Perform();
+    }
+    catch (Standard_Failure)
+    {
+      AddError(new BOPAlgo_AlertIntersectionFailed);
+    }
   }
   //
  protected:
@@ -229,7 +238,11 @@ void BOPAlgo_PaveFiller::PerformEE()
     Bnd_Box aBB1, aBB2;
     //
     BOPAlgo_EdgeEdge& anEdgeEdge=aVEdgeEdge(k);
-    if (!anEdgeEdge.IsDone()) {
+    if (!anEdgeEdge.IsDone() || anEdgeEdge.HasErrors()) {
+      // Warn about failed intersection of sub-shapes
+      const TopoDS_Shape& aE1 = myDS->Shape(anEdgeEdge.PaveBlock1()->OriginalEdge());
+      const TopoDS_Shape& aE2 = myDS->Shape(anEdgeEdge.PaveBlock2()->OriginalEdge());
+      AddIntersectionFailedWarning(aE1, aE2);
       continue;
     }
     //
diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_4.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_4.cxx
index 291edb2de..900d363bb 100644
--- a/src/BOPAlgo/BOPAlgo_PaveFiller_4.cxx
+++ b/src/BOPAlgo/BOPAlgo_PaveFiller_4.cxx
@@ -17,6 +17,7 @@
 
 
 #include <BOPAlgo_PaveFiller.hxx>
+#include <BOPAlgo_Alerts.hxx>
 #include <BOPAlgo_SectionAttribute.hxx>
 #include <BOPCol_MapOfInteger.hxx>
 #include <BOPCol_NCVector.hxx>
@@ -107,7 +108,16 @@ class BOPAlgo_VertexFace : public BOPAlgo_Algo {
   //
   virtual void Perform() {
     BOPAlgo_Algo::UserBreak();
-    myFlag=myContext->ComputeVF(myV, myF, myT1, myT2, myTolVNew, myFuzzyValue);
+    try
+    {
+      OCC_CATCH_SIGNALS
+
+      myFlag=myContext->ComputeVF(myV, myF, myT1, myT2, myTolVNew, myFuzzyValue);
+    }
+    catch (Standard_Failure)
+    {
+      AddError(new BOPAlgo_AlertIntersectionFailed);
+    }
   }
   //
  protected:
@@ -212,7 +222,12 @@ void BOPAlgo_PaveFiller::PerformVF()
     const BOPAlgo_VertexFace& aVertexFace=aVVF(k);
     // 
     iFlag=aVertexFace.Flag();
-    if (iFlag) {
+    if (iFlag != 0) {
+      if (aVertexFace.HasErrors())
+      {
+        // Warn about failed intersection of sub-shapes
+        AddIntersectionFailedWarning(aVertexFace.Vertex(), aVertexFace.Face());
+      }
       continue;
     }
     //
diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx
index 84fc6d10d..717e47892 100644
--- a/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx
+++ b/src/BOPAlgo/BOPAlgo_PaveFiller_5.cxx
@@ -103,7 +103,16 @@ class BOPAlgo_EdgeFace :
   //
   virtual void Perform() {
     BOPAlgo_Algo::UserBreak();
-    IntTools_EdgeFace::Perform();
+    try
+    {
+      OCC_CATCH_SIGNALS
+
+      IntTools_EdgeFace::Perform();
+    }
+    catch (Standard_Failure)
+    {
+      AddError(new BOPAlgo_AlertIntersectionFailed);
+    }
   }
   //
  protected:
@@ -258,7 +267,9 @@ void BOPAlgo_PaveFiller::PerformEF()
   //
   for (k=0; k < aNbEdgeFace; ++k) {
     BOPAlgo_EdgeFace& aEdgeFace=aVEdgeFace(k);
-    if (!aEdgeFace.IsDone()) {
+    if (!aEdgeFace.IsDone() || aEdgeFace.HasErrors()) {
+      // Warn about failed intersection of sub-shapes
+      AddIntersectionFailedWarning(aEdgeFace.Edge(), aEdgeFace.Face());
       continue;
     }
     //
diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx
index bbc1b35c9..dfbfe6195 100644
--- a/src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx
+++ b/src/BOPAlgo/BOPAlgo_PaveFiller_6.cxx
@@ -144,7 +144,16 @@ class BOPAlgo_FaceFace :
   //
   virtual void Perform() {
     BOPAlgo_Algo::UserBreak();
-    IntTools_FaceFace::Perform(myF1, myF2);
+    try
+    {
+      OCC_CATCH_SIGNALS
+
+      IntTools_FaceFace::Perform(myF1, myF2);
+    }
+    catch (Standard_Failure)
+    {
+      AddError(new BOPAlgo_AlertIntersectionFailed);
+    }
   }
   //
  protected:
@@ -263,10 +272,12 @@ void BOPAlgo_PaveFiller::PerformFF()
   for (k = 0; k < aNbFaceFace; ++k) {
     BOPAlgo_FaceFace& aFaceFace = aVFaceFace(k);
     aFaceFace.Indices(nF1, nF2);
-    if (!aFaceFace.IsDone()) {
+    if (!aFaceFace.IsDone() || aFaceFace.HasErrors()) {
       BOPDS_InterfFF& aFF = aFFs.Append1();
       aFF.SetIndices(nF1, nF2);
       aFF.Init(0, 0);
+      // Warn about failed intersection of faces
+      AddIntersectionFailedWarning(aFaceFace.Face1(), aFaceFace.Face2());
       continue;
     }
     //
@@ -373,6 +384,7 @@ void BOPAlgo_PaveFiller::MakeBlocks()
   BOPCol_DataMapOfIntegerListOfInteger aDMBV(100, aAllocator);
   BOPCol_DataMapIteratorOfDataMapOfIntegerReal aItMV;
   BOPCol_IndexedMapOfShape aMicroEdges(100, aAllocator);
+  BOPCol_IndexedMapOfShape aVertsOnRejectedPB;
   //
   for (i=0; i<aNbFF; ++i) {
     //
@@ -557,6 +569,19 @@ void BOPAlgo_PaveFiller::MakeBlocks()
             if (!bInBothFaces) {
               aMPBAdd.Add(aPBOut);
               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
+              // for technological vertices, which will be removed)
+              Standard_Integer nVOut1, nVOut2;
+              aPBOut->Indices(nVOut1, nVOut2);
+              if (nV1 != nVOut1 && nV1 != nVOut2 && !aMVBounds.Contains(nV1))
+              {
+                aVertsOnRejectedPB.Add(aV1);
+              }
+              if (nV2 != nVOut1 && nV2 != nVOut2 && !aMVBounds.Contains(nV2))
+              {
+                aVertsOnRejectedPB.Add(aV2);
+              }
             }
           }
           continue;
@@ -639,7 +664,7 @@ void BOPAlgo_PaveFiller::MakeBlocks()
   // 
   // post treatment
   MakeSDVerticesFF(aDMVLV, aDMNewSD);
-  PostTreatFF(aMSCPB, aDMExEdges, aDMNewSD, aMicroEdges, aAllocator);
+  PostTreatFF(aMSCPB, aDMExEdges, aDMNewSD, aMicroEdges, aVertsOnRejectedPB, aAllocator);
   if (HasErrors()) {
     return;
   }
@@ -697,6 +722,7 @@ void BOPAlgo_PaveFiller::PostTreatFF
      BOPDS_DataMapOfPaveBlockListOfPaveBlock& aDMExEdges,
      BOPCol_DataMapOfIntegerInteger& aDMNewSD,
      const BOPCol_IndexedMapOfShape& theMicroEdges,
+     const BOPCol_IndexedMapOfShape& theVertsOnRejectedPB,
      const Handle(NCollection_BaseAllocator)& theAllocator)
 {
   Standard_Integer aNbS = theMSCPB.Extent();
@@ -724,8 +750,9 @@ void BOPAlgo_PaveFiller::PostTreatFF
   BOPDS_VectorOfInterfFF& aFFs=myDS->InterfFF();
   //
   Standard_Integer aNbME = theMicroEdges.Extent();
+  Standard_Integer aNbVOnRPB = theVertsOnRejectedPB.Extent();
   // 0
-  if (aNbS==1 && (aNbME == 0)) {
+  if (aNbS==1 && (aNbME == 0) && (aNbVOnRPB == 0)) {
     const TopoDS_Shape& aS=theMSCPB.FindKey(1);
     const BOPDS_CoupleOfPaveBlocks &aCPB=theMSCPB.FindFromIndex(1);
     //
@@ -824,6 +851,20 @@ void BOPAlgo_PaveFiller::PostTreatFF
       aBB.UpdateVertex(aVerts[1], aTolV2 + aDist);
     }
   }
+
+  // Add vertices put on the real section curves to unify them with the
+  // vertices of the edges, by which these sections curves have been rejected
+  for (Standard_Integer i = 1; i <= aNbVOnRPB; ++i)
+  {
+    TopoDS_Shape aVer = theVertsOnRejectedPB(i);
+    Standard_Integer iVer = myDS->Index(aVer);
+    const Standard_Integer* pSD = aDMNewSD.Seek(iVer);
+    if (pSD)
+      aVer = myDS->Shape(*pSD);
+
+    if (anAddedSD.Add(aVer))
+      aLS.Append(aVer);
+  }
   //
   // 2 Fuse shapes
   aPF.SetProgressIndicator(myProgressIndicator);
diff --git a/src/BOPAlgo/BOPAlgo_PaveFiller_7.cxx b/src/BOPAlgo/BOPAlgo_PaveFiller_7.cxx
index bf0217599..1e91f5529 100644
--- a/src/BOPAlgo/BOPAlgo_PaveFiller_7.cxx
+++ b/src/BOPAlgo/BOPAlgo_PaveFiller_7.cxx
@@ -16,6 +16,7 @@
 // commercial license or contractual agreement.
 
 #include <BOPAlgo_PaveFiller.hxx>
+#include <BOPAlgo_Alerts.hxx>
 #include <BOPAlgo_SectionAttribute.hxx>
 #include <BOPAlgo_Tools.hxx>
 #include <BOPCol_IndexedMapOfShape.hxx>
@@ -241,28 +242,37 @@ class BOPAlgo_MPC : public BOPAlgo_Algo  {
   }
   //
   virtual void Perform() {
-    Standard_Integer iErr;
-    //
-    iErr=1;
-    if (!myEz.IsNull()) {
-      TopoDS_Edge aSpz;
+    try
+    {
+      OCC_CATCH_SIGNALS
+
+      Standard_Integer iErr;
       //
-      BOPTools_AlgoTools::MakeSplitEdge(myEz,myV1, myT1, 
-                                        myV2, myT2, aSpz);
+      iErr=1;
+      if (!myEz.IsNull()) {
+        TopoDS_Edge aSpz;
+        //
+        BOPTools_AlgoTools::MakeSplitEdge(myEz,myV1, myT1, 
+                                          myV2, myT2, aSpz);
+        //
+        iErr=
+          BOPTools_AlgoTools2D::AttachExistingPCurve(aSpz, 
+                                                     myE, 
+                                                     myF, 
+                                                     myContext);
+      }
       //
-      iErr=
-        BOPTools_AlgoTools2D::AttachExistingPCurve(aSpz, 
-                                                   myE, 
-                                                   myF, 
-                                                   myContext);
-    }
-    //
-    if (iErr) { 
-      BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(myE, myF, myContext);
+      if (iErr) { 
+        BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(myE, myF, myContext);
+      }
+      // 
+      if (myFlag) {
+        UpdateVertices(myE, myF);
+      }
     }
-    // 
-    if (myFlag) {
-      UpdateVertices(myE, myF);
+    catch (Standard_Failure)
+    {
+      AddError(new BOPAlgo_AlertBuildingPCurveFailed(TopoDS_Shape()));
     }
   }
   //
@@ -676,6 +686,20 @@ void BOPAlgo_PaveFiller::MakePCurves()
   //======================================================
   BOPAlgo_MPCCnt::Perform(myRunParallel, aVMPC, myContext);
   //======================================================
+
+  // Add warnings of the failed projections
+  Standard_Integer aNb = aVMPC.Extent();
+  for (i = 0; i < aNb; ++i)
+  {
+    if (aVMPC(i).HasErrors())
+    {
+      TopoDS_Compound aWC;
+      BRep_Builder().MakeCompound(aWC);
+      BRep_Builder().Add(aWC, aVMPC(i).Edge());
+      BRep_Builder().Add(aWC, aVMPC(i).Face());
+      AddWarning(new BOPAlgo_AlertBuildingPCurveFailed(aWC));
+    }
+  }
 }
 //=======================================================================
 //function : UpdateVertices
diff --git a/src/BOPTest/BOPTest_CheckCommands.cxx b/src/BOPTest/BOPTest_CheckCommands.cxx
index 618e86cda..77d5cd2a4 100644
--- a/src/BOPTest/BOPTest_CheckCommands.cxx
+++ b/src/BOPTest/BOPTest_CheckCommands.cxx
@@ -235,6 +235,8 @@ Standard_Integer bopcheck (Draw_Interpretor& di,
   //
   aTimer.Stop();
   //
+  BOPTest::ReportAlerts(aChecker);
+  //
   iErr=aChecker.HasErrors();
   //
   const BOPDS_DS& aDS=*(aChecker.PDS());
diff --git a/tests/bugs/modalg_7/bug25879 b/tests/bugs/modalg_7/bug25879
index bb45244df..e344c396a 100755
--- a/tests/bugs/modalg_7/bug25879
+++ b/tests/bugs/modalg_7/bug25879
@@ -13,7 +13,8 @@ explode Box E
 
 blend Fillet Box 1 Box_1 1 Box_2 1 Box_3 1 Box_4 1 Box_5 1 Box_6 1 Box_7 1 Box_8 1 Box_9 1 Box_10 1 Box_11 1 Box_12
 
-if { [regexp "There were errors during the operation, so the list may be incomplete" [bopcheck Fillet]] == 1 } {
+set bug_info [string trim [bopcheck Fillet]]
+if {$bug_info != "This shape seems to be OK."} {
     puts "Error : result of blend fails the bopcheck"
 }
 
diff --git a/tests/bugs/modalg_7/bug29073 b/tests/bugs/modalg_7/bug29073
new file mode 100644
index 000000000..e13beca62
--- /dev/null
+++ b/tests/bugs/modalg_7/bug29073
@@ -0,0 +1,34 @@
+puts "======="
+puts "0029073"
+puts "======="
+puts ""
+##################################################
+# Regression: General Cut produces invalid shape
+##################################################
+
+brestore [locate_data_file bug29073_M6.brep] b1
+brestore [locate_data_file bug29073_Shell.brep] b2
+
+bclearobjects
+bcleartools
+baddobjects b1
+baddtools b2
+bfillds
+
+# check the result of SECTION
+bbop rsec 4
+checknbshapes rsec -edge 1 -vertex 2
+
+# check the result of GF
+bbuild rgf
+checkshape rgf
+checkprops rgf -s 163.708 -v 115.912
+checknbshapes rgf -wire 25 -face 24 -shell 3 -solid 1
+
+# check the CUT
+bbop result 3
+checkshape result
+checkprops result -s 0.000713987
+checknbshapes result -wire 1 -face 1
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/bugs/moddata_3/bug25693_1 b/tests/bugs/moddata_3/bug25693_1
index de7953d46..86d1aebbb 100755
--- a/tests/bugs/moddata_3/bug25693_1
+++ b/tests/bugs/moddata_3/bug25693_1
@@ -10,7 +10,8 @@ puts ""
 
 restore [locate_data_file bug25693_path3035.brep] result
 
-if { [regexp "There were errors during the operation, so the list may be incomplete" [bopcheck result]] == 1 } {
+set bug_info [string trim [bopcheck result]]
+if {$bug_info != "This shape seems to be OK."} {
     puts "Error : Wire of BSplines fails bopcheck"
 }
 
diff --git a/tests/bugs/moddata_3/bug25693_2 b/tests/bugs/moddata_3/bug25693_2
index 6b3bfb1d5..cfc7a0e05 100755
--- a/tests/bugs/moddata_3/bug25693_2
+++ b/tests/bugs/moddata_3/bug25693_2
@@ -12,11 +12,13 @@ restore [locate_data_file bug25693_path3039.brep] path3039
 
 prism Extrude_path3039 path3039 0 0 50
 
-if { [regexp "There were errors during the operation, so the list may be incomplete" [bopcheck path3039]] == 1 } {
+set log1 [string trim [bopcheck path3039]]
+if {$log1 != "This shape seems to be OK."} {
     puts "Error : bad shape"
 }
 
-if { [regexp "There were errors during the operation, so the list may be incomplete" [bopcheck Extrude_path3039]] == 1 } {
+set log2 [string trim [bopcheck Extrude_path3039]]
+if {$log2 != "This shape seems to be OK."} {
     puts "Error : Wire of BSplines fails bopcheck"
 }
 
-- 
GitLab