0028646: Draw Harness, ViewerTest - rename vsetfilter command with vselfilter
[occt.git] / src / BRepCheck / BRepCheck_Shell.cxx
1 // Created on: 1995-12-12
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 <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRepCheck.hxx>
21 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
22 #include <BRepCheck_ListOfStatus.hxx>
23 #include <BRepCheck_Shell.hxx>
24 #include <Standard_Type.hxx>
25 #include <TopExp.hxx>
26 #include <TopExp_Explorer.hxx>
27 #include <TopoDS.hxx>
28 #include <TopoDS_Edge.hxx>
29 #include <TopoDS_Face.hxx>
30 #include <TopoDS_Shape.hxx>
31 #include <TopoDS_Shell.hxx>
32 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
33 #include <TopTools_DataMapOfShapeInteger.hxx>
34 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
35 #include <TopTools_ListIteratorOfListOfShape.hxx>
36 #include <TopTools_ListOfShape.hxx>
37 #include <TopTools_MapIteratorOfMapOfShape.hxx>
38 #include <TopTools_MapOfShape.hxx>
39
40 IMPLEMENT_STANDARD_RTTIEXT(BRepCheck_Shell,BRepCheck_Result)
41
42 //=======================================================================
43 //function : Propagate
44 //purpose  : 
45 //=======================================================================
46 static void Propagate(const TopTools_IndexedDataMapOfShapeListOfShape& mapEF,
47                       const TopoDS_Shape& theFace,
48                       TopTools_IndexedMapOfShape& theMapF)
49 {
50   // Base for the traverse procedure.
51   theMapF.Add(theFace);
52
53   // Perform well-known width-first traverse.
54   for (Standard_Integer anIdx = 1; anIdx <= theMapF.Extent(); ++anIdx)
55   {
56     const TopoDS_Shape& aFace = theMapF(anIdx);
57     for (TopExp_Explorer ex(aFace, TopAbs_EDGE); ex.More(); ex.Next())
58     {
59       const TopoDS_Edge& edg = TopoDS::Edge(ex.Current());
60
61       // Test if the edge is in the map (only oriented edges are present).
62       const TopTools_ListOfShape* aList = mapEF.Seek(edg);
63
64       if ( aList == NULL )
65         continue;
66
67       for (TopTools_ListIteratorOfListOfShape itl(*aList); itl.More(); itl.Next())
68       {
69         // This code assumes that shape is added to an end of the map.
70         // The idea is simple: existing objects will not be added, new objects
71         // will be added to an end.
72         theMapF.Add(itl.Value());
73       }
74     }
75   }
76 }
77
78 //=======================================================================
79 //function : BRepCheck_Trace
80 //purpose  : 
81 //=======================================================================
82 Standard_EXPORT Standard_Integer BRepCheck_Trace(const Standard_Integer phase) {
83   static int BRC_Trace = 0;
84   if (phase < 0) BRC_Trace =0;
85   else if (phase > 0) BRC_Trace=phase;
86   return BRC_Trace;
87 }
88
89 void PrintShape(const TopoDS_Shape& theShape, const Standard_Integer upper) {
90   if (!theShape.IsNull()) {
91     Standard_Integer code = theShape.HashCode(upper);
92     std::cout << TopAbs::ShapeTypeToString (theShape.ShapeType()) << " : " << code
93        << " " << TopAbs::ShapeOrientationToString(theShape.Orientation()) << std::endl;
94   }
95 }
96     
97 //=======================================================================
98 //function : IsOriented
99 //purpose  : 
100 //=======================================================================
101 inline Standard_Boolean IsOriented(const TopoDS_Shape& S)
102 {
103   return (S.Orientation() == TopAbs_FORWARD ||
104           S.Orientation() == TopAbs_REVERSED);
105 }
106
107
108 //=======================================================================
109 //function : BRepCheck_Shell
110 //purpose  : 
111 //=======================================================================
112
113 BRepCheck_Shell::BRepCheck_Shell(const TopoDS_Shell& S)
114 {
115   Init(S);
116 }
117
118
119 //=======================================================================
120 //function : Minimum
121 //purpose  : 
122 //=======================================================================
123 void BRepCheck_Shell::Minimum()
124 {
125   myCdone = Standard_False;
126   myOdone = Standard_False;
127
128   if (!myMin)
129   {
130     BRepCheck_ListOfStatus thelist;
131     myMap.Bind(myShape, thelist);
132     BRepCheck_ListOfStatus& lst = myMap(myShape);
133
134     // it is checked if the shell is "connected"
135     TopExp_Explorer exp(myShape,TopAbs_FACE);
136     Standard_Integer nbface = 0;
137     myMapEF.Clear();
138     for (; exp.More(); exp.Next())
139     {
140       nbface++;
141       TopExp_Explorer expe;
142       for (expe.Init(exp.Current(),TopAbs_EDGE);
143                         expe.More(); expe.Next())
144       {
145         const TopoDS_Shape& edg = expe.Current();
146         Standard_Integer index = myMapEF.FindIndex(edg);
147         if (index == 0)
148         {
149           TopTools_ListOfShape thelist1;
150           index = myMapEF.Add(edg, thelist1);
151         }
152
153         myMapEF(index).Append(exp.Current());
154       }
155     }//for (; exp.More(); exp.Next())
156
157     if (nbface == 0)
158     {
159       BRepCheck::Add(lst,BRepCheck_EmptyShell);
160     }
161     else if (nbface >= 2)
162     {
163       TopTools_IndexedMapOfShape mapF;
164       exp.ReInit();
165
166       Propagate(myMapEF,exp.Current(),mapF);
167
168       if (mapF.Extent() != nbface)
169       {
170         BRepCheck::Add(lst,BRepCheck_NotConnected);
171       }
172     }//else if (nbface >= 2)
173
174     if (lst.IsEmpty())
175     {
176       lst.Append(BRepCheck_NoError);
177     }
178     
179     myMapEF.Clear();
180     myMin = Standard_True;
181   }
182 }
183
184 //=======================================================================
185 //function : InContext
186 //purpose  : 
187 //=======================================================================
188
189 void BRepCheck_Shell::InContext(const TopoDS_Shape& S)
190 {
191
192   if (myMap.IsBound(S)) {
193     return;
194   }
195   BRepCheck_ListOfStatus thelist;
196   myMap.Bind(S, thelist);
197
198   BRepCheck_ListOfStatus& lst = myMap(S);
199
200 //  for (TopExp_Explorer exp(S,TopAbs_SHELL); exp.More(); exp.Next()) {
201   TopExp_Explorer exp(S,TopAbs_SHELL) ;
202   for ( ; exp.More(); exp.Next()) {
203     if (exp.Current().IsSame(myShape)) {
204       break;
205     }
206   }
207   if (!exp.More()) {
208     BRepCheck::Add(lst,BRepCheck_SubshapeNotInShape);
209     return;
210   }
211
212   TopAbs_ShapeEnum styp = S.ShapeType();
213   switch (styp) {
214
215   case TopAbs_SOLID:
216     {
217       BRepCheck_Status fst = Closed();
218       if ((fst == BRepCheck_NotClosed && S.Closed()) ||
219           (fst != BRepCheck_NoError)) {
220         BRepCheck::Add(lst,fst);
221       }
222       else if (!IsUnorientable()) {
223         fst = Orientation();
224         BRepCheck::Add(lst,fst);
225       }
226     }
227     break;
228
229   default:
230     break;
231   }
232
233
234   if (lst.IsEmpty()) {
235     lst.Append(BRepCheck_NoError);
236   }
237 }
238
239
240 //=======================================================================
241 //function : Blind
242 //purpose  : 
243 //=======================================================================
244
245 void BRepCheck_Shell::Blind()
246 {
247   if (!myBlind) {
248     // nothing more than in the minimum
249     myBlind = Standard_True;
250   }
251 }
252
253
254 //=======================================================================
255 //function : Closed
256 //purpose  : 
257 //=======================================================================
258 BRepCheck_Status BRepCheck_Shell::Closed(const Standard_Boolean Update)
259 {
260   if (myCdone)
261   {
262     if (Update)
263     {
264       BRepCheck::Add(myMap(myShape), myCstat);
265     }
266
267     return myCstat;
268   }
269
270   myCdone = Standard_True; // it will be done...
271
272   BRepCheck_ListIteratorOfListOfStatus itl(myMap(myShape));
273   if (itl.Value() != BRepCheck_NoError)
274   {
275     myCstat = itl.Value();
276     return myCstat; // already saved
277   }
278
279   myCstat = BRepCheck_NoError;
280   //
281   Standard_Integer index, aNbF;
282   TopExp_Explorer exp, ede;
283   TopTools_IndexedMapOfShape mapS;
284   TopTools_MapOfShape aMEToAvoid;
285   myMapEF.Clear();
286   
287
288   // Checks if the oriented faces of the shell give a "closed" shell,
289   // i-e if each oriented edge on oriented faces is found 2 times.
290   //
291   //modified by NIZNHY-PKV Mon Jun  4 13:59:21 2007f
292   exp.Init(myShape,TopAbs_FACE);
293   for (; exp.More(); exp.Next())
294   {
295     const TopoDS_Shape& aF=exp.Current();
296     if (IsOriented(aF))
297     {
298       ede.Init(exp.Current(),TopAbs_EDGE);
299       for (; ede.More(); ede.Next())
300       {
301         const TopoDS_Shape& aE=ede.Current();
302         if (!IsOriented(aE))
303         {
304           aMEToAvoid.Add(aE);
305         }
306       }
307     }
308   }
309   //modified by NIZNHY-PKV Mon Jun  4 13:59:23 2007t
310   //
311   exp.Init(myShape,TopAbs_FACE);
312   for (; exp.More(); exp.Next())
313   {
314     const TopoDS_Shape& aF=exp.Current();
315     if (IsOriented(aF))
316     {
317       if (!mapS.Add(aF))
318       {
319         myCstat = BRepCheck_RedundantFace;
320         
321         if (Update)
322         {
323           BRepCheck::Add(myMap(myShape),myCstat);
324         }
325
326         return myCstat;
327       }
328
329       //
330       ede.Init(exp.Current(),TopAbs_EDGE);
331       for (; ede.More(); ede.Next())
332       {
333         const TopoDS_Shape& aE=ede.Current();
334         //modified by NIZNHY-PKV Mon Jun  4 14:07:57 2007f
335         //if (IsOriented(aE)) {
336         if (!aMEToAvoid.Contains(aE))
337         {
338           //modified by NIZNHY-PKV Mon Jun  4 14:08:01 2007
339           index = myMapEF.FindIndex(aE);
340           
341           if (!index)
342           {
343             TopTools_ListOfShape thelist;
344             index = myMapEF.Add(aE, thelist);
345           }
346
347           myMapEF(index).Append(aF);
348         }
349       }
350     }
351   }
352
353   //
354   myNbori = mapS.Extent();
355   if (myNbori >= 2)
356   {
357     mapS.Clear();
358     // Search for the first oriented face
359     TopoDS_Shape aF;
360     exp.Init(myShape, TopAbs_FACE);
361     for (;exp.More(); exp.Next())
362     {
363       aF=exp.Current();
364       if (IsOriented(aF))
365       {
366         break;
367       }
368     }
369
370     Propagate(myMapEF, aF, mapS);
371   }
372   //
373
374   //
375   aNbF=mapS.Extent();
376   if (myNbori != aNbF)
377   {
378     myCstat = BRepCheck_NotConnected;
379     if (Update)
380     {
381       BRepCheck::Add(myMap(myShape),myCstat);
382     }
383     return myCstat;
384   }
385   //
386   //
387   Standard_Integer i, Nbedges, nboc, nbSet;
388   //
389   Nbedges = myMapEF.Extent();
390   for (i = 1; i<=Nbedges; ++i)
391   {
392     nboc = myMapEF(i).Extent();
393     if (nboc == 0 || nboc >= 3)
394     {
395       TopTools_ListOfShape theSet;
396       nbSet=NbConnectedSet(theSet);
397       // If there is more than one closed cavity the shell is considered invalid
398       // this corresponds to the criteria of a solid (not those of a shell)
399       if (nbSet>1)
400       {
401         myCstat = BRepCheck_InvalidMultiConnexity;
402         if (Update)
403         {
404           BRepCheck::Add(myMap(myShape),myCstat);
405         }
406
407         return myCstat;
408       }
409     }
410     else if (nboc == 1)
411     {
412       if (!BRep_Tool::Degenerated(TopoDS::Edge(myMapEF.FindKey(i))))
413       {
414         myCstat=BRepCheck_NotClosed;
415         if (Update)
416         {
417           BRepCheck::Add(myMap(myShape),myCstat);
418         }
419
420         return myCstat;
421       }
422     }
423   }
424   
425   if (Update) {
426     BRepCheck::Add(myMap(myShape),myCstat);
427   }
428   return myCstat;
429 }
430
431
432 //=======================================================================
433 //function : Orientation
434 //purpose  : 
435 //=======================================================================
436
437 BRepCheck_Status BRepCheck_Shell::Orientation(const Standard_Boolean Update)
438 {
439   if (myOdone) {
440     if (Update) {
441       BRepCheck::Add(myMap(myShape), myOstat);
442     }
443     return myOstat;
444   }
445   myOdone = Standard_True;
446
447   myOstat = Closed();
448   if (myOstat != BRepCheck_NotClosed && myOstat != BRepCheck_NoError) {
449     if (Update) {
450       BRepCheck::Add(myMap(myShape), myOstat);
451     }
452     return myOstat;
453   }
454
455   myOstat = BRepCheck_NoError;
456
457
458 // First the orientation of each face in relation to the shell is found.
459 // It is used to check BRepCheck_RedundantFace
460
461   TopTools_DataMapOfShapeInteger MapOfShapeOrientation;
462   TopExp_Explorer exp,ede;
463
464   for (exp.Init(myShape,TopAbs_FACE); exp.More(); exp.Next()) {
465     if (!MapOfShapeOrientation.Bind(exp.Current(), (Standard_Integer)(exp.Current().Orientation()))) {
466       myOstat = BRepCheck_RedundantFace;
467       if (Update) {
468         BRepCheck::Add(myMap(myShape), myOstat);
469       }
470       else {
471         return myOstat;
472       }
473     }
474   }
475
476 #ifdef OCCT_DEBUG
477   if (BRepCheck_Trace(0) > 1) {
478     TopTools_DataMapIteratorOfDataMapOfShapeInteger itt(MapOfShapeOrientation);
479     Standard_Integer upper = MapOfShapeOrientation.NbBuckets();
480     cout << "La map shape Orientation :" << endl;
481     for (; itt.More(); itt.Next()) {
482       PrintShape(itt.Key(), upper);
483     }
484     cout << endl;
485   }
486 #endif
487
488
489 // Then the orientation of faces by their connectivity is checked
490 // BRepCheck_BadOrientationOfSubshape and 
491 //         BRepCheck_SubshapeNotInShape are checked;
492
493   Standard_Integer Nbedges = myMapEF.Extent();
494   TopoDS_Face Fref;
495   TopAbs_Orientation orf;
496
497   for (Standard_Integer i = 1; i<= Nbedges; i++) {
498
499     const TopoDS_Edge& edg = TopoDS::Edge(myMapEF.FindKey(i));
500     if (BRep_Tool::Degenerated(edg)) continue;
501     TopTools_ListOfShape& lface = myMapEF(i);
502     TopTools_ListIteratorOfListOfShape lite(lface);
503
504     if (lface.Extent() <= 2)
505       {
506         lite.Initialize(lface);
507         Fref = TopoDS::Face(lite.Value());
508         
509         if (!MapOfShapeOrientation.IsBound(Fref)) {
510           myOstat = BRepCheck_SubshapeNotInShape;
511           if (Update) {
512             BRepCheck::Add(myMap(myShape), myOstat);
513             }
514           // quit because no workaround for the incoherence is possible
515           return myOstat;
516         }
517         lite.Next();
518         
519         if (lite.More()) { // Edge of connectivity
520           //JR/Hp :
521           Standard_Integer iorf = MapOfShapeOrientation.Find(Fref);
522           orf = (TopAbs_Orientation) iorf;
523           //orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fref);
524           Fref.Orientation(orf);
525           
526           // edge is examined
527           if (!lite.Value().IsSame(Fref)) { // edge non "closed"
528             for (ede.Init(Fref,TopAbs_EDGE); ede.More(); ede.Next()) {
529               if (ede.Current().IsSame(edg)) {
530                 break;
531               }
532             }
533             TopAbs_Orientation orient = ede.Current().Orientation();
534             TopoDS_Face Fcur= TopoDS::Face(lite.Value());
535             
536             if (!MapOfShapeOrientation.IsBound(Fcur)) {
537               myOstat = BRepCheck_SubshapeNotInShape;
538               if (Update) {
539                 BRepCheck::Add(myMap(myShape), myOstat);
540                 }
541               // quit because no workaround for the incoherence is possible
542               return myOstat;
543             }
544             
545             //JR/Hp :
546             Standard_Integer anOriFCur = MapOfShapeOrientation.Find(Fcur) ;
547             orf = (TopAbs_Orientation)anOriFCur;
548             //  orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fcur);
549             Fcur.Orientation(orf);
550             
551             for (ede.Init(Fcur, TopAbs_EDGE); ede.More(); ede.Next()) {
552               if (ede.Current().IsSame(edg)) {
553                 break;
554               }
555             }
556             if (ede.Current().Orientation() == orient) {
557               // The loop is continued on the edges as many times 
558               // as the same edge is present in the wire
559
560               // modified by NIZHNY-MKK  Tue Sep 30 11:11:42 2003
561               Standard_Boolean bfound = Standard_False;
562               ede.Next();
563               for (; ede.More(); ede.Next()) {
564                 if (ede.Current().IsSame(edg)) {
565                   // modified by NIZHNY-MKK  Tue Sep 30 11:12:03 2003
566                   bfound = Standard_True;
567                   break;
568                 }
569               }
570               //              if (ede.Current().Orientation() == orient) {
571               // modified by NIZHNY-MKK  Thu Oct  2 17:56:47 2003
572               if (!bfound || (ede.Current().Orientation() == orient)) {
573                 myOstat = BRepCheck_BadOrientationOfSubshape;
574                 if (Update) {
575                   BRepCheck::Add(myMap(myShape), myOstat);
576                     break;
577                   }
578                 return myOstat;
579               }
580             }
581           }
582         }
583       }
584     else //more than two faces
585       {
586         Standard_Integer numF = 0, numR = 0;
587         TopTools_MapOfShape Fmap;
588
589         for (lite.Initialize(lface); lite.More(); lite.Next())
590           {
591             TopoDS_Face Fcur= TopoDS::Face(lite.Value());
592             if (!MapOfShapeOrientation.IsBound(Fcur))
593               {
594                 myOstat = BRepCheck_SubshapeNotInShape;
595                 if (Update)
596                   BRepCheck::Add(myMap(myShape), myOstat);
597               // quit because no workaround for the incoherence is possible
598                 return myOstat;
599               }
600
601             Standard_Integer iorf = MapOfShapeOrientation.Find(Fcur);
602             orf = (TopAbs_Orientation) iorf;
603             //orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fcur);
604             Fcur.Orientation(orf);
605
606             for (ede.Init(Fcur,TopAbs_EDGE); ede.More(); ede.Next())
607               if (ede.Current().IsSame(edg))
608                 break;
609             if (Fmap.Contains(Fcur)) //edge is "closed" on Fcur, we meet Fcur twice
610               {
611                 ede.Next();
612                 for (; ede.More(); ede.Next())
613                   if (ede.Current().IsSame(edg))
614                     break;
615               }
616             TopAbs_Orientation orient = ede.Current().Orientation();
617             if (orient == TopAbs_FORWARD)
618               numF++;
619             else
620               numR++;
621
622             Fmap.Add(Fcur);
623           }
624
625         if (numF != numR)
626           {
627             myOstat = BRepCheck_BadOrientationOfSubshape;
628             if (Update)
629               {
630                 BRepCheck::Add(myMap(myShape), myOstat);
631                 break;
632               }
633             return myOstat;
634           }
635       }
636   }
637
638 // If at least one incorrectly oriented face has been found, it is checked if the shell can be oriented. 
639 //          i.e. : if by modification of the orientation of a face it is possible to find 
640 //          a coherent orientation. (it is not possible on a Moebius band)
641 //          BRepCheck_UnorientableShape is checked
642
643   if (myOstat == BRepCheck_BadOrientationOfSubshape) {
644     if (!Fref.IsNull()) {
645       if (Nbedges > 0) {
646         TopTools_MapOfShape alre;
647         TopTools_ListOfShape voisin;
648         voisin.Append(Fref);
649         alre.Clear();
650         while (!voisin.IsEmpty()) {
651           Fref=TopoDS::Face(voisin.First());
652           voisin.RemoveFirst();
653           if (!MapOfShapeOrientation.IsBound(Fref)) {
654             myOstat = BRepCheck_SubshapeNotInShape;
655             if (Update) {
656               BRepCheck::Add(myMap(myShape), myOstat);
657             }
658             // quit because no workaround for the incoherence is possible
659             return myOstat;
660           }
661 //JR/Hp :
662           Standard_Integer iorf = MapOfShapeOrientation.Find(Fref) ;
663           orf = (TopAbs_Orientation) iorf ;
664 //        orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fref);
665           Fref.Orientation(orf);
666
667 #ifdef OCCT_DEBUG
668   if (BRepCheck_Trace(0) > 3) {
669     cout << "Fref : " ;
670     PrintShape(Fref, MapOfShapeOrientation.NbBuckets());
671   }
672 #endif
673
674           TopExp_Explorer edFcur;
675           alre.Add(Fref);
676
677           for (ede.Init(Fref,TopAbs_EDGE); ede.More(); ede.Next()) {
678             const TopoDS_Edge& edg = TopoDS::Edge(ede.Current());
679             TopAbs_Orientation orient = edg.Orientation();
680             TopTools_ListOfShape& lface = myMapEF.ChangeFromKey(edg);
681             TopTools_ListIteratorOfListOfShape lite(lface);
682           
683             TopoDS_Face Fcur= TopoDS::Face(lite.Value());
684             if (Fcur.IsSame(Fref)) {
685               lite.Next();
686               if (lite.More()) {
687                 Fcur=TopoDS::Face(lite.Value());
688               }
689               else {
690                 // from the free border one goes to the next edge
691                 continue;
692               }
693             }
694
695             if (!MapOfShapeOrientation.IsBound(Fcur)) {
696               myOstat = BRepCheck_SubshapeNotInShape;
697               if (Update) {
698                 BRepCheck::Add(myMap(myShape), myOstat);
699               }
700               // quit because no workaround for the incoherence is possible
701               return myOstat;
702             }
703
704 //JR/Hp :
705             Standard_Integer anOriFCur = MapOfShapeOrientation.Find(Fcur) ;
706             orf = (TopAbs_Orientation)anOriFCur;
707 //          orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fcur);
708             Fcur.Orientation(orf);
709
710 #ifdef OCCT_DEBUG
711   if (BRepCheck_Trace(0) > 3) {
712     cout << "    Fcur : " ;
713     PrintShape(Fcur, MapOfShapeOrientation.NbBuckets());
714   }
715 #endif
716             for (edFcur.Init(Fcur, TopAbs_EDGE); edFcur.More(); edFcur.Next()) {
717               if (edFcur.Current().IsSame(edg)) {
718                 break;
719               }
720             }
721             if (edFcur.Current().Orientation() == orient) {
722               if (alre.Contains(Fcur)) {
723                 // It is necessary to return a face that has been already examined or returned
724                 // if one gets nowhere, the shell cannot be oriented.
725                 myOstat = BRepCheck_UnorientableShape;
726                 if (Update) {
727                   BRepCheck::Add(myMap(myShape), myOstat);
728                 }
729                 // quit, otherwise there is a risk of taking too much time.
730 #ifdef OCCT_DEBUG
731   if (BRepCheck_Trace(0) > 3) {
732     orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fcur);
733     Fcur.Orientation(orf);
734     cout << "    Error : this face has been already examined " << endl;
735     cout << "    Imposible to return it ";
736     PrintShape(Fcur, MapOfShapeOrientation.NbBuckets());
737   }
738 #endif
739                 return myOstat;
740               }
741               orf = TopAbs::Reverse(orf);
742               MapOfShapeOrientation(Fcur)=orf;
743
744
745 #ifdef OCCT_DEBUG
746   if (BRepCheck_Trace(0) > 3) {
747     orf = (TopAbs_Orientation)MapOfShapeOrientation.Find(Fcur);
748     Fcur.Orientation(orf);
749     cout << "    Resulting Fcur is returned : " ;
750     PrintShape(Fcur, MapOfShapeOrientation.NbBuckets());
751   }
752 #endif
753
754             }
755             if (alre.Add(Fcur)) {
756               voisin.Append(Fcur);
757             }
758           }
759         }
760       }
761     }
762   }
763
764   if (Update) {
765     BRepCheck::Add(myMap(myShape), myOstat);
766   }
767   return myOstat;
768 }
769
770 //=======================================================================
771 //function : SetUnorientable
772 //purpose  : 
773 //=======================================================================
774
775 void BRepCheck_Shell::SetUnorientable()
776 {
777   BRepCheck::Add(myMap(myShape),BRepCheck_UnorientableShape);
778 }
779
780
781 //=======================================================================
782 //function : IsUnorientable
783 //purpose  : 
784 //=======================================================================
785
786 Standard_Boolean BRepCheck_Shell::IsUnorientable() const
787 {
788   if (myOdone) {
789     return (myOstat != BRepCheck_NoError);
790   }
791   for (BRepCheck_ListIteratorOfListOfStatus itl(myMap(myShape));
792        itl.More();
793        itl.Next()) {
794     if (itl.Value() == BRepCheck_UnorientableShape) {
795       return Standard_True;
796     }
797   }
798   return Standard_False;
799 }
800
801 //=======================================================================
802 //function : NbConnectedSet
803 //purpose  : 
804 //=======================================================================
805
806 Standard_Integer BRepCheck_Shell::NbConnectedSet(TopTools_ListOfShape& theSets)
807 {
808   // The connections are found 
809   TopTools_IndexedDataMapOfShapeListOfShape parents;
810   TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, parents);
811   // All faces are taken
812   TopTools_MapOfShape theFaces;
813   TopExp_Explorer exsh(myShape, TopAbs_FACE);
814   for (; exsh.More(); exsh.Next()) theFaces.Add(exsh.Current());
815   // The edges that are not oriented or have more than 2 connections are missing
816   Standard_Integer iCur;
817   TopTools_MapOfShape theMultiEd;
818   TopTools_MapOfShape theUnOriEd;
819   for (iCur=1; iCur<=parents.Extent(); iCur++) {
820     const TopoDS_Edge& Ed = TopoDS::Edge(parents.FindKey(iCur));
821     if (parents(iCur).Extent()> 2) theMultiEd.Add(Ed);
822     if (Ed.Orientation()!=TopAbs_REVERSED &&
823         Ed.Orientation()!=TopAbs_FORWARD) theUnOriEd.Add(Ed);
824   }
825   // Starting from multiconnected edges propagation by simple connections
826   TopTools_ListIteratorOfListOfShape lconx1, lconx2;
827   TopTools_MapIteratorOfMapOfShape itmsh(theMultiEd);
828   TopoDS_Shell CurShell;
829   TopoDS_Shape adFac;
830   TopTools_ListOfShape lesCur;
831   BRep_Builder BRB;
832   Standard_Boolean newCur=Standard_True;
833   BRB.MakeShell(CurShell);
834   for (; itmsh.More(); itmsh.Next()) {
835     const TopoDS_Shape& Ed = itmsh.Key();
836     if (!theUnOriEd.Contains(Ed)) {
837       for (lconx1.Initialize(parents.FindFromKey(Ed)); lconx1.More(); lconx1.Next()) {
838         if (theFaces.Contains(lconx1.Value())) {
839           adFac=lconx1.Value();
840           BRB.Add(CurShell, adFac);
841           theFaces.Remove(adFac);
842           newCur=Standard_False;
843           if (theFaces.IsEmpty()) break;
844           lesCur.Append(adFac);
845           while (!lesCur.IsEmpty()) {
846             adFac=lesCur.First();
847             lesCur.RemoveFirst();
848             for (exsh.Init(adFac, TopAbs_EDGE); exsh.More(); exsh.Next()) {
849               const TopoDS_Shape& ced = exsh.Current();
850               if (!theMultiEd.Contains(ced)) {
851                 for (lconx2.Initialize(parents.FindFromKey(ced)); lconx2.More(); lconx2.Next()) {
852                   if (theFaces.Contains(lconx2.Value())) {
853                     adFac=lconx2.Value();
854                     BRB.Add(CurShell, adFac);
855                     theFaces.Remove(adFac);
856                     newCur=Standard_False;
857                     if (theFaces.IsEmpty()) break;
858                     lesCur.Append(adFac);
859                   }
860                 }
861               }
862               if (theFaces.IsEmpty()) break;
863             }
864           }
865           if (!newCur) {
866             CurShell.Closed (BRep_Tool::IsClosed (CurShell));
867             theSets.Append(CurShell);
868             CurShell.Nullify();
869             newCur=Standard_True;
870             BRB.MakeShell(CurShell);
871           }
872         }
873         if (theFaces.IsEmpty()) break;
874       }
875     }
876     if (theFaces.IsEmpty()) break;
877   }
878   return theSets.Extent();
879 }