0029580: Regression: invalid result of BOP Fuse
authoremv <emv@opencascade.com>
Thu, 15 Mar 2018 14:02:46 +0000 (17:02 +0300)
committerbugmaster <bugmaster@opencascade.com>
Tue, 20 Mar 2018 12:18:16 +0000 (15:18 +0300)
Boolean Operation - avoid creation of INTERNAL solid from unclassified faces in Solid Builder algorithm.
Instead warn the user that some of the faces have been unclassified and not used for solids creation.

Adjustment of the test cases.
Test cases for the issue.

17 files changed:
dox/dev_guides/upgrade/upgrade.md
src/BOPAlgo/BOPAlgo.msg
src/BOPAlgo/BOPAlgo_Alerts.hxx
src/BOPAlgo/BOPAlgo_BOP.cxx
src/BOPAlgo/BOPAlgo_BOPAlgo_msg.pxx
src/BOPAlgo/BOPAlgo_BuilderSolid.cxx
src/BOPAlgo/BOPAlgo_BuilderSolid.hxx
src/BOPAlgo/BOPAlgo_Builder_3.cxx
src/BOPAlgo/BOPAlgo_CellsBuilder.cxx
src/BOPAlgo/BOPAlgo_MakerVolume.cxx
src/BOPAlgo/BOPAlgo_Tools.cxx
tests/boolean/bcut_complex/F2
tests/bugs/modalg_6/bug26789_1
tests/bugs/modalg_7/bug25983_1 [copied from tests/bugs/modalg_7/bug25983 with 63% similarity]
tests/bugs/modalg_7/bug25983_2 [moved from tests/bugs/modalg_7/bug25983 with 77% similarity]
tests/bugs/modalg_7/bug29580_1 [new file with mode: 0644]
tests/bugs/modalg_7/bug29580_2 [new file with mode: 0644]

index 450b744..6742c1e 100644 (file)
@@ -1552,3 +1552,11 @@ Since new version, the method BRepAdaptor_CompCurve::IsPeriodic() will always re
 
 Interfaces of the following methods have been changed: IntPatch_WLineTool::ComputePurgedWLine(...), IntPatch_PrmPrmIntersection::Perform(...), IntPatch_Intersection::Perform(...), IntPatch_Intersection::ParamParamPerfom(...), IntPatch_Intersection::GeomGeomPerfom(...). Please see documentation about corresponding methods.
 
+@subsection upgrade_730_BuilderSolid Boolean Operations - Solid Builder algorithm
+
+Previously, the unclassified faces of *BOPAlgo_BuilderSolid* algorithm (the faces which have not been used for solids creation and located outside of all created solids) have been used to form an additional solid (not closed one) with INTERNAL orientation.
+Since new version, these unclassified faces are no longer added into resulting solids. Instead, the @ref occt_algorithms_ers "warning" containing these faces appears.
+
+The following public methods of the *BOPAlgo_BuilderSolid* class have been removed as excessive:
+* void SetSolid(const TopoDS_Solid& theSolid);
+* const TopoDS_Solid& Solid() const;
index e6c22a3..72c842f 100644 (file)
@@ -88,3 +88,6 @@ Error: No faces have been found for removal
 
 .BOPAlgo_AlertRemoveFeaturesFailed
 Error: The Feature Removal algorithm has failed
+
+.BOPAlgo_AlertSolidBuilderUnusedFaces
+Warning: Some of the faces passed to the Solid Builder algorithm have not been classified and not used for solids creation
index 806184d..7a4f927 100644 (file)
@@ -100,4 +100,8 @@ DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnableToRemoveTheFeature)
 //! The Feature Removal algorithm has failed
 DEFINE_SIMPLE_ALERT(BOPAlgo_AlertRemoveFeaturesFailed)
 
+//! Some of the faces passed to the Solid Builder algorithm have not been classified
+//! and not used for solids creation
+DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertSolidBuilderUnusedFaces)
+
 #endif // _BOPAlgo_Alerts_HeaderFile
