0022746: Progress indicator in ShapeHealing
[occt.git] / src / ShapeFix / ShapeFix_Solid.cxx
1 #include <ShapeFix_Solid.ixx>
2   
3 #include <Standard_ErrorHandler.hxx>
4 #include <Standard_Failure.hxx>
5   
6 #include <BRep_Builder.hxx>
7 #include <BRepClass3d_SolidClassifier.hxx>
8 #include <Precision.hxx>
9 #include <TopoDS_Shape.hxx>
10 #include <ShapeBuild_ReShape.hxx> 
11 #include <TopoDS_Iterator.hxx>
12 #include <TopoDS.hxx>
13 #include <ShapeExtend.hxx>
14 #include <ShapeAnalysis_Edge.hxx>
15 #include <ShapeAnalysis_Curve.hxx>
16 #include <TopoDS_Wire.hxx>
17 #include <ShapeExtend_WireData.hxx>
18 #include <TopTools_MapIteratorOfMapOfShape.hxx>
19 #include <TopoDS_Iterator.hxx>
20 #include <TopTools_MapOfShape.hxx>
21 #include <TopTools_DataMapOfShapeListOfShape.hxx>
22 #include <TopTools_SequenceOfShape.hxx>
23 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
24 #include <TopExp.hxx>
25 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
26 #include <gp_Pnt.hxx>
27 #include <Bnd_Box2d.hxx>
28 #include <ShapeAnalysis.hxx>
29 #include <TopoDS_Edge.hxx>
30 #include <BRep_Tool.hxx>
31 #include <Geom_Surface.hxx>
32 #include <TopTools_ListOfShape.hxx>
33 #include <Precision.hxx>
34 #include <TopAbs.hxx>
35 #include <TopTools_ListIteratorOfListOfShape.hxx>
36 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
37 #include <TopTools_ListIteratorOfListOfShape.hxx>
38 #include <TopoDS_Solid.hxx>
39 #include <BRep_Builder.hxx>
40 #include <TopoDS_CompSolid.hxx>
41 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
42 #include <TopAbs.hxx>
43 #include <BRep_Tool.hxx>
44 #include <TopTools_IndexedMapOfShape.hxx>
45 #include <TopTools_IndexedDataMapOfShapeShape.hxx>
46 #include <Message_Msg.hxx>
47 #include <Message_ProgressSentry.hxx>
48 #include <TopoDS_Vertex.hxx>
49 #include <TopTools_IndexedMapOfShape.hxx>
50
51 #include <TopTools_DataMapOfShapeInteger.hxx>
52 #include <Geom_Curve.hxx>
53 #include <ShapeAnalysis_FreeBounds.hxx>
54   
55 //======================================================
56 //function : ShapeFix_Solid
57 //purpose  : 
58 //=======================================================================
59
60 ShapeFix_Solid::ShapeFix_Solid()
61 {
62   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
63   myFixShellMode = -1;
64   myFixShell = new ShapeFix_Shell;
65   myCreateOpenSolidMode = Standard_False;
66 }
67
68 //=======================================================================
69 //function : ShapeFix_Solid
70 //purpose  : 
71 //=======================================================================
72
73 ShapeFix_Solid::ShapeFix_Solid(const TopoDS_Solid& solid)
74 {
75   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
76   myFixShellMode = -1;
77   myFixShell = new ShapeFix_Shell;
78   myCreateOpenSolidMode = Standard_False;
79   Init(solid);
80 }
81
82 //=======================================================================
83 //function : Init
84 //purpose  : 
85 //=======================================================================
86
87  void ShapeFix_Solid::Init(const TopoDS_Solid& solid) 
88 {
89   mySolid = solid;
90   //mySolid = TopoDS::Solid(shape.EmptyCopied());
91   //BRep_Builder B;
92  // for( TopoDS_Iterator iter(solid); iter.More(); iter.Next()) 
93  //  B.Add(mySolid,TopoDS::Shell(iter.Value()));
94   myShape = solid;
95 }
96 //=======================================================================
97 //function : CollectSolids
98 //purpose  : 
99 //=======================================================================
100 static void GetMiddlePoint(const TopoDS_Shape& aShape, gp_Pnt& pmid)
101 {
102   TopExp_Explorer aExp(aShape,TopAbs_EDGE);
103   gp_XYZ center(0.0,0.0,0.0);
104   Standard_Integer numpoints =0;
105   for( ; aExp.More(); aExp.Next()) {
106     TopoDS_Edge e1 = TopoDS::Edge(aExp.Current());
107     Standard_Real f,l;
108     Handle(Geom_Curve) c3d = BRep_Tool::Curve(e1,f,l);
109     if(!c3d.IsNull()) {
110       for(Standard_Integer i =1 ; i <=5; i++) {
111         Standard_Real param = f+(l-f)/4*(i-1);
112         gp_Pnt pt;
113         numpoints++;
114         c3d->D0(param,pt);
115         center+=pt.XYZ();
116       
117       }
118     }
119   }
120   center /= numpoints;
121   pmid.SetXYZ(center);
122 }
123 static void CollectSolids(const TopTools_SequenceOfShape& aSeqShells , 
124                           TopTools_DataMapOfShapeListOfShape& aMapShellHoles,
125                           TopTools_DataMapOfShapeInteger& theMapStatus)
126 {
127   TopTools_MapOfShape aMapHoles;
128   for ( Standard_Integer i1 = 1; i1 <= aSeqShells.Length(); i1++ ) {
129     TopoDS_Shell aShell1 = TopoDS::Shell(aSeqShells.Value(i1));
130     TopTools_ListOfShape lshells;
131     aMapShellHoles.Bind(aShell1,lshells);
132   }
133   //Finds roots shells and hole shells.
134   for ( Standard_Integer i = 1; i <= aSeqShells.Length(); i++ ) {
135     TopoDS_Shell aShell1 =  TopoDS::Shell(aSeqShells.Value(i));
136     TopExp_Explorer aExpEdges(aShell1,TopAbs_EDGE);
137     if(!BRep_Tool::IsClosed(aShell1) || !aExpEdges.More()) continue;
138     TopoDS_Solid solid;
139     BRep_Builder B;
140     B.MakeSolid (solid);
141     B.Add (solid,aShell1);
142     try {
143       OCC_CATCH_SIGNALS
144      TopAbs_State infinstatus = TopAbs_UNKNOWN;
145      BRepClass3d_SolidClassifier bsc3d (solid);
146      Standard_Integer st = 0;
147      if(!theMapStatus.IsBound(aShell1)) {
148          
149          bsc3d.PerformInfinitePoint(Precision::Confusion());
150          infinstatus = bsc3d.State();
151          
152          if(infinstatus != TopAbs_UNKNOWN &&  infinstatus !=TopAbs_ON)
153            st = (infinstatus == TopAbs_IN ? 1 :2);
154          theMapStatus.Bind(aShell1,st);
155          
156        
157        }
158       else {
159         st = theMapStatus.Find(aShell1);
160         if(st)
161           infinstatus =  (theMapStatus.Find(aShell1) == 1 ? TopAbs_IN : TopAbs_OUT);
162       }
163       if(!st) continue;
164       for ( Standard_Integer j = 1; j <= aSeqShells.Length(); j++ ) {
165         if(i==j) continue;
166         TopoDS_Shape aShell2 = aSeqShells.Value(j);
167         if(!BRep_Tool::IsClosed(aShell2)) continue;
168         if(aMapHoles.Contains(aShell2)) continue;
169         if(aMapShellHoles.IsBound(aShell2)) {
170           Standard_Boolean isAnalysis = Standard_False;
171           const TopTools_ListOfShape& ls = aMapShellHoles.Find(aShell2);
172           for(TopTools_ListIteratorOfListOfShape li(ls); li.More() && !isAnalysis; li.Next())
173             isAnalysis = li.Value().IsSame(aShell1);
174           if(isAnalysis) continue;
175         }
176         TopAbs_State pointstatus = TopAbs_UNKNOWN;
177         Standard_Integer numon =0;
178         TopTools_IndexedMapOfShape amapVert;
179         for(TopExp_Explorer aExpVert(aShell2,TopAbs_VERTEX); aExpVert.More() && amapVert.Extent() < 10; aExpVert.Next())
180           amapVert.Add(aExpVert.Current());
181         for(Standard_Integer k = 1; k <= amapVert.Extent() && 
182             (pointstatus ==TopAbs_UNKNOWN || (pointstatus ==TopAbs_ON && numon < 3)); k++) {
183           TopoDS_Vertex aV = TopoDS::Vertex(amapVert.FindKey(k));
184           gp_Pnt aPf =  BRep_Tool::Pnt(aV);
185           bsc3d.Perform(aPf,Precision::Confusion());
186           pointstatus =bsc3d.State();
187           if(pointstatus ==TopAbs_ON) numon++;
188         }
189         
190         if(numon == 3 && pointstatus ==TopAbs_ON) {
191           //gp_Pnt pmid;
192           //GetMiddlePoint(aShell2,pmid);
193           //bsc3d.Perform(pmid,Precision::Confusion());
194           pointstatus = /*(bsc3d.State() == TopAbs_IN ? TopAbs_IN :*/TopAbs_OUT;
195         }
196         if(pointstatus != infinstatus) {
197           aMapShellHoles.ChangeFind(aShell1).Append(aShell2);
198           if( aMapHoles.Contains(aShell2))
199             aMapHoles.Remove(aShell2);
200           else aMapHoles.Add(aShell2);
201         }
202       }
203     }
204     catch(Standard_Failure) {
205 #ifdef DEB 
206       cout << "Warning: ShapeFix_Solid::SolidFromShell: Exception: ";
207       Standard_Failure::Caught()->Print(cout); cout << endl;
208 #endif
209       continue;
210     }
211   }
212   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItShellHoles( aMapShellHoles);
213   for(; aItShellHoles.More();aItShellHoles.Next()) {
214     if(aMapHoles.Contains(aItShellHoles.Key())) continue;
215     const TopTools_ListOfShape& lHoles =aItShellHoles.Value();
216     if(lHoles.IsEmpty()) continue;
217     for(TopTools_ListIteratorOfListOfShape lItHoles(lHoles);lItHoles.More(); lItHoles.Next()) {
218       if(aMapHoles.Contains(lItHoles.Value())) {
219         const TopTools_ListOfShape& lUnHoles = aMapShellHoles.Find(lItHoles.Value());
220         for(TopTools_ListIteratorOfListOfShape lItUnHoles(lUnHoles);lItUnHoles.More(); lItUnHoles.Next()) 
221           aMapHoles.Remove(lItUnHoles.Value());
222       }
223     }
224   }
225   for(TopTools_MapIteratorOfMapOfShape aIterHoles(aMapHoles);aIterHoles.More(); aIterHoles.Next())
226     aMapShellHoles.UnBind(aIterHoles.Key());
227     
228 }
229 //=======================================================================
230 //function : CreateSolids
231 //purpose  : 
232 //=======================================================================
233
234 static Standard_Boolean CreateSolids(const TopoDS_Shape aShape,TopTools_IndexedMapOfShape& aMapSolids)
235 {
236   TopTools_SequenceOfShape aSeqShells;
237   Standard_Boolean isDone = Standard_False;
238
239   for(TopExp_Explorer aExpShell(aShape,TopAbs_SHELL); aExpShell.More(); aExpShell.Next()) {
240     aSeqShells.Append(aExpShell.Current());
241   }
242   TopTools_DataMapOfShapeListOfShape aMapShellHoles;
243   TopTools_DataMapOfShapeInteger aMapStatus;
244   CollectSolids(aSeqShells,aMapShellHoles,aMapStatus);
245   TopTools_IndexedDataMapOfShapeShape ShellSolid;
246   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItShellHoles( aMapShellHoles);
247   //Defines correct orientation of shells
248   for(; aItShellHoles.More();aItShellHoles.Next()) {
249     TopoDS_Shell aShell = TopoDS::Shell(aItShellHoles.Key());
250     TopExp_Explorer aExpEdges(aShell,TopAbs_EDGE);
251     if(!BRep_Tool::IsClosed(aShell) || !aExpEdges.More()) {
252       ShellSolid.Add(aShell,aShell);
253       isDone = Standard_True;
254       continue;
255     }
256     BRep_Builder B;
257     TopAbs_State infinstatus = TopAbs_UNKNOWN;
258     TopoDS_Solid aSolid;
259     B.MakeSolid (aSolid);
260     B.Add (aSolid,aShell);
261     if(aMapStatus.IsBound(aShell)) { 
262       Standard_Integer st = aMapStatus.Find(aShell);
263       if(st)
264         infinstatus =  (aMapStatus.Find(aShell) == 1 ? TopAbs_IN : TopAbs_OUT);
265     }
266
267     else {
268       
269     try {
270       OCC_CATCH_SIGNALS
271       BRepClass3d_SolidClassifier bsc3d (aSolid);
272       bsc3d.PerformInfinitePoint(Precision::Confusion());
273       infinstatus = bsc3d.State();
274       }
275     catch(Standard_Failure) {
276 #ifdef DEB 
277       cout << "Warning: ShapeFix_Solid::SolidFromShell: Exception: ";
278       Standard_Failure::Caught()->Print(cout); cout << endl;
279 #endif
280       ShellSolid.Add(aShell,aSolid);
281       continue;
282     } 
283   }
284   if (infinstatus == TopAbs_IN) {
285     isDone = Standard_True;
286     aShell.Reverse();
287     TopoDS_Solid aTmpSolid;
288     B.MakeSolid (aTmpSolid);
289     B.Add (aTmpSolid,aShell);
290     aSolid = aTmpSolid;
291   }
292     
293     const TopTools_ListOfShape& lHoles = aItShellHoles.Value();
294     for(TopTools_ListIteratorOfListOfShape lItHoles(lHoles); lItHoles.More();lItHoles.Next()) {
295       TopoDS_Shell aShellHole = TopoDS::Shell(lItHoles.Value());
296       if(aMapStatus.IsBound(aShellHole)) {
297         infinstatus = (aMapStatus.Find(aShellHole) == 1 ? TopAbs_IN : TopAbs_OUT);
298       }
299       else {
300         TopoDS_Solid solid;
301         B.MakeSolid (solid);
302         B.Add (solid,aShellHole);
303         BRepClass3d_SolidClassifier bsc3dHol (solid);
304         bsc3dHol.PerformInfinitePoint(Precision::Confusion());
305         infinstatus = bsc3dHol.State();
306       }
307       if (infinstatus == TopAbs_OUT) {
308         aShellHole.Reverse();
309         isDone = Standard_True;
310       }
311       B.Add(aSolid,aShellHole);
312     }
313     ShellSolid.Add(aShell,aSolid);
314   }
315   //Creation of compsolid from shells containing shared faces. 
316   TopTools_IndexedDataMapOfShapeListOfShape aMapFaceShells;
317   TopExp::MapShapesAndAncestors(aShape,TopAbs_FACE,TopAbs_SHELL,aMapFaceShells); 
318   for(Standard_Integer i =1; i <= aMapFaceShells.Extent(); i++) {
319     const TopTools_ListOfShape& lshells = aMapFaceShells.FindFromIndex(i);
320     if(lshells.Extent() <2) continue;
321     TopoDS_CompSolid aCompSolid;
322     BRep_Builder aB;
323     aB.MakeCompSolid(aCompSolid);
324     isDone = (aShape.ShapeType() != TopAbs_COMPSOLID || isDone);
325     for(TopTools_ListIteratorOfListOfShape lItSh(lshells);lItSh.More(); lItSh.Next()) {
326       if(ShellSolid.Contains(lItSh.Value())) {
327         for(TopExp_Explorer aExpSol(ShellSolid.FindFromKey(lItSh.Value()),TopAbs_SOLID);aExpSol.More(); aExpSol.Next())
328           aB.Add(aCompSolid,aExpSol.Current());
329         ShellSolid.ChangeFromKey(lItSh.Value()) = aCompSolid;
330       }
331     }
332   }
333   for(Standard_Integer kk =1 ; kk <= ShellSolid.Extent();kk++)
334     if(!aMapSolids.Contains(ShellSolid.FindFromIndex(kk)))
335        aMapSolids.Add(ShellSolid.FindFromIndex(kk));
336   isDone = (aMapSolids.Extent() >1 || isDone);
337   return isDone;
338 }
339 //=======================================================================
340 //function : Perform
341 //purpose  : 
342 //=======================================================================
343
344 Standard_Boolean ShapeFix_Solid::Perform(const Handle(Message_ProgressIndicator)& theProgress) 
345 {
346
347   Standard_Boolean status = Standard_False;
348   if ( Context().IsNull() )
349     SetContext ( new ShapeBuild_ReShape );
350   myFixShell->SetContext(Context());
351
352   Standard_Integer NbShells = 0;
353   TopoDS_Shape S = Context()->Apply ( myShape );
354
355   // Calculate number of underlying shells
356   Standard_Integer aNbShells = 0;
357   for ( TopExp_Explorer aExpSh(S, TopAbs_SHELL); aExpSh.More(); aExpSh.Next() )
358     aNbShells++;
359
360   // Start progress scope (no need to check if progress exists -- it is safe)
361   Message_ProgressSentry aPSentry(theProgress, "Fixing solid stage", 0, 2, 1);
362
363   if ( NeedFix(myFixShellMode) )
364   {
365     // Start progress scope (no need to check if progress exists -- it is safe)
366     Message_ProgressSentry aPSentry(theProgress, "Fixing shell", 0, aNbShells, 1);
367
368     // Fix shell by shell using ShapeFix_Shell tool
369     for ( TopExp_Explorer aExpSh(S, TopAbs_SHELL); aExpSh.More() && aPSentry.More(); aExpSh.Next(), aPSentry.Next() )
370     { 
371       TopoDS_Shape sh = aExpSh.Current();
372
373       myFixShell->Init( TopoDS::Shell(sh) );
374       if ( myFixShell->Perform(theProgress) )
375       {
376         status = Standard_True;
377         myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
378       }
379       NbShells+= myFixShell->NbShells();
380     }
381
382     // Halt algorithm in case of user's abort
383     if ( !aPSentry.More() )
384       return Standard_False;
385   }
386   else 
387   {
388     NbShells = aNbShells;
389   }
390
391   // Switch to the second stage
392   aPSentry.Next();
393     
394   if(NbShells ==1) {
395     TopoDS_Shape tmpShape = Context()->Apply(myShape);
396     TopExp_Explorer aExp(tmpShape,TopAbs_SHELL);
397     Standard_Boolean isClosed = Standard_False;
398     if(aExp.More()) {
399       TopoDS_Shell  aShtmp = TopoDS::Shell(aExp.Current());
400       ShapeAnalysis_FreeBounds sfb(aShtmp);
401       TopoDS_Compound aC1 = sfb.GetClosedWires();
402       TopoDS_Compound aC2 = sfb.GetOpenWires();
403       Standard_Integer numedge =0;
404       TopExp_Explorer aExp1(aC1,TopAbs_EDGE); 
405       for( ; aExp1.More(); aExp1.Next())
406         numedge++;
407       for(aExp1.Init(aC2,TopAbs_EDGE) ; aExp1.More(); aExp1.Next())
408         numedge++;
409       isClosed = (!numedge);
410       aShtmp.Closed(isClosed);
411     }
412       
413     if(isClosed || myCreateOpenSolidMode) {
414       if(BRep_Tool::IsClosed(tmpShape)) {
415         TopoDS_Iterator itersh(tmpShape);
416         TopoDS_Shell aShell;
417         if(itersh.More() && itersh.Value().ShapeType() == TopAbs_SHELL)
418           aShell = TopoDS::Shell(itersh.Value());
419         if(!aShell.IsNull()) {
420           TopoDS_Solid aSol = SolidFromShell(aShell);
421           if(ShapeExtend::DecodeStatus(myStatus,ShapeExtend_DONE2)) {
422             SendWarning (Message_Msg ("FixAdvSolid.FixOrientation.MSG20"));// Orientaion of shell was corrected.
423             Context()->Replace(tmpShape,aSol);
424             tmpShape = aSol;
425           }
426         }
427       }
428       mySolid  = TopoDS::Solid(tmpShape);
429     }
430     else {
431       TopoDS_Iterator aIt(tmpShape,Standard_False);
432       Context()->Replace(tmpShape,aIt.Value());
433       SendFail (Message_Msg ("FixAdvSolid.FixShell.MSG10")); // Solid can not be created from open shell. 
434     }
435   }
436   else {
437     TopoDS_Shape aResShape = Context()->Apply(myShape);
438     TopTools_SequenceOfShape aSeqShells;
439     TopTools_IndexedMapOfShape aMapSolids;
440     if(CreateSolids(aResShape,aMapSolids)) {
441       SendWarning (Message_Msg ("FixAdvSolid.FixOrientation.MSG20"));// Orientaion of shell was corrected.. 
442       if(aMapSolids.Extent() ==1) {
443         TopoDS_Shape aResSol = aMapSolids.FindKey(1);
444         if(aResShape.ShapeType() == TopAbs_SHELL && myCreateOpenSolidMode) {
445           TopoDS_Solid solid;
446           BRep_Builder B;
447           B.MakeSolid (solid);
448           B.Add (solid,aResSol);
449           mySolid = solid;
450         }
451         else {
452           mySolid =aResSol;
453           if(aResSol.ShapeType() == TopAbs_SHELL)
454             SendFail (Message_Msg ("FixAdvSolid.FixShell.MSG10")); // Solid can not be created from open shell. 
455         }
456         Context()->Replace(aResShape,mySolid);
457       }
458       else if(aMapSolids.Extent() >1) {
459         SendWarning (Message_Msg ("FixAdvSolid.FixOrientation.MSG30"));// Bad connected solid a few solids were created.
460         BRep_Builder aB;
461         TopoDS_Compound aComp;
462         aB.MakeCompound(aComp);
463         Message_ProgressSentry aPSentry(theProgress, "Creating solid",
464                                         0, aMapSolids.Extent(), 1);
465         for(Standard_Integer i =1; (i <= aMapSolids.Extent()) && (aPSentry.More()); 
466             i++, aPSentry.Next()) 
467         {
468           TopoDS_Shape aResSh =aMapSolids.FindKey(i);
469           if(aResShape.ShapeType() == TopAbs_SHELL && myCreateOpenSolidMode) {
470             aResSh.Closed(Standard_False);
471             TopoDS_Solid solid;
472             BRep_Builder B;
473             B.MakeSolid (solid);
474             B.Add (solid,aResSh);
475             aResSh = solid;
476           }
477           else if (aResShape.ShapeType() == TopAbs_SHELL)
478             SendFail(Message_Msg ("FixAdvSolid.FixShell.MSG10")); // Solid can not be created from open shell. 
479           aB.Add(aComp,aResSh);
480           
481         }
482         if ( !aPSentry.More() )
483           return Standard_False; // aborted execution
484         Context()->Replace(aResShape,aComp);
485       }
486     }
487   }
488   myShape = Context()->Apply(myShape);
489   return status;
490 }
491 //=======================================================================
492 //function : Shape
493 //purpose  : 
494 //=======================================================================
495
496 TopoDS_Shape ShapeFix_Solid::Shape() 
497 {
498  return myShape; 
499 }
500 //=======================================================================
501 //function : SolidFromShell
502 //purpose  : 
503 //=======================================================================
504
505 TopoDS_Solid ShapeFix_Solid::SolidFromShell (const TopoDS_Shell& shell) 
506 {
507   TopoDS_Shell sh = shell;
508   if (!sh.Free ()) sh.Free(Standard_True);
509
510   TopoDS_Solid solid;
511   BRep_Builder B;
512   B.MakeSolid (solid);
513   B.Add (solid,sh);
514 //   Pas encore fini : il faut une bonne orientation
515   try {
516     OCC_CATCH_SIGNALS
517     BRepClass3d_SolidClassifier bsc3d (solid);
518     Standard_Real t = Precision::Confusion();    // tolerance moyenne
519     bsc3d.PerformInfinitePoint(t);
520     
521     if (bsc3d.State() == TopAbs_IN) {
522       //         Ensuite, inverser C-A-D REPRENDRE LES SHELLS
523       //         (l inversion du solide n est pas bien prise en compte)
524       sh = shell;
525       if (!sh.Free ()) sh.Free(Standard_True);
526       TopoDS_Solid soli2;
527       B.MakeSolid (soli2);    // on recommence
528       sh.Reverse();
529       B.Add (soli2,sh);
530       solid = soli2;
531       myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
532     }
533   }
534   catch(Standard_Failure) {
535 #ifdef DEB 
536     cout << "Warning: ShapeFix_Solid::SolidFromShell: Exception: ";
537     Standard_Failure::Caught()->Print(cout); cout << endl;
538 #endif
539     return solid;
540   }
541   return solid;
542 }
543
544 //=======================================================================
545 //function : Status
546 //purpose  : 
547 //=======================================================================
548
549  Standard_Boolean ShapeFix_Solid::Status(const ShapeExtend_Status /*status*/) const
550 {
551  return myStatus;
552 }
553
554 //=======================================================================
555 //function : Solid
556 //purpose  : 
557 //=======================================================================
558
559  TopoDS_Shape ShapeFix_Solid::Solid() const
560 {
561  return mySolid;
562 }
563
564 //=======================================================================
565 //function : SetMsgRegistrator
566 //purpose  : 
567 //=======================================================================
568
569 void ShapeFix_Solid::SetMsgRegistrator(const Handle(ShapeExtend_BasicMsgRegistrator)& msgreg)
570 {
571   ShapeFix_Root::SetMsgRegistrator ( msgreg );
572   myFixShell->SetMsgRegistrator ( msgreg );
573 }
574
575 //=======================================================================
576 //function : SetPrecision
577 //purpose  : 
578 //=======================================================================
579
580 void ShapeFix_Solid::SetPrecision (const Standard_Real preci) 
581 {
582   ShapeFix_Root::SetPrecision ( preci );
583   myFixShell->SetPrecision ( preci );
584 }
585
586 //=======================================================================
587 //function : SetMinTolerance
588 //purpose  : 
589 //=======================================================================
590
591 void ShapeFix_Solid::SetMinTolerance (const Standard_Real mintol) 
592 {
593   ShapeFix_Root::SetMinTolerance ( mintol );
594   myFixShell->SetMinTolerance ( mintol );
595 }
596
597 //=======================================================================
598 //function : SetMaxTolerance
599 //purpose  : 
600 //=======================================================================
601
602 void ShapeFix_Solid::SetMaxTolerance (const Standard_Real maxtol) 
603 {
604   ShapeFix_Root::SetMaxTolerance ( maxtol );
605   myFixShell->SetMaxTolerance ( maxtol );
606 }