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