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