index 1734329..3d1271c 100644 (file)
@@ -1019,16 +1019,19 @@ void BOPAlgo_BOP::BuildSolid()
   BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
   if (aSFS.Extent()) {
     // Build solids from set of faces
-    BOPAlgo_BuilderSolid aSB;
-    aSB.SetContext(myContext);
-    aSB.SetShapes(aSFS);
-    aSB.Perform();
-    if (aSB.HasErrors()) {
+    BOPAlgo_BuilderSolid aBS;
+    aBS.SetContext(myContext);
+    aBS.SetShapes(aSFS);
+    aBS.Perform();
+    if (aBS.HasErrors()) {
       AddError (new BOPAlgo_AlertSolidBuilderFailed); // SolidBuilder failed
       return;
     }
+
+    myReport->Merge(aBS.GetReport());
+
     // new solids
-    const TopTools_ListOfShape& aLSR = aSB.Areas();
+    const TopTools_ListOfShape& aLSR = aBS.Areas();
     //
     // add new solids to result
     aItLS.Initialize(aLSR);
index 6d3ff38..6cd2187 100644 (file)
@@ -90,4 +90,7 @@ static const char BOPAlgo_BOPAlgo_msg[] =
   "Error: No faces have been found for removal\n"
   "\n"
   ".BOPAlgo_AlertRemoveFeaturesFailed\n"
-  "Error: The Feature Removal algorithm has failed\n";
+  "Error: The Feature Removal algorithm has failed\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";
index d9e6241..bcff591 100644 (file)
@@ -103,22 +103,6 @@ BOPAlgo_BuilderSolid::~BOPAlgo_BuilderSolid()
 {
 }
 //=======================================================================
-//function : SetSolid 
-//purpose  : 
-//=======================================================================
-void BOPAlgo_BuilderSolid::SetSolid(const TopoDS_Solid& aS)
-{
-  mySolid=aS;
-}
-//=======================================================================
-//function : Solid 
-//purpose  : 
-//=======================================================================
-const TopoDS_Solid& BOPAlgo_BuilderSolid::Solid()const
-{
-  return mySolid;
-}
-//=======================================================================
 //function : Perform
 //purpose  : 
 //=======================================================================
@@ -674,8 +658,10 @@ void BOPAlgo_BuilderSolid::PerformInternalShapes()
     }
   }
 
-  // Make solid from the unused faces (if any)
+  // Find all unclassified faces and warn the user about them.
+  // Do not put such faces into result as they will form not closed solid.
   TopTools_IndexedMapOfShape aMFUnUsed;
+
   for (i = 1; i <= aNbF; ++i)
   {
     const TopoDS_Shape& aF = aMFs(i);
@@ -685,24 +671,21 @@ void BOPAlgo_BuilderSolid::PerformInternalShapes()
 
   if (aMFUnUsed.Extent())
   {
-    TopoDS_Solid aSolid;
-    aBB.MakeSolid(aSolid);
-    //
     TopTools_ListOfShape aLSI;
     MakeInternalShells(aMFUnUsed, aLSI);
-    //
-    aItLS.Initialize(aLSI);
-    for (; aItLS.More(); aItLS.Next())
-    {
-      const TopoDS_Shape& aSI = aItLS.Value();
-      aBB.Add (aSolid, aSI);
 
-      Bnd_Box aBox;
-      BRepBndLib::Add(aSolid, aBox);
-      myBoxes.Bind(aSolid, aBox);
+    TopoDS_Shape aWShape;
+    if (aLSI.Extent() == 1)
+      aWShape = aLSI.First();
+    else
+    {
+      aBB.MakeCompound(TopoDS::Compound(aWShape));
+      aItLS.Initialize(aLSI);
+      for (; aItLS.More(); aItLS.Next())
+        aBB.Add(aWShape, aItLS.Value());
     }
-    myAreas.Append(aSolid);
-  }
+
+    AddWarning(new BOPAlgo_AlertSolidBuilderUnusedFaces(aWShape));  }
 }
 //=======================================================================
 //function : MakeInternalShells
