0026377: Passing Handle objects as arguments to functions as non-const reference...
[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 <BOPCol_DataMapOfShapeListOfShape.hxx>
20 #include <BOPCol_ListOfShape.hxx>
21 #include <BOPDS_DS.hxx>
22 #include <BOPTools.hxx>
23 #include <BOPTools_AlgoTools.hxx>
24 #include <BRepPrimAPI_MakeBox.hxx>
25 #include <TopExp_Explorer.hxx>
26 #include <TopoDS_Solid.hxx>
27
28 static
29   void AddFace(const TopoDS_Shape& theF,
30                BOPCol_ListOfShape& theLF);
31 static
32   void TreatCompound(const TopoDS_Shape& theS,
33                      BOPCol_MapOfShape& aMFence,
34                      BOPCol_ListOfShape& theLS);
35
36 //=======================================================================
37 //function : CheckData
38 //purpose  : 
39 //=======================================================================
40 void BOPAlgo_MakerVolume::CheckData()
41 {
42   if (myArguments.IsEmpty()) {
43     myErrorStatus = 100; // no arguments to process
44     return;
45   }
46   // myPaveFiller
47   if (!myPaveFiller) {
48     myErrorStatus = 101; 
49     return;
50   }
51   //
52   myErrorStatus = myPaveFiller->ErrorStatus();
53   if (myErrorStatus) {
54     myErrorStatus = 102; // PaveFiller is failed
55     return;
56   }
57 }
58
59 //=======================================================================
60 //function : Perform
61 //purpose  : 
62 //=======================================================================
63 void BOPAlgo_MakerVolume::Perform()
64 {
65   myErrorStatus = 0;
66   //
67   if (myEntryPoint == 1) {
68     if (myPaveFiller) {
69       delete myPaveFiller;
70       myPaveFiller = NULL;
71     }
72   }
73   //
74   Handle(NCollection_BaseAllocator) aAllocator = 
75     NCollection_BaseAllocator::CommonBaseAllocator();
76   BOPAlgo_PaveFiller* pPF = new BOPAlgo_PaveFiller(aAllocator);
77   //
78   if (!myIntersect) {
79     //if there is no need to intersect the arguments, then it is necessary
80     //to create the compound of them and use it as one argument
81     TopoDS_Compound anArgs;
82     BRep_Builder aBB;
83     BOPCol_ListIteratorOfListOfShape aIt;
84     BOPCol_ListOfShape aLS;
85     //
86     aBB.MakeCompound(anArgs);
87     aIt.Initialize(myArguments);
88     for (; aIt.More(); aIt.Next()) {
89       const TopoDS_Shape& aS = aIt.Value();
90       aBB.Add(anArgs, aS);
91     }
92     aLS.Append(anArgs);
93     //
94     pPF->SetArguments(aLS);
95   }
96   else {
97     pPF->SetArguments(myArguments);
98   }
99   //
100   pPF->SetRunParallel(myRunParallel);
101   pPF->SetProgressIndicator(myProgressIndicator);
102   pPF->SetFuzzyValue(myFuzzyValue);
103   pPF->SetNonDestructive(myNonDestructive);
104   pPF->Perform();
105   //
106   myEntryPoint = 1;
107   PerformInternal(*pPF);
108 }
109
110 //=======================================================================
111 //function : PerformInternal1
112 //purpose  : 
113 //=======================================================================
114 void BOPAlgo_MakerVolume::PerformInternal1
115   (const BOPAlgo_PaveFiller& theFiller)
116 {
117   myErrorStatus=0;
118   //
119   myPaveFiller = (BOPAlgo_PaveFiller*)&theFiller;
120   myDS = myPaveFiller->PDS();
121   myContext = myPaveFiller->Context();
122   //
123   // 1. CheckData
124   CheckData();
125   if (myErrorStatus) {
126     return;
127   }
128   //
129   // 2. Prepare
130   Prepare();
131   if (myErrorStatus) {
132     return;
133   }
134   //
135   // 3. Fill Images
136   // 3.1. Vertice
137   if (myIntersect) {
138     FillImagesVertices();
139     if (myErrorStatus) {
140       return;
141     }
142     // 3.2. Edges
143     FillImagesEdges();
144     if (myErrorStatus) {
145       return;
146     }
147     // 3.3. Wires
148     FillImagesContainers(TopAbs_WIRE);
149     if (myErrorStatus) {
150       return;
151     }
152     // 3.4. Faces
153     FillImagesFaces();
154     if (myErrorStatus) {
155       return;
156     }
157   }
158   //
159   // 4. Collect faces
160   CollectFaces();
161   if (myErrorStatus) {
162     return;
163   }
164   //
165   BOPCol_MapOfShape aBoxFaces;
166   BOPCol_ListOfShape aLSR;
167   //
168   // 5. Create bounding box
169   MakeBox(aBoxFaces);
170   //
171   // 6. Make volumes
172   BuildSolids(aLSR);
173   if (myErrorStatus) {
174     return;
175   }
176   //
177   // 7. Treat the result
178   RemoveBox(aLSR, aBoxFaces);
179   //
180   // 8. Fill internal shapes
181   FillInternalShapes(aLSR);
182   //
183   // 9. Build Result
184   BuildShape(aLSR);
185   //
186   // 10. History
187   PrepareHistory();
188   //
189   // 11. Post-treatment 
190   PostTreat();  
191 }
192
193 //=======================================================================
194 //function : CollectFaces
195 //purpose  : 
196 //=======================================================================
197 void BOPAlgo_MakerVolume::CollectFaces()
198 {
199   UserBreak();
200   //
201   Standard_Integer i, aNbShapes;
202   BOPCol_ListIteratorOfListOfShape aIt;
203   //
204   aNbShapes = myDS->NbSourceShapes();
205   for (i = 0; i < aNbShapes; ++i) {
206     const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
207     if (aSI.ShapeType() != TopAbs_FACE) {
208       continue;
209     }
210     //
211     const Bnd_Box& aB = aSI.Box();
212     myBBox.Add(aB);
213     //
214     const TopoDS_Shape& aF = aSI.Shape();
215     if (myImages.IsBound(aF)) {
216       const BOPCol_ListOfShape& aLFIm = myImages.Find(aF);
217       aIt.Initialize(aLFIm);
218       for (; aIt.More(); aIt.Next()) {
219         const TopoDS_Shape& aFIm = aIt.Value();
220         AddFace(aFIm, myFaces);
221       }
222     }
223     else {
224       AddFace(aF, myFaces);
225     }
226   }
227 }
228
229 //=======================================================================
230 //function : MakeBox
231 //purpose  : 
232 //=======================================================================
233 void BOPAlgo_MakerVolume::MakeBox(BOPCol_MapOfShape& theBoxFaces)
234 {
235   UserBreak();
236   //
237   Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, anExt;
238   //
239   anExt = sqrt(myBBox.SquareExtent()) * 0.5;
240   myBBox.Enlarge(anExt);
241   myBBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
242   //
243   gp_Pnt aPMin(aXmin, aYmin, aZmin), 
244          aPMax(aXmax, aYmax, aZmax);
245   //
246   mySBox = BRepPrimAPI_MakeBox(aPMin, aPMax).Solid();
247   //
248   TopExp_Explorer aExp(mySBox, TopAbs_FACE);
249   for (; aExp.More(); aExp.Next()) {
250     const TopoDS_Shape& aF = aExp.Current();
251     myFaces.Append(aF);
252     theBoxFaces.Add(aF);
253   }
254 }
255
256 //=======================================================================
257 //function : BuildSolids
258 //purpose  : 
259 //=======================================================================
260 void BOPAlgo_MakerVolume::BuildSolids(BOPCol_ListOfShape& theLSR)
261 {
262   UserBreak();
263   //
264   BOPAlgo_BuilderSolid aBS;
265   //
266   aBS.SetSolid(mySBox);
267   aBS.SetShapes(myFaces);
268   aBS.SetRunParallel(myRunParallel);
269   aBS.Perform();
270   if (aBS.ErrorStatus()) {
271     myErrorStatus = 103;
272     return;
273   }
274   //
275   theLSR = aBS.Areas();
276 }
277
278 //=======================================================================
279 //function : TreatResult
280 //purpose  : 
281 //=======================================================================
282 void BOPAlgo_MakerVolume::RemoveBox(BOPCol_ListOfShape&      theLSR,
283                                     const BOPCol_MapOfShape& theBoxFaces)
284 {
285   UserBreak();
286   //
287   BOPCol_ListIteratorOfListOfShape aIt;
288   TopExp_Explorer aExp;
289   Standard_Boolean bFound;
290   //
291   bFound = Standard_False;
292   aIt.Initialize(theLSR);
293   for (; aIt.More(); aIt.Next()) {
294     const TopoDS_Shape& aSR = aIt.Value();
295     //
296     aExp.Init(aSR, TopAbs_FACE);
297     for (; aExp.More(); aExp.Next()) {
298       const TopoDS_Shape& aF = aExp.Current();
299       if (theBoxFaces.Contains(aF)) {
300         bFound = Standard_True;
301         theLSR.Remove(aIt);
302         break;
303       }
304     }
305     if (bFound) {
306       break;
307     }
308   }
309 }
310
311 //=======================================================================
312 //function : BuildShape
313 //purpose  : 
314 //=======================================================================
315 void BOPAlgo_MakerVolume::BuildShape(const BOPCol_ListOfShape& theLSR)
316
317   if (theLSR.Extent() == 1) {
318     myShape = theLSR.First();
319   }
320   else {
321     BRep_Builder aBB;
322     BOPCol_ListIteratorOfListOfShape aIt;
323     //
324     aIt.Initialize(theLSR);
325     for (; aIt.More(); aIt.Next()) {
326       const TopoDS_Shape& aSol = aIt.Value();
327       aBB.Add(myShape, aSol);
328     }
329   }
330 }
331
332 //=======================================================================
333 //function : FillInternalShapes 
334 //purpose  : 
335 //=======================================================================
336 void BOPAlgo_MakerVolume::FillInternalShapes(const BOPCol_ListOfShape& theLSR)
337 {
338   UserBreak();
339   //
340   Standard_Integer aNbSI;
341   TopAbs_ShapeEnum aType;
342   TopAbs_State aState; 
343   TopoDS_Iterator aItS;
344   BRep_Builder aBB;
345   BOPCol_MapOfShape aMFence;
346   BOPCol_IndexedMapOfShape aMSS;
347   BOPCol_ListOfShape aLVE, aLSC, aLSIn;
348   BOPCol_ListIteratorOfListOfShape aIt, aIt1;
349   //
350   // 1. Collect shapes to process: vertices, edges, wires
351   const BOPCol_ListOfShape& anArguments = myDS->Arguments();
352   aIt.Initialize(anArguments);
353   for (; aIt.More(); aIt.Next()) {
354     const TopoDS_Shape& aS = aIt.Value();
355     TreatCompound(aS, aMFence, aLSC);
356   }
357   //
358   aIt.Initialize(aLSC);
359   for (; aIt.More(); aIt.Next()) {
360     const TopoDS_Shape& aS = aIt.Value();
361     aType = aS.ShapeType();
362     if (aType == TopAbs_WIRE) {
363       aItS.Initialize(aS);
364       for(; aItS.More(); aItS.Next()) {
365         const TopoDS_Shape& aE = aItS.Value();
366         if (aMFence.Add(aE)) {
367           aLVE.Append(aE);
368         }
369       }
370     }
371     else if (aType == TopAbs_VERTEX || aType == TopAbs_EDGE) {
372       aLVE.Append(aS);
373     } 
374   }
375   //
376   aIt.Initialize(theLSR);
377   for (; aIt.More(); aIt.Next()) {
378     const TopoDS_Shape& aS = aIt.Value();
379     BOPTools::MapShapes(aS, TopAbs_EDGE, aMSS);
380     BOPTools::MapShapes(aS, TopAbs_VERTEX, aMSS);
381   }
382   //
383   aIt.Initialize(aLVE);
384   for (; aIt.More(); aIt.Next()) {
385     const TopoDS_Shape& aS = aIt.Value();
386     if (myImages.IsBound(aS)) {
387       const BOPCol_ListOfShape &aLSp = myImages.Find(aS);
388       aIt1.Initialize(aLSp);
389       for (; aIt1.More(); aIt1.Next()) {
390         const TopoDS_Shape& aSp = aIt1.Value();
391         if (aMSS.Add(aSp)) {
392           aLSIn.Append(aSp);
393         }
394       }
395     }
396     else {
397       if (aMSS.Add(aS)) {
398         aLSIn.Append(aS);
399       }
400     }
401   }
402   //
403   aNbSI = aLSIn.Extent();
404   if (!aNbSI) {
405     return;
406   }
407   //
408   // 2. Settle internal vertices and edges into solids
409   aIt.Initialize(theLSR);
410   for (; aIt.More(); aIt.Next()) {
411     TopoDS_Solid aSd = *(TopoDS_Solid*)&aIt.Value();
412     //
413     aIt1.Initialize(aLSIn);
414     for (; aIt1.More(); ) {
415       TopoDS_Shape aSI = aIt1.Value();
416       aSI.Orientation(TopAbs_INTERNAL);
417       //
418       aState = BOPTools_AlgoTools::ComputeStateByOnePoint(aSI, aSd, 1.e-11, myContext);
419       if (aState == TopAbs_IN) {
420         aBB.Add(aSd, aSI);
421         aLSIn.Remove(aIt1);
422       }
423       else {
424         aIt1.Next();
425       }
426     }
427   }
428 }
429
430 //=======================================================================
431 //function : AddFace
432 //purpose  : 
433 //=======================================================================
434 void AddFace(const TopoDS_Shape& theF,
435              BOPCol_ListOfShape& theLF)
436 {
437   TopoDS_Shape aFF = theF;
438   aFF.Orientation(TopAbs_FORWARD);
439   theLF.Append(aFF);
440   aFF.Orientation(TopAbs_REVERSED);
441   theLF.Append(aFF);
442 }
443
444 //=======================================================================
445 //function : TreatCompound
446 //purpose  : 
447 //=======================================================================
448 void TreatCompound(const TopoDS_Shape& theS,
449                    BOPCol_MapOfShape& aMFence,
450                    BOPCol_ListOfShape& theLS)
451 {
452   TopAbs_ShapeEnum aType = theS.ShapeType();
453   if (aType != TopAbs_COMPOUND) {
454     if (aMFence.Add(theS)) {
455       theLS.Append(theS);
456     }
457     return;
458   }
459   //
460   TopoDS_Iterator aIt(theS);
461   for (; aIt.More(); aIt.Next()) {
462     const TopoDS_Shape& aS = aIt.Value();
463     TreatCompound(aS, aMFence, theLS);
464   }
465 }
466