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