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