0028786: Refactoring of the Warning/Error reporting system of Boolean Operations...
[occt.git] / src / BOPAlgo / BOPAlgo_CheckerSI.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 2010-2014 OPEN CASCADE SAS
3 // Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
4 // Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT,
5 //                         EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 //
7 // This file is part of Open CASCADE Technology software library.
8 //
9 // This library is free software; you can redistribute it and/or modify it under
10 // the terms of the GNU Lesser General Public License version 2.1 as published
11 // by the Free Software Foundation, with special exception defined in the file
12 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
13 // distribution for complete text of the license and disclaimer of any warranty.
14 //
15 // Alternatively, this file may be used under the terms of Open CASCADE
16 // commercial license or contractual agreement.
17
18 //
19
20 #include <BOPAlgo_CheckerSI.hxx>
21 #include <BOPAlgo_Alerts.hxx>
22 #include <BOPCol_MapOfShape.hxx>
23 #include <BOPCol_Parallel.hxx>
24 #include <BOPDS_DS.hxx>
25 #include <BOPDS_Interf.hxx>
26 #include <BOPDS_IteratorSI.hxx>
27 #include <BOPDS_MapOfPair.hxx>
28 #include <BOPDS_Pair.hxx>
29 #include <BOPDS_PIteratorSI.hxx>
30 #include <BOPDS_VectorOfInterfEF.hxx>
31 #include <BOPDS_VectorOfInterfFF.hxx>
32 #include <BOPDS_VectorOfInterfVE.hxx>
33 #include <BOPDS_VectorOfInterfVF.hxx>
34 #include <BOPDS_VectorOfInterfVV.hxx>
35 #include <BOPTools.hxx>
36 #include <BOPTools_AlgoTools.hxx>
37 #include <BRepBuilderAPI_Copy.hxx>
38 #include <IntTools_Context.hxx>
39 #include <IntTools_Tools.hxx>
40 #include <IntTools_FaceFace.hxx>
41 #include <Standard_ErrorHandler.hxx>
42 #include <Standard_Failure.hxx>
43 #include <TopTools_ListOfShape.hxx>
44 #include <BRep_Tool.hxx>
45 #include <gp_Torus.hxx>
46
47 //=======================================================================
48 //class    : BOPAlgo_FaceSelfIntersect
49 //purpose  : 
50 //=======================================================================
51 class BOPAlgo_FaceSelfIntersect : 
52   public IntTools_FaceFace,
53   public BOPAlgo_Algo {
54
55  public:
56   DEFINE_STANDARD_ALLOC
57
58   BOPAlgo_FaceSelfIntersect() : 
59     IntTools_FaceFace(),  
60     BOPAlgo_Algo(),
61     myIF(-1), myTolF(1.e-7) {
62   }
63   //
64   virtual ~BOPAlgo_FaceSelfIntersect() {
65   }
66   //
67   void SetIndex(const Standard_Integer nF) {
68     myIF = nF;
69   }
70   //
71   Standard_Integer IndexOfFace() const {
72     return myIF;
73   }
74   //
75   void SetFace(const TopoDS_Face& aF) {
76     myF = aF;
77   }
78   //
79   const TopoDS_Face& Face()const {
80     return myF;
81   }
82   //
83   void SetTolF(const Standard_Real aTolF) {
84     myTolF = aTolF;
85   }
86   //
87   Standard_Real TolF() const{
88     return myTolF;
89   }
90   //
91   virtual void Perform() {
92     BOPAlgo_Algo::UserBreak();
93     IntTools_FaceFace::Perform(myF, myF);
94   }
95   //
96  protected:
97   Standard_Integer myIF;
98   Standard_Real myTolF;
99   TopoDS_Face myF;
100 };
101 //end of definition of class BOPAlgo_FaceSelfIntersect
102
103 //=======================================================================
104
105 typedef BOPCol_NCVector
106   <BOPAlgo_FaceSelfIntersect> BOPAlgo_VectorOfFaceSelfIntersect; 
107 //
108 typedef BOPCol_Functor 
109   <BOPAlgo_FaceSelfIntersect,
110   BOPAlgo_VectorOfFaceSelfIntersect> BOPAlgo_FaceSelfIntersectFunctor;
111 //
112 typedef BOPCol_Cnt 
113   <BOPAlgo_FaceSelfIntersectFunctor,
114   BOPAlgo_VectorOfFaceSelfIntersect> BOPAlgo_FaceSelfIntersectCnt;
115
116
117 //=======================================================================
118 //function : 
119 //purpose  : 
120 //=======================================================================
121 BOPAlgo_CheckerSI::BOPAlgo_CheckerSI()
122 :
123   BOPAlgo_PaveFiller()
124 {
125   myLevelOfCheck=BOPDS_DS::NbInterfTypes()-1;
126   myNonDestructive=Standard_True;
127   SetAvoidBuildPCurve(Standard_True);
128 }
129 //=======================================================================
130 //function : ~
131 //purpose  : 
132 //=======================================================================
133 BOPAlgo_CheckerSI::~BOPAlgo_CheckerSI()
134 {
135 }
136 //=======================================================================
137 //function : SetLevelOfCheck
138 //purpose  : 
139 //=======================================================================
140 void BOPAlgo_CheckerSI::SetLevelOfCheck(const Standard_Integer theLevel)
141 {
142   Standard_Integer aNbLists;
143   //
144   aNbLists=BOPDS_DS::NbInterfTypes();
145   if (theLevel >= 0 && theLevel < aNbLists) {
146     myLevelOfCheck = theLevel;
147   }
148 }
149 //=======================================================================
150 //function : Init
151 //purpose  : 
152 //=======================================================================
153 void BOPAlgo_CheckerSI::Init()
154 {
155   Clear();
156   //
157   // 1. myDS
158   myDS=new BOPDS_DS(myAllocator);
159   myDS->SetArguments(myArguments);
160   myDS->Init(myFuzzyValue);
161   //
162   // 2.myIterator 
163   BOPDS_PIteratorSI theIterSI=new BOPDS_IteratorSI(myAllocator);
164   theIterSI->SetDS(myDS);
165   theIterSI->Prepare();
166   theIterSI->UpdateByLevelOfCheck(myLevelOfCheck);
167   //
168   myIterator=theIterSI;
169   //
170   // 3 myContext
171   myContext=new IntTools_Context;
172 }
173 //=======================================================================
174 //function : Perform
175 //purpose  : 
176 //=======================================================================
177 void BOPAlgo_CheckerSI::Perform()
178 {
179   try {
180     OCC_CATCH_SIGNALS
181     //
182     if (myArguments.Extent() != 1) {
183       AddError (new BOPAlgo_AlertMultipleArguments);
184       return;
185     }
186     //
187     // Perform intersection of sub shapes
188     BOPAlgo_PaveFiller::Perform();
189     //
190     CheckFaceSelfIntersection();
191     
192     // Perform intersection with solids
193     if (!HasErrors())
194       PerformVZ();
195     //
196     if (!HasErrors())
197       PerformEZ();
198     //
199     if (!HasErrors())
200       PerformFZ();
201     //
202     if (!HasErrors())
203       PerformZZ();
204     //
205     // Treat the intersection results
206     PostTreat();
207   }
208   //
209   catch (Standard_Failure) {
210     AddError (new BOPAlgo_AlertIntersectionFailed);
211   }
212 }
213 //=======================================================================
214 //function : PostTreat
215 //purpose  : 
216 //=======================================================================
217 void BOPAlgo_CheckerSI::PostTreat()
218 {
219   Standard_Integer i, aNb, n1, n2; 
220   BOPDS_Pair aPK;
221   //
222   BOPDS_MapOfPair& aMPK=
223     *((BOPDS_MapOfPair*)&myDS->Interferences());
224
225   // 0
226   BOPDS_VectorOfInterfVV& aVVs=myDS->InterfVV();
227   aNb=aVVs.Extent();
228   for (i=0; i!=aNb; ++i) {
229     const BOPDS_InterfVV& aVV=aVVs(i);
230     aVV.Indices(n1, n2);
231     if (myDS->IsNewShape(n1) || myDS->IsNewShape(n2)) {
232       continue;
233     }
234     aPK.SetIndices(n1, n2);
235     aMPK.Add(aPK);
236   }
237   //
238   // 1
239   BOPDS_VectorOfInterfVE& aVEs=myDS->InterfVE();
240   aNb=aVEs.Extent();
241   for (i=0; i!=aNb; ++i) {
242     const BOPDS_InterfVE& aVE=aVEs(i);
243     aVE.Indices(n1, n2);
244     if (myDS->IsNewShape(n1) || myDS->IsNewShape(n2)) {
245       continue;
246     }
247     aPK.SetIndices(n1, n2);
248     aMPK.Add(aPK);
249   }
250   //
251   // 2
252   BOPDS_VectorOfInterfEE& aEEs=myDS->InterfEE();
253   aNb=aEEs.Extent();
254   for (i=0; i!=aNb; ++i) {
255     const BOPDS_InterfEE& aEE=aEEs(i);
256     aEE.Indices(n1, n2);
257     if (myDS->IsNewShape(n1) || myDS->IsNewShape(n2)) {
258       continue;
259     }
260     aPK.SetIndices(n1, n2);
261     aMPK.Add(aPK);
262   }
263   //
264   // 3
265   BOPDS_VectorOfInterfVF& aVFs=myDS->InterfVF();
266   aNb=aVFs.Extent();
267   for (i=0; i!=aNb; ++i) {
268     const BOPDS_InterfVF& aVF=aVFs(i);
269     aVF.Indices(n1, n2);
270     if (myDS->IsNewShape(n1) || myDS->IsNewShape(n2)) {
271       continue;
272     }
273     aPK.SetIndices(n1, n2);
274     aMPK.Add(aPK);
275   }
276   //
277   // 4
278   BOPDS_VectorOfInterfEF& aEFs=myDS->InterfEF();
279   aNb=aEFs.Extent();
280   for (i=0; i!=aNb; ++i) {
281     const BOPDS_InterfEF& aEF=aEFs(i);
282     if (aEF.CommonPart().Type()==TopAbs_SHAPE) {
283       continue;
284     }
285     aEF.Indices(n1, n2);
286     if (myDS->IsNewShape(n1) || myDS->IsNewShape(n2)) {
287       continue;
288     }
289     aPK.SetIndices(n1, n2);
290     aMPK.Add(aPK);
291   }
292   //
293   // 5
294   BOPDS_VectorOfInterfFF& aFFs=myDS->InterfFF();
295   aNb=aFFs.Extent();
296   for (i=0; i!=aNb; ++i) {
297     Standard_Boolean bTangentFaces, bFlag;
298     Standard_Integer aNbC, aNbP, j, iFound;
299     //
300     const BOPDS_InterfFF& aFF=aFFs(i);
301     aFF.Indices(n1, n2);
302     //
303     bTangentFaces=aFF.TangentFaces();
304     aNbP=aFF.Points().Extent();
305     const BOPDS_VectorOfCurve& aVC=aFF.Curves();
306     aNbC=aVC.Extent();
307     if (!aNbP && !aNbC && !bTangentFaces) {
308       continue;
309     }
310     //
311     iFound = (n1 == n2) ? 1 : 0;
312     //case of self-intersection inside one face
313     if (!iFound)
314     {
315       if (bTangentFaces) {
316         const TopoDS_Face& aF1=*((TopoDS_Face*)&myDS->Shape(n1));
317         const TopoDS_Face& aF2=*((TopoDS_Face*)&myDS->Shape(n2));
318         bFlag=BOPTools_AlgoTools::AreFacesSameDomain
319           (aF1, aF2, myContext, myFuzzyValue);
320         if (bFlag) {
321           ++iFound;
322         }
323       }
324       else {
325         for (j=0; j!=aNbC; ++j) {
326           const BOPDS_Curve& aNC=aVC(j);
327           const BOPDS_ListOfPaveBlock& aLPBC=aNC.PaveBlocks();
328           if (aLPBC.Extent()) {
329             ++iFound;
330             break;
331           }
332         }
333       }
334     }
335     //
336     if (!iFound) {
337       continue;
338     }
339     //
340     aPK.SetIndices(n1, n2);
341     aMPK.Add(aPK);
342   }
343   //
344   //
345   // 6
346   BOPDS_VectorOfInterfVZ& aVZs=myDS->InterfVZ();
347   aNb=aVZs.Extent();
348   for (i=0; i!=aNb; ++i) {
349     //
350     const BOPDS_InterfVZ& aVZ=aVZs(i);
351     aVZ.Indices(n1, n2);
352     if (myDS->IsNewShape(n1) || myDS->IsNewShape(n2)) {
353       continue;
354     }
355     aPK.SetIndices(n1, n2);
356     aMPK.Add(aPK);
357   }
358   //
359   // 7
360   BOPDS_VectorOfInterfEZ& aEZs=myDS->InterfEZ();
361   aNb=aEZs.Extent();
362   for (i=0; i!=aNb; ++i) {
363     //
364     const BOPDS_InterfEZ& aEZ=aEZs(i);
365     aEZ.Indices(n1, n2);
366     aPK.SetIndices(n1, n2);
367     aMPK.Add(aPK);
368   }
369   //
370   // 8
371   BOPDS_VectorOfInterfFZ& aFZs=myDS->InterfFZ();
372   aNb=aFZs.Extent();
373   for (i=0; i!=aNb; ++i) {
374     //
375     const BOPDS_InterfFZ& aFZ=aFZs(i);
376     aFZ.Indices(n1, n2);
377     aPK.SetIndices(n1, n2);
378     aMPK.Add(aPK);
379   }
380   //
381   // 9
382   BOPDS_VectorOfInterfZZ& aZZs=myDS->InterfZZ();
383   aNb=aZZs.Extent();
384   for (i=0; i!=aNb; ++i) {
385     //
386     const BOPDS_InterfZZ& aZZ=aZZs(i);
387     aZZ.Indices(n1, n2);
388     aPK.SetIndices(n1, n2);
389     aMPK.Add(aPK);
390   }
391 }
392
393 //=======================================================================
394 //function : CheckFaceSelfIntersection
395 //purpose  : 
396 //=======================================================================
397 void BOPAlgo_CheckerSI::CheckFaceSelfIntersection()
398 {
399   if (myLevelOfCheck < 5)
400     return;
401   
402   BOPDS_Pair aPK;
403
404   BOPDS_MapOfPair& aMPK=
405     *((BOPDS_MapOfPair*)&myDS->Interferences());
406   aMPK.Clear();
407   
408   BOPAlgo_VectorOfFaceSelfIntersect aVFace;
409   
410   Standard_Integer aNbS=myDS->NbSourceShapes();
411   
412   //
413   for (Standard_Integer i = 0; i < aNbS; i++)
414   {
415     const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
416     if (aSI.ShapeType() != TopAbs_FACE)
417       continue;
418     //
419     const TopoDS_Face& aF = (*(TopoDS_Face*)(&aSI.Shape()));
420     BRepAdaptor_Surface BAsurf(aF, Standard_False);
421     GeomAbs_SurfaceType aSurfType = BAsurf.GetType();
422     if (aSurfType == GeomAbs_Plane ||
423         aSurfType == GeomAbs_Cylinder ||
424         aSurfType == GeomAbs_Cone ||
425         aSurfType == GeomAbs_Sphere)
426       continue;
427
428     if (aSurfType == GeomAbs_Torus)
429     {
430       gp_Torus aTorus = BAsurf.Torus();
431       Standard_Real aMajorRadius = aTorus.MajorRadius();
432       Standard_Real aMinorRadius = aTorus.MinorRadius();
433       if (aMajorRadius > aMinorRadius + Precision::Confusion())
434         continue;
435     }
436
437     Standard_Real aTolF = BRep_Tool::Tolerance(aF);
438     
439     BOPAlgo_FaceSelfIntersect& aFaceSelfIntersect = aVFace.Append1();
440     //
441     aFaceSelfIntersect.SetIndex(i);
442     aFaceSelfIntersect.SetFace(aF);
443     aFaceSelfIntersect.SetTolF(aTolF);
444     //
445     aFaceSelfIntersect.SetProgressIndicator(myProgressIndicator);
446   }
447   
448   Standard_Integer aNbFace = aVFace.Extent();
449   //======================================================
450   BOPAlgo_FaceSelfIntersectCnt::Perform(myRunParallel, aVFace);
451   //======================================================
452   //
453   for (Standard_Integer k = 0; k < aNbFace; k++)
454   {
455     BOPAlgo_FaceSelfIntersect& aFaceSelfIntersect = aVFace(k);
456     //
457     Standard_Integer nF = aFaceSelfIntersect.IndexOfFace();
458
459     Standard_Boolean bIsDone = aFaceSelfIntersect.IsDone();
460     if (bIsDone)
461     {
462       const IntTools_SequenceOfCurves& aCvsX = aFaceSelfIntersect.Lines();
463       const IntTools_SequenceOfPntOn2Faces& aPntsX = aFaceSelfIntersect.Points();
464       //
465       Standard_Integer aNbCurves = aCvsX.Length();
466       Standard_Integer aNbPoints = aPntsX.Length();
467       //
468       if (aNbCurves || aNbPoints)
469       {
470         aPK.SetIndices(nF, nF);
471         aMPK.Add(aPK);
472       }
473     }
474   }
475 }