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