1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00
occt/src/BRepFeat/BRepFeat_Builder.cxx
emv 81a55a6996 0029333: Boolean Operations - Prevent modification of the input shapes in case their sub-shapes have not been modified
Prevent modification of the input shapes in destructive mode in case their sub-shapes have not been modified:
1. Prevent edge splitting for the pave blocks with old vertices if it is possible to use the existing edge (*BOPAlgo_PaveFiller::MakeSplitEdges*);
2. Prevent creation of the new containers (WIRES/SHELLS/COMPSOLIDS) if non of its parts have been modified (*BOPAlgo_Builder::FillImagesContainer*);
3. Prevent creation of the new face if non of its wires have been modified (*BOPAlgo_Builder::FillImagesFaces*);
4. If possible, use the original face to be the representative for the group of SD faces (*BOPAlgo_Builder::FillSameDomainFaces*).

Cosmetic changes:
1. Documentation of the *BOPAlgo_Builder* class.
2. Making simple methods of the *BOPAlgo_Builder* class inline.
3. Getting rid of the *BOPAlgo_Builder::mySplits* field as it is excessive. *BOPAlgo_Builder::myImages* can be used instead.
3. Moving the Check Inverted option from *BOPAlgo_Options* to *BOPAlgo_Builder*.

Test cases for the issue.
Adjustment of the test case to their current behavior.
Test case *blend/complex/H2* has been deleted as duplicate of the test case *blend/simple/Z1*.
2017-11-30 12:11:20 +03:00

970 lines
27 KiB
C++

