diff --git a/src/BOPAlgo/BOPAlgo.msg b/src/BOPAlgo/BOPAlgo.msg index 673a39ec42..72c842f7df 100644 --- a/src/BOPAlgo/BOPAlgo.msg +++ b/src/BOPAlgo/BOPAlgo.msg @@ -76,3 +76,18 @@ 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 + +.BOPAlgo_AlertUnsupportedType +Warning: Unsupported type of input shape + +.BOPAlgo_AlertUnableToRemoveTheFeature +Warning: Unable to remove the feature + +.BOPAlgo_AlertNoFacesToRemove +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 diff --git a/src/BOPAlgo/BOPAlgo_Alerts.hxx b/src/BOPAlgo/BOPAlgo_Alerts.hxx index 04ce9c7b4f..7a4f927f76 100644 --- a/src/BOPAlgo/BOPAlgo_Alerts.hxx +++ b/src/BOPAlgo/BOPAlgo_Alerts.hxx @@ -88,4 +88,20 @@ DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertBuildingPCurveFailed) //! other shapes and the argument became self-interfered DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertAcquiredSelfIntersection) +//! Unsupported type of input shape +DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnsupportedType) + +//! No faces have been found for removal +DEFINE_SIMPLE_ALERT(BOPAlgo_AlertNoFacesToRemove) + +//! Unable to remove the feature +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 diff --git a/src/BOPAlgo/BOPAlgo_BOP.cxx b/src/BOPAlgo/BOPAlgo_BOP.cxx index c1e8804295..c6a4948612 100644 --- a/src/BOPAlgo/BOPAlgo_BOP.cxx +++ b/src/BOPAlgo/BOPAlgo_BOP.cxx @@ -1018,16 +1018,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); diff --git a/src/BOPAlgo/BOPAlgo_BOPAlgo_msg.pxx b/src/BOPAlgo/BOPAlgo_BOPAlgo_msg.pxx index feec778809..6cd2187474 100644 --- a/src/BOPAlgo/BOPAlgo_BOPAlgo_msg.pxx +++ b/src/BOPAlgo/BOPAlgo_BOPAlgo_msg.pxx @@ -78,4 +78,19 @@ static const char BOPAlgo_BOPAlgo_msg[] = "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"; + "Warning: Some sub-shapes of some of the argument become connected through other shapes and the argument became self-interfered\n" + "\n" + ".BOPAlgo_AlertUnsupportedType\n" + "Warning: Unsupported type of input shape\n" + "\n" + ".BOPAlgo_AlertUnableToRemoveTheFeature\n" + "Warning: Unable to remove the feature\n" + "\n" + ".BOPAlgo_AlertNoFacesToRemove\n" + "Error: No faces have been found for removal\n" + "\n" + ".BOPAlgo_AlertRemoveFeaturesFailed\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"; diff --git a/src/BOPAlgo/BOPAlgo_BuilderSolid.cxx b/src/BOPAlgo/BOPAlgo_BuilderSolid.cxx index d9e6241267..bcff591cd7 100644 --- a/src/BOPAlgo/BOPAlgo_BuilderSolid.cxx +++ b/src/BOPAlgo/BOPAlgo_BuilderSolid.cxx @@ -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 diff --git a/src/BOPAlgo/BOPAlgo_BuilderSolid.hxx b/src/BOPAlgo/BOPAlgo_BuilderSolid.hxx index b665e3ecf0..756d1861e8 100644 --- a/src/BOPAlgo/BOPAlgo_BuilderSolid.hxx +++ b/src/BOPAlgo/BOPAlgo_BuilderSolid.hxx @@ -22,65 +22,116 @@ #include #include -#include #include #include #include -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 - 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 + + //! 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; - - //! Build draft solids that contains boundary faces + + //! 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; - - //! Build finalized solids with internal shells + + //! 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; - - TopoDS_Solid mySolid; - - private: TopTools_DataMapOfShapeBox myBoxes; // Boxes of the produced solids diff --git a/src/BOPAlgo/BOPAlgo_Builder_3.cxx b/src/BOPAlgo/BOPAlgo_Builder_3.cxx index f3f9c7d266..f7763d37cb 100644 --- a/src/BOPAlgo/BOPAlgo_Builder_3.cxx +++ b/src/BOPAlgo/BOPAlgo_Builder_3.cxx @@ -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_VectorOfBuilderSolid; +typedef NCollection_Vector BOPAlgo_VectorOfBuilderSolid; // Functors to split solids -typedef BOPTools_Functor BOPAlgo_BuilderSolidFunctor; // typedef BOPTools_CntMerge(aBS.GetReport()); } // // Add new solids to images map diff --git a/src/BOPAlgo/BOPAlgo_CellsBuilder.cxx b/src/BOPAlgo/BOPAlgo_CellsBuilder.cxx index f9c33b684e..7b1c928d3e 100644 --- a/src/BOPAlgo/BOPAlgo_CellsBuilder.cxx +++ b/src/BOPAlgo/BOPAlgo_CellsBuilder.cxx @@ -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 diff --git a/src/BOPAlgo/BOPAlgo_MakerVolume.cxx b/src/BOPAlgo/BOPAlgo_MakerVolume.cxx index c4ead83d1b..85987c1c00 100644 --- a/src/BOPAlgo/BOPAlgo_MakerVolume.cxx +++ b/src/BOPAlgo/BOPAlgo_MakerVolume.cxx @@ -253,7 +253,6 @@ void BOPAlgo_MakerVolume::BuildSolids(TopTools_ListOfShape& theLSR) // BOPAlgo_BuilderSolid aBS; // - aBS.SetSolid(mySBox); aBS.SetShapes(myFaces); aBS.SetRunParallel(myRunParallel); aBS.SetAvoidInternalShapes(myAvoidInternalShapes); @@ -264,6 +263,8 @@ void BOPAlgo_MakerVolume::BuildSolids(TopTools_ListOfShape& theLSR) return; } // + myReport->Merge(aBS.GetReport()); + // theLSR = aBS.Areas(); } diff --git a/src/BOPAlgo/BOPAlgo_Tools.cxx b/src/BOPAlgo/BOPAlgo_Tools.cxx index 1e6184990f..ac65629892 100644 --- a/src/BOPAlgo/BOPAlgo_Tools.cxx +++ b/src/BOPAlgo/BOPAlgo_Tools.cxx @@ -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); diff --git a/tests/boolean/bcut_complex/F2 b/tests/boolean/bcut_complex/F2 index 5ca5836f25..7aa2f6f0b7 100644 --- a/tests/boolean/bcut_complex/F2 +++ b/tests/boolean/bcut_complex/F2 @@ -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 diff --git a/tests/bugs/modalg_6/bug26789_1 b/tests/bugs/modalg_6/bug26789_1 index c5dddec066..c1bb6f2b38 100644 --- a/tests/bugs/modalg_6/bug26789_1 +++ b/tests/bugs/modalg_6/bug26789_1 @@ -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" diff --git a/tests/bugs/modalg_7/bug25983_1 b/tests/bugs/modalg_7/bug25983_1 new file mode 100644 index 0000000000..9d5204f1a7 --- /dev/null +++ b/tests/bugs/modalg_7/bug25983_1 @@ -0,0 +1,30 @@ +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" +puts "========" +puts "" +########################################## +# Fusion of sweep and its mirror invalid +########################################## + +restore [locate_data_file bug25983_deform-fusion1-tcl-BSpline.brep] BSpline +wire Knurling-0-spine BSpline +mksweep Knurling-0-spine +setsweep -FR +polyline DWire 0 0 0 1 -0.9999999999999998 0 1.0000000000000002 0.9999999999999998 0 0 0 0 +trotate DWire 0 0 0 1 0 0 134.99999999999693 +ttranslate DWire 9 0 0 +addsweep DWire +buildsweep Knurling -C -S +copy Knurling Clone +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 diff --git a/tests/bugs/modalg_7/bug25983 b/tests/bugs/modalg_7/bug25983_2 similarity index 77% rename from tests/bugs/modalg_7/bug25983 rename to tests/bugs/modalg_7/bug25983_2 index 9eb515cdb2..23fad7968d 100644 --- a/tests/bugs/modalg_7/bug25983 +++ b/tests/bugs/modalg_7/bug25983_2 @@ -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 index 0000000000..5592ec77f6 --- /dev/null +++ b/tests/bugs/modalg_7/bug29580_1 @@ -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 index 0000000000..2b60f9a310 --- /dev/null +++ b/tests/bugs/modalg_7/bug29580_2 @@ -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