0030145: Modeling Algorithms - Boolean Operations on open solids
[occt.git] / src / BOPAlgo / BOPAlgo_Builder.cxx
CommitLineData
4e57c75e 1// Created by: Peter KURNEV
973c2be1 2// Copyright (c) 2010-2014 OPEN CASCADE SAS
4e57c75e 3// Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
4// Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT,
5// EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6//
973c2be1 7// This file is part of Open CASCADE Technology software library.
4e57c75e 8//
d5f74e42 9// This library is free software; you can redistribute it and/or modify it under
10// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 11// by the Free Software Foundation, with special exception defined in the file
12// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
13// distribution for complete text of the license and disclaimer of any warranty.
4e57c75e 14//
973c2be1 15// Alternatively, this file may be used under the terms of Open CASCADE
16// commercial license or contractual agreement.
4e57c75e 17
4e57c75e 18
42cf5bc1 19#include <BOPAlgo_Builder.hxx>
33ba8565 20#include <BOPAlgo_Alerts.hxx>
13c0e402 21#include <BOPAlgo_BuilderSolid.hxx>
22#include <BOPAlgo_PaveFiller.hxx>
23#include <BOPAlgo_Tools.hxx>
24#include <BOPDS_DS.hxx>
25#include <BOPDS_ShapeInfo.hxx>
42cf5bc1 26#include <BOPTools_AlgoTools.hxx>
27#include <BRep_Builder.hxx>
28#include <IntTools_Context.hxx>
36f4947b 29#include <Standard_ErrorHandler.hxx>
30#include <Standard_Failure.hxx>
13c0e402 31#include <TopExp.hxx>
32#include <TopExp_Explorer.hxx>
33#include <TopoDS.hxx>
4e57c75e 34#include <TopoDS_Compound.hxx>
13c0e402 35#include <TopoDS_Solid.hxx>
1155d05a 36#include <TopTools_IndexedMapOfShape.hxx>
13c0e402 37#include <TopTools_MapOfOrientedShape.hxx>
4e57c75e 38
3510db62 39
4e57c75e 40//=======================================================================
41//function :
42//purpose :
43//=======================================================================
796a784d 44BOPAlgo_Builder::BOPAlgo_Builder()
4e57c75e 45:
46 BOPAlgo_BuilderShape(),
47 myArguments(myAllocator),
48 myMapFence(100, myAllocator),
49 myPaveFiller(NULL),
50 myDS(NULL),
4e57c75e 51 myEntryPoint(0),
52 myImages(100, myAllocator),
53 myShapesSD(100, myAllocator),
b1d15f53 54 myOrigins(100, myAllocator),
13c0e402 55 myInParts(100, myAllocator),
483ce1bd 56 myNonDestructive(Standard_False),
81a55a69 57 myGlue(BOPAlgo_GlueOff),
58 myCheckInverted(Standard_True)
4e57c75e 59{
60}
61//=======================================================================
62//function :
63//purpose :
64//=======================================================================
796a784d 65BOPAlgo_Builder::BOPAlgo_Builder
66 (const Handle(NCollection_BaseAllocator)& theAllocator)
4e57c75e 67:
68 BOPAlgo_BuilderShape(theAllocator),
69 myArguments(myAllocator),
70 myMapFence(100, myAllocator),
71 myPaveFiller(NULL),
72 myDS(NULL),
4e57c75e 73 myEntryPoint(0),
74 myImages(100, myAllocator),
75 myShapesSD(100, myAllocator),
b1d15f53 76 myOrigins(100, myAllocator),
13c0e402 77 myInParts(100, myAllocator),
483ce1bd 78 myNonDestructive(Standard_False),
81a55a69 79 myGlue(BOPAlgo_GlueOff),
80 myCheckInverted(Standard_True)
4e57c75e 81{
82}
83//=======================================================================
84//function : ~
85//purpose :
86//=======================================================================
796a784d 87BOPAlgo_Builder::~BOPAlgo_Builder()
4e57c75e 88{
89 if (myEntryPoint==1) {
90 if (myPaveFiller) {
91 delete myPaveFiller;
92 myPaveFiller=NULL;
93 }
94 }
95}
96//=======================================================================
97//function : Clear
98//purpose :
99//=======================================================================
796a784d 100void BOPAlgo_Builder::Clear()
4e57c75e 101{
948fe6ca 102 BOPAlgo_BuilderShape::Clear();
4e57c75e 103 myArguments.Clear();
104 myMapFence.Clear();
105 myImages.Clear();
106 myShapesSD.Clear();
4e57c75e 107 myOrigins.Clear();
13c0e402 108 myInParts.Clear();
4e57c75e 109}
110//=======================================================================
111//function : AddArgument
112//purpose :
113//=======================================================================
796a784d 114void BOPAlgo_Builder::AddArgument(const TopoDS_Shape& theShape)
4e57c75e 115{
116 if (myMapFence.Add(theShape)) {
117 myArguments.Append(theShape);
118 }
119}
120//=======================================================================
92ae0f2f 121//function : SetArguments
122//purpose :
123//=======================================================================
1155d05a 124void BOPAlgo_Builder::SetArguments(const TopTools_ListOfShape& theShapes)
92ae0f2f 125{
1155d05a 126 TopTools_ListIteratorOfListOfShape aIt;
92ae0f2f 127 //
49b0c452 128 myArguments.Clear();
129 //
92ae0f2f 130 aIt.Initialize(theShapes);
131 for (; aIt.More(); aIt.Next()) {
132 const TopoDS_Shape& aS = aIt.Value();
133 AddArgument(aS);
134 }
135}
136//=======================================================================
4e57c75e 137// function: CheckData
138// purpose:
139//=======================================================================
796a784d 140void BOPAlgo_Builder::CheckData()
4e57c75e 141{
33ba8565 142 Standard_Integer aNb = myArguments.Extent();
4e57c75e 143 if (aNb<2) {
33ba8565 144 AddError (new BOPAlgo_AlertTooFewArguments); // too few arguments to process
4e57c75e 145 return;
146 }
147 //
33ba8565 148 CheckFiller();
149}
150//=======================================================================
151// function: CheckFiller
152// purpose:
153//=======================================================================
154void BOPAlgo_Builder::CheckFiller()
155{
4e57c75e 156 if (!myPaveFiller) {
33ba8565 157 AddError (new BOPAlgo_AlertNoFiller);
4e57c75e 158 return;
159 }
33ba8565 160 GetReport()->Merge (myPaveFiller->GetReport());
4e57c75e 161}
33ba8565 162
4e57c75e 163//=======================================================================
164//function : Prepare
165//purpose :
166//=======================================================================
796a784d 167void BOPAlgo_Builder::Prepare()
4e57c75e 168{
4e57c75e 169 BRep_Builder aBB;
170 TopoDS_Compound aC;
171 //
172 // 1. myShape is empty compound
173 aBB.MakeCompound(aC);
174 myShape=aC;
4e57c75e 175}
176//=======================================================================
177//function : Perform
178//purpose :
179//=======================================================================
796a784d 180void BOPAlgo_Builder::Perform()
4e57c75e 181{
33ba8565 182 GetReport()->Clear();
4e57c75e 183 //
184 if (myEntryPoint==1) {
185 if (myPaveFiller) {
186 delete myPaveFiller;
187 myPaveFiller=NULL;
188 }
189 }
190 //
488e5b9d 191 Handle(NCollection_BaseAllocator) aAllocator=
192 NCollection_BaseAllocator::CommonBaseAllocator();
4e57c75e 193 //
194 BOPAlgo_PaveFiller* pPF=new BOPAlgo_PaveFiller(aAllocator);
195 //
196 pPF->SetArguments(myArguments);
92ae0f2f 197 pPF->SetRunParallel(myRunParallel);
b1d15f53 198 pPF->SetProgressIndicator(myProgressIndicator);
199 pPF->SetFuzzyValue(myFuzzyValue);
3510db62 200 pPF->SetNonDestructive(myNonDestructive);
483ce1bd 201 pPF->SetGlue(myGlue);
944768d2 202 pPF->SetUseOBB(myUseOBB);
4e57c75e 203 //
204 pPF->Perform();
205 //
206 myEntryPoint=1;
207 PerformInternal(*pPF);
208}
209//=======================================================================
210//function : PerformWithFiller
211//purpose :
212//=======================================================================
796a784d 213void BOPAlgo_Builder::PerformWithFiller(const BOPAlgo_PaveFiller& theFiller)
4e57c75e 214{
33ba8565 215 GetReport()->Clear();
4e57c75e 216 myEntryPoint=0;
3510db62 217 myNonDestructive = theFiller.NonDestructive();
218 myFuzzyValue = theFiller.FuzzyValue();
483ce1bd 219 myGlue = theFiller.Glue();
944768d2 220 myUseOBB = theFiller.UseOBB();
4e57c75e 221 PerformInternal(theFiller);
222}
223//=======================================================================
224//function : PerformInternal
225//purpose :
226//=======================================================================
796a784d 227void BOPAlgo_Builder::PerformInternal(const BOPAlgo_PaveFiller& theFiller)
36f4947b 228{
33ba8565 229 GetReport()->Clear();
230 //
231 try {
36f4947b 232 OCC_CATCH_SIGNALS
233 PerformInternal1(theFiller);
234 }
235 //
236 catch (Standard_Failure) {
33ba8565 237 AddError (new BOPAlgo_AlertBuilderFailed);
238 }
36f4947b 239}
240//=======================================================================
241//function : PerformInternal1
242//purpose :
243//=======================================================================
244void BOPAlgo_Builder::PerformInternal1(const BOPAlgo_PaveFiller& theFiller)
4e57c75e 245{
4e57c75e 246 myPaveFiller=(BOPAlgo_PaveFiller*)&theFiller;
247 myDS=myPaveFiller->PDS();
248 myContext=myPaveFiller->Context();
0d0481c7 249 myFuzzyValue = myPaveFiller->FuzzyValue();
250 myNonDestructive = myPaveFiller->NonDestructive();
4e57c75e 251 //
252 // 1. CheckData
253 CheckData();
33ba8565 254 if (HasErrors()) {
4e57c75e 255 return;
256 }
257 //
258 // 2. Prepare
259 Prepare();
33ba8565 260 if (HasErrors()) {
4e57c75e 261 return;
262 }
263 //
264 // 3. Fill Images
265 // 3.1 Vertice
266 FillImagesVertices();
33ba8565 267 if (HasErrors()) {
4e57c75e 268 return;
269 }
270 //
271 BuildResult(TopAbs_VERTEX);
33ba8565 272 if (HasErrors()) {
4e57c75e 273 return;
274 }
275 // 3.2 Edges
276 FillImagesEdges();
33ba8565 277 if (HasErrors()) {
4e57c75e 278 return;
279 }
280 //
281 BuildResult(TopAbs_EDGE);
33ba8565 282 if (HasErrors()) {
4e57c75e 283 return;
284 }
285 //
286 // 3.3 Wires
287 FillImagesContainers(TopAbs_WIRE);
33ba8565 288 if (HasErrors()) {
4e57c75e 289 return;
290 }
291 //
292 BuildResult(TopAbs_WIRE);
33ba8565 293 if (HasErrors()) {
4e57c75e 294 return;
295 }
296
297 // 3.4 Faces
298 FillImagesFaces();
33ba8565 299 if (HasErrors()) {
4e57c75e 300 return;
301 }
302 //
303 BuildResult(TopAbs_FACE);
33ba8565 304 if (HasErrors()) {
4e57c75e 305 return;
306 }
307 // 3.5 Shells
308 FillImagesContainers(TopAbs_SHELL);
33ba8565 309 if (HasErrors()) {
4e57c75e 310 return;
311 }
312
313 BuildResult(TopAbs_SHELL);
33ba8565 314 if (HasErrors()) {
4e57c75e 315 return;
316 }
317 // 3.6 Solids
318 FillImagesSolids();
33ba8565 319 if (HasErrors()) {
4e57c75e 320 return;
321 }
322
323 BuildResult(TopAbs_SOLID);
33ba8565 324 if (HasErrors()) {
4e57c75e 325 return;
326 }
327 // 3.7 CompSolids
328 FillImagesContainers(TopAbs_COMPSOLID);
33ba8565 329 if (HasErrors()) {
4e57c75e 330 return;
331 }
332
333 BuildResult(TopAbs_COMPSOLID);
33ba8565 334 if (HasErrors()) {
4e57c75e 335 return;
336 }
337
338 // 3.8 Compounds
339 FillImagesCompounds();
33ba8565 340 if (HasErrors()) {
4e57c75e 341 return;
342 }
343
344 BuildResult(TopAbs_COMPOUND);
33ba8565 345 if (HasErrors()) {
4e57c75e 346 return;
347 }
348 //
349 // 4.History
350 PrepareHistory();
351 //
352 //
353 // 5 Post-treatment
354 PostTreat();
355
356}
4e57c75e 357//=======================================================================
358//function : PostTreat
359//purpose :
360//=======================================================================
796a784d 361void BOPAlgo_Builder::PostTreat()
4e57c75e 362{
3510db62 363 Standard_Integer i, aNbS;
364 TopAbs_ShapeEnum aType;
1155d05a 365 TopTools_IndexedMapOfShape aMA;
3510db62 366 if (myPaveFiller->NonDestructive()) {
367 // MapToAvoid
368 aNbS=myDS->NbSourceShapes();
369 for (i=0; i<aNbS; ++i) {
370 const BOPDS_ShapeInfo& aSI=myDS->ShapeInfo(i);
371 aType=aSI.ShapeType();
372 if (aType==TopAbs_VERTEX ||
373 aType==TopAbs_EDGE||
374 aType==TopAbs_FACE) {
375 const TopoDS_Shape& aS=aSI.Shape();
376 aMA.Add(aS);
377 }
378 }
379 }
380 //
381 BOPTools_AlgoTools::CorrectTolerances(myShape, aMA, 0.05, myRunParallel);
382 BOPTools_AlgoTools::CorrectShapeTolerances(myShape, aMA, myRunParallel);
4e57c75e 383}
13c0e402 384
385//=======================================================================
386//function : BuildBOP
387//purpose :
388//=======================================================================
389void BOPAlgo_Builder::BuildBOP(const TopTools_ListOfShape& theObjects,
390 const TopAbs_State theObjState,
391 const TopTools_ListOfShape& theTools,
392 const TopAbs_State theToolsState,
393 Handle(Message_Report) theReport)
394{
395 if (HasErrors())
396 return;
397
398 // Report for the method
399 Handle(Message_Report) aReport = theReport.IsNull() ? myReport : theReport;
400
401 if (myArguments.IsEmpty() || myShape.IsNull())
402 {
403 aReport->AddAlert(Message_Fail, new BOPAlgo_AlertBuilderFailed());
404 return;
405 }
406
407 // Check the input data
408 if ((theObjState != TopAbs_IN && theObjState != TopAbs_OUT) ||
409 (theToolsState != TopAbs_IN && theToolsState != TopAbs_OUT))
410 {
411 aReport->AddAlert(Message_Fail, new BOPAlgo_AlertBOPNotSet());
412 return;
413 }
414
415 // Check input shapes
416 Standard_Boolean hasObjects = !theObjects.IsEmpty();
417 Standard_Boolean hasTools = !theTools .IsEmpty();
418 if (!hasObjects && !hasTools)
419 {
420 aReport->AddAlert(Message_Fail, new BOPAlgo_AlertTooFewArguments());
421 return;
422 }
423
424 // Check that all input solids are from the arguments
425 for (Standard_Integer i = 0; i < 2; ++i)
426 {
427 const TopTools_ListOfShape& aList = !i ? theObjects : theTools;
428 TopTools_ListOfShape::Iterator itLS(aList);
429 for (; itLS.More(); itLS.Next())
430 {
431 const TopoDS_Shape& aS = itLS.Value();
432 // Check if the shape belongs to the arguments of operation
433 if (myDS->Index(aS) < 0)
434 {
435 aReport->AddAlert(Message_Fail, new BOPAlgo_AlertUnknownShape(aS));
436 return;
437 }
438
439 // Check if the shape is a solid or collection of them
440 if (aS.ShapeType() != TopAbs_SOLID)
441 {
442 TopTools_ListOfShape aLS;
443 TopTools_MapOfShape aMFence;
444 BOPAlgo_Tools::TreatCompound(aS, aMFence, aLS);
445
446 TopTools_ListOfShape::Iterator it(aLS);
447 for (; it.More(); it.Next())
448 {
449 const TopoDS_Shape& aSx = it.Value();
450 if (aSx.ShapeType() != TopAbs_SOLID &&
451 aSx.ShapeType() != TopAbs_COMPSOLID)
452 {
453 aReport->AddAlert(Message_Fail, new BOPAlgo_AlertUnsupportedType(aS));
454 return;
455 }
456 }
457 }
458 }
459 }
460
461 // Classification of the faces relatively solids has been made
462 // on the stage of Solids splitting. All results are saved into
463 // myInParts map, which connects the solids with its IN faces from
464 // other arguments. All faces not contained in the list of IN faces
465 // will be considered as OUT.
466
467 // Prepare the maps of splits of solids faces with orientations
468 TopTools_IndexedMapOfOrientedShape aMObjFacesOri, aMToolFacesOri;
469 // Prepare the maps of splits of solids faces
470 TopTools_IndexedMapOfShape aMObjFaces, aMToolFaces;
471 // Copy the list of IN faces of the solids into map
472 TopTools_MapOfShape anINObjects, anINTools;
473
474 for (Standard_Integer i = 0; i < 2; ++i)
475 {
476 const TopTools_ListOfShape& aList = !i ? theObjects : theTools;
477 TopTools_IndexedMapOfOrientedShape& aMapOri = !i ? aMObjFacesOri : aMToolFacesOri;
478 TopTools_IndexedMapOfShape& aMap = !i ? aMObjFaces : aMToolFaces;
479 TopTools_ListOfShape::Iterator itLS(aList);
480 for (; itLS.More(); itLS.Next())
481 {
482 const TopoDS_Shape& aShape = itLS.Value();
483 TopExp_Explorer expS(aShape, TopAbs_SOLID);
484 for (; expS.More(); expS.Next())
485 {
486 const TopoDS_Shape& aS = expS.Current();
487 TopExp_Explorer expF(aS, TopAbs_FACE);
488 for (; expF.More(); expF.Next())
489 {
490 const TopoDS_Shape& aF = expF.Current();
491 if (aF.Orientation() != TopAbs_FORWARD &&
492 aF.Orientation() != TopAbs_REVERSED)
493 continue;
494 const TopTools_ListOfShape* pLFIm = myImages.Seek(aF);
495 if (pLFIm)
496 {
497 TopTools_ListOfShape::Iterator itLFIm(*pLFIm);
498 for (; itLFIm.More(); itLFIm.Next())
499 {
500 TopoDS_Face aFIm = TopoDS::Face(itLFIm.Value());
501 if (BOPTools_AlgoTools::IsSplitToReverse(aFIm, aF, myContext))
502 aFIm.Reverse();
503 aMapOri.Add(aFIm);
504 aMap.Add(aFIm);
505 }
506 }
507 else
508 {
509 aMapOri.Add(aF);
510 aMap.Add(aF);
511 }
512 }
513
514 // Copy the list of IN faces into a map
515 const TopTools_ListOfShape* pLFIN = myInParts.Seek(aS);
516 if (pLFIN)
517 {
518 TopTools_MapOfShape& anINMap = !i ? anINObjects : anINTools;
519 TopTools_ListOfShape::Iterator itLFIn(*pLFIN);
520 for (; itLFIn.More(); itLFIn.Next())
521 anINMap.Add(itLFIn.Value());
522 }
523 }
524 }
525 }
526
527 // Now we need to select all faces which will participate in
528 // building of the resulting solids. The final set of faces
529 // depends on the given states for the groups.
530 Standard_Boolean isObjectsIN = (theObjState == TopAbs_IN),
531 isToolsIN = (theToolsState == TopAbs_IN);
532
533 // Shortcuts
534 Standard_Boolean bAvoidIN = (!isObjectsIN && !isToolsIN), // avoid all in faces
535 bAvoidINforBoth = (isObjectsIN != isToolsIN); // avoid faces IN for both groups
536
537 // Choose which SD faces are needed to be taken - equally or differently oriented faces
538 Standard_Boolean isSameOriNeeded = (theObjState == theToolsState);
539 // Resulting faces
540 TopTools_IndexedMapOfOrientedShape aMResFacesOri;
541 TopTools_MapOfShape aMResFacesFence;
542 // Fence map
543 TopTools_MapOfShape aMFence, aMFToAvoid;
544 // Oriented fence map
545 TopTools_MapOfOrientedShape aMFenceOri;
546
547 for (Standard_Integer i = 0; i < 2; ++i)
548 {
549 const TopTools_IndexedMapOfOrientedShape& aMap = !i ? aMObjFacesOri : aMToolFacesOri;
550 const TopTools_IndexedMapOfShape& anOppositeMap = !i ? aMToolFaces : aMObjFaces;
551 const TopTools_MapOfShape& anINMap = !i ? anINObjects : anINTools;
552 const TopTools_MapOfShape& anOppositeINMap = !i ? anINTools : anINObjects;
553 const Standard_Boolean bTakeIN = !i ? isObjectsIN : isToolsIN;
554
555 const Standard_Integer aNbF = aMap.Extent();
556 for (Standard_Integer j = 1; j <= aNbF; ++j)
557 {
558 TopoDS_Shape aFIm = aMap(j);
559
560 Standard_Boolean isIN = anINMap.Contains(aFIm);
561 Standard_Boolean isINOpposite = anOppositeINMap.Contains(aFIm);
562
563 // Filtering for FUSE - avoid any IN faces
564 if (bAvoidIN && (isIN || isINOpposite))
565 continue;
566
567 // Filtering for CUT - avoid faces IN for both groups
568 if (bAvoidINforBoth && isIN && isINOpposite)
569 continue;
570
571 // Treatment of SD faces
572 if (!aMFence.Add(aFIm))
573 {
574 if (!anOppositeMap.Contains(aFIm))
575 {
576 // The face belongs to only one group
577 if (bTakeIN != isSameOriNeeded)
578 aMFToAvoid.Add(aFIm);
579 }
580 else
581 {
582 // The face belongs to both groups.
583 // Using its orientation decide if it is needed in the result or not.
584 Standard_Boolean isSameOri = !aMFenceOri.Add(aFIm);
585 if (isSameOriNeeded == isSameOri)
586 {
587 // Take the shape without classification
588 if (aMResFacesFence.Add(aFIm))
589 aMResFacesOri.Add(aFIm);
590 }
591 else
592 // Remove the face
593 aMFToAvoid.Add(aFIm);
594
595 continue;
596 }
597 }
598 if (!aMFenceOri.Add(aFIm))
599 continue;
600
601 if (bTakeIN == isINOpposite)
602 {
603 if (isIN)
604 {
605 aMResFacesOri.Add(aFIm);
606 aMResFacesOri.Add(aFIm.Reversed());
607 }
608 else if (bTakeIN && !isSameOriNeeded)
609 aMResFacesOri.Add(aFIm.Reversed());
610 else
611 aMResFacesOri.Add(aFIm);
612 aMResFacesFence.Add(aFIm);
613 }
614 }
615 }
616
617 // Remove the faces which has to be avoided
618 TopTools_ListOfShape aResFaces;
619 const Standard_Integer aNbRF = aMResFacesOri.Extent();
620 for (Standard_Integer i = 1; i <= aNbRF; ++i)
621 {
622 const TopoDS_Shape& aRF = aMResFacesOri(i);
623 if (!aMFToAvoid.Contains(aRF))
624 aResFaces.Append(aRF);
625 }
626
627 BRep_Builder aBB;
628
629 // Try to build closed solids from the faces
630 BOPAlgo_BuilderSolid aBS;
631 aBS.SetShapes(aResFaces);
632 aBS.SetRunParallel(myRunParallel);
633 aBS.SetContext(myContext);
634 aBS.SetFuzzyValue(myFuzzyValue);
635 aBS.SetProgressIndicator(myProgressIndicator);
636 aBS.Perform();
637
638 // Resulting solids
639 TopTools_ListOfShape aResSolids;
640
641 aMFence.Clear();
642 if (!aBS.HasErrors())
643 {
644 // If any, add solids into resulting compound
645 TopTools_ListIteratorOfListOfShape itA(aBS.Areas());
646 for (; itA.More(); itA.Next())
647 {
648 const TopoDS_Shape& aSolid = itA.Value();
649 // The solid must contain at least one face
650 // from either of objects or tools
651 TopExp_Explorer expF(aSolid, TopAbs_FACE);
652 for (; expF.More(); expF.Next())
653 {
654 const TopoDS_Shape& aF = expF.Current();
655 if (aMObjFacesOri.Contains(aF) || aMToolFacesOri.Contains(aF))
656 break;
657 }
658 if (expF.More())
659 {
660 aResSolids.Append(aSolid);
661 TopExp::MapShapes(aSolid, aMFence);
662 }
663 }
664 }
665
666 // Collect unused faces
667 TopoDS_Compound anUnUsedFaces;
668 aBB.MakeCompound(anUnUsedFaces);
669
670 TopTools_ListOfShape::Iterator itLF(aResFaces);
671 for (; itLF.More(); itLF.Next())
672 {
673 if (aMFence.Add(itLF.Value()))
674 aBB.Add(anUnUsedFaces, itLF.Value());
675 }
676
677 // Build blocks from the unused faces
678 TopTools_ListOfShape aLCB;
679 BOPTools_AlgoTools::MakeConnexityBlocks(anUnUsedFaces, TopAbs_EDGE, TopAbs_FACE, aLCB);
680
681 // Build solid from each block
682 TopTools_ListIteratorOfListOfShape itCB(aLCB);
683 for (; itCB.More(); itCB.Next())
684 {
685 const TopoDS_Shape& aCB = itCB.Value();
686 TopoDS_Shell aShell;
687 aBB.MakeShell(aShell);
688 // Add faces of the block to the shell
689 TopExp_Explorer anExpF(aCB, TopAbs_FACE);
690 for (; anExpF.More(); anExpF.Next())
691 aBB.Add(aShell, TopoDS::Face(anExpF.Current()));
692
693 BOPTools_AlgoTools::OrientFacesOnShell(aShell);
694 // Make solid out of the shell
695 TopoDS_Solid aSolid;
696 aBB.MakeSolid(aSolid);
697 aBB.Add(aSolid, aShell);
698 // Add new solid to result
699 aResSolids.Append(aSolid);
700 }
701
702 if (!bAvoidIN)
703 {
704 // Fill solids with internal parts coming with the solids
705 TopTools_ListOfShape anInParts;
706 for (Standard_Integer i = 0; i < 2; ++i)
707 {
708 const TopTools_ListOfShape& aList = !i ? theObjects : theTools;
709 TopTools_ListOfShape::Iterator itLS(aList);
710 for (; itLS.More(); itLS.Next())
711 {
712 TopExp_Explorer expS(itLS.Value(), TopAbs_SOLID);
713 for (; expS.More(); expS.Next())
714 {
715 const TopoDS_Shape& aS = expS.Current(); // Solid
716 for (TopoDS_Iterator it(aS); it.More(); it.Next())
717 {
718 const TopoDS_Shape& aSInt = it.Value();
719 if (aSInt.Orientation() == TopAbs_INTERNAL)
720 anInParts.Append(aSInt); // vertex or edge
721 else
722 {
723 // shell treatment
724 TopoDS_Iterator itInt(aSInt);
725 if (itInt.More() && itInt.Value().Orientation() == TopAbs_INTERNAL)
726 anInParts.Append(aSInt);
727 }
728 }
729 }
730 }
731 }
732
733 BOPAlgo_Tools::FillInternals(aResSolids, anInParts, myImages, myContext);
734 }
735
736 // Combine solids into compound
737 TopoDS_Shape aResult;
738 aBB.MakeCompound(TopoDS::Compound(aResult));
739
740 TopTools_ListOfShape::Iterator itLS(aResSolids);
741 for (; itLS.More(); itLS.Next())
742 aBB.Add(aResult, itLS.Value());
743
744 myShape = aResult;
745 PrepareHistory();
746}