// Created on: 2012-06-01
// Created by: Eugeny MALTCHIKOV
// Copyright (c) 1999-2014 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <BOPAlgo_BuilderFace.hxx>
#include <BOPDS_DS.hxx>
#include <BOPDS_FaceInfo.hxx>
#include <BOPDS_ListOfPave.hxx>
#include <BOPDS_ListOfPaveBlock.hxx>
#include <BOPDS_MapOfPaveBlock.hxx>
#include <BOPDS_Pave.hxx>
#include <BOPDS_ShapeInfo.hxx>
#include <BOPTools_AlgoTools.hxx>
#include <BOPTools_AlgoTools2D.hxx>
#include <BOPTools_AlgoTools3D.hxx>
#include <BOPTools_MapOfSet.hxx>
#include <BRep_Builder.hxx>
#include <BRep_Tool.hxx>
#include <BRepBndLib.hxx>
#include <BRepFeat_Builder.hxx>
#include <Geom_Curve.hxx>
#include <IntTools_Tools.hxx>
#include <Precision.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <TopoDS_Edge.hxx>
#include <TopoDS_Face.hxx>
#include <TopoDS_Shape.hxx>
#include <TopTools_ListIteratorOfListOfShape.hxx>
#include <TopTools_DataMapOfShapeListOfShape.hxx>
//=======================================================================
//function :
//purpose :
//=======================================================================
BRepFeat_Builder::BRepFeat_Builder()
:
BOPAlgo_BOP()
{
Clear();
}
//=======================================================================
//function : ~
//purpose :
//=======================================================================
BRepFeat_Builder::~BRepFeat_Builder()
{
}
//=======================================================================
//function : Clear
//purpose :
//=======================================================================
void BRepFeat_Builder::Clear()
{
myShapes.Clear();
myRemoved.Clear();
BOPAlgo_BOP::Clear();
}
//=======================================================================
//function : Init
//purpose :
//=======================================================================
void BRepFeat_Builder::Init(const TopoDS_Shape& theShape)
{
Clear();
//
AddArgument(theShape);
}
//=======================================================================
//function : Init
//purpose :
//=======================================================================
void BRepFeat_Builder::Init(const TopoDS_Shape& theShape,
const TopoDS_Shape& theTool)
{
Clear();
//
AddArgument(theShape);
AddTool(theTool);
}
//=======================================================================
//function : SetOperation
//purpose :
//=======================================================================
void BRepFeat_Builder::SetOperation(const Standard_Integer theFuse)
{
myFuse = theFuse;
myOperation = myFuse ? BOPAlgo_FUSE : BOPAlgo_CUT;
}
//=======================================================================
//function : SetOperation
//purpose :
//=======================================================================
void BRepFeat_Builder::SetOperation(const Standard_Integer theFuse,
const Standard_Boolean theFlag)
{
myFuse = theFuse;
if (!theFlag) {
myOperation = myFuse ? BOPAlgo_FUSE : BOPAlgo_CUT;
} else {
myOperation = myFuse ? BOPAlgo_CUT21 : BOPAlgo_COMMON;
}
}
//=======================================================================
//function : PartsOfTool
//purpose :
//=======================================================================
void BRepFeat_Builder::PartsOfTool(TopTools_ListOfShape& aLT)
{
TopExp_Explorer aExp;
//
aLT.Clear();
aExp.Init(myShape, TopAbs_SOLID);
for (;aExp.More(); aExp.Next()) {
const TopoDS_Shape& aS = aExp.Current();
aLT.Append(aS);
}
}
//=======================================================================
//function : KeepPartsOfTool
//purpose :
//=======================================================================
void BRepFeat_Builder::KeepParts(const TopTools_ListOfShape& theIm)
{
TopTools_ListIteratorOfListOfShape aItT;
aItT.Initialize(theIm);
for (; aItT.More(); aItT.Next()) {
const TopoDS_Shape& aTIm=aItT.Value();
KeepPart(aTIm);
}
}
//=======================================================================
//function : KeepPart
//purpose :
//=======================================================================
void BRepFeat_Builder::KeepPart(const TopoDS_Shape& thePart)
{
TopoDS_Shape aF, aFOr;
TopExp_Explorer aExp;
//
TopExp::MapShapes(thePart, myShapes);
}
//=======================================================================
//function : Prepare
//purpose :
//=======================================================================
void BRepFeat_Builder::Prepare()
{
GetReport()->Clear();
//
BRep_Builder aBB;
TopoDS_Compound aC;
aBB.MakeCompound(aC);
myShape=aC;
//
myFlagHistory=Standard_True;
//
FillRemoved();
}
//=======================================================================
//function : FillRemoved
//purpose :
//=======================================================================
void BRepFeat_Builder::FillRemoved()
{
TopExp_Explorer aExp;
//
const TopoDS_Shape& aArgs0=myArguments.First();
const TopoDS_Shape& aArgs1=myTools.First();
//
aExp.Init(aArgs0, TopAbs_SOLID);
for (; aExp.More(); aExp.Next()) {
const TopoDS_Shape& aS = aExp.Current();
myImages.UnBind(aS);
}
//
if (!myImages.IsBound(aArgs1)) {
return;
}
//
TopTools_ListIteratorOfListOfShape aItIm;
//
TopTools_ListOfShape& aLS = myImages.ChangeFind(aArgs1);
aItIm.Initialize(aLS);
for (; aItIm.More(); aItIm.Next()) {
const TopoDS_Shape& aS = aItIm.Value();
FillRemoved(aS, myRemoved);
}
}
//=======================================================================
//function : PerformResult
//purpose :
//=======================================================================
void BRepFeat_Builder::PerformResult()
{
myOperation = myFuse ? BOPAlgo_FUSE : BOPAlgo_CUT;
//
if (!myShapes.IsEmpty()) {
//
Prepare();
//
RebuildFaces();
//
FillImagesContainers(TopAbs_SHELL);
if (HasErrors()) {
return;
}
//
FillImagesSolids();
if (HasErrors()) {
return;
}
//
CheckSolidImages();
//
BuildResult(TopAbs_SOLID);
if (HasErrors()) {
return;
}
//
FillImagesCompounds();
if (HasErrors()) {
return;
}
//
BuildResult(TopAbs_COMPOUND);
if (HasErrors()) {
return;
}
}
//
BuildShape();
}
//=======================================================================
//function : RebuildFaces
//purpose :
//=======================================================================
void BRepFeat_Builder::RebuildFaces()
{
Standard_Integer aNbS, i, iRank, nSp, j;
Standard_Boolean bIsClosed, bIsDegenerated, bToReverse,
bRem, bIm, bFlagSD, bVInShapes;
TopAbs_Orientation anOriF, anOriE;
TopoDS_Face aFF, aFSD;
TopoDS_Edge aSp;
TopoDS_Shape aSx;
TopExp_Explorer aExp, aExpE;
TopTools_MapOfShape aME, aMESplit;
TopTools_ListIteratorOfListOfShape aItIm;
BOPDS_MapIteratorOfMapOfPaveBlock aItMPB;
TopTools_MapIteratorOfMapOfShape aItM;
BOPTools_MapOfSet aMST;
TopTools_ListOfShape aLE;
//
aItM.Initialize(myShapes);
for (; aItM.More(); aItM.Next()) {
const TopoDS_Shape& aS = aItM.Value();
if (aS.ShapeType() == TopAbs_FACE) {
BOPTools_Set aST;
aST.Add(aS, TopAbs_EDGE);
aMST.Add(aST);
}
}
//
aNbS=myDS->NbSourceShapes();
for (i=0; i<aNbS; ++i) {
const BOPDS_ShapeInfo& aSI=myDS->ShapeInfo(i);
//
iRank = myDS->Rank(i);
if (iRank == 1) {
const TopoDS_Shape& aS = aSI.Shape();
//
if (myImages.IsBound(aS)) {
TopTools_ListOfShape& aLIm = myImages.ChangeFind(aS);
aItIm.Initialize(aLIm);
for (; aItIm.More(); ) {
const TopoDS_Shape& aSIm = aItIm.Value();
if (!myShapes.Contains(aSIm)) {
aLIm.Remove(aItIm);
continue;
}
aItIm.Next();
}
}
continue;
}
//
if (aSI.ShapeType()!=TopAbs_FACE) {
continue;
}
//
const BOPDS_FaceInfo& aFI=myDS->FaceInfo(i);
const TopoDS_Face& aF=(*(TopoDS_Face*)(&aSI.Shape()));
//
if (!myImages.IsBound(aF)) {
continue;
}
//
anOriF=aF.Orientation();
aFF=aF;
aFF.Orientation(TopAbs_FORWARD);
const BOPDS_IndexedMapOfPaveBlock& aMPBIn=aFI.PaveBlocksIn();
const BOPDS_IndexedMapOfPaveBlock& aMPBSc=aFI.PaveBlocksSc();
aLE.Clear();
//bounding edges
aExp.Init(aFF, TopAbs_EDGE);
for (; aExp.More(); aExp.Next()) {
const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
anOriE=aE.Orientation();
bIsDegenerated=BRep_Tool::Degenerated(aE);
bIsClosed=BRep_Tool::IsClosed(aE, aF);
if (myImages.IsBound(aE)) {
TopTools_ListOfShape& aLEIm = myImages.ChangeFind(aE);
//
bRem = Standard_False;
bIm = Standard_False;
aME.Clear();
TopTools_ListOfShape aLEImNew;
//
aItIm.Initialize(aLEIm);
for (; aItIm.More(); aItIm.Next()) {
const TopoDS_Shape& aS = aItIm.Value();
bVInShapes = Standard_False;
if (myShapes.Contains(aS)) {
bVInShapes = Standard_True;
} else {
aExpE.Init(aS, TopAbs_VERTEX);
for(;aExpE.More(); aExpE.Next()) {
const TopoDS_Shape& aV = aExpE.Current();
if (myShapes.Contains(aV)) {
bVInShapes = Standard_True;
break;
}
}
}
//
if (bVInShapes) {
bIm = Standard_True;
aLEImNew.Append(aS);
} else {
bRem = Standard_True;
aME.Add(aS);
}
}
//
if (!bIm) {
aLE.Append(aE);
continue;
}
//
if (bRem && bIm) {
if (aLEIm.Extent() == 2) {
aLE.Append(aE);
continue;
}
if (aMESplit.Add(aE)) {
RebuildEdge(aE, aFF, aME, aLEImNew);
aLEIm.Assign(aLEImNew);
if (aLEIm.Extent() == 1) {
aLE.Append(aE);
continue;
}
}
}
//
aItIm.Initialize(aLEIm);
for (; aItIm.More(); aItIm.Next()) {
aSp = *(TopoDS_Edge*)&aItIm.Value();
if (bIsDegenerated) {
aSp.Orientation(anOriE);
aLE.Append(aSp);
continue;
}
//
if (anOriE==TopAbs_INTERNAL) {
aSp.Orientation(TopAbs_FORWARD);
aLE.Append(aSp);
aSp.Orientation(TopAbs_REVERSED);
aLE.Append(aSp);
continue;
}
//
if (bIsClosed) {
if (!BRep_Tool::IsClosed(aSp, aFF)){
BOPTools_AlgoTools3D::DoSplitSEAMOnFace(aSp, aFF);
}
//
aSp.Orientation(TopAbs_FORWARD);
aLE.Append(aSp);
aSp.Orientation(TopAbs_REVERSED);
aLE.Append(aSp);
continue;
}// if (bIsClosed){
//
aSp.Orientation(anOriE);
bToReverse=BOPTools_AlgoTools::IsSplitToReverse(aSp, aE, myContext);
if (bToReverse) {
aSp.Reverse();
}
aLE.Append(aSp);
}
}
else {
aLE.Append(aE);
}
}
Standard_Integer aNbPBIn, aNbPBSc;
aNbPBIn = aMPBIn.Extent();
aNbPBSc = aMPBSc.Extent();
//
//in edges
for (j=1; j<=aNbPBIn; ++j) {
const Handle(BOPDS_PaveBlock)& aPB=aMPBIn(j);
nSp=aPB->Edge();
aSp=(*(TopoDS_Edge*)(&myDS->Shape(nSp)));
if (myRemoved.Contains(aSp)) {
continue;
}
//
aSp.Orientation(TopAbs_FORWARD);
aLE.Append(aSp);
aSp.Orientation(TopAbs_REVERSED);
aLE.Append(aSp);
}
//section edges
for (j=1; j<=aNbPBSc; ++j) {
const Handle(BOPDS_PaveBlock)& aPB=aMPBSc(j);
nSp=aPB->Edge();
aSp=(*(TopoDS_Edge*)(&myDS->Shape(nSp)));
if (myRemoved.Contains(aSp)) {
continue;
}
//
aSp.Orientation(TopAbs_FORWARD);
aLE.Append(aSp);
aSp.Orientation(TopAbs_REVERSED);
aLE.Append(aSp);
}
//build new faces
BOPAlgo_BuilderFace aBF;
aBF.SetFace(aFF);
aBF.SetShapes(aLE);
aBF.Perform();
TopTools_ListOfShape& aLFIm = myImages.ChangeFind(aF);
aLFIm.Clear();
const TopTools_ListOfShape& aLFR=aBF.Areas();
aItIm.Initialize(aLFR);
for (; aItIm.More(); aItIm.Next()) {
TopoDS_Shape& aFR=aItIm.ChangeValue();
//
BOPTools_Set aST;
aST.Add(aFR, TopAbs_EDGE);
bFlagSD=aMST.Contains(aST);
//
const BOPTools_Set& aSTx=aMST.Added(aST);
aSx=aSTx.Shape();
aSx.Orientation(anOriF);
aLFIm.Append(aSx);
//
TopTools_ListOfShape* pLOr = myOrigins.ChangeSeek(aSx);
if (!pLOr) {
pLOr = myOrigins.Bound(aSx, TopTools_ListOfShape());
}
pLOr->Append(aF);
//
if (bFlagSD) {
myShapesSD.Bind(aFR, aSx);
}
}
//
if (aLFIm.Extent() == 0) {
myImages.UnBind(aF);
}
}
}
//=======================================================================
//function : RebuildEdge
//purpose :
//=======================================================================
void BRepFeat_Builder::RebuildEdge(const TopoDS_Shape& theE,
const TopoDS_Face& theF,
const TopTools_MapOfShape& aME,
TopTools_ListOfShape& aLIm)
{
Standard_Integer nE, nSp, nV1, nV2, nE1, nV, nVx, nVSD;
Standard_Integer nV11, nV21;
Standard_Boolean bOld;
Standard_Real aT11, aT21;
Standard_Real aT1, aT2;
TopoDS_Edge aSp, aE;
BOPDS_ShapeInfo aSI;
TopoDS_Vertex aV1, aV2;
Handle(BOPDS_PaveBlock) aPBNew;
TColStd_MapOfInteger aMI, aMAdd, aMV, aMVOr;
BOPDS_ListIteratorOfListOfPaveBlock aItPB;
TopTools_ListIteratorOfListOfShape aIt;
TColStd_ListIteratorOfListOfInteger aItLI;
TopTools_MapIteratorOfMapOfShape aItM;
BOPDS_MapOfPaveBlock aMPB;
BOPDS_MapIteratorOfMapOfPaveBlock aItMPB;
//
aSI.SetShapeType(TopAbs_EDGE);
//1. collect origin vertices to aMV map.
nE = myDS->Index(theE);
const BOPDS_ShapeInfo& aSIE = myDS->ShapeInfo(nE);
const TColStd_ListOfInteger& aLS = aSIE.SubShapes();
aItLI.Initialize(aLS);
for(; aItLI.More(); aItLI.Next()) {
nV = aItLI.Value();
nVx=nV;
if (myDS->HasShapeSD(nV, nVSD)) {
nVx=nVSD;
}
aMV.Add(nVx);
aMVOr.Add(nVx);
}
//
//2. collect vertices that should be removed to aMI map.
aPBNew = new BOPDS_PaveBlock;
BOPDS_ListOfPave& aLPExt = aPBNew->ChangeExtPaves();
BOPDS_ListOfPaveBlock& aLPB = myDS->ChangePaveBlocks(nE);
//
for (aItPB.Initialize(aLPB); aItPB.More(); aItPB.Next()) {
const Handle(BOPDS_PaveBlock)& aPB = aItPB.Value();
nE1 = aPB->Edge();
const TopoDS_Shape& aE1 = myDS->Shape(nE1);
//
if (aME.Contains(aE1)) {
aPB->Indices(nV1, nV2);
aMI.Add(nV1);
aMI.Add(nV2);
}
else {
aMPB.Add(aPB);
}
}
//3. collect vertices that split the source shape.
for (aItPB.Initialize(aLPB); aItPB.More(); aItPB.Next()) {
const Handle(BOPDS_PaveBlock)& aPB = aItPB.Value();
aPB->Indices(nV1, nV2);
//
if (!aMI.Contains(nV1)) {
aMV.Add(nV1);
}
if (!aMI.Contains(nV2)) {
aMV.Add(nV2);
}
}
//4. collect ext paves.
for (aItPB.Initialize(aLPB); aItPB.More(); aItPB.Next()) {
const Handle(BOPDS_PaveBlock)& aPB = aItPB.Value();
aPB->Indices(nV1, nV2);
//
if (aMV.Contains(nV1)) {
if (aMAdd.Add(nV1) || aMVOr.Contains(nV1)) {
aLPExt.Append(aPB->Pave1());
}
}
//
if (aMV.Contains(nV2)) {
if (aMAdd.Add(nV2) || aMVOr.Contains(nV2)) {
aLPExt.Append(aPB->Pave2());
}
}
}
aE = (*(TopoDS_Edge *)(&theE));
aE.Orientation(TopAbs_FORWARD);
//
aLIm.Clear();
//
//5. split edge by new set of vertices.
aLPB.Clear();
aPBNew->SetOriginalEdge(nE);
aPBNew->Update(aLPB, Standard_False);
//
for (aItPB.Initialize(aLPB); aItPB.More(); aItPB.Next()) {
Handle(BOPDS_PaveBlock)& aPB = aItPB.ChangeValue();
const BOPDS_Pave& aPave1=aPB->Pave1();
aPave1.Contents(nV1, aT1);
//
const BOPDS_Pave& aPave2=aPB->Pave2();
aPave2.Contents(nV2, aT2);
//
aItMPB.Initialize(aMPB);
//check if it is the old pave block.
bOld = Standard_False;
for (; aItMPB.More(); aItMPB.Next()) {
const Handle(BOPDS_PaveBlock)& aPB1 = aItMPB.Value();
aPB1->Indices(nV11, nV21);
aPB1->Range(aT11, aT21);
if (nV1 == nV11 && nV2 == nV21 &&
aT1 == aT11 && aT2 == aT21) {
const TopoDS_Shape& aEIm = myDS->Shape(aPB1->Edge());
aLIm.Append(aEIm);
bOld = Standard_True;
break;
}
}
if (bOld) {
continue;
}
//
aV1=(*(TopoDS_Vertex *)(&myDS->Shape(nV1)));
aV1.Orientation(TopAbs_FORWARD);
//
aV2=(*(TopoDS_Vertex *)(&myDS->Shape(nV2)));
aV2.Orientation(TopAbs_REVERSED);
//
BOPTools_AlgoTools::MakeSplitEdge(aE, aV1, aT1, aV2, aT2, aSp);
BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(aSp, theF, myContext);
//
aSI.SetShape(aSp);
//
Bnd_Box& aBox=aSI.ChangeBox();
BRepBndLib::Add(aSp, aBox);
//
nSp=myDS->Append(aSI);
//
aPB->SetEdge(nSp);
aLIm.Append(aSp);
}
}
//=======================================================================
//function : CheckSolidImages
//purpose :
//=======================================================================
void BRepFeat_Builder::CheckSolidImages()
{
BOPTools_MapOfSet aMST;
TopTools_ListOfShape aLSImNew;
TopTools_MapOfShape aMS;
TopTools_ListIteratorOfListOfShape aIt;
TopExp_Explorer aExp, aExpF;
Standard_Boolean bFlagSD;
//
const TopoDS_Shape& aArgs0=myArguments.First();
const TopoDS_Shape& aArgs1=myTools.First();
//
const TopTools_ListOfShape& aLSIm = myImages.Find(aArgs1);
aIt.Initialize(aLSIm);
for(;aIt.More();aIt.Next()) {
const TopoDS_Shape& aSolIm = aIt.Value();
//
BOPTools_Set aST;
aST.Add(aSolIm, TopAbs_FACE);
aMST.Add(aST);
}
//
aExp.Init(aArgs0, TopAbs_SOLID);
for(; aExp.More(); aExp.Next()) {
const TopoDS_Shape& aSolid = aExp.Current();
if (myImages.IsBound(aSolid)) {
TopTools_ListOfShape& aLSImSol = myImages.ChangeFind(aSolid);
aIt.Initialize(aLSImSol);
for(;aIt.More();aIt.Next()) {
const TopoDS_Shape& aSolIm = aIt.Value();
//
BOPTools_Set aST;
aST.Add(aSolIm, TopAbs_FACE);
bFlagSD=aMST.Contains(aST);
//
const BOPTools_Set& aSTx=aMST.Added(aST);
const TopoDS_Shape& aSx=aSTx.Shape();
aLSImNew.Append(aSx);
//
if (bFlagSD) {
myShapesSD.Bind(aSolIm, aSx);
}
}
aLSImSol.Assign(aLSImNew);
}
}
}
//=======================================================================
//function : MapShapes
//purpose :
//=======================================================================
void BRepFeat_Builder::FillRemoved(const TopoDS_Shape& S,
TopTools_MapOfShape& M)
{
if (myShapes.Contains(S)) {
return;
}
//
M.Add(S);
TopoDS_Iterator It(S);
while (It.More()) {
FillRemoved(It.Value(),M);
It.Next();
}
}
//=======================================================================
//function : FillIn3DParts
//purpose :
//=======================================================================
void BRepFeat_Builder::FillIn3DParts(TopTools_DataMapOfShapeListOfShape& theInParts,
TopTools_DataMapOfShapeShape& theDraftSolids,
const Handle(NCollection_BaseAllocator)& theAllocator)
{
GetReport()->Clear();
//
Standard_Boolean bIsIN, bHasImage;
Standard_Integer aNbS, i, j, aNbFP, aNbFPx, aNbFIN, aNbLIF, aNbEFP;
TopAbs_ShapeEnum aType;
TopAbs_State aState;
TopoDS_Iterator aIt, aItF;
BRep_Builder aBB;
TopoDS_Solid aSolidSp;
TopoDS_Face aFP;
TopTools_ListIteratorOfListOfShape aItS, aItFP, aItEx;
TopTools_MapIteratorOfMapOfShape aItMS, aItMS1;
//
TopTools_ListOfShape aLIF(theAllocator);
TopTools_MapOfShape aMFDone(100, theAllocator);
TopTools_MapOfShape aMSolids(100, theAllocator);
TopTools_MapOfShape aMFaces(100, theAllocator);
TopTools_MapOfShape aMFIN(100, theAllocator);
TopTools_IndexedMapOfShape aMS(100, theAllocator);
TopTools_IndexedDataMapOfShapeListOfShape aMEF(100, theAllocator);
//
theDraftSolids.Clear();
//
aNbS=myDS->NbSourceShapes();
for (i=0; i<aNbS; ++i) {
const BOPDS_ShapeInfo& aSI=myDS->ShapeInfo(i);
const TopoDS_Shape& aS=aSI.Shape();
//
aType=aSI.ShapeType();
switch(aType) {
case TopAbs_SOLID: {
aMSolids.Add(aS);
break;
}
//
case TopAbs_FACE: {
// all faces (originals or images)
if (myImages.IsBound(aS)) {
const TopTools_ListOfShape& aLS=myImages.Find(aS);
aItS.Initialize(aLS);
for (; aItS.More(); aItS.Next()) {
const TopoDS_Shape& aFx=aItS.Value();
if (!myRemoved.Contains(aFx)) {
aMFaces.Add(aFx);
}
}
}
else {
if (!myRemoved.Contains(aS)) {
aMFaces.Add(aS);
}
}
break;
}
//
default:
break;
}
}
//
aItMS.Initialize(aMSolids);
for (; aItMS.More(); aItMS.Next()) {
const TopoDS_Solid& aSolid=(*(TopoDS_Solid*)(&aItMS.Value()));
//
aMFDone.Clear();
aMFIN.Clear();
aMEF.Clear();
//
aBB.MakeSolid(aSolidSp);
//
// Draft solid and its pure internal faces => aSolidSp, aLIF
aLIF.Clear();
BuildDraftSolid(aSolid, aSolidSp, aLIF);
aNbLIF=aLIF.Extent();
//
// 1 all faces/edges from aSolid [ aMS ]
bHasImage=Standard_False;
aMS.Clear();
aIt.Initialize(aSolid);
for (; aIt.More(); aIt.Next()) {
const TopoDS_Shape& aShell=aIt.Value();
//
if (myImages.IsBound(aShell)) {
bHasImage=Standard_True;
//
const TopTools_ListOfShape& aLS=myImages.Find(aShell);
aItS.Initialize(aLS);
for (; aItS.More(); aItS.Next()) {
const TopoDS_Shape& aSx=aItS.Value();
aMS.Add(aSx);
TopExp::MapShapes(aSx, TopAbs_FACE, aMS);
TopExp::MapShapes(aSx, TopAbs_EDGE, aMS);
TopExp::MapShapesAndAncestors(aSx, TopAbs_EDGE, TopAbs_FACE, aMEF);
}
}
else {
//aMS.Add(aShell);
TopExp::MapShapes(aShell, TopAbs_FACE, aMS);
TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aMEF);
}
}
//
// 2 all faces that are not from aSolid [ aLFP1 ]
TopTools_IndexedDataMapOfShapeListOfShape aMEFP(100, theAllocator);
TopTools_ListOfShape aLFP1(theAllocator);
TopTools_ListOfShape aLFP(theAllocator);
TopTools_ListOfShape aLCBF(theAllocator);
TopTools_ListOfShape aLFIN(theAllocator);
TopTools_ListOfShape aLEx(theAllocator);
//
// for all non-solid faces build EF map [ aMEFP ]
aItMS1.Initialize(aMFaces);
for (; aItMS1.More(); aItMS1.Next()) {
const TopoDS_Shape& aFace=aItMS1.Value();
if (!aMS.Contains(aFace)) {
TopExp::MapShapesAndAncestors(aFace, TopAbs_EDGE, TopAbs_FACE, aMEFP);
}
}
//
// among all faces from aMEFP select these that have same edges
// with the solid (i.e aMEF). These faces will be treated first
// to prevent the usage of 3D classifier.
// The full list of faces to process is aLFP1.
aNbEFP=aMEFP.Extent();
for (j=1; j<=aNbEFP; ++j) {
const TopoDS_Shape& aE=aMEFP.FindKey(j);
//
if (aMEF.Contains(aE)) { // !!
const TopTools_ListOfShape& aLF=aMEFP(j);
aItFP.Initialize(aLF);
for (; aItFP.More(); aItFP.Next()) {
const TopoDS_Shape& aF=aItFP.Value();
if (aMFDone.Add(aF)) {
aLFP1.Append(aF);
}
}
}
else {
aLEx.Append(aE);
}
}
//
aItEx.Initialize(aLEx);
for (; aItEx.More(); aItEx.Next()) {
const TopoDS_Shape& aE=aItEx.Value();
const TopTools_ListOfShape& aLF=aMEFP.FindFromKey(aE);
aItFP.Initialize(aLF);
for (; aItFP.More(); aItFP.Next()) {
const TopoDS_Shape& aF=aItFP.Value();
if (aMFDone.Add(aF)) {
//aLFP2.Append(aF);
aLFP1.Append(aF);
}
}
}
//
//==========
//
// 3 Process faces aLFP1
aMFDone.Clear();
aNbFP=aLFP1.Extent();
aItFP.Initialize(aLFP1);
for (; aItFP.More(); aItFP.Next()) {
const TopoDS_Shape& aSP=aItFP.Value();
if (!aMFDone.Add(aSP)) {
continue;
}
//
// first face to process
aFP=(*(TopoDS_Face*)(&aSP));
bIsIN=BOPTools_AlgoTools::IsInternalFace(aFP, aSolidSp, aMEF, 1.e-14, myContext);
aState=(bIsIN) ? TopAbs_IN : TopAbs_OUT;
//
// collect faces to process [ aFP is the first ]
aLFP.Clear();
aLFP.Append(aFP);
aItS.Initialize(aLFP1);
for (; aItS.More(); aItS.Next()) {
const TopoDS_Shape& aSk=aItS.Value();
if (!aMFDone.Contains(aSk)) {
aLFP.Append(aSk);
}
}
//
// Connexity Block that spreads from aFP the Bound
// or till the end of the block itself
aLCBF.Clear();
BOPTools_AlgoTools::MakeConnexityBlock(aLFP, aMS, aLCBF, theAllocator);
//
// fill states for the Connexity Block
aItS.Initialize(aLCBF);
for (; aItS.More(); aItS.Next()) {
const TopoDS_Shape& aSx=aItS.Value();
aMFDone.Add(aSx);
if (aState==TopAbs_IN) {
aMFIN.Add(aSx);
}
}
//
aNbFPx=aMFDone.Extent();
if (aNbFPx==aNbFP) {
break;
}
}//for (; aItFP.More(); aItFP.Next())
//
// faces Inside aSolid
aLFIN.Clear();
aNbFIN=aMFIN.Extent();
if (aNbFIN || aNbLIF) {
aItMS1.Initialize(aMFIN);
for (; aItMS1.More(); aItMS1.Next()) {
const TopoDS_Shape& aFIn=aItMS1.Value();
aLFIN.Append(aFIn);
}
//
aItS.Initialize(aLIF);
for (; aItS.More(); aItS.Next()) {
const TopoDS_Shape& aFIN=aItS.Value();
aLFIN.Append(aFIN);
}
//
theInParts.Bind(aSolid, aLFIN);
}
if (aNbFIN || bHasImage) {
theDraftSolids.Bind(aSolid, aSolidSp);
}
}// for (; aItMS.More(); aItMS.Next()) {
}