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