0030145: Modeling Algorithms - Boolean Operations on open solids
[occt.git] / src / BOPAlgo / BOPAlgo_BOP.cxx
CommitLineData
4e57c75e 1// Created by: Peter KURNEV
973c2be1 2// Copyright (c) 1999-2014 OPEN CASCADE SAS
4e57c75e 3//
973c2be1 4// This file is part of Open CASCADE Technology software library.
4e57c75e 5//
d5f74e42 6// This library is free software; you can redistribute it and/or modify it under
7// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 8// by the Free Software Foundation, with special exception defined in the file
9// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10// distribution for complete text of the license and disclaimer of any warranty.
4e57c75e 11//
973c2be1 12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
4e57c75e 14
4e57c75e 15
42cf5bc1 16#include <BOPAlgo_BOP.hxx>
17#include <BOPAlgo_BuilderSolid.hxx>
18#include <BOPAlgo_PaveFiller.hxx>
977ad983 19#include <BOPAlgo_Tools.hxx>
33ba8565 20#include <BOPAlgo_Alerts.hxx>
8620e18d 21#include <BOPDS_DS.hxx>
4e57c75e 22#include <BOPTools_AlgoTools.hxx>
23#include <BOPTools_AlgoTools3D.hxx>
1155d05a 24#include <BOPTools_IndexedDataMapOfSetShape.hxx>
955b3e71 25#include <BOPTools_Set.hxx>
26#include <BOPTools_SetMapHasher.hxx>
42cf5bc1 27#include <BRep_Builder.hxx>
28#include <BRep_Tool.hxx>
955b3e71 29#include <NCollection_DataMap.hxx>
42cf5bc1 30#include <TopAbs_ShapeEnum.hxx>
1155d05a 31#include <TopExp.hxx>
42cf5bc1 32#include <TopExp_Explorer.hxx>
13c0e402 33#include <TopoDS.hxx>
42cf5bc1 34#include <TopoDS_Compound.hxx>
35#include <TopoDS_Edge.hxx>
36#include <TopoDS_Iterator.hxx>
37#include <TopoDS_Shape.hxx>
1155d05a 38#include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
39#include <TopTools_IndexedMapOfShape.hxx>
40#include <TopTools_ListOfShape.hxx>
41#include <TopTools_MapOfShape.hxx>
955b3e71 42
4e57c75e 43static
44 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim);
9526aa6a 45//
46static
47 void CollectContainers(const TopoDS_Shape& theS,
1155d05a 48 TopTools_ListOfShape& theLSC);
77a11d3d 49//
50static
1155d05a 51 void RemoveDuplicates(TopTools_ListOfShape& theContainers);
77a11d3d 52//
53static
1155d05a 54 void RemoveDuplicates(TopTools_ListOfShape& theContainers,
77a11d3d 55 const TopAbs_ShapeEnum theType);
56//
57static
1155d05a 58 Standard_Integer NbCommonItemsInMap(const TopTools_MapOfShape& theM1,
59 const TopTools_MapOfShape& theM2);
25dfc507 60//
61static
62 void MapFacesToBuildSolids(const TopoDS_Shape& theSol,
1155d05a 63 TopTools_IndexedDataMapOfShapeListOfShape& theMFS,
64 TopTools_IndexedMapOfShape& theMFI);
8620e18d 65
4e57c75e 66//=======================================================================
67//function :
68//purpose :
69//=======================================================================
8620e18d 70BOPAlgo_BOP::BOPAlgo_BOP()
5fbe3d01 71: BOPAlgo_ToolsProvider()
4e57c75e 72{
4e57c75e 73 Clear();
74}
75//=======================================================================
76//function :
77//purpose :
78//=======================================================================
5fbe3d01 79BOPAlgo_BOP::BOPAlgo_BOP(const Handle(NCollection_BaseAllocator)& theAllocator)
80: BOPAlgo_ToolsProvider(theAllocator)
4e57c75e 81{
4e57c75e 82 Clear();
83}
84//=======================================================================
85//function : ~
86//purpose :
87//=======================================================================
8620e18d 88BOPAlgo_BOP::~BOPAlgo_BOP()
4e57c75e 89{
90}
91//=======================================================================
92//function : Clear
93//purpose :
94//=======================================================================
8620e18d 95void BOPAlgo_BOP::Clear()
4e57c75e 96{
97 myOperation=BOPAlgo_UNKNOWN;
4e57c75e 98 myDims[0]=-1;
99 myDims[1]=-1;
5fbe3d01 100
101 BOPAlgo_ToolsProvider::Clear();
4e57c75e 102}
103//=======================================================================
8620e18d 104//function : SetOperation
4e57c75e 105//purpose :
106//=======================================================================
8620e18d 107void BOPAlgo_BOP::SetOperation(const BOPAlgo_Operation theOperation)
4e57c75e 108{
8620e18d 109 myOperation=theOperation;
4e57c75e 110}
111//=======================================================================
8620e18d 112//function : Operation
4e57c75e 113//purpose :
114//=======================================================================
8620e18d 115BOPAlgo_Operation BOPAlgo_BOP::Operation()const
4e57c75e 116{
8620e18d 117 return myOperation;
4e57c75e 118}
119//=======================================================================
4e57c75e 120//function : CheckData
121//purpose :
122//=======================================================================
8620e18d 123void BOPAlgo_BOP::CheckData()
4e57c75e 124{
8620e18d 125 Standard_Integer i, j, iDim, aNbArgs, aNbTools;
33ba8565 126 Standard_Boolean bFuse;
1155d05a 127 TopTools_ListIteratorOfListOfShape aItLS;
4e57c75e 128 //
85915310 129 if (!(myOperation==BOPAlgo_COMMON ||
130 myOperation==BOPAlgo_FUSE ||
131 myOperation==BOPAlgo_CUT||
132 myOperation==BOPAlgo_CUT21)) {
133 // non-licit operation
33ba8565 134 AddError (new BOPAlgo_AlertBOPNotSet);
85915310 135 return;
136 }
137 //
8620e18d 138 aNbArgs=myArguments.Extent();
139 if (!aNbArgs) {
85915310 140 // invalid number of Arguments
33ba8565 141 AddError (new BOPAlgo_AlertTooFewArguments);
8620e18d 142 return;
143 }
144 //
145 aNbTools=myTools.Extent();
85915310 146 if (!aNbTools) {
147 // invalid number of Tools
33ba8565 148 AddError (new BOPAlgo_AlertTooFewArguments);
4e57c75e 149 return;
150 }
151 //
33ba8565 152 CheckFiller();
153 if (HasErrors()) {
4e57c75e 154 return;
155 }
156 //
9526aa6a 157 bFuse = (myOperation == BOPAlgo_FUSE);
158 //
159 // The rules for different types of operations are the following:
160 // 1. FUSE: All arguments and tools should have the same dimension;
161 // 2. CUT: The MAXIMAL dimension of the ARGUMENTS should be less
162 // or equal to the MINIMAL dimension of the TOOLS;
163 // 3. CUT21: The MINIMAL dimension of ARGUMENTS should be grater
164 // or equal to the MAXIMAL dimension of the TOOLS;
165 // 4. COMMON: The arguments and tools could have any dimensions.
166 //
3dc58095 167 Standard_Integer iDimMin[2] = { 0, 0 }, iDimMax[2] = { 0, 0 };
33ba8565 168 Standard_Boolean bHasValid[2] = {Standard_False, Standard_False};
9526aa6a 169 //
8620e18d 170 for (i=0; i<2; ++i) {
1155d05a 171 const TopTools_ListOfShape& aLS=(!i)? myArguments : myTools;
8620e18d 172 aItLS.Initialize(aLS);
173 for (j=0; aItLS.More(); aItLS.Next(), ++j) {
174 const TopoDS_Shape& aS=aItLS.Value();
33ba8565 175 Standard_Boolean bIsEmpty = BOPTools_AlgoTools3D::IsEmptyShape(aS);
176 if (bIsEmpty) {
177 AddWarning(new BOPAlgo_AlertEmptyShape (aS));
178 continue;
8620e18d 179 }
180 //
33ba8565 181 iDim = BOPTools_AlgoTools::Dimension(aS);
182 if (iDim < 0) {
183 // non-homogeneous argument
184 AddError (new BOPAlgo_AlertBOPNotAllowed);
8620e18d 185 return;
186 }
187 //
33ba8565 188 bHasValid[i] = Standard_True;
189 //
8620e18d 190 if (!j) {
9526aa6a 191 iDimMin[i] = iDim;
192 iDimMax[i] = iDim;
8620e18d 193 continue;
194 }
195 //
9526aa6a 196 if (iDim < iDimMin[i]) {
197 iDimMin[i] = iDim;
198 }
199 else if (iDim > iDimMax[i]) {
200 iDimMax[i] = iDim;
201 }
202 //
203 if (bFuse && (iDimMin[i] != iDimMax[i])) {
33ba8565 204 // non-homogeneous argument
205 AddError (new BOPAlgo_AlertBOPNotAllowed);
8620e18d 206 return;
207 }
4e57c75e 208 }
209 }
210 //
33ba8565 211 if (bHasValid[0] && bHasValid[1]) {
212 if (((myOperation == BOPAlgo_FUSE) && (iDimMax[0] != iDimMax[1])) ||
213 ((myOperation == BOPAlgo_CUT) && (iDimMax[0] > iDimMin[1])) ||
214 ((myOperation == BOPAlgo_CUT21) && (iDimMin[0] < iDimMax[1])) )
215 {
216 // non-licit operation for the arguments
217 AddError (new BOPAlgo_AlertBOPNotAllowed);
218 return;
219 }
3dc58095 220 }
221
222 if (bHasValid[0] || bHasValid[1])
223 {
224 // In case of all empty shapes in one of the groups
225 // this group aquires the dimension of other group
226 myDims[0] = bHasValid[0] ? iDimMin[0] : iDimMin[1];
227 myDims[1] = bHasValid[1] ? iDimMin[1] : iDimMin[0];
4e57c75e 228 }
229}
230//=======================================================================
33ba8565 231//function : TreatEmtpyShape
4e57c75e 232//purpose :
233//=======================================================================
33ba8565 234Standard_Boolean BOPAlgo_BOP::TreatEmptyShape()
4e57c75e 235{
33ba8565 236 if (! GetReport()->HasAlert (STANDARD_TYPE(BOPAlgo_AlertEmptyShape)))
237 {
238 return Standard_False;
239 }
4e57c75e 240 //
33ba8565 241 // Find non-empty objects
1155d05a 242 TopTools_ListOfShape aLValidObjs;
243 TopTools_ListIteratorOfListOfShape aItLS(myArguments);
33ba8565 244 for (; aItLS.More(); aItLS.Next()) {
245 if (!BOPTools_AlgoTools3D::IsEmptyShape(aItLS.Value())) {
246 aLValidObjs.Append(aItLS.Value());
247 }
248 }
4e57c75e 249 //
33ba8565 250 // Find non-empty tools
1155d05a 251 TopTools_ListOfShape aLValidTools;
33ba8565 252 aItLS.Initialize(myTools);
253 for (; aItLS.More() ; aItLS.Next()) {
254 if (!BOPTools_AlgoTools3D::IsEmptyShape(aItLS.Value())) {
255 aLValidTools.Append(aItLS.Value());
256 }
257 }
258 //
259 Standard_Boolean bHasValidObj = (aLValidObjs .Extent() > 0);
260 Standard_Boolean bHasValidTool = (aLValidTools.Extent() > 0);
261 //
262 if (bHasValidObj && bHasValidTool) {
263 // We need to continue the operation to obtain the result
264 return Standard_False;
265 }
266 //
267 if (!bHasValidObj && !bHasValidTool) {
268 // All shapes are empty shapes, the result will always be empty shape
269 return Standard_True;
8620e18d 270 }
33ba8565 271 //
272 // One of the groups of arguments consists of empty shapes only,
273 // so we can build the result of operation right away just by
274 // choosing the list of shapes to add to result, depending on
3dc58095 275 // the type of the operation.
276 // Although, if the group with valid shapes consists from more
277 // than just one shape, depending on the operation type we may need
278 // to split the shapes in this group before adding them into result.
279
1155d05a 280 TopTools_ListOfShape *pLResult = NULL;
33ba8565 281 //
282 switch (myOperation) {
283 case BOPAlgo_FUSE:
3dc58095 284 {
285 if (aLValidObjs.Extent() + aLValidTools.Extent() > 1)
286 // The arguments must be split before adding into result
287 return Standard_False;
288
33ba8565 289 // Add not empty shapes into result
290 pLResult = bHasValidObj ? &aLValidObjs : &aLValidTools;
291 break;
3dc58095 292 }
33ba8565 293 case BOPAlgo_CUT:
3dc58095 294 {
295 if (aLValidObjs.Extent() > 1)
296 // The objects must be split before adding into result
297 return Standard_False;
298
33ba8565 299 // Add objects into result
300 pLResult = &aLValidObjs;
301 break;
3dc58095 302 }
33ba8565 303 case BOPAlgo_CUT21:
3dc58095 304 {
305 if (aLValidTools.Extent() > 1)
306 // The tools must be split before adding into result
307 return Standard_False;
308
33ba8565 309 // Add tools into result
310 pLResult = &aLValidTools;
311 break;
3dc58095 312 }
33ba8565 313 case BOPAlgo_COMMON:
3dc58095 314 // Common will always be empty
33ba8565 315 break;
316 default:
317 break;
318 }
319 //
320 if (pLResult) {
321 aItLS.Initialize(*pLResult);
322 for (; aItLS.More(); aItLS.Next()) {
323 BRep_Builder().Add(myShape, aItLS.Value());
324 }
325 }
326 return Standard_True;
8620e18d 327}
328//=======================================================================
329//function : BuildResult
330//purpose :
331//=======================================================================
332void BOPAlgo_BOP::BuildResult(const TopAbs_ShapeEnum theType)
333{
334 TopAbs_ShapeEnum aType;
335 BRep_Builder aBB;
1155d05a 336 TopTools_MapOfShape aM;
337 TopTools_ListIteratorOfListOfShape aIt, aItIm;
8620e18d 338 //
1155d05a 339 const TopTools_ListOfShape& aLA=myDS->Arguments();
8620e18d 340 aIt.Initialize(aLA);
341 for (; aIt.More(); aIt.Next()) {
342 const TopoDS_Shape& aS=aIt.Value();
343 aType=aS.ShapeType();
344 if (aType==theType) {
345 if (myImages.IsBound(aS)){
1155d05a 346 const TopTools_ListOfShape& aLSIm=myImages.Find(aS);
8620e18d 347 aItIm.Initialize(aLSIm);
348 for (; aItIm.More(); aItIm.Next()) {
349 const TopoDS_Shape& aSIm=aItIm.Value();
350 if (aM.Add(aSIm)) {
351 aBB.Add(myShape, aSIm);
352 }
353 }
354 }
355 else {
356 if (aM.Add(aS)) {
357 aBB.Add(myShape, aS);
358 }
359 }
4e57c75e 360 }
361 }
362}
363//=======================================================================
8620e18d 364//function : Perform
365//purpose :
366//=======================================================================
367void BOPAlgo_BOP::Perform()
368{
369 Handle(NCollection_BaseAllocator) aAllocator;
370 BOPAlgo_PaveFiller* pPF;
1155d05a 371 TopTools_ListIteratorOfListOfShape aItLS;
8620e18d 372 //
33ba8565 373 GetReport()->Clear();
8620e18d 374 //
375 if (myEntryPoint==1) {
376 if (myPaveFiller) {
377 delete myPaveFiller;
378 myPaveFiller=NULL;
379 }
380 }
381 //
488e5b9d 382 aAllocator=
383 NCollection_BaseAllocator::CommonBaseAllocator();
1155d05a 384 TopTools_ListOfShape aLS(aAllocator);
8620e18d 385 //
386 aItLS.Initialize(myArguments);
387 for (; aItLS.More(); aItLS.Next()) {
388 const TopoDS_Shape& aS=aItLS.Value();
389 aLS.Append(aS);
390 }
391 //
392 aItLS.Initialize(myTools);
393 for (; aItLS.More(); aItLS.Next()) {
394 const TopoDS_Shape& aS=aItLS.Value();
395 aLS.Append(aS);
396 }
397 //
398 pPF=new BOPAlgo_PaveFiller(aAllocator);
399 pPF->SetArguments(aLS);
b1d15f53 400 pPF->SetRunParallel(myRunParallel);
401 pPF->SetProgressIndicator(myProgressIndicator);
402 pPF->SetFuzzyValue(myFuzzyValue);
3510db62 403 pPF->SetNonDestructive(myNonDestructive);
483ce1bd 404 pPF->SetGlue(myGlue);
944768d2 405 pPF->SetUseOBB(myUseOBB);
8620e18d 406 //
407 pPF->Perform();
408 //
409 myEntryPoint=1;
410 PerformInternal(*pPF);
411}
412//=======================================================================
36f4947b 413//function : PerformInternal1
4e57c75e 414//purpose :
415//=======================================================================
36f4947b 416void BOPAlgo_BOP::PerformInternal1(const BOPAlgo_PaveFiller& theFiller)
4e57c75e 417{
4e57c75e 418 myPaveFiller=(BOPAlgo_PaveFiller*)&theFiller;
419 myDS=myPaveFiller->PDS();
420 myContext=myPaveFiller->Context();
0d0481c7 421 myFuzzyValue = myPaveFiller->FuzzyValue();
422 myNonDestructive = myPaveFiller->NonDestructive();
4e57c75e 423 //
424 // 1. CheckData
425 CheckData();
33ba8565 426 if (HasErrors()) {
4e57c75e 427 return;
428 }
429 //
430 // 2. Prepare
431 Prepare();
33ba8565 432 if (HasErrors()) {
4e57c75e 433 return;
434 }
8620e18d 435 //
33ba8565 436 if (GetReport()->HasAlert (STANDARD_TYPE(BOPAlgo_AlertEmptyShape)))
437 {
438 Standard_Boolean bDone = TreatEmptyShape();
439 if (bDone) {
3dc58095 440 PrepareHistory();
33ba8565 441 return;
442 }
4e57c75e 443 }
33ba8565 444 //
4e57c75e 445 // 3. Fill Images
446 // 3.1 Vertices
447 FillImagesVertices();
33ba8565 448 if (HasErrors()) {
4e57c75e 449 return;
450 }
451 //
452 BuildResult(TopAbs_VERTEX);
33ba8565 453 if (HasErrors()) {
4e57c75e 454 return;
455 }
456 // 3.2 Edges
457 FillImagesEdges();
33ba8565 458 if (HasErrors()) {
4e57c75e 459 return;
460 }
85915310 461 //
4e57c75e 462 BuildResult(TopAbs_EDGE);
33ba8565 463 if (HasErrors()) {
4e57c75e 464 return;
465 }
4e57c75e 466 //
467 // 3.3 Wires
468 FillImagesContainers(TopAbs_WIRE);
33ba8565 469 if (HasErrors()) {
4e57c75e 470 return;
471 }
85915310 472 //
4e57c75e 473 BuildResult(TopAbs_WIRE);
33ba8565 474 if (HasErrors()) {
4e57c75e 475 return;
476 }
85915310 477 //
4e57c75e 478 // 3.4 Faces
479 FillImagesFaces();
33ba8565 480 if (HasErrors()) {
4e57c75e 481 return;
482 }
483
484 BuildResult(TopAbs_FACE);
33ba8565 485 if (HasErrors()) {
4e57c75e 486 return;
487 }
85915310 488 //
4e57c75e 489 // 3.5 Shells
4e57c75e 490 FillImagesContainers(TopAbs_SHELL);
33ba8565 491 if (HasErrors()) {
4e57c75e 492 return;
493 }
85915310 494 //
4e57c75e 495 BuildResult(TopAbs_SHELL);
33ba8565 496 if (HasErrors()) {
4e57c75e 497 return;
498 }
85915310 499 //
4e57c75e 500 // 3.6 Solids
501 FillImagesSolids();
33ba8565 502 if (HasErrors()) {
4e57c75e 503 return;
504 }
85915310 505 //
4e57c75e 506 BuildResult(TopAbs_SOLID);
33ba8565 507 if (HasErrors()) {
4e57c75e 508 return;
509 }
85915310 510 //
4e57c75e 511 // 3.7 CompSolids
512 FillImagesContainers(TopAbs_COMPSOLID);
33ba8565 513 if (HasErrors()) {
4e57c75e 514 return;
515 }
85915310 516 //
4e57c75e 517 BuildResult(TopAbs_COMPSOLID);
33ba8565 518 if (HasErrors()) {
4e57c75e 519 return;
520 }
85915310 521 //
4e57c75e 522 // 3.8 Compounds
523 FillImagesCompounds();
33ba8565 524 if (HasErrors()) {
4e57c75e 525 return;
526 }
85915310 527 //
4e57c75e 528 BuildResult(TopAbs_COMPOUND);
33ba8565 529 if (HasErrors()) {
4e57c75e 530 return;
531 }
532 //
8620e18d 533 // 4.BuildShape;
4e57c75e 534 BuildShape();
33ba8565 535 if (HasErrors()) {
8620e18d 536 return;
537 }
4e57c75e 538 //
8620e18d 539 // 5.History
4e57c75e 540 PrepareHistory();
4e57c75e 541 //
8620e18d 542 // 6 Post-treatment
4e57c75e 543 PostTreat();
544}
545//=======================================================================
8620e18d 546//function : BuildRC
547//purpose :
548//=======================================================================
549void BOPAlgo_BOP::BuildRC()
550{
9526aa6a 551 TopAbs_ShapeEnum aType;
8620e18d 552 TopoDS_Compound aC;
8620e18d 553 BRep_Builder aBB;
8620e18d 554 //
8620e18d 555 aBB.MakeCompound(aC);
556 //
557 // A. Fuse
9526aa6a 558 if (myOperation == BOPAlgo_FUSE) {
1155d05a 559 TopTools_MapOfShape aMFence;
9526aa6a 560 aType = TypeToExplore(myDims[0]);
561 TopExp_Explorer aExp(myShape, aType);
8620e18d 562 for (; aExp.More(); aExp.Next()) {
9526aa6a 563 const TopoDS_Shape& aS = aExp.Current();
564 if (aMFence.Add(aS)) {
565 aBB.Add(aC, aS);
566 }
8620e18d 567 }
9526aa6a 568 myRC = aC;
8620e18d 569 return;
8620e18d 570 }
8620e18d 571 //
572 // B. Common, Cut, Cut21
573 //
9526aa6a 574 Standard_Integer i, j, aNb, iDim;
575 Standard_Boolean bCheckEdges, bContains, bCut21, bCommon;
1155d05a 576 TopTools_ListIteratorOfListOfShape aItLS;
8620e18d 577 //
25dfc507 578 // prepare the building elements of arguments to get its splits
1155d05a 579 TopTools_IndexedMapOfShape aMArgs, aMTools;
9526aa6a 580 for (i = 0; i < 2; ++i) {
1155d05a 581 const TopTools_ListOfShape& aLS = !i ? myArguments : myTools;
582 TopTools_IndexedMapOfShape& aMS = !i ? aMArgs : aMTools;
9526aa6a 583 aItLS.Initialize(aLS);
584 for (; aItLS.More(); aItLS.Next()) {
585 const TopoDS_Shape& aS = aItLS.Value();
586 iDim = BOPTools_AlgoTools::Dimension(aS);
33ba8565 587 if (iDim < 0) {
588 continue;
589 }
9526aa6a 590 aType = TypeToExplore(iDim);
1155d05a 591 TopExp::MapShapes(aS, aType, aMS);
9526aa6a 592 }
593 }
594 //
595 bCheckEdges = Standard_False;
596 //
25dfc507 597 // get splits of building elements
1155d05a 598 TopTools_IndexedMapOfShape aMArgsIm, aMToolsIm;
25dfc507 599 BOPTools_IndexedDataMapOfSetShape aMSetArgs, aMSetTools;
600
9526aa6a 601 for (i = 0; i < 2; ++i) {
1155d05a 602 const TopTools_IndexedMapOfShape& aMS = !i ? aMArgs : aMTools;
603 TopTools_IndexedMapOfShape& aMSIm = !i ? aMArgsIm : aMToolsIm;
25dfc507 604 BOPTools_IndexedDataMapOfSetShape& aMSet = !i ? aMSetArgs : aMSetTools;
8620e18d 605 //
9526aa6a 606 aNb = aMS.Extent();
607 for (j = 1; j <= aNb; ++j) {
608 const TopoDS_Shape& aS = aMS(j);
609 aType = aS.ShapeType();
610 if (aType == TopAbs_EDGE) {
611 const TopoDS_Edge& aE = *(TopoDS_Edge*)&aS;
612 bCheckEdges = Standard_True;
613 if (BRep_Tool::Degenerated(aE)) {
614 continue;
8620e18d 615 }
616 }
9526aa6a 617 //
618 if (myImages.IsBound(aS)) {
1155d05a 619 const TopTools_ListOfShape& aLSIm = myImages.Find(aS);
9526aa6a 620 aItLS.Initialize(aLSIm);
621 for (; aItLS.More(); aItLS.Next()) {
622 const TopoDS_Shape& aSIm = aItLS.Value();
623 aMSIm.Add(aSIm);
955b3e71 624 }
8620e18d 625 }
9526aa6a 626 else {
627 aMSIm.Add(aS);
25dfc507 628 if (aS.ShapeType() == TopAbs_SOLID) {
629 BOPTools_Set aST;
630 aST.Add(aS, TopAbs_FACE);
631 if (!aMSet.Contains(aST)) {
632 aMSet.Add(aST, aS);
633 }
634 }
9526aa6a 635 }
8620e18d 636 }
9526aa6a 637 }
8620e18d 638 //
9526aa6a 639 // compare the maps and make the result
640 //
641 Standard_Integer iDimMin, iDimMax;
642 //
643 iDimMin = Min(myDims[0], myDims[1]);
644 bCommon = (myOperation == BOPAlgo_COMMON);
645 bCut21 = (myOperation == BOPAlgo_CUT21);
646 //
1155d05a 647 const TopTools_IndexedMapOfShape& aMIt = bCut21 ? aMToolsIm : aMArgsIm;
648 const TopTools_IndexedMapOfShape& aMCheck = bCut21 ? aMArgsIm : aMToolsIm;
25dfc507 649 const BOPTools_IndexedDataMapOfSetShape& aMSetCheck = bCut21 ? aMSetArgs : aMSetTools;
9526aa6a 650 //
1155d05a 651 TopTools_IndexedMapOfShape aMCheckExp, aMItExp;
9526aa6a 652 //
653 if (bCommon) {
654 aNb = aMIt.Extent();
655 for (i = 1; i <= aNb; ++i) {
656 const TopoDS_Shape& aS = aMIt(i);
657 iDimMax = BOPTools_AlgoTools::Dimension(aS);
658 for (iDim = iDimMin; iDim < iDimMax; ++iDim) {
659 aType = TypeToExplore(iDim);
1155d05a 660 TopExp::MapShapes(aS, aType, aMItExp);
9526aa6a 661 }
662 aMItExp.Add(aS);
663 }
664 }
665 else {
666 aMItExp = aMIt;
667 }
668 //
669 aNb = aMCheck.Extent();
670 for (i = 1; i <= aNb; ++i) {
671 const TopoDS_Shape& aS = aMCheck(i);
672 iDimMax = BOPTools_AlgoTools::Dimension(aS);
673 for (iDim = iDimMin; iDim < iDimMax; ++iDim) {
674 aType = TypeToExplore(iDim);
1155d05a 675 TopExp::MapShapes(aS, aType, aMCheckExp);
9526aa6a 676 }
677 aMCheckExp.Add(aS);
678 }
679 //
680 aNb = aMItExp.Extent();
681 for (i = 1; i <= aNb; ++i) {
682 const TopoDS_Shape& aS = aMItExp(i);
683 //
684 bContains = aMCheckExp.Contains(aS);
25dfc507 685 if (!bContains && aS.ShapeType() == TopAbs_SOLID) {
686 BOPTools_Set aST;
687 aST.Add(aS, TopAbs_FACE);
688 bContains = aMSetCheck.Contains(aST);
689 }
690 //
9526aa6a 691 if (bCommon) {
692 if (bContains) {
693 aBB.Add(aC, aS);
8620e18d 694 }
9526aa6a 695 }
8620e18d 696 else {
9526aa6a 697 if (!bContains) {
698 aBB.Add(aC, aS);
699 }
700 }
701 }
702 //
703 // filter result for COMMON operation
704 if (bCommon) {
1155d05a 705 TopTools_MapOfShape aMFence;
9526aa6a 706 TopExp_Explorer aExp;
707 TopoDS_Compound aCx;
708 aBB.MakeCompound(aCx);
709 //
710 for (iDim = 3; iDim >= iDimMin; --iDim) {
711 aType = TypeToExplore(iDim);
712 aExp.Init(aC, aType);
8620e18d 713 for (; aExp.More(); aExp.Next()) {
9526aa6a 714 const TopoDS_Shape& aS = aExp.Current();
715 if (aMFence.Add(aS)) {
716 aBB.Add(aCx, aS);
1155d05a 717 TopExp::MapShapes(aS, aMFence);
8620e18d 718 }
719 }
720 }
9526aa6a 721 aC = aCx;
722 }
8620e18d 723 //
9526aa6a 724 if (!bCheckEdges) {
725 myRC = aC;
8620e18d 726 return;
727 }
8620e18d 728 //
729 // The squats around degenerated edges
9526aa6a 730 Standard_Integer nVD;
1155d05a 731 TopTools_IndexedMapOfShape aMVC;
8620e18d 732 //
733 // 1. Vertices of aC
1155d05a 734 TopExp::MapShapes(aC, TopAbs_VERTEX, aMVC);
8620e18d 735 //
736 // 2. DE candidates
9526aa6a 737 aNb = myDS->NbSourceShapes();
738 for (i = 0; i < aNb; ++i) {
739 const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
740 aType = aSI.ShapeType();
741 if (aType != TopAbs_EDGE) {
8620e18d 742 continue;
743 }
744 //
9526aa6a 745 const TopoDS_Edge& aE = *((TopoDS_Edge*)&aSI.Shape());
8620e18d 746 if (!BRep_Tool::Degenerated(aE)) {
747 continue;
748 }
749 //
9526aa6a 750 nVD = aSI.SubShapes().First();
751 const TopoDS_Shape& aVD = myDS->Shape(nVD);
8620e18d 752 //
753 if (!aMVC.Contains(aVD)) {
754 continue;
755 }
756 //
757 if (myDS->IsNewShape(nVD)) {
758 continue;
759 }
760 //
761 if (myDS->HasInterf(nVD)) {
762 continue;
763 }
764 //
765 aBB.Add(aC, aE);
766 }
767 //
768 myRC=aC;
769}
770//=======================================================================
4e57c75e 771//function : BuildShape
772//purpose :
773//=======================================================================
8620e18d 774void BOPAlgo_BOP::BuildShape()
4e57c75e 775{
13c0e402 776 if (myDims[0] == 3 && myDims[1] == 3)
777 {
778 // For the Boolean operation on solids we need to check first
779 // if we are dealing with closed solids, because for open solids
780 // we cannot expect the BuilderSolid algorithm to produce good
781 // splits for them and have to try the alternative approach for
782 // building the result shape.
783 // This approach is not used by default as it will loose the
784 // modification history for solids, because the result solid
785 // will be built from scratch using the splits of faces.
786 Standard_Boolean hasNotClosedSolids = CheckArgsForOpenSolid();
787 if (hasNotClosedSolids)
788 {
789 Handle(Message_Report) aReport = new Message_Report();
790 BuildBOP(myArguments, myTools, myOperation, aReport);
791 if (aReport->GetAlerts(Message_Fail).IsEmpty())
792 {
793 // Success. Merge the report into the main report.
794 myReport->Merge(aReport);
795 return;
796 }
797 }
798 }
799
800 // Build the result using splits of arguments.
801
9526aa6a 802 BuildRC();
803 //
804 if ((myOperation == BOPAlgo_FUSE) && (myDims[0] == 3)) {
805 BuildSolid();
806 return;
807 }
808 //
809 Standard_Integer i;
810 TopAbs_ShapeEnum aType, aT1, aT2;
1155d05a 811 TopTools_ListOfShape aLSC, aLCB;
812 TopTools_ListIteratorOfListOfShape aItLS, aItLSIm, aItLCB;
4e57c75e 813 TopoDS_Iterator aIt;
814 BRep_Builder aBB;
9526aa6a 815 TopoDS_Shape aRC, aRCB;
4e57c75e 816 //
1155d05a 817 TopTools_MapOfShape aMSRC;
818 TopExp::MapShapes(myRC, aMSRC);
4e57c75e 819 //
9526aa6a 820 // collect images of containers
821 for (i = 0; i < 2; ++i) {
1155d05a 822 const TopTools_ListOfShape& aLS = !i ? myArguments : myTools;
9526aa6a 823 //
824 aItLS.Initialize(aLS);
825 for (; aItLS.More(); aItLS.Next()) {
826 const TopoDS_Shape& aS = aItLS.Value();
827 //
828 CollectContainers(aS, aLSC);
829 }
4e57c75e 830 }
9526aa6a 831 // make containers
1155d05a 832 TopTools_ListOfShape aLCRes;
833 TopTools_MapOfShape aMInpFence;
9526aa6a 834 aItLS.Initialize(aLSC);
835 for (; aItLS.More(); aItLS.Next()) {
836 const TopoDS_Shape& aSC = aItLS.Value();
977ad983 837 aMInpFence.Add(aSC);
9526aa6a 838 //
839 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
840 //
841 aIt.Initialize(aSC);
842 for (; aIt.More(); aIt.Next()) {
843 const TopoDS_Shape& aS = aIt.Value();
844 if (myImages.IsBound(aS)) {
1155d05a 845 const TopTools_ListOfShape& aLSIm = myImages.Find(aS);
9526aa6a 846 //
847 aItLSIm.Initialize(aLSIm);
848 for (; aItLSIm.More(); aItLSIm.Next()) {
849 const TopoDS_Shape& aSIm = aItLSIm.Value();
1511c7e9 850 if (aMSRC.Contains(aSIm)) {
9526aa6a 851 aBB.Add(aRC, aSIm);
852 }
853 }
854 }
1511c7e9 855 else if (aMSRC.Contains(aS)) {
9526aa6a 856 aBB.Add(aRC, aS);
857 }
4e57c75e 858 }
859 //
9526aa6a 860 aType = aSC.ShapeType();
861 switch (aType) {
862 case TopAbs_WIRE: {
863 aT1 = TopAbs_VERTEX;
864 aT2 = TopAbs_EDGE;
865 break;
866 }
867 case TopAbs_SHELL: {
868 aT1 = TopAbs_EDGE;
869 aT2 = TopAbs_FACE;
870 break;
871 }
872 default: {
873 aT1 = TopAbs_FACE;
874 aT2 = TopAbs_SOLID;
875 }
4e57c75e 876 }
877 //
9526aa6a 878 aLCB.Clear();
879 BOPTools_AlgoTools::MakeConnexityBlocks(aRC, aT1, aT2, aLCB);
880 if (aLCB.IsEmpty()) {
881 continue;
882 }
4e57c75e 883 //
884 aItLCB.Initialize(aLCB);
885 for (; aItLCB.More(); aItLCB.Next()) {
9526aa6a 886 BOPTools_AlgoTools::MakeContainer(aType, aRCB);
4e57c75e 887 //
9526aa6a 888 const TopoDS_Shape& aCB = aItLCB.Value();
4e57c75e 889 aIt.Initialize(aCB);
890 for (; aIt.More(); aIt.Next()) {
9526aa6a 891 const TopoDS_Shape& aCBS = aIt.Value();
892 aBB.Add(aRCB, aCBS);
4e57c75e 893 }
894 //
77a11d3d 895 if (aType == TopAbs_WIRE) {
896 // reorient wire
897 BOPTools_AlgoTools::OrientEdgesOnWire(aRCB);
898 }
899 else if (aType == TopAbs_SHELL) {
9526aa6a 900 BOPTools_AlgoTools::OrientFacesOnShell(aRCB);
4e57c75e 901 }
902 //
77a11d3d 903 aRCB.Orientation(aSC.Orientation());
904 //
905 aLCRes.Append(aRCB);
4e57c75e 906 }
9526aa6a 907 }
908 //
77a11d3d 909 RemoveDuplicates(aLCRes);
910 //
911 // add containers to result
912 TopoDS_Compound aResult;
913 aBB.MakeCompound(aResult);
914 //
915 aItLS.Initialize(aLCRes);
916 for (; aItLS.More(); aItLS.Next()) {
917 aBB.Add(aResult, aItLS.Value());
918 }
977ad983 919
920 // create map of containers
1155d05a 921 TopTools_MapOfShape aMSResult;
922 TopExp::MapShapes(aResult, aMSResult);
977ad983 923
924 // get input non-container shapes
1155d05a 925 TopTools_ListOfShape aLSNonCont;
977ad983 926 for (i = 0; i < 2; ++i)
927 {
1155d05a 928 const TopTools_ListOfShape& aLS = !i ? myArguments : myTools;
977ad983 929 aItLS.Initialize(aLS);
930 for (; aItLS.More(); aItLS.Next())
931 {
932 const TopoDS_Shape& aS = aItLS.Value();
933 BOPAlgo_Tools::TreatCompound(aS, aMInpFence, aLSNonCont);
4e57c75e 934 }
935 }
977ad983 936
937 // put non-container shapes in the result
938 aItLS.Initialize(aLSNonCont);
939 for (; aItLS.More(); aItLS.Next())
940 {
941 const TopoDS_Shape& aS = aItLS.Value();
942 if (myImages.IsBound(aS))
943 {
1155d05a 944 const TopTools_ListOfShape& aLSIm = myImages.Find(aS);
977ad983 945 aItLSIm.Initialize(aLSIm);
946 for (; aItLSIm.More(); aItLSIm.Next())
947 {
948 const TopoDS_Shape& aSIm = aItLSIm.Value();
949 if (aMSRC.Contains(aSIm) && aMSResult.Add(aSIm))
950 aBB.Add(aResult, aSIm);
951 }
952 }
953 else if (aMSRC.Contains(aS) && aMSResult.Add(aS))
954 aBB.Add(aResult, aS);
955 }
956
9526aa6a 957 myShape = aResult;
4e57c75e 958}
959//=======================================================================
960//function : BuildSolid
961//purpose :
962//=======================================================================
8620e18d 963void BOPAlgo_BOP::BuildSolid()
4e57c75e 964{
25dfc507 965 // Containers
1155d05a 966 TopTools_ListOfShape aLSC;
4e57c75e 967 //
1155d05a 968 TopTools_ListIteratorOfListOfShape aItLS;
25dfc507 969 TopExp_Explorer aExp;
970 BRep_Builder aBB;
971 //
25dfc507 972 // Get solids from input arguments
1155d05a 973 TopTools_MapOfShape aMSA;
25dfc507 974 // Map the arguments to find shared faces
1155d05a 975 TopTools_IndexedDataMapOfShapeListOfShape aMFS;
25dfc507 976 for (Standard_Integer i = 0; i < 2; ++i) {
1155d05a 977 const TopTools_ListOfShape& aLSA = (i) ? myArguments : myTools;
955b3e71 978 aItLS.Initialize(aLSA);
979 for (; aItLS.More(); aItLS.Next()) {
25dfc507 980 const TopoDS_Shape& aSA = aItLS.Value();
955b3e71 981 aExp.Init(aSA, TopAbs_SOLID);
982 for (; aExp.More(); aExp.Next()) {
25dfc507 983 const TopoDS_Shape& aSol = aExp.Current();
984 aMSA.Add(aSol);
1155d05a 985 TopExp::MapShapesAndAncestors(aSol, TopAbs_FACE, TopAbs_SOLID, aMFS);
955b3e71 986 }
25dfc507 987 //
988 // get Compsolids from input arguments
989 CollectContainers(aSA, aLSC);
955b3e71 990 }
991 }
992 //
25dfc507 993 // Find solids in input arguments sharing faces with other solids
1155d05a 994 TopTools_MapOfShape aMTSols;
25dfc507 995 Standard_Integer i, aNb = aMFS.Extent();
996 for (i = 1; i < aNb; ++i) {
1155d05a 997 const TopTools_ListOfShape& aLSols = aMFS(i);
25dfc507 998 if (aLSols.Extent() > 1) {
999 aItLS.Initialize(aLSols);
955b3e71 1000 for(; aItLS.More(); aItLS.Next()) {
25dfc507 1001 aMTSols.Add(aItLS.Value());
955b3e71 1002 }
1003 }
1004 }
1005 //
25dfc507 1006 // Possibly untouched solids - to be added to results as is
1155d05a 1007 TopTools_IndexedMapOfShape aMUSols;
25dfc507 1008 // Use map to chose the most outer faces to build result solids
955b3e71 1009 aMFS.Clear();
25dfc507 1010 // Internal faces
1155d05a 1011 TopTools_IndexedMapOfShape aMFI;
955b3e71 1012 //
25dfc507 1013 TopoDS_Iterator aIt(myRC);
4e57c75e 1014 for (; aIt.More(); aIt.Next()) {
25dfc507 1015 const TopoDS_Shape& aSx = aIt.Value();
955b3e71 1016 if (aMSA.Contains(aSx)) {
25dfc507 1017 if (!aMTSols.Contains(aSx)) {
1018 aMUSols.Add(aSx);
1019 continue;
955b3e71 1020 }
25dfc507 1021 }
1022 //
1023 MapFacesToBuildSolids(aSx, aMFS, aMFI);
1024 } // for (; aIt.More(); aIt.Next()) {
1025 //
1026 // Process possibly untouched solids.
1027 // Really untouched solids will be added into result as is.
1028 // Others will be processed by BuilderSolid.
1029 BOPTools_IndexedDataMapOfSetShape aDMSTS;
1030 //
1031 aNb = aMUSols.Extent();
1032 for (i = 1; i <= aNb; ++i) {
1033 const TopoDS_Shape& aSx = aMUSols(i);
955b3e71 1034 //
4e57c75e 1035 aExp.Init(aSx, TopAbs_FACE);
1036 for (; aExp.More(); aExp.Next()) {
25dfc507 1037 if (aMFS.Contains(aExp.Current())) {
1038 break;
4e57c75e 1039 }
25dfc507 1040 }
1041 //
1042 if (aExp.More()) {
1043 MapFacesToBuildSolids(aSx, aMFS, aMFI);
1044 }
1045 else {
1046 BOPTools_Set aST;
1047 aST.Add(aSx, TopAbs_FACE);
1048 if (!aDMSTS.Contains(aST)) {
1049 aDMSTS.Add(aST, aSx);
4e57c75e 1050 }
1051 }
25dfc507 1052 }
1053 //
1155d05a 1054 TopTools_IndexedDataMapOfShapeListOfShape aMEF;
81a55a69 1055 // Fill the list of faces to build the result solids
1056 TopTools_ListOfShape aSFS;
25dfc507 1057 aNb = aMFS.Extent();
1058 for (i = 1; i <= aNb; ++i) {
1155d05a 1059 const TopTools_ListOfShape& aLSx = aMFS(i);
25dfc507 1060 if (aLSx.Extent() == 1) {
1061 const TopoDS_Shape& aFx = aMFS.FindKey(i);
1155d05a 1062 TopExp::MapShapesAndAncestors(aFx, TopAbs_EDGE, TopAbs_FACE, aMEF);
81a55a69 1063 aSFS.Append(aFx);
4e57c75e 1064 }
1065 }
25dfc507 1066 // Internal faces
1067 aNb = aMFI.Extent();
1068 for (i = 1; i <= aNb; ++i) {
1069 TopoDS_Shape aFx = aMFI.FindKey(i);
1070 aSFS.Append(aFx.Oriented(TopAbs_FORWARD));
1071 aSFS.Append(aFx.Oriented(TopAbs_REVERSED));
4e57c75e 1072 }
1073 //
25dfc507 1074 TopoDS_Shape aRC;
1075 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC);
1076 if (aSFS.Extent()) {
1077 // Build solids from set of faces
7f3408c8 1078 BOPAlgo_BuilderSolid aBS;
1079 aBS.SetContext(myContext);
1080 aBS.SetShapes(aSFS);
1081 aBS.Perform();
1082 if (aBS.HasErrors()) {
33ba8565 1083 AddError (new BOPAlgo_AlertSolidBuilderFailed); // SolidBuilder failed
25dfc507 1084 return;
1085 }
7f3408c8 1086
1087 myReport->Merge(aBS.GetReport());
1088
25dfc507 1089 // new solids
7f3408c8 1090 const TopTools_ListOfShape& aLSR = aBS.Areas();
25dfc507 1091 //
1092 // add new solids to result
1093 aItLS.Initialize(aLSR);
1094 for (; aItLS.More(); aItLS.Next()) {
1095 const TopoDS_Shape& aSR = aItLS.Value();
1096 aBB.Add(aRC, aSR);
1097 }
4e57c75e 1098 }
955b3e71 1099 //
25dfc507 1100 // add untouched solids to result
1101 aNb = aDMSTS.Extent();
1102 for (i = 1; i <= aNb; ++i) {
319da2e4 1103 const TopoDS_Shape& aSx = aDMSTS(i);
955b3e71 1104 aBB.Add(aRC, aSx);
1105 }
1106 //
77a11d3d 1107 if (aLSC.IsEmpty()) {
1108 // no Compsolids in arguments
25dfc507 1109 myShape = aRC;
77a11d3d 1110 return;
1111 }
1112 //
1113 // build new Compsolids from new solids containing splits
1114 // of faces from arguments of type Compsolid
1115 //
1116 TopoDS_Shape aResult;
1117 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aResult);
1118 //
25dfc507 1119 aIt.Initialize(aRC);
1120 if (!aIt.More()) {
1121 // no solids in the result
1122 myShape = aRC;
1123 return;
1124 }
1125 //
1126 const TopoDS_Shape& aSol1 = aIt.Value();
1127 aIt.Next();
1128 //
77a11d3d 1129 // optimization for one solid in the result
25dfc507 1130 if (!aIt.More()) {
77a11d3d 1131 TopoDS_Shape aCS;
1132 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPSOLID, aCS);
25dfc507 1133 aBB.Add(aCS, aSol1);
77a11d3d 1134 //
1135 aBB.Add(aResult, aCS);
1136 myShape = aResult;
1137 return;
1138 }
1139 //
1140 // get splits of faces of the Compsolid arguments
1155d05a 1141 TopTools_MapOfShape aMFCs;
77a11d3d 1142 aItLS.Initialize(aLSC);
1143 for (; aItLS.More(); aItLS.Next()) {
1144 const TopoDS_Shape& aCs = aItLS.Value();
1145 aExp.Init(aCs, TopAbs_FACE);
1146 for (; aExp.More(); aExp.Next()) {
1147 const TopoDS_Shape& aF = aExp.Current();
1155d05a 1148 const TopTools_ListOfShape* pLFIm = myImages.Seek(aF);
77a11d3d 1149 if (!pLFIm) {
1150 aMFCs.Add(aF);
1151 }
1152 else {
1155d05a 1153 TopTools_ListIteratorOfListOfShape aItLFIm(*pLFIm);
77a11d3d 1154 for (; aItLFIm.More(); aItLFIm.Next()) {
1155 aMFCs.Add(aItLFIm.Value());
1156 }
1157 }
1158 }
1159 }
1160 //
1161 // build connexity blocks from new solids
1155d05a 1162 TopTools_ListOfShape aLCBS;
77a11d3d 1163 BOPTools_AlgoTools::MakeConnexityBlocks(aRC, TopAbs_FACE, TopAbs_SOLID, aLCBS);
1164 //
1165 aItLS.Initialize(aLCBS);
1166 for (; aItLS.More(); aItLS.Next()) {
1167 const TopoDS_Shape& aCB = aItLS.Value();
1168 //
1169 // check if the Compsolid should be created
1170 aExp.Init(aCB, TopAbs_FACE);
1171 for (; aExp.More(); aExp.Next()) {
1172 if (aMFCs.Contains(aExp.Current())) {
1173 break;
1174 }
1175 }
1176 //
1177 if (!aExp.More()) {
1178 // add solids directly into result as their origins are not Compsolids
1179 for (aIt.Initialize(aCB); aIt.More(); aIt.Next()) {
1180 aBB.Add(aResult, aIt.Value());
1181 }
1182 continue;
1183 }
1184 //
1185 // make Compsolid
1186 TopoDS_Shape aCS;
1187 BOPTools_AlgoTools::MakeContainer(TopAbs_COMPSOLID, aCS);
1188 //
1189 aIt.Initialize(aCB);
1190 for (; aIt.More(); aIt.Next()) {
1191 aBB.Add(aCS, aIt.Value());
1192 }
1193 //
1194 aBB.Add(aResult, aCS);
1195 }
1196 //
1197 myShape = aResult;
4e57c75e 1198}
13c0e402 1199
1200//=======================================================================
1201//function : CheckArgsForOpenSolid
1202//purpose :
1203//=======================================================================
1204Standard_Boolean BOPAlgo_BOP::CheckArgsForOpenSolid()
1205{
1206 // Analyze the report to find if BuilderSolid has generated warnings
1207 // for any of the solids and collect these solids to check if they are open.
1208 TopTools_MapOfShape aFailedSolids;
1209 {
1210 const Message_ListOfAlert& aList = myReport->GetAlerts(Message_Warning);
1211 for (Message_ListOfAlert::Iterator aIt(aList); aIt.More(); aIt.Next())
1212 {
1213 const Handle(Standard_Type)& aType = aIt.Value()->DynamicType();
1214 if (aType != STANDARD_TYPE(BOPAlgo_AlertSolidBuilderUnusedFaces))
1215 continue;
1216
1217 Handle(TopoDS_AlertWithShape) aShapeAlert = Handle(TopoDS_AlertWithShape)::DownCast(aIt.Value());
1218 if (!aShapeAlert.IsNull())
1219 {
1220 const TopoDS_Shape& aWarnShape = aShapeAlert->GetShape();
1221 if (!aWarnShape.IsNull())
1222 {
1223 TopExp_Explorer expS(aWarnShape, TopAbs_SOLID);
1224 for (; expS.More(); expS.Next())
1225 aFailedSolids.Add(expS.Current());
1226 }
1227 }
1228 }
1229 }
1230
1231 // Iterate on all solids from the arguments and check if any
1232 // of them are not closed.
1233 // At the same time, collect all internal faces of the input solids
1234 // to check if the splits of open solids did not acquire any new
1235 // internal faces.
1236
1237 const Standard_Integer aNbS = myDS->NbSourceShapes();
1238 for (Standard_Integer i = 0; i < aNbS; ++i)
1239 {
1240 const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
1241 if (aSI.ShapeType() != TopAbs_SOLID)
1242 continue;
1243
1244 const TopoDS_Shape& aSolid = aSI.Shape();
1245
1246 // Check that not INTERNAL faces create closed loops
1247 TopTools_IndexedDataMapOfShapeListOfShape aMEF;
1248 // Collect all splits of internal faces
1249 TopTools_MapOfShape aMFInternal;
1250
1251 for (TopoDS_Iterator itSh(aSolid); itSh.More(); itSh.Next())
1252 {
1253 const TopoDS_Shape& aSh = itSh.Value();
1254 if (aSh.ShapeType() != TopAbs_SHELL)
1255 continue;
1256
1257 for (TopoDS_Iterator itF(aSh); itF.More(); itF.Next())
1258 {
1259 const TopoDS_Shape& aF = itF.Value();
1260 if (aF.Orientation() == TopAbs_INTERNAL)
1261 {
1262 const TopTools_ListOfShape* pLFIm = myImages.Seek(aF);
1263 if (pLFIm)
1264 {
1265 TopTools_ListOfShape::Iterator itLFIm(*pLFIm);
1266 for (; itLFIm.More(); itLFIm.Next())
1267 aMFInternal.Add(itLFIm.Value());
1268 }
1269 else
1270 aMFInternal.Add(aF);
1271 }
1272 else
1273 TopExp::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
1274 }
1275 }
1276
1277 // Analyze the Edge-Face connection map on free edges
1278 Standard_Boolean isClosed = Standard_True;
1279 const Standard_Integer aNbE = aMEF.Extent();
1280 for (Standard_Integer j = 1; j <= aNbE && isClosed; ++j)
1281 {
1282 const TopoDS_Edge& aE = TopoDS::Edge(aMEF.FindKey(j));
1283 if (BRep_Tool::Degenerated(aE))
1284 // Skip degenerated edges
1285 continue;
1286
1287 isClosed = (aMEF(j).Extent() > 1);
1288 if (!isClosed)
1289 {
1290 const TopoDS_Face& aF = TopoDS::Face(aMEF(j).First());
1291 isClosed = BRep_Tool::IsClosed(aE, aF); // Check for seam edges
1292 if (!isClosed)
1293 {
1294 // Check if the edge is not internal in the face
1295 TopExp_Explorer expE(aF, TopAbs_EDGE);
1296 for (; expE.More(); expE.Next())
1297 {
1298 if (expE.Current().IsSame(aE))
1299 {
1300 isClosed = (expE.Current().Orientation() == TopAbs_INTERNAL);
1301 break;
1302 }
1303 }
1304 }
1305 }
1306 }
1307
1308 if (isClosed)
1309 continue;
1310
1311 // Not closed solid is found
1312
1313 if (aFailedSolids.Contains(aSolid))
1314 // Warning has been generated for this solid, return positive result right away.
1315 return Standard_True;
1316
1317
1318 // Check the splits not to acquire new INTERNAL faces
1319 const TopTools_ListOfShape *pLSIm = myImages.Seek(aSolid);
1320 if (!pLSIm)
1321 continue;
1322
1323 TopTools_ListOfShape::Iterator itLSIm(*pLSIm);
1324 for (; itLSIm.More(); itLSIm.Next())
1325 {
1326 const TopoDS_Shape& aSIm = itLSIm.Value();
1327 for (TopoDS_Iterator itSh(aSIm); itSh.More(); itSh.Next())
1328 {
1329 const TopoDS_Shape& aSh = itSh.Value();
1330 if (aSh.ShapeType() != TopAbs_SHELL)
1331 continue;
1332
1333 for (TopoDS_Iterator itF(aSh); itF.More(); itF.Next())
1334 {
1335 const TopoDS_Shape& aF = itF.Value();
1336 if (aF.Orientation() == TopAbs_INTERNAL)
1337 {
1338 if (!aMFInternal.Contains(aF))
1339 // New internal face is found
1340 return Standard_True;
1341 }
1342 }
1343 }
1344 }
1345 }
1346
1347 return Standard_False;
1348}
1349
4e57c75e 1350//=======================================================================
8620e18d 1351//function : TypeToExplore
1352//purpose :
1353//=======================================================================
1354TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim)
1355{
1356 TopAbs_ShapeEnum aRet;
1357 //
1358 switch(theDim) {
1359 case 0:
1360 aRet=TopAbs_VERTEX;
1361 break;
1362 case 1:
1363 aRet=TopAbs_EDGE;
1364 break;
1365 case 2:
1366 aRet=TopAbs_FACE;
1367 break;
1368 case 3:
1369 aRet=TopAbs_SOLID;
1370 break;
1371 default:
1372 aRet=TopAbs_SHAPE;
1373 break;
1374 }
1375 return aRet;
1376}
9526aa6a 1377//=======================================================================
1378//function : CollectContainers
1379//purpose :
1380//=======================================================================
1381void CollectContainers(const TopoDS_Shape& theS,
1155d05a 1382 TopTools_ListOfShape& theLSC)
9526aa6a 1383{
1384 TopAbs_ShapeEnum aType = theS.ShapeType();
1385 if (aType == TopAbs_WIRE ||
1386 aType == TopAbs_SHELL ||
1387 aType == TopAbs_COMPSOLID) {
1388 theLSC.Append(theS);
1389 return;
1390 }
1391 //
1392 if (aType != TopAbs_COMPOUND) {
1393 return;
1394 }
1395 //
1396 TopoDS_Iterator aIt(theS);
1397 for (; aIt.More(); aIt.Next()) {
1398 const TopoDS_Shape& aS = aIt.Value();
1399 CollectContainers(aS, theLSC);
1400 }
1401}
1402
77a11d3d 1403//=======================================================================
1404//function : RemoveDuplicates
1405//purpose : Filters the containers with identical contents
1406//=======================================================================
1155d05a 1407void RemoveDuplicates(TopTools_ListOfShape& theContainers)
77a11d3d 1408{
1409 RemoveDuplicates(theContainers, TopAbs_WIRE);
1410 RemoveDuplicates(theContainers, TopAbs_SHELL);
1411 RemoveDuplicates(theContainers, TopAbs_COMPSOLID);
1412}
1413
1414//=======================================================================
1415//function : RemoveDuplicates
1416//purpose : Filters the containers of given type with identical contents
1417//=======================================================================
1155d05a 1418void RemoveDuplicates(TopTools_ListOfShape& theContainers,
77a11d3d 1419 const TopAbs_ShapeEnum theType)
1420{
1421 // get containers of given type
1155d05a 1422 TopTools_ListOfShape aLC;
1423 TopTools_ListIteratorOfListOfShape aItLC(theContainers);
77a11d3d 1424 for (; aItLC.More(); aItLC.Next()) {
1425 const TopoDS_Shape& aC = aItLC.Value();
1426 if (aC.ShapeType() == theType) {
1427 aLC.Append(aC);
1428 }
1429 }
1430 //
1431 if (aLC.IsEmpty()) {
1432 return;
1433 }
1434 //
1435 // map containers to compare its contents
1155d05a 1436 NCollection_IndexedDataMap<TopoDS_Shape, TopTools_MapOfShape> aContents;
77a11d3d 1437 //
1438 aItLC.Initialize(aLC);
1439 for (; aItLC.More(); aItLC.Next()) {
1440 const TopoDS_Shape& aC = aItLC.Value();
1441 //
1155d05a 1442 TopTools_MapOfShape& aMC = aContents(aContents.Add(aC, TopTools_MapOfShape()));
77a11d3d 1443 //
1444 TopoDS_Iterator aIt(aC);
1445 for (; aIt.More(); aIt.Next()) {
1446 aMC.Add(aIt.Value());
1447 }
1448 }
1449 //
1450 // compare the contents of the containers and find duplicates
1155d05a 1451 TopTools_MapOfShape aDuplicates;
77a11d3d 1452 //
1453 Standard_Integer i, j, aNb = aContents.Extent();
1454 for (i = 1; i <= aNb; ++i) {
1455 const TopoDS_Shape& aCi = aContents.FindKey(i);
1456 if (aDuplicates.Contains(aCi)) {
1457 continue;
1458 }
1155d05a 1459 const TopTools_MapOfShape& aMi = aContents(i);
77a11d3d 1460 Standard_Integer aNbi = aMi.Extent();
1461 //
1462 for (j = i + 1; j <= aNb; ++j) {
1463 const TopoDS_Shape& aCj = aContents.FindKey(j);
1464 if (aDuplicates.Contains(aCj)) {
1465 continue;
1466 }
1155d05a 1467 const TopTools_MapOfShape& aMj = aContents(j);
77a11d3d 1468 Standard_Integer aNbj = aMj.Extent();
1469 //
1470 Standard_Integer aNbCommon = NbCommonItemsInMap(aMi, aMj);
1471 //
1472 if (aNbj == aNbCommon) {
1473 aDuplicates.Add(aCj);
1474 continue;
1475 }
1476 //
1477 if (aNbi == aNbCommon) {
1478 aDuplicates.Add(aCi);
1479 break;
1480 }
1481 }
1482 }
1483 //
1484 if (aDuplicates.IsEmpty()) {
1485 return;
1486 }
1487 //
1488 // remove duplicating containers
1489 aItLC.Initialize(theContainers);
1490 for (; aItLC.More(); ) {
1491 const TopoDS_Shape& aC = aItLC.Value();
1492 if (aDuplicates.Contains(aC)) {
1493 theContainers.Remove(aItLC);
1494 continue;
1495 }
1496 aItLC.Next();
1497 }
1498}
1499
1500//=======================================================================
1501//function : NbCommonItemsInMap
1502//purpose : Counts the items contained in both maps
1503//=======================================================================
1155d05a 1504Standard_Integer NbCommonItemsInMap(const TopTools_MapOfShape& theM1,
1505 const TopTools_MapOfShape& theM2)
77a11d3d 1506{
1155d05a 1507 const TopTools_MapOfShape* aMap1 = &theM1;
1508 const TopTools_MapOfShape* aMap2 = &theM2;
77a11d3d 1509 //
1510 if (theM2.Extent() < theM1.Extent()) {
1511 aMap1 = &theM2;
1512 aMap2 = &theM1;
1513 }
1514 //
1515 Standard_Integer iCommon = 0;
1155d05a 1516 for (TopTools_MapIteratorOfMapOfShape aIt(*aMap1); aIt.More(); aIt.Next()) {
77a11d3d 1517 if (aMap2->Contains(aIt.Value())) {
1518 ++iCommon;
1519 }
1520 }
1521 return iCommon;
1522}
25dfc507 1523//=======================================================================
1524//function : MapFacesToBuildSolids
1525//purpose : Stores the faces of the given solid into outgoing maps:
1526// <theMFS> - not internal faces with reference to solid;
1527// <theMFI> - internal faces.
1528//=======================================================================
1529void MapFacesToBuildSolids(const TopoDS_Shape& theSol,
1155d05a 1530 TopTools_IndexedDataMapOfShapeListOfShape& theMFS,
1531 TopTools_IndexedMapOfShape& theMFI)
25dfc507 1532{
1533 TopExp_Explorer aExp(theSol, TopAbs_FACE);
1534 for (; aExp.More(); aExp.Next()) {
1535 const TopoDS_Shape& aF = aExp.Current();
1536 //
1537 if (aF.Orientation() == TopAbs_INTERNAL) {
1538 theMFI.Add(aF);
1539 continue;
1540 }
1541 //
1155d05a 1542 TopTools_ListOfShape* pLSol = theMFS.ChangeSeek(aF);
25dfc507 1543 if (!pLSol) {
1155d05a 1544 pLSol = &theMFS(theMFS.Add(aF, TopTools_ListOfShape()));
25dfc507 1545 pLSol->Append(theSol);
1546 }
1547 else {
1548 const TopoDS_Shape& aF1 = theMFS.FindKey(theMFS.FindIndex(aF));
1549 if (aF1.Orientation() != aF.Orientation()) {
1550 pLSol->Append(theSol);
1551 }
1552 }
1553 }
1554}