8b7a54b66a21e0519f5788a6ad1466f2a1b7c352
[occt.git] / src / BOPAlgo / BOPAlgo_CellsBuilder.cxx
1 // Created by: Eugeny MALTCHIKOV
2 // Copyright (c) 2015 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_CellsBuilder.hxx>
17
18 #include <BOPAlgo_Alerts.hxx>
19 #include <BOPAlgo_BuilderSolid.hxx>
20 #include <BOPDS_DS.hxx>
21 #include <BOPTools_AlgoTools.hxx>
22 #include <BOPTools_AlgoTools3D.hxx>
23 #include <BRep_Builder.hxx>
24 #include <ShapeUpgrade_UnifySameDomain.hxx>
25 #include <TColStd_MapOfInteger.hxx>
26 #include <TopExp.hxx>
27 #include <TopExp_Explorer.hxx>
28 #include <TopoDS_Compound.hxx>
29
30
31 static
32   TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim);
33
34 static
35   void MakeTypedContainers(const TopoDS_Shape& theSC,
36                            TopoDS_Shape& theResult);
37
38 static void CollectMaterialBoundaries(const TopTools_ListOfShape& theLS,
39                                       TopTools_MapOfShape& theMapKeepBnd);
40
41 //=======================================================================
42 //function : empty constructor
43 //purpose  : 
44 //=======================================================================
45 BOPAlgo_CellsBuilder::BOPAlgo_CellsBuilder()
46 :
47   BOPAlgo_Builder(),
48   myIndex(100, myAllocator),
49   myMaterials(100, myAllocator),
50   myShapeMaterial(100, myAllocator),
51   myMapModified(100, myAllocator)
52 {
53 }
54
55 //=======================================================================
56 //function : empty constructor
57 //purpose  : 
58 //=======================================================================
59 BOPAlgo_CellsBuilder::BOPAlgo_CellsBuilder
60   (const Handle(NCollection_BaseAllocator)& theAllocator)
61 :
62   BOPAlgo_Builder(theAllocator),
63   myIndex(100, myAllocator),
64   myMaterials(100, myAllocator),
65   myShapeMaterial(100, myAllocator),
66   myMapModified(100, myAllocator)
67 {
68 }
69
70 //=======================================================================
71 //function : ~
72 //purpose  : 
73 //=======================================================================
74 BOPAlgo_CellsBuilder::~BOPAlgo_CellsBuilder()
75 {
76   Clear();
77 }
78
79 //=======================================================================
80 //function : Clear
81 //purpose  : 
82 //=======================================================================
83 void BOPAlgo_CellsBuilder::Clear()
84 {
85   BOPAlgo_Builder::Clear();
86   myIndex.Clear();
87   myMaterials.Clear();
88   myShapeMaterial.Clear();
89   myMapModified.Clear();
90 }
91
92 //=======================================================================
93 //function : GetAllParts
94 //purpose  : 
95 //=======================================================================
96 const TopoDS_Shape& BOPAlgo_CellsBuilder::GetAllParts() const
97 {
98   return myAllParts;
99 }
100
101 //=======================================================================
102 //function : PerformInternal1
103 //purpose  : 
104 //=======================================================================
105 void BOPAlgo_CellsBuilder::PerformInternal1(const BOPAlgo_PaveFiller& theFiller)
106 {
107   // Avoid filling history after GF operation as later
108   // in this method the result shape will be nullified
109   Standard_Boolean isHistory = HasHistory();
110   SetToFillHistory(Standard_False);
111   // Perform splitting of the arguments
112   BOPAlgo_Builder::PerformInternal1(theFiller);
113   if (HasErrors()) {
114     return;
115   }
116
117   // index all the parts to its origins
118   IndexParts();
119
120   // and nullify <myShape> for building the result;
121   RemoveAllFromResult();
122
123   // Restore user's history settings
124   SetToFillHistory(isHistory);
125 }
126
127 //=======================================================================
128 //function : IndexParts
129 //purpose  : 
130 //=======================================================================
131 void BOPAlgo_CellsBuilder::IndexParts()
132 {
133   BRep_Builder aBB;
134   // all split parts of the shapes
135   TopoDS_Compound anAllParts;
136   aBB.MakeCompound(anAllParts);
137   //
138   TopTools_MapOfShape aMFence;
139   TColStd_MapOfInteger aMDims;
140   //
141   TopTools_ListIteratorOfListOfShape aIt(myArguments);
142   for (; aIt.More(); aIt.Next()) {
143     const TopoDS_Shape& aS = aIt.Value();
144     //
145     Standard_Integer iDim = BOPTools_AlgoTools::Dimension(aS);
146     aMDims.Add(iDim);
147     TopAbs_ShapeEnum aType = TypeToExplore(iDim);
148     //
149     TopExp_Explorer aExp(aS, aType);
150     for (; aExp.More(); aExp.Next()) {
151       const TopoDS_Shape& aST = aExp.Current();
152       const TopTools_ListOfShape* pLSIm = myImages.Seek(aST);
153       if (!pLSIm) {
154         TopTools_ListOfShape* pLS = myIndex.ChangeSeek(aST);
155         if (!pLS) {
156           pLS = &myIndex(myIndex.Add(aST, TopTools_ListOfShape()));
157         }
158         pLS->Append(aS);
159         //
160         if (aMFence.Add(aST)) {
161           aBB.Add(anAllParts, aST);
162         }
163         //
164         continue;
165       }
166       //
167       TopTools_ListIteratorOfListOfShape aItIm(*pLSIm);
168       for (; aItIm.More(); aItIm.Next()) {
169         const TopoDS_Shape& aSTIm = aItIm.Value();
170         //
171         TopTools_ListOfShape* pLS = myIndex.ChangeSeek(aSTIm);
172         if (!pLS) {
173           pLS = &myIndex(myIndex.Add(aSTIm, TopTools_ListOfShape()));
174         }
175         pLS->Append(aS);
176         //
177         if (aMFence.Add(aSTIm)) {
178           aBB.Add(anAllParts, aSTIm);
179         }
180       } // for (; aItIm.More(); aItIm.Next()) {
181     } // for (; aExp.More(); aExp.Next()) {
182   } // for (; aIt.More(); aIt.Next()) {
183   //
184   myAllParts = anAllParts;
185   //
186   if (aMDims.Extent() == 1) {
187     return;
188   }
189   //
190   // for the multi-dimensional case
191   // add sub-shapes of the splits into the <myIndex> map
192   //
193   Standard_Integer i, aNbS = myIndex.Extent();
194   for (i = 1; i <= aNbS; ++i) {
195     const TopoDS_Shape& aSP = myIndex.FindKey(i);
196     const TopTools_ListOfShape& aLSOr = myIndex(i);
197     //
198     Standard_Integer iType = BOPTools_AlgoTools::Dimension(aSP);
199     TColStd_MapIteratorOfMapOfInteger aItM(aMDims);
200     for (; aItM.More(); aItM.Next()) {
201       Standard_Integer k = aItM.Value();
202       if (k >= iType) {
203         continue;
204       }
205       //
206       TopExp_Explorer aExp(aSP, TypeToExplore(k));
207       for (; aExp.More(); aExp.Next()) {
208         const TopoDS_Shape& aSS = aExp.Current();
209         TopTools_ListOfShape* pLSSOr = myIndex.ChangeSeek(aSS);
210         if (!pLSSOr) {
211           myIndex.Add(aSS, aLSOr);
212           continue;
213         }
214         // add ancestors of the shape to the ancestors of the sub-shape
215         TopTools_ListIteratorOfListOfShape aItLS(aLSOr);
216         for (; aItLS.More(); aItLS.Next()) {
217           const TopoDS_Shape& aSOr = aItLS.Value();
218           // provide uniqueness of the ancestors
219           TopTools_ListIteratorOfListOfShape aItLSS(*pLSSOr);
220           for (; aItLSS.More(); aItLSS.Next()) {
221             if (aSOr.IsSame(aItLSS.Value())) {
222               break;
223             }
224           }
225           //
226           if (!aItLSS.More()) {
227             pLSSOr->Append(aSOr);
228           }
229         }
230       }
231     }
232   }
233 }
234
235 //=======================================================================
236 //function : AddToResult
237 //purpose  : 
238 //=======================================================================
239 void BOPAlgo_CellsBuilder::AddToResult(const TopTools_ListOfShape& theLSToTake,
240                                        const TopTools_ListOfShape& theLSToAvoid,
241                                        const Standard_Integer theMaterial,
242                                        const Standard_Boolean theUpdate)
243 {
244   // find parts
245   TopTools_ListOfShape aParts;
246   FindParts(theLSToTake, theLSToAvoid, aParts);
247   if (aParts.IsEmpty()) {
248     return;
249   }
250   //
251   // collect result parts to avoid multiple adding of the same parts
252   TopTools_MapOfShape aResParts;
253   TopoDS_Iterator aIt(myShape);
254   for (; aIt.More(); aIt.Next()) {
255     aResParts.Add(aIt.Value());
256   }
257   //
258   Standard_Boolean bChanged = Standard_False;
259   // add parts to result
260   TopTools_ListIteratorOfListOfShape aItLP(aParts);
261   for (; aItLP.More(); aItLP.Next()) {
262     const TopoDS_Shape& aPart = aItLP.Value();
263     // provide uniqueness of the parts 
264     if (aResParts.Add(aPart) && !myShapeMaterial.IsBound(aPart)) {
265       BRep_Builder().Add(myShape, aPart);
266       bChanged = Standard_True;
267     }
268   }
269   //
270   // update the material
271   if (theMaterial != 0) {
272     TopTools_ListOfShape aLSP;
273     aItLP.Initialize(aParts);
274     for (; aItLP.More(); aItLP.Next()) {
275       const TopoDS_Shape& aPart = aItLP.Value();
276       if (!myShapeMaterial.IsBound(aPart)) {
277         myShapeMaterial.Bind(aPart, theMaterial);
278         aLSP.Append(aPart);
279       }
280     } // for (; aIt.More(); aIt.Next()) {
281     //
282     if (aLSP.Extent()) {
283       TopTools_ListOfShape* pLS = myMaterials.ChangeSeek(theMaterial);
284       if (!pLS) {
285         pLS = myMaterials.Bound(theMaterial, TopTools_ListOfShape());
286       }
287       pLS->Append(aLSP);
288     } // if (aLSP.Extent()) {
289   } // if (theMaterial != 0) {
290   //
291   if (!theUpdate) {
292     if (bChanged) {
293       PrepareHistory();
294     }
295   }
296   else {
297     RemoveInternalBoundaries();
298   }
299 }
300
301 //=======================================================================
302 //function : AddAllToResult
303 //purpose  : 
304 //=======================================================================
305 void BOPAlgo_CellsBuilder::AddAllToResult(const Standard_Integer theMaterial,
306                                           const Standard_Boolean theUpdate)
307 {
308   myShapeMaterial.Clear();
309   myMaterials.Clear();
310   myMapModified.Clear();
311   //
312   myShape = myAllParts;
313   //
314   if (theMaterial != 0) {
315     TopTools_ListOfShape* pLSM = myMaterials.Bound(theMaterial, TopTools_ListOfShape());
316     //
317     TopoDS_Iterator aIt(myAllParts);
318     for (; aIt.More(); aIt.Next()) {
319       const TopoDS_Shape& aPart = aIt.Value();
320       myShapeMaterial.Bind(aPart, theMaterial);
321       pLSM->Append(aPart);
322     }
323   }
324   //
325   if (!theUpdate) {
326     PrepareHistory();
327   }
328   else {
329     RemoveInternalBoundaries();
330   }
331 }
332
333 //=======================================================================
334 //function : RemoveFromResult
335 //purpose  : 
336 //=======================================================================
337 void BOPAlgo_CellsBuilder::RemoveFromResult(const TopTools_ListOfShape& theLSToTake,
338                                             const TopTools_ListOfShape& theLSToAvoid)
339 {
340   // find parts
341   TopTools_ListOfShape aParts;
342   FindParts(theLSToTake, theLSToAvoid, aParts);
343   if (aParts.IsEmpty()) {
344     return;
345   }
346   //
347   // collect parts into the map and remove parts from materials
348   TopTools_MapOfShape aPartsToRemove;
349   TopTools_ListIteratorOfListOfShape aItP(aParts);
350   for (; aItP.More(); aItP.Next()) {
351     const TopoDS_Shape& aPart = aItP.Value();
352     aPartsToRemove.Add(aPart);
353     //
354     const Standard_Integer* pMaterial = myShapeMaterial.Seek(aPart);
355     if (pMaterial) {
356       TopTools_ListOfShape* pLSM = myMaterials.ChangeSeek(*pMaterial);
357       if (pLSM) {
358         TopTools_ListIteratorOfListOfShape aItM(*pLSM);
359         for (; aItM.More(); aItM.Next()) {
360           if (aPart.IsSame(aItM.Value())) {
361             pLSM->Remove(aItM);
362             break;
363           }
364         }
365       }
366       myShapeMaterial.UnBind(aPart);
367     }
368   }
369   //
370   BRep_Builder aBB;
371   TopoDS_Compound aResult;
372   aBB.MakeCompound(aResult);
373   Standard_Boolean bChanged = Standard_False;
374   //
375   TopoDS_Iterator aIt(myShape);
376   for (; aIt.More(); aIt.Next()) {
377     const TopoDS_Shape& aS = aIt.Value();
378     TopAbs_ShapeEnum aType = aS.ShapeType();
379     if (aType != TopAbs_WIRE &&
380         aType != TopAbs_SHELL &&
381         aType != TopAbs_COMPSOLID) {
382       // basic element
383       if (aPartsToRemove.Contains(aS)) {
384         bChanged = Standard_True;
385         continue;
386       }
387       aBB.Add(aResult, aS);
388     }
389     else {
390       // container
391       TopoDS_Compound aSC;
392       aBB.MakeCompound(aSC);
393       Standard_Boolean bSCNotEmpty = Standard_False;
394       //
395       TopoDS_Iterator aItSC(aS);
396       for (; aItSC.More(); aItSC.Next()) {
397         const TopoDS_Shape& aSS = aItSC.Value();
398         if (aPartsToRemove.Contains(aSS)) {
399           bChanged = Standard_True;
400           continue;
401         }
402         //
403         bSCNotEmpty = Standard_True;
404         aBB.Add(aSC, aSS);
405       }
406       //
407       if (bSCNotEmpty) {
408         MakeTypedContainers(aSC, aResult);
409       }
410     }
411   }
412   //
413   if (bChanged) {
414     myShape = aResult;
415     //
416     PrepareHistory();
417   }
418 }
419
420 //=======================================================================
421 //function : RemoveAllFromResult
422 //purpose  : 
423 //=======================================================================
424 void BOPAlgo_CellsBuilder::RemoveAllFromResult()
425 {
426   // empty compound
427   TopoDS_Compound aC;
428   BRep_Builder().MakeCompound(aC);
429   myShape = aC;
430   //
431   myMaterials.Clear();
432   myShapeMaterial.Clear();
433   myMapModified.Clear();
434   //
435   PrepareHistory();
436 }
437
438 //=======================================================================
439 //function : RemoveInternalBoundaries
440 //purpose  : 
441 //=======================================================================
442 void BOPAlgo_CellsBuilder::RemoveInternalBoundaries()
443 {
444   if (myMaterials.IsEmpty()) {
445     return;
446   }
447   //
448   BRep_Builder aBB;
449   TopoDS_Compound aResult;
450   aBB.MakeCompound(aResult);
451   //
452   Standard_Boolean bChanged = Standard_False;
453   // try to remove the internal boundaries between the
454   // shapes of the same material
455   TopTools_DataMapIteratorOfDataMapOfIntegerListOfShape aItM(myMaterials);
456   TopTools_ListOfShape aLSUnify[2];
457   TopTools_MapOfShape aKeepMap[2];
458   for (; aItM.More(); aItM.Next()) {
459     Standard_Integer iMaterial = aItM.Key();
460     TopTools_ListOfShape& aLS = aItM.ChangeValue();
461     //
462     if (aLS.IsEmpty()) {
463       continue;
464     }
465     //
466     if (aLS.Extent() == 1) {
467       TopAbs_ShapeEnum aType = aLS.First().ShapeType();
468       if (aType != TopAbs_WIRE &&
469           aType != TopAbs_SHELL &&
470           aType != TopAbs_COMPSOLID) {
471         aBB.Add(aResult, aLS.First());
472         continue;
473       }
474     }
475     //
476     // check the shapes of the same material to be of the same type
477     TopTools_ListIteratorOfListOfShape aItLS(aLS);
478     TopAbs_ShapeEnum aType = aItLS.Value().ShapeType();
479     for (aItLS.Next(); aItLS.More(); aItLS.Next()) {
480       if (aType != aItLS.Value().ShapeType()) {
481         break;
482       }
483     }
484
485     if (aItLS.More())
486     {
487       // add the warning
488       TopoDS_Compound aMultiDimS;
489       aBB.MakeCompound(aMultiDimS);
490       aBB.Add(aMultiDimS, aLS.First());
491       aBB.Add(aMultiDimS, aItLS.Value());
492       AddWarning(new BOPAlgo_AlertRemovalOfIBForMDimShapes(aMultiDimS));
493     }
494     else
495     {
496       if (aType == TopAbs_EDGE || aType == TopAbs_FACE)
497       {
498         // for edges and faces, just collect shapes to unify them later after exiting the loop;
499         // collect boundaries of shapes of current material in the keep map
500         Standard_Integer iType = (aType == TopAbs_EDGE ? 0 : 1);
501         CollectMaterialBoundaries(aLS, aKeepMap[iType]);
502         // save shapes to unify later
503         TopTools_ListOfShape aCopy(aLS);
504         aLSUnify[iType].Append(aCopy);
505         continue;
506       }
507       else
508       {
509         // aType is Solid;
510         // remove internal faces between solids of the same material just now
511         TopTools_ListOfShape aLSNew;
512         if (RemoveInternals(aLS, aLSNew))
513         {
514           bChanged = Standard_True;
515           // update materials maps
516           for (aItLS.Initialize(aLSNew); aItLS.More(); aItLS.Next()) {
517             const TopoDS_Shape& aS = aItLS.Value();
518             myShapeMaterial.Bind(aS, iMaterial);
519           }
520           aLS.Assign(aLSNew);
521         }
522       }
523     }
524     // add shapes to result (multidimensional and solids)
525     for (aItLS.Initialize(aLS); aItLS.More(); aItLS.Next()) {
526       const TopoDS_Shape& aS = aItLS.Value();
527       aBB.Add(aResult, aS);
528     }
529   }
530
531   // remove internal boundaries for edges and faces
532   for (Standard_Integer iType = 0; iType < 2; ++iType)
533   {
534     if (aLSUnify[iType].IsEmpty())
535       continue;
536     TopTools_ListOfShape aLSN;
537     if (RemoveInternals(aLSUnify[iType], aLSN, aKeepMap[iType]))
538       bChanged = Standard_True;
539     // add shapes to result ([unified] edges or faces)
540     for (TopTools_ListIteratorOfListOfShape aItLS(aLSN); aItLS.More(); aItLS.Next()) {
541       const TopoDS_Shape& aS = aItLS.Value();
542       aBB.Add(aResult, aS);
543     }
544   }
545   //
546   if (bChanged) {
547     // add shapes without material into result
548     TopoDS_Iterator aIt(myShape);
549     for (; aIt.More(); aIt.Next()) {
550       const TopoDS_Shape& aS = aIt.Value();
551       //
552       if (myShapeMaterial.IsBound(aS)) {
553         continue;
554       }
555       //
556       // check if it is not a collection
557       TopAbs_ShapeEnum aType = aS.ShapeType();
558       if (aType != TopAbs_WIRE &&
559           aType != TopAbs_SHELL &&
560           aType != TopAbs_COMPSOLID) {
561         aBB.Add(aResult, aS);
562       }
563       else {
564         TopoDS_Compound aSC;
565         aBB.MakeCompound(aSC);
566         Standard_Boolean bSCEmpty(Standard_True), bSCChanged(Standard_False);
567         //
568         TopoDS_Iterator aItSC(aS);
569         for (; aItSC.More(); aItSC.Next()) {
570           const TopoDS_Shape& aSS = aItSC.Value();
571           if (!myShapeMaterial.IsBound(aSS)) {
572             aBB.Add(aSC, aSS);
573             bSCEmpty = Standard_False;
574           }
575           else {
576             bSCChanged = Standard_True;
577           }
578         }
579         //
580         if (bSCEmpty) {
581           continue;
582         }
583         //
584         if (bSCChanged) {
585           MakeTypedContainers(aSC, aResult);
586         }
587         else {
588           aBB.Add(aResult, aS);
589         }
590       }
591     }
592     //
593     myShape = aResult;
594     //
595     PrepareHistory();
596   }
597 }
598
599 //=======================================================================
600 //function : FindPart
601 //purpose  : 
602 //=======================================================================
603 void BOPAlgo_CellsBuilder::FindParts(const TopTools_ListOfShape& theLSToTake,
604                                      const TopTools_ListOfShape& theLSToAvoid,
605                                      TopTools_ListOfShape& theParts)
606 {
607   if (theLSToTake.IsEmpty()) {
608     return;
609   }
610   //
611   // map shapes to avoid
612   TopTools_MapOfShape aMSToAvoid;
613   TopTools_ListIteratorOfListOfShape aItArgs(theLSToAvoid);
614   for (; aItArgs.More(); aItArgs.Next()) {
615     const TopoDS_Shape& aS = aItArgs.Value();
616     aMSToAvoid.Add(aS);
617   }
618   //
619   // map shapes to be taken
620   TopTools_MapOfShape aMSToTake;
621   aItArgs.Initialize(theLSToTake);
622   for (; aItArgs.More(); aItArgs.Next()) {
623     const TopoDS_Shape& aS = aItArgs.Value();
624     aMSToTake.Add(aS);
625   }
626   //
627   Standard_Integer aNbS = aMSToTake.Extent();
628   //
629   // among the shapes to be taken into result, find any one
630   // of minimal dimension
631   Standard_Integer iDimMin = 10;
632   TopoDS_Shape aSMin;
633   //
634   aItArgs.Initialize(theLSToTake);
635   for (; aItArgs.More(); aItArgs.Next()) {
636     const TopoDS_Shape& aS = aItArgs.Value();
637     Standard_Integer iDim = BOPTools_AlgoTools::Dimension(aS);
638     if (iDim < iDimMin) {
639       iDimMin = iDim;
640       aSMin = aS;
641     }
642   }
643   //
644   // among the split parts of the shape of minimal dimension
645   // look for the parts to be taken into result
646   TopAbs_ShapeEnum aType = TypeToExplore(iDimMin);
647   TopExp_Explorer aExp(aSMin, aType);
648   for (; aExp.More(); aExp.Next()) {
649     const TopoDS_Shape& aST = aExp.Current();
650     // get split parts of the shape
651     TopTools_ListOfShape aLSTIm;
652     if (!myImages.IsBound(aST)) {
653       aLSTIm.Append(aST);
654     } else {
655       aLSTIm = myImages.Find(aST);
656     }
657     //
658     TopTools_ListIteratorOfListOfShape aItIm(aLSTIm);
659     for (; aItIm.More(); aItIm.Next()) {
660       const TopoDS_Shape& aPart = aItIm.Value();
661       //
662       if (!myIndex.Contains(aPart)) {
663         continue;
664       }
665       //
666       // get input shapes in which the split part is contained
667       const TopTools_ListOfShape& aLS = myIndex.FindFromKey(aPart);
668       if (aLS.Extent() < aNbS) {
669         continue;
670       }
671       //
672       // check that input shapes containing the part should not be avoided
673       TopTools_MapOfShape aMS;
674       aItArgs.Initialize(aLS);
675       for (; aItArgs.More(); aItArgs.Next()) {
676         const TopoDS_Shape& aS = aItArgs.Value();
677         aMS.Add(aS);
678         if (aMSToAvoid.Contains(aS)) {
679           break;
680         }
681       }
682       //
683       if (aItArgs.More()) {
684         continue;
685       }
686       //
687       // check that all shapes which should be taken contain the part
688       aItArgs.Initialize(theLSToTake);
689       for (; aItArgs.More(); aItArgs.Next()) {
690         if (!aMS.Contains(aItArgs.Value())) {
691           break;
692         }
693       }
694       //
695       if (!aItArgs.More()) {
696         theParts.Append(aPart);
697       }
698     }
699   }
700 }
701
702 //=======================================================================
703 //function : MakeContainers
704 //purpose  : 
705 //=======================================================================
706 void BOPAlgo_CellsBuilder::MakeContainers()
707 {
708   BRep_Builder aBB;
709   TopoDS_Compound aResult;
710   aBB.MakeCompound(aResult);
711   //
712   // basic elements of type EDGE, FACE and SOLID added into result
713   TopTools_ListOfShape aLS[3];
714   //
715   TopoDS_Iterator aIt(myShape);
716   for (; aIt.More(); aIt.Next()) {
717     const TopoDS_Shape& aS = aIt.Value();
718     //
719     Standard_Integer iDim = BOPTools_AlgoTools::Dimension(aS);
720     if (iDim <= 0) {
721       aBB.Add(aResult, aS);
722       continue;
723     }
724     //
725     aLS[iDim-1].Append(aS);
726   }
727   //
728   for (Standard_Integer i = 0; i < 3; ++i) {
729     if (aLS[i].IsEmpty()) {
730       continue;
731     }
732     //
733     TopoDS_Compound aC;
734     aBB.MakeCompound(aC);
735     TopTools_ListIteratorOfListOfShape aItLS(aLS[i]);
736     for (; aItLS.More(); aItLS.Next()) {
737       aBB.Add(aC, aItLS.Value());
738     }
739     //
740     MakeTypedContainers(aC, aResult);
741   }
742   myShape = aResult;
743 }
744
745 //=======================================================================
746 //function : RemoveInternals
747 //purpose  : 
748 //=======================================================================
749 Standard_Boolean BOPAlgo_CellsBuilder::RemoveInternals(const TopTools_ListOfShape& theLS,
750                                                        TopTools_ListOfShape& theLSNew,
751                                                        const TopTools_MapOfShape& theMapKeepBnd)
752 {
753   Standard_Boolean bRemoved = Standard_False;
754   if (theLS.Extent() < 2) {
755     theLSNew = theLS;
756     return bRemoved;
757   }
758   //
759   TopAbs_ShapeEnum aType = theLS.First().ShapeType();
760   //
761   if (aType == TopAbs_EDGE ||
762       aType == TopAbs_FACE) {
763     //
764     // make container
765     BRep_Builder aBB;
766     TopoDS_Shape aShape;
767     //
768     BOPTools_AlgoTools::MakeContainer
769       ((aType == TopAbs_FACE) ? TopAbs_SHELL : TopAbs_WIRE, aShape);
770     //
771     for (TopTools_ListIteratorOfListOfShape aIt(theLS); aIt.More(); aIt.Next()) {
772       const TopoDS_Shape& aS = aIt.Value();
773       aBB.Add(aShape, aS);
774     }
775     //
776     // Unify same domain
777     Standard_Boolean bFaces, bEdges;
778     //
779     bFaces = (aType == TopAbs_FACE);
780     bEdges = (aType == TopAbs_EDGE);
781     ShapeUpgrade_UnifySameDomain anUnify (aShape, bEdges, bFaces);
782     anUnify.KeepShapes(theMapKeepBnd);
783     anUnify.Build();
784     const TopoDS_Shape& aSNew = anUnify.Shape();
785     //
786     TopExp_Explorer aExp(aSNew, aType);
787     for (; aExp.More(); aExp.Next()) {
788       const TopoDS_Shape& aSn = aExp.Current();
789       theLSNew.Append(aSn);
790     }
791     //
792     if (theLSNew.IsEmpty()) {
793       // add the warning
794       if (bFaces)
795         AddWarning (new BOPAlgo_AlertRemovalOfIBForFacesFailed (aShape));
796       else
797         AddWarning (new BOPAlgo_AlertRemovalOfIBForEdgesFailed (aShape));
798       //
799       theLSNew.Assign(theLS);
800       return bRemoved;
801     }
802     //
803     // fill map of modified shapes
804     TopTools_IndexedMapOfShape aMG;
805     Standard_Integer i, aNb;
806     //
807     TopExp::MapShapes(aShape, TopAbs_VERTEX, aMG);
808     TopExp::MapShapes(aShape, TopAbs_EDGE,   aMG);
809     TopExp::MapShapes(aShape, TopAbs_FACE,   aMG);
810     //
811     aNb = aMG.Extent();
812     for (i = 1; i <= aNb; ++i) {
813       const TopoDS_Shape& aSS = aMG(i);
814       const Standard_Integer* pMaterial = myShapeMaterial.Seek(aSS);
815       const TopTools_ListOfShape& aLSMod = anUnify.History()->Modified(aSS);
816       TopTools_ListIteratorOfListOfShape aIt(aLSMod);
817       for (; aIt.More(); aIt.Next()) {
818         const TopoDS_Shape& aSU = aIt.Value();
819         myMapModified.Bind(aSS, aSU);
820         bRemoved = Standard_True;
821         if (pMaterial && !myShapeMaterial.IsBound(aSU))
822           myShapeMaterial.Bind(aSU, *pMaterial);
823       }
824     }
825   }
826   else if (aType == TopAbs_SOLID) {
827     BRep_Builder aBB;
828     TopoDS_Compound aSolids;
829     aBB.MakeCompound(aSolids);
830     //
831     TopTools_ListIteratorOfListOfShape aItLS(theLS);
832     for (; aItLS.More(); aItLS.Next()) {
833       const TopoDS_Shape& aSol = aItLS.Value();
834       aBB.Add(aSolids, aSol);
835     }
836     //
837     // Make connexity blocks of solids to create from each isolated block one solid.
838     // It will allow attaching internal entities of the solids to new solid.
839     TopTools_ListOfShape aLCB;
840     BOPTools_AlgoTools::MakeConnexityBlocks(aSolids, TopAbs_FACE, TopAbs_SOLID, aLCB);
841     //
842     // for each block remove internal faces
843     TopTools_ListIteratorOfListOfShape aItLCB(aLCB);
844     for (; aItLCB.More(); aItLCB.Next()) {
845       const TopoDS_Shape& aCB = aItLCB.Value();
846       //
847       // Map faces and solids to find boundary faces that can be removed
848       TopTools_IndexedDataMapOfShapeListOfShape aDMFS;
849       // internal entities
850       TopTools_ListOfShape aLSInt;
851       //
852       TopoDS_Iterator aItS(aCB);
853       for (; aItS.More(); aItS.Next()) {
854         const TopoDS_Shape& aSol = aItS.Value();
855         //
856         TopoDS_Iterator aItIS(aSol);
857         for (; aItIS.More(); aItIS.Next()) {
858           const TopoDS_Shape& aSI = aItIS.Value();
859           if (aSI.Orientation() == TopAbs_INTERNAL) {
860             aLSInt.Append(aSI);
861           }
862           else {
863             TopoDS_Iterator aItF(aSI);
864             for (; aItF.More(); aItF.Next()) {
865               const TopoDS_Shape& aF = aItF.Value();
866               TopTools_ListOfShape *pLSols = aDMFS.ChangeSeek(aF);
867               if (!pLSols) {
868                 pLSols = &aDMFS(aDMFS.Add(aF, TopTools_ListOfShape()));
869               }
870               pLSols->Append(aSol);
871             }
872           }
873         }
874       }
875       //
876       // to build unified solid, select only faces attached to only one solid
877       TopTools_ListOfShape aLFUnique;
878       Standard_Integer i, aNb = aDMFS.Extent();
879       for (i = 1; i <= aNb; ++i) {
880         if (aDMFS(i).Extent() == 1) {
881           aLFUnique.Append(aDMFS.FindKey(i));
882         }
883       }
884       //
885       if (aNb == aLFUnique.Extent()) {
886         // no faces to remove
887         aItS.Initialize(aCB);
888         for (; aItS.More(); aItS.Next()) {
889           theLSNew.Append(aItS.Value());
890         }
891         continue;
892       }
893       //
894       // build new solid
895       BOPAlgo_BuilderSolid aBS;
896       aBS.SetShapes(aLFUnique);
897       aBS.Perform();
898       //
899       if (aBS.HasErrors() || aBS.Areas().Extent() != 1) {
900         // add the warning
901         {
902           TopoDS_Compound aUniqeFaces;
903           aBB.MakeCompound(aUniqeFaces);
904           TopTools_ListIteratorOfListOfShape aItLFUniqe(aLFUnique);
905           for (; aItLFUniqe.More(); aItLFUniqe.Next()) {
906             aBB.Add(aUniqeFaces, aItLFUniqe.Value());
907           }
908           //
909           AddWarning (new BOPAlgo_AlertRemovalOfIBForSolidsFailed (aUniqeFaces));
910         }
911         //
912         aItS.Initialize(aCB);
913         for (; aItS.More(); aItS.Next()) {
914           theLSNew.Append(aItS.Value());
915         }
916         continue;
917       }
918       //
919       myReport->Merge(aBS.GetReport());
920       //
921       TopoDS_Solid& aSNew = *(TopoDS_Solid*)&aBS.Areas().First();
922       //
923       // put all internal parts into new solid
924       aSNew.Free(Standard_True);
925       TopTools_ListIteratorOfListOfShape aItLSI(aLSInt);
926       for (; aItLSI.More(); aItLSI.Next()) {
927         aBB.Add(aSNew, aItLSI.Value());
928       }
929       aSNew.Free(Standard_False);
930       //
931       theLSNew.Append(aSNew);
932       bRemoved = Standard_True;
933
934       // Save information about the fuse of the solids into a history map
935       aItS.Initialize(aCB);
936       for (; aItS.More(); aItS.Next())
937         myMapModified.Bind(aItS.Value(), aSNew);
938     }
939   }
940   return bRemoved;
941 }
942
943 //=======================================================================
944 //function : LocModified
945 //purpose  : 
946 //=======================================================================
947 const TopTools_ListOfShape* BOPAlgo_CellsBuilder::LocModified(const TopoDS_Shape& theS)
948 {
949   // Get shape's modification coming from GF operation
950   const TopTools_ListOfShape* pLSp = BOPAlgo_Builder::LocModified(theS);
951   if (myMapModified.IsEmpty())
952     // No local modifications
953     return pLSp;
954
955   myHistShapes.Clear();
956
957   // Check if the shape (or its splits) has participated in unification
958   if (!pLSp)
959   {
960     // No splits from GF operation.
961     // Check if the shape has been unified with other shapes
962     const TopoDS_Shape* pSU = myMapModified.Seek(theS);
963     if (!pSU)
964       return NULL;
965
966     myHistShapes.Append(*pSU);
967   }
968   else
969   {
970     TopTools_MapOfShape aMFence;
971     // Process all GF splits and check them for local unification with other shapes
972     TopTools_ListIteratorOfListOfShape aIt(*pLSp);
973     for (; aIt.More(); aIt.Next())
974     {
975       const TopoDS_Shape* pSp = &aIt.Value();
976       const TopoDS_Shape* pSU = myMapModified.Seek(*pSp);
977       if (pSU) pSp = pSU;
978       if (aMFence.Add(*pSp))
979         myHistShapes.Append(*pSp);
980     }
981   }
982   return &myHistShapes;
983 }
984
985 //=======================================================================
986 //function : MakeTypedContainers
987 //purpose  : 
988 //=======================================================================
989 void MakeTypedContainers(const TopoDS_Shape& theSC,
990                          TopoDS_Shape& theResult)
991 {
992   TopAbs_ShapeEnum aContainerType, aConnexityType, aPartType;
993   //
994   aPartType = TypeToExplore(BOPTools_AlgoTools::Dimension(theSC));
995   switch (aPartType) {
996     case TopAbs_EDGE: {
997       aContainerType = TopAbs_WIRE;
998       aConnexityType = TopAbs_VERTEX;
999       break;
1000     }
1001     case TopAbs_FACE: {
1002       aContainerType = TopAbs_SHELL;
1003       aConnexityType = TopAbs_EDGE;
1004       break;
1005     }
1006     case TopAbs_SOLID: {
1007       aContainerType = TopAbs_COMPSOLID;
1008       aConnexityType = TopAbs_FACE;
1009       break;
1010     }
1011     default:
1012       return;
1013   }
1014   //
1015   TopTools_ListOfShape aLCB;
1016   BOPTools_AlgoTools::MakeConnexityBlocks(theSC, aConnexityType, aPartType, aLCB);
1017   if (aLCB.IsEmpty()) {
1018     return;
1019   }
1020   //
1021   BRep_Builder aBB;
1022   TopExp_Explorer aExp;
1023   TopTools_ListIteratorOfListOfShape aItCB;
1024   //
1025   aItCB.Initialize(aLCB);
1026   for (; aItCB.More(); aItCB.Next()) {
1027     TopoDS_Shape aRCB;
1028     BOPTools_AlgoTools::MakeContainer(aContainerType, aRCB);
1029     //
1030     const TopoDS_Shape& aCB = aItCB.Value();
1031     aExp.Init(aCB, aPartType);
1032     for (; aExp.More(); aExp.Next()) {
1033       const TopoDS_Shape& aCBS = aExp.Current();
1034       aBB.Add(aRCB, aCBS);
1035     }
1036     //
1037     if (aContainerType == TopAbs_SHELL) {
1038       BOPTools_AlgoTools::OrientFacesOnShell(aRCB);
1039     }
1040     //
1041     aBB.Add(theResult, aRCB);
1042   }
1043 }
1044
1045 //=======================================================================
1046 //function : CollectMaterialBoundaries
1047 //purpose  : Add to theMapKeepBnd the boundary shapes of the area defined by shapes from the list
1048 //=======================================================================
1049 static void CollectMaterialBoundaries(const TopTools_ListOfShape& theLS,
1050                                       TopTools_MapOfShape& theMapKeepBnd)
1051 {
1052   TopAbs_ShapeEnum aType = theLS.First().ShapeType();
1053   TopAbs_ShapeEnum aTypeSubsh = (aType == TopAbs_FACE ? TopAbs_EDGE : TopAbs_VERTEX);
1054   TopTools_IndexedDataMapOfShapeListOfShape aMapSubSh;
1055   TopTools_ListIteratorOfListOfShape anIt(theLS);
1056   for (; anIt.More(); anIt.Next())
1057   {
1058     const TopoDS_Shape& aS = anIt.Value();
1059     TopExp::MapShapesAndAncestors(aS, aTypeSubsh, aType, aMapSubSh);
1060   }
1061   for (int i = 1; i <= aMapSubSh.Extent(); i++)
1062   {
1063     // check if the subshape belongs to boundary of the area
1064     if (aMapSubSh(i).Extent() == 1)
1065     {
1066       // add to theMapKeepBnd
1067       theMapKeepBnd.Add(aMapSubSh.FindKey(i));
1068     }
1069   }
1070 }
1071
1072 //=======================================================================
1073 //function : TypeToExplore
1074 //purpose  : 
1075 //=======================================================================
1076 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim)
1077 {
1078   TopAbs_ShapeEnum aRet;
1079   //
1080   switch(theDim) {
1081   case 0:
1082     aRet=TopAbs_VERTEX;
1083     break;
1084   case 1:
1085     aRet=TopAbs_EDGE;
1086     break;
1087   case 2:
1088     aRet=TopAbs_FACE;
1089     break;
1090   case 3:
1091     aRet=TopAbs_SOLID;
1092     break;
1093   default:
1094     aRet=TopAbs_SHAPE;
1095     break;
1096   }
1097   return aRet;
1098 }