From: emv Date: Tue, 2 Jun 2020 09:06:42 +0000 (+0300) Subject: 0031587: Modeling Data - add BRepTools::RemoveInternals() removing internal sub-shape... X-Git-Tag: V7_5_0_beta~181 X-Git-Url: http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commitdiff_plain;h=09543c2d99f53edff60fd66a0f9725f68b16b686 0031587: Modeling Data - add BRepTools::RemoveInternals() removing internal sub-shapes from the shape --- diff --git a/src/BRepTools/BRepTools.cxx b/src/BRepTools/BRepTools.cxx index cc38b3a2e5..2af4d6123e 100644 --- a/src/BRepTools/BRepTools.cxx +++ b/src/BRepTools/BRepTools.cxx @@ -1156,3 +1156,112 @@ TopAbs_Orientation BRepTools::OriEdgeInFace (const TopoDS_Edge& E, } throw Standard_ConstructionError("BRepTools::OriEdgeInFace"); } + + +namespace +{ + //======================================================================= + //function : findInternalsToKeep + //purpose : Looks for internal sub-shapes which has to be kept to preserve + // topological connectivity. + //======================================================================= + static void findInternalsToKeep (const TopoDS_Shape& theS, + TopTools_MapOfShape& theAllNonInternals, + TopTools_MapOfShape& theAllInternals, + TopTools_MapOfShape& theShapesToKeep) + { + for (TopoDS_Iterator it (theS, Standard_True); it.More(); it.Next()) + { + const TopoDS_Shape& aSS = it.Value(); + findInternalsToKeep (aSS, theAllNonInternals, theAllInternals, theShapesToKeep); + + if (aSS.Orientation() == TopAbs_INTERNAL) + theAllInternals.Add (aSS); + else + theAllNonInternals.Add (aSS); + + if (theAllNonInternals.Contains(aSS) && theAllInternals.Contains (aSS)) + theShapesToKeep.Add (aSS); + } + } + + //======================================================================= + //function : removeShapes + //purpose : Removes sub-shapes from the shape + //======================================================================= + static void removeShapes (TopoDS_Shape& theS, + const TopTools_ListOfShape& theLS) + { + BRep_Builder aBB; + Standard_Boolean isFree = theS.Free(); + theS.Free (Standard_True); + + for (TopTools_ListOfShape::Iterator it (theLS); it.More(); it.Next()) + { + aBB.Remove (theS, it.Value()); + } + theS.Free (isFree); + } + + //======================================================================= + //function : removeInternals + //purpose : Removes recursively all internal sub-shapes from the given shape. + // Returns true if all sub-shapes have been removed from the shape. + //======================================================================= + static Standard_Boolean removeInternals (TopoDS_Shape& theS, + const TopTools_MapOfShape* theShapesToKeep) + { + TopTools_ListOfShape aLRemove; + for (TopoDS_Iterator it (theS, Standard_True); it.More(); it.Next()) + { + const TopoDS_Shape& aSS = it.Value(); + if (aSS.Orientation() == TopAbs_INTERNAL) + { + if (!theShapesToKeep || !theShapesToKeep->Contains (aSS)) + aLRemove.Append (aSS); + } + else + { + if (removeInternals (*(TopoDS_Shape*)&aSS, theShapesToKeep)) + aLRemove.Append (aSS); + } + } + + Standard_Integer aNbSToRemove = aLRemove.Extent(); + if (aNbSToRemove) + { + removeShapes (theS, aLRemove); + return (theS.NbChildren() == 0); + } + return Standard_False; + } + +} + +//======================================================================= +//function : RemoveInternals +//purpose : +//======================================================================= +void BRepTools::RemoveInternals (TopoDS_Shape& theS, + const Standard_Boolean theForce) +{ + TopTools_MapOfShape *pMKeep = NULL, aMKeep; + if (!theForce) + { + // Find all internal sub-shapes which has to be kept to preserve topological connectivity. + // Note that if the multi-connected shape is not directly contained in some shape, + // but as a part of bigger sub-shape which will be removed, the multi-connected + // shape is going to be removed also, breaking topological connectivity. + // For instance, is a compound of the face and edge, which does not + // belong to the face. The face contains internal wire and the edge shares + // the vertex with one of the vertices of that wire. The vertex is not directly + // contained in the face, thus will be removed as part of internal wire, and topological + // connectivity between edge and face will be lost. + TopTools_MapOfShape anAllNonInternals, anAllInternals; + findInternalsToKeep (theS, anAllNonInternals, anAllInternals, aMKeep); + if (aMKeep.Extent()) + pMKeep = &aMKeep; + } + + removeInternals (theS, pMKeep); +} diff --git a/src/BRepTools/BRepTools.hxx b/src/BRepTools/BRepTools.hxx index 1e1b916ddb..cbc23eb622 100644 --- a/src/BRepTools/BRepTools.hxx +++ b/src/BRepTools/BRepTools.hxx @@ -238,6 +238,16 @@ public: Standard_EXPORT static TopAbs_Orientation OriEdgeInFace(const TopoDS_Edge& theEdge, const TopoDS_Face& theFace); + //! Removes internal sub-shapes from the shape. + //! The check on internal status is based on orientation of sub-shapes, + //! classification is not performed. + //! Before removal of internal sub-shapes the algorithm checks if such + //! removal is not going to break topological connectivity between sub-shapes. + //! The flag if set to true disables the connectivity check and clears + //! the given shape from all sub-shapes with internal orientation. + Standard_EXPORT static void RemoveInternals (TopoDS_Shape& theS, + const Standard_Boolean theForce = Standard_False); + protected: diff --git a/src/DBRep/DBRep.cxx b/src/DBRep/DBRep.cxx index f5d8ad9b15..214ba8bf3e 100644 --- a/src/DBRep/DBRep.cxx +++ b/src/DBRep/DBRep.cxx @@ -1416,6 +1416,39 @@ static Standard_Integer binrestore(Draw_Interpretor& di, Standard_Integer n, con return 0; } +//======================================================================= +// removeinternals +//======================================================================= +static Standard_Integer removeInternals (Draw_Interpretor& di, + Standard_Integer n, + const char** a) +{ + if (n < 2) + { + di.PrintHelp (a[0]); + return 1; + } + + TopoDS_Shape aShape = DBRep::Get (a[1]); + if (aShape.IsNull()) + { + di << a[1] << "is a null shape\n"; + return 1; + } + + Standard_Boolean isForce = Standard_False; + if (n > 2) + { + isForce = (Draw::Atoi (a[2]) != 0); + } + + BRepTools::RemoveInternals (aShape, isForce); + + DBRep::Set (a[1], aShape); + + return 0; +} + //======================================================================= //function : BasicCommands //purpose : @@ -1487,6 +1520,12 @@ void DBRep::BasicCommands(Draw_Interpretor& theCommands) theCommands.Add("binrestore", "binrestore filename shape\n" "\t\trestore the shape from the binary format file", __FILE__, binrestore, g); + + theCommands.Add ("removeinternals", "removeinternals shape [force flag {0/1}]" + "\n\t\t Removes sub-shapes with internal orientation from the shape.\n" + "\n\t\t Force flag disables the check on topological connectivity and" + "removes all internal sub-shapes\n", + __FILE__, removeInternals, g); } //======================================================================= diff --git a/tests/bugs/moddata_3/bug31587_1 b/tests/bugs/moddata_3/bug31587_1 new file mode 100644 index 0000000000..b811bc4cc0 --- /dev/null +++ b/tests/bugs/moddata_3/bug31587_1 @@ -0,0 +1,21 @@ +puts "================" +puts "0031587: Modeling Data - Remove internal sub-shapes from the shape" +puts "================" +puts "" + +box b 10 10 10 +box b1 2 2 2 3 2 1 +explode b1 f + +bclearobjects +bcleartools +baddobjects b +baddtools b1_1 +eval baddtools [explode b1_2 e] +bfillds +bsplit r + +removeinternals r + +checkshape r +checknbshapes r -vertex 8 -edge 12 -wire 6 -face 6 -shell 1 -solid 1 diff --git a/tests/bugs/moddata_3/bug31587_2 b/tests/bugs/moddata_3/bug31587_2 new file mode 100644 index 0000000000..671f613ef3 --- /dev/null +++ b/tests/bugs/moddata_3/bug31587_2 @@ -0,0 +1,22 @@ +puts "================" +puts "0031587: Modeling Data - Remove internal sub-shapes from the shape" +puts "================" +puts "" + +box b 10 10 10 +box b1 2 2 0 3 2 1 +explode b1 f + +bclearobjects +bcleartools +baddobjects b +baddtools b1_1 +eval baddtools [explode b1_2 e] +eval baddtools [explode b1_3 v] +bfillds +bsplit r + +removeinternals r + +checkshape r +checknbshapes r -vertex 8 -edge 12 -wire 6 -face 6 -shell 1 -solid 1 diff --git a/tests/bugs/moddata_3/bug31587_3 b/tests/bugs/moddata_3/bug31587_3 new file mode 100644 index 0000000000..96c519440b --- /dev/null +++ b/tests/bugs/moddata_3/bug31587_3 @@ -0,0 +1,34 @@ +puts "================" +puts "0031587: Modeling Data - Remove internal sub-shapes from the shape" +puts "================" +puts "" + +box b 10 10 10 +box b1 2 2 -1 3 2 2 +explode b1 f + +bclearobjects +bcleartools +baddobjects b +baddtools b1_1 b1_2 +bfillds +bsplit r + +removeinternals r + +checkshape r +checknbshapes r -vertex 8 -edge 12 -wire 6 -face 6 -shell 1 -solid 1 + +bbuild r +bbuild r1 +removeinternals r1 0 + +checkshape r1 +checknbshapes r1 -ref [nbshapes r] + +removeinternals r1 1 +checkshape r1 +checknbshapes r1 -vertex 20 -edge 26 -wire 10 -face 10 -shell 1 -solid 1 + +explode r1 so +checknbshapes r1_1 -vertex 8 -edge 12 -wire 6 -face 6 -shell 1 -solid 1 diff --git a/tests/bugs/moddata_3/bug31587_4 b/tests/bugs/moddata_3/bug31587_4 new file mode 100644 index 0000000000..9bc082604a --- /dev/null +++ b/tests/bugs/moddata_3/bug31587_4 @@ -0,0 +1,20 @@ +puts "================" +puts "0031587: Modeling Data - Remove internal sub-shapes from the shape" +puts "================" +puts "" + +box b 10 10 10 +box b1 2 2 0 5 5 5 +explode b1 f +bclearobjects +bcleartools +baddobjects b +baddtools b1_2 b1_3 +eval baddtools [explode b1_1 w] +bfillds +bsplit r + +removeinternals r + +checkshape r +checknbshapes r -vertex 8 -edge 12 -wire 6 -face 6 -shell 1 -solid 1 diff --git a/tests/bugs/moddata_3/bug31587_5 b/tests/bugs/moddata_3/bug31587_5 new file mode 100644 index 0000000000..e06e4a9374 --- /dev/null +++ b/tests/bugs/moddata_3/bug31587_5 @@ -0,0 +1,23 @@ +puts "================" +puts "0031587: Modeling Data - Remove internal sub-shapes from the shape" +puts "================" +puts "" + +box b 10 10 10 +box b1 2 2 0 5 5 5 +box b2 3 2 2 4 5 2 +explode b1 f +explode b2 f +bclearobjects +bcleartools +baddobjects b +baddtools b1_2 b1_3 +eval baddtools [explode b1_1 w] +baddtools b2_5 b2_6 +bfillds +bsplit r + +removeinternals r + +checkshape r +checknbshapes r -vertex 8 -edge 12 -wire 6 -face 6 -shell 1 -solid 1 diff --git a/tests/bugs/moddata_3/bug31587_6 b/tests/bugs/moddata_3/bug31587_6 new file mode 100644 index 0000000000..58a631e1e6 --- /dev/null +++ b/tests/bugs/moddata_3/bug31587_6 @@ -0,0 +1,23 @@ +puts "================" +puts "0031587: Modeling Data - Remove internal sub-shapes from the shape" +puts "================" +puts "" + +box b 10 10 10 +polyline e1 2 2 0 8 2 0 +polyline e2 3 2 -5 3 2 0 + +bclearobjects +bcleartools +baddobjects b +baddtools e1 e2 +bfillds +bsplit r + +compound r e2 c + +# topological connectivity is broken without force flag set to true +removeinternals c + +checkshape c +checknbshapes c -vertex 10 -edge 13 -wire 7 -face 6 -shell 1 -solid 1 diff --git a/tests/bugs/moddata_3/bug31587_7 b/tests/bugs/moddata_3/bug31587_7 new file mode 100644 index 0000000000..0d12f2b8dd --- /dev/null +++ b/tests/bugs/moddata_3/bug31587_7 @@ -0,0 +1,11 @@ +puts "================" +puts "0031587: Modeling Data - Remove internal sub-shapes from the shape" +puts "================" +puts "" + +restore [locate_data_file bug31587_wall1.brep] s +removeinternals s + +checkshape s +checknbshapes s -vertex 6 -edge 6 -wire 1 -face 1 + diff --git a/tests/bugs/moddata_3/bug31587_8 b/tests/bugs/moddata_3/bug31587_8 new file mode 100644 index 0000000000..35b056e8da --- /dev/null +++ b/tests/bugs/moddata_3/bug31587_8 @@ -0,0 +1,10 @@ +puts "================" +puts "0031587: Modeling Data - Remove internal sub-shapes from the shape" +puts "================" +puts "" + +restore [locate_data_file bug31587_wall12.brep] s +removeinternals s + +checkshape s +checknbshapes s -vertex 16 -edge 16 -wire 3 -face 3