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