5a03b46644b89ca963b1bd0debe0d829c4b43560
[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       nshell.Closed (BRep_Tool::IsClosed (nshell));
273       aMapFaceShells.Bind(F1,nshell);
274       Lface.Remove(i);
275       
276       // if closed shell is obtained it adds to sequence of shells and new shell begin to construct.
277       if(isMultiConnex && nshell.Closed()) {
278         aSeqShells.Append(nshell);
279         TopoDS_Shell nshellnext;
280         B.MakeShell(nshellnext);
281         nshell = nshellnext;
282         j=1;
283       }
284         
285       i=0;
286     }
287     //if shell contains of one face. This face is added to sequence of faces.
288     // This shell is removed.
289     if(Lface.Length() && i == Lface.Length() && j <=2) {
290       TopoDS_Iterator aItf(nshell,Standard_False);
291       if(aItf.More()) {
292         aSeqUnconnectFaces.Append(aItf.Value());
293         aMapFaceShells.UnBind(aItf.Value());
294       }
295       TopoDS_Shell nshellnext;
296       B.MakeShell(nshellnext);
297       nshell = nshellnext;
298       i=0;
299       j=1;
300     }
301   }
302   Standard_Boolean isContains = Standard_False;
303   for(Standard_Integer k =1 ; k <= aSeqShells.Length() && !isContains; k++)
304     isContains = nshell.IsSame(aSeqShells.Value(k));
305   if(!isContains) {
306     Standard_Integer numFace =0;
307     TopoDS_Shape aFace;
308     for(TopoDS_Iterator aItf(nshell,Standard_False) ; aItf.More(); aItf.Next()) {
309       aFace = aItf.Value();
310       numFace++;
311     }
312     if(numFace >1)
313       aSeqShells.Append(nshell);
314     else if(numFace == 1) {
315       if(aMapFaceShells.IsBound(aFace))
316         aMapFaceShells.UnBind(aFace);
317       Lface.Append(aFace);
318     }
319   }
320   
321   //Sequence of faces Lface contains faces which can not be added to obtained shells.
322   for(Standard_Integer j1 =1; j1 <= aSeqUnconnectFaces.Length(); j1++) {
323     Lface.Append(aSeqUnconnectFaces);
324   }
325   
326   return done;
327 }
328 //=======================================================================
329 // function : AddMultiConexityFaces
330 // purpose  : In this function faces have only of multiconnexity boundary
331 //            are added to shells having free boundary contains the same 
332 //            multiconnexity edges as faces.
333 //=======================================================================
334 static Standard_Boolean AddMultiConexityFaces(TopTools_SequenceOfShape& Lface,
335                                               const TopTools_MapOfShape& aMapMultiConnectEdges,
336                                               TopTools_SequenceOfShape& SeqShells,
337                                               const TopTools_DataMapOfShapeShape& aMapFaceShells,
338                                               const TopTools_IndexedDataMapOfShapeListOfShape& aMapEdgeFaces,
339                                               TopTools_SequenceOfShape& ErrFaces,
340                                               const Standard_Boolean NonManifold)
341 {
342   Standard_Boolean done = Standard_False;
343 //  BRep_Builder aB;
344   TopTools_SequenceOfShape llPosibleShells;
345   TopTools_SequenceOfShape AddShapes; 
346   for(Standard_Integer i1 = 1 ; i1<=Lface.Length();i1++ )  {
347    
348     TopoDS_Shape aShape = Lface.Value(i1);
349     
350     Standard_Integer aNbMultEdges =0;
351     
352     //Finds faces having only multiconnexity boundary.
353     for(TopoDS_Iterator aItWires(aShape,Standard_False);  aItWires.More();  aItWires.Next()) {
354       Standard_Integer aNbEdges =0;
355       for(TopoDS_Iterator aItEdges(aItWires.Value(),Standard_False);  aItEdges.More();  aItEdges.Next(),aNbEdges++) {
356         TopoDS_Shape edge = aItEdges.Value();
357         if(!aMapMultiConnectEdges.Contains(edge)) continue;
358         aNbMultEdges++;
359       }
360       if(!aNbMultEdges) continue;
361     
362       if(aNbMultEdges == aNbEdges)
363         AddShapes.Append(aShape);
364       else llPosibleShells.Append(aShape);
365     }
366   }
367   
368   // Attemp to create shell from unconnected which have not only multiconnexity boundary.
369   TopTools_SequenceOfShape aTmpShells;
370   if(!llPosibleShells.IsEmpty()) {
371     TopTools_MapOfShape aMap;
372     TopTools_SequenceOfShape aTmp;
373     TopTools_DataMapOfShapeShape aTmpFaceShell;
374     if(GetShells(llPosibleShells,aMap,aTmpShells,aTmpFaceShell,aTmp)) {
375       for(Standard_Integer kk =1; kk <= aTmpShells.Length(); kk++) {
376         TopoDS_Shape aSh = aTmpShells.Value(kk);
377         TopTools_MapOfShape mapEdges;
378         if(GetFreeEdges(aSh,mapEdges)) {
379           Standard_Integer nbedge =0;
380           for(TopTools_MapIteratorOfMapOfShape amapIter(mapEdges);amapIter.More(); amapIter.Next()) {
381             if( aMapMultiConnectEdges.Contains(amapIter.Key()))
382               nbedge++;
383           }
384           if(nbedge && nbedge == mapEdges.Extent())
385             AddShapes.Append(aSh);
386         }
387       }
388     }
389   }
390   
391   //Add choosen faces to shells.
392   for(Standard_Integer k1 =1; k1 <= AddShapes.Length(); k1++) {
393     TopTools_DataMapOfShapeInteger MapOtherShells;
394     TopTools_MapOfShape dire,reve;
395     TopoDS_Shape aSh = AddShapes.Value(k1);
396     TopTools_MapOfShape mapEdges;
397     if(!GetFreeEdges(aSh,mapEdges)) continue;
398     TopTools_ListOfShape lfaces;
399     
400     //Fill MapOtherShells which will contain shells with orientation in which selected shape aSh will be add.
401     
402     for(TopTools_MapIteratorOfMapOfShape amapIter(mapEdges);amapIter.More(); amapIter.Next()) {
403       if(!aMapMultiConnectEdges.Contains(amapIter.Key())) continue;
404       TopoDS_Edge edge = TopoDS::Edge(amapIter.Key());
405       if( edge.Orientation() == TopAbs_FORWARD) dire.Add(edge);
406       else reve.Add(edge);
407       TopTools_ListOfShape lf;
408       lf = aMapEdgeFaces.FindFromKey(edge);
409       lfaces.Append(lf);
410     }
411     for(TopTools_ListIteratorOfListOfShape aItl(lfaces) ; aItl.More(); aItl.Next()) {
412       TopoDS_Shape aF = aItl.Value();
413       if(!aMapFaceShells.IsBound( aF)) continue;
414      
415       TopoDS_Shape aOthershell;
416       aOthershell = aMapFaceShells.Find(aF);
417       if(MapOtherShells.IsBound(aOthershell)) continue;
418       if(!NonManifold && BRep_Tool::IsClosed(aOthershell))
419         continue;
420       
421       TopTools_MapOfShape mapShellEdges;
422       GetFreeEdges(aOthershell,mapShellEdges);
423       Standard_Boolean isAdd = Standard_True;
424       for(TopTools_MapIteratorOfMapOfShape amapIter1(mapEdges);amapIter1.More() && isAdd ; amapIter1.Next()) 
425         isAdd = mapShellEdges.Contains(amapIter1.Key());
426       
427       if(!isAdd) continue;
428       Standard_Integer nbdir =0, nbrev=0;
429       
430       //add only free face whome all edges contains in the shell as open boundary.
431       for(TopTools_MapIteratorOfMapOfShape aIte( mapShellEdges);aIte.More() ;aIte.Next()) {
432         TopoDS_Edge edgeS = TopoDS::Edge(aIte.Key());
433         if(!aMapMultiConnectEdges.Contains(edgeS)) continue;
434         if( (edgeS.Orientation() == TopAbs_FORWARD && dire.Contains(edgeS)) || (edgeS.Orientation() == TopAbs_REVERSED && reve.Contains(edgeS)))  nbrev++;
435         else if((edgeS.Orientation() == TopAbs_FORWARD && reve.Contains(edgeS))
436                 || (edgeS.Orientation() == TopAbs_REVERSED && dire.Contains(edgeS))) nbdir++;
437       }
438       if(nbdir && nbrev) {
439         ErrFaces.Append(aSh);
440         continue;
441       }
442       if(nbdir || nbrev) {
443         Standard_Integer isReverse =(nbrev ? 1: 0);
444         MapOtherShells.Bind(aOthershell,isReverse);
445       }
446       
447     }
448     if(MapOtherShells.IsEmpty()) {
449 //      i1++;
450       continue;
451     }
452     
453     //Adds face to open shells containg the same multishared edges.
454     //For nonmanifold mode creation ine shell from face and shells containing the same multishared edges.
455     // If one face can be added to a few shells (case of compsolid) face will be added to each shell.
456     done = Standard_True;
457     Standard_Integer FirstRev = 0,FirstInd =0;
458     Standard_Integer ind =0;
459     for(Standard_Integer l =1; l <= SeqShells.Length(); l++) {
460       if(!MapOtherShells.IsBound(SeqShells.Value(l))) continue;
461       ind++;
462       Standard_Integer isRev = MapOtherShells.Find(SeqShells.Value(l));
463       TopoDS_Shape anewShape = (isRev ? aSh.Reversed() :aSh);
464      
465       BRep_Builder aB1;
466       TopoDS_Shape aShell = SeqShells.Value(l);
467       if(ind ==1 || !NonManifold) {
468         if(ind ==1) {
469           FirstRev = isRev;
470           FirstInd = l;
471         }
472         for(TopExp_Explorer aE(anewShape,TopAbs_FACE); aE.More(); aE.Next())
473           aB1.Add(aShell,aE.Current());
474         SeqShells.ChangeValue(l) = aShell;
475       }
476       else if(NonManifold) {
477         Standard_Boolean isReversed = !((!(isRev) && !FirstRev) || ((isRev) && FirstRev));
478         aShell = SeqShells.Value(FirstInd);
479         for(TopoDS_Iterator aItF(SeqShells.Value(l),Standard_False); aItF.More(); aItF.Next()) {
480           TopoDS_Shape nF = ( isReversed ? aItF.Value().Reversed() : aItF.Value());
481           aB1.Add(aShell,nF);
482         }
483         SeqShells.ChangeValue(FirstInd) = aShell;
484         SeqShells.Remove(l--);
485       }
486     }
487       
488     dire.Clear();
489     reve.Clear();
490     for(TopExp_Explorer aEt(aSh,TopAbs_FACE); aEt.More(); aEt.Next()) {
491       for(Standard_Integer kk =1 ; kk <= Lface.Length(); kk++) {
492         if(aEt.Current().IsSame(Lface.Value(kk)))
493           Lface.Remove(kk--);
494       }
495     }
496   }
497   return done;
498 }
499
500 //=======================================================================
501 // function : BoxIn
502 // purpose  : Check if one face contains inside other.
503 //=======================================================================
504 static Standard_Integer BoxIn(const Bnd_Box& theBox1,const Bnd_Box& theBox2)
505 {
506      Standard_Integer aNumIn = 0;
507      Standard_Real aXmin1,aYmin1,aXmax1,aYmax1,aXmin2,aYmin2,aXmax2,aYmax2,aZmin1,aZmax1,aZmin2,aZmax2;
508      theBox1.Get(aXmin1,aYmin1,aZmin1,aXmax1,aYmax1,aZmax1);
509      theBox2.Get(aXmin2,aYmin2,aZmin2,aXmax2,aYmax2,aZmax2);
510      if(aXmin1 == aXmin2 && aXmax1 == aXmax2 && aYmin1 == aYmin2 && aYmax1 == aYmax2 &&
511         aZmin1 == aZmin2 && aZmax1 == aZmax2)
512        aNumIn = 0;
513      else if( aXmin1 >= aXmin2 && aXmax1 <= aXmax2 && aYmin1 >= aYmin2 && aYmax1 <= aYmax2 &&
514         aZmin1 >= aZmin2 && aZmax1 <= aZmax2)  
515         aNumIn = 1;
516      else if( aXmin1 <= aXmin2 && aXmax1 >= aXmax2 && aYmin1 <= aYmin2 && aYmax1 >= aYmax2 && aZmin1 <= aZmin2 && aZmax1 >= aZmax2)
517        aNumIn = 2;
518      return aNumIn;
519 }
520 //=======================================================================
521 // function : GetClosedShells
522 // purpose  : Check if one shell is a part from other shell.
523 //            For case of compsolid when afew shells are created from
524 //            the same set of faces.
525 //=======================================================================
526 static void GetClosedShells(TopTools_SequenceOfShape& Shells, TopTools_SequenceOfShape& aRemainShells)
527 {
528   Bnd_Array1OfBox aBoxes(1,Shells.Length());
529   for(Standard_Integer i =1; i <= Shells.Length(); i++) {
530     Bnd_Box Box;
531     BRepBndLib::AddClose(Shells.Value(i),Box);
532     aBoxes.SetValue(i,Box);
533   }
534   TColStd_MapOfInteger aMapNum;
535   for(Standard_Integer j = 1; j <= aBoxes.Length(); j++) {
536     for(Standard_Integer k = j+1; k <= aBoxes.Length(); k++) {
537       Standard_Integer NumIn = BoxIn(aBoxes.Value(j),aBoxes.Value(k));
538       switch(NumIn) {
539       case 1:aMapNum.Add(k); break;
540       case 2: aMapNum.Add(j); break;
541         default : break;
542       }
543     }
544   }
545   for(Standard_Integer i1 =1; i1 <= Shells.Length(); i1++) {
546     if(!aMapNum.Contains(i1))
547       aRemainShells.Append(Shells.Value(i1));
548   }
549   
550 }
551 //=======================================================================
552 // function : GlueClosedCandidate
553 // purpose  :Attemt firstly to create closed shells from sequence of open shells.
554 //=======================================================================
555 static void GlueClosedCandidate(TopTools_SequenceOfShape& OpenShells,
556                                                     const TopTools_MapOfShape& aMapMultiConnectEdges,
557                                                     TopTools_SequenceOfShape& aSeqNewShells)
558                                                     
559 {
560   // Creating new shells if some open shells contain the same free boundary.
561   for(Standard_Integer i = 1 ; i < OpenShells.Length();i++ )  {
562     TopoDS_Shape aShell = OpenShells.Value(i);
563     TopTools_MapOfShape mapEdges1;
564     TopTools_MapOfShape dire,reve;
565     if(!GetFreeEdges(aShell,mapEdges1)) continue;
566     
567     for(TopTools_MapIteratorOfMapOfShape aIte( mapEdges1);aIte.More() ;aIte.Next()) {
568       TopoDS_Edge edge1 = TopoDS::Edge(aIte.Key());
569       if(!aMapMultiConnectEdges.Contains(edge1)) break;
570       if(edge1.Orientation() == TopAbs_FORWARD) dire.Add(edge1);
571       else if(edge1.Orientation() == TopAbs_REVERSED) reve.Add(edge1);
572     }
573     if(mapEdges1.Extent() >(dire.Extent() + reve.Extent())) continue;
574     
575     //Filling map MapOtherShells which contains candidate to creation of closed shell
576     // with aShell.
577     
578     TopTools_DataMapOfShapeInteger MapOtherShells;
579     
580     for(Standard_Integer j = i+1 ; j <= OpenShells.Length();j++ )  {
581       Standard_Boolean isAddShell = Standard_True;
582       Standard_Boolean isReversed = Standard_False;
583       Standard_Integer nbedge =0;
584       TopTools_MapOfShape mapEdges2;
585       TopoDS_Shape aShell2 = OpenShells.Value(j);
586       if(!GetFreeEdges(aShell2,mapEdges2)) continue;
587       for(TopTools_MapIteratorOfMapOfShape aIte2( mapEdges2);aIte2.More() && isAddShell;aIte2.Next()) {
588         TopoDS_Edge edge2 = TopoDS::Edge(aIte2.Key());
589         if(!aMapMultiConnectEdges.Contains(edge2)) {
590           isAddShell = Standard_False;
591           break;
592           //continue;
593         }
594         isAddShell = (dire.Contains(edge2) || reve.Contains(edge2)); 
595         if((edge2.Orientation() == TopAbs_FORWARD && dire.Contains(edge2))
596            || (edge2.Orientation() == TopAbs_REVERSED && reve.Contains(edge2)))
597           isReversed = Standard_True;
598         nbedge++;
599       }
600       
601       if(!isAddShell) continue;
602       MapOtherShells.Bind(OpenShells.Value(j),isReversed);
603     }
604     if(!MapOtherShells.Extent()) continue;
605     
606     
607     if(MapOtherShells.Extent() >1) {
608       
609       // Case of compsolid when more than two shells have the same free boundary.
610       TopTools_SequenceOfShape aSeqCandidate;
611       aSeqCandidate.Append(OpenShells.Value(i));
612       
613       for(TopTools_DataMapIteratorOfDataMapOfShapeInteger aIt(MapOtherShells); aIt.More(); aIt.Next())
614        aSeqCandidate.Append(aIt.Key());
615       
616       //Creation all possibly shells from choosen candidate.And
617       // addition of them to temporary sequence.
618       
619       TopTools_SequenceOfShape aTmpSeq;
620       for(Standard_Integer k =1; k <= aSeqCandidate.Length(); k++) {
621         
622         for(Standard_Integer l = k+1; l <= aSeqCandidate.Length(); l++) {
623           TopoDS_Shell aNewSh;
624           BRep_Builder aB;
625           aB.MakeShell(aNewSh);
626           for(TopoDS_Iterator aIt1(aSeqCandidate.Value(k),Standard_False); aIt1.More(); aIt1.Next())
627             aB.Add(aNewSh,aIt1.Value());
628           Standard_Integer isRev = MapOtherShells.Find(aSeqCandidate.Value(l));
629           if(k !=1) {
630             isRev = ((isRev == MapOtherShells.Find(aSeqCandidate.Value(k))) ? 1 : 0);
631           }
632           for(TopExp_Explorer aExp(aSeqCandidate.Value(l),TopAbs_FACE); aExp.More(); aExp.Next()) {
633             TopoDS_Shape aFace = (isRev ? aExp.Current().Reversed(): aExp.Current());
634             aB.Add(aNewSh,aFace);
635           }
636           aTmpSeq.Append(aNewSh);
637         }
638       }
639       
640       //Choice from temporary sequence shells contains different set of faces (case of compsolid) 
641       TopTools_SequenceOfShape aRemainShells;
642       GetClosedShells(aTmpSeq,aRemainShells);
643       aSeqNewShells.Append(aRemainShells);
644       
645       for(Standard_Integer j1 = i+1 ; j1 <= OpenShells.Length();j1++ )  {
646         if(!MapOtherShells.IsBound(OpenShells.Value(j1))) continue;
647         OpenShells.Remove(j1--);
648       }
649       
650     }
651     else {
652       BRep_Builder aB;
653       TopoDS_Shape aNewShell = aShell;
654       TopoDS_Shape addShell;
655       Standard_Boolean isReversed = Standard_False;
656       for(Standard_Integer j1 = i+1 ; j1 <= OpenShells.Length();j1++ )  {
657         if(!MapOtherShells.IsBound(OpenShells.Value(j1))) continue;
658         addShell = OpenShells.Value(j1);
659         isReversed = MapOtherShells.Find(addShell);
660         OpenShells.Remove(j1);
661         break;
662       }
663       
664       for(TopExp_Explorer aExpF(addShell,TopAbs_FACE); aExpF.More(); aExpF.Next()) {
665         TopoDS_Shape aFace = aExpF.Current();
666         if(isReversed)
667           aFace.Reverse();
668         aB.Add(aNewShell,aFace);
669       }
670       aSeqNewShells.Append(aNewShell);
671     }
672     
673     //OpenShells.ChangeValue(i) = aShell;
674     OpenShells.Remove(i--);
675   }
676 }
677 //=======================================================================
678 // function : CreateNonManifoldShells
679 // purpose  : Attempt to create max possible shells from open shells.
680 //=======================================================================
681
682 static void CreateNonManifoldShells(TopTools_SequenceOfShape& SeqShells,
683                               const TopTools_MapOfShape& aMapMultiConnectEdges)
684 {
685   TopTools_IndexedDataMapOfShapeListOfShape aMap;
686   for(Standard_Integer i =1 ; i <= SeqShells.Length(); i++) {
687     TopoDS_Shape aShell = SeqShells.Value(i);
688     TopTools_IndexedMapOfShape medeg;
689     TopExp::MapShapes(aShell,TopAbs_EDGE,medeg);
690     for(TopTools_MapIteratorOfMapOfShape mit(aMapMultiConnectEdges); mit.More(); mit.Next()) {
691     //for(TopExp_Explorer aExp(aShell,TopAbs_EDGE); aExp.More(); aExp.Next(),nbe++) {
692       //TopoDS_Shape ae = aExp.Current();
693       TopoDS_Shape ae =mit.Key();
694       //if( aMapMultiConnectEdges.Contains(aExp.Current())) {
695       if(medeg.Contains(ae)) {
696         if(aMap.Contains(ae))
697          aMap.ChangeFromKey(ae).Append(aShell);
698         else {
699           TopTools_ListOfShape al;
700           al.Append(aShell);
701           aMap.Add(ae,al);
702         }
703       }
704     }
705   }
706   TopTools_IndexedDataMapOfShapeShape aMapShells;
707   for(Standard_Integer j =1; j <= aMap.Extent(); j++) {
708     const TopTools_ListOfShape& LShells = aMap.FindFromIndex(j);
709     TopoDS_Shell aNewShell;
710     BRep_Builder aB;
711     aB.MakeShell(aNewShell);
712     TopTools_MapOfShape mapmerge;
713     Standard_Boolean ismerged = Standard_False;
714     Standard_Integer num = 1;
715     for(TopTools_ListIteratorOfListOfShape alit(LShells); alit.More();alit.Next(),num++) { 
716       if(!aMapShells.Contains(alit.Value())) {
717         for(TopExp_Explorer aEf(alit.Value(),TopAbs_FACE); aEf.More(); aEf.Next()) {
718           aB.Add(aNewShell,aEf.Current());
719         }
720         ismerged = Standard_True;
721         mapmerge.Add(alit.Value());
722       }
723       else if(ismerged) {
724         TopoDS_Shape arshell = aMapShells.FindFromKey(alit.Value());
725         while(aMapShells.Contains(arshell)){
726           TopoDS_Shape ss = aMapShells.FindFromKey(arshell);
727           if(ss.IsSame(arshell)) break;
728           arshell = ss;
729         }
730          
731         if(!mapmerge.Contains(arshell)) {
732           for(TopExp_Explorer aEf(arshell,TopAbs_FACE); aEf.More(); aEf.Next()) {
733             aB.Add(aNewShell,aEf.Current());
734           }
735           mapmerge.Add(arshell);
736         }
737       }
738       else {
739         TopoDS_Shape arshell = aMapShells.FindFromKey(alit.Value());
740          while(aMapShells.Contains(arshell)) {
741           TopoDS_Shape ss = aMapShells.FindFromKey(arshell);
742           if(ss.IsSame(arshell)) break;
743           arshell = ss;
744         }
745         if(num == 1) {
746           for(TopExp_Explorer aEf(arshell,TopAbs_FACE); aEf.More(); aEf.Next()) 
747             aB.Add(aNewShell,aEf.Current());
748           
749           mapmerge.Add(arshell);
750         }
751         else if(!mapmerge.Contains(arshell)) {
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       }
758     }
759     if(mapmerge.Extent() >1 || ismerged) {
760       for(TopTools_MapIteratorOfMapOfShape alit1(mapmerge); alit1.More();alit1.Next()) {
761         TopoDS_Shape oldShell = alit1.Key();
762          //while(aMapShells.Contains(oldShell)) {
763          //  TopoDS_Shape ss = aMapShells.FindFromKey(oldShell);
764          //  if(ss.IsSame(oldShell)) break;
765          //  oldShell = ss;
766          //}
767         aMapShells.Add(oldShell,aNewShell);
768       }
769     }
770   }
771   TopTools_IndexedMapOfShape MapNewShells;
772   for(Standard_Integer nn = 1;nn <= SeqShells.Length(); nn++) {
773     if(aMapShells.Contains(SeqShells.Value(nn))) {
774       TopoDS_Shape aNewShell = aMapShells.FindFromKey(SeqShells.Value(nn));
775       while(aMapShells.Contains(aNewShell)) {
776         TopoDS_Shape ss = aMapShells.FindFromKey(aNewShell);
777         if(ss.IsSame(aNewShell)) break;
778         aNewShell = ss;
779       }
780       MapNewShells.Add(aNewShell);
781       
782       SeqShells.Remove(nn--);
783     }
784     
785   }
786   for(Standard_Integer ii =1; ii <= MapNewShells.Extent(); ii++)
787     SeqShells.Append(MapNewShells.FindKey(ii));
788 }
789 //=======================================================================
790 // function : CreateClosedShell
791 // purpose  : Attempt to create max possible shells from open shells.
792 //=======================================================================
793
794 static void CreateClosedShell(TopTools_SequenceOfShape& OpenShells,
795                               const TopTools_MapOfShape& aMapMultiConnectEdges)
796 {
797   TopTools_SequenceOfShape aNewShells;
798   //Attemt firstly to create closed shells.
799   GlueClosedCandidate(OpenShells,aMapMultiConnectEdges,aNewShells);
800   
801   // Creating new shells if some open shells contain the multishared same edges.
802   for(Standard_Integer i = 1 ; i < OpenShells.Length();i++ )  {
803     Standard_Boolean isAddShell = Standard_False;
804     TopoDS_Shape aShell = OpenShells.Value(i);
805     Standard_Boolean isReversed = Standard_False;
806     for(Standard_Integer j = i+1 ; j <= OpenShells.Length();j++ )  {
807       TopTools_MapOfShape mapEdges1;
808       TopTools_MapOfShape dire,reve;
809       if(!GetFreeEdges(aShell,mapEdges1)) break;
810       for(TopTools_MapIteratorOfMapOfShape aIte( mapEdges1);aIte.More() ;aIte.Next()) {
811         TopoDS_Edge edge1 = TopoDS::Edge(aIte.Key());
812         if(!aMapMultiConnectEdges.Contains(edge1)) continue;
813         if(edge1.Orientation() == TopAbs_FORWARD) dire.Add(edge1);
814         else if(edge1.Orientation() == TopAbs_REVERSED) reve.Add(edge1);
815       }
816       if(dire.IsEmpty() &&  reve.IsEmpty()) break;
817       TopTools_MapOfShape mapEdges2;
818       TopoDS_Shape aShell2 = OpenShells.Value(j);
819       if(!GetFreeEdges(aShell2,mapEdges2)) continue;
820       for(TopTools_MapIteratorOfMapOfShape aIte2( mapEdges2);aIte2.More() ;aIte2.Next()) {
821         TopoDS_Edge edge2 = TopoDS::Edge(aIte2.Key());
822         if(!aMapMultiConnectEdges.Contains(edge2)) continue;
823         if(!dire.Contains(edge2) && !reve.Contains(edge2)) continue;
824         isAddShell = Standard_True;
825         if((edge2.Orientation() == TopAbs_FORWARD && dire.Contains(edge2))
826            || (edge2.Orientation() == TopAbs_REVERSED && reve.Contains(edge2)))
827           isReversed = Standard_True;
828       }
829       
830       if(!isAddShell) continue;
831       BRep_Builder aB;
832       
833       for(TopExp_Explorer aExpF21(OpenShells.Value(j),TopAbs_FACE); aExpF21.More(); aExpF21.Next()) {
834         TopoDS_Shape aFace = aExpF21.Current();
835         if(isReversed)
836           aFace.Reverse();
837         aB.Add( aShell,aFace);
838       }
839       
840       OpenShells.ChangeValue(i) = aShell;
841       OpenShells.Remove(j--);
842     }
843   }
844  
845   OpenShells.Append(aNewShells);
846   
847 }
848   
849
850 //=======================================================================
851 // function : FixFaceOrientation
852 // purpose  : 
853 //=======================================================================
854   
855 Standard_Boolean ShapeFix_Shell::FixFaceOrientation(const TopoDS_Shell& shell,const Standard_Boolean isAccountMultiConex,const Standard_Boolean NonManifold) 
856 {
857   //myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
858   Standard_Boolean done = Standard_False;
859   TopTools_SequenceOfShape aSeqShells;
860   TopTools_SequenceOfShape aErrFaces; // Compound of faces like to Mebiuce leaf.
861   TopTools_SequenceOfShape Lface;
862   TopTools_DataMapOfShapeShape aMapFaceShells;
863   myShell = shell;
864   myShape = shell;
865   Standard_Integer aNumMultShell =0;
866   for (TopoDS_Iterator iter(shell); iter.More(); iter.Next()) 
867     Lface.Append(iter.Value());
868   TopTools_IndexedDataMapOfShapeListOfShape aMapEdgeFaces;
869   TopExp::MapShapesAndAncestors(myShell,TopAbs_EDGE,TopAbs_FACE,aMapEdgeFaces);
870   TopTools_MapOfShape aMapMultiConnectEdges;
871   Standard_Boolean isFreeBoundaries = Standard_False;
872   for(Standard_Integer k = 1; k <= aMapEdgeFaces.Extent(); k++) {
873     const Standard_Integer aFaceCount = aMapEdgeFaces.FindFromIndex(k).Extent();
874     if (!isFreeBoundaries && aFaceCount == 1) {
875       TopoDS_Edge E = TopoDS::Edge(aMapEdgeFaces.FindKey(k));
876       if (!BRep_Tool::Degenerated(E))
877         isFreeBoundaries = Standard_True;
878     }
879     //Finds multishared edges
880     else if (isAccountMultiConex && aFaceCount > 2)
881       aMapMultiConnectEdges.Add(aMapEdgeFaces.FindKey(k));
882   }
883   if (BRep_Tool::IsClosed(myShell)? isFreeBoundaries : !isFreeBoundaries)
884   {
885     myShell.Closed (!isFreeBoundaries);
886     SendWarning (Message_Msg ("FixAdvShell.FixClosedFlag.MSG0"));//Shell has incorrect flag isClosed
887   }
888   Standard_Boolean isGetShells = Standard_True;
889   //Gets possible shells with taking in account of multiconnexity.
890   while(isGetShells && Lface.Length()) {
891     TopTools_SequenceOfShape aTmpSeqShells;
892     if(GetShells(Lface, aMapMultiConnectEdges, aTmpSeqShells,aMapFaceShells,aErrFaces)) {
893       done = Standard_True;
894     }
895     isGetShells = !aTmpSeqShells.IsEmpty();
896     if(isGetShells) 
897       aSeqShells.Append(aTmpSeqShells);
898   }
899   if(!done)
900     done = (aSeqShells.Length() >1);
901   Standard_Boolean aIsDone = Standard_False;
902   if(Lface.Length() > 0 && aSeqShells.Length()) {
903     for(Standard_Integer jj =1; jj <= Lface.Length(); jj++) {
904       if(aMapFaceShells.IsBound(Lface.Value(jj)))
905         aMapFaceShells.UnBind(Lface.Value(jj));
906     }
907     
908     //Addition of faces having only multiconnexity boundary to shells having holes
909     // containing only the multiconnexity edges
910     aIsDone = AddMultiConexityFaces(Lface,aMapMultiConnectEdges,aSeqShells,aMapFaceShells,
911                                     aMapEdgeFaces,aErrFaces,NonManifold);
912   }
913   aNumMultShell = aSeqShells.Length();
914   if (!aErrFaces.IsEmpty())  {
915     
916     //if Shell contains of Mebius faces one shell will be created from each those face.
917     BRep_Builder B;
918     B.MakeCompound(myErrFaces);
919     TopoDS_Compound aCompShells;
920     B.MakeCompound(aCompShells);
921     for(Standard_Integer n =1; n <= aErrFaces.Length(); n++)
922       B.Add(myErrFaces,aErrFaces.Value(n));
923     if(aNumMultShell) {
924       if(aNumMultShell == 1) {
925         B.Add(aCompShells,aSeqShells.Value(1));
926         for(Standard_Integer n1 =1; n1 <= aErrFaces.Length(); n1++) {
927           TopoDS_Shell aSh;
928           B.MakeShell(aSh);
929           B.Add(aSh,aErrFaces.Value(n1));
930            B.Add(aCompShells,aSh);
931         }
932         myShape = aCompShells;
933       }
934       else {
935         for(Standard_Integer i =1; i <= aSeqShells.Length(); i++)
936           B.Add(aCompShells,aSeqShells.Value(i));
937         for(Standard_Integer n1 =1; n1 <= aErrFaces.Length(); n1++) {
938           TopoDS_Shell aSh;
939           B.MakeShell(aSh);
940           B.Add(aSh,aErrFaces.Value(n1));
941            B.Add(aCompShells,aSh);
942         }
943         myShape = aCompShells;
944       }
945     }
946     
947     done = Standard_True;
948     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_FAIL);
949     SendWarning ( Message_Msg ( "FixAdvShell.FixOrientation.MSG20" ) );// Impossible to orient faces in shell, several shells created
950     return Standard_True;
951   }
952   if(aNumMultShell >1) {
953     TopTools_SequenceOfShape OpenShells;
954     for(Standard_Integer i1 =1; i1 <= aSeqShells.Length(); i1++) {
955       TopoDS_Shape aShell = aSeqShells.Value(i1);
956       if(!BRep_Tool::IsClosed(aShell)) {
957         OpenShells.Append(aShell);
958         aSeqShells.Remove(i1--);
959        }
960     }
961     if(OpenShells.Length() >1) 
962       //Attempt of creation closed shell from open shells with taking into account multiconnexity.
963       CreateClosedShell(OpenShells,aMapMultiConnectEdges);
964     aSeqShells.Append(OpenShells);
965     
966   }
967   
968   // In the case if NonManifold is equal to Standard_True one non-manifold shell will be created.
969   //Else compound from shells will be created if length of sequence of shape >1.
970   if(Lface.Length()) {
971    
972     for(Standard_Integer i = 1; i <= Lface.Length();i++) {
973       BRep_Builder aB;
974       TopoDS_Shell OneShell;
975       aB.MakeShell(OneShell);
976       aB.Add(OneShell, Lface.Value(i));
977       aSeqShells.Append(OneShell);
978     }
979       
980   }
981   if(NonManifold && aSeqShells.Length() >1 ) {
982     CreateNonManifoldShells(aSeqShells,aMapMultiConnectEdges);
983   }
984   if(!done)
985     done = (aSeqShells.Length() >1 || aIsDone);
986   if(aSeqShells.Length() == 1) {
987     myShell = TopoDS::Shell(aSeqShells.Value(1));
988     myShape =myShell;
989     myNbShells =1;
990   }
991   else {
992     BRep_Builder B;
993     TopoDS_Compound aCompShells;
994     B.MakeCompound(aCompShells);
995     for(Standard_Integer i =1; i <= aSeqShells.Length(); i++)
996       B.Add(aCompShells,aSeqShells.Value(i));  
997     myShape = aCompShells;
998     myNbShells =  aSeqShells.Length();
999   }
1000   if(done) {
1001     myStatus = ShapeExtend::EncodeStatus (ShapeExtend_DONE2);
1002     if(!Context().IsNull())
1003       Context()->Replace(shell, myShape);
1004     if ( myNbShells == 1 )
1005       SendWarning ( Message_Msg ( "FixAdvShell.FixOrientation.MSG0" ) );// Faces were incorrectly oriented in the shell, corrected
1006     else
1007       SendWarning ( Message_Msg ( "FixAdvShell.FixOrientation.MSG30" ) );// Improperly connected shell split into parts
1008     return Standard_True;
1009   }
1010   else return Standard_False;
1011 }
1012
1013 //=======================================================================
1014 //function : Status
1015 //purpose  : 
1016 //=======================================================================
1017
1018 Standard_Boolean ShapeFix_Shell::Status(const ShapeExtend_Status status) const
1019 {
1020   return ShapeExtend::DecodeStatus (myStatus, status);
1021 }
1022
1023 //=======================================================================
1024 //function : Shell
1025 //purpose  : 
1026 //=======================================================================
1027
1028 TopoDS_Shell ShapeFix_Shell::Shell() 
1029 {
1030  return myShell; 
1031 }
1032 //=======================================================================
1033 //function : Shell
1034 //purpose  : 
1035 //=======================================================================
1036
1037 TopoDS_Shape ShapeFix_Shell::Shape() 
1038 {
1039  return myShape; 
1040 }
1041
1042 //=======================================================================
1043 //function : ErrorFaces
1044 //purpose  : 
1045 //=======================================================================
1046
1047 TopoDS_Compound ShapeFix_Shell::ErrorFaces() const
1048 {
1049   return myErrFaces;
1050 }
1051
1052 //=======================================================================
1053 //function : SetMsgRegistrator
1054 //purpose  : 
1055 //=======================================================================
1056
1057 void ShapeFix_Shell::SetMsgRegistrator(const Handle(ShapeExtend_BasicMsgRegistrator)& msgreg)
1058 {
1059   ShapeFix_Root::SetMsgRegistrator ( msgreg );
1060   myFixFace->SetMsgRegistrator ( msgreg );
1061 }
1062
1063 //=======================================================================
1064 //function : SetPrecision
1065 //purpose  : 
1066 //=======================================================================
1067
1068 void ShapeFix_Shell::SetPrecision (const Standard_Real preci) 
1069 {
1070   ShapeFix_Root::SetPrecision ( preci );
1071   myFixFace->SetPrecision ( preci );
1072 }
1073
1074 //=======================================================================
1075 //function : SetMinTolerance
1076 //purpose  : 
1077 //=======================================================================
1078
1079 void ShapeFix_Shell::SetMinTolerance (const Standard_Real mintol) 
1080 {
1081   ShapeFix_Root::SetMinTolerance ( mintol );
1082   myFixFace->SetMinTolerance ( mintol );
1083 }
1084
1085 //=======================================================================
1086 //function : SetMaxTolerance
1087 //purpose  : 
1088 //=======================================================================
1089
1090 void ShapeFix_Shell::SetMaxTolerance (const Standard_Real maxtol) 
1091 {
1092   ShapeFix_Root::SetMaxTolerance ( maxtol );
1093   myFixFace->SetMaxTolerance ( maxtol );
1094 }
1095 //=======================================================================
1096 //function : NbShells
1097 //purpose  : 
1098 //=======================================================================
1099
1100 Standard_Integer ShapeFix_Shell::NbShells() const
1101 {
1102   return myNbShells;
1103 }