mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-04 13:13:25 +03:00
0029580: Regression: invalid result of BOP Fuse
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.
This commit is contained in:
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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);
|
||||
|
@@ -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";
|
||||
|
@@ -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
|
||||
|
@@ -22,65 +22,116 @@
|
||||
#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
|
||||
|
||||
//! 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
|
||||
|
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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();
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user