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