0025788: Parallelization of the BOP Builder algorithm on second level
[occt.git] / src / BOPAlgo / BOPAlgo_ShellSplitter.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 // File: BOPAlgo_ShellSplitter.cxx
16 // Created: Thu Jan 16 08:33:50 2014
17
18 #include <BOPAlgo_ShellSplitter.ixx>
19 //
20 #include <TopoDS_Shape.hxx>
21 #include <TopoDS_Shell.hxx>
22 #include <TopoDS_Edge.hxx>
23
24 #include <BRep_Builder.hxx>
25 #include <TopExp_Explorer.hxx>
26 //
27 #include <BOPCol_Parallel.hxx>
28 #include <BOPCol_IndexedMapOfShape.hxx>
29 #include <BOPCol_MapOfShape.hxx>
30 #include <BOPCol_MapOfOrientedShape.hxx>
31 #include <BOPCol_NCVector.hxx>
32 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
33 //
34 #include <IntTools_Context.hxx>
35 //
36 #include <BOPTools.hxx>
37 #include <BOPTools_AlgoTools.hxx>
38 #include <BOPTools_CoupleOfShape.hxx>
39
40 //
41 static
42   void MakeShell(const BOPCol_ListOfShape& , 
43                  TopoDS_Shell& );
44 //
45 static
46   void RefineShell(TopoDS_Shell& theShell);
47 //
48 static
49   void MapEdgesAndFaces
50   (const TopoDS_Shape& aF,
51    BOPCol_IndexedDataMapOfShapeListOfShape& aMEF,
52    const Handle(NCollection_BaseAllocator)& theAllocator);
53
54 //=======================================================================
55 //class    : BOPAlgo_CBK
56 //purpose  : 
57 //=======================================================================
58 class BOPAlgo_CBK {
59  public:
60   BOPAlgo_CBK() : 
61     myPCB (NULL) {
62   }
63   //
64   ~BOPAlgo_CBK() {
65   }
66   //
67   void SetConnexityBlock (const BOPTools_ConnexityBlock& aCB) {
68     myPCB=(BOPTools_ConnexityBlock*)&aCB;
69   }
70   //
71   BOPTools_ConnexityBlock& ConnexityBlock () {
72     return *myPCB;
73   }
74   //
75   void Perform() {
76     BOPAlgo_ShellSplitter::SplitBlock(*myPCB);
77   }
78  protected:
79   BOPTools_ConnexityBlock *myPCB;
80 };
81 //=======================================================================
82 typedef BOPCol_NCVector
83   <BOPAlgo_CBK> BOPAlgo_VectorOfCBK; 
84 //
85 typedef BOPCol_Functor 
86   <BOPAlgo_CBK,
87   BOPAlgo_VectorOfCBK> BOPAlgo_CBKFunctor;
88 //
89 typedef BOPCol_Cnt 
90   <BOPAlgo_CBKFunctor,
91   BOPAlgo_VectorOfCBK> BOPAlgo_CBKCnt;
92 //
93 //=======================================================================
94 //function : 
95 //purpose  : 
96 //=======================================================================
97 BOPAlgo_ShellSplitter::BOPAlgo_ShellSplitter()
98 :
99   BOPAlgo_Algo(),
100   myStartShapes(myAllocator),
101   myShells(myAllocator),
102   myLCB(myAllocator)
103 {
104 }
105 //=======================================================================
106 //function : 
107 //purpose  : 
108 //=======================================================================
109 BOPAlgo_ShellSplitter::BOPAlgo_ShellSplitter
110   (const Handle(NCollection_BaseAllocator)& theAllocator)
111 :
112   BOPAlgo_Algo(theAllocator),
113   myStartShapes(theAllocator),
114   myShells(theAllocator),
115   myLCB(myAllocator)
116 {
117 }
118 //=======================================================================
119 //function : ~
120 //purpose  : 
121 //=======================================================================
122 BOPAlgo_ShellSplitter::~BOPAlgo_ShellSplitter()
123 {
124 }
125 //=======================================================================
126 //function : AddStartElement
127 //purpose  : 
128 //=======================================================================
129 void BOPAlgo_ShellSplitter::AddStartElement(const TopoDS_Shape& aE)
130 {
131   myStartShapes.Append(aE);
132 }
133 //=======================================================================
134 //function : StartElements
135 //purpose  : 
136 //=======================================================================
137 const BOPCol_ListOfShape& BOPAlgo_ShellSplitter::StartElements()const
138 {
139   return myStartShapes;
140 }
141 //=======================================================================
142 //function : Loops
143 //purpose  : 
144 //=======================================================================
145 const BOPCol_ListOfShape& BOPAlgo_ShellSplitter::Shells()const
146 {
147   return myShells;
148 }
149 //=======================================================================
150 //function : Perform
151 //purpose  : 
152 //=======================================================================
153 void BOPAlgo_ShellSplitter::Perform()
154 {
155   myErrorStatus=0;
156   //
157   MakeConnexityBlocks();
158   if (myErrorStatus) {
159     return;
160   }
161   //
162   MakeShells();
163 }
164 //=======================================================================
165 //function : MakeConnexityBlocks
166 //purpose  : 
167 //=======================================================================
168 void BOPAlgo_ShellSplitter::MakeConnexityBlocks()
169 {
170   Standard_Boolean bRegular;
171   Standard_Integer i, j, aNbE, aNbES, aNbEP, k, aNbCB;
172   TopoDS_Shape aFR;
173   TopoDS_Iterator aItF, aItW;
174   BOPCol_IndexedDataMapOfShapeListOfShape aMEF(100, myAllocator);
175   BOPCol_IndexedMapOfShape aMEP(100, myAllocator);
176   BOPCol_IndexedMapOfShape aMFC(100, myAllocator);
177   BOPCol_MapOfShape aMER(100, myAllocator);
178   BOPCol_MapOfShape aMFP(100, myAllocator);
179   BOPCol_IndexedMapOfShape aMEAdd(100, myAllocator);
180   BOPCol_MapOfShape aMES(100, myAllocator);
181   BOPCol_ListIteratorOfListOfShape aIt;
182   //
183   myErrorStatus=0;
184   //
185   myLCB.Clear();
186   //
187   const BOPCol_ListOfShape& aLSE=myStartShapes;
188   aIt.Initialize(aLSE);
189   for (i=1; aIt.More(); aIt.Next(), ++i) {
190     const TopoDS_Shape& aSE=aIt.Value();
191     if (!aMEP.Contains(aSE)) {
192       aMEP.Add(aSE);
193       MapEdgesAndFaces(aSE, aMEF, myAllocator);
194     }
195     else {
196       aMER.Add(aSE);
197     }
198   }
199   //
200   // 2
201   aNbE=aMEF.Extent();
202   for (i=1; i<=aNbE; ++i) {
203     aNbES=aMES.Extent();
204     if (aNbES==aNbE) {
205       break;
206     }
207     //
208     const TopoDS_Shape& aE=aMEF.FindKey(i);
209     //
210     if (!aMES.Add(aE)) {
211       continue;
212     }
213     // aMES - globally processed edges
214     //
215     //------------------------------------- goal: aMEC
216     aMFC.Clear();    // aMEC - edges of CB
217     aMEP.Clear();    // aMVP - edges to process right now 
218     aMEAdd.Clear();  // aMVAdd edges to process on next step of for(;;) {
219     //
220     aMEP.Add(aE);
221     //
222     for(;;) {
223       aNbEP=aMEP.Extent();
224       for (k=1; k<=aNbEP; ++k) {
225         const TopoDS_Shape& aEP=aMEP(k);
226         const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aEP);
227         aIt.Initialize(aLF);
228         for (; aIt.More(); aIt.Next()) {
229           const TopoDS_Shape& aF=aIt.Value();
230           if (aMFC.Add(aF)) {
231             aItF.Initialize(aF);
232             while (aItF.More()) {
233               const TopoDS_Shape& aW=aItF.Value();  
234               if (aW.ShapeType()!=TopAbs_WIRE) {
235                 aItF.Next();
236                 continue;
237               }
238               //
239               aItW.Initialize(aW);
240               while (aItW.More()) {
241                 const TopoDS_Shape& aEF=aItW.Value();  
242                 //
243                 if (aMES.Add(aEF)) {
244                   aMEAdd.Add(aEF);
245                 }
246                 //
247                 aItW.Next();
248               }
249               //
250               aItF.Next();
251             }
252           }
253         }
254       }
255       //
256       aNbEP=aMEAdd.Extent();
257       if (!aNbEP) {
258         break; // from for(;;) {
259       }
260       //
261       aMEP.Clear();
262       //
263       for (k=1; k<=aNbEP; ++k) {
264         const TopoDS_Shape& aEF=aMEAdd(k);
265         aMEP.Add(aEF);
266       }
267       aMEAdd.Clear();
268     }// for(;;) {
269     //
270     //-------------------------------------
271     BOPTools_ConnexityBlock aCB(myAllocator);
272     //
273     BOPCol_ListOfShape& aLECB=aCB.ChangeShapes();
274     BOPCol_IndexedDataMapOfShapeListOfShape aMEFR(100, myAllocator);
275     //
276     bRegular=Standard_True;
277     aNbCB = aMFC.Extent();
278     for (j=1; j<=aNbCB; ++j) {
279       aFR = aMFC(j);
280       //
281       if (aMER.Contains(aFR)) {
282         aFR.Orientation(TopAbs_FORWARD);
283         aLECB.Append(aFR);
284         aFR.Orientation(TopAbs_REVERSED);
285         aLECB.Append(aFR);
286         bRegular=Standard_False;
287       }
288       else {
289         aLECB.Append(aFR);
290       }
291       //
292       if (bRegular) {
293         MapEdgesAndFaces(aFR, aMEFR, myAllocator);
294       }
295     }
296     //
297     if (bRegular) {
298       Standard_Integer aNbER, aNbFR; 
299       //
300       aNbER=aMEFR.Extent();
301       for (k=1; k<=aNbER; ++k) {
302         const BOPCol_ListOfShape& aLFR=aMEFR(k);
303         aNbFR=aLFR.Extent();
304         if (aNbFR>2) {
305           bRegular=!bRegular;
306           break;
307         }
308       }
309     }
310     //
311     aCB.SetRegular(bRegular);
312     myLCB.Append(aCB);
313   }
314 }
315 //=======================================================================
316 //function : SplitBlock
317 //purpose  : 
318 //=======================================================================
319 void BOPAlgo_ShellSplitter::SplitBlock(BOPTools_ConnexityBlock& aCB)
320 {
321   Standard_Integer aNbLF, aNbOff, aNbFP;
322   Standard_Integer i;
323   TopAbs_Orientation anOr;
324   TopoDS_Edge aEL;
325   BRep_Builder aBB;
326   TopoDS_Iterator aItS;
327   TopExp_Explorer aExp;
328   BOPCol_ListIteratorOfListOfShape aItF;
329   BOPTools_CoupleOfShape aCSOff;
330   BOPCol_MapOfOrientedShape AddedFacesMap;
331   BOPCol_IndexedDataMapOfShapeListOfShape aEFMap, aMEFP;
332   // 
333   Handle (IntTools_Context) aContext=new IntTools_Context;
334   //
335   const BOPCol_ListOfShape& myShapes=aCB.Shapes();
336   //
337   BOPCol_ListOfShape& myLoops=aCB.ChangeLoops();
338   myLoops.Clear();
339   //
340   // 1. Shells Usual
341   aItF.Initialize (myShapes);
342   for (; aItF.More(); aItF.Next()) {
343     const TopoDS_Shape& aFF = aItF.Value();
344     BOPTools::MapShapesAndAncestors (aFF, 
345                                      TopAbs_EDGE, 
346                                      TopAbs_FACE, 
347                                      aEFMap);
348   }
349   //
350   aItF.Initialize (myShapes);
351   for (i=1; aItF.More(); aItF.Next(), ++i) {
352     const TopoDS_Shape& aFF = aItF.Value();
353     if (!AddedFacesMap.Add(aFF)) {
354       continue;
355     }
356     //
357     // make a new shell
358     TopoDS_Shell aShell;
359     aBB.MakeShell(aShell);
360     aBB.Add(aShell, aFF);
361     //
362     aMEFP.Clear();
363     BOPTools::MapShapesAndAncestors(aFF, 
364                                     TopAbs_EDGE, 
365                                     TopAbs_FACE, 
366                                     aMEFP);
367     //
368     // loop on faces added to Shell; 
369     // add their neighbor faces to Shell and so on
370     aItS.Initialize (aShell);
371     for (; aItS.More(); aItS.Next()) {
372       const TopoDS_Face& aF = (*(TopoDS_Face*)(&aItS.Value()));
373       //
374       // loop on edges of aF; find a good neighbor face of aF by aE
375       aExp.Init(aF, TopAbs_EDGE);
376       for (; aExp.More(); aExp.Next()) {
377         const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
378         //
379         //1
380         if (aMEFP.Contains(aE)) {
381           const BOPCol_ListOfShape& aLFP=aMEFP.FindFromKey(aE);
382           aNbFP=aLFP.Extent();
383           if (aNbFP>1) { 
384             continue;
385           }
386         }
387         //2
388         anOr=aE.Orientation();
389         if (anOr==TopAbs_INTERNAL) {
390           continue;
391         }
392         //3
393         if (BRep_Tool::Degenerated(aE)) {
394           continue;
395         }
396         //
397         // candidate faces list
398         const BOPCol_ListOfShape& aLF=aEFMap.FindFromKey(aE);
399         aNbLF=aLF.Extent();
400         if (!aNbLF) {
401           continue;
402         }
403         //
404         // try to select one of neighbors
405         // check if a face already added to Shell shares E
406         Standard_Boolean bFound;
407         BOPCol_ListIteratorOfListOfShape aItLF;
408         BOPTools_ListOfCoupleOfShape aLCSOff;
409         //
410         aItLF.Initialize(aLF);
411         for (; aItLF.More(); aItLF.Next()) { 
412           const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItLF.Value()));
413           if (aF.IsSame(aFL)) {
414             continue;
415           } 
416           if (AddedFacesMap.Contains(aFL)){
417             continue;
418           }
419           //
420           bFound=BOPTools_AlgoTools::GetEdgeOff(aE, aFL, aEL);
421           if (!bFound) {
422             continue;
423           }
424           //
425           aCSOff.SetShape1(aEL);
426           aCSOff.SetShape2(aFL);
427           aLCSOff.Append(aCSOff);
428         }//for (; aItLF.More(); aItLF.Next()) { 
429         //
430         aNbOff=aLCSOff.Extent();
431         if (!aNbOff){
432           continue;
433         }
434         //
435         TopoDS_Face aSelF;
436         if (aNbOff==1) {
437           aSelF=(*(TopoDS_Face*)(&aLCSOff.First().Shape2()));
438         }
439         else if (aNbOff>1){
440           BOPTools_AlgoTools::GetFaceOff(aE, 
441                                          aF, 
442                                          aLCSOff, 
443                                          aSelF, 
444                                          aContext);
445         }
446         //
447         if (!aSelF.IsNull() && AddedFacesMap.Add(aSelF)) { 
448           aBB.Add(aShell, aSelF);
449           BOPTools::MapShapesAndAncestors(aSelF, 
450                                           TopAbs_EDGE, 
451                                           TopAbs_FACE, 
452                                           aMEFP);
453         }
454       } // for (; aExp.More(); aExp.Next()) {
455     } // for (; aItS.More(); aItS.Next()) {
456     //
457     if (BRep_Tool::IsClosed(aShell)) {
458       aShell.Closed (Standard_True);
459       myLoops.Append(aShell);
460     }
461     else {
462       RefineShell(aShell);
463       if (BRep_Tool::IsClosed(aShell)) {
464         aShell.Closed (Standard_True);
465         myLoops.Append(aShell);
466       }
467     }
468   } // for (; aItF.More(); aItF.Next()) {
469 }
470 //=======================================================================
471 //function : RefineShell
472 //purpose  : 
473 //=======================================================================
474 void RefineShell(TopoDS_Shell& theShell)
475 {
476   TopoDS_Iterator aIt;
477   //
478   aIt.Initialize(theShell);
479   if(!aIt.More()) {
480     return;
481   }
482   //
483   Standard_Integer i, aNbMEF, aNbF;
484   BOPCol_IndexedDataMapOfShapeListOfShape aMEF; 
485   TopoDS_Builder aBB;
486   TopExp_Explorer aExp;
487   BOPCol_MapOfShape aMEStop, aMFB;
488   BOPCol_MapIteratorOfMapOfShape aItM;
489   BOPCol_ListIteratorOfListOfShape aItLF, aItLFP;
490   BOPCol_ListOfShape aLFP, aLFP1;
491   //
492   // Branch points
493   BOPTools::MapShapesAndAncestors (theShell, 
494                                    TopAbs_EDGE, 
495                                    TopAbs_FACE, 
496                                    aMEF);
497   aNbMEF=aMEF.Extent();
498   for (i=1; i<=aNbMEF; ++i) {
499     const TopoDS_Shape& aE=aMEF.FindKey(i);
500     const BOPCol_ListOfShape& aLF=aMEF.FindFromIndex(i);
501     aNbF=aLF.Extent();
502     if (aNbF>2) {
503       aMEStop.Add(aE);
504     }
505   }
506   //
507   if (aMEStop.IsEmpty()) {
508     return;
509   }
510   //
511   // The first Face 
512   const TopoDS_Shape& aF1=aIt.Value();
513   aMFB.Add(aF1);
514   aLFP.Append(aF1);
515   //
516   // Trying to reach the branch point
517   for (;;)  {
518     aItLFP.Initialize(aLFP);
519     for (; aItLFP.More(); aItLFP.Next()) { 
520       const TopoDS_Shape& aFP=aItLFP.Value();
521       //
522       aExp.Init(aFP, TopAbs_EDGE);
523       for (; aExp.More(); aExp.Next()) {
524         const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
525         if (aMEStop.Contains(aE)) {
526           continue;
527         }
528         //
529         if (BRep_Tool::Degenerated(aE)) {
530           continue;
531         }
532         //
533         const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE);
534         //
535         aItLF.Initialize(aLF);
536         for (; aItLF.More(); aItLF.Next()) { 
537           const TopoDS_Shape& aFP1=aItLF.Value();
538           if (aFP1.IsSame(aFP)) {
539             continue;
540           }
541           if (aMFB.Contains(aFP1)) {
542             continue;
543           }
544           aMFB.Add(aFP1);
545           aLFP1.Append(aFP1);
546         }// for (; aItLF.More(); aItLF.Next()) { 
547       }// for (; aExp.More(); aExp.Next()) {
548     }// for (; aItLFP.More(); aItLFP.Next()) { 
549     //
550     //
551     if (aLFP1.IsEmpty()) {
552       break;
553     }
554     //
555     aLFP.Clear();
556     aItLF.Initialize(aLFP1);
557     for (; aItLF.More(); aItLF.Next()) { 
558       const TopoDS_Shape& aFP1=aItLF.Value();
559       aLFP.Append(aFP1);
560     }
561     aLFP1.Clear();
562   }// for (;;)  {
563   //
564   // Remove all faces before the branch point
565   aItM.Initialize(aMFB);
566   for (; aItM.More(); aItM.Next()) { 
567     const TopoDS_Shape& aFB=aItM.Value();
568     aBB.Remove(theShell, aFB);
569   }
570 }
571 //=======================================================================
572 //function : MakeShells
573 //purpose  : 
574 //=======================================================================
575 void BOPAlgo_ShellSplitter::MakeShells()
576 {
577   Standard_Boolean bIsRegular;
578   Standard_Integer aNbVCBK, k;
579   BOPTools_ListIteratorOfListOfConnexityBlock aItCB;
580   BOPCol_ListIteratorOfListOfShape aIt;
581   BOPAlgo_VectorOfCBK aVCBK;
582   //
583   myErrorStatus=0;
584   myShells.Clear();
585   //
586   aItCB.Initialize(myLCB);
587   for (; aItCB.More(); aItCB.Next()) {
588     BOPTools_ConnexityBlock& aCB=aItCB.ChangeValue();
589     bIsRegular=aCB.IsRegular();
590     if (bIsRegular) {
591       TopoDS_Shell aShell;
592       //
593       const BOPCol_ListOfShape& aLF=aCB.Shapes();
594       MakeShell(aLF, aShell);
595       aShell.Closed(Standard_True);
596       myShells.Append(aShell);
597     }
598     else {
599       BOPAlgo_CBK& aCBK=aVCBK.Append1();
600       aCBK.SetConnexityBlock(aCB);
601     }
602   }
603   //
604   aNbVCBK=aVCBK.Extent();
605   //===================================================
606   BOPAlgo_CBKCnt::Perform(myRunParallel, aVCBK);
607   //===================================================
608   for (k=0; k<aNbVCBK; ++k) {
609     BOPAlgo_CBK& aCBK=aVCBK(k);
610     const BOPTools_ConnexityBlock& aCB=aCBK.ConnexityBlock();
611     const BOPCol_ListOfShape& aLS=aCB.Loops();
612     aIt.Initialize(aLS);
613     for (; aIt.More(); aIt.Next()) {
614       TopoDS_Shape& aShell=aIt.ChangeValue();
615       aShell.Closed(Standard_True);
616       myShells.Append(aShell);
617     }
618   }
619 }
620 //=======================================================================
621 //function : MakeShell
622 //purpose  : 
623 //=======================================================================
624 void MakeShell(const BOPCol_ListOfShape& aLS, 
625                TopoDS_Shell& aShell)
626 {
627   BRep_Builder aBB;
628   BOPCol_ListIteratorOfListOfShape aIt;
629   //
630   aBB.MakeShell(aShell);
631   //
632   aIt.Initialize(aLS);
633   for (; aIt.More(); aIt.Next()) {
634     const TopoDS_Shape& aF=aIt.Value();
635     aBB.Add(aShell, aF);
636   }
637 }
638 //=======================================================================
639 // function: MapEdgesAndFaces
640 // purpose: 
641 //=======================================================================
642 void MapEdgesAndFaces
643   (const TopoDS_Shape& aF,
644    BOPCol_IndexedDataMapOfShapeListOfShape& aMEF,
645    const Handle(NCollection_BaseAllocator)& theAllocator)
646 {
647   TopoDS_Iterator aItF, aItW;
648   //
649   aItF.Initialize(aF);
650   while (aItF.More()) {
651     const TopoDS_Shape& aW=aItF.Value();  
652     if (aW.ShapeType()!=TopAbs_WIRE) {
653       aItF.Next();
654       continue;
655     }
656     //
657     aItW.Initialize(aW);
658     while (aItW.More()) {
659       const TopoDS_Shape& aE=aItW.Value();  
660       //
661       if (aMEF.Contains(aE)) {
662         BOPCol_ListOfShape& aLF=aMEF.ChangeFromKey(aE);
663         aLF.Append(aF);
664       }
665       else {
666         BOPCol_ListOfShape aLS(theAllocator);
667         //
668         aLS.Append(aF);
669         aMEF.Add(aE, aLS);
670       }
671       //
672       aItW.Next();
673     }
674     //
675     aItF.Next();
676   }
677 }