mirror of
https://git.dev.opencascade.org/repos/occt.git
synced 2025-08-04 13:13:25 +03:00
0030145: Modeling Algorithms - Boolean Operations on open solids
Provide possibility to perform Boolean operations on open solids. Implementation of the new method *BOPAlgo_Builder::BuildBOP* performing the construction of the result shape for the given type of Boolean operation. This approach does not rely on the splits of solid to be correct and looks for the faces with necessary state relatively opposite solids to build the result solid. The call to this method is performed from BOP algorithm in case there were open solids in the arguments. Implementation of the draw command *buildbop* performing a call to the method above.
This commit is contained in:
@@ -6,94 +6,97 @@
|
||||
N/A
|
||||
|
||||
.BOPAlgo_AlertBOPIsNotSet
|
||||
Error: The type of Boolean Operation is not set
|
||||
The type of Boolean Operation is not set
|
||||
|
||||
.BOPAlgo_AlertBOPNotAllowed
|
||||
Error: Boolean operation of the given type is not allowed on the given inputs
|
||||
Boolean operation of the given type is not allowed on the given inputs
|
||||
|
||||
.BOPAlgo_AlertSolidBuilderFailed
|
||||
Error: Building Fused solid has failed
|
||||
Building Fused solid has failed
|
||||
|
||||
.BOPAlgo_AlertTooFewArguments
|
||||
Error: There are no enough arguments to perform the operation
|
||||
There are no enough arguments to perform the operation
|
||||
|
||||
.BOPAlgo_AlertMultipleArguments
|
||||
Error: More than one argument is provided
|
||||
More than one argument is provided
|
||||
|
||||
.BOPAlgo_AlertNoFiller
|
||||
Error: The Pave Filler (the intersection tool) has not been created
|
||||
The Pave Filler (the intersection tool) has not been created
|
||||
|
||||
.BOPAlgo_AlertIntersectionFailed
|
||||
Error: The intersection of the arguments has failed
|
||||
The intersection of the arguments has failed
|
||||
|
||||
.BOPAlgo_AlertBuilderFailed
|
||||
Error: Building of the result shape has failed
|
||||
Building of the result shape has failed
|
||||
|
||||
.BOPAlgo_AlertNullFace
|
||||
Error: The face given to be split is a null shape
|
||||
The face given to be split is a null shape
|
||||
|
||||
.BOPAlgo_AlertNullInputShapes
|
||||
Error: No or null input shapes
|
||||
No or null input shapes
|
||||
|
||||
.BOPAlgo_AlertPostTreatFF
|
||||
Error: Cannot connect face intersection curves
|
||||
Cannot connect face intersection curves
|
||||
|
||||
.BOPAlgo_AlertEmptyShape
|
||||
Warning: Some of the arguments are empty shapes
|
||||
Some of the arguments are empty shapes
|
||||
|
||||
.BOPAlgo_AlertSelfInterferingShape
|
||||
Warning: Some of the arguments are self-interfering shapes
|
||||
Some of the arguments are self-interfering shapes
|
||||
|
||||
.BOPAlgo_AlertTooSmallEdge
|
||||
Warning: Some edges are too small and have no valid range
|
||||
Some edges are too small and have no valid range
|
||||
|
||||
.BOPAlgo_AlertNotSplittableEdge
|
||||
Warning: Some edges are very small and have such a small valid range, that they cannot be split
|
||||
Some edges are very small and have such a small valid range, that they cannot be split
|
||||
|
||||
.BOPAlgo_AlertBadPositioning
|
||||
Warning: The positioning of the shapes leads to creation of the small edges without valid range
|
||||
The positioning of the shapes leads to creation of the small edges without valid range
|
||||
|
||||
.BOPAlgo_AlertShellSplitterFailed
|
||||
Warning: Unable to build loops from the given faces
|
||||
Unable to build loops from the given faces
|
||||
|
||||
.BOPAlgo_AlertRemovalOfIBForMDimShapes
|
||||
Warning: Removal of internal boundaries among the multi-dimensional shapes is not supported yet
|
||||
Removal of internal boundaries among the multi-dimensional shapes is not supported yet
|
||||
|
||||
.BOPAlgo_AlertRemovalOfIBForSolidsFailed
|
||||
Warning: Removal of internal boundaries among Solids has failed
|
||||
Removal of internal boundaries among Solids has failed
|
||||
|
||||
.BOPAlgo_AlertRemovalOfIBForFacesFailed
|
||||
Warning: Removal of internal boundaries among Faces has failed
|
||||
Removal of internal boundaries among Faces has failed
|
||||
|
||||
.BOPAlgo_AlertRemovalOfIBForEdgesFailed
|
||||
Warning: Removal of internal boundaries among Edges has failed
|
||||
Removal of internal boundaries among Edges has failed
|
||||
|
||||
.BOPAlgo_AlertIntersectionOfPairOfShapesFailed
|
||||
Warning: Intersection of pair of shapes has failed
|
||||
Intersection of pair of shapes has failed
|
||||
|
||||
.BOPAlgo_AlertBuildingPCurveFailed
|
||||
Warning: Building 2D curve of edge on face has failed
|
||||
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
|
||||
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
|
||||
Unsupported type of input shape
|
||||
|
||||
.BOPAlgo_AlertUnableToRemoveTheFeature
|
||||
Warning: Unable to remove the feature
|
||||
Unable to remove the feature
|
||||
|
||||
.BOPAlgo_AlertNoFacesToRemove
|
||||
Error: No faces have been found for removal
|
||||
No faces have been found for removal
|
||||
|
||||
.BOPAlgo_AlertRemoveFeaturesFailed
|
||||
Error: The Feature Removal algorithm has failed
|
||||
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
|
||||
Some of the faces passed to the Solid Builder algorithm have not been classified and not used for solids creation
|
||||
|
||||
.BOPAlgo_AlertFaceBuilderUnusedEdges
|
||||
Warning: Some of the edges passed to the Face Builder algorithm have not been classified and not used for faces creation
|
||||
Some of the edges passed to the Face Builder algorithm have not been classified and not used for faces creation
|
||||
|
||||
.BOPAlgo_AlertUnableToOrientTheShape
|
||||
Warning: Unable to orient the shape correctly
|
||||
Unable to orient the shape correctly
|
||||
|
||||
.BOPAlgo_AlertUnknownShape
|
||||
Shape is unknown for operation
|
||||
|
@@ -111,4 +111,7 @@ DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertFaceBuilderUnusedEdges)
|
||||
//! Unable to orient the shape correctly
|
||||
DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnableToOrientTheShape)
|
||||
|
||||
//! Shape is unknown for operation
|
||||
DEFINE_ALERT_WITH_SHAPE(BOPAlgo_AlertUnknownShape)
|
||||
|
||||
#endif // _BOPAlgo_Alerts_HeaderFile
|
||||
|
@@ -30,6 +30,7 @@
|
||||
#include <TopAbs_ShapeEnum.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <TopoDS_Edge.hxx>
|
||||
#include <TopoDS_Iterator.hxx>
|
||||
@@ -772,6 +773,32 @@ void BOPAlgo_BOP::BuildRC()
|
||||
//=======================================================================
|
||||
void BOPAlgo_BOP::BuildShape()
|
||||
{
|
||||
if (myDims[0] == 3 && myDims[1] == 3)
|
||||
{
|
||||
// For the Boolean operation on solids we need to check first
|
||||
// if we are dealing with closed solids, because for open solids
|
||||
// we cannot expect the BuilderSolid algorithm to produce good
|
||||
// splits for them and have to try the alternative approach for
|
||||
// building the result shape.
|
||||
// This approach is not used by default as it will loose the
|
||||
// modification history for solids, because the result solid
|
||||
// will be built from scratch using the splits of faces.
|
||||
Standard_Boolean hasNotClosedSolids = CheckArgsForOpenSolid();
|
||||
if (hasNotClosedSolids)
|
||||
{
|
||||
Handle(Message_Report) aReport = new Message_Report();
|
||||
BuildBOP(myArguments, myTools, myOperation, aReport);
|
||||
if (aReport->GetAlerts(Message_Fail).IsEmpty())
|
||||
{
|
||||
// Success. Merge the report into the main report.
|
||||
myReport->Merge(aReport);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build the result using splits of arguments.
|
||||
|
||||
BuildRC();
|
||||
//
|
||||
if ((myOperation == BOPAlgo_FUSE) && (myDims[0] == 3)) {
|
||||
@@ -1169,6 +1196,157 @@ void BOPAlgo_BOP::BuildSolid()
|
||||
//
|
||||
myShape = aResult;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : CheckArgsForOpenSolid
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
Standard_Boolean BOPAlgo_BOP::CheckArgsForOpenSolid()
|
||||
{
|
||||
// Analyze the report to find if BuilderSolid has generated warnings
|
||||
// for any of the solids and collect these solids to check if they are open.
|
||||
TopTools_MapOfShape aFailedSolids;
|
||||
{
|
||||
const Message_ListOfAlert& aList = myReport->GetAlerts(Message_Warning);
|
||||
for (Message_ListOfAlert::Iterator aIt(aList); aIt.More(); aIt.Next())
|
||||
{
|
||||
const Handle(Standard_Type)& aType = aIt.Value()->DynamicType();
|
||||
if (aType != STANDARD_TYPE(BOPAlgo_AlertSolidBuilderUnusedFaces))
|
||||
continue;
|
||||
|
||||
Handle(TopoDS_AlertWithShape) aShapeAlert = Handle(TopoDS_AlertWithShape)::DownCast(aIt.Value());
|
||||
if (!aShapeAlert.IsNull())
|
||||
{
|
||||
const TopoDS_Shape& aWarnShape = aShapeAlert->GetShape();
|
||||
if (!aWarnShape.IsNull())
|
||||
{
|
||||
TopExp_Explorer expS(aWarnShape, TopAbs_SOLID);
|
||||
for (; expS.More(); expS.Next())
|
||||
aFailedSolids.Add(expS.Current());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Iterate on all solids from the arguments and check if any
|
||||
// of them are not closed.
|
||||
// At the same time, collect all internal faces of the input solids
|
||||
// to check if the splits of open solids did not acquire any new
|
||||
// internal faces.
|
||||
|
||||
const Standard_Integer aNbS = myDS->NbSourceShapes();
|
||||
for (Standard_Integer i = 0; i < aNbS; ++i)
|
||||
{
|
||||
const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
|
||||
if (aSI.ShapeType() != TopAbs_SOLID)
|
||||
continue;
|
||||
|
||||
const TopoDS_Shape& aSolid = aSI.Shape();
|
||||
|
||||
// Check that not INTERNAL faces create closed loops
|
||||
TopTools_IndexedDataMapOfShapeListOfShape aMEF;
|
||||
// Collect all splits of internal faces
|
||||
TopTools_MapOfShape aMFInternal;
|
||||
|
||||
for (TopoDS_Iterator itSh(aSolid); itSh.More(); itSh.Next())
|
||||
{
|
||||
const TopoDS_Shape& aSh = itSh.Value();
|
||||
if (aSh.ShapeType() != TopAbs_SHELL)
|
||||
continue;
|
||||
|
||||
for (TopoDS_Iterator itF(aSh); itF.More(); itF.Next())
|
||||
{
|
||||
const TopoDS_Shape& aF = itF.Value();
|
||||
if (aF.Orientation() == TopAbs_INTERNAL)
|
||||
{
|
||||
const TopTools_ListOfShape* pLFIm = myImages.Seek(aF);
|
||||
if (pLFIm)
|
||||
{
|
||||
TopTools_ListOfShape::Iterator itLFIm(*pLFIm);
|
||||
for (; itLFIm.More(); itLFIm.Next())
|
||||
aMFInternal.Add(itLFIm.Value());
|
||||
}
|
||||
else
|
||||
aMFInternal.Add(aF);
|
||||
}
|
||||
else
|
||||
TopExp::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
|
||||
}
|
||||
}
|
||||
|
||||
// Analyze the Edge-Face connection map on free edges
|
||||
Standard_Boolean isClosed = Standard_True;
|
||||
const Standard_Integer aNbE = aMEF.Extent();
|
||||
for (Standard_Integer j = 1; j <= aNbE && isClosed; ++j)
|
||||
{
|
||||
const TopoDS_Edge& aE = TopoDS::Edge(aMEF.FindKey(j));
|
||||
if (BRep_Tool::Degenerated(aE))
|
||||
// Skip degenerated edges
|
||||
continue;
|
||||
|
||||
isClosed = (aMEF(j).Extent() > 1);
|
||||
if (!isClosed)
|
||||
{
|
||||
const TopoDS_Face& aF = TopoDS::Face(aMEF(j).First());
|
||||
isClosed = BRep_Tool::IsClosed(aE, aF); // Check for seam edges
|
||||
if (!isClosed)
|
||||
{
|
||||
// Check if the edge is not internal in the face
|
||||
TopExp_Explorer expE(aF, TopAbs_EDGE);
|
||||
for (; expE.More(); expE.Next())
|
||||
{
|
||||
if (expE.Current().IsSame(aE))
|
||||
{
|
||||
isClosed = (expE.Current().Orientation() == TopAbs_INTERNAL);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isClosed)
|
||||
continue;
|
||||
|
||||
// Not closed solid is found
|
||||
|
||||
if (aFailedSolids.Contains(aSolid))
|
||||
// Warning has been generated for this solid, return positive result right away.
|
||||
return Standard_True;
|
||||
|
||||
|
||||
// Check the splits not to acquire new INTERNAL faces
|
||||
const TopTools_ListOfShape *pLSIm = myImages.Seek(aSolid);
|
||||
if (!pLSIm)
|
||||
continue;
|
||||
|
||||
TopTools_ListOfShape::Iterator itLSIm(*pLSIm);
|
||||
for (; itLSIm.More(); itLSIm.Next())
|
||||
{
|
||||
const TopoDS_Shape& aSIm = itLSIm.Value();
|
||||
for (TopoDS_Iterator itSh(aSIm); itSh.More(); itSh.Next())
|
||||
{
|
||||
const TopoDS_Shape& aSh = itSh.Value();
|
||||
if (aSh.ShapeType() != TopAbs_SHELL)
|
||||
continue;
|
||||
|
||||
for (TopoDS_Iterator itF(aSh); itF.More(); itF.Next())
|
||||
{
|
||||
const TopoDS_Shape& aF = itF.Value();
|
||||
if (aF.Orientation() == TopAbs_INTERNAL)
|
||||
{
|
||||
if (!aMFInternal.Contains(aF))
|
||||
// New internal face is found
|
||||
return Standard_True;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Standard_False;
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : TypeToExplore
|
||||
//purpose :
|
||||
|
@@ -107,6 +107,12 @@ protected:
|
||||
//! all shapes in one of the groups are empty shapes.
|
||||
Standard_EXPORT Standard_Boolean TreatEmptyShape();
|
||||
|
||||
//! Checks if the arguments of Boolean Operation on solids
|
||||
//! contain any open solids, for which the building of the splits
|
||||
//! has failed. In case of positive check, run different procedure
|
||||
//! for building the result shape.
|
||||
Standard_EXPORT virtual Standard_Boolean CheckArgsForOpenSolid();
|
||||
|
||||
protected:
|
||||
|
||||
BOPAlgo_Operation myOperation;
|
||||
|
@@ -9,94 +9,97 @@ static const char BOPAlgo_BOPAlgo_msg[] =
|
||||
"N/A\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertBOPIsNotSet\n"
|
||||
"Error: The type of Boolean Operation is not set\n"
|
||||
"The type of Boolean Operation is not set\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertBOPNotAllowed\n"
|
||||
"Error: Boolean operation of the given type is not allowed on the given inputs\n"
|
||||
"Boolean operation of the given type is not allowed on the given inputs\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertSolidBuilderFailed\n"
|
||||
"Error: Building Fused solid has failed\n"
|
||||
"Building Fused solid has failed\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertTooFewArguments\n"
|
||||
"Error: There are no enough arguments to perform the operation\n"
|
||||
"There are no enough arguments to perform the operation\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertMultipleArguments\n"
|
||||
"Error: More than one argument is provided\n"
|
||||
"More than one argument is provided\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertNoFiller\n"
|
||||
"Error: The Pave Filler (the intersection tool) has not been created\n"
|
||||
"The Pave Filler (the intersection tool) has not been created\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertIntersectionFailed\n"
|
||||
"Error: The intersection of the arguments has failed\n"
|
||||
"The intersection of the arguments has failed\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertBuilderFailed\n"
|
||||
"Error: Building of the result shape has failed\n"
|
||||
"Building of the result shape has failed\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertNullFace\n"
|
||||
"Error: The face given to be split is a null shape\n"
|
||||
"The face given to be split is a null shape\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertNullInputShapes\n"
|
||||
"Error: No or null input shapes\n"
|
||||
"No or null input shapes\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertPostTreatFF\n"
|
||||
"Error: Cannot connect face intersection curves\n"
|
||||
"Cannot connect face intersection curves\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertEmptyShape\n"
|
||||
"Warning: Some of the arguments are empty shapes\n"
|
||||
"Some of the arguments are empty shapes\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertSelfInterferingShape\n"
|
||||
"Warning: Some of the arguments are self-interfering shapes\n"
|
||||
"Some of the arguments are self-interfering shapes\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertTooSmallEdge\n"
|
||||
"Warning: Some edges are too small and have no valid range\n"
|
||||
"Some edges are too small and have no valid range\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertNotSplittableEdge\n"
|
||||
"Warning: Some edges are very small and have such a small valid range, that they cannot be split\n"
|
||||
"Some edges are very small and have such a small valid range, that they cannot be split\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertBadPositioning\n"
|
||||
"Warning: The positioning of the shapes leads to creation of the small edges without valid range\n"
|
||||
"The positioning of the shapes leads to creation of the small edges without valid range\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertShellSplitterFailed\n"
|
||||
"Warning: Unable to build loops from the given faces\n"
|
||||
"Unable to build loops from the given faces\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertRemovalOfIBForMDimShapes\n"
|
||||
"Warning: Removal of internal boundaries among the multi-dimensional shapes is not supported yet\n"
|
||||
"Removal of internal boundaries among the multi-dimensional shapes is not supported yet\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertRemovalOfIBForSolidsFailed\n"
|
||||
"Warning: Removal of internal boundaries among Solids has failed\n"
|
||||
"Removal of internal boundaries among Solids has failed\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertRemovalOfIBForFacesFailed\n"
|
||||
"Warning: Removal of internal boundaries among Faces has failed\n"
|
||||
"Removal of internal boundaries among Faces has failed\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertRemovalOfIBForEdgesFailed\n"
|
||||
"Warning: Removal of internal boundaries among Edges has failed\n"
|
||||
"Removal of internal boundaries among Edges has failed\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertIntersectionOfPairOfShapesFailed\n"
|
||||
"Warning: Intersection of pair of shapes has failed\n"
|
||||
"Intersection of pair of shapes has failed\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertBuildingPCurveFailed\n"
|
||||
"Warning: Building 2D curve of edge on face has failed\n"
|
||||
"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"
|
||||
"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"
|
||||
"Unsupported type of input shape\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertUnableToRemoveTheFeature\n"
|
||||
"Warning: Unable to remove the feature\n"
|
||||
"Unable to remove the feature\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertNoFacesToRemove\n"
|
||||
"Error: No faces have been found for removal\n"
|
||||
"No faces have been found for removal\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertRemoveFeaturesFailed\n"
|
||||
"Error: The Feature Removal algorithm has failed\n"
|
||||
"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"
|
||||
"Some of the faces passed to the Solid Builder algorithm have not been classified and not used for solids creation\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertFaceBuilderUnusedEdges\n"
|
||||
"Warning: Some of the edges passed to the Face Builder algorithm have not been classified and not used for faces creation\n"
|
||||
"Some of the edges passed to the Face Builder algorithm have not been classified and not used for faces creation\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertUnableToOrientTheShape\n"
|
||||
"Warning: Unable to orient the shape correctly\n";
|
||||
"Unable to orient the shape correctly\n"
|
||||
"\n"
|
||||
".BOPAlgo_AlertUnknownShape\n"
|
||||
"Shape is unknown for operation\n";
|
||||
|
@@ -17,22 +17,24 @@
|
||||
|
||||
|
||||
#include <BOPAlgo_Builder.hxx>
|
||||
#include <BOPAlgo_PaveFiller.hxx>
|
||||
#include <BOPAlgo_Alerts.hxx>
|
||||
#include <BOPAlgo_BuilderSolid.hxx>
|
||||
#include <BOPAlgo_PaveFiller.hxx>
|
||||
#include <BOPAlgo_Tools.hxx>
|
||||
#include <BOPDS_DS.hxx>
|
||||
#include <BOPDS_ShapeInfo.hxx>
|
||||
#include <BOPTools_AlgoTools.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
#include <IntTools_Context.hxx>
|
||||
#include <Standard_ErrorHandler.hxx>
|
||||
#include <Standard_Failure.hxx>
|
||||
#include <TopExp.hxx>
|
||||
#include <TopExp_Explorer.hxx>
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_Compound.hxx>
|
||||
#include <BRep_Builder.hxx>
|
||||
|
||||
#include <BOPDS_ShapeInfo.hxx>
|
||||
#include <BOPDS_DS.hxx>
|
||||
|
||||
#include <BOPTools_AlgoTools.hxx>
|
||||
#include <TopoDS_Solid.hxx>
|
||||
#include <TopTools_IndexedMapOfShape.hxx>
|
||||
#include <TopTools_ListIteratorOfListOfShape.hxx>
|
||||
#include <TopTools_MapOfOrientedShape.hxx>
|
||||
|
||||
|
||||
//=======================================================================
|
||||
@@ -50,6 +52,7 @@ BOPAlgo_Builder::BOPAlgo_Builder()
|
||||
myImages(100, myAllocator),
|
||||
myShapesSD(100, myAllocator),
|
||||
myOrigins(100, myAllocator),
|
||||
myInParts(100, myAllocator),
|
||||
myNonDestructive(Standard_False),
|
||||
myGlue(BOPAlgo_GlueOff),
|
||||
myCheckInverted(Standard_True)
|
||||
@@ -71,6 +74,7 @@ BOPAlgo_Builder::BOPAlgo_Builder
|
||||
myImages(100, myAllocator),
|
||||
myShapesSD(100, myAllocator),
|
||||
myOrigins(100, myAllocator),
|
||||
myInParts(100, myAllocator),
|
||||
myNonDestructive(Standard_False),
|
||||
myGlue(BOPAlgo_GlueOff),
|
||||
myCheckInverted(Standard_True)
|
||||
@@ -101,6 +105,7 @@ void BOPAlgo_Builder::Clear()
|
||||
myImages.Clear();
|
||||
myShapesSD.Clear();
|
||||
myOrigins.Clear();
|
||||
myInParts.Clear();
|
||||
}
|
||||
//=======================================================================
|
||||
//function : AddArgument
|
||||
@@ -376,3 +381,366 @@ void BOPAlgo_Builder::PostTreat()
|
||||
BOPTools_AlgoTools::CorrectTolerances(myShape, aMA, 0.05, myRunParallel);
|
||||
BOPTools_AlgoTools::CorrectShapeTolerances(myShape, aMA, myRunParallel);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : BuildBOP
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void BOPAlgo_Builder::BuildBOP(const TopTools_ListOfShape& theObjects,
|
||||
const TopAbs_State theObjState,
|
||||
const TopTools_ListOfShape& theTools,
|
||||
const TopAbs_State theToolsState,
|
||||
Handle(Message_Report) theReport)
|
||||
{
|
||||
if (HasErrors())
|
||||
return;
|
||||
|
||||
// Report for the method
|
||||
Handle(Message_Report) aReport = theReport.IsNull() ? myReport : theReport;
|
||||
|
||||
if (myArguments.IsEmpty() || myShape.IsNull())
|
||||
{
|
||||
aReport->AddAlert(Message_Fail, new BOPAlgo_AlertBuilderFailed());
|
||||
return;
|
||||
}
|
||||
|
||||
// Check the input data
|
||||
if ((theObjState != TopAbs_IN && theObjState != TopAbs_OUT) ||
|
||||
(theToolsState != TopAbs_IN && theToolsState != TopAbs_OUT))
|
||||
{
|
||||
aReport->AddAlert(Message_Fail, new BOPAlgo_AlertBOPNotSet());
|
||||
return;
|
||||
}
|
||||
|
||||
// Check input shapes
|
||||
Standard_Boolean hasObjects = !theObjects.IsEmpty();
|
||||
Standard_Boolean hasTools = !theTools .IsEmpty();
|
||||
if (!hasObjects && !hasTools)
|
||||
{
|
||||
aReport->AddAlert(Message_Fail, new BOPAlgo_AlertTooFewArguments());
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that all input solids are from the arguments
|
||||
for (Standard_Integer i = 0; i < 2; ++i)
|
||||
{
|
||||
const TopTools_ListOfShape& aList = !i ? theObjects : theTools;
|
||||
TopTools_ListOfShape::Iterator itLS(aList);
|
||||
for (; itLS.More(); itLS.Next())
|
||||
{
|
||||
const TopoDS_Shape& aS = itLS.Value();
|
||||
// Check if the shape belongs to the arguments of operation
|
||||
if (myDS->Index(aS) < 0)
|
||||
{
|
||||
aReport->AddAlert(Message_Fail, new BOPAlgo_AlertUnknownShape(aS));
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if the shape is a solid or collection of them
|
||||
if (aS.ShapeType() != TopAbs_SOLID)
|
||||
{
|
||||
TopTools_ListOfShape aLS;
|
||||
TopTools_MapOfShape aMFence;
|
||||
BOPAlgo_Tools::TreatCompound(aS, aMFence, aLS);
|
||||
|
||||
TopTools_ListOfShape::Iterator it(aLS);
|
||||
for (; it.More(); it.Next())
|
||||
{
|
||||
const TopoDS_Shape& aSx = it.Value();
|
||||
if (aSx.ShapeType() != TopAbs_SOLID &&
|
||||
aSx.ShapeType() != TopAbs_COMPSOLID)
|
||||
{
|
||||
aReport->AddAlert(Message_Fail, new BOPAlgo_AlertUnsupportedType(aS));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Classification of the faces relatively solids has been made
|
||||
// on the stage of Solids splitting. All results are saved into
|
||||
// myInParts map, which connects the solids with its IN faces from
|
||||
// other arguments. All faces not contained in the list of IN faces
|
||||
// will be considered as OUT.
|
||||
|
||||
// Prepare the maps of splits of solids faces with orientations
|
||||
TopTools_IndexedMapOfOrientedShape aMObjFacesOri, aMToolFacesOri;
|
||||
// Prepare the maps of splits of solids faces
|
||||
TopTools_IndexedMapOfShape aMObjFaces, aMToolFaces;
|
||||
// Copy the list of IN faces of the solids into map
|
||||
TopTools_MapOfShape anINObjects, anINTools;
|
||||
|
||||
for (Standard_Integer i = 0; i < 2; ++i)
|
||||
{
|
||||
const TopTools_ListOfShape& aList = !i ? theObjects : theTools;
|
||||
TopTools_IndexedMapOfOrientedShape& aMapOri = !i ? aMObjFacesOri : aMToolFacesOri;
|
||||
TopTools_IndexedMapOfShape& aMap = !i ? aMObjFaces : aMToolFaces;
|
||||
TopTools_ListOfShape::Iterator itLS(aList);
|
||||
for (; itLS.More(); itLS.Next())
|
||||
{
|
||||
const TopoDS_Shape& aShape = itLS.Value();
|
||||
TopExp_Explorer expS(aShape, TopAbs_SOLID);
|
||||
for (; expS.More(); expS.Next())
|
||||
{
|
||||
const TopoDS_Shape& aS = expS.Current();
|
||||
TopExp_Explorer expF(aS, TopAbs_FACE);
|
||||
for (; expF.More(); expF.Next())
|
||||
{
|
||||
const TopoDS_Shape& aF = expF.Current();
|
||||
if (aF.Orientation() != TopAbs_FORWARD &&
|
||||
aF.Orientation() != TopAbs_REVERSED)
|
||||
continue;
|
||||
const TopTools_ListOfShape* pLFIm = myImages.Seek(aF);
|
||||
if (pLFIm)
|
||||
{
|
||||
TopTools_ListOfShape::Iterator itLFIm(*pLFIm);
|
||||
for (; itLFIm.More(); itLFIm.Next())
|
||||
{
|
||||
TopoDS_Face aFIm = TopoDS::Face(itLFIm.Value());
|
||||
if (BOPTools_AlgoTools::IsSplitToReverse(aFIm, aF, myContext))
|
||||
aFIm.Reverse();
|
||||
aMapOri.Add(aFIm);
|
||||
aMap.Add(aFIm);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aMapOri.Add(aF);
|
||||
aMap.Add(aF);
|
||||
}
|
||||
}
|
||||
|
||||
// Copy the list of IN faces into a map
|
||||
const TopTools_ListOfShape* pLFIN = myInParts.Seek(aS);
|
||||
if (pLFIN)
|
||||
{
|
||||
TopTools_MapOfShape& anINMap = !i ? anINObjects : anINTools;
|
||||
TopTools_ListOfShape::Iterator itLFIn(*pLFIN);
|
||||
for (; itLFIn.More(); itLFIn.Next())
|
||||
anINMap.Add(itLFIn.Value());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Now we need to select all faces which will participate in
|
||||
// building of the resulting solids. The final set of faces
|
||||
// depends on the given states for the groups.
|
||||
Standard_Boolean isObjectsIN = (theObjState == TopAbs_IN),
|
||||
isToolsIN = (theToolsState == TopAbs_IN);
|
||||
|
||||
// Shortcuts
|
||||
Standard_Boolean bAvoidIN = (!isObjectsIN && !isToolsIN), // avoid all in faces
|
||||
bAvoidINforBoth = (isObjectsIN != isToolsIN); // avoid faces IN for both groups
|
||||
|
||||
// Choose which SD faces are needed to be taken - equally or differently oriented faces
|
||||
Standard_Boolean isSameOriNeeded = (theObjState == theToolsState);
|
||||
// Resulting faces
|
||||
TopTools_IndexedMapOfOrientedShape aMResFacesOri;
|
||||
TopTools_MapOfShape aMResFacesFence;
|
||||
// Fence map
|
||||
TopTools_MapOfShape aMFence, aMFToAvoid;
|
||||
// Oriented fence map
|
||||
TopTools_MapOfOrientedShape aMFenceOri;
|
||||
|
||||
for (Standard_Integer i = 0; i < 2; ++i)
|
||||
{
|
||||
const TopTools_IndexedMapOfOrientedShape& aMap = !i ? aMObjFacesOri : aMToolFacesOri;
|
||||
const TopTools_IndexedMapOfShape& anOppositeMap = !i ? aMToolFaces : aMObjFaces;
|
||||
const TopTools_MapOfShape& anINMap = !i ? anINObjects : anINTools;
|
||||
const TopTools_MapOfShape& anOppositeINMap = !i ? anINTools : anINObjects;
|
||||
const Standard_Boolean bTakeIN = !i ? isObjectsIN : isToolsIN;
|
||||
|
||||
const Standard_Integer aNbF = aMap.Extent();
|
||||
for (Standard_Integer j = 1; j <= aNbF; ++j)
|
||||
{
|
||||
TopoDS_Shape aFIm = aMap(j);
|
||||
|
||||
Standard_Boolean isIN = anINMap.Contains(aFIm);
|
||||
Standard_Boolean isINOpposite = anOppositeINMap.Contains(aFIm);
|
||||
|
||||
// Filtering for FUSE - avoid any IN faces
|
||||
if (bAvoidIN && (isIN || isINOpposite))
|
||||
continue;
|
||||
|
||||
// Filtering for CUT - avoid faces IN for both groups
|
||||
if (bAvoidINforBoth && isIN && isINOpposite)
|
||||
continue;
|
||||
|
||||
// Treatment of SD faces
|
||||
if (!aMFence.Add(aFIm))
|
||||
{
|
||||
if (!anOppositeMap.Contains(aFIm))
|
||||
{
|
||||
// The face belongs to only one group
|
||||
if (bTakeIN != isSameOriNeeded)
|
||||
aMFToAvoid.Add(aFIm);
|
||||
}
|
||||
else
|
||||
{
|
||||
// The face belongs to both groups.
|
||||
// Using its orientation decide if it is needed in the result or not.
|
||||
Standard_Boolean isSameOri = !aMFenceOri.Add(aFIm);
|
||||
if (isSameOriNeeded == isSameOri)
|
||||
{
|
||||
// Take the shape without classification
|
||||
if (aMResFacesFence.Add(aFIm))
|
||||
aMResFacesOri.Add(aFIm);
|
||||
}
|
||||
else
|
||||
// Remove the face
|
||||
aMFToAvoid.Add(aFIm);
|
||||
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!aMFenceOri.Add(aFIm))
|
||||
continue;
|
||||
|
||||
if (bTakeIN == isINOpposite)
|
||||
{
|
||||
if (isIN)
|
||||
{
|
||||
aMResFacesOri.Add(aFIm);
|
||||
aMResFacesOri.Add(aFIm.Reversed());
|
||||
}
|
||||
else if (bTakeIN && !isSameOriNeeded)
|
||||
aMResFacesOri.Add(aFIm.Reversed());
|
||||
else
|
||||
aMResFacesOri.Add(aFIm);
|
||||
aMResFacesFence.Add(aFIm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove the faces which has to be avoided
|
||||
TopTools_ListOfShape aResFaces;
|
||||
const Standard_Integer aNbRF = aMResFacesOri.Extent();
|
||||
for (Standard_Integer i = 1; i <= aNbRF; ++i)
|
||||
{
|
||||
const TopoDS_Shape& aRF = aMResFacesOri(i);
|
||||
if (!aMFToAvoid.Contains(aRF))
|
||||
aResFaces.Append(aRF);
|
||||
}
|
||||
|
||||
BRep_Builder aBB;
|
||||
|
||||
// Try to build closed solids from the faces
|
||||
BOPAlgo_BuilderSolid aBS;
|
||||
aBS.SetShapes(aResFaces);
|
||||
aBS.SetRunParallel(myRunParallel);
|
||||
aBS.SetContext(myContext);
|
||||
aBS.SetFuzzyValue(myFuzzyValue);
|
||||
aBS.SetProgressIndicator(myProgressIndicator);
|
||||
aBS.Perform();
|
||||
|
||||
// Resulting solids
|
||||
TopTools_ListOfShape aResSolids;
|
||||
|
||||
aMFence.Clear();
|
||||
if (!aBS.HasErrors())
|
||||
{
|
||||
// If any, add solids into resulting compound
|
||||
TopTools_ListIteratorOfListOfShape itA(aBS.Areas());
|
||||
for (; itA.More(); itA.Next())
|
||||
{
|
||||
const TopoDS_Shape& aSolid = itA.Value();
|
||||
// The solid must contain at least one face
|
||||
// from either of objects or tools
|
||||
TopExp_Explorer expF(aSolid, TopAbs_FACE);
|
||||
for (; expF.More(); expF.Next())
|
||||
{
|
||||
const TopoDS_Shape& aF = expF.Current();
|
||||
if (aMObjFacesOri.Contains(aF) || aMToolFacesOri.Contains(aF))
|
||||
break;
|
||||
}
|
||||
if (expF.More())
|
||||
{
|
||||
aResSolids.Append(aSolid);
|
||||
TopExp::MapShapes(aSolid, aMFence);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Collect unused faces
|
||||
TopoDS_Compound anUnUsedFaces;
|
||||
aBB.MakeCompound(anUnUsedFaces);
|
||||
|
||||
TopTools_ListOfShape::Iterator itLF(aResFaces);
|
||||
for (; itLF.More(); itLF.Next())
|
||||
{
|
||||
if (aMFence.Add(itLF.Value()))
|
||||
aBB.Add(anUnUsedFaces, itLF.Value());
|
||||
}
|
||||
|
||||
// Build blocks from the unused faces
|
||||
TopTools_ListOfShape aLCB;
|
||||
BOPTools_AlgoTools::MakeConnexityBlocks(anUnUsedFaces, TopAbs_EDGE, TopAbs_FACE, aLCB);
|
||||
|
||||
// Build solid from each block
|
||||
TopTools_ListIteratorOfListOfShape itCB(aLCB);
|
||||
for (; itCB.More(); itCB.Next())
|
||||
{
|
||||
const TopoDS_Shape& aCB = itCB.Value();
|
||||
TopoDS_Shell aShell;
|
||||
aBB.MakeShell(aShell);
|
||||
// Add faces of the block to the shell
|
||||
TopExp_Explorer anExpF(aCB, TopAbs_FACE);
|
||||
for (; anExpF.More(); anExpF.Next())
|
||||
aBB.Add(aShell, TopoDS::Face(anExpF.Current()));
|
||||
|
||||
BOPTools_AlgoTools::OrientFacesOnShell(aShell);
|
||||
// Make solid out of the shell
|
||||
TopoDS_Solid aSolid;
|
||||
aBB.MakeSolid(aSolid);
|
||||
aBB.Add(aSolid, aShell);
|
||||
// Add new solid to result
|
||||
aResSolids.Append(aSolid);
|
||||
}
|
||||
|
||||
if (!bAvoidIN)
|
||||
{
|
||||
// Fill solids with internal parts coming with the solids
|
||||
TopTools_ListOfShape anInParts;
|
||||
for (Standard_Integer i = 0; i < 2; ++i)
|
||||
{
|
||||
const TopTools_ListOfShape& aList = !i ? theObjects : theTools;
|
||||
TopTools_ListOfShape::Iterator itLS(aList);
|
||||
for (; itLS.More(); itLS.Next())
|
||||
{
|
||||
TopExp_Explorer expS(itLS.Value(), TopAbs_SOLID);
|
||||
for (; expS.More(); expS.Next())
|
||||
{
|
||||
const TopoDS_Shape& aS = expS.Current(); // Solid
|
||||
for (TopoDS_Iterator it(aS); it.More(); it.Next())
|
||||
{
|
||||
const TopoDS_Shape& aSInt = it.Value();
|
||||
if (aSInt.Orientation() == TopAbs_INTERNAL)
|
||||
anInParts.Append(aSInt); // vertex or edge
|
||||
else
|
||||
{
|
||||
// shell treatment
|
||||
TopoDS_Iterator itInt(aSInt);
|
||||
if (itInt.More() && itInt.Value().Orientation() == TopAbs_INTERNAL)
|
||||
anInParts.Append(aSInt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOPAlgo_Tools::FillInternals(aResSolids, anInParts, myImages, myContext);
|
||||
}
|
||||
|
||||
// Combine solids into compound
|
||||
TopoDS_Shape aResult;
|
||||
aBB.MakeCompound(TopoDS::Compound(aResult));
|
||||
|
||||
TopTools_ListOfShape::Iterator itLS(aResSolids);
|
||||
for (; itLS.More(); itLS.Next())
|
||||
aBB.Add(aResult, itLS.Value());
|
||||
|
||||
myShape = aResult;
|
||||
PrepareHistory();
|
||||
}
|
||||
|
@@ -25,6 +25,7 @@
|
||||
#include <BOPAlgo_PPaveFiller.hxx>
|
||||
#include <BOPAlgo_BuilderShape.hxx>
|
||||
#include <BOPAlgo_GlueEnum.hxx>
|
||||
#include <BOPAlgo_Operation.hxx>
|
||||
#include <BOPDS_PDS.hxx>
|
||||
#include <NCollection_BaseAllocator.hxx>
|
||||
#include <Standard_Integer.hxx>
|
||||
@@ -38,6 +39,7 @@
|
||||
class IntTools_Context;
|
||||
class TopoDS_Shape;
|
||||
class BOPAlgo_PaveFiller;
|
||||
class TopoDS_Solid;
|
||||
|
||||
//!
|
||||
//! The class is a General Fuse algorithm - base algorithm for the
|
||||
@@ -174,6 +176,114 @@ public: //! @name Performing the operation
|
||||
Standard_EXPORT virtual void PerformWithFiller (const BOPAlgo_PaveFiller& theFiller);
|
||||
|
||||
|
||||
public: //! @name BOPs on open solids
|
||||
|
||||
//! Builds the result shape according to the given states for the objects
|
||||
//! and tools. These states can be unambiguously converted into the Boolean operation type.
|
||||
//! Thus, it performs the Boolean operation on the given groups of shapes.
|
||||
//!
|
||||
//! The result is built basing on the result of Builder operation (GF or any other).
|
||||
//! The only condition for the Builder is that the splits of faces should be created
|
||||
//! and classified relatively solids.
|
||||
//!
|
||||
//! The method uses classification approach for choosing the faces which will
|
||||
//! participate in building the result shape:
|
||||
//! - All faces from each group having the given state for the opposite group
|
||||
//! will be taken into result.
|
||||
//!
|
||||
//! Such approach shows better results (in comparison with BOPAlgo_BuilderSolid approach)
|
||||
//! when working with open solids. However, the result may not be always
|
||||
//! correct on such data (at least, not as expected) as the correct classification
|
||||
//! of the faces relatively open solids is not always possible and may vary
|
||||
//! depending on the chosen classification point on the face.
|
||||
//!
|
||||
//! History is not created for the solids in this method.
|
||||
//!
|
||||
//! To avoid pollution of the report of Builder algorithm, there is a possibility to pass
|
||||
//! the different report to collect the alerts of the method only. But, if the new report
|
||||
//! is not given, the Builder report will be used.
|
||||
//! So, even if Builder passed without any errors, but some error has been stored into its report
|
||||
//! in this method, for the following calls the Builder report must be cleared.
|
||||
//!
|
||||
//! The method may set the following errors:
|
||||
//! - BOPAlgo_AlertBuilderFailed - Building operation has not been performed yet or failed;
|
||||
//! - BOPAlgo_AlertBOPNotSet - invalid BOP type is given (COMMON/FUSE/CUT/CUT21 are supported);
|
||||
//! - BOPAlgo_AlertTooFewArguments - arguments are not given;
|
||||
//! - BOPAlgo_AlertUnknownShape - the shape is unknown for the operation.
|
||||
//!
|
||||
//! Parameters:
|
||||
//! @param theObjects - The group of Objects for BOP;
|
||||
//! @param theObjState - State for objects faces to pass into result;
|
||||
//! @param theTools - The group of Tools for BOP;
|
||||
//! @param theObjState - State for tools faces to pass into result;
|
||||
//! @param theReport - The alternative report to avoid pollution of the main one.
|
||||
Standard_EXPORT virtual void BuildBOP(const TopTools_ListOfShape& theObjects,
|
||||
const TopAbs_State theObjState,
|
||||
const TopTools_ListOfShape& theTools,
|
||||
const TopAbs_State theToolsState,
|
||||
Handle(Message_Report) theReport = NULL);
|
||||
|
||||
//! Builds the result of Boolean operation of given type
|
||||
//! basing on the result of Builder operation (GF or any other).
|
||||
//!
|
||||
//! The method converts the given type of operation into the states
|
||||
//! for the objects and tools required for their face to pass into result
|
||||
//! and performs the call to the same method, but with states instead
|
||||
//! of operation type.
|
||||
//!
|
||||
//! The conversion looks as follows:
|
||||
//! - COMMON is built from the faces of objects located IN any of the tools
|
||||
//! and vice versa.
|
||||
//! - FUSE is built from the faces OUT of all given shapes;
|
||||
//! - CUT is built from the faces of the objects OUT of the tools and
|
||||
//! faces of the tools located IN solids of the objects.
|
||||
//!
|
||||
//! @param theObjects - The group of Objects for BOP;
|
||||
//! @param theTools - The group of Tools for BOP;
|
||||
//! @param theOperation - The BOP type;
|
||||
//! @param theReport - The alternative report to avoid pollution of the global one.
|
||||
void BuildBOP(const TopTools_ListOfShape& theObjects,
|
||||
const TopTools_ListOfShape& theTools,
|
||||
const BOPAlgo_Operation theOperation,
|
||||
Handle(Message_Report) theReport = NULL)
|
||||
{
|
||||
TopAbs_State anObjState, aToolsState;
|
||||
switch (theOperation)
|
||||
{
|
||||
case BOPAlgo_COMMON:
|
||||
{
|
||||
anObjState = TopAbs_IN;
|
||||
aToolsState = TopAbs_IN;
|
||||
break;
|
||||
}
|
||||
case BOPAlgo_FUSE:
|
||||
{
|
||||
anObjState = TopAbs_OUT;
|
||||
aToolsState = TopAbs_OUT;
|
||||
break;
|
||||
}
|
||||
case BOPAlgo_CUT:
|
||||
{
|
||||
anObjState = TopAbs_OUT;
|
||||
aToolsState = TopAbs_IN;
|
||||
break;
|
||||
}
|
||||
case BOPAlgo_CUT21:
|
||||
{
|
||||
anObjState = TopAbs_IN;
|
||||
aToolsState = TopAbs_OUT;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
anObjState = TopAbs_UNKNOWN;
|
||||
aToolsState = TopAbs_UNKNOWN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
BuildBOP(theObjects, anObjState, theTools, aToolsState, theReport);
|
||||
}
|
||||
|
||||
protected: //! @name History methods
|
||||
|
||||
//! Prepare information for history support.
|
||||
@@ -315,15 +425,11 @@ protected: //! @name Fill Images of SOLIDS
|
||||
TopTools_ListOfShape& theLIF);
|
||||
|
||||
//! Finds faces located inside each solid.
|
||||
Standard_EXPORT virtual void FillIn3DParts (TopTools_DataMapOfShapeListOfShape& theInParts,
|
||||
TopTools_DataMapOfShapeShape& theDraftSolids,
|
||||
const Handle(NCollection_BaseAllocator)& theAllocator);
|
||||
Standard_EXPORT virtual void FillIn3DParts(TopTools_DataMapOfShapeShape& theDraftSolids);
|
||||
|
||||
//! Builds the splits of the solids using their draft versions
|
||||
//! and faces located inside.
|
||||
Standard_EXPORT void BuildSplitSolids (TopTools_DataMapOfShapeListOfShape& theInParts,
|
||||
TopTools_DataMapOfShapeShape& theDraftSolids,
|
||||
const Handle(NCollection_BaseAllocator)& theAllocator);
|
||||
Standard_EXPORT void BuildSplitSolids(TopTools_DataMapOfShapeShape& theDraftSolids);
|
||||
|
||||
//! Classifies the vertices and edges from the arguments relatively
|
||||
//! splits of solids and makes them INTERNAL for solids.
|
||||
@@ -358,6 +464,7 @@ protected: //! @name Fields
|
||||
TopTools_DataMapOfShapeListOfShape myImages; //!< Images - map of Images of the sub-shapes of arguments
|
||||
TopTools_DataMapOfShapeShape myShapesSD; //!< ShapesSD - map of SD Shapes
|
||||
TopTools_DataMapOfShapeListOfShape myOrigins; //!< Origins - map of Origins, back map of Images
|
||||
TopTools_DataMapOfShapeListOfShape myInParts; //!< InParts - map of own and acquired IN faces of the arguments solids
|
||||
Standard_Boolean myNonDestructive; //!< Safe processing option allows avoiding modification of the input shapes
|
||||
BOPAlgo_GlueEnum myGlue; //!< Gluing option allows speeding up the intersection of the input shapes
|
||||
Standard_Boolean myCheckInverted; //!< Check inverted option allows disabling the check of input solids on inverted status
|
||||
|
@@ -23,6 +23,7 @@
|
||||
#include <TopAbs_State.hxx>
|
||||
//
|
||||
#include <TopoDS.hxx>
|
||||
#include <TopoDS_AlertWithShape.hxx>
|
||||
#include <TopoDS_Iterator.hxx>
|
||||
#include <TopoDS_Solid.hxx>
|
||||
#include <TopoDS_Shape.hxx>
|
||||
@@ -90,29 +91,21 @@ void BOPAlgo_Builder::FillImagesSolids()
|
||||
if (!bHasSolids) {
|
||||
return;
|
||||
}
|
||||
//
|
||||
Handle(NCollection_BaseAllocator) aAlr;
|
||||
//
|
||||
aAlr=NCollection_BaseAllocator::CommonBaseAllocator();
|
||||
//
|
||||
TopTools_DataMapOfShapeListOfShape theInParts(100, aAlr);
|
||||
TopTools_DataMapOfShapeShape theDraftSolids(100, aAlr);
|
||||
//
|
||||
FillIn3DParts(theInParts, theDraftSolids, aAlr);
|
||||
BuildSplitSolids(theInParts, theDraftSolids, aAlr);
|
||||
|
||||
// Draft solids
|
||||
TopTools_DataMapOfShapeShape aDraftSolids;
|
||||
// Find all IN faces for all IN faces
|
||||
FillIn3DParts(aDraftSolids);
|
||||
// Build split of the solids
|
||||
BuildSplitSolids(aDraftSolids);
|
||||
// Fill solids with internal parts
|
||||
FillInternalShapes();
|
||||
//
|
||||
theInParts.Clear();
|
||||
theDraftSolids.Clear();
|
||||
}
|
||||
//=======================================================================
|
||||
//function : FillIn3DParts
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void BOPAlgo_Builder::FillIn3DParts
|
||||
(TopTools_DataMapOfShapeListOfShape& theInParts,
|
||||
TopTools_DataMapOfShapeShape& theDraftSolids,
|
||||
const Handle(NCollection_BaseAllocator)& )
|
||||
void BOPAlgo_Builder::FillIn3DParts(TopTools_DataMapOfShapeShape& theDraftSolids)
|
||||
{
|
||||
Handle(NCollection_BaseAllocator) anAlloc = new NCollection_IncAllocator;
|
||||
|
||||
@@ -224,7 +217,7 @@ void BOPAlgo_Builder::FillIn3DParts
|
||||
if (aNbInt || aNbIN)
|
||||
{
|
||||
// Combine the lists
|
||||
TopTools_ListOfShape *pLIN = theInParts.Bound(aSolid, TopTools_ListOfShape());
|
||||
TopTools_ListOfShape *pLIN = myInParts.Bound(aSolid, TopTools_ListOfShape());
|
||||
|
||||
TopTools_ListIteratorOfListOfShape aItLS(aLInFaces);
|
||||
for (; aItLS.More(); aItLS.Next())
|
||||
@@ -360,10 +353,7 @@ typedef BOPTools_Cnt<BOPAlgo_BuilderSolidFunctor,
|
||||
//function : BuildSplitSolids
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void BOPAlgo_Builder::BuildSplitSolids
|
||||
(TopTools_DataMapOfShapeListOfShape& theInParts,
|
||||
TopTools_DataMapOfShapeShape& theDraftSolids,
|
||||
const Handle(NCollection_BaseAllocator)& )
|
||||
void BOPAlgo_Builder::BuildSplitSolids(TopTools_DataMapOfShapeShape& theDraftSolids)
|
||||
{
|
||||
Standard_Boolean bFlagSD;
|
||||
Standard_Integer i, aNbS;
|
||||
@@ -417,7 +407,7 @@ void BOPAlgo_Builder::BuildSplitSolids
|
||||
continue;
|
||||
|
||||
const TopoDS_Shape& aSD = theDraftSolids.Find(aS);
|
||||
const TopTools_ListOfShape* pLFIN = theInParts.Seek(aS);
|
||||
const TopTools_ListOfShape* pLFIN = myInParts.Seek(aS);
|
||||
if (!pLFIN || pLFIN->IsEmpty())
|
||||
{
|
||||
aSolidsIm(aSolidsIm.Add(aS, TopTools_ListOfShape())).Append(aSD);
|
||||
@@ -464,7 +454,35 @@ void BOPAlgo_Builder::BuildSplitSolids
|
||||
{
|
||||
BOPAlgo_SplitSolid& aBS = aVBS(k);
|
||||
aSolidsIm.Add(aBS.Solid(), aBS.Areas());
|
||||
myReport->Merge(aBS.GetReport());
|
||||
|
||||
// Merge BuilderSolid's report into main report,
|
||||
// assigning the solid with the warnings/errors which
|
||||
// have been generated for it.
|
||||
// Convert all errors of BuilderSolid into warnings for main report.
|
||||
const Handle(Message_Report)& aBSReport = aBS.GetReport();
|
||||
Message_Gravity anAlertTypes[2] = { Message_Warning, Message_Fail };
|
||||
for (Standard_Integer iGravity = 0; iGravity < 2; iGravity++)
|
||||
{
|
||||
const Message_ListOfAlert& anLAlerts = aBSReport->GetAlerts(anAlertTypes[iGravity]);
|
||||
for (Message_ListOfAlert::Iterator itA(anLAlerts); itA.More(); itA.Next())
|
||||
{
|
||||
Handle(Message_Alert) anAlert = itA.Value();
|
||||
|
||||
Handle(TopoDS_AlertWithShape) anAlertWithShape = Handle(TopoDS_AlertWithShape)::DownCast(itA.Value());
|
||||
if (!anAlertWithShape.IsNull())
|
||||
{
|
||||
TopoDS_Shape aWarnShape;
|
||||
BRep_Builder().MakeCompound(TopoDS::Compound(aWarnShape));
|
||||
BRep_Builder().Add(aWarnShape, aBS.Solid());
|
||||
BRep_Builder().Add(aWarnShape, anAlertWithShape->GetShape());
|
||||
|
||||
anAlertWithShape->SetShape(aWarnShape);
|
||||
AddWarning(anAlertWithShape);
|
||||
}
|
||||
else
|
||||
AddWarning(anAlert);
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
// Add new solids to images map
|
||||
|
@@ -332,97 +332,40 @@ void BOPAlgo_MakerVolume::FillInternalShapes(const TopTools_ListOfShape& theLSR)
|
||||
if (myAvoidInternalShapes) {
|
||||
return;
|
||||
}
|
||||
//
|
||||
|
||||
UserBreak();
|
||||
//
|
||||
Standard_Integer aNbSI;
|
||||
TopAbs_ShapeEnum aType;
|
||||
TopAbs_State aState;
|
||||
TopoDS_Iterator aItS;
|
||||
BRep_Builder aBB;
|
||||
|
||||
// Get all non-compound shapes
|
||||
TopTools_ListOfShape aLSC;
|
||||
// Fence map
|
||||
TopTools_MapOfShape aMFence;
|
||||
TopTools_IndexedMapOfShape aMSS;
|
||||
TopTools_ListOfShape aLVE, aLSC, aLSIn;
|
||||
TopTools_ListIteratorOfListOfShape aIt, aIt1;
|
||||
//
|
||||
// 1. Collect shapes to process: vertices, edges, wires
|
||||
const TopTools_ListOfShape& anArguments = myDS->Arguments();
|
||||
aIt.Initialize(anArguments);
|
||||
for (; aIt.More(); aIt.Next()) {
|
||||
const TopoDS_Shape& aS = aIt.Value();
|
||||
BOPAlgo_Tools::TreatCompound(aS, aMFence, aLSC);
|
||||
}
|
||||
//
|
||||
aIt.Initialize(aLSC);
|
||||
for (; aIt.More(); aIt.Next()) {
|
||||
const TopoDS_Shape& aS = aIt.Value();
|
||||
aType = aS.ShapeType();
|
||||
if (aType == TopAbs_WIRE) {
|
||||
aItS.Initialize(aS);
|
||||
for(; aItS.More(); aItS.Next()) {
|
||||
const TopoDS_Shape& aE = aItS.Value();
|
||||
if (aMFence.Add(aE)) {
|
||||
aLVE.Append(aE);
|
||||
}
|
||||
|
||||
TopTools_ListOfShape::Iterator itLA(myDS->Arguments());
|
||||
for (; itLA.More(); itLA.Next())
|
||||
BOPAlgo_Tools::TreatCompound(itLA.Value(), aMFence, aLSC);
|
||||
|
||||
// Get only edges and vertices from arguments
|
||||
TopTools_ListOfShape aLVE;
|
||||
|
||||
itLA.Initialize(aLSC);
|
||||
for (; itLA.More(); itLA.Next())
|
||||
{
|
||||
const TopoDS_Shape& aS = itLA.Value();
|
||||
TopAbs_ShapeEnum aType = aS.ShapeType();
|
||||
if (aType == TopAbs_WIRE)
|
||||
{
|
||||
for (TopoDS_Iterator it(aS); it.More(); it.Next())
|
||||
{
|
||||
const TopoDS_Shape& aSS = it.Value();
|
||||
if (aMFence.Add(aSS))
|
||||
aLVE.Append(aSS);
|
||||
}
|
||||
}
|
||||
else if (aType == TopAbs_VERTEX || aType == TopAbs_EDGE) {
|
||||
else if (aType == TopAbs_VERTEX || aType == TopAbs_EDGE)
|
||||
aLVE.Append(aS);
|
||||
}
|
||||
}
|
||||
//
|
||||
aIt.Initialize(theLSR);
|
||||
for (; aIt.More(); aIt.Next()) {
|
||||
const TopoDS_Shape& aS = aIt.Value();
|
||||
TopExp::MapShapes(aS, TopAbs_EDGE, aMSS);
|
||||
TopExp::MapShapes(aS, TopAbs_VERTEX, aMSS);
|
||||
}
|
||||
//
|
||||
aIt.Initialize(aLVE);
|
||||
for (; aIt.More(); aIt.Next()) {
|
||||
const TopoDS_Shape& aS = aIt.Value();
|
||||
if (myImages.IsBound(aS)) {
|
||||
const TopTools_ListOfShape &aLSp = myImages.Find(aS);
|
||||
aIt1.Initialize(aLSp);
|
||||
for (; aIt1.More(); aIt1.Next()) {
|
||||
const TopoDS_Shape& aSp = aIt1.Value();
|
||||
if (aMSS.Add(aSp)) {
|
||||
aLSIn.Append(aSp);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (aMSS.Add(aS)) {
|
||||
aLSIn.Append(aS);
|
||||
}
|
||||
}
|
||||
}
|
||||
//
|
||||
aNbSI = aLSIn.Extent();
|
||||
if (!aNbSI) {
|
||||
return;
|
||||
}
|
||||
//
|
||||
// 2. Settle internal vertices and edges into solids
|
||||
aIt.Initialize(theLSR);
|
||||
for (; aIt.More(); aIt.Next()) {
|
||||
TopoDS_Solid aSd = *(TopoDS_Solid*)&aIt.Value();
|
||||
//
|
||||
aIt1.Initialize(aLSIn);
|
||||
for (; aIt1.More(); ) {
|
||||
TopoDS_Shape aSI = aIt1.Value();
|
||||
aSI.Orientation(TopAbs_INTERNAL);
|
||||
//
|
||||
aState = BOPTools_AlgoTools::ComputeStateByOnePoint(aSI, aSd, 1.e-11, myContext);
|
||||
if (aState == TopAbs_IN) {
|
||||
aBB.Add(aSd, aSI);
|
||||
aLSIn.Remove(aIt1);
|
||||
}
|
||||
else {
|
||||
aIt1.Next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BOPAlgo_Tools::FillInternals(theLSR, aLVE, myImages, myContext);
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
|
@@ -1643,3 +1643,148 @@ void BOPAlgo_Tools::ClassifyFaces(const TopTools_ListOfShape& theFaces,
|
||||
theInParts.Add(aS, aLFIn);
|
||||
}
|
||||
}
|
||||
|
||||
//=======================================================================
|
||||
//function : FillInternals
|
||||
//purpose :
|
||||
//=======================================================================
|
||||
void BOPAlgo_Tools::FillInternals(const TopTools_ListOfShape& theSolids,
|
||||
const TopTools_ListOfShape& theParts,
|
||||
const TopTools_DataMapOfShapeListOfShape& theImages,
|
||||
const Handle(IntTools_Context)& theContext)
|
||||
{
|
||||
if (theSolids.IsEmpty() || theParts.IsEmpty())
|
||||
return;
|
||||
|
||||
// Map the solids to avoid classification of the own shapes of the solids
|
||||
TopTools_IndexedMapOfShape aMSSolids;
|
||||
TopTools_ListOfShape::Iterator itLS(theSolids);
|
||||
for (; itLS.More(); itLS.Next())
|
||||
{
|
||||
const TopoDS_Shape& aSolid = itLS.Value();
|
||||
if (aSolid.ShapeType() == TopAbs_SOLID)
|
||||
{
|
||||
TopExp::MapShapes(aSolid, TopAbs_VERTEX, aMSSolids);
|
||||
TopExp::MapShapes(aSolid, TopAbs_EDGE, aMSSolids);
|
||||
TopExp::MapShapes(aSolid, TopAbs_FACE, aMSSolids);
|
||||
}
|
||||
}
|
||||
|
||||
// Extract BRep elements from the given parts and
|
||||
// check them for possible splits
|
||||
TopTools_ListOfShape aLPartsInput = theParts, aLParts;
|
||||
TopTools_ListOfShape::Iterator itLP(aLPartsInput);
|
||||
for (; itLP.More(); itLP.Next())
|
||||
{
|
||||
const TopoDS_Shape& aPart = itLP.Value();
|
||||
switch (aPart.ShapeType())
|
||||
{
|
||||
case TopAbs_VERTEX:
|
||||
case TopAbs_EDGE:
|
||||
case TopAbs_FACE:
|
||||
{
|
||||
const TopTools_ListOfShape* pIm = theImages.Seek(aPart);
|
||||
if (pIm)
|
||||
{
|
||||
TopTools_ListOfShape::Iterator itIm(*pIm);
|
||||
for (; itIm.More(); itIm.Next())
|
||||
{
|
||||
const TopoDS_Shape& aPartIm = itIm.Value();
|
||||
if (!aMSSolids.Contains(aPartIm))
|
||||
aLParts.Append(aPartIm);
|
||||
}
|
||||
}
|
||||
else if (!aMSSolids.Contains(aPart))
|
||||
aLParts.Append(aPart);
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
for (TopoDS_Iterator it(aPart); it.More(); it.Next())
|
||||
aLPartsInput.Append(it.Value());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Classify the given parts relatively solids.
|
||||
// Add edges and vertices classified as IN into solids instantly,
|
||||
// and collect faces classified as IN into a list for further shell creation
|
||||
|
||||
TopTools_DataMapOfShapeListOfShape anINFaces;
|
||||
itLS.Initialize(theSolids);
|
||||
for (; itLS.More(); itLS.Next())
|
||||
{
|
||||
const TopoDS_Shape& aSolid = itLS.Value();
|
||||
if (aSolid.ShapeType() != TopAbs_SOLID)
|
||||
continue;
|
||||
|
||||
TopoDS_Solid aSd = *(TopoDS_Solid*)&aSolid;
|
||||
|
||||
itLP.Initialize(aLParts);
|
||||
for (; itLP.More();)
|
||||
{
|
||||
TopoDS_Shape aPart = itLP.Value();
|
||||
TopAbs_State aState =
|
||||
BOPTools_AlgoTools::ComputeStateByOnePoint(aPart, aSd, Precision::Confusion(), theContext);
|
||||
if (aState == TopAbs_IN)
|
||||
{
|
||||
if (aPart.ShapeType() == TopAbs_FACE)
|
||||
{
|
||||
TopTools_ListOfShape *pFaces = anINFaces.ChangeSeek(aSd);
|
||||
if (!pFaces)
|
||||
pFaces = anINFaces.Bound(aSd, TopTools_ListOfShape());
|
||||
pFaces->Append(aPart);
|
||||
}
|
||||
else
|
||||
{
|
||||
aPart.Orientation(TopAbs_INTERNAL);
|
||||
BRep_Builder().Add(aSd, aPart);
|
||||
}
|
||||
aLParts.Remove(itLP);
|
||||
}
|
||||
else
|
||||
itLP.Next();
|
||||
}
|
||||
}
|
||||
|
||||
// Make shells from faces and put them into solids
|
||||
TopTools_DataMapOfShapeListOfShape::Iterator itM(anINFaces);
|
||||
for (; itM.More(); itM.Next())
|
||||
{
|
||||
TopoDS_Solid aSd = *(TopoDS_Solid*)&itM.Key();
|
||||
const TopTools_ListOfShape& aFaces = itM.Value();
|
||||
|
||||
TopoDS_Compound aCF;
|
||||
BRep_Builder().MakeCompound(aCF);
|
||||
|
||||
TopTools_ListOfShape::Iterator itLF(aFaces);
|
||||
for (; itLF.More(); itLF.Next())
|
||||
BRep_Builder().Add(aCF, itLF.Value());
|
||||
|
||||
// Build blocks from the faces
|
||||
TopTools_ListOfShape aLCB;
|
||||
BOPTools_AlgoTools::MakeConnexityBlocks(aCF, TopAbs_EDGE, TopAbs_FACE, aLCB);
|
||||
|
||||
// Build shell from each block
|
||||
TopTools_ListOfShape::Iterator itCB(aLCB);
|
||||
for (; itCB.More(); itCB.Next())
|
||||
{
|
||||
const TopoDS_Shape& aCB = itCB.Value();
|
||||
|
||||
TopoDS_Shell aShell;
|
||||
BRep_Builder().MakeShell(aShell);
|
||||
// Add faces of the block to the shell
|
||||
TopExp_Explorer expF(aCB, TopAbs_FACE);
|
||||
for (; expF.More(); expF.Next())
|
||||
{
|
||||
TopoDS_Face aFInt = TopoDS::Face(expF.Current());
|
||||
aFInt.Orientation(TopAbs_INTERNAL);
|
||||
BRep_Builder().Add(aShell, aFInt);
|
||||
}
|
||||
|
||||
BRep_Builder().Add(aSd, aShell);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -194,6 +194,18 @@ public:
|
||||
const TopTools_DataMapOfShapeBox& theShapeBoxMap = TopTools_DataMapOfShapeBox(),
|
||||
const TopTools_DataMapOfShapeListOfShape& theSolidsIF = TopTools_DataMapOfShapeListOfShape());
|
||||
|
||||
//! Classifies the given parts relatively the given solids and
|
||||
//! fills the solids with the parts classified as INTERNAL.
|
||||
//!
|
||||
//! @param theSolids - The solids to put internals to
|
||||
//! @param theParts - The parts to classify relatively solids
|
||||
//! @param theImages - Possible images of the parts that has to be classified
|
||||
//! @param theContext - Cashed geometrical tools to speed-up classifications
|
||||
Standard_EXPORT static void FillInternals(const TopTools_ListOfShape& theSolids,
|
||||
const TopTools_ListOfShape& theParts,
|
||||
const TopTools_DataMapOfShapeListOfShape& theImages,
|
||||
const Handle(IntTools_Context)& theContext);
|
||||
|
||||
};
|
||||
|
||||
#endif // _BOPAlgo_Tools_HeaderFile
|
||||
|
Reference in New Issue
Block a user