3a34b9b2dd716b4491f91ee8248e7bf463ce573d
[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 <BOPDS_DS.hxx>
23 #include <BOPDS_Interf.hxx>
24 #include <BOPDS_IteratorSI.hxx>
25 #include <BOPDS_MapOfPair.hxx>
26 #include <BOPDS_Pair.hxx>
27 #include <BOPDS_PIteratorSI.hxx>
28 #include <BOPDS_VectorOfInterfEF.hxx>
29 #include <BOPDS_VectorOfInterfFF.hxx>
30 #include <BOPDS_VectorOfInterfVE.hxx>
31 #include <BOPDS_VectorOfInterfVF.hxx>
32 #include <BOPDS_VectorOfInterfVV.hxx>
33 #include <BRep_Tool.hxx>
34 #include <gp_Torus.hxx>
35 #include <TopExp.hxx>
36 #include <BOPTools_AlgoTools.hxx>
37 #include <BOPTools_Parallel.hxx>
38 #include <BRepBuilderAPI_Copy.hxx>
39 #include <IntTools_Context.hxx>
40 #include <IntTools_Tools.hxx>
41 #include <IntTools_FaceFace.hxx>
42 #include <Standard_ErrorHandler.hxx>
43 #include <Standard_Failure.hxx>
44 #include <TopTools_ListOfShape.hxx>
45 #include <TopTools_MapOfShape.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 NCollection_Vector<BOPAlgo_FaceSelfIntersect> BOPAlgo_VectorOfFaceSelfIntersect;
106
107 //=======================================================================
108 //function : 
109 //purpose  : 
110 //=======================================================================
111 BOPAlgo_CheckerSI::BOPAlgo_CheckerSI()
112 :
113   BOPAlgo_PaveFiller()
114 {
115   myLevelOfCheck=BOPDS_DS::NbInterfTypes()-1;
116   myNonDestructive=Standard_True;
117   SetAvoidBuildPCurve(Standard_True);
118 }
119 //=======================================================================
120 //function : ~
121 //purpose  : 
122 //=======================================================================
123 BOPAlgo_CheckerSI::~BOPAlgo_CheckerSI()
124 {
125 }
126 //=======================================================================
127 //function : SetLevelOfCheck
128 //purpose  : 
129 //=======================================================================
130 void BOPAlgo_CheckerSI::SetLevelOfCheck(const Standard_Integer theLevel)
131 {
132   Standard_Integer aNbLists;
133   //
134   aNbLists=BOPDS_DS::NbInterfTypes();
135   if (theLevel >= 0 && theLevel < aNbLists) {
136     myLevelOfCheck = theLevel;
137   }
138 }
139 //=======================================================================
140 //function : Init
141 //purpose  : 
142 //=======================================================================
143 void BOPAlgo_CheckerSI::Init()
144 {
145   Clear();
146   //
147   // 1. myDS
148   myDS=new BOPDS_DS(myAllocator);
149   myDS->SetArguments(myArguments);
150   myDS->Init(myFuzzyValue);
151   //
152   // 2 myContext
153   myContext=new IntTools_Context;
154   //
155   // 3.myIterator 
156   BOPDS_PIteratorSI theIterSI=new BOPDS_IteratorSI(myAllocator);
157   theIterSI->SetDS(myDS);
158   theIterSI->Prepare(myContext, myUseOBB, myFuzzyValue);
159   theIterSI->UpdateByLevelOfCheck(myLevelOfCheck);
160   //
161   myIterator=theIterSI;
162 }
163 //=======================================================================
164 //function : Perform
165 //purpose  : 
166 //=======================================================================
167 void BOPAlgo_CheckerSI::Perform()
168 {
169   try {
170     OCC_CATCH_SIGNALS
171     //
172     if (myArguments.Extent() != 1) {
173       AddError (new BOPAlgo_AlertMultipleArguments);
174       return;
175     }
176     //
177     // Perform intersection of sub shapes
178     BOPAlgo_PaveFiller::Perform();
179     //
180     CheckFaceSelfIntersection();
181     
182     // Perform intersection with solids
183     if (!HasErrors())
184       PerformVZ();
185     //
186     if (!HasErrors())
187       PerformEZ();
188     //
189     if (!HasErrors())
190       PerformFZ();
191     //
192     if (!HasErrors())
193       PerformZZ();
194     //
195     // Treat the intersection results
196     PostTreat();
197   }
198   //
199   catch (Standard_Failure const&) {
200     AddError (new BOPAlgo_AlertIntersectionFailed);
201   }
202 }
203 //=======================================================================
204 //function : PostTreat
205 //purpose  : 
206 //=======================================================================
207 void BOPAlgo_CheckerSI::PostTreat()
208 {
209   Standard_Integer i, aNb, n1, n2; 
210   BOPDS_Pair aPK;
211   //
212   BOPDS_MapOfPair& aMPK=
213     *((BOPDS_MapOfPair*)&myDS->Interferences());
214
215   // 0
216   BOPDS_VectorOfInterfVV& aVVs=myDS->InterfVV();
217   aNb=aVVs.Length();
218   for (i=0; i!=aNb; ++i) {
219     const BOPDS_InterfVV& aVV=aVVs(i);
220     aVV.Indices(n1, n2);
221     if (myDS->IsNewShape(n1) || myDS->IsNewShape(n2)) {
222       continue;
223     }
224     aPK.SetIndices(n1, n2);
225     aMPK.Add(aPK);
226   }
227   //
228   // 1
229   BOPDS_VectorOfInterfVE& aVEs=myDS->InterfVE();
230   aNb=aVEs.Length();
231   for (i=0; i!=aNb; ++i) {
232     const BOPDS_InterfVE& aVE=aVEs(i);
233     aVE.Indices(n1, n2);
234     if (myDS->IsNewShape(n1) || myDS->IsNewShape(n2)) {
235       continue;
236     }
237     aPK.SetIndices(n1, n2);
238     aMPK.Add(aPK);
239   }
240   //
241   // 2
242   BOPDS_VectorOfInterfEE& aEEs=myDS->InterfEE();
243   aNb=aEEs.Length();
244   for (i=0; i!=aNb; ++i) {
245     const BOPDS_InterfEE& aEE=aEEs(i);
246     aEE.Indices(n1, n2);
247     if (myDS->IsNewShape(n1) || myDS->IsNewShape(n2)) {
248       continue;
249     }
250     aPK.SetIndices(n1, n2);
251     aMPK.Add(aPK);
252   }
253   //
254   // 3
255   BOPDS_VectorOfInterfVF& aVFs=myDS->InterfVF();
256   aNb=aVFs.Length();
257   for (i=0; i!=aNb; ++i) {
258     const BOPDS_InterfVF& aVF=aVFs(i);
259     aVF.Indices(n1, n2);
260     if (myDS->IsNewShape(n1) || myDS->IsNewShape(n2)) {
261       continue;
262     }
263     aPK.SetIndices(n1, n2);
264     aMPK.Add(aPK);
265   }
266   //
267   // 4
268   BOPDS_VectorOfInterfEF& aEFs=myDS->InterfEF();
269   aNb=aEFs.Length();
270   for (i=0; i!=aNb; ++i) {
271     const BOPDS_InterfEF& aEF=aEFs(i);
272     if (aEF.CommonPart().Type()==TopAbs_SHAPE) {
273       continue;
274     }
275     aEF.Indices(n1, n2);
276     if (myDS->IsNewShape(n1) || myDS->IsNewShape(n2)) {
277       continue;
278     }
279     aPK.SetIndices(n1, n2);
280     aMPK.Add(aPK);
281   }
282   //
283   // 5
284   BOPDS_VectorOfInterfFF& aFFs=myDS->InterfFF();
285   aNb=aFFs.Length();
286   for (i=0; i!=aNb; ++i) {
287     Standard_Boolean bTangentFaces, bFlag;
288     Standard_Integer aNbC, aNbP, j, iFound;
289     //
290     const BOPDS_InterfFF& aFF=aFFs(i);
291     aFF.Indices(n1, n2);
292     //
293     bTangentFaces=aFF.TangentFaces();
294     aNbP=aFF.Points().Length();
295     const BOPDS_VectorOfCurve& aVC=aFF.Curves();
296     aNbC=aVC.Length();
297     if (!aNbP && !aNbC && !bTangentFaces) {
298       continue;
299     }
300     //
301     iFound = (n1 == n2) ? 1 : 0;
302     //case of self-intersection inside one face
303     if (!iFound)
304     {
305       if (bTangentFaces) {
306         const TopoDS_Face& aF1=*((TopoDS_Face*)&myDS->Shape(n1));
307         const TopoDS_Face& aF2=*((TopoDS_Face*)&myDS->Shape(n2));
308         bFlag=BOPTools_AlgoTools::AreFacesSameDomain
309           (aF1, aF2, myContext, myFuzzyValue);
310         if (bFlag) {
311           ++iFound;
312         }
313       }
314       else {
315         for (j=0; j!=aNbC; ++j) {
316           const BOPDS_Curve& aNC=aVC(j);
317           const BOPDS_ListOfPaveBlock& aLPBC=aNC.PaveBlocks();
318           if (aLPBC.Extent()) {
319             ++iFound;
320             break;
321           }
322         }
323       }
324     }
325     //
326     if (!iFound) {
327       continue;
328     }
329     //
330     aPK.SetIndices(n1, n2);
331     aMPK.Add(aPK);
332   }
333   //
334   //
335   // 6
336   BOPDS_VectorOfInterfVZ& aVZs=myDS->InterfVZ();
337   aNb=aVZs.Length();
338   for (i=0; i!=aNb; ++i) {
339     //
340     const BOPDS_InterfVZ& aVZ=aVZs(i);
341     aVZ.Indices(n1, n2);
342     if (myDS->IsNewShape(n1) || myDS->IsNewShape(n2)) {
343       continue;
344     }
345     aPK.SetIndices(n1, n2);
346     aMPK.Add(aPK);
347   }
348   //
349   // 7
350   BOPDS_VectorOfInterfEZ& aEZs=myDS->InterfEZ();
351   aNb=aEZs.Length();
352   for (i=0; i!=aNb; ++i) {
353     //
354     const BOPDS_InterfEZ& aEZ=aEZs(i);
355     aEZ.Indices(n1, n2);
356     aPK.SetIndices(n1, n2);
357     aMPK.Add(aPK);
358   }
359   //
360   // 8
361   BOPDS_VectorOfInterfFZ& aFZs=myDS->InterfFZ();
362   aNb=aFZs.Length();
363   for (i=0; i!=aNb; ++i) {
364     //
365     const BOPDS_InterfFZ& aFZ=aFZs(i);
366     aFZ.Indices(n1, n2);
367     aPK.SetIndices(n1, n2);
368     aMPK.Add(aPK);
369   }
370   //
371   // 9
372   BOPDS_VectorOfInterfZZ& aZZs=myDS->InterfZZ();
373   aNb=aZZs.Length();
374   for (i=0; i!=aNb; ++i) {
375     //
376     const BOPDS_InterfZZ& aZZ=aZZs(i);
377     aZZ.Indices(n1, n2);
378     aPK.SetIndices(n1, n2);
379     aMPK.Add(aPK);
380   }
381 }
382
383 //=======================================================================
384 //function : CheckFaceSelfIntersection
385 //purpose  : 
386 //=======================================================================
387 void BOPAlgo_CheckerSI::CheckFaceSelfIntersection()
388 {
389   if (myLevelOfCheck < 5)
390     return;
391   
392   BOPDS_Pair aPK;
393
394   BOPDS_MapOfPair& aMPK=
395     *((BOPDS_MapOfPair*)&myDS->Interferences());
396   aMPK.Clear();
397   
398   BOPAlgo_VectorOfFaceSelfIntersect aVFace;
399   
400   Standard_Integer aNbS=myDS->NbSourceShapes();
401   
402   //
403   for (Standard_Integer i = 0; i < aNbS; i++)
404   {
405     const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i);
406     if (aSI.ShapeType() != TopAbs_FACE)
407       continue;
408     //
409     const TopoDS_Face& aF = (*(TopoDS_Face*)(&aSI.Shape()));
410     BRepAdaptor_Surface BAsurf(aF, Standard_False);
411     GeomAbs_SurfaceType aSurfType = BAsurf.GetType();
412     if (aSurfType == GeomAbs_Plane ||
413         aSurfType == GeomAbs_Cylinder ||
414         aSurfType == GeomAbs_Cone ||
415         aSurfType == GeomAbs_Sphere)
416       continue;
417
418     if (aSurfType == GeomAbs_Torus)
419     {
420       gp_Torus aTorus = BAsurf.Torus();
421       Standard_Real aMajorRadius = aTorus.MajorRadius();
422       Standard_Real aMinorRadius = aTorus.MinorRadius();
423       if (aMajorRadius > aMinorRadius + Precision::Confusion())
424         continue;
425     }
426
427     Standard_Real aTolF = BRep_Tool::Tolerance(aF);
428     
429     BOPAlgo_FaceSelfIntersect& aFaceSelfIntersect = aVFace.Appended();
430     //
431     aFaceSelfIntersect.SetIndex(i);
432     aFaceSelfIntersect.SetFace(aF);
433     aFaceSelfIntersect.SetTolF(aTolF);
434     //
435     aFaceSelfIntersect.SetProgressIndicator(myProgressIndicator);
436   }
437   
438   Standard_Integer aNbFace = aVFace.Length();
439   //======================================================
440   BOPTools_Parallel::Perform (myRunParallel, aVFace);
441   //======================================================
442   //
443   for (Standard_Integer k = 0; k < aNbFace; k++)
444   {
445     BOPAlgo_FaceSelfIntersect& aFaceSelfIntersect = aVFace(k);
446     //
447     Standard_Integer nF = aFaceSelfIntersect.IndexOfFace();
448
449     Standard_Boolean bIsDone = aFaceSelfIntersect.IsDone();
450     if (bIsDone)
451     {
452       const IntTools_SequenceOfCurves& aCvsX = aFaceSelfIntersect.Lines();
453       const IntTools_SequenceOfPntOn2Faces& aPntsX = aFaceSelfIntersect.Points();
454       //
455       Standard_Integer aNbCurves = aCvsX.Length();
456       Standard_Integer aNbPoints = aPntsX.Length();
457       //
458       if (aNbCurves || aNbPoints)
459       {
460         aPK.SetIndices(nF, nF);
461         aMPK.Add(aPK);
462       }
463     }
464   }
465 }