0025748: Parallel version of progress indicator
[occt.git] / src / ShapeFix / ShapeFix_Shell.cxx
1 // Created on: 1998-08-12
2 // Created by: Galina KULIKOVA
3 // Copyright (c) 1998-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 // pdn 17.12.98 ie_exhaust-A.stp
18
19 #include <Bnd_Array1OfBox.hxx>
20 #include <Bnd_Box.hxx>
21 #include <BRep_Builder.hxx>
22 #include <BRep_Tool.hxx>
23 #include <BRepBndLib.hxx>
24 #include <Message_Msg.hxx>
25 #include <Message_ProgressScope.hxx>
26 #include <Precision.hxx>
27 #include <ShapeAnalysis_Shell.hxx>
28 #include <ShapeBuild_ReShape.hxx>
29 #include <ShapeExtend.hxx>
30 #include <ShapeExtend_BasicMsgRegistrator.hxx>
31 #include <ShapeFix_Face.hxx>
32 #include <ShapeFix_Shell.hxx>
33 #include <Standard_Type.hxx>
34 #include <TColStd_DataMapOfIntegerListOfInteger.hxx>
35 #include <TColStd_MapOfInteger.hxx>
36 #include <TColStd_SequenceOfInteger.hxx>
37 #include <TopAbs.hxx>
38 #include <TopExp.hxx>
39 #include <TopExp_Explorer.hxx>
40 #include <TopoDS.hxx>
41 #include <TopoDS_Compound.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <TopoDS_Face.hxx>
44 #include <TopoDS_Iterator.hxx>
45 #include <TopoDS_Shape.hxx>
46 #include <TopoDS_Shell.hxx>
47 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
48 #include <TopTools_DataMapOfShapeInteger.hxx>
49 #include <TopTools_DataMapOfShapeShape.hxx>
50 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
51 #include <TopTools_IndexedDataMapOfShapeShape.hxx>
52 #include <TopTools_IndexedMapOfShape.hxx>
53 #include <TopTools_ListIteratorOfListOfShape.hxx>
54 #include <TopTools_ListOfShape.hxx>
55 #include <TopTools_MapIteratorOfMapOfShape.hxx>
56 #include <TopTools_MapOfShape.hxx>
57 #include <TopTools_SequenceOfShape.hxx>
58
59 IMPLEMENT_STANDARD_RTTIEXT(ShapeFix_Shell,ShapeFix_Root)
60
61 //=======================================================================
62 //function : ShapeFix_Shell
63 //purpose  : 
64 //=======================================================================
65 ShapeFix_Shell::ShapeFix_Shell()
66 {    
67   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
68   myFixFaceMode = -1;
69   myFixOrientationMode = -1;
70   myFixFace = new ShapeFix_Face;
71   myNbShells =0;
72   myNonManifold = Standard_False;
73 }
74
75 //=======================================================================
76 //function : ShapeFix_Shell
77 //purpose  : 
78 //=======================================================================
79
80 ShapeFix_Shell::ShapeFix_Shell(const TopoDS_Shell& shape)
81 {
82   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
83   myFixFaceMode = -1;
84   myFixOrientationMode = -1;
85   myFixFace = new ShapeFix_Face;
86   Init(shape);
87   myNonManifold = Standard_False;
88 }
89
90 //=======================================================================
91 //function : Init
92 //purpose  : 
93 //=======================================================================
94
95 void ShapeFix_Shell::Init(const TopoDS_Shell& shell) 
96 {
97   myShape = shell;
98   myShell = shell;
99   myNbShells =0;
100 }
101
102 //=======================================================================
103 //function : Perform
104 //purpose  : 
105 //=======================================================================
106
107 Standard_Boolean ShapeFix_Shell::Perform(const Message_ProgressRange& theProgress) 
108 {
109   Standard_Boolean status = Standard_False;
110   if ( Context().IsNull() )
111     SetContext(new ShapeBuild_ReShape);
112   myFixFace->SetContext(Context());
113
114   if ( NeedFix(myFixFaceMode) )
115   {
116     TopoDS_Shape S = Context()->Apply(myShell);
117
118     // Get the number of faces for progress indication
119     Standard_Integer aNbFaces = S.NbChildren();
120
121     // Start progress scope (no need to check if progress exists -- it is safe)
122     Message_ProgressScope aPS(theProgress, "Fixing face", aNbFaces);
123
124     for( TopoDS_Iterator iter(S); iter.More() && aPS.More(); iter.Next(), aPS.Next() )
125     { 
126       TopoDS_Shape sh = iter.Value();
127       TopoDS_Face tmpFace = TopoDS::Face(sh);
128       myFixFace->Init(tmpFace);
129       if ( myFixFace->Perform() )
130       {
131         status = Standard_True;
132         myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
133       }
134     }
135
136     // Halt algorithm in case of user's abort
137     if ( !aPS.More() )
138       return Standard_False;
139   }
140
141   TopoDS_Shape newsh = Context()->Apply(myShell);
142   if ( NeedFix ( myFixOrientationMode) )
143     FixFaceOrientation(TopoDS::Shell(newsh), Standard_True, myNonManifold);
144
145   TopoDS_Shape aNewsh = Context()->Apply (newsh);
146   ShapeAnalysis_Shell aSas;
147   for (TopExp_Explorer aShellExp (aNewsh, TopAbs_SHELL); aShellExp.More(); aShellExp.Next())
148   {
149     TopoDS_Shell aCurShell = TopoDS::Shell (aShellExp.Current());
150     if (aCurShell.Closed())
151     {
152       aSas.LoadShells (aCurShell);
153       aSas.CheckOrientedShells (aCurShell, Standard_True);
154       if (aSas.HasFreeEdges())
155       {
156         aCurShell.Closed (Standard_False);
157         SendWarning (Message_Msg ("FixAdvShell.FixClosedFlag.MSG0"));//Shell has incorrect flag isClosed
158       }
159       aSas.Clear();
160         }
161   }
162
163   if ( status )
164     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
165   if(Status(ShapeExtend_DONE2))
166     status = Standard_True;
167   return status;
168 }
169
170 //=======================================================================
171 // function : GetFreeEdges
172 // purpose  : 
173 //=======================================================================
174 static Standard_Boolean GetFreeEdges(const TopoDS_Shape& aShape,TopTools_MapOfShape& MapEdges)
175 {
176   for(TopExp_Explorer aExpF(aShape,TopAbs_FACE); aExpF.More(); aExpF.Next()) {
177     for(TopExp_Explorer aExpE(aExpF.Current(),TopAbs_EDGE); aExpE.More(); aExpE.Next()) {
178       TopoDS_Edge edge = TopoDS::Edge(aExpE.Current());
179       if(!MapEdges.Contains(edge))
180         MapEdges.Add(edge);
181       else  MapEdges.Remove(edge);
182     }
183   }
184   return !MapEdges.IsEmpty();
185 }
186 //=======================================================================
187 // function : GetShells
188 // purpose  : If mode isMultiConnex = Standard_True gets max possible shell for 
189 //            exception of multiconnexity parts.
190 //            Else if this mode is equal to Standard_False maximum possible 
191 //            shell will be created without taking account of multiconnexity.
192 //            In this function map face - shell and sequence of mebius faces is formed.
193 //=======================================================================
194 static  Standard_Boolean GetShells(TopTools_SequenceOfShape& Lface,
195                                    const TopTools_MapOfShape& aMapMultiConnectEdges,
196                                    TopTools_SequenceOfShape& aSeqShells,
197                                    TopTools_DataMapOfShapeShape& aMapFaceShells,
198                                    TopTools_SequenceOfShape& ErrFaces) 
199 {
200   Standard_Boolean done = Standard_False;
201   if(!Lface.Length()) return Standard_False;
202   TopoDS_Shell nshell;
203   TopTools_MapOfShape dire, reve;
204   BRep_Builder B;
205   B.MakeShell(nshell);
206   Standard_Boolean isMultiConnex = !aMapMultiConnectEdges.IsEmpty();
207   Standard_Integer i=1, j=1;
208   TopTools_SequenceOfShape aSeqUnconnectFaces;
209   for( ; i<=Lface.Length(); i++)  {
210     TopTools_MapOfShape dtemp, rtemp;
211     Standard_Integer nbbe=0, nbe = 0;
212     TopoDS_Face F1 = TopoDS::Face(Lface.Value(i));
213     for(TopExp_Explorer expe(F1, TopAbs_EDGE); expe.More(); expe.Next()) {
214       TopoDS_Edge edge = TopoDS::Edge(expe.Current());
215       
216       // if multiconnexity mode is equal to Standard_True faces contains
217       // the same multiconnexity edges are not added to one shell.
218       if(isMultiConnex && aMapMultiConnectEdges.Contains(edge))
219         continue;
220       
221       if((edge.Orientation() == TopAbs_FORWARD && dire.Contains(edge))
222         || (edge.Orientation() == TopAbs_REVERSED && reve.Contains(edge))) 
223         nbbe++;
224       else if((edge.Orientation() == TopAbs_FORWARD && reve.Contains(edge))
225         || (edge.Orientation() == TopAbs_REVERSED && dire.Contains(edge)))   
226         nbe++;
227       
228       if(dire.Contains(edge)) dire.Remove(edge);
229       else 
230         if(reve.Contains(edge)) reve.Remove(edge);
231         else {
232           if(edge.Orientation() == TopAbs_FORWARD) dtemp.Add(edge);
233           if(edge.Orientation() == TopAbs_REVERSED) rtemp.Add(edge);
234         }
235     }
236     if(!nbbe && !nbe && dtemp.IsEmpty() && rtemp.IsEmpty()) 
237       continue;
238     
239     // if face can not be added to shell it added to sequence of error faces.
240     
241     if( nbe != 0 && nbbe != 0) {
242       ErrFaces.Append(F1);
243       Lface.Remove(i);
244       j++;
245       continue;
246     }
247     
248     // Addition of face to shell. In the dependance of orientation faces in the shell 
249     //  added face can be reversed.
250
251     if((nbe != 0 || nbbe != 0) || j == 1) {
252       if(nbbe != 0) {
253         F1.Reverse();
254         for(TopTools_MapIteratorOfMapOfShape ite(dtemp); ite.More(); ite.Next()) 
255           reve.Add(ite.Key());
256         for(TopTools_MapIteratorOfMapOfShape ite1(rtemp); ite1.More(); ite1.Next())
257           dire.Add(ite1.Key());
258         done = Standard_True;
259       }
260       else {
261         for(TopTools_MapIteratorOfMapOfShape ite(dtemp); ite.More(); ite.Next()) 
262           dire.Add(ite.Key());
263         for(TopTools_MapIteratorOfMapOfShape ite1(rtemp); ite1.More(); ite1.Next())
264           reve.Add(ite1.Key());
265       }
266       j++;
267       B.Add(nshell,F1);
268       aMapFaceShells.Bind(F1,nshell);
269       Lface.Remove(i);
270       
271       // check if closed shell is obtained in multy connex mode and add to sequence of 
272       // shells and new shell begin to construct.
273       // (check is n*2)
274       if(isMultiConnex && BRep_Tool::IsClosed (nshell)) {
275         nshell.Closed (Standard_True);
276         aSeqShells.Append(nshell);
277         TopoDS_Shell nshellnext;
278         B.MakeShell(nshellnext);
279         nshell = nshellnext;
280         j=1;
281       }
282         
283       i=0;
284     }
285     //if shell contains of one face. This face is added to sequence of faces.
286     // This shell is removed.
287     if(Lface.Length() && i == Lface.Length() && j <=2) {
288       TopoDS_Iterator aItf(nshell,Standard_False);
289       if(aItf.More()) {
290         aSeqUnconnectFaces.Append(aItf.Value());
291         aMapFaceShells.UnBind(aItf.Value());
292       }
293       TopoDS_Shell nshellnext;
294       B.MakeShell(nshellnext);
295       nshell = nshellnext;
296       i=0;
297       j=1;
298     }
299   }
300   Standard_Boolean isContains = Standard_False;
301   for(Standard_Integer k =1 ; k <= aSeqShells.Length() && !isContains; k++)
302     isContains = nshell.IsSame(aSeqShells.Value(k));
303   if(!isContains) {
304     Standard_Integer numFace =0;
305     TopoDS_Shape aFace;
306     for(TopoDS_Iterator aItf(nshell,Standard_False) ; aItf.More(); aItf.Next()) {
307       aFace = aItf.Value();
308       numFace++;
309     }
310     if(numFace >1) {
311       // close all closed shells in no multy connex mode
312       if(!isMultiConnex)
313         nshell.Closed (BRep_Tool::IsClosed (nshell));
314       aSeqShells.Append(nshell);
315     }
316     else if(numFace == 1) {
317       if(aMapFaceShells.IsBound(aFace))
318         aMapFaceShells.UnBind(aFace);
319       Lface.Append(aFace);
320     }
321   }
322   
323   //Sequence of faces Lface contains faces which can not be added to obtained shells.
324   for(Standard_Integer j1 =1; j1 <= aSeqUnconnectFaces.Length(); j1++) {
325     Lface.Append(aSeqUnconnectFaces);
326   }
327   
328   return done;
329 }
330 //=======================================================================
331 // function : AddMultiConexityFaces
332 // purpose  : In this function faces have only of multiconnexity boundary
333 //            are added to shells having free boundary contains the same 
334 //            multiconnexity edges as faces.
335 //=======================================================================
336 static Standard_Boolean AddMultiConexityFaces(TopTools_SequenceOfShape& Lface,
337                                               const TopTools_MapOfShape& aMapMultiConnectEdges,
338                                               TopTools_SequenceOfShape& SeqShells,
339                                               const TopTools_DataMapOfShapeShape& aMapFaceShells,
340                                               const TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces,
341                                               TopTools_SequenceOfShape& ErrFaces,
342                                               const Standard_Boolean NonManifold)
343 {
344   Standard_Boolean done = Standard_False;
345 //  BRep_Builder aB;
346   TopTools_SequenceOfShape llPosibleShells;
347   TopTools_SequenceOfShape AddShapes; 
348   for(Standard_Integer i1 = 1 ; i1<=Lface.Length();i1++ )  {
349    
350     TopoDS_Shape aShape = Lface.Value(i1);
351     
352     Standard_Integer aNbMultEdges =0;
353     
354     //Finds faces having only multiconnexity boundary.
355     for(TopoDS_Iterator aItWires(aShape,Standard_False);  aItWires.More();  aItWires.Next()) {
356       Standard_Integer aNbEdges =0;
357       for(TopoDS_Iterator aItEdges(aItWires.Value(),Standard_False);  aItEdges.More();  aItEdges.Next(),aNbEdges++) {
358         TopoDS_Shape edge = aItEdges.Value();
359         if(!aMapMultiConnectEdges.Contains(edge)) continue;
360         aNbMultEdges++;
361       }
362       if(!aNbMultEdges) continue;
363     
364       if(aNbMultEdges == aNbEdges)
365         AddShapes.Append(aShape);
366       else llPosibleShells.Append(aShape);
367     }
368   }
369   
370   // Attemp to create shell from unconnected which have not only multiconnexity boundary.
371   TopTools_SequenceOfShape aTmpShells;
372   if(!llPosibleShells.IsEmpty()) {
373     TopTools_MapOfShape aMap;
374     TopTools_SequenceOfShape aTmp;
375     TopTools_DataMapOfShapeShape aTmpFaceShell;
376     if(GetShells(llPosibleShells,aMap,aTmpShells,aTmpFaceShell,aTmp)) {
377       for(Standard_Integer kk =1; kk <= aTmpShells.Length(); kk++) {
378         TopoDS_Shape aSh = aTmpShells.Value(kk);
379         TopTools_MapOfShape mapEdges;
380         if(GetFreeEdges(aSh,mapEdges)) {
381           Standard_Integer nbedge =0;
382           for(TopTools_MapIteratorOfMapOfShape amapIter(mapEdges);amapIter.More(); amapIter.Next()) {
383             if( aMapMultiConnectEdges.Contains(amapIter.Key()))
384               nbedge++;
385           }
386           if(nbedge && nbedge == mapEdges.Extent())
387             AddShapes.Append(aSh);
388         }
389       }
390     }
391   }
392   
393   //Add choosen faces to shells.
394   for(Standard_Integer k1 =1; k1 <= AddShapes.Length(); k1++) {
395     TopTools_DataMapOfShapeInteger MapOtherShells;
396     TopTools_MapOfShape dire,reve;
397     TopoDS_Shape aSh = AddShapes.Value(k1);
398     TopTools_MapOfShape mapEdges;
399     if(!GetFreeEdges(aSh,mapEdges)) continue;
400     TopTools_ListOfShape lfaces;
401     
402     //Fill MapOtherShells which will contain shells with orientation in which selected shape aSh will be add.
403     
404     for(TopTools_MapIteratorOfMapOfShape amapIter(mapEdges);amapIter.More(); amapIter.Next()) {
405       if(!aMapMultiConnectEdges.Contains(amapIter.Key())) continue;
406       TopoDS_Edge edge = TopoDS::Edge(amapIter.Key());
407       if( edge.Orientation() == TopAbs_FORWARD) dire.Add(edge);
408       else reve.Add(edge);
409       TopTools_ListOfShape lf;
410       lf = aMapEdgeFaces.FindFromKey(edge);
411       lfaces.Append(lf);
412     }
413     for(TopTools_ListIteratorOfListOfShape aItl(lfaces) ; aItl.More(); aItl.Next()) {
414       TopoDS_Shape aF = aItl.Value();
415       if(!aMapFaceShells.IsBound( aF)) continue;
416      
417       TopoDS_Shape aOthershell;
418       aOthershell = aMapFaceShells.Find(aF);
419       if(MapOtherShells.IsBound(aOthershell)) continue;
420       if(!NonManifold && BRep_Tool::IsClosed(aOthershell))
421         continue;
422       
423       TopTools_MapOfShape mapShellEdges;
424       GetFreeEdges(aOthershell,mapShellEdges);
425       Standard_Boolean isAdd = Standard_True;
426       for(TopTools_MapIteratorOfMapOfShape amapIter1(mapEdges);amapIter1.More() && isAdd ; amapIter1.Next()) 
427         isAdd = mapShellEdges.Contains(amapIter1.Key());
428       
429       if(!isAdd) continue;
430       Standard_Integer nbdir =0, nbrev=0;
431       
432       //add only free face whome all edges contains in the shell as open boundary.
433       for(TopTools_MapIteratorOfMapOfShape aIte( mapShellEdges);aIte.More() ;aIte.Next()) {
434         TopoDS_Edge edgeS = TopoDS::Edge(aIte.Key());
435         if(!aMapMultiConnectEdges.Contains(edgeS)) continue;
436         if( (edgeS.Orientation() == TopAbs_FORWARD && dire.Contains(edgeS)) || (edgeS.Orientation() == TopAbs_REVERSED && reve.Contains(edgeS)))  nbrev++;
437         else if((edgeS.Orientation() == TopAbs_FORWARD && reve.Contains(edgeS))
438                 || (edgeS.Orientation() == TopAbs_REVERSED && dire.Contains(edgeS))) nbdir++;
439       }
440       if(nbdir && nbrev) {
441         ErrFaces.Append(aSh);
442         continue;
443       }
444       if(nbdir || nbrev) {
445         Standard_Integer isReverse =(nbrev ? 1: 0);
446         MapOtherShells.Bind(aOthershell,isReverse);
447       }
448       
449     }
450     if(MapOtherShells.IsEmpty()) {
451 //      i1++;
452       continue;
453     }
454     
455     //Adds face to open shells containg the same multishared edges.
456     //For nonmanifold mode creation ine shell from face and shells containing the same multishared edges.
457     // If one face can be added to a few shells (case of compsolid) face will be added to each shell.
458     done = Standard_True;
459     Standard_Integer FirstRev = 0,FirstInd =0;
460     Standard_Integer ind =0;
461     for(Standard_Integer l =1; l <= SeqShells.Length(); l++) {
462       if(!MapOtherShells.IsBound(SeqShells.Value(l))) continue;
463       ind++;
464       Standard_Integer isRev = MapOtherShells.Find(SeqShells.Value(l));
465       TopoDS_Shape anewShape = (isRev ? aSh.Reversed() :aSh);
466      
467       BRep_Builder aB1;
468       TopoDS_Shape aShell = SeqShells.Value(l);
469       if(ind ==1 || !NonManifold) {
470         if(ind ==1) {
471           FirstRev = isRev;
472           FirstInd = l;
473         }
474         for(TopExp_Explorer aE(anewShape,TopAbs_FACE); aE.More(); aE.Next())
475           aB1.Add(aShell,aE.Current());
476         SeqShells.ChangeValue(l) = aShell;
477       }
478       else if(NonManifold) {
479         Standard_Boolean isReversed = !((!(isRev) && !FirstRev) || ((isRev) && FirstRev));
480         aShell = SeqShells.Value(FirstInd);
481         for(TopoDS_Iterator aItF(SeqShells.Value(l),Standard_False); aItF.More(); aItF.Next()) {
482           TopoDS_Shape nF = ( isReversed ? aItF.Value().Reversed() : aItF.Value());
483           aB1.Add(aShell,nF);
484         }
485         SeqShells.ChangeValue(FirstInd) = aShell;
486         SeqShells.Remove(l--);
487       }
488     }
489       
490     dire.Clear();
491     reve.Clear();
492     for(TopExp_Explorer aEt(aSh,TopAbs_FACE); aEt.More(); aEt.Next()) {
493       for(Standard_Integer kk =1 ; kk <= Lface.Length(); kk++) {
494         if(aEt.Current().IsSame(Lface.Value(kk)))
495           Lface.Remove(kk--);
496       }
497     }
498   }
499   return done;
500 }
501
502 //=======================================================================
503 // function : BoxIn
504 // purpose  : Check if one face contains inside other.
505 //=======================================================================
506 static Standard_Integer BoxIn(const Bnd_Box& theBox1,const Bnd_Box& theBox2)
507 {
508      Standard_Integer aNumIn = 0;
509      Standard_Real aXmin1,aYmin1,aXmax1,aYmax1,aXmin2,aYmin2,aXmax2,aYmax2,aZmin1,aZmax1,aZmin2,aZmax2;
510      theBox1.Get(aXmin1,aYmin1,aZmin1,aXmax1,aYmax1,aZmax1);
511      theBox2.Get(aXmin2,aYmin2,aZmin2,aXmax2,aYmax2,aZmax2);
512      if(aXmin1 == aXmin2 && aXmax1 == aXmax2 && aYmin1 == aYmin2 && aYmax1 == aYmax2 &&
513         aZmin1 == aZmin2 && aZmax1 == aZmax2)
514        aNumIn = 0;
515      else if( aXmin1 >= aXmin2 && aXmax1 <= aXmax2 && aYmin1 >= aYmin2 && aYmax1 <= aYmax2 &&
516         aZmin1 >= aZmin2 && aZmax1 <= aZmax2)  
517         aNumIn = 1;
518      else if( aXmin1 <= aXmin2 && aXmax1 >= aXmax2 && aYmin1 <= aYmin2 && aYmax1 >= aYmax2 && aZmin1 <= aZmin2 && aZmax1 >= aZmax2)
519        aNumIn = 2;
520      return aNumIn;
521 }
522 //=======================================================================
523 // function : GetClosedShells
524 // purpose  : Check if one shell is a part from other shell.
525 //            For case of compsolid when afew shells are created from
526 //            the same set of faces.
527 //=======================================================================
528 static void GetClosedShells(TopTools_SequenceOfShape& Shells, TopTools_SequenceOfShape& aRemainShells)
529 {
530   Bnd_Array1OfBox aBoxes(1,Shells.Length());
531   for(Standard_Integer i =1; i <= Shells.Length(); i++) {
532     Bnd_Box Box;
533     BRepBndLib::AddClose(Shells.Value(i),Box);
534     aBoxes.SetValue(i,Box);
535   }
536   TColStd_MapOfInteger aMapNum;
537   for(Standard_Integer j = 1; j <= aBoxes.Length(); j++) {
538     for(Standard_Integer k = j+1; k <= aBoxes.Length(); k++) {
539       Standard_Integer NumIn = BoxIn(aBoxes.Value(j),aBoxes.Value(k));
540       switch(NumIn) {
541       case 1:aMapNum.Add(k); break;
542       case 2: aMapNum.Add(j); break;
543         default : break;
544       }
545     }
546   }
547   for(Standard_Integer i1 =1; i1 <= Shells.Length(); i1++) {
548     if(!aMapNum.Contains(i1))
549       aRemainShells.Append(Shells.Value(i1));
550   }
551   
552 }
553 //=======================================================================
554 // function : GlueClosedCandidate
555 // purpose  :Attemt firstly to create closed shells from sequence of open shells.
556 //=======================================================================
557 static void GlueClosedCandidate(TopTools_SequenceOfShape& OpenShells,
558                                                     const TopTools_MapOfShape& aMapMultiConnectEdges,
559                                                     TopTools_SequenceOfShape& aSeqNewShells)
560                                                     
561 {
562   // Creating new shells if some open shells contain the same free boundary.
563   for(Standard_Integer i = 1 ; i < OpenShells.Length();i++ )  {
564     TopoDS_Shape aShell = OpenShells.Value(i);
565     TopTools_MapOfShape mapEdges1;
566     TopTools_MapOfShape dire,reve;
567     if(!GetFreeEdges(aShell,mapEdges1)) continue;
568     
569     for(TopTools_MapIteratorOfMapOfShape aIte( mapEdges1);aIte.More() ;aIte.Next()) {
570       TopoDS_Edge edge1 = TopoDS::Edge(aIte.Key());
571       if(!aMapMultiConnectEdges.Contains(edge1)) break;
572       if(edge1.Orientation() == TopAbs_FORWARD) dire.Add(edge1);
573       else if(edge1.Orientation() == TopAbs_REVERSED) reve.Add(edge1);
574     }
575     if(mapEdges1.Extent() >(dire.Extent() + reve.Extent())) continue;
576     
577     //Filling map MapOtherShells which contains candidate to creation of closed shell
578     // with aShell.
579     NCollection_DataMap<TopoDS_Shape, Standard_Boolean, TopTools_ShapeMapHasher> MapOtherShells;
580     for(Standard_Integer j = i+1 ; j <= OpenShells.Length();j++ )  {
581       Standard_Boolean isAddShell = Standard_True;
582       Standard_Boolean isReversed = Standard_False;
583       Standard_Integer nbedge =0;
584       TopTools_MapOfShape mapEdges2;
585       TopoDS_Shape aShell2 = OpenShells.Value(j);
586       if(!GetFreeEdges(aShell2,mapEdges2)) continue;
587       for(TopTools_MapIteratorOfMapOfShape aIte2( mapEdges2);aIte2.More() && isAddShell;aIte2.Next()) {
588         TopoDS_Edge edge2 = TopoDS::Edge(aIte2.Key());
589         if(!aMapMultiConnectEdges.Contains(edge2)) {
590           isAddShell = Standard_False;
591           break;
592           //continue;
593         }
594         isAddShell = (dire.Contains(edge2) || reve.Contains(edge2)); 
595         if((edge2.Orientation() == TopAbs_FORWARD && dire.Contains(edge2))
596            || (edge2.Orientation() == TopAbs_REVERSED && reve.Contains(edge2)))
597           isReversed = Standard_True;
598         nbedge++;
599       }
600       
601       if(!isAddShell) continue;
602       MapOtherShells.Bind(OpenShells.Value(j),isReversed);
603     }
604     if(MapOtherShells.IsEmpty()) continue;
605     
606     
607     if (!MapOtherShells.IsEmpty())
608     {
609       // Case of compsolid when more than two shells have the same free boundary.
610       TopTools_SequenceOfShape aSeqCandidate;
611       aSeqCandidate.Append(OpenShells.Value(i));
612       
613       for (NCollection_DataMap<TopoDS_Shape, Standard_Boolean, TopTools_ShapeMapHasher>::Iterator aIt(MapOtherShells); aIt.More(); aIt.Next())
614       {
615         aSeqCandidate.Append(aIt.Key());
616       }
617       
618       //Creation all possibly shells from choosen candidate.And
619       // addition of them to temporary sequence.
620       
621       TopTools_SequenceOfShape aTmpSeq;
622       for(Standard_Integer k =1; k <= aSeqCandidate.Length(); k++) {
623         
624         for(Standard_Integer l = k+1; l <= aSeqCandidate.Length(); l++) {
625           TopoDS_Shell aNewSh;
626           BRep_Builder aB;
627           aB.MakeShell(aNewSh);
628           for(TopoDS_Iterator aIt1(aSeqCandidate.Value(k),Standard_False); aIt1.More(); aIt1.Next())
629             aB.Add(aNewSh,aIt1.Value());
630           Standard_Boolean isRev = MapOtherShells.Find(aSeqCandidate.Value(l));
631           if(k !=1) {
632             isRev = (isRev == MapOtherShells.Find(aSeqCandidate.Value(k)));
633           }
634           for(TopExp_Explorer aExp(aSeqCandidate.Value(l),TopAbs_FACE); aExp.More(); aExp.Next()) {
635             TopoDS_Shape aFace = (isRev ? aExp.Current().Reversed(): aExp.Current());
636             aB.Add(aNewSh,aFace);
637           }
638           aTmpSeq.Append(aNewSh);
639         }
640       }
641       
642       //Choice from temporary sequence shells contains different set of faces (case of compsolid) 
643       TopTools_SequenceOfShape aRemainShells;
644       GetClosedShells(aTmpSeq,aRemainShells);
645       aSeqNewShells.Append(aRemainShells);
646       
647       for(Standard_Integer j1 = i+1 ; j1 <= OpenShells.Length();j1++ )  {
648         if(!MapOtherShells.IsBound(OpenShells.Value(j1))) continue;
649         OpenShells.Remove(j1--);
650       }
651       
652     }
653     else {
654       BRep_Builder aB;
655       TopoDS_Shape aNewShell = aShell;
656       TopoDS_Shape addShell;
657       Standard_Boolean isReversed = Standard_False;
658       for(Standard_Integer j1 = i+1 ; j1 <= OpenShells.Length();j1++ )  {
659         if(!MapOtherShells.Find (OpenShells.Value(j1), isReversed)) continue;
660         addShell = OpenShells.Value(j1);
661         OpenShells.Remove(j1);
662         break;
663       }
664       
665       for(TopExp_Explorer aExpF(addShell,TopAbs_FACE); aExpF.More(); aExpF.Next()) {
666         TopoDS_Shape aFace = aExpF.Current();
667         if(isReversed)
668           aFace.Reverse();
669         aB.Add(aNewShell,aFace);
670       }
671       aSeqNewShells.Append(aNewShell);
672     }
673     
674     //OpenShells.ChangeValue(i) = aShell;
675     OpenShells.Remove(i--);
676   }
677 }
678 //=======================================================================
679 // function : CreateNonManifoldShells
680 // purpose  : Attempt to create max possible shells from open shells.
681 //=======================================================================
682
683 static void CreateNonManifoldShells(TopTools_SequenceOfShape& SeqShells,
684                               const TopTools_MapOfShape& aMapMultiConnectEdges)
685 {
686   TopTools_IndexedDataMapOfShapeListOfShape aMap;
687   for(Standard_Integer i =1 ; i <= SeqShells.Length(); i++) {
688     TopoDS_Shape aShell = SeqShells.Value(i);
689     TopTools_IndexedMapOfShape medeg;
690     TopExp::MapShapes(aShell,TopAbs_EDGE,medeg);
691     for(TopTools_MapIteratorOfMapOfShape mit(aMapMultiConnectEdges); mit.More(); mit.Next()) {
692     //for(TopExp_Explorer aExp(aShell,TopAbs_EDGE); aExp.More(); aExp.Next(),nbe++) {
693       //TopoDS_Shape ae = aExp.Current();
694       TopoDS_Shape ae =mit.Key();
695       //if( aMapMultiConnectEdges.Contains(aExp.Current())) {
696       if(medeg.Contains(ae)) {
697         if(aMap.Contains(ae))
698          aMap.ChangeFromKey(ae).Append(aShell);
699         else {
700           TopTools_ListOfShape al;
701           al.Append(aShell);
702           aMap.Add(ae,al);
703         }
704       }
705     }
706   }
707   TopTools_IndexedDataMapOfShapeShape aMapShells;
708   for(Standard_Integer j =1; j <= aMap.Extent(); j++) {
709     const TopTools_ListOfShape& LShells = aMap.FindFromIndex(j);
710     TopoDS_Shell aNewShell;
711     BRep_Builder aB;
712     aB.MakeShell(aNewShell);
713     TopTools_MapOfShape mapmerge;
714     Standard_Boolean ismerged = Standard_False;
715     Standard_Integer num = 1;
716     for(TopTools_ListIteratorOfListOfShape alit(LShells); alit.More();alit.Next(),num++) { 
717       if(!aMapShells.Contains(alit.Value())) {
718         for(TopExp_Explorer aEf(alit.Value(),TopAbs_FACE); aEf.More(); aEf.Next()) {
719           aB.Add(aNewShell,aEf.Current());
720         }
721         ismerged = Standard_True;
722         mapmerge.Add(alit.Value());
723       }
724       else if(ismerged) {
725         TopoDS_Shape arshell = aMapShells.FindFromKey(alit.Value());
726         while(aMapShells.Contains(arshell)){
727           TopoDS_Shape ss = aMapShells.FindFromKey(arshell);
728           if(ss.IsSame(arshell)) break;
729           arshell = ss;
730         }
731          
732         if(!mapmerge.Contains(arshell)) {
733           for(TopExp_Explorer aEf(arshell,TopAbs_FACE); aEf.More(); aEf.Next()) {
734             aB.Add(aNewShell,aEf.Current());
735           }
736           mapmerge.Add(arshell);
737         }
738       }
739       else {
740         TopoDS_Shape arshell = aMapShells.FindFromKey(alit.Value());
741          while(aMapShells.Contains(arshell)) {
742           TopoDS_Shape ss = aMapShells.FindFromKey(arshell);
743           if(ss.IsSame(arshell)) break;
744           arshell = ss;
745         }
746         if(num == 1) {
747           for(TopExp_Explorer aEf(arshell,TopAbs_FACE); aEf.More(); aEf.Next()) 
748             aB.Add(aNewShell,aEf.Current());
749           
750           mapmerge.Add(arshell);
751         }
752         else if(!mapmerge.Contains(arshell)) {
753           for(TopExp_Explorer aEf(arshell,TopAbs_FACE); aEf.More(); aEf.Next()) {
754             aB.Add(aNewShell,aEf.Current());
755           }
756           mapmerge.Add(arshell);
757         }
758       }
759     }
760     if(mapmerge.Extent() >1 || ismerged) {
761       for(TopTools_MapIteratorOfMapOfShape alit1(mapmerge); alit1.More();alit1.Next()) {
762         TopoDS_Shape oldShell = alit1.Key();
763          //while(aMapShells.Contains(oldShell)) {
764          //  TopoDS_Shape ss = aMapShells.FindFromKey(oldShell);
765          //  if(ss.IsSame(oldShell)) break;
766          //  oldShell = ss;
767          //}
768         aMapShells.Add(oldShell,aNewShell);
769       }
770     }
771   }
772   TopTools_IndexedMapOfShape MapNewShells;
773   for(Standard_Integer nn = 1;nn <= SeqShells.Length(); nn++) {
774     if(aMapShells.Contains(SeqShells.Value(nn))) {
775       TopoDS_Shape aNewShell = aMapShells.FindFromKey(SeqShells.Value(nn));
776       while(aMapShells.Contains(aNewShell)) {
777         TopoDS_Shape ss = aMapShells.FindFromKey(aNewShell);
778         if(ss.IsSame(aNewShell)) break;
779         aNewShell = ss;
780       }
781       MapNewShells.Add(aNewShell);
782       
783       SeqShells.Remove(nn--);
784     }
785     
786   }
787   for(Standard_Integer ii =1; ii <= MapNewShells.Extent(); ii++)
788     SeqShells.Append(MapNewShells.FindKey(ii));
789 }
790 //=======================================================================
791 // function : CreateClosedShell
792 // purpose  : Attempt to create max possible shells from open shells.
793 //=======================================================================
794
795 static void CreateClosedShell(TopTools_SequenceOfShape& OpenShells,
796                               const TopTools_MapOfShape& aMapMultiConnectEdges)
797 {
798   TopTools_SequenceOfShape aNewShells;
799   //Attemt firstly to create closed shells.
800   GlueClosedCandidate(OpenShells,aMapMultiConnectEdges,aNewShells);
801   
802   // Creating new shells if some open shells contain the multishared same edges.
803   for(Standard_Integer i = 1 ; i < OpenShells.Length();i++ )  {
804     Standard_Boolean isAddShell = Standard_False;
805     TopoDS_Shape aShell = OpenShells.Value(i);
806     Standard_Boolean isReversed = Standard_False;
807     for(Standard_Integer j = i+1 ; j <= OpenShells.Length();j++ )  {
808       TopTools_MapOfShape mapEdges1;
809       TopTools_MapOfShape dire,reve;
810       if(!GetFreeEdges(aShell,mapEdges1)) break;
811       for(TopTools_MapIteratorOfMapOfShape aIte( mapEdges1);aIte.More() ;aIte.Next()) {
812         TopoDS_Edge edge1 = TopoDS::Edge(aIte.Key());
813         if(!aMapMultiConnectEdges.Contains(edge1)) continue;
814         if(edge1.Orientation() == TopAbs_FORWARD) dire.Add(edge1);
815         else if(edge1.Orientation() == TopAbs_REVERSED) reve.Add(edge1);
816       }
817       if(dire.IsEmpty() &&  reve.IsEmpty()) break;
818       TopTools_MapOfShape mapEdges2;
819       TopoDS_Shape aShell2 = OpenShells.Value(j);
820       if(!GetFreeEdges(aShell2,mapEdges2)) continue;
821       for(TopTools_MapIteratorOfMapOfShape aIte2( mapEdges2);aIte2.More() ;aIte2.Next()) {
822         TopoDS_Edge edge2 = TopoDS::Edge(aIte2.Key());
823         if(!aMapMultiConnectEdges.Contains(edge2)) continue;
824         if(!dire.Contains(edge2) && !reve.Contains(edge2)) continue;
825         isAddShell = Standard_True;
826         if((edge2.Orientation() == TopAbs_FORWARD && dire.Contains(edge2))
827            || (edge2.Orientation() == TopAbs_REVERSED && reve.Contains(edge2)))
828           isReversed = Standard_True;
829       }
830       
831       if(!isAddShell) continue;
832       BRep_Builder aB;
833       
834       for(TopExp_Explorer aExpF21(OpenShells.Value(j),TopAbs_FACE); aExpF21.More(); aExpF21.Next()) {
835         TopoDS_Shape aFace = aExpF21.Current();
836         if(isReversed)
837           aFace.Reverse();
838         aB.Add( aShell,aFace);
839       }
840       
841       OpenShells.ChangeValue(i) = aShell;
842       OpenShells.Remove(j--);
843     }
844   }
845  
846   OpenShells.Append(aNewShells);
847   
848 }
849   
850
851 //=======================================================================
852 // function : FixFaceOrientation
853 // purpose  : 
854 //=======================================================================
855   
856 Standard_Boolean ShapeFix_Shell::FixFaceOrientation(
857     const TopoDS_Shell& shell,
858     const Standard_Boolean isAccountMultiConex,
859     const Standard_Boolean NonManifold) 
860 {
861   //myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
862   Standard_Boolean done = Standard_False;
863   TopTools_SequenceOfShape aSeqShells;
864   TopTools_SequenceOfShape aErrFaces; // Compound of faces like to Mebiuce leaf.
865   TopTools_SequenceOfShape Lface;
866   TopTools_DataMapOfShapeShape aMapFaceShells;
867   myShell = shell;
868   myShape = shell;
869   Standard_Integer aNumMultShell =0;
870   Standard_Integer nbF = 0;
871   TopTools_MapOfShape aMapAdded;
872   for (TopoDS_Iterator iter(shell); iter.More(); iter.Next(),nbF++) 
873   {
874     if(aMapAdded.Add(iter.Value()))
875       Lface.Append(iter.Value());
876   }
877   if(Lface.Length() < nbF)
878     done = Standard_True;
879
880   TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
881   TopExp::MapShapesAndAncestors(myShell,TopAbs_EDGE,TopAbs_FACE,aMapEdgeFaces);
882   TopTools_MapOfShape aMapMultiConnectEdges;
883   Standard_Boolean isFreeBoundaries = Standard_False;
884   for(Standard_Integer k = 1; k <= aMapEdgeFaces.Extent(); k++) {
885     const Standard_Integer aFaceCount = aMapEdgeFaces.FindFromIndex(k).Extent();
886     if (!isFreeBoundaries && aFaceCount == 1) {
887       TopoDS_Edge E = TopoDS::Edge(aMapEdgeFaces.FindKey(k));
888       if (!BRep_Tool::Degenerated(E))
889         isFreeBoundaries = Standard_True;
890     }
891     //Finds multishared edges
892     else if (isAccountMultiConex && aFaceCount > 2)
893       aMapMultiConnectEdges.Add(aMapEdgeFaces.FindKey(k));
894   }
895   if (BRep_Tool::IsClosed(myShell)? isFreeBoundaries : !isFreeBoundaries)
896   {
897     myShell.Closed (!isFreeBoundaries);
898     SendWarning (Message_Msg ("FixAdvShell.FixClosedFlag.MSG0"));//Shell has incorrect flag isClosed
899   }
900   Standard_Boolean isGetShells = Standard_True;
901   //Gets possible shells with taking in account of multiconnexity.
902   while(isGetShells && Lface.Length()) {
903     TopTools_SequenceOfShape aTmpSeqShells;
904     if(GetShells(Lface, aMapMultiConnectEdges, aTmpSeqShells,aMapFaceShells,aErrFaces)) {
905       done = Standard_True;
906     }
907     isGetShells = !aTmpSeqShells.IsEmpty();
908     if(isGetShells) 
909       aSeqShells.Append(aTmpSeqShells);
910   }
911   if(!done)
912     done = (aSeqShells.Length() >1);
913   Standard_Boolean aIsDone = Standard_False;
914   if(Lface.Length() > 0 && aSeqShells.Length()) {
915     for(Standard_Integer jj =1; jj <= Lface.Length(); jj++) {
916       if(aMapFaceShells.IsBound(Lface.Value(jj)))
917         aMapFaceShells.UnBind(Lface.Value(jj));
918     }
919     
920     //Addition of faces having only multiconnexity boundary to shells having holes
921     // containing only the multiconnexity edges
922     aIsDone = AddMultiConexityFaces(Lface,aMapMultiConnectEdges,aSeqShells,aMapFaceShells,
923                                     aMapEdgeFaces,aErrFaces,NonManifold);
924   }
925   aNumMultShell = aSeqShells.Length();
926   if (!aErrFaces.IsEmpty())  {
927     
928     //if Shell contains of Mebius faces one shell will be created from each those face.
929     BRep_Builder B;
930     B.MakeCompound(myErrFaces);
931     TopoDS_Compound aCompShells;
932     B.MakeCompound(aCompShells);
933     for(Standard_Integer n =1; n <= aErrFaces.Length(); n++)
934       B.Add(myErrFaces,aErrFaces.Value(n));
935     if(aNumMultShell) {
936       if(aNumMultShell == 1) {
937         B.Add(aCompShells,aSeqShells.Value(1));
938         for(Standard_Integer n1 =1; n1 <= aErrFaces.Length(); n1++) {
939           TopoDS_Shell aSh;
940           B.MakeShell(aSh);
941           B.Add(aSh,aErrFaces.Value(n1));
942            B.Add(aCompShells,aSh);
943         }
944         myShape = aCompShells;
945       }
946       else {
947         for(Standard_Integer i =1; i <= aSeqShells.Length(); i++)
948           B.Add(aCompShells,aSeqShells.Value(i));
949         for(Standard_Integer n1 =1; n1 <= aErrFaces.Length(); n1++) {
950           TopoDS_Shell aSh;
951           B.MakeShell(aSh);
952           B.Add(aSh,aErrFaces.Value(n1));
953            B.Add(aCompShells,aSh);
954         }
955         myShape = aCompShells;
956       }
957     }
958     
959     done = Standard_True;
960     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL);
961     SendWarning ( Message_Msg ( "FixAdvShell.FixOrientation.MSG20" ) );// Impossible to orient faces in shell, several shells created
962     return Standard_True;
963   }
964   if(aNumMultShell >1) {
965     TopTools_SequenceOfShape OpenShells;
966     for(Standard_Integer i1 =1; i1 <= aSeqShells.Length(); i1++) {
967       TopoDS_Shape aShell = aSeqShells.Value(i1);
968       if(!BRep_Tool::IsClosed(aShell)) {
969         OpenShells.Append(aShell);
970         aSeqShells.Remove(i1--);
971        }
972     }
973     if(OpenShells.Length() >1) 
974       //Attempt of creation closed shell from open shells with taking into account multiconnexity.
975       CreateClosedShell(OpenShells,aMapMultiConnectEdges);
976     aSeqShells.Append(OpenShells);
977     
978   }
979   
980   // In the case if NonManifold is equal to Standard_True one non-manifold shell will be created.
981   //Else compound from shells will be created if length of sequence of shape >1.
982   if(Lface.Length()) {
983    
984     for(Standard_Integer i = 1; i <= Lface.Length();i++) {
985       BRep_Builder aB;
986       TopoDS_Shell OneShell;
987       aB.MakeShell(OneShell);
988       aB.Add(OneShell, Lface.Value(i));
989       aSeqShells.Append(OneShell);
990     }
991       
992   }
993   if(NonManifold && aSeqShells.Length() >1 ) {
994     CreateNonManifoldShells(aSeqShells,aMapMultiConnectEdges);
995   }
996   if(!done)
997     done = (aSeqShells.Length() >1 || aIsDone);
998   if(aSeqShells.Length() == 1) {
999     myShell = TopoDS::Shell(aSeqShells.Value(1));
1000     myShape =myShell;
1001     myNbShells =1;
1002   }
1003   else {
1004     BRep_Builder B;
1005     TopoDS_Compound aCompShells;
1006     B.MakeCompound(aCompShells);
1007     for(Standard_Integer i =1; i <= aSeqShells.Length(); i++)
1008       B.Add(aCompShells,aSeqShells.Value(i));  
1009     myShape = aCompShells;
1010     myNbShells =  aSeqShells.Length();
1011   }
1012   if(done) {
1013     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
1014     if(!Context().IsNull())
1015       Context()->Replace(shell, myShape);
1016     if ( myNbShells == 1 )
1017       SendWarning ( Message_Msg ( "FixAdvShell.FixOrientation.MSG0" ) );// Faces were incorrectly oriented in the shell, corrected
1018     else
1019       SendWarning ( Message_Msg ( "FixAdvShell.FixOrientation.MSG30" ) );// Improperly connected shell split into parts
1020     return Standard_True;
1021   }
1022   else return Standard_False;
1023 }
1024
1025 //=======================================================================
1026 //function : Status
1027 //purpose  : 
1028 //=======================================================================
1029
1030 Standard_Boolean ShapeFix_Shell::Status(const ShapeExtend_Status status) const
1031 {
1032   return ShapeExtend::DecodeStatus (myStatus, status);
1033 }
1034
1035 //=======================================================================
1036 //function : Shell
1037 //purpose  : 
1038 //=======================================================================
1039
1040 TopoDS_Shell ShapeFix_Shell::Shell() 
1041 {
1042  return myShell; 
1043 }
1044 //=======================================================================
1045 //function : Shell
1046 //purpose  : 
1047 //=======================================================================
1048
1049 TopoDS_Shape ShapeFix_Shell::Shape() 
1050 {
1051  return myShape; 
1052 }
1053
1054 //=======================================================================
1055 //function : ErrorFaces
1056 //purpose  : 
1057 //=======================================================================
1058
1059 TopoDS_Compound ShapeFix_Shell::ErrorFaces() const
1060 {
1061   return myErrFaces;
1062 }
1063
1064 //=======================================================================
1065 //function : SetMsgRegistrator
1066 //purpose  : 
1067 //=======================================================================
1068
1069 void ShapeFix_Shell::SetMsgRegistrator(const Handle(ShapeExtend_BasicMsgRegistrator)& msgreg)
1070 {
1071   ShapeFix_Root::SetMsgRegistrator ( msgreg );
1072   myFixFace->SetMsgRegistrator ( msgreg );
1073 }
1074
1075 //=======================================================================
1076 //function : SetPrecision
1077 //purpose  : 
1078 //=======================================================================
1079
1080 void ShapeFix_Shell::SetPrecision (const Standard_Real preci) 
1081 {
1082   ShapeFix_Root::SetPrecision ( preci );
1083   myFixFace->SetPrecision ( preci );
1084 }
1085
1086 //=======================================================================
1087 //function : SetMinTolerance
1088 //purpose  : 
1089 //=======================================================================
1090
1091 void ShapeFix_Shell::SetMinTolerance (const Standard_Real mintol) 
1092 {
1093   ShapeFix_Root::SetMinTolerance ( mintol );
1094   myFixFace->SetMinTolerance ( mintol );
1095 }
1096
1097 //=======================================================================
1098 //function : SetMaxTolerance
1099 //purpose  : 
1100 //=======================================================================
1101
1102 void ShapeFix_Shell::SetMaxTolerance (const Standard_Real maxtol) 
1103 {
1104   ShapeFix_Root::SetMaxTolerance ( maxtol );
1105   myFixFace->SetMaxTolerance ( maxtol );
1106 }
1107
1108 //=======================================================================
1109 //function : NbShells
1110 //purpose  : 
1111 //=======================================================================
1112
1113 Standard_Integer ShapeFix_Shell::NbShells() const
1114 {
1115   return myNbShells;
1116 }
1117
1118 //=======================================================================
1119 //function : SetNonManifoldFlag
1120 //purpose  : 
1121 //=======================================================================
1122
1123 void ShapeFix_Shell::SetNonManifoldFlag(const Standard_Boolean isNonManifold)
1124 {
1125     myNonManifold = isNonManifold;
1126 }