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