0025748: Parallel version of progress indicator
[occt.git] / src / BOPAlgo / BOPAlgo_MakerVolume.cxx
1 // Created by: Eugeny MALTCHIKOV
2 // Copyright (c) 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 #include <Bnd_Box.hxx>
16 #include <BOPAlgo_BuilderSolid.hxx>
17 #include <BOPAlgo_MakerVolume.hxx>
18 #include <BOPAlgo_PaveFiller.hxx>
19 #include <BOPAlgo_Tools.hxx>
20 #include <BOPAlgo_Alerts.hxx>
21 #include <BOPDS_DS.hxx>
22 #include <BOPTools_AlgoTools.hxx>
23 #include <BRepPrimAPI_MakeBox.hxx>
24 #include <TopExp.hxx>
25 #include <TopExp_Explorer.hxx>
26 #include <TopoDS_Solid.hxx>
27 #include <TopTools_ListOfShape.hxx>
28
29 static
30   void AddFace(const TopoDS_Shape& theF,
31                TopTools_ListOfShape& theLF);
32
33 //=======================================================================
34 //function : CheckData
35 //purpose  : 
36 //=======================================================================
37 void BOPAlgo_MakerVolume::CheckData()
38 {
39   if (myArguments.IsEmpty()) {
40     AddError (new BOPAlgo_AlertTooFewArguments); // no arguments to process
41     return;
42   }
43   //
44   CheckFiller();
45 }
46
47 //=======================================================================
48 //function : Perform
49 //purpose  : 
50 //=======================================================================
51 void BOPAlgo_MakerVolume::Perform()
52 {
53   GetReport()->Clear();
54   //
55   if (myEntryPoint == 1) {
56     if (myPaveFiller) {
57       delete myPaveFiller;
58       myPaveFiller = NULL;
59     }
60   }
61   //
62   Handle(NCollection_BaseAllocator) aAllocator = 
63     NCollection_BaseAllocator::CommonBaseAllocator();
64   BOPAlgo_PaveFiller* pPF = new BOPAlgo_PaveFiller(aAllocator);
65   //
66   if (!myIntersect) {
67     //if there is no need to intersect the arguments, then it is necessary
68     //to create the compound of them and use it as one argument
69     TopoDS_Compound anArgs;
70     BRep_Builder aBB;
71     TopTools_ListIteratorOfListOfShape aIt;
72     TopTools_ListOfShape aLS;
73     //
74     aBB.MakeCompound(anArgs);
75     aIt.Initialize(myArguments);
76     for (; aIt.More(); aIt.Next()) {
77       const TopoDS_Shape& aS = aIt.Value();
78       aBB.Add(anArgs, aS);
79     }
80     aLS.Append(anArgs);
81     //
82     pPF->SetArguments(aLS);
83   }
84   else {
85     pPF->SetArguments(myArguments);
86   }
87   //
88   pPF->SetRunParallel(myRunParallel);
89   pPF->SetProgressIndicator(*myProgressScope);
90   pPF->SetFuzzyValue(myFuzzyValue);
91   pPF->SetNonDestructive(myNonDestructive);
92   pPF->SetGlue(myGlue);
93   pPF->SetUseOBB(myUseOBB);
94   pPF->Perform();
95   //
96   myEntryPoint = 1;
97   PerformInternal(*pPF);
98 }
99
100 //=======================================================================
101 //function : PerformInternal1
102 //purpose  : 
103 //=======================================================================
104 void BOPAlgo_MakerVolume::PerformInternal1
105   (const BOPAlgo_PaveFiller& theFiller)
106 {
107   myPaveFiller = (BOPAlgo_PaveFiller*)&theFiller;
108   myDS = myPaveFiller->PDS();
109   myContext = myPaveFiller->Context();
110   //
111   // 1. CheckData
112   CheckData();
113   if (HasErrors()) {
114     return;
115   }
116   //
117   // 2. Prepare
118   Prepare();
119   if (HasErrors()) {
120     return;
121   }
122   //
123   // 3. Fill Images
124   // 3.1. Vertice
125   if (myIntersect) {
126     FillImagesVertices();
127     if (HasErrors()) {
128       return;
129     }
130     // 3.2. Edges
131     FillImagesEdges();
132     if (HasErrors()) {
133       return;
134     }
135     // 3.3. Wires
136     FillImagesContainers(TopAbs_WIRE);
137     if (HasErrors()) {
138       return;
139     }
140     // 3.4. Faces
141     FillImagesFaces();
142     if (HasErrors()) {
143       return;
144     }
145   }
146   //
147   // 4. Collect faces
148   CollectFaces();
149   if (HasErrors()) {
150     return;
151   }
152   //
153   TopTools_MapOfShape aBoxFaces;
154   TopTools_ListOfShape aLSR;
155   //
156   // 5. Create bounding box
157   MakeBox(aBoxFaces);
158   //
159   // 6. Make volumes
160   BuildSolids(aLSR);
161   if (HasErrors()) {
162     return;
163   }
164   //
165   // 7. Treat the result
166   RemoveBox(aLSR, aBoxFaces);
167   //
168   // 8. Fill internal shapes
169   FillInternalShapes(aLSR);
170   //
171   // 9. Build Result
172   BuildShape(aLSR);
173   //
174   // 10. History
175   PrepareHistory();
176   //
177   // 11. Post-treatment 
178   PostTreat();  
179 }
180
181 //=======================================================================
182 //function : CollectFaces
183 //purpose  : 
184 //=======================================================================
185 void BOPAlgo_MakerVolume::CollectFaces()
186 {
187   UserBreak();
188   //
189   Standard_Integer i, aNbShapes;
190   TopTools_ListIteratorOfListOfShape aIt;
191   TopTools_MapOfShape aMFence;
192   //
193   aNbShapes = myDS->NbSourceShapes();
194   for (i = 0; i < aNbShapes; ++i) {
195     const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
196     if (aSI.ShapeType() != TopAbs_FACE) {
197       continue;
198     }
199     //
200     const Bnd_Box& aB = aSI.Box();
201     myBBox.Add(aB);
202     //
203     const TopoDS_Shape& aF = aSI.Shape();
204     if (myImages.IsBound(aF)) {
205       const TopTools_ListOfShape& aLFIm = myImages.Find(aF);
206       aIt.Initialize(aLFIm);
207       for (; aIt.More(); aIt.Next()) {
208         const TopoDS_Shape& aFIm = aIt.Value();
209         if (aMFence.Add(aFIm)) {
210           AddFace(aFIm, myFaces);
211         }
212       }
213     }
214     else {
215       AddFace(aF, myFaces);
216     }
217   }
218 }
219
220 //=======================================================================
221 //function : MakeBox
222 //purpose  : 
223 //=======================================================================
224 void BOPAlgo_MakerVolume::MakeBox(TopTools_MapOfShape& theBoxFaces)
225 {
226   UserBreak();
227   //
228   Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, anExt;
229   //
230   anExt = sqrt(myBBox.SquareExtent()) * 0.5;
231   myBBox.Enlarge(anExt);
232   myBBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
233   //
234   gp_Pnt aPMin(aXmin, aYmin, aZmin), 
235          aPMax(aXmax, aYmax, aZmax);
236   //
237   mySBox = BRepPrimAPI_MakeBox(aPMin, aPMax).Solid();
238   //
239   TopExp_Explorer aExp(mySBox, TopAbs_FACE);
240   for (; aExp.More(); aExp.Next()) {
241     const TopoDS_Shape& aF = aExp.Current();
242     myFaces.Append(aF);
243     theBoxFaces.Add(aF);
244   }
245 }
246
247 //=======================================================================
248 //function : BuildSolids
249 //purpose  : 
250 //=======================================================================
251 void BOPAlgo_MakerVolume::BuildSolids(TopTools_ListOfShape& theLSR)
252 {
253   UserBreak();
254   //
255   BOPAlgo_BuilderSolid aBS;
256   //
257   aBS.SetShapes(myFaces);
258   aBS.SetRunParallel(myRunParallel);
259   aBS.SetAvoidInternalShapes(myAvoidInternalShapes);
260   aBS.Perform();
261   if (aBS.HasErrors())
262   {
263     AddError (new BOPAlgo_AlertSolidBuilderFailed); // SolidBuilder failed
264     return;
265   }
266   //
267   myReport->Merge(aBS.GetReport());
268   //
269   theLSR = aBS.Areas();
270 }
271
272 //=======================================================================
273 //function : TreatResult
274 //purpose  : 
275 //=======================================================================
276 void BOPAlgo_MakerVolume::RemoveBox(TopTools_ListOfShape&      theLSR,
277                                     const TopTools_MapOfShape& theBoxFaces)
278 {
279   UserBreak();
280   //
281   TopTools_ListIteratorOfListOfShape aIt;
282   TopExp_Explorer aExp;
283   Standard_Boolean bFound;
284   //
285   bFound = Standard_False;
286   aIt.Initialize(theLSR);
287   for (; aIt.More(); aIt.Next()) {
288     const TopoDS_Shape& aSR = aIt.Value();
289     //
290     aExp.Init(aSR, TopAbs_FACE);
291     for (; aExp.More(); aExp.Next()) {
292       const TopoDS_Shape& aF = aExp.Current();
293       if (theBoxFaces.Contains(aF)) {
294         bFound = Standard_True;
295         theLSR.Remove(aIt);
296         break;
297       }
298     }
299     if (bFound) {
300       break;
301     }
302   }
303 }
304
305 //=======================================================================
306 //function : BuildShape
307 //purpose  : 
308 //=======================================================================
309 void BOPAlgo_MakerVolume::BuildShape(const TopTools_ListOfShape& theLSR)
310
311   if (theLSR.Extent() == 1) {
312     myShape = theLSR.First();
313   }
314   else {
315     BRep_Builder aBB;
316     TopTools_ListIteratorOfListOfShape aIt;
317     //
318     aIt.Initialize(theLSR);
319     for (; aIt.More(); aIt.Next()) {
320       const TopoDS_Shape& aSol = aIt.Value();
321       aBB.Add(myShape, aSol);
322     }
323   }
324 }
325
326 //=======================================================================
327 //function : FillInternalShapes 
328 //purpose  : 
329 //=======================================================================
330 void BOPAlgo_MakerVolume::FillInternalShapes(const TopTools_ListOfShape& theLSR)
331 {
332   if (myAvoidInternalShapes) {
333     return;
334   }
335
336   UserBreak();
337
338   // Get all non-compound shapes
339   TopTools_ListOfShape aLSC;
340   // Fence map
341   TopTools_MapOfShape aMFence;
342
343   TopTools_ListOfShape::Iterator itLA(myDS->Arguments());
344   for (; itLA.More(); itLA.Next())
345     BOPTools_AlgoTools::TreatCompound(itLA.Value(), aLSC, &aMFence);
346
347   // Get only edges and vertices from arguments
348   TopTools_ListOfShape aLVE;
349
350   itLA.Initialize(aLSC);
351   for (; itLA.More(); itLA.Next())
352   {
353     const TopoDS_Shape& aS = itLA.Value();
354     TopAbs_ShapeEnum aType = aS.ShapeType();
355     if (aType == TopAbs_WIRE)
356     {
357       for (TopoDS_Iterator it(aS); it.More(); it.Next())
358       {
359         const TopoDS_Shape& aSS = it.Value();
360         if (aMFence.Add(aSS))
361           aLVE.Append(aSS);
362       }
363     }
364     else if (aType == TopAbs_VERTEX || aType == TopAbs_EDGE)
365       aLVE.Append(aS);
366   }
367
368   BOPAlgo_Tools::FillInternals(theLSR, aLVE, myImages, myContext);
369 }
370
371 //=======================================================================
372 //function : AddFace
373 //purpose  : 
374 //=======================================================================
375 void AddFace(const TopoDS_Shape& theF,
376              TopTools_ListOfShape& theLF)
377 {
378   TopoDS_Shape aFF = theF;
379   aFF.Orientation(TopAbs_FORWARD);
380   theLF.Append(aFF);
381   aFF.Orientation(TopAbs_REVERSED);
382   theLF.Append(aFF);
383 }