index b665e3e..756d186 100644 (file)
 #include <Standard_DefineAlloc.hxx>
 #include <Standard_Handle.hxx>
 
-#include <TopoDS_Solid.hxx>
 #include <BOPAlgo_BuilderArea.hxx>
 #include <NCollection_BaseAllocator.hxx>
 #include <TopTools_DataMapOfShapeBox.hxx>
-class TopoDS_Solid;
 
 
-//! The algorithm to build solids from set of faces
+//! Solid Builder is the algorithm for building solids from set of faces.
+//! The given faces should be non-intersecting, i.e. all coinciding parts
+//! of the faces should be shared among them.
+//!
+//! The algorithm performs the following steps to build the solids:
+//! 1. Find:
+//!    - faces orientated INTERNAL;
+//!    - alone faces given twice with different orientation;
+//! 2. Build all possible closed shells from the rest of the faces
+//!    (*BOPAlgo_ShellSplitter* is used for that);
+//! 3. Classify the obtained shells on the Holes and Growths;
+//! 4. Build solids from the Growth shells, put Hole shells into closest Growth solids;
+//! 5. Classify all unused faces relatively created solids and put them as internal
+//!    shells into the closest solids;
+//! 6. Find all unclassified faces, i.e. faces outside of all created solids,
+//!    make internal shells from them and put these shells into a warning.
+//!
+//! It is possible to avoid all internal shells in the resulting solids.
+//! For that it is necessary to use the method SetAvoidInternalShapes(true)
+//! of the base class. In this case the steps 5 and 6 will not be performed at all.
+//!
+//! The algorithm may return the following warnings:
+//! - *BOPAlgo_AlertShellSplitterFailed* in case the ShellSplitter algorithm has failed;
+//! - *BOPAlgo_AlertSolidBuilderUnusedFaces* in case there are some faces outside of
+//!   created solids left.
+//!
+//! Example of usage of the algorithm:
+//! ~~~~
+//! const TopTools_ListOfShape& aFaces = ...;     // Faces to build the solids
+//! Standard_Boolean isAvoidInternals = ...;      // Flag which defines whether to create the internal shells or not
+//! BOPAlgo_BuilderSolid aBS;                     // Solid Builder tool
+//! aBS.SetShapes(aFaces);                        // Set the faces
+//! aBS.SetAvoidInternalShapes(isAvoidInternals); // Set the AvoidInternalShapesFlag
+//! aBS.Perform();                                // Perform the operation
+//! if (!aBS.IsDone())                            // Check for the errors
+//! {
+//!   // error treatment
+//!   Standard_SStream aSStream;
+//!   aBS.DumpErrors(aSStream);
+//!   return;
+//! }
+//! if (aBS.HasWarnings())                        // Check for the warnings
+//! {
+//!   // warnings treatment
+//!   Standard_SStream aSStream;
+//!   aBS.DumpWarnings(aSStream);
+//! }
+//!
+//! const TopTools_ListOfShape& aSolids = aBS.Areas(); // Obtaining the result solids
+//! ~~~~
+//!
 class BOPAlgo_BuilderSolid  : public BOPAlgo_BuilderArea
 {
 public:
 
   DEFINE_STANDARD_ALLOC
 
-  
+public: //! @name Constructors
+
+  //! Empty constructor
   Standard_EXPORT BOPAlgo_BuilderSolid();
-Standard_EXPORT virtual ~BOPAlgo_BuilderSolid();
-  
+  Standard_EXPORT virtual ~BOPAlgo_BuilderSolid();
+
+  //! Constructor with allocator
   Standard_EXPORT BOPAlgo_BuilderSolid(const Handle(NCollection_BaseAllocator)& theAllocator);
-  
-  //! Sets the source solid <theSolid>
-  Standard_EXPORT void SetSolid (const TopoDS_Solid& theSolid);
-  
-  //! Returns the source solid
-  Standard_EXPORT const TopoDS_Solid& Solid() const;
-  
-  //! Performs the algorithm
+
+public: //! @name Performing the operation
+
+  //! Performs the construction of the solids from the given faces
   Standard_EXPORT virtual void Perform() Standard_OVERRIDE;
 
-  //! Returns the map of solid/box pairs
+public: //! @name Getting the bounding boxes of the created solids
+
+  //! For classification purposes the algorithm builds the bounding boxes
+  //! for all created solids. This method returns the data map of solid - box pairs.
   const TopTools_DataMapOfShapeBox& GetBoxesMap() const
   {
     return myBoxes;
   }
 
-protected:
-  
-  //! Collect the faces that
-  //! a) are internal
-  //! b) are the same and have different orientation
+protected: //! @name Protected methods performing the operation
+
+  //! Collect the faces:
+  //! - with INTERNAL orientation;
+  //! - that are alone but given twice with different orientation.
+  //! These faces will be put into the map *myShapesToAvoid* and will be
+  //! avoided in shells construction, but will be classified later on.
   Standard_EXPORT virtual void PerformShapesToAvoid() Standard_OVERRIDE;
-  
-  //! Build draft shells
-  //! a)myLoops - draft shells that consist of
-  //! boundary faces
-  //! b)myLoopsInternal - draft shells that contains
-  //! inner faces
-  Standard_EXPORT virtual void PerformLoops() Standard_OVERRIDE;
-  
-  //! Build draft solids that contains boundary faces
-  Standard_EXPORT virtual void PerformAreas() Standard_OVERRIDE;
-  
-  //! Build finalized solids with internal shells
-  Standard_EXPORT virtual void PerformInternalShapes() Standard_OVERRIDE;
 
+  //! Build all possible closed shells from the given faces.
+  //! The method fills the following maps:
+  //! - myLoops - Created closed shells;
+  //! - myLoopsInternal - The shells created from unused faces.
+  Standard_EXPORT virtual void PerformLoops() Standard_OVERRIDE;
 
-  TopoDS_Solid mySolid;
+  //! Classifies the created shells on the Holes and Growths.
+  //! Creates the solids from the Growths shells.
+  //! Puts the Hole shells into the closest Growths solids.
+  Standard_EXPORT virtual void PerformAreas() Standard_OVERRIDE;
 
+  //! Classifies the unused faces relatively the created solids.
+  //! Puts the classified faces into the closest solids as internal shells.
+  //! Warns the user about unclassified faces if any.
+  Standard_EXPORT virtual void PerformInternalShapes() Standard_OVERRIDE;
 
 private:
 
index f3f9c7d..f7763d3 100644 (file)
@@ -329,10 +329,28 @@ void BOPAlgo_Builder::BuildDraftSolid(const TopoDS_Shape& theSolid,
 }
 
 //=======================================================================
+
+//=======================================================================
+//class : BOPAlgo_SplitSolid
+//purpose  : Auxiliary class to extend the BOPAlgo_BuilderSolid with the solid to split
+//=======================================================================
+class BOPAlgo_SplitSolid : public BOPAlgo_BuilderSolid
+{
+public:
+  //! Sets the solid
+  void SetSolid(const TopoDS_Solid& theSolid) { mySolid = theSolid; }
+
+  //! Returns the solid
+  const TopoDS_Solid& Solid() const { return mySolid; }
+
+private:
+  TopoDS_Solid mySolid; //!< Solid to split
+};
+
 // Vector of Solid Builders
-typedef NCollection_Vector<BOPAlgo_BuilderSolid> BOPAlgo_VectorOfBuilderSolid;
+typedef NCollection_Vector<BOPAlgo_SplitSolid> BOPAlgo_VectorOfBuilderSolid;
 // Functors to split solids
-typedef BOPTools_Functor<BOPAlgo_BuilderSolid,
+typedef BOPTools_Functor<BOPAlgo_SplitSolid,
                        BOPAlgo_VectorOfBuilderSolid> BOPAlgo_BuilderSolidFunctor;
 //
 typedef BOPTools_Cnt<BOPAlgo_BuilderSolidFunctor,
@@ -428,7 +446,7 @@ void BOPAlgo_Builder::BuildSplitSolids
     }
     //
     // 1.3 Build new solids
