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