0028187: Add possibility to avoid creation of Internal parts in the result of Volume...
[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.SetAvoidInternalShapes(myAvoidInternalShapes);
274   aBS.Perform();
275   if (aBS.ErrorStatus()) {
276     myErrorStatus = 103;
277     return;
278   }
279   //
280   theLSR = aBS.Areas();
281 }
282
283 //=======================================================================
284 //function : TreatResult
285 //purpose  : 
286 //=======================================================================
287 void BOPAlgo_MakerVolume::RemoveBox(BOPCol_ListOfShape&      theLSR,
288                                     const BOPCol_MapOfShape& theBoxFaces)
289 {
290   UserBreak();
291   //
292   BOPCol_ListIteratorOfListOfShape aIt;
293   TopExp_Explorer aExp;
294   Standard_Boolean bFound;
295   //
296   bFound = Standard_False;
297   aIt.Initialize(theLSR);
298   for (; aIt.More(); aIt.Next()) {
299     const TopoDS_Shape& aSR = aIt.Value();
300     //
301     aExp.Init(aSR, TopAbs_FACE);
302     for (; aExp.More(); aExp.Next()) {
303       const TopoDS_Shape& aF = aExp.Current();
304       if (theBoxFaces.Contains(aF)) {
305         bFound = Standard_True;
306         theLSR.Remove(aIt);
307         break;
308       }
309     }
310     if (bFound) {
311       break;
312     }
313   }
314 }
315
316 //=======================================================================
317 //function : BuildShape
318 //purpose  : 
319 //=======================================================================
320 void BOPAlgo_MakerVolume::BuildShape(const BOPCol_ListOfShape& theLSR)
321
322   if (theLSR.Extent() == 1) {
323     myShape = theLSR.First();
324   }
325   else {
326     BRep_Builder aBB;
327     BOPCol_ListIteratorOfListOfShape aIt;
328     //
329     aIt.Initialize(theLSR);
330     for (; aIt.More(); aIt.Next()) {
331       const TopoDS_Shape& aSol = aIt.Value();
332       aBB.Add(myShape, aSol);
333     }
334   }
335 }
336
337 //=======================================================================
338 //function : FillInternalShapes 
339 //purpose  : 
340 //=======================================================================
341 void BOPAlgo_MakerVolume::FillInternalShapes(const BOPCol_ListOfShape& theLSR)
342 {
343   if (myAvoidInternalShapes) {
344     return;
345   }
346   //
347   UserBreak();
348   //
349   Standard_Integer aNbSI;
350   TopAbs_ShapeEnum aType;
351   TopAbs_State aState; 
352   TopoDS_Iterator aItS;
353   BRep_Builder aBB;
354   BOPCol_MapOfShape aMFence;
355   BOPCol_IndexedMapOfShape aMSS;
356   BOPCol_ListOfShape aLVE, aLSC, aLSIn;
357   BOPCol_ListIteratorOfListOfShape aIt, aIt1;
358   //
359   // 1. Collect shapes to process: vertices, edges, wires
360   const BOPCol_ListOfShape& anArguments = myDS->Arguments();
361   aIt.Initialize(anArguments);
362   for (; aIt.More(); aIt.Next()) {
363     const TopoDS_Shape& aS = aIt.Value();
364     TreatCompound(aS, aMFence, aLSC);
365   }
366   //
367   aIt.Initialize(aLSC);
368   for (; aIt.More(); aIt.Next()) {
369     const TopoDS_Shape& aS = aIt.Value();
370     aType = aS.ShapeType();
371     if (aType == TopAbs_WIRE) {
372       aItS.Initialize(aS);
373       for(; aItS.More(); aItS.Next()) {
374         const TopoDS_Shape& aE = aItS.Value();
375         if (aMFence.Add(aE)) {
376           aLVE.Append(aE);
377         }
378       }
379     }
380     else if (aType == TopAbs_VERTEX || aType == TopAbs_EDGE) {
381       aLVE.Append(aS);
382     } 
383   }
384   //
385   aIt.Initialize(theLSR);
386   for (; aIt.More(); aIt.Next()) {
387     const TopoDS_Shape& aS = aIt.Value();
388     BOPTools::MapShapes(aS, TopAbs_EDGE, aMSS);
389     BOPTools::MapShapes(aS, TopAbs_VERTEX, aMSS);
390   }
391   //
392   aIt.Initialize(aLVE);
393   for (; aIt.More(); aIt.Next()) {
394     const TopoDS_Shape& aS = aIt.Value();
395     if (myImages.IsBound(aS)) {
396       const BOPCol_ListOfShape &aLSp = myImages.Find(aS);
397       aIt1.Initialize(aLSp);
398       for (; aIt1.More(); aIt1.Next()) {
399         const TopoDS_Shape& aSp = aIt1.Value();
400         if (aMSS.Add(aSp)) {
401           aLSIn.Append(aSp);
402         }
403       }
404     }
405     else {
406       if (aMSS.Add(aS)) {
407         aLSIn.Append(aS);
408       }
409     }
410   }
411   //
412   aNbSI = aLSIn.Extent();
413   if (!aNbSI) {
414     return;
415   }
416   //
417   // 2. Settle internal vertices and edges into solids
418   aIt.Initialize(theLSR);
419   for (; aIt.More(); aIt.Next()) {
420     TopoDS_Solid aSd = *(TopoDS_Solid*)&aIt.Value();
421     //
422     aIt1.Initialize(aLSIn);
423     for (; aIt1.More(); ) {
424       TopoDS_Shape aSI = aIt1.Value();
425       aSI.Orientation(TopAbs_INTERNAL);
426       //
427       aState = BOPTools_AlgoTools::ComputeStateByOnePoint(aSI, aSd, 1.e-11, myContext);
428       if (aState == TopAbs_IN) {
429         aBB.Add(aSd, aSI);
430         aLSIn.Remove(aIt1);
431       }
432       else {
433         aIt1.Next();
434       }
435     }
436   }
437 }
438
439 //=======================================================================
440 //function : AddFace
441 //purpose  : 
442 //=======================================================================
443 void AddFace(const TopoDS_Shape& theF,
444              BOPCol_ListOfShape& theLF)
445 {
446   TopoDS_Shape aFF = theF;
447   aFF.Orientation(TopAbs_FORWARD);
448   theLF.Append(aFF);
449   aFF.Orientation(TopAbs_REVERSED);
450   theLF.Append(aFF);
451 }
452
453 //=======================================================================
454 //function : TreatCompound
455 //purpose  : 
456 //=======================================================================
457 void TreatCompound(const TopoDS_Shape& theS,
458                    BOPCol_MapOfShape& aMFence,
459                    BOPCol_ListOfShape& theLS)
460 {
461   TopAbs_ShapeEnum aType = theS.ShapeType();
462   if (aType != TopAbs_COMPOUND) {
463     if (aMFence.Add(theS)) {
464       theLS.Append(theS);
465     }
466     return;
467   }
468   //
469   TopoDS_Iterator aIt(theS);
470   for (; aIt.More(); aIt.Next()) {
471     const TopoDS_Shape& aS = aIt.Value();
472     TreatCompound(aS, aMFence, theLS);
473   }
474 }
475