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