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