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