0025418: Debug output to be limited to OCC development environment
[occt.git] / src / ShapeFix / ShapeFix_FixSmallFace.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_FixSmallFace.ixx>
15 #include <TopoDS.hxx>
16 #include <TopoDS_Shell.hxx>
17 #include <TopoDS_Edge.hxx>
18 #include <TopoDS_Vertex.hxx>
19 #include <TopoDS_Iterator.hxx>
20 #include <TopExp_Explorer.hxx>
21 #include <TopExp.hxx>
22 #include <BRep_Tool.hxx>
23
24 #include <Geom_Curve.hxx>
25 #include <Geom_Surface.hxx>
26 #include <Geom_BSplineSurface.hxx>
27 #include <Geom_BezierSurface.hxx>
28
29 #include <ShapeAnalysis_Curve.hxx>
30 //#include <GeomLProp_SLProps.hxx>
31 #include <GeomAdaptor_Surface.hxx>
32 #include <Geom_ElementarySurface.hxx>
33 //#include <TColStd_Array2OfReal.hxx>
34 #include <gp_Dir.hxx>
35 #include <gp_Vec.hxx>
36 //#include <TColStd_Array1OfReal.hxx>
37 #include <TColgp_Array1OfPnt.hxx>
38 #include <TopTools_Array1OfShape.hxx>
39
40 #include <TColgp_Array2OfPnt.hxx>
41
42 #include <TColgp_SequenceOfXYZ.hxx>
43 #include <BRep_Builder.hxx>
44 #include <ShapeBuild_ReShape.hxx>
45 #include <BRepTools.hxx>
46 #include <ShapeFix_Edge.hxx>
47 #include <Precision.hxx>
48 #include <TopoDS_Wire.hxx>
49 #include <ShapeFix_Wire.hxx>
50 #include <Geom_Line.hxx>
51 #include <TopExp.hxx>
52 #include <ElCLib.hxx>
53 #include <TopoDS_Builder.hxx>
54 #include <TopoDS_Compound.hxx>
55 #include <Poly_Polygon3D.hxx>
56 #include <Geom2d_Curve.hxx>
57 #include <BRepLib.hxx>
58 #include <GeomLib.hxx>
59 #include <ShapeFix_Face.hxx>
60 #include <ShapeFix_Wire.hxx>
61 #include <Geom_TrimmedCurve.hxx>
62 #include <GeomAdaptor_Curve.hxx>
63 #include <ShapeFix_Shape.hxx>
64 #include <Precision.hxx>
65 #include <TopExp_Explorer.hxx>
66 #include <TopTools_DataMapOfShapeListOfShape.hxx>
67 #include <ShapeAnalysis_DataMapOfShapeListOfReal.hxx>
68 #include <TopoDS_Compound.hxx>
69 #include <TopoDS_Iterator.hxx>
70
71 ShapeFix_FixSmallFace::ShapeFix_FixSmallFace()
72 {
73   myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
74   SetPrecision(Precision::Confusion());
75
76 }
77
78  void ShapeFix_FixSmallFace::Init(const TopoDS_Shape& S) 
79 {
80   myShape = S;
81   if ( Context().IsNull() ) 
82     SetContext ( new ShapeBuild_ReShape );
83   myResult = myShape;
84   Context()->Apply(myShape);
85 }
86
87
88  void ShapeFix_FixSmallFace::Perform() 
89 {
90   FixSpotFace();
91   FixStripFace();
92 }
93
94  TopoDS_Shape ShapeFix_FixSmallFace::FixSpotFace() 
95 {
96  
97   // gp_Pnt spot;
98   // Standard_Real spotol;
99   Standard_Boolean done = Standard_False;
100   TopAbs_ShapeEnum st = myShape.ShapeType();
101   if (st == TopAbs_COMPOUND || st == TopAbs_COMPSOLID || st == TopAbs_SOLID || st == TopAbs_SHELL ||  st == TopAbs_FACE) { 
102     for (TopExp_Explorer itf (myShape,TopAbs_FACE); itf.More(); itf.Next()) {
103 //smh#8
104       TopoDS_Shape tmpFace = Context()->Apply(itf.Current());
105       TopoDS_Face F = TopoDS::Face (tmpFace);
106       if(F.IsNull()) continue;
107       if (myAnalyzer.CheckSpotFace (F,Precision())) 
108         {
109           ReplaceVerticesInCaseOfSpot(F,Precision());
110           RemoveFacesInCaseOfSpot(F);
111           myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_DONE1 );
112           done = Standard_True;
113         }
114     }
115     myShape = Context()->Apply(myShape);
116     Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
117     if (done)
118       {
119         if (myShape.IsNull()) return myShape;
120         /*ShapeFix_Wire sfw;
121         sfw.SetContext(Context());
122         sfw.SetPrecision(Precision::Confusion());
123         if (myShape.IsNull()) return myShape;
124         for (TopExp_Explorer itfw (myShape,TopAbs_FACE); itfw.More(); itfw.Next()) {
125           for (TopExp_Explorer itw (myShape,TopAbs_WIRE); itw.More(); itw.Next()) {
126             TopoDS_Wire w = TopoDS::Wire(itw.Current());
127             sfw.Init(w, TopoDS::Face(itfw.Current()), Precision::Confusion());
128             sfw->FixNotchedEdgesMode() = 0;
129             if(sfw.Perform())
130                 Context()->Replace(w, sfw.Wire());
131           }                      
132         }*/
133         myShape = FixShape();
134       }
135   
136   //myShape = Context()->Apply(myShape);
137   myResult = myShape;
138   }
139   return myShape;
140 }
141
142  Standard_Boolean ShapeFix_FixSmallFace::ReplaceVerticesInCaseOfSpot(TopoDS_Face& F,const Standard_Real /*tol*/) const
143 {
144
145   TColgp_SequenceOfXYZ thePositions;
146   gp_XYZ thePosition;
147   BRep_Builder theBuilder;
148   Standard_Real theMaxDev;
149   Standard_Real theMaxTol = 0.0;
150   thePositions.Clear();
151   gp_Pnt thePoint;
152 //smh#8
153   TopoDS_Shape tmpFace = Context()->Apply(F);
154   F = TopoDS::Face(tmpFace);
155   // gka Mar2000 Protection against faces without wires
156   // but they occur due to bugs in the algorithm itself, it needs to be fixed
157   Standard_Boolean isWir = Standard_False;
158   for(TopoDS_Iterator itw(F,Standard_False) ; itw.More();itw.Next()) {
159     if(itw.Value().ShapeType() != TopAbs_WIRE)
160       continue;
161     TopoDS_Wire w1 = TopoDS::Wire(itw.Value());
162     if (!w1.IsNull()) {isWir = Standard_True; break;}
163   }
164   if(!isWir) return Standard_True;
165   //Accumulating positions and maximal vertex tolerance
166   for (TopExp_Explorer iter_vertex(F,TopAbs_VERTEX); iter_vertex.More(); iter_vertex.Next()) {
167     TopoDS_Vertex V = TopoDS::Vertex (iter_vertex.Current());
168     thePoint = BRep_Tool::Pnt(V);
169     if (theMaxTol <= (BRep_Tool::Tolerance(V))) theMaxTol = BRep_Tool::Tolerance(V);
170     thePositions.Append(thePoint.XYZ());
171   } 
172   //Calculate common vertex position
173   thePosition = gp_XYZ(0.,0.,0.);
174   Standard_Integer theNbPos = thePositions.Length();
175   Standard_Integer i; // svv Jan11 2000 : porting on DEC
176   for (  i = 1; i <= theNbPos; i++ ) thePosition += thePositions.Value(i);
177   if ( theNbPos > 1 ) thePosition /= theNbPos;
178    
179   // Calculate maximal deviation
180   theMaxDev = 0.;
181   for (  i = 1; i <= theNbPos; i++ ) {
182     Standard_Real theDeviation = (thePosition-thePositions.Value(i)).Modulus();
183     if ( theDeviation > theMaxDev ) theMaxDev = theDeviation;
184   }
185   theMaxDev *= 1.00001; 
186   
187   //Cretate new vertex with mean point
188   TopoDS_Vertex theSharedVertex;
189   theBuilder.MakeVertex(theSharedVertex);
190   theBuilder.UpdateVertex( theSharedVertex, gp_Pnt(thePosition), theMaxDev+theMaxTol/2 );
191   //Use external tolerance
192 //   if (tol!=-1.0) theBuilder.UpdateVertex( theSharedVertex, tol);
193   //Replacing all vertices in the face by new one
194   TopoDS_Vertex theNewVertex;
195   for ( TopExp_Explorer iter_vert(F,TopAbs_VERTEX); iter_vert.More(); iter_vert.Next()) {
196     TopoDS_Vertex V = TopoDS::Vertex (iter_vert.Current());
197     if (V.Orientation()==TopAbs_FORWARD)  
198 //smh#8
199       {
200         TopoDS_Shape tmpVertexFwd = theSharedVertex.Oriented(TopAbs_FORWARD);
201         theNewVertex = TopoDS::Vertex(tmpVertexFwd);
202       }
203     else 
204 //smh#8
205       {
206         TopoDS_Shape tmpVertexRev = theSharedVertex.Oriented(TopAbs_REVERSED);
207         theNewVertex = TopoDS::Vertex(tmpVertexRev);
208       }
209     Context()->Replace(V, theNewVertex);
210   }
211   return Standard_True;
212 }
213
214  Standard_Boolean ShapeFix_FixSmallFace::RemoveFacesInCaseOfSpot(const TopoDS_Face& F) const
215 {
216   for ( TopExp_Explorer iter_vert(F,TopAbs_EDGE); iter_vert.More(); iter_vert.Next()) {
217     TopoDS_Edge Ed = TopoDS::Edge (iter_vert.Current());
218     Context()->Remove(Ed);
219   }
220   Context()->Remove(F);
221   return Standard_True;
222
223
224 }
225
226  TopoDS_Shape ShapeFix_FixSmallFace::FixStripFace(const Standard_Boolean wasdone) 
227 {
228   if(myShape.IsNull()) return myShape;
229   TopAbs_ShapeEnum st = myShape.ShapeType();
230   // BRep_Builder theBuilder;
231   Standard_Boolean done = wasdone;
232   if (st == TopAbs_COMPOUND || st == TopAbs_COMPSOLID ||st == TopAbs_SOLID || st == TopAbs_SHELL || st == TopAbs_FACE) {
233     for (TopExp_Explorer itf (myShape,TopAbs_FACE); itf.More(); itf.Next()) {
234       TopoDS_Face F = TopoDS::Face (itf.Current());
235 //smh#8
236       TopoDS_Shape tmpFace = Context()->Apply(F);
237       F= TopoDS::Face(tmpFace);
238       if(F.IsNull()) continue;
239       // Standard_Real dmax = 1;
240       TopoDS_Edge E1,E2;
241       if (myAnalyzer.CheckStripFace (F, E1,E2,Precision()))  
242         {
243           if(ReplaceInCaseOfStrip(F,E1,E2, Precision()))
244             RemoveFacesInCaseOfStrip(F);
245           myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_DONE2 );
246           done = Standard_True;
247         }
248     }
249     myShape = Context()->Apply(myShape);
250     //Particular case of empty shell
251     if (!myShape.IsNull())
252       {
253         for (TopExp_Explorer exp_s (myShape,TopAbs_SHELL); exp_s.More(); exp_s.Next()) {
254           TopoDS_Shell Sh = TopoDS::Shell (exp_s.Current());
255           TopExp_Explorer ex_sh(Sh,TopAbs_FACE);
256           if (!ex_sh.More())  { Context()->Remove(Sh);
257 //                              cout << "Empty shell was removed" << endl; 
258                               }
259         }
260         myShape = Context()->Apply(myShape);
261     //Fixing of missing pcurves on new edges, if thay were inserted
262         if (done)
263           {
264             if (myShape.IsNull()) return myShape;
265             TopoDS_Shape theResult;
266             myShape = FixShape();
267             //myShape = Context()->Apply(myShape);
268             myResult = myShape;
269           }
270         
271       }
272   }
273   return myShape; 
274
275 }
276
277  Standard_Boolean ShapeFix_FixSmallFace::ReplaceInCaseOfStrip(TopoDS_Face& F,TopoDS_Edge& E1,TopoDS_Edge& E2, const Standard_Real tol) const
278 {
279   if(E1.IsNull() || E2.IsNull()) return Standard_False;
280   TopoDS_Edge theSharedEdge;
281   TopoDS_Face F1,F2;
282 //smh#8
283   TopoDS_Shape tmpFace = Context()->Apply(F);
284   F= TopoDS::Face(tmpFace);
285   for(TopExp_Explorer expf(myShape,TopAbs_FACE); expf.More(); expf.Next()) {
286 //smh#8
287     TopoDS_Shape tmpShape = Context()->Apply(expf.Current());
288     TopoDS_Face tempF = TopoDS::Face (tmpShape);
289     if(tempF.IsNull() || tempF.IsSame(F)) continue;
290     for(TopExp_Explorer expe(tempF,TopAbs_EDGE); expe.More(); expe.Next()) {
291       TopoDS_Edge tempE = TopoDS::Edge (expe.Current());
292       if(tempE.IsSame(E1)) F1 = tempF;
293       if(tempE.IsSame(E2)) F2 = tempF; 
294       if(!F1.IsNull()) break; // && !F2.IsNull()) break;
295     }
296   }
297   
298   //Compute shared edge for this face
299   if(F1.IsNull() && F2.IsNull()) return Standard_True;
300   TopoDS_Edge E1tmp = E1;
301   TopoDS_Edge E2tmp = E2;
302   if(F1.IsNull()) {
303     E1tmp = E2;
304     E2tmp = E1;
305     F1 = F2;
306   }
307   theSharedEdge = ComputeSharedEdgeForStripFace(F, E1tmp, E2tmp, F1, tol);
308   //Replace two long edges by new one
309   if (theSharedEdge.IsNull()) return Standard_False;
310   if (E1.Orientation()==TopAbs_REVERSED) {
311       Context()->Replace(E1tmp, theSharedEdge.Oriented(TopAbs_REVERSED));
312       if(F.Orientation() == F1.Orientation())
313         Context()->Replace(E2tmp, theSharedEdge);
314       else 
315        Context()->Replace(E2tmp, theSharedEdge.Oriented(TopAbs_REVERSED));
316     }
317   else 
318     {
319       Context()->Replace(E1tmp, theSharedEdge);
320      if(F.Orientation() == F1.Orientation())
321       Context()->Replace(E2tmp, theSharedEdge.Oriented(TopAbs_REVERSED));
322      else
323       Context()->Replace(E2tmp, theSharedEdge);
324     }
325     
326   //Remove short edges
327   for (TopExp_Explorer exp_e (F,TopAbs_EDGE); exp_e.More(); exp_e.Next()) {
328     TopoDS_Edge shortedge = TopoDS::Edge (exp_e.Current());
329     if (!shortedge.IsSame(E1tmp) && !shortedge.IsSame(E2tmp)) Context()->Remove(shortedge); 
330   }
331   
332   return Standard_True;
333 }
334
335  Standard_Boolean ShapeFix_FixSmallFace::RemoveFacesInCaseOfStrip(const TopoDS_Face& F) const
336 {
337   Context()->Remove(F);
338   return Standard_True;
339 }
340
341  TopoDS_Edge ShapeFix_FixSmallFace::ComputeSharedEdgeForStripFace(const TopoDS_Face& /*F*/,const TopoDS_Edge& E1,const TopoDS_Edge& E2,const TopoDS_Face& F1,const Standard_Real tol) const
342 {
343
344   BRep_Builder theBuilder;
345   //Compute deviation between two vertices and create new vertices
346   TopoDS_Edge theNewEdge;
347   TopoDS_Vertex V1,V2, V3, V4;
348   TopExp::Vertices (E1,V1,V2);
349   TopExp::Vertices (E2,V3,V4);
350   gp_Pnt p1, p2;
351   Standard_Real dev;
352   p1 = BRep_Tool::Pnt(V1);
353   p2 =  BRep_Tool::Pnt(V3);
354   dev = p1.Distance(p2);
355   TopoDS_Vertex theFirstVer;
356   TopoDS_Vertex theSecondVer;
357   theBuilder.MakeVertex(theFirstVer);
358   theBuilder.MakeVertex(theSecondVer);
359   gp_XYZ thePosition;
360   TopoDS_Shape temp;
361   
362   if ((dev<=BRep_Tool::Tolerance (V1)) || (dev<=BRep_Tool::Tolerance (V3)) || (dev<=tol)) {
363       if (V1.IsSame(V3))  
364 // #ifdef AIX  CKY : applies to all platforms
365         theFirstVer = V1; 
366 //      theFirstVer = TopoDS::Vertex(V1); 
367
368       else {
369         dev = (dev/2)*1.0001;
370         thePosition = (p1.XYZ()+p2.XYZ())/2;  
371         theBuilder.UpdateVertex(theFirstVer, gp_Pnt(thePosition), dev );
372         //if(Context()->Status(V1, temp) != 0) theFirstVer = TopoDS::Vertex (temp); //If this vertex already recorded in map
373         //else                                                                       //take recorded vertex 
374         //  if(theRepVert->Status(V3, temp) != 0) theFirstVer = TopoDS::Vertex (temp);
375         if (V1.Orientation()==TopAbs_FORWARD) Context()->Replace(V1, theFirstVer.Oriented(TopAbs_FORWARD));
376         else Context()->Replace(V1, theFirstVer.Oriented(TopAbs_REVERSED));
377         if (V3.Orientation()==TopAbs_FORWARD) Context()->Replace(V3, theFirstVer.Oriented(TopAbs_FORWARD));
378         else Context()->Replace(V3, theFirstVer.Oriented(TopAbs_REVERSED));
379         
380      }
381       if(V1.IsSame(V2) || V3.IsSame(V4))
382         theSecondVer = theFirstVer; 
383       else {
384         if (!V2.IsSame(V4))   {
385           // #ifdef AIX  CKY : applies to all platforms
386           
387           p1 = BRep_Tool::Pnt(V2);
388           p2 =  BRep_Tool::Pnt(V4);
389           dev = p1.Distance(p2);
390           thePosition = (p1.XYZ()+p2.XYZ())/2;  
391           theBuilder.UpdateVertex(theSecondVer, gp_Pnt(thePosition), dev );
392           //if(theRepVert->Status(V2, temp) != 0) theSecondVer = TopoDS::Vertex (temp); //If this vertex already recorded in map
393           //else 
394           //  if(theRepVert->Status(V4, temp) != 0) theSecondVer = TopoDS::Vertex (temp);
395         }
396         else theSecondVer = V2;
397         
398       }
399       if (!V2.IsSame(theSecondVer))   {
400         if (V2.Orientation()==TopAbs_FORWARD) Context()->Replace(V2, theSecondVer.Oriented(TopAbs_FORWARD));
401         else Context()->Replace(V2, theSecondVer.Oriented(TopAbs_REVERSED));
402         if (V4.Orientation()==TopAbs_FORWARD) Context()->Replace(V4, theSecondVer.Oriented(TopAbs_FORWARD));
403         else Context()->Replace(V4, theSecondVer.Oriented(TopAbs_REVERSED));
404       }
405     }
406   else   {
407       p2 =  BRep_Tool::Pnt(V4);  
408       dev = p1.Distance(p2);
409       if ((dev<=BRep_Tool::Tolerance (V1)) || (dev<=BRep_Tool::Tolerance (V4)) || (dev<=tol)) {
410           if (V1.IsSame(V4))  
411 // #ifdef AIX  CKY : applies to all platforms
412             theFirstVer = V1;
413 //          theFirstVer = TopoDS::Vertex(V1);
414
415           else {
416             dev = (dev/2)*1.0001;
417             thePosition = (p1.XYZ()+p2.XYZ())/2;  
418             theBuilder.UpdateVertex(theFirstVer, gp_Pnt(thePosition), dev );
419         //    if(theRepVert->Status(V1, temp) != 0) theFirstVer = TopoDS::Vertex (temp); //If this vertex already recorded in map
420           //  else 
421           //    if(theRepVert->Status(V4, temp) != 0) theFirstVer = TopoDS::Vertex (temp);
422             if (V1.Orientation()==TopAbs_FORWARD) Context()->Replace(V1, theFirstVer.Oriented(TopAbs_FORWARD));
423             else Context()->Replace(V1, theFirstVer.Oriented(TopAbs_REVERSED));
424             if (V4.Orientation()==TopAbs_FORWARD) Context()->Replace(V4, theFirstVer.Oriented(TopAbs_FORWARD));
425             else Context()->Replace(V4, theFirstVer.Oriented(TopAbs_REVERSED));
426           }
427           if(V1.IsSame(V2) || V3.IsSame(V4))
428             theSecondVer = theFirstVer; 
429           else {
430             
431             if (!V2.IsSame(V3)) {
432               p1 = BRep_Tool::Pnt(V2);
433               p2 =  BRep_Tool::Pnt(V3);
434               dev = p1.Distance(p2);
435               thePosition = (p1.XYZ()+p2.XYZ())/2;  
436               theBuilder.UpdateVertex(theSecondVer, gp_Pnt(thePosition), dev );
437             }
438             else theSecondVer = V2;
439           }
440               //  if(theRepVert->Status(V2, temp) != 0) theSecondVer = TopoDS::Vertex (temp); //If this vertex already recorded in map
441               // else 
442               //  if(theRepVert->Status(V3, temp) != 0) theSecondVer = TopoDS::Vertex (temp);
443           if (!V2.IsSame(theSecondVer)) {
444               if (V2.Orientation()==TopAbs_FORWARD) Context()->Replace(V2, theSecondVer.Oriented(TopAbs_FORWARD));
445             else Context()->Replace(V2, theSecondVer.Oriented(TopAbs_REVERSED));
446             if (V3.Orientation()==TopAbs_FORWARD) Context()->Replace(V3, theSecondVer.Oriented(TopAbs_FORWARD));
447             else Context()->Replace(V3, theSecondVer.Oriented(TopAbs_REVERSED));
448           }
449           
450         } 
451       else {
452 #ifdef OCCT_DEBUG
453         cout << "The face is not strip face"  << endl;
454 #endif
455         return theNewEdge;
456       }
457     }
458   if (theFirstVer.IsNull() || theSecondVer.IsNull()) return theNewEdge;
459   //Cretate new edge 
460   theBuilder.MakeEdge(theNewEdge);
461   Standard_Real f, l, fp1, lp1/*, fp2, lp2*/;
462   TopLoc_Location loc;
463   Handle(Geom_Curve) the3dcurve;
464   the3dcurve = BRep_Tool::Curve(E1, f, l);
465   Handle(Geom2d_Curve) the2dcurve1, the2dcurve2, thenew1, thenew2;
466   if (!F1.IsNull())   
467     {
468       the2dcurve1 = BRep_Tool::CurveOnSurface(E1, F1, fp1, lp1);
469       if(!the2dcurve1.IsNull() && fp1!=f && lp1!=l) GeomLib::SameRange(Precision::Confusion(), the2dcurve1, fp1, lp1, f, l, thenew1);  
470     }
471       
472  /* if (!F2.IsNull())   
473     {
474       the2dcurve2 = BRep_Tool::CurveOnSurface(E2, F2, fp2, lp2);
475       if(!the2dcurve2.IsNull()) GeomLib::SameRange(Precision::Confusion(), the2dcurve2, fp2, lp2, f, l, thenew2); 
476     }*/
477   
478   Standard_Real maxdev; 
479   if ((BRep_Tool::Tolerance(theFirstVer))<=(BRep_Tool::Tolerance(theSecondVer))) 
480     maxdev = (BRep_Tool::Tolerance(theSecondVer));
481   else  maxdev = (BRep_Tool::Tolerance(theFirstVer));
482   theBuilder.UpdateVertex(theFirstVer, maxdev);
483   theBuilder.UpdateVertex(theSecondVer, maxdev);
484   //Standard_Boolean IsFree = Standard_True;
485   theBuilder.SameParameter(theNewEdge, Standard_False);
486   the3dcurve = BRep_Tool::Curve(E1, f, l);
487   theBuilder.UpdateEdge(theNewEdge, the3dcurve, maxdev);
488   theBuilder.Range(theNewEdge, f, l);
489   if (!F1.IsNull() && !thenew1.IsNull())  
490     {
491       theBuilder.UpdateEdge(theNewEdge, thenew1, F1, maxdev); 
492       //IsFree = Standard_False;
493     }
494   /*if (!F2.IsNull() && !thenew2.IsNull())
495     {
496       theBuilder.UpdateEdge(theNewEdge, thenew2, F2, maxdev);
497       IsFree = Standard_False;
498     }*/
499   theBuilder.Add(theNewEdge, theFirstVer.Oriented(TopAbs_FORWARD));
500   theBuilder.Add(theNewEdge, theSecondVer.Oriented(TopAbs_REVERSED));
501   //Call fixsameparameter for computing distance between 3d and pcurves, if edge is not free
502 //   if (!IsFree)
503 //     {
504 //       ShapeFix_Edge sfe;
505 //       if (!F1.IsNull() && !thenew1.IsNull()) sfe.FixReversed2d(theNewEdge, F1);
506 //       if (!F2.IsNull() && !thenew2.IsNull()) sfe.FixReversed2d(theNewEdge, F2);
507 //       sfe.FixSameParameter(theNewEdge, maxdev);
508 //     }
509   return theNewEdge;
510
511
512 }
513
514  TopoDS_Shape ShapeFix_FixSmallFace::FixSplitFace(const TopoDS_Shape& /*S*/) 
515 {
516   if (myShape.IsNull()) return myShape;
517   TopAbs_ShapeEnum st = myShape.ShapeType();
518   Standard_Boolean done = Standard_False;
519   TopoDS_Compound theSplittedFaces;
520   BRep_Builder theBuilder;
521   if (st == TopAbs_COMPOUND || st == TopAbs_COMPSOLID ||
522       st == TopAbs_SOLID || st ==  TopAbs_SHELL || st ==  TopAbs_FACE) {
523     for (TopExp_Explorer itf (myShape,TopAbs_FACE); itf.More(); itf.Next()) {
524       TopoDS_Face F = TopoDS::Face (itf.Current());
525       TopoDS_Compound CompSplittedFaces;
526       theBuilder.MakeCompound(CompSplittedFaces);
527       if(SplitOneFace(F, CompSplittedFaces)) {
528         done = Standard_True;
529         Context()->Replace(F, CompSplittedFaces);
530       }
531     }
532   }
533   if(done) myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_DONE3 );
534   myShape = Context()->Apply(myShape);
535   myResult = myShape;
536   return myShape;
537 }
538
539  TopoDS_Shape ShapeFix_FixSmallFace::SplitFaces() 
540 {
541    myShape = RemoveSmallFaces();
542    myResult = myShape;
543   return myShape;
544
545 }
546
547  Standard_Boolean ShapeFix_FixSmallFace::SplitOneFace(TopoDS_Face& F,TopoDS_Compound& theSplittedFaces) 
548 {
549   TopTools_DataMapOfShapeListOfShape MapEdges; 
550   ShapeAnalysis_DataMapOfShapeListOfReal MapParam;
551   TopoDS_Compound theAllVert;
552   BRep_Builder theBuilder;
553   theBuilder.MakeCompound(theAllVert);
554 //smh#8
555   TopoDS_Shape tmpShape = Context()->Apply(F);
556   F = TopoDS::Face(tmpShape);
557   if (myAnalyzer.CheckSplittingVertices(F,MapEdges,MapParam,theAllVert) != 0) 
558     {
559       TopoDS_Wire tempwire;
560       //Take information about splitting vertices
561       if (theAllVert.IsNull()) return Standard_False;
562       //Standard_Integer i;
563       TopoDS_Vertex V;
564       TopExp_Explorer itc(theAllVert,TopAbs_VERTEX); V = TopoDS::Vertex (itc.Current());
565       if (V.IsNull()) return Standard_False;
566       gp_Pnt proj;
567       gp_Pnt vp = BRep_Tool::Pnt(V);
568       TopoDS_Vertex theNewVertex;
569       TopoDS_Edge E;
570       TopoDS_Edge theFirstEdge, theSecondEdge;
571       
572       {
573         //If one vertex presents do splitting by two faces
574         ShapeAnalysis_Curve SAC;
575         for (TopExp_Explorer ite(F,TopAbs_EDGE); ite.More(); ite.Next()) {
576           E = TopoDS::Edge (ite.Current());
577           TopoDS_Vertex V1,V2;
578           TopExp::Vertices (E,V1,V2);
579           Standard_Real cf,cl;
580           Handle(Geom_Curve) C3D = BRep_Tool::Curve (E,cf,cl);
581           if (C3D.IsNull()) continue;
582           if (V.IsSame(V1) || V.IsSame(V2)) continue;
583           Standard_Real vt = BRep_Tool::Tolerance (V);
584           Standard_Real param;
585           Standard_Real dist = SAC.Project (C3D,vp,vt*10.,proj,param,cf,cl);
586           if (dist==0) continue; //Projection on same curve but on other edge ?
587           if ( dist <= vt ) 
588             {
589               theBuilder.MakeVertex(theNewVertex);
590               theBuilder.UpdateVertex(theNewVertex, proj, Precision::Confusion());
591               theBuilder.MakeEdge(theFirstEdge);
592               theBuilder.MakeEdge(theSecondEdge);
593               Standard_Real f, l;
594               Handle(Geom_Curve) the3dcurve = BRep_Tool::Curve(E, f, l);
595               theBuilder.UpdateEdge(theFirstEdge, the3dcurve,Precision::Confusion());
596               theBuilder.UpdateEdge(theSecondEdge, the3dcurve,Precision::Confusion());
597               if (V1.Orientation()==TopAbs_FORWARD) 
598                 {
599                   theBuilder.Add(theFirstEdge, V1);
600                   theBuilder.Add(theFirstEdge,theNewVertex.Oriented(TopAbs_REVERSED));
601                   theBuilder.Add(theSecondEdge,theNewVertex.Oriented(TopAbs_FORWARD));
602                   theBuilder.Add(theSecondEdge, V2);
603                 }
604               else {
605                 theBuilder.Add(theFirstEdge,V2);
606                 theBuilder.Add(theFirstEdge,theNewVertex.Oriented(TopAbs_REVERSED));
607                 theBuilder.Add(theSecondEdge,theNewVertex.Oriented(TopAbs_FORWARD));
608                 theBuilder.Add(theSecondEdge, V1);
609               }
610               theBuilder.Range(theFirstEdge, cf, param);
611               theBuilder.Range(theSecondEdge, param, cl);
612               //Replace old edge by two new edges
613               TopoDS_Wire twoedges;
614               theBuilder.MakeWire(twoedges);
615               if (E.Orientation() == TopAbs_FORWARD)
616                 {
617                   theBuilder.Add(twoedges, theFirstEdge.Oriented(TopAbs_FORWARD));
618                   theBuilder.Add(twoedges, theSecondEdge.Oriented(TopAbs_FORWARD));
619                 }
620               else 
621                 {
622                   theBuilder.Add(twoedges, theFirstEdge.Oriented(TopAbs_REVERSED));
623                   theBuilder.Add(twoedges, theSecondEdge.Oriented(TopAbs_REVERSED));
624                 }
625               Context()->Replace(E, twoedges);
626               break;
627             }
628         }
629         if (theNewVertex.IsNull()) return Standard_False;
630         //Create split edge
631         TopoDS_Edge theSplitEdge;
632         gp_Lin lin(vp, gp_Dir(gp_Vec( vp, proj)));
633         Standard_Real firstparam = ElCLib::Parameter(lin, vp);
634         Standard_Real lastparam = ElCLib::Parameter(lin, proj);
635         Handle(Geom_Line) L = new Geom_Line( vp, gp_Vec( vp, proj));
636         Handle(Geom_Curve) the3dc = L;
637         theBuilder.MakeEdge(theSplitEdge, the3dc, Precision::Confusion());
638         theBuilder.Add(theSplitEdge, V.Oriented(TopAbs_FORWARD));
639         theBuilder.Add(theSplitEdge, theNewVertex.Oriented(TopAbs_REVERSED));  
640         theBuilder.Range(theSplitEdge, firstparam, lastparam);
641         //Add pcurve in new edge
642         Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
643         sfe->FixAddPCurve(theSplitEdge, F, Standard_False);
644         //Reorder the wire 
645         TopoDS_Wire wireonface;
646         //Inher loop is not support yet !!!
647         TopExp_Explorer itw(F,TopAbs_WIRE);
648         wireonface = TopoDS::Wire (itw.Current());
649         itw.Next();
650         if (itw.More()) return Standard_False; //if face contains more than one wire  
651         Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
652         sfw->Init(wireonface, F, Precision::Confusion());
653         sfw->FixReorder();
654         wireonface = sfw->Wire();
655         
656         //Create two new wires
657         TopoDS_Wire w1, w2;
658         theBuilder.MakeWire(w1);
659         theBuilder.MakeWire(w2);
660         theBuilder.MakeWire(tempwire);
661         for (TopExp_Explorer itnew(wireonface, TopAbs_EDGE ); itnew.More(); itnew.Next()) 
662           {
663             TopoDS_Edge ce = TopoDS::Edge (itnew.Current());
664             if (ce.IsSame(E)) 
665               { 
666                 theBuilder.Remove(wireonface, ce);
667                 theBuilder.Add(wireonface, theFirstEdge.Oriented(TopAbs_FORWARD)); 
668                 theBuilder.Add(wireonface, theSecondEdge.Oriented(TopAbs_FORWARD)); 
669               }
670           }
671         sfw->Init(wireonface, F, Precision::Confusion());
672         sfw->FixReorder();
673         wireonface = sfw->Wire();
674           
675         for (TopExp_Explorer itere(wireonface, TopAbs_EDGE); itere.More(); itere.Next()) 
676           {
677             TopoDS_Edge ce = TopoDS::Edge (itere.Current());
678             TopoDS_Vertex thecontrol;
679             if (ce.Orientation () == TopAbs_FORWARD) thecontrol = TopExp::LastVertex(ce);  
680             else thecontrol = TopExp::FirstVertex(ce);
681             theBuilder.Add(w1, ce);
682             if (thecontrol.IsSame(V))
683               {
684                 theBuilder.Add(w1, theSplitEdge.Oriented(TopAbs_FORWARD));
685                 TopoDS_Wire wtemp = w1;
686                 w1 = w2;
687                 w2 = wtemp;
688               }
689             if (thecontrol.IsSame(theNewVertex))
690               {
691                 theBuilder.Add(w1, theSplitEdge.Oriented(TopAbs_REVERSED));
692                 TopoDS_Wire wtemp = w1;
693                 w1 = w2;
694                 w2 = wtemp;
695               }
696           }
697         if ( w1.IsNull()|| w2.IsNull() ) return Standard_False;
698         //Create two new faces and replace old one
699         TopoDS_Face F1;
700         TopoDS_Face F2;
701         theBuilder.MakeFace(F1, BRep_Tool::Surface(F), Precision::Confusion());
702         theBuilder.MakeFace(F2, BRep_Tool::Surface(F), Precision::Confusion());      
703         theBuilder.Add(F1, w1);
704         theBuilder.Add(F2, w2);
705         TopoDS_Compound tf;
706         theBuilder.MakeCompound(tf);
707         theBuilder.Add(tf,F1);
708         theBuilder.Add(tf, F2);
709  //Call recursive spliteoneface() for each face     
710         if(!SplitOneFace(F1, theSplittedFaces)) theBuilder.Add(theSplittedFaces, F1);
711         if(!SplitOneFace(F2, theSplittedFaces)) theBuilder.Add(theSplittedFaces, F2);
712       }
713       return Standard_True ;
714     }
715   return Standard_False ;
716 }
717
718
719  TopoDS_Shape ShapeFix_FixSmallFace::RemoveSmallFaces() 
720 {
721    myShape = SplitFaces();
722    myShape = FixSpotFace();
723    myShape = FixStripFace ();
724    return myShape;
725
726 }
727
728  TopoDS_Face ShapeFix_FixSmallFace::FixFace(const TopoDS_Face& F) 
729 {
730 //smh#8
731   TopoDS_Shape emptyCopied = F.EmptyCopied();
732   TopoDS_Face theFixedFace = TopoDS::Face(emptyCopied);
733  // BRep_Builder theBuilder;
734   
735  // Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
736  // sfw->SetContext(Context());
737  // for (TopExp_Explorer exp_w (F,TopAbs_WIRE); exp_w.More(); exp_w.Next()) {
738  //   TopoDS_Wire theCurWire = TopoDS::Wire (exp_w.Current());
739     
740  //   sfw->Init(theCurWire,  F, Precision::Confusion());
741  //   if(sfw->NbEdges() == 0) continue;
742  //   sfw->FixNotchedEdgesMode() = 0;
743  //   sfw->Perform();
744  //   theCurWire = sfw->Wire();
745  //   theBuilder.Add(theFixedFace, theCurWire);
746  // }
747   Handle(ShapeFix_Face) sff = new ShapeFix_Face;
748   sff->SetContext(Context());
749   sff->Init(F);
750   sff->Perform();
751   //sff->Init(theFixedFace);
752   //sff->FixOrientation();
753   theFixedFace = sff->Face();
754   return theFixedFace; 
755 }
756
757  TopoDS_Shape ShapeFix_FixSmallFace::FixShape() 
758 {
759   TopoDS_Shape FixSh;
760   if(myShape.IsNull()) return FixSh;
761   /*ShapeFix_Shape sfs;
762   sfs.SetContext(Context());
763
764   sfs.SetPrecision(Precision::Confusion());
765   sfs.Init(myShape);
766   sfs.Perform();
767   FixSh = sfs.Shape();*/
768   for(TopExp_Explorer expf(myShape,TopAbs_FACE) ; expf.More(); expf.Next()) {
769    TopoDS_Face F = TopoDS::Face(expf.Current());
770 //smh#8
771    TopoDS_Shape tmpFace = Context()->Apply(F);
772    F= TopoDS::Face(tmpFace);
773    TopoDS_Face newF = FixFace(F);
774    Context()->Replace(F,newF);
775   }
776   FixSh = Context()->Apply(myShape);  
777   return FixSh;
778
779 }
780  TopoDS_Shape ShapeFix_FixSmallFace::Shape() 
781 {
782   return myShape;
783 }
784
785 Standard_Boolean ShapeFix_FixSmallFace::FixPinFace (TopoDS_Face& /*F*/)
786 {
787   return Standard_True;
788 }