0025109: Check PolygonOnTriangulation contained in edges
[occt.git] / src / BRepCheck / BRepCheck_Analyzer.cxx
1 // Created on: 1995-12-08
2 // Created by: Jacques GOUSSARD
3 // Copyright (c) 1995-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <BRepCheck_Analyzer.ixx>
18
19 #include <BRepCheck_Vertex.hxx>
20 #include <BRepCheck_Edge.hxx>
21 #include <BRepCheck_Wire.hxx>
22 #include <BRepCheck_Face.hxx>
23 #include <BRepCheck_Shell.hxx>
24 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
25
26 #include <TopoDS_Iterator.hxx>
27 #include <TopExp_Explorer.hxx>
28
29 #include <TopTools_MapOfShape.hxx>
30 #include <TopoDS.hxx>
31 #include <TopoDS_Face.hxx>
32
33 #include <Standard_ErrorHandler.hxx>
34 #include <Standard_Failure.hxx>
35
36 //=======================================================================
37 //function : Init
38 //purpose  : 
39 //=======================================================================
40
41 void BRepCheck_Analyzer::Init(const TopoDS_Shape& S,
42                               const Standard_Boolean B)
43 {
44   if (S.IsNull()) {
45     Standard_NullObject::Raise();
46   }
47   myShape = S;
48   myMap.Clear();
49   Put(S,B);
50   Perform(S);
51 }
52
53
54
55 //=======================================================================
56 //function : Put
57 //purpose  : 
58 //=======================================================================
59
60 void BRepCheck_Analyzer::Put(const TopoDS_Shape& S,
61                              const Standard_Boolean B)
62 {
63   if (!myMap.IsBound(S)) {
64     Handle(BRepCheck_Result) HR;
65     switch (S.ShapeType()) {
66     case TopAbs_VERTEX:
67       HR = new BRepCheck_Vertex(TopoDS::Vertex(S));
68       break;
69     case TopAbs_EDGE:
70       HR = new BRepCheck_Edge(TopoDS::Edge(S));
71       Handle(BRepCheck_Edge)::DownCast(HR)->GeometricControls(B);
72       break;
73     case TopAbs_WIRE:
74       HR = new BRepCheck_Wire(TopoDS::Wire(S));
75       Handle(BRepCheck_Wire)::DownCast(HR)->GeometricControls(B);
76       break;
77     case TopAbs_FACE:
78       HR = new BRepCheck_Face(TopoDS::Face(S));
79       Handle(BRepCheck_Face)::DownCast(HR)->GeometricControls(B);
80       break;
81     case TopAbs_SHELL:
82       HR = new BRepCheck_Shell(TopoDS::Shell(S));
83       break;
84     case TopAbs_SOLID:
85     case TopAbs_COMPSOLID:
86     case TopAbs_COMPOUND:
87       break;
88     default:
89       break;
90     }
91     myMap.Bind(S,HR);
92     for(TopoDS_Iterator theIterator(S);theIterator.More();theIterator.Next()) {
93       Put(theIterator.Value(),B); // performs minimum on each shape
94     }
95   }
96 }
97
98
99 //=======================================================================
100 //function : Perform
101 //purpose  : 
102 //=======================================================================
103
104 void BRepCheck_Analyzer::Perform(const TopoDS_Shape& S)
105 {
106   for(TopoDS_Iterator theIterator(S);theIterator.More();theIterator.Next()) 
107     Perform(theIterator.Value());
108   
109   //
110   TopAbs_ShapeEnum styp;
111   TopExp_Explorer exp;
112   //
113   styp = S.ShapeType();
114   
115   switch (styp) 
116   {
117   case TopAbs_VERTEX: 
118     // modified by NIZHNY-MKK  Wed May 19 16:56:16 2004.BEGIN
119     // There is no need to check anything.
120     //       if (myShape.IsSame(S)) {
121     //  myMap(S)->Blind();
122     //       }
123     // modified by NIZHNY-MKK  Wed May 19 16:56:23 2004.END
124   
125     break;
126   case TopAbs_EDGE:
127     {
128       Handle(BRepCheck_Result)& aRes = myMap(S);
129
130       try
131       {
132         BRepCheck_Status ste = Handle(BRepCheck_Edge)::
133           DownCast(aRes)->CheckPolygonOnTriangulation(TopoDS::Edge(S));
134
135         if(ste != BRepCheck_NoError)
136         {
137           Handle(BRepCheck_Edge)::DownCast(aRes)->SetStatus(ste);
138         }
139       }
140       catch(Standard_Failure)
141       {
142 #ifdef DEB
143         cout<<"BRepCheck_Analyzer : ";
144         Standard_Failure::Caught()->Print(cout);  
145         cout<<endl;
146 #endif
147         if ( ! myMap(S).IsNull() )
148         {
149           myMap(S)->SetFailStatus(S);
150         }
151
152         if ( ! aRes.IsNull() )
153         {
154           aRes->SetFailStatus(exp.Current());
155           aRes->SetFailStatus(S);
156         }
157       }
158
159       TopTools_MapOfShape MapS;
160       
161       for (exp.Init(S,TopAbs_VERTEX);exp.More(); exp.Next())
162       {
163         const TopoDS_Shape& aVertex = exp.Current();
164         try
165         {
166           OCC_CATCH_SIGNALS
167           if (MapS.Add(aVertex))
168             myMap(aVertex)->InContext(S);
169         }
170         catch(Standard_Failure)
171         {
172 #ifdef DEB
173           cout<<"BRepCheck_Analyzer : ";
174           Standard_Failure::Caught()->Print(cout);  
175           cout<<endl;
176 #endif
177           if ( ! myMap(S).IsNull() )
178             myMap(S)->SetFailStatus(S);
179
180           Handle(BRepCheck_Result) aRes = myMap(aVertex);
181
182           if ( ! aRes.IsNull() ) 
183           {
184             aRes->SetFailStatus(aVertex);
185             aRes->SetFailStatus(S);
186           }
187         }//catch(Standard_Failure)
188       }//for (exp.Init(S,TopAbs_VERTEX);exp.More(); exp.Next())
189     }
190     break;
191   case TopAbs_WIRE:
192     {
193     }
194     break;
195   case TopAbs_FACE:
196     {
197       TopTools_MapOfShape MapS;
198       for (exp.Init(S,TopAbs_VERTEX);exp.More(); exp.Next())
199       {
200         try
201         {
202           OCC_CATCH_SIGNALS
203           if (MapS.Add(exp.Current()))
204           {
205             myMap(exp.Current())->InContext(S);
206           }
207         }
208         catch(Standard_Failure)
209         {
210 #ifdef DEB
211           cout<<"BRepCheck_Analyzer : ";
212           Standard_Failure::Caught()->Print(cout);  
213           cout<<endl;
214 #endif
215           if ( ! myMap(S).IsNull() )
216           {
217             myMap(S)->SetFailStatus(S);
218           }
219           
220           Handle(BRepCheck_Result) aRes = myMap(exp.Current());
221
222           if ( ! aRes.IsNull() )
223           {
224             aRes->SetFailStatus(exp.Current());
225             aRes->SetFailStatus(S);
226           }
227         }
228       }
229
230       Standard_Boolean performwire = Standard_True;
231       Standard_Boolean isInvalidTolerance = Standard_False;
232       MapS.Clear();
233       for (exp.Init(S,TopAbs_EDGE);exp.More(); exp.Next())
234       {
235         try
236         {
237           OCC_CATCH_SIGNALS
238           if (MapS.Add(exp.Current()))
239           {
240             Handle(BRepCheck_Result)& res = myMap(exp.Current());
241             res->InContext(S);
242             if (performwire)
243             {
244               for ( res->InitContextIterator();
245                     res->MoreShapeInContext();
246                     res->NextShapeInContext())
247               {
248                 if(res->ContextualShape().IsSame(S))
249                   break;
250               }
251
252               BRepCheck_ListIteratorOfListOfStatus itl(res->StatusOnShape());
253               for (; itl.More(); itl.Next())
254               {
255                 BRepCheck_Status ste = itl.Value();
256                 if (ste == BRepCheck_NoCurveOnSurface  ||
257                     ste == BRepCheck_InvalidCurveOnSurface ||
258                     ste == BRepCheck_InvalidRange ||
259                     ste == BRepCheck_InvalidCurveOnClosedSurface)
260                 {
261                   performwire = Standard_False;
262                   break;
263                 }
264               }
265             }
266           }
267         }
268         catch(Standard_Failure)
269         {
270 #ifdef DEB
271           cout<<"BRepCheck_Analyzer : ";
272           Standard_Failure::Caught()->Print(cout);  
273           cout<<endl;
274 #endif
275           if ( ! myMap(S).IsNull() )
276           {
277             myMap(S)->SetFailStatus(S);
278           }
279
280           Handle(BRepCheck_Result) aRes = myMap(exp.Current());
281
282           if ( ! aRes.IsNull() )
283           {
284             aRes->SetFailStatus(exp.Current());
285             aRes->SetFailStatus(S);
286           }
287         }
288       }
289
290       Standard_Boolean orientofwires = performwire;
291       for (exp.Init(S,TopAbs_WIRE);exp.More(); exp.Next())
292       {
293         try
294         {
295           OCC_CATCH_SIGNALS
296           Handle(BRepCheck_Result)& res = myMap(exp.Current());
297           res->InContext(S);
298           if (orientofwires)
299           {
300             for ( res->InitContextIterator();
301                   res->MoreShapeInContext();
302                   res->NextShapeInContext())
303             {
304               if(res->ContextualShape().IsSame(S))
305               {
306                 break;
307               }
308             }
309             BRepCheck_ListIteratorOfListOfStatus itl(res->StatusOnShape());
310             for (; itl.More(); itl.Next())
311             {
312               BRepCheck_Status ste = itl.Value();
313               if (ste != BRepCheck_NoError)
314               {
315                 orientofwires = Standard_False;
316                 break;
317               }
318             }
319           }
320         }
321         catch(Standard_Failure)
322         {
323 #ifdef DEB
324           cout<<"BRepCheck_Analyzer : ";
325           Standard_Failure::Caught()->Print(cout);  
326           cout<<endl;
327 #endif
328           if ( ! myMap(S).IsNull() )
329           {
330             myMap(S)->SetFailStatus(S);
331           }
332
333           Handle(BRepCheck_Result) aRes = myMap(exp.Current());
334
335           if ( ! aRes.IsNull() )
336           {
337             aRes->SetFailStatus(exp.Current());
338             aRes->SetFailStatus(S);
339           }
340         }
341       }
342
343       try
344       {
345         OCC_CATCH_SIGNALS
346         if(isInvalidTolerance)
347         {
348           Handle(BRepCheck_Face)::
349               DownCast(myMap(S))->SetStatus(BRepCheck_InvalidToleranceValue);
350         }
351         else if (performwire)
352         {
353           if (orientofwires)
354           {
355             Handle(BRepCheck_Face)::DownCast(myMap(S))->
356                         OrientationOfWires(Standard_True);// on enregistre
357           }
358           else
359           {
360             Handle(BRepCheck_Face)::DownCast(myMap(S))->SetUnorientable();
361           }
362         }
363         else
364         {
365           Handle(BRepCheck_Face)::DownCast(myMap(S))->SetUnorientable();
366         }
367       }
368       catch(Standard_Failure)
369       {
370 #ifdef DEB
371         cout<<"BRepCheck_Analyzer : ";
372         Standard_Failure::Caught()->Print(cout);  
373         cout<<endl;
374 #endif
375         if ( ! myMap(S).IsNull() )
376         {
377           myMap(S)->SetFailStatus(S);
378         }
379
380         for (exp.Init(S,TopAbs_WIRE);exp.More(); exp.Next())
381         {
382           Handle(BRepCheck_Result) aRes = myMap(exp.Current());
383           
384           if ( ! aRes.IsNull() )
385           {
386             aRes->SetFailStatus(exp.Current());
387             aRes->SetFailStatus(S);
388             myMap(S)->SetFailStatus(exp.Current());
389           }
390         }
391       }
392     }
393     break;
394     
395   case TopAbs_SHELL:   
396     //modified by NIZNHY-PKV Mon Oct 13 14:23:53 2008f
397     //modified by NIZNHY-PKV Mon Oct 13 14:24:04 2008t
398     break;
399
400   case TopAbs_SOLID:
401     {
402     exp.Init(S,TopAbs_SHELL);
403       for (; exp.More(); exp.Next())
404       {
405       const TopoDS_Shape& aShell=exp.Current();
406         try 
407         {
408         OCC_CATCH_SIGNALS
409         myMap(aShell)->InContext(S);
410       }
411         catch(Standard_Failure)
412         {
413 #ifdef DEB
414         cout<<"BRepCheck_Analyzer : ";
415         Standard_Failure::Caught()->Print(cout);  
416         cout<<endl;
417 #endif
418           if ( ! myMap(S).IsNull() )
419           {
420           myMap(S)->SetFailStatus(S);
421         }
422
423         //
424         Handle(BRepCheck_Result) aRes = myMap(aShell);
425           if (!aRes.IsNull() )
426           {
427           aRes->SetFailStatus(exp.Current());
428           aRes->SetFailStatus(S);
429         }
430         }//catch(Standard_Failure)
431       }//for (; exp.More(); exp.Next())
432       }
433   break;//case TopAbs_SOLID
434   default:
435     break;
436   }//switch (styp) {
437 }
438
439
440 //=======================================================================
441 //function : IsValid
442 //purpose  : 
443 //=======================================================================
444
445 Standard_Boolean BRepCheck_Analyzer::IsValid(const TopoDS_Shape& S) const
446 {
447   if (!myMap(S).IsNull()) {
448     BRepCheck_ListIteratorOfListOfStatus itl;
449     itl.Initialize(myMap(S)->Status());
450     if (itl.Value() != BRepCheck_NoError) { // a voir
451       return Standard_False;
452     }
453   }
454
455   for(TopoDS_Iterator theIterator(S);theIterator.More();theIterator.Next()) {
456     if (!IsValid(theIterator.Value())) {
457       return Standard_False;
458     }
459   }
460
461   switch (S.ShapeType()) {
462   case TopAbs_EDGE:
463     {
464       return ValidSub(S,TopAbs_VERTEX);
465     }
466 //    break;
467   case TopAbs_FACE:
468     {
469       Standard_Boolean valid = ValidSub(S,TopAbs_WIRE);
470       valid = valid && ValidSub(S,TopAbs_EDGE);
471       valid = valid && ValidSub(S,TopAbs_VERTEX);
472       return valid;
473     }
474
475 //    break;
476   case TopAbs_SHELL:
477 //    return ValidSub(S,TopAbs_FACE);
478     break;
479   case TopAbs_SOLID:
480 //    return ValidSub(S,TopAbs_EDGE);
481 //    break;
482     return ValidSub(S,TopAbs_SHELL);
483     break;
484   default:
485     break;
486   }
487
488   return Standard_True;
489 }
490
491 //=======================================================================
492 //function : ValidSub
493 //purpose  : 
494 //=======================================================================
495
496 Standard_Boolean BRepCheck_Analyzer::ValidSub
497    (const TopoDS_Shape& S,
498     const TopAbs_ShapeEnum SubType) const
499 {
500   BRepCheck_ListIteratorOfListOfStatus itl;
501   TopExp_Explorer exp;
502   for (exp.Init(S,SubType);exp.More(); exp.Next()) {
503 //  for (TopExp_Explorer exp(S,SubType);exp.More(); exp.Next()) {
504     const Handle(BRepCheck_Result)& RV = myMap(exp.Current());
505     for (RV->InitContextIterator();
506          RV->MoreShapeInContext(); 
507          RV->NextShapeInContext()) {
508       if (RV->ContextualShape().IsSame(S)) {
509         break;
510       }
511     }
512
513     if(!RV->MoreShapeInContext()) break;
514
515     for (itl.Initialize(RV->StatusOnShape()); itl.More(); itl.Next()) {
516       if (itl.Value() != BRepCheck_NoError) {
517         return Standard_False;
518       }
519     }
520   }
521   return Standard_True ;
522 }