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