-    BOPAlgo_BuilderSolid& aBS=aVBS.Appended();
+    BOPAlgo_SplitSolid& aBS=aVBS.Appended();
     aBS.SetSolid(aSolid);
     aBS.SetShapes(aSFS);
     aBS.SetRunParallel(myRunParallel);
@@ -445,8 +463,9 @@ void BOPAlgo_Builder::BuildSplitSolids
   //
   for (k = 0; k < aNbBS; ++k)
   {
-    BOPAlgo_BuilderSolid& aBS = aVBS(k);
+    BOPAlgo_SplitSolid& aBS = aVBS(k);
     aSolidsIm.Add(aBS.Solid(), aBS.Areas());
+    myReport->Merge(aBS.GetReport());
   }
   //
   // Add new solids to images map
index f9c33b6..7b1c928 100644 (file)
@@ -922,6 +922,8 @@ Standard_Boolean BOPAlgo_CellsBuilder::RemoveInternals(const TopTools_ListOfShap
         continue;
       }
       //
+      myReport->Merge(aBS.GetReport());
+      //
       TopoDS_Solid& aSNew = *(TopoDS_Solid*)&aBS.Areas().First();
       //
       // put all internal parts into new solid
index 27748d7..21c2048 100644 (file)
@@ -254,7 +254,6 @@ void BOPAlgo_MakerVolume::BuildSolids(TopTools_ListOfShape& theLSR)
   //
   BOPAlgo_BuilderSolid aBS;
   //
-  aBS.SetSolid(mySBox);
   aBS.SetShapes(myFaces);
   aBS.SetRunParallel(myRunParallel);
   aBS.SetAvoidInternalShapes(myAvoidInternalShapes);
@@ -265,6 +264,8 @@ void BOPAlgo_MakerVolume::BuildSolids(TopTools_ListOfShape& theLSR)
     return;
   }
   //
+  myReport->Merge(aBS.GetReport());
+  //
   theLSR = aBS.Areas();
 }
 
index 1e61849..ac65629 100644 (file)
@@ -1491,8 +1491,8 @@ void BOPAlgo_FillIn3DParts::MakeConnexityBlock(const TopoDS_Face& theFStart,
       myItW.Initialize(aW);
       for (; myItW.More(); myItW.Next())
       {
-        const TopoDS_Shape& aE = myItW.Value();
-        if (theMEAvoid.Contains(aE))
+        const TopoDS_Edge& aE = TopoDS::Edge(myItW.Value());
+        if (theMEAvoid.Contains(aE) || BRep_Tool::Degenerated(aE))
         {
           if (theFaceToClassify.IsNull())
             theFaceToClassify = TopoDS::Face(aF);
index 5ca5836..7aa2f6f 100644 (file)
@@ -1,12 +1,10 @@
 # Original bug : buc60127
 # Date : 18mar98
 
-puts "TODO #22911 ALL: Faulty shapes in variables faulty_1 to faulty_"
-puts "TODO #22911 ALL: Error : The area of result shape is"
+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
 
 bcut result part tool
 checkprops result -s 0
-checkview -display result -2d -s -otherwise { part tool } -path ${imagedir}/${test_image}.png
index c5dddec..c1bb6f2 100644 (file)
@@ -1,8 +1,6 @@
 puts "TODO 0026789 ALL: Error : The area of result shape is"
 puts "TODO 0026789 ALL: Error : The volume of result shape is"
-puts "TODO 0026789 ALL: Error :  is WRONG because number of SOLID entities in shape"
-puts "TODO 0026789 ALL: Error :  is WRONG because number of SHELL entities in shape"
-puts "TODO 0026789 ALL: Faulty shapes in variables faulty_"
+puts "TODO 0026789 ALL: Error :  is WRONG because number of"
 
 puts "========"
 puts "OCC26789"
similarity index 63%
copy from tests/bugs/modalg_7/bug25983
copy to tests/bugs/modalg_7/bug25983_1
index 9eb515c..9d5204f 100644 (file)
@@ -1,4 +1,6 @@
-puts "TODO OCC25983 ALL: Faulty shapes in variables faulty_1 to faulty_"
+puts "TODO OCC25983 ALL: Error :  is WRONG because number of"
+puts "TODO OCC25983 ALL: Error : The area of result shape is"
+puts "TODO OCC25983 ALL: Error : The volume of result shape is"
 
 puts "========"
 puts "OCC25983"
@@ -22,3 +24,7 @@ tmirror Clone 0 0 0 1 0 0
 bfuse result Knurling Clone
 
 checkshape result
+checknbshapes result -wire 24 -face 24 -shell 1 -solid 1
+checkprops result -s 262.476 -v 54.0383
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
similarity index 77%
rename from tests/bugs/modalg_7/bug25983
rename to tests/bugs/modalg_7/bug25983_2
index 9eb515c..23fad79 100644 (file)
@@ -1,5 +1,3 @@
-puts "TODO OCC25983 ALL: Faulty shapes in variables faulty_1 to faulty_"
-
 puts "========"
 puts "OCC25983"
 puts "========"
@@ -19,6 +17,12 @@ addsweep DWire
 buildsweep Knurling -C -S
 copy Knurling Clone
 tmirror Clone 0 0 0 1 0 0
+
+bfuzzyvalue 1.e-3
 bfuse result Knurling Clone
 
 checkshape result
+checknbshapes result -wire 24 -face 24 -shell 1 -solid 1
+checkprops result -s 262.476 -v 54.0383
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/bugs/modalg_7/bug29580_1 b/tests/bugs/modalg_7/bug29580_1
new file mode 100644 (file)
index 0000000..5592ec7
--- /dev/null
@@ -0,0 +1,18 @@
+puts "========"
+puts "OCC29580"
+puts "========"
+puts ""
+#################################################
+# Regression: invalid result of BOP Fuse
+#################################################
+
+restore [locate_data_file bug29580_Cylinder.brep] b1
+restore [locate_data_file bug29580_Solid.brep] b2
+
+bfuse result b1 b2
+
+checkshape result
+checknbshapes result -wire 14 -face 13 -shell 1 -solid 1
+checkprops result -s 865.851 -v 1622.19
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png
diff --git a/tests/bugs/modalg_7/bug29580_2 b/tests/bugs/modalg_7/bug29580_2
new file mode 100644 (file)
index 0000000..2b60f9a
--- /dev/null
@@ -0,0 +1,37 @@
+puts "========"
+puts "OCC29580"
+puts "========"
+puts ""
+#################################################
+# Regression: invalid result of BOP Fuse
+#################################################
+
+
+circle c1 0 -5 0 1 0 0 10 
+circle c2 0 5 0 1 0 0 10
+mkedge e1 c1 
+mkedge e2 c2 
+wire w1 e1 
+wire w2 e2 
+mkplane f1 w1 
+mkplane f2 w2 
+bcut f12 f1 f2 
+revol b1 f12 0 0 0 0 0 1 180
+ttranslate b1 0 31.358955689999998 0 
+
+plane pln 0 0 0 0 0 1 1.1102230246251565e-016 -1 0 
+psphere b2 pln 8.6602540399999999 180 
+ttranslate b2  0 31.358955689999998 0
+
+bclearobjects
+bcleartools
+baddobjects b1
+baddtools b2
+bfillds
+bbuild result
+
+checkshape result
+checknbshapes result -vertex 4 -edge 14 -wire 10 -face 10 -shell 3 -solid 3 -t
+checkprops result -s 3879.55 -v 6295.15
+
+checkview -display result -2d -path ${imagedir}/${test_image}.png