0022746: Progress indicator in ShapeHealing
[occt.git] / src / ShapeFix / ShapeFix_Shape.cxx
1 // File:        ShapeFix_Shape.cxx
2 // Created:     Wed Aug 09 12:27:47 1999
3 // Author:      Galina Kulikova
4 //              <gka@nnov.matra-dtv.fr>
5
6 #include <ShapeFix_Shape.ixx>
7
8 #include <Precision.hxx>
9
10 #include <TopoDS.hxx>
11 #include <TopoDS_Edge.hxx>
12 #include <TopoDS_Wire.hxx>
13 #include <TopoDS_Face.hxx>
14 #include <TopoDS_Iterator.hxx>
15 #include <TopExp_Explorer.hxx>
16 #include <TopAbs.hxx>
17 #include <TopAbs_ShapeEnum.hxx>
18 #include <BRepTools.hxx>
19 #include <BRep_Builder.hxx>
20
21 #include <ShapeFix.hxx>
22 #include <ShapeBuild_ReShape.hxx>
23 #include <ShapeFix_Edge.hxx>
24 #include <ShapeFix_Wire.hxx>
25 #include <ShapeFix_Face.hxx>
26 #include <ShapeFix_Shell.hxx>
27 #include <ShapeFix_Solid.hxx>
28
29 #include <Message_ProgressSentry.hxx>
30
31 //=======================================================================
32 //function : ShapeFix_Shape
33 //purpose  : 
34 //=======================================================================
35
36 ShapeFix_Shape::ShapeFix_Shape()
37 {  
38   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
39   myFixSolidMode = -1;
40   myFixShellMode = -1;
41   myFixFaceMode  = -1;
42   myFixWireMode  = -1;
43   myFixSameParameterMode = -1;
44   myFixVertexPositionMode =0;
45   myFixSolid = new ShapeFix_Solid;
46 }
47
48 //=======================================================================
49 //function : ShapeFix_Shape
50 //purpose  : 
51 //=======================================================================
52
53 ShapeFix_Shape::ShapeFix_Shape(const TopoDS_Shape& shape)
54 {
55   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
56   myFixSolidMode = -1;
57   myFixShellMode = -1;
58   myFixFaceMode  = -1;
59   myFixWireMode  = -1;
60   myFixSameParameterMode = -1;
61   myFixSolid = new ShapeFix_Solid;
62   myFixVertexPositionMode =0;
63   Init(shape);
64 }
65
66 //=======================================================================
67 //function : Init
68 //purpose  : 
69 //=======================================================================
70
71 void ShapeFix_Shape::Init(const TopoDS_Shape& shape) 
72 {
73   myShape = shape;
74   if ( Context().IsNull() ) {
75     SetContext ( new ShapeBuild_ReShape );
76     Context()->ModeConsiderLocation() = Standard_True;
77   }
78   myResult = myShape;
79 }
80
81 //=======================================================================
82 //function : Perform
83 //purpose  : 
84 //=======================================================================
85
86 Standard_Boolean ShapeFix_Shape::Perform(const Handle(Message_ProgressIndicator)& theProgress) 
87 {
88   Standard_Integer savFixSmallAreaWireMode = 0;
89
90   Handle(ShapeFix_Face) fft = Handle(ShapeFix_Face)::DownCast( FixFaceTool() );
91   if ( !fft.IsNull() ) {
92     savFixSmallAreaWireMode = fft->FixSmallAreaWireMode();
93     if ( savFixSmallAreaWireMode == -1 &&
94          myShape.ShapeType() == TopAbs_FACE ) {
95       fft->FixSmallAreaWireMode() = Standard_True;
96     }
97   }
98
99   myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
100   Standard_Boolean status = Standard_False;
101   TopAbs_ShapeEnum st;
102   
103   //gka fix for sharing assembly
104   TopLoc_Location nullLoc,L;
105   L = myShape.Location();
106   TopoDS_Shape aShapeNullLoc = myShape;
107   aShapeNullLoc.Location(nullLoc);
108   if(myMapFixingShape.Contains(aShapeNullLoc)) {
109     myShape.Location(L);
110     myResult = Context()->Apply(myShape);
111     status = Standard_True;
112     return status;
113   }
114   else myMapFixingShape.Add(aShapeNullLoc);
115   //---------------------------------------
116   myShape.Location(L);
117   TopoDS_Shape S = Context()->Apply(myShape);
118   if ( NeedFix (  myFixVertexPositionMode ) )
119     ShapeFix::FixVertexPosition(S,Precision(),Context());
120
121   st = S.ShapeType();
122
123   // Open progress indication scope for the following fix stages:
124   // - Fix on Solid or Shell;
125   // - Fix same parameterization;
126   Message_ProgressSentry aPSentry(theProgress, "Fixing stage", 0, 2, 1);
127
128   switch ( st ) {
129   case TopAbs_COMPOUND:  
130   case TopAbs_COMPSOLID: {
131     TopoDS_Shape shape = myShape;
132     Standard_Boolean savFixSameParameterMode = myFixSameParameterMode;
133     myFixSameParameterMode = Standard_False;
134
135     Standard_Integer aShapesNb = 0;
136     for ( TopoDS_Iterator anIter(S); anIter.More(); anIter.Next() )
137       ++aShapesNb;
138
139     // Open progress indication scope for sub-shape fixing
140     Message_ProgressSentry aPSentry(theProgress, "Fixing sub-shape", 0, aShapesNb, 1);
141     for ( TopoDS_Iterator anIter(S); anIter.More() && aPSentry.More(); anIter.Next(), aPSentry.Next() )
142     {
143       myShape = anIter.Value();
144       if ( Perform(theProgress) )
145         status = Standard_True;
146     }
147     if ( !aPSentry.More() )
148       return Standard_False; // aborted execution
149
150     myFixSameParameterMode = savFixSameParameterMode;
151     myShape = shape;
152     break;
153   }
154   case TopAbs_SOLID: {  
155     if ( !NeedFix(myFixSolidMode) )
156       break;
157     myFixSolid->Init(TopoDS::Solid(S)); 
158     myFixSolid->SetContext(Context());
159
160     if ( myFixSolid->Perform(theProgress) )
161       status = Standard_True;
162
163     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
164     break;
165   }
166   case TopAbs_SHELL:  {
167     if ( !NeedFix(myFixShellMode) )
168       break;
169     Handle(ShapeFix_Shell) sfsh = FixShellTool(); 
170     sfsh->Init( TopoDS::Shell(S) ); 
171     sfsh->SetContext( Context() );
172
173     if ( sfsh->Perform(theProgress) )
174       status = Standard_True;
175
176     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE4 );
177     break;
178   }
179   case TopAbs_FACE: {
180     if ( ! NeedFix ( myFixFaceMode ) ) break;
181     Handle(ShapeFix_Face) sff = FixFaceTool();
182     Standard_Integer savTopoMode = sff->FixWireTool()->ModifyTopologyMode();
183     sff->FixWireTool()->ModifyTopologyMode() = Standard_True;
184     sff->Init(TopoDS::Face(S)); 
185     sff->SetContext(Context());
186
187     if(sff->Perform()) {
188       status = Standard_True;
189     }
190     sff->FixWireTool()->ModifyTopologyMode() = savTopoMode;
191     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
192     break;
193   }
194   case TopAbs_WIRE: {
195     if ( ! NeedFix ( myFixWireMode ) ) break;
196     Handle(ShapeFix_Wire) sfw = FixWireTool();
197     Standard_Integer savTopoMode = sfw->ModifyTopologyMode();
198     Standard_Integer savClosedMode = sfw->ClosedWireMode();
199     sfw->ModifyTopologyMode() = Standard_True;
200     if ( ! S.Closed() ) 
201       sfw->ClosedWireMode() = Standard_False;
202     sfw->SetFace(TopoDS_Face());
203     sfw->Load(TopoDS::Wire(S));
204     sfw->SetContext(Context());
205     if(sfw->Perform()) {
206       status = Standard_True;
207       Context()->Replace(S,sfw->Wire()); // replace for wire only
208     }
209     sfw->ModifyTopologyMode() = savTopoMode;
210     sfw->ClosedWireMode() = savClosedMode;
211     myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
212     break;
213   }
214   case TopAbs_EDGE: {
215     Handle(ShapeFix_Edge) sfe = FixEdgeTool();
216     if(sfe->FixVertexTolerance(TopoDS::Edge(S)))
217       myStatus |= ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
218     break;
219   }
220   case TopAbs_VERTEX:
221   case TopAbs_SHAPE :    
222   default           : break;
223   }
224
225   // Switch to the second progress indication scope if it exists
226   aPSentry.Next();
227   
228   myResult = Context()->Apply(S);  
229
230   if ( NeedFix(myFixSameParameterMode) )
231   {
232     SameParameter(myResult, Standard_False, theProgress);
233   }
234
235   if ( !fft.IsNull() )
236     fft->FixSmallAreaWireMode() = savFixSmallAreaWireMode;
237
238   return status;
239 }  
240
241 //=======================================================================
242 //function : SameParameter
243 //purpose  : 
244 //=======================================================================
245
246 void ShapeFix_Shape::SameParameter(const TopoDS_Shape& sh,
247                                    const Standard_Boolean enforce,
248                                    const Handle(Message_ProgressIndicator)& theProgress)
249 {
250   ShapeFix::SameParameter(sh, enforce, 0.0, theProgress);
251 }
252
253 //=======================================================================
254 //function : Shape
255 //purpose  : 
256 //=======================================================================
257
258 TopoDS_Shape ShapeFix_Shape::Shape() const
259 {
260   return myResult;
261 }
262
263 //=======================================================================
264 //function : SetMsgRegistrator
265 //purpose  : 
266 //=======================================================================
267
268 void ShapeFix_Shape::SetMsgRegistrator(const Handle(ShapeExtend_BasicMsgRegistrator)& msgreg)
269 {
270   ShapeFix_Root::SetMsgRegistrator ( msgreg );
271   myFixSolid->SetMsgRegistrator ( msgreg );
272 }
273
274 //=======================================================================
275 //function : SetPrecision
276 //purpose  : 
277 //=======================================================================
278
279 void ShapeFix_Shape::SetPrecision (const Standard_Real preci) 
280 {
281   ShapeFix_Root::SetPrecision ( preci );
282   myFixSolid->SetPrecision ( preci );
283 }
284
285 //=======================================================================
286 //function : SetMinTolerance
287 //purpose  : 
288 //=======================================================================
289
290 void ShapeFix_Shape::SetMinTolerance (const Standard_Real mintol) 
291 {
292   ShapeFix_Root::SetMinTolerance ( mintol );
293   myFixSolid->SetMinTolerance ( mintol );
294 }
295
296 //=======================================================================
297 //function : SetMaxTolerance
298 //purpose  : 
299 //=======================================================================
300
301 void ShapeFix_Shape::SetMaxTolerance (const Standard_Real maxtol) 
302 {
303   ShapeFix_Root::SetMaxTolerance ( maxtol );
304   myFixSolid->SetMaxTolerance ( maxtol );
305 }
306 //=======================================================================
307 //function : Status
308 //purpose  : 
309 //=======================================================================
310
311 Standard_Boolean ShapeFix_Shape::Status (const ShapeExtend_Status status) const
312 {
313   return ShapeExtend::DecodeStatus ( myStatus, status ); 
314 }