1
0
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:
emv
2018-09-07 15:24:49 +03:00
committed by bugmaster
parent 60b1a085c7
commit 13c0e40223
35 changed files with 1686 additions and 446 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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 :

View File

@@ -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;

View File

@@ -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";

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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

View File

@@ -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);
}
//=======================================================================

View File

@@ -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);
}
}
}

View File

@@ -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