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