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