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