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