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