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