5c13a2193c842a63574afcc22c6396ab7c1a96a1
[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 <TopoDS_Compound.hxx>
19
20 #include <BRep_Builder.hxx>
21
22 #include <TopExp_Explorer.hxx>
23
24 #include <BOPTools.hxx>
25 #include <BOPTools_AlgoTools.hxx>
26
27 #include <BOPAlgo_BuilderSolid.hxx>
28
29 #include <ShapeUpgrade_UnifySameDomain.hxx>
30
31
32 static
33   TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim);
34
35 static
36   void MakeTypedContainers(const TopoDS_Shape& theSC,
37                            const TopAbs_ShapeEnum aType,
38                            TopoDS_Shape& theResult);
39
40 //=======================================================================
41 //function : empty constructor
42 //purpose  : 
43 //=======================================================================
44 BOPAlgo_CellsBuilder::BOPAlgo_CellsBuilder()
45 :
46   BOPAlgo_Builder(),
47   myType(TopAbs_SHAPE),
48   myIndex(100, myAllocator),
49   myMaterials(100, myAllocator),
50   myShapeMaterial(100, myAllocator),
51   myMapGenerated(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   myType(TopAbs_SHAPE),
64   myIndex(100, myAllocator),
65   myMaterials(100, myAllocator),
66   myShapeMaterial(100, myAllocator),
67   myMapGenerated(100, myAllocator)
68 {
69 }
70
71 //=======================================================================
72 //function : ~
73 //purpose  : 
74 //=======================================================================
75 BOPAlgo_CellsBuilder::~BOPAlgo_CellsBuilder()
76 {
77   Clear();
78 }
79
80
81 //=======================================================================
82 //function : Clear
83 //purpose  : 
84 //=======================================================================
85 void BOPAlgo_CellsBuilder::Clear()
86 {
87   BOPAlgo_Builder::Clear();
88   myIndex.Clear();
89   myMaterials.Clear();
90   myShapeMaterial.Clear();
91   myMapGenerated.Clear();
92 }
93
94 //=======================================================================
95 //function : GetAllParts
96 //purpose  : 
97 //=======================================================================
98 const TopoDS_Shape& BOPAlgo_CellsBuilder::GetAllParts() const
99 {
100   return myAllParts;
101 }
102
103 //=======================================================================
104 //function : Prepare
105 //purpose  : 
106 //=======================================================================
107 void BOPAlgo_CellsBuilder::Prepare()
108 {
109   BOPAlgo_Builder::Prepare();
110   //
111   myFlagHistory=Standard_False;
112 }
113
114 //=======================================================================
115 // function: CheckData
116 // purpose: 
117 //=======================================================================
118 void BOPAlgo_CellsBuilder::CheckData()
119 {
120   BOPAlgo_Builder::CheckData();
121   if (myErrorStatus) {
122     return;
123   }
124   //
125   // additional check for the arguments to be of the same dimension.
126   Standard_Integer aDim1, aDimi;
127   BOPCol_ListIteratorOfListOfShape aIt;
128   //
129   aIt.Initialize(myArguments);
130   const TopoDS_Shape& aS1 = aIt.Value();
131   aDim1 = BOPTools_AlgoTools::Dimension(aS1);
132   //
133   for (aIt.Next(); aIt.More(); aIt.Next()) {
134     const TopoDS_Shape& aSi = aIt.Value();
135     aDimi = BOPTools_AlgoTools::Dimension(aSi);
136     //
137     if (aDim1 != aDimi) {
138       myErrorStatus = 201; // non-homogenous arguments
139       break;
140     }
141   }
142 }
143
144 //=======================================================================
145 //function : PerformInternal1
146 //purpose  : 
147 //=======================================================================
148 void BOPAlgo_CellsBuilder::PerformInternal1(const BOPAlgo_PaveFiller& theFiller)
149 {
150   BOPAlgo_Builder::PerformInternal1(theFiller);
151   //
152   if (myErrorStatus) {
153     return;
154   }
155   //
156   // save the splits to <myAllParts>
157   TakeAllParts();
158   //
159   // index all the parts to its origins
160   IndexParts();
161   //
162   // and nullify <myShape> for building the result;
163   RemoveAllFromResult();
164   //
165   myFlagHistory = Standard_True;
166 }
167
168 //=======================================================================
169 //function : TakeAllParts
170 //purpose  : 
171 //=======================================================================
172 void BOPAlgo_CellsBuilder::TakeAllParts()
173 {
174   Standard_Integer aDim;
175   TopoDS_Compound aC;
176   BRep_Builder aBB;
177   //
178   aDim = BOPTools_AlgoTools::Dimension(myArguments.First());
179   myType = TypeToExplore(aDim);
180   //
181   aBB.MakeCompound(aC);
182   TopExp_Explorer aExp(myShape, myType);
183   for (; aExp.More(); aExp.Next()) {
184     const TopoDS_Shape& aS = aExp.Current();
185     aBB.Add(aC, aS);
186   }
187   myAllParts = aC;
188 }
189
190 //=======================================================================
191 //function : IndexParts
192 //purpose  : 
193 //=======================================================================
194 void BOPAlgo_CellsBuilder::IndexParts()
195 {
196   BOPCol_ListIteratorOfListOfShape aIt, aItIm;
197   TopExp_Explorer aExp;
198   //
199   aIt.Initialize(myArguments);
200   for (; aIt.More(); aIt.Next()) {
201     const TopoDS_Shape& aS = aIt.Value();
202     //
203     aExp.Init(aS, myType);
204     for (; aExp.More(); aExp.Next()) {
205       const TopoDS_Shape& aST = aExp.Current();
206       if (!myImages.IsBound(aST)) {
207         BOPCol_ListOfShape aLS;
208         aLS.Append(aS);
209         myIndex.Add(aST, aLS);
210         continue;
211       }
212       //
213       const BOPCol_ListOfShape& aLSIm = myImages.Find(aST);
214       aItIm.Initialize(aLSIm);
215       for (; aItIm.More(); aItIm.Next()) {
216         const TopoDS_Shape& aSTIm = aItIm.Value();
217         //
218         if (myIndex.Contains(aSTIm)) {
219           BOPCol_ListOfShape& aLS = myIndex.ChangeFromKey(aSTIm);
220           aLS.Append(aS);
221         }
222         else {
223           BOPCol_ListOfShape aLS;
224           aLS.Append(aS);
225           myIndex.Add(aSTIm, aLS);
226         }
227       } // for (; aItIm.More(); aItIm.Next()) {
228     } // for (; aExp.More(); aExp.Next()) {
229   } // for (; aIt.More(); aIt.Next()) {
230 }
231
232 //=======================================================================
233 //function : AddToResult
234 //purpose  : 
235 //=======================================================================
236 void BOPAlgo_CellsBuilder::AddToResult(const BOPCol_ListOfShape& theLSToTake,
237                                        const BOPCol_ListOfShape& theLSToAvoid,
238                                        const Standard_Integer theMaterial,
239                                        const Standard_Boolean theUpdate)
240 {
241   // find parts
242   BOPCol_ListOfShape aParts;
243   FindParts(theLSToTake, theLSToAvoid, aParts);
244   if (aParts.IsEmpty()) {
245     return;
246   }
247   //
248   Standard_Boolean bChanged;
249   BRep_Builder aBB;
250   BOPCol_MapOfShape aResParts;
251   TopExp_Explorer aExp;
252   BOPCol_ListIteratorOfListOfShape aIt;
253   //
254   bChanged = Standard_False;
255   // collect result parts to avoid multiple adding of the same parts
256   aExp.Init(myShape, myType);
257   for (; aExp.More(); aExp.Next()) {
258     const TopoDS_Shape& aPart = aExp.Current();
259     aResParts.Add(aPart);
260   }
261   // add parts to result 
262   aIt.Initialize(aParts);
263   for (; aIt.More(); aIt.Next()) {
264     const TopoDS_Shape& aPart = aIt.Value();
265     if (aResParts.Add(aPart)) {
266       aBB.Add(myShape, aPart);
267       bChanged = Standard_True;
268     }
269   }
270   //
271   // update the material
272   if (theMaterial != 0) {
273     BOPCol_ListOfShape aLSP;
274     aIt.Initialize(aParts);
275     for (; aIt.More(); aIt.Next()) {
276       const TopoDS_Shape& aPart = aIt.Value();
277       if (!myShapeMaterial.IsBound(aPart)) {
278         myShapeMaterial.Bind(aPart, theMaterial);
279         aLSP.Append(aPart);
280       }
281     } // for (; aIt.More(); aIt.Next()) {
282     //
283     if (aLSP.Extent()) {
284       if (myMaterials.IsBound(theMaterial)) {
285         BOPCol_ListOfShape& aLS = myMaterials.ChangeFind(theMaterial);
286         aLS.Append(aLSP);
287       } // if (myMaterials.IsBound(theMaterial)) {
288       else {
289         myMaterials.Bind(theMaterial, aLSP);
290       }
291     } // if (aLSP.Extent()) {
292   } // if (theMaterial != 0) {
293   //
294   if (!theUpdate) {
295     if (bChanged) {
296       PrepareHistory();
297     }
298   }
299   else {
300     RemoveInternalBoundaries();
301   }
302 }
303
304 //=======================================================================
305 //function : AddAllToResult
306 //purpose  : 
307 //=======================================================================
308 void BOPAlgo_CellsBuilder::AddAllToResult(const Standard_Integer theMaterial,
309                                           const Standard_Boolean theUpdate)
310 {
311   TopoDS_Compound aResult;
312   BRep_Builder aBB;
313   BOPCol_ListOfShape aLSM;
314   //
315   aBB.MakeCompound(aResult);
316   myShapeMaterial.Clear();
317   myMaterials.Clear();
318   myMapGenerated.Clear();
319   //
320   TopoDS_Iterator aIt(myAllParts);
321   for (; aIt.More(); aIt.Next()) {
322     const TopoDS_Shape& aPart = aIt.Value();
323     aBB.Add(aResult, aPart);
324     //
325     if (theMaterial != 0) {
326       myShapeMaterial.Bind(aPart, theMaterial);
327       aLSM.Append(aPart);
328     }
329   }
330   //
331   myShape = aResult;
332   //
333   if (theMaterial != 0) {
334     myMaterials.Bind(theMaterial, aLSM);
335   }
336   //
337   if (!theUpdate) {
338     PrepareHistory();
339   }
340   else {
341     RemoveInternalBoundaries();
342   }
343 }
344
345 //=======================================================================
346 //function : RemoveFromResult
347 //purpose  : 
348 //=======================================================================
349 void BOPAlgo_CellsBuilder::RemoveFromResult(const BOPCol_ListOfShape& theLSToTake,
350                                             const BOPCol_ListOfShape& theLSToAvoid)
351 {
352   // find parts
353   BOPCol_ListOfShape aParts;
354   FindParts(theLSToTake, theLSToAvoid, aParts);
355   if (aParts.IsEmpty()) {
356     return;
357   }
358   //
359   BOPCol_MapOfShape aPartsToRemove;
360   BOPCol_ListIteratorOfListOfShape aItP, aItM;
361   //
362   // collect parts into the map and remove parts from materials
363   aItP.Initialize(aParts);
364   for (; aItP.More(); aItP.Next()) {
365     const TopoDS_Shape& aPart = aItP.Value();
366     aPartsToRemove.Add(aPart);
367     //
368     if (myShapeMaterial.IsBound(aPart)) {
369       Standard_Integer iMaterial = myShapeMaterial.Find(aPart);
370       if (!myMaterials.IsBound(iMaterial)) {
371         myShapeMaterial.UnBind(aPart);
372         continue;
373       }
374       //
375       BOPCol_ListOfShape& aLSM = myMaterials.ChangeFind(iMaterial);
376       //
377       aItM.Initialize(aLSM);
378       for (; aItM.More(); aItM.Next()) {
379         const TopoDS_Shape& aSM = aItM.Value();
380         if (aSM.IsSame(aPart)) {
381           aLSM.Remove(aItM);
382           break;
383         } // if (aSM.IsSame(aPart)) {
384       } // for (; aItM.More(); aItM.Next()) {
385       //
386       myShapeMaterial.UnBind(aPart);
387     } // if (myShapeMaterial.IsBound(aPart)) {
388   } // for (; aItP.More(); aItP.Next()) {
389   //
390   Standard_Boolean bChanged;
391   TopoDS_Compound aResult;
392   BRep_Builder aBB;
393   TopoDS_Iterator aIt1, aIt2;
394   TopAbs_ShapeEnum aType;
395   //
396   aBB.MakeCompound(aResult);
397   bChanged = Standard_False;
398   //
399   aIt1.Initialize(myShape);
400   for (; aIt1.More(); aIt1.Next()) {
401     const TopoDS_Shape& aS = aIt1.Value();
402     aType = aS.ShapeType();
403     //
404     if (aType == myType) {
405       // basic element
406       if (aPartsToRemove.Contains(aS)) {
407         bChanged = Standard_True;
408         continue;
409       }
410       aBB.Add(aResult, aS);
411     } // if (aType == myType) {
412     else {
413       // container
414       Standard_Boolean bNotEmpty;
415       TopoDS_Compound aSC;
416       aBB.MakeCompound(aSC);
417       //
418       bNotEmpty = Standard_False;
419       aIt2.Initialize(aS);
420       for (; aIt2.More(); aIt2.Next()) {
421         const TopoDS_Shape& aSS = aIt2.Value();
422         if (aPartsToRemove.Contains(aSS)) {
423           bChanged = Standard_True;
424           continue;
425         }
426         aBB.Add(aSC, aSS);
427         bNotEmpty = Standard_True;
428       } // for (; aIt2.More(); aIt2.Next()) {
429       //
430       if (bNotEmpty) {
431         MakeTypedContainers(aSC, myType, aResult);
432       }
433     } // else {
434   } // for (; aIt1.More(); aIt1.Next()) {
435   //
436   if (bChanged) {
437     myShape = aResult;
438     //
439     PrepareHistory();
440   }
441 }
442
443 //=======================================================================
444 //function : RemoveAllFromResult
445 //purpose  : 
446 //=======================================================================
447 void BOPAlgo_CellsBuilder::RemoveAllFromResult()
448 {
449   // empty compound
450   TopoDS_Compound aC;
451   BRep_Builder aBB;
452   //
453   aBB.MakeCompound(aC);
454   myShape = aC;
455   //
456   myMaterials.Clear();
457   myShapeMaterial.Clear();
458   myMapGenerated.Clear();
459   //
460   PrepareHistory();
461 }
462
463 //=======================================================================
464 //function : RemoveInternalBoundaries
465 //purpose  : 
466 //=======================================================================
467 void BOPAlgo_CellsBuilder::RemoveInternalBoundaries()
468 {
469   if (myMaterials.IsEmpty()) {
470     return;
471   }
472   //
473   Standard_Integer iMaterial, iErr;
474   TopoDS_Compound aResult;
475   BRep_Builder aBB;
476   TopExp_Explorer aExp;
477   BOPCol_ListIteratorOfListOfShape aItS;
478   BOPCol_DataMapIteratorOfDataMapOfIntegerListOfShape aItM;
479   //
480   aBB.MakeCompound(aResult);
481   aExp.Init(myShape, myType);
482   for (; aExp.More(); aExp.Next()) {
483     const TopoDS_Shape& aS = aExp.Current();
484     if (!myShapeMaterial.IsBound(aS)) {
485       aBB.Add(aResult, aS);
486     }
487   }
488   //
489   aItM.Initialize(myMaterials);
490   for (; aItM.More(); aItM.Next()) {
491     iMaterial = aItM.Key();
492     //
493     BOPCol_ListOfShape aLSNew;
494     BOPCol_ListOfShape& aLS = myMaterials(iMaterial);
495     iErr = RemoveInternals(aLS, aLSNew);
496     if (iErr || aLSNew.IsEmpty()) {
497       myErrorStatus = 202; // unable to remove internal boundaries
498       return;
499     }
500     //
501     // update materials maps and add new shapes to result
502     aLS.Assign(aLSNew);
503     aItS.Initialize(aLSNew);
504     for (; aItS.More(); aItS.Next()) {
505       const TopoDS_Shape& aS = aItS.Value();
506       aBB.Add(aResult, aS);
507       if (!myShapeMaterial.IsBound(aS)) {
508         myShapeMaterial.Bind(aS, iMaterial);
509       }
510     }
511   }
512   //
513   myShape = aResult;
514   //
515   PrepareHistory();
516 }
517
518 //=======================================================================
519 //function : FindPart
520 //purpose  : 
521 //=======================================================================
522 void BOPAlgo_CellsBuilder::FindParts(const BOPCol_ListOfShape& theLSToTake,
523                                      const BOPCol_ListOfShape& theLSToAvoid,
524                                      BOPCol_ListOfShape& theParts)
525 {
526   if (theLSToTake.IsEmpty()) {
527     return;
528   }
529   //
530   Standard_Boolean bFound;
531   Standard_Integer aNbS;
532   BOPCol_ListIteratorOfListOfShape aItIm, aItArgs;
533   BOPCol_MapOfShape aMSToTake, aMSToAvoid, aMS;
534   TopExp_Explorer aExp;
535   //
536   aItArgs.Initialize(theLSToAvoid);
537   for (; aItArgs.More(); aItArgs.Next()) {
538     const TopoDS_Shape& aS = aItArgs.Value();
539     aMSToAvoid.Add(aS);
540   }
541   //
542   aItArgs.Initialize(theLSToTake);
543   for (; aItArgs.More(); aItArgs.Next()) {
544     const TopoDS_Shape& aS = aItArgs.Value();
545     aMSToTake.Add(aS);
546   }
547   //
548   aNbS = aMSToTake.Extent();
549   //
550   const TopoDS_Shape& aSToTake = theLSToTake.First();
551   aExp.Init(aSToTake, myType);
552   for (; aExp.More(); aExp.Next()) {
553     const TopoDS_Shape& aST = aExp.Current();
554     BOPCol_ListOfShape aLSTIm;
555     if (!myImages.IsBound(aST)) {
556       aLSTIm.Append(aST);
557     } else {
558       aLSTIm = myImages.Find(aST);
559     }
560     //
561     aItIm.Initialize(aLSTIm);
562     for (; aItIm.More(); aItIm.Next()) {
563       const TopoDS_Shape& aPart = aItIm.Value();
564       //
565       if (!myIndex.Contains(aPart)) {
566         continue;
567       }
568       //
569       const BOPCol_ListOfShape& aLS = myIndex.FindFromKey(aPart);
570       if (aLS.Extent() < aNbS) {
571         continue;
572       }
573       //
574       aMS.Clear();
575       aItArgs.Initialize(aLS);
576       for (bFound = Standard_True; aItArgs.More() && bFound; aItArgs.Next()) {
577         const TopoDS_Shape& aS = aItArgs.Value();
578         bFound = !aMSToAvoid.Contains(aS);
579         aMS.Add(aS);
580       }
581       //
582       if (!bFound) {
583         continue;
584       }
585       //
586       aItArgs.Initialize(theLSToTake);
587       for (; aItArgs.More() && bFound; aItArgs.Next()) {
588         const TopoDS_Shape& aS = aItArgs.Value();
589         bFound = aMS.Contains(aS);
590       }
591       //
592       if (bFound) {
593         theParts.Append(aPart);
594       } // if (bFound) {
595     } // for (; aItIm.More(); aItIm.Next()) {
596   } // for (; aExp.More(); aExp.Next()) {
597 }
598
599 //=======================================================================
600 //function : MakeContainers
601 //purpose  : 
602 //=======================================================================
603 void BOPAlgo_CellsBuilder::MakeContainers()
604 {
605   TopoDS_Compound aResult;
606   BRep_Builder aBB;
607   //
608   aBB.MakeCompound(aResult);
609   MakeTypedContainers(myShape, myType, aResult);
610   myShape = aResult;
611 }
612
613 //=======================================================================
614 //function : RemoveInternals
615 //purpose  : 
616 //=======================================================================
617 Standard_Integer BOPAlgo_CellsBuilder::RemoveInternals(const BOPCol_ListOfShape& theLS,
618                                                        BOPCol_ListOfShape& theLSNew)
619 {
620   Standard_Integer iErr = 0;
621   if (theLS.Extent() < 2) {
622     theLSNew = theLS;
623     return iErr;
624   }
625   //
626   BOPCol_ListIteratorOfListOfShape aIt;
627   TopExp_Explorer aExp;
628   //
629   TopAbs_ShapeEnum aType = theLS.First().ShapeType();
630   //
631   if (aType == TopAbs_EDGE ||
632       aType == TopAbs_FACE) {
633     //
634     // make container
635     BRep_Builder aBB;
636     TopoDS_Shape aShape;
637     //
638     BOPTools_AlgoTools::MakeContainer
639       ((aType == TopAbs_FACE) ? TopAbs_SHELL : TopAbs_WIRE, aShape);
640     //
641     aIt.Initialize(theLS);
642     for (; aIt.More(); aIt.Next()) {
643       const TopoDS_Shape& aS = aIt.Value();
644       aBB.Add(aShape, aS);
645     }
646     //
647     // Unify same domain
648     Standard_Boolean bFaces, bEdges;
649     //
650     bFaces = (aType == TopAbs_FACE);
651     bEdges = (aType == TopAbs_EDGE);
652     //
653     ShapeUpgrade_UnifySameDomain anUnify (aShape, bEdges, bFaces);
654     anUnify.Build();
655     const TopoDS_Shape& aSNew = anUnify.Shape();
656     //
657     aExp.Init(aSNew, aType);
658     for (; aExp.More(); aExp.Next()) {
659       const TopoDS_Shape& aSn = aExp.Current();
660       theLSNew.Append(aSn);
661     }
662     //
663     // fill map of generated shapes
664     BOPCol_IndexedMapOfShape aMG;
665     Standard_Integer i, aNb;
666     //
667     BOPTools::MapShapes(aShape, TopAbs_VERTEX, aMG);
668     BOPTools::MapShapes(aShape, TopAbs_EDGE,   aMG);
669     BOPTools::MapShapes(aShape, TopAbs_FACE,   aMG);
670     //
671     aNb = aMG.Extent();
672     for (i = 1; i <= aNb; ++i) {
673       const TopoDS_Shape& aSS = aMG(i);
674       const TopoDS_Shape& aSNew = anUnify.Generated(aSS);
675       if (!aSNew.IsNull() && !aSS.IsSame(aSNew)) {
676         myMapGenerated.Bind(aSS, aSNew);
677       }
678     }
679   }
680   else if (aType == TopAbs_SOLID) {
681     // build all solids from the faces
682     BOPCol_ListOfShape aLSF;
683     //
684     aIt.Initialize(theLS);
685     for (; aIt.More(); aIt.Next()) {
686       const TopoDS_Shape& aS = aIt.Value();
687       //
688       aExp.Init(aS, TopAbs_FACE);
689       for (; aExp.More(); aExp.Next()) {
690         const TopoDS_Shape& aF = aExp.Current();
691         aLSF.Append(aF);
692       }
693     }
694     //
695     BOPAlgo_BuilderSolid aBS;
696     aBS.SetShapes(aLSF);
697     aBS.Perform();
698     //
699     iErr = aBS.ErrorStatus();
700     if (iErr) {
701       return iErr;
702     }
703     //
704     theLSNew = aBS.Areas();
705     if (theLSNew.Extent() == 1) {
706       return iErr;
707     }
708     //
709     // result is a list of solids. we need to select external faces.
710     BOPCol_IndexedDataMapOfShapeListOfShape aDMFS;
711     BOPCol_ListOfShape aLFNew;
712     Standard_Integer i, aNb;
713     //
714     // map faces and solids
715     BOPCol_ListIteratorOfListOfShape aIt(theLSNew);
716     for (; aIt.More(); aIt.Next()) {
717       const TopoDS_Shape& aS = aIt.Value();
718       //
719       aExp.Init(aS, TopAbs_FACE);
720       for (; aExp.More(); aExp.Next()) {
721         const TopoDS_Shape& aF = aExp.Current();
722         if (aDMFS.Contains(aF)) {
723           BOPCol_ListOfShape& aLFS = aDMFS.ChangeFromKey(aF);
724           aLFS.Append(aS);
725         }
726         else {
727           BOPCol_ListOfShape aLFS;
728           aLFS.Append(aS);
729           aDMFS.Add(aF, aLFS);
730         }
731       }
732     }
733     //
734     // select faces attached to only one solid
735     aNb = aDMFS.Extent();
736     for (i = 1; i <= aNb; ++i) {
737       const BOPCol_ListOfShape& aLS = aDMFS(i);
738       if (aLS.Extent() == 1) {
739         const TopoDS_Shape& aF = aDMFS.FindKey(i);
740         aLFNew.Append(aF);
741       }
742     }
743     //
744     if (aNb == aLFNew.Extent()) {
745       return iErr;
746     }
747     //
748     // build new solid
749     BOPAlgo_BuilderSolid aBS1;
750     aBS1.SetShapes(aLFNew);
751     aBS1.Perform();
752     //
753     iErr = aBS1.ErrorStatus();
754     if (iErr) {
755       return iErr;
756     }
757     //
758     theLSNew = aBS1.Areas();
759   }
760   //
761   return iErr;
762 }
763
764 //=======================================================================
765 //function : IsDeleted
766 //purpose  : 
767 //=======================================================================
768 Standard_Boolean BOPAlgo_CellsBuilder::IsDeleted(const TopoDS_Shape& theS)
769 {
770   Standard_Boolean bRet = Standard_True;
771   if (theS.IsNull()) {
772     return bRet;
773   }
774   //
775   TopAbs_ShapeEnum aType = theS.ShapeType();
776   if (!(aType==TopAbs_EDGE || aType==TopAbs_FACE || 
777       aType==TopAbs_VERTEX || aType==TopAbs_SOLID)) {
778     return bRet;
779   }
780   //
781   Standard_Boolean bHasImage, bHasGenerated;
782   //
783   bHasImage = myImages.IsBound(theS);
784   bHasGenerated = myMapGenerated.IsBound(theS);
785   if (!bHasImage && !bHasGenerated) {
786     bRet = !myMapShape.Contains(theS);
787     return bRet;
788   }
789   //
790   if (bHasGenerated) {
791     const TopoDS_Shape& aSG = myMapGenerated.Find(theS);
792     if (myMapShape.Contains(aSG)) {
793       bRet = Standard_False;
794       return bRet;
795     }
796   }
797   //
798   if (bHasImage) {
799     const BOPCol_ListOfShape& aLSp = myImages.Find(theS);
800     BOPCol_ListIteratorOfListOfShape aIt(aLSp);
801     for (; aIt.More(); aIt.Next()) {
802       const TopoDS_Shape& aSp = aIt.Value();
803       const TopoDS_Shape& aSpR = myShapesSD.IsBound(aSp) ? 
804         myShapesSD.Find(aSp) : aSp;
805       //
806       const TopoDS_Shape& aSpRG = myMapGenerated.IsBound(aSpR) ?
807         myMapGenerated.Find(aSpR) : aSpR;
808       if (myMapShape.Contains(aSpRG)) {
809         bRet = Standard_False;
810         break;
811       }
812     }
813   }
814   //
815   return bRet;
816 }
817
818 //=======================================================================
819 //function : Generated
820 //purpose  : 
821 //=======================================================================
822 const TopTools_ListOfShape& BOPAlgo_CellsBuilder::Generated(const TopoDS_Shape& theS)
823 {
824   myHistShapes.Clear();
825   if (theS.IsNull()) {
826     return myHistShapes;
827   }
828   //
829   TopAbs_ShapeEnum aType = theS.ShapeType();
830   if (!(aType==TopAbs_EDGE || aType==TopAbs_FACE || aType==TopAbs_VERTEX)) {
831     return myHistShapes;
832   }
833   //
834   Standard_Boolean bHasGenerated = myMapGenerated.IsBound(theS);
835   if (bHasGenerated) {
836     const TopoDS_Shape& aSG = myMapGenerated.Find(theS);
837     if (myMapShape.Contains(aSG)) {
838       myHistShapes.Append(aSG);
839     }
840     return myHistShapes;
841   }
842   //
843   Standard_Boolean bHasImage = myImages.IsBound(theS);
844   if (!bHasImage) {
845     return myHistShapes;
846   }
847   //
848   BOPCol_MapOfShape aMFence;
849   const BOPCol_ListOfShape& aLSp = myImages.Find(theS);
850   BOPCol_ListIteratorOfListOfShape aIt(aLSp);
851   for (; aIt.More(); aIt.Next()) {
852     const TopoDS_Shape aSp = aIt.Value();
853     const TopoDS_Shape& aSpR = myShapesSD.IsBound(aSp) ? 
854       myShapesSD.Find(aSp) : aSp;
855     //
856     if (myMapGenerated.IsBound(aSpR)) {
857       const TopoDS_Shape& aSG = myMapGenerated.Find(aSpR);
858       if (myMapShape.Contains(aSG)) {
859         if (aMFence.Add(aSG)) {
860           myHistShapes.Append(aSG);
861         }
862       }
863     }
864   }
865   //
866   return myHistShapes;
867 }
868
869 //=======================================================================
870 //function : MakeTypedContainers
871 //purpose  : 
872 //=======================================================================
873 void MakeTypedContainers(const TopoDS_Shape& theSC,
874                          const TopAbs_ShapeEnum aType,
875                          TopoDS_Shape& theResult)
876 {
877   TopAbs_ShapeEnum aContainerType, aConnexityType, aPartType;
878   //
879   aPartType = aType;
880   switch (aPartType) {
881     case TopAbs_EDGE: {
882       aContainerType = TopAbs_WIRE;
883       aConnexityType = TopAbs_VERTEX;
884       break;
885     }
886     case TopAbs_FACE: {
887       aContainerType = TopAbs_SHELL;
888       aConnexityType = TopAbs_EDGE;
889       break;
890     }
891     case TopAbs_SOLID: {
892       aContainerType = TopAbs_COMPSOLID;
893       aConnexityType = TopAbs_FACE;
894       break;
895     }
896     default:
897       return;
898   }
899   //
900   BOPCol_ListOfShape aLCB;
901   BOPTools_AlgoTools::MakeConnexityBlocks(theSC, aConnexityType, aPartType, aLCB);
902   if (aLCB.IsEmpty()) {
903     return;
904   }
905   //
906   BRep_Builder aBB;
907   TopExp_Explorer aExp;
908   BOPCol_ListIteratorOfListOfShape aItCB;
909   //
910   aItCB.Initialize(aLCB);
911   for (; aItCB.More(); aItCB.Next()) {
912     TopoDS_Shape aRCB;
913     BOPTools_AlgoTools::MakeContainer(aContainerType, aRCB);
914     //
915     const TopoDS_Shape& aCB = aItCB.Value();
916     aExp.Init(aCB, aPartType);
917     for (; aExp.More(); aExp.Next()) {
918       const TopoDS_Shape& aCBS = aExp.Current();
919       aBB.Add(aRCB, aCBS);
920     }
921     //
922     if (aContainerType == TopAbs_SHELL) {
923       BOPTools_AlgoTools::OrientFacesOnShell(aRCB);
924     }
925     //
926     aBB.Add(theResult, aRCB);
927   }
928 }
929
930 //=======================================================================
931 //function : TypeToExplore
932 //purpose  : 
933 //=======================================================================
934 TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim)
935 {
936   TopAbs_ShapeEnum aRet;
937   //
938   switch(theDim) {
939   case 0:
940     aRet=TopAbs_VERTEX;
941     break;
942   case 1:
943     aRet=TopAbs_EDGE;
944     break;
945   case 2:
946     aRet=TopAbs_FACE;
947     break;
948   case 3:
949     aRet=TopAbs_SOLID;
950     break;
951   default:
952     aRet=TopAbs_SHAPE;
953     break;
954   }
955   return aRet;
956 }