0022746: Progress indicator in ShapeHealing
[occt.git] / src / ShapeFix / ShapeFix.cxx
1 // File:        ShapeFix.cxx
2 // Created:     Fri Jan 21 12:00:39 2000
3 // Author:      data exchange team
4 //              <det@nnov.matra-dtv.fr>
5
6
7 #include <ShapeFix.hxx>
8 //:k2 abv 16.12.98: eliminating code duplication
9 //pdn     18.12.98: checking deviation for SP edges
10 //:   abv 22.02.99: method FillFace() removed since PRO13123 is fixed
11 //szv#4 S4163
12 //szv#9:S4244:19Aug99: Added method FixWireGaps
13 //szv#10:S4244:23Aug99: Added method FixFaceGaps
14
15 #include <BRep_Builder.hxx>
16 #include <BRep_Tool.hxx>
17
18 #include <Geom2d_Curve.hxx>
19 #include <Geom_Curve.hxx>
20
21 #include <Precision.hxx>
22
23 #include <Standard_ErrorHandler.hxx>
24 #include <Standard_Failure.hxx>
25
26 #include <TopExp_Explorer.hxx>
27 #include <TopLoc_Location.hxx>
28 #include <TopoDS.hxx>
29 #include <TopoDS_Edge.hxx>
30 #include <TopoDS_Face.hxx>
31 #include <Geom_Surface.hxx>
32
33 //:i2
34 #include <gp_Pnt.hxx>
35 #include <Geom_Plane.hxx>
36 #include <ShapeFix_Edge.hxx>
37 #include <Geom2dAdaptor_HCurve.hxx>
38 #include <Adaptor3d_CurveOnSurface.hxx>
39 #include <Geom_RectangularTrimmedSurface.hxx>
40 #include <ShapeAnalysis_Surface.hxx>
41   
42 #include <ShapeFix_Edge.hxx>
43 #include <ShapeFix_Shape.hxx>
44 #include <ShapeFix_Wire.hxx>
45 #include <ShapeFix_Face.hxx>
46 #include <TopoDS_Iterator.hxx>
47 #include <GeomAdaptor_HSurface.hxx>
48 #include <TopTools_MapOfShape.hxx>
49 #include <BRepLib.hxx>
50
51 #include <ShapeAnalysis_Edge.hxx>
52 #include <ShapeBuild_Edge.hxx>
53 #include <TopoDS_Vertex.hxx>
54 #include <ShapeBuild_ReShape.hxx>
55 #include <TColgp_SequenceOfPnt.hxx>
56 #include <TopTools_ListOfShape.hxx>
57 #include <TopTools_ListIteratorOfListOfShape.hxx>
58 #include <TopTools_SequenceOfShape.hxx>
59 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
60 #include <TopExp.hxx>
61
62 #include <Message_ProgressSentry.hxx>
63
64 //=======================================================================
65 //function : SameParameter
66 //purpose  : 
67 //=======================================================================
68
69 Standard_Boolean ShapeFix::SameParameter(const TopoDS_Shape& shape,
70                                          const Standard_Boolean enforce,
71                                          const Standard_Real preci,
72                                          const Handle(Message_ProgressIndicator)& theProgress)
73 {
74   // Calculate number of edges
75   Standard_Integer aNbEdges = 0;
76   for ( TopExp_Explorer anEdgeExp(shape, TopAbs_EDGE); anEdgeExp.More(); anEdgeExp.Next() )
77     ++aNbEdges;
78
79   // Calculate number of faces
80   Standard_Integer aNbFaces = 0;
81   for ( TopExp_Explorer anEdgeExp(shape, TopAbs_FACE); anEdgeExp.More(); anEdgeExp.Next() )
82     ++aNbFaces;
83
84   BRep_Builder B;
85   //Standard_Integer nbexcp = 0; 
86   Standard_Integer nbfail = 0,  numedge = 0; 
87   Standard_Boolean status = Standard_True;
88   Standard_Real tol = preci;
89   Standard_Boolean iatol = (tol > 0);
90   Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
91   TopExp_Explorer ex(shape,TopAbs_EDGE);
92
93   // Start progress scope (no need to check if progress exists -- it is safe)
94   Message_ProgressSentry aPSentry(theProgress, "Fixing same parameter problem", 0, 2, 1);
95
96   {
97     // Start progress scope (no need to check if progress exists -- it is safe)
98     Message_ProgressSentry aPSentry(theProgress, "Fixing edge", 0, aNbEdges, 1);
99
100     while ( ex.More() )
101     {
102       TopoDS_Edge E;
103       while ( ex.More() && aPSentry.More() )
104       {
105         numedge ++;
106         int ierr = 0;
107         TopLoc_Location loc;
108         E = TopoDS::Edge (ex.Current());
109         ex.Next();
110         
111         if (!iatol)
112           tol = BRep_Tool::Tolerance (E);
113         if (enforce)
114         {
115           B.SameRange     (E,Standard_False);
116           B.SameParameter (E,Standard_False);
117         }
118
119         sfe->FixSameParameter (E); // K2-SEP97
120
121         if (!BRep_Tool::SameParameter (E)) { ierr = 1; nbfail ++; }
122         
123         if (ierr)
124         {
125           status = Standard_False;
126           B.SameRange (E,Standard_False);
127           B.SameParameter (E,Standard_False);
128         }
129
130         // Complete step in current progress scope
131         aPSentry.Next();     
132       } // -- end while
133
134       // Halt algorithm in case of user's abort
135       if ( !aPSentry.More() )
136         return Standard_False;
137     }
138
139   }
140   // Switch to "Update tolerances" step
141   aPSentry.Next();
142
143   {
144     // Start progress scope (no need to check if progress exists -- it is safe)
145     Message_ProgressSentry aPSentry(theProgress, "Update tolerances", 0, aNbFaces, 1);
146
147     //:i2 abv 21 Aug 98: ProSTEP TR8 Motor.rle face 710:
148     // Update tolerance of edges on planes (no pcurves are stored)
149     for ( TopExp_Explorer exp ( shape, TopAbs_FACE ); exp.More() && aPSentry.More(); exp.Next(), aPSentry.Next() )
150     {
151       TopoDS_Face face = TopoDS::Face ( exp.Current() );
152       Handle(Geom_Surface) Surf = BRep_Tool::Surface ( face );
153         
154       Handle(Geom_Plane) plane = Handle(Geom_Plane)::DownCast ( Surf );
155       if ( plane.IsNull() ) {
156         Handle(Geom_RectangularTrimmedSurface) GRTS = 
157           Handle(Geom_RectangularTrimmedSurface)::DownCast ( Surf );
158         if ( ! GRTS.IsNull() ) 
159           plane = Handle(Geom_Plane)::DownCast ( GRTS->BasisSurface() );
160         if ( plane.IsNull() )
161            continue;
162       }
163
164       Handle(GeomAdaptor_HSurface) AS = new GeomAdaptor_HSurface ( plane );
165       for ( TopExp_Explorer ed ( face, TopAbs_EDGE ); ed.More(); ed.Next() ) {
166         TopoDS_Edge edge = TopoDS::Edge ( ed.Current() );
167         Standard_Real f, l;
168         Handle(Geom_Curve) crv = BRep_Tool::Curve ( edge, f, l );
169         if ( crv.IsNull() )
170           continue;
171         
172         Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface ( edge, face, f, l );;
173         if ( c2d.IsNull() ) continue;
174         Handle(Geom2dAdaptor_HCurve) GHPC = new Geom2dAdaptor_HCurve ( c2d, f, l );
175         Adaptor3d_CurveOnSurface ACS(GHPC,AS);
176         
177         Standard_Real tol0 = BRep_Tool::Tolerance(edge);
178         tol = tol0;
179         Standard_Real tol2 = tol*tol;
180         const Standard_Integer NCONTROL = 23;
181         for ( Standard_Integer i = 0; i < NCONTROL; i++ )
182         {
183           Standard_Real par = ( f * ( NCONTROL - 1 - i ) + l * i ) / ( NCONTROL - 1 );
184           gp_Pnt pnt = crv->Value ( par );
185           gp_Pnt prj = ACS.Value( par );
186           Standard_Real dist = pnt.SquareDistance(prj);
187           if ( tol2 < dist )
188             tol2 = dist;
189         }
190         tol = 1.00005 * sqrt(tol2); // coeff: see trj3_pm1-ct-203.stp #19681, edge 10
191         if ( tol >= tol0 )
192         {
193           B.UpdateEdge ( edge, tol );
194           for ( TopoDS_Iterator itV(edge); itV.More(); itV.Next() )
195           {
196             TopoDS_Shape S = itV.Value();
197             B.UpdateVertex ( TopoDS::Vertex ( S ), tol );
198           }
199         }
200       }
201
202       // Halt algorithm in case of user's abort
203       if ( !aPSentry.More() )
204         return Standard_False;
205     }
206   }
207
208   if (!status) {
209 #ifdef DEB
210     cout<<"** SameParameter not complete. On "<<numedge<<" Edges:";
211     if (nbfail > 0) cout<<"  "<<nbfail<<" Failed";
212     cout<<endl;
213 #endif
214   }
215   return status;
216 }
217
218
219 //=======================================================================
220 //function : EncodeRegularity
221 //purpose  : 
222 //=======================================================================
223
224 static void EncodeRegularity (const TopoDS_Shape& shape,
225                               const Standard_Real tolang,
226                               TopTools_MapOfShape &aMap)
227 {
228   TopoDS_Shape S = shape;
229   TopLoc_Location L;
230   S.Location ( L );
231   if ( ! aMap.Add ( S ) ) return;
232   
233   if ( S.ShapeType() == TopAbs_COMPOUND || 
234        S.ShapeType() == TopAbs_COMPSOLID ) {
235     for ( TopoDS_Iterator it(S); it.More(); it.Next() ) {
236       EncodeRegularity ( it.Value(), tolang, aMap );
237     }
238     return;
239   }
240   
241   try {
242     OCC_CATCH_SIGNALS
243     BRepLib::EncodeRegularity ( S, tolang );
244   }
245   catch(Standard_Failure) {
246 #ifdef DEB
247     cout << "Warning: Exception in ShapeFix::EncodeRegularity(): ";
248     Standard_Failure::Caught()->Print ( cout );
249     cout << endl;
250 #endif
251   }
252 }
253
254 void ShapeFix::EncodeRegularity (const TopoDS_Shape& shape,
255                                  const Standard_Real tolang)
256 {
257   TopTools_MapOfShape aMap;
258   ::EncodeRegularity ( shape, tolang, aMap );
259 }
260
261
262 //=======================================================================
263 //function : RemoveSmallEdges
264 //purpose  : 
265 //=======================================================================
266
267 TopoDS_Shape ShapeFix::RemoveSmallEdges (TopoDS_Shape& Shape,
268                                          const Standard_Real Tolerance,
269                                          Handle(ShapeBuild_ReShape)& context)
270 {
271   Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
272   sfs->Init(Shape);
273   sfs->SetPrecision(Tolerance);
274   Handle(ShapeFix_Face)::DownCast(sfs->FixFaceTool())->FixMissingSeamMode() = Standard_False;
275   Handle(ShapeFix_Face)::DownCast(sfs->FixFaceTool())->FixOrientationMode() = Standard_False;
276   Handle(ShapeFix_Face)::DownCast(sfs->FixFaceTool())->FixSmallAreaWireMode() = Standard_False;
277   sfs->FixWireTool()->ModifyTopologyMode() = Standard_True;
278   //sfs.FixWireTool().FixReorderMode() = Standard_False;
279   sfs->FixWireTool()->FixConnectedMode() = Standard_False;
280   sfs->FixWireTool()->FixEdgeCurvesMode() = Standard_False;
281   sfs->FixWireTool()->FixDegeneratedMode() = Standard_False;
282   Handle(ShapeFix_Wire)::DownCast(sfs->FixWireTool())->FixSelfIntersectionMode() = Standard_False; 
283   Handle(ShapeFix_Wire)::DownCast(sfs->FixWireTool())->FixLackingMode() = Standard_False; 
284   Handle(ShapeFix_Wire)::DownCast(sfs->FixWireTool())->FixSmallMode() = Standard_True;
285   sfs->Perform();
286   TopoDS_Shape result = sfs->Shape();
287   context = sfs->Context();
288   return result;
289 }
290
291
292 //=======================================================================
293 //function : ReplaceVertex
294 //purpose  : auxilary for FixVertexPosition
295 //=======================================================================
296 static TopoDS_Edge ReplaceVertex(const TopoDS_Edge& theEdge,
297                                  const gp_Pnt theP,
298                                  const Standard_Boolean theFwd)
299 {
300   TopoDS_Vertex aNewVertex;
301   BRep_Builder aB;
302   aB.MakeVertex(aNewVertex,theP,Precision::Confusion());
303   TopoDS_Vertex aV1,aV2;
304   if(theFwd) {
305     aV1 = aNewVertex;
306     aV1.Orientation( TopAbs_FORWARD);
307   }
308   else {
309     aV2 = aNewVertex;
310     aV2.Orientation( TopAbs_REVERSED);
311   }
312   ShapeBuild_Edge aSbe;
313   TopoDS_Edge e1 = theEdge;
314   TopAbs_Orientation Ori = e1.Orientation();
315   e1.Orientation(TopAbs_FORWARD);
316   TopoDS_Edge aNewEdge = aSbe.CopyReplaceVertices(e1,aV1,aV2);
317   aNewEdge.Orientation(Ori);
318   return aNewEdge;
319 }
320
321
322 //=======================================================================
323 //function : getNearPoint
324 //purpose  : auxilary for FixVertexPosition
325 //=======================================================================
326 static Standard_Real getNearPoint(const TColgp_SequenceOfPnt& aSeq1,
327                                   const TColgp_SequenceOfPnt& aSeq2,
328                                   gp_XYZ& acent)
329 {
330   Standard_Integer i =1;
331   Standard_Integer ind1 =0,ind2 =0;
332   Standard_Real mindist =RealLast();
333   for( ; i <= aSeq1.Length(); i++) {
334     gp_Pnt p1 = aSeq1.Value(i);
335     Standard_Integer j=1;
336     for( ; j <= aSeq2.Length(); j++) {
337       gp_Pnt p2 = aSeq2.Value(j);
338       Standard_Real d = p1.Distance(p2);
339       if(fabs(d -mindist ) <= Precision::Confusion())
340         continue;
341       if(d < mindist) {
342         mindist = d;
343         ind1 =i;
344         ind2 = j;
345       }
346       
347     }
348   }
349   if(ind1 && ind2)
350     acent = (aSeq1.Value(ind1).XYZ() + aSeq2.Value(ind2).XYZ())/2.0;
351   return mindist;
352 }
353
354
355 //=======================================================================
356 //function : getNearestEdges
357 //purpose  : auxilary for FixVertexPosition
358 //=======================================================================
359 static Standard_Boolean getNearestEdges(TopTools_ListOfShape& theLEdges,
360                                         const TopoDS_Vertex theVert,
361                                         TopTools_SequenceOfShape& theSuitEdges,
362                                         TopTools_SequenceOfShape& theRejectEdges,
363                                         const Standard_Real theTolerance,
364                                         gp_XYZ& thecentersuit,
365                                         gp_XYZ& thecenterreject)
366 {
367   if(theLEdges.IsEmpty())
368     return Standard_False;
369   TopTools_MapOfShape aMapEdges;
370   
371   TopTools_ListOfShape atempList;
372   atempList= theLEdges;
373   TopTools_ListIteratorOfListOfShape alIter(atempList);
374   
375   TopoDS_Edge aEdge1 = TopoDS::Edge(alIter.Value());
376   TopoDS_Vertex aVert11,aVert12;
377   TopExp::Vertices(aEdge1, aVert11,aVert12 );
378   aMapEdges.Add(aEdge1);
379   Standard_Real aFirst1,aLast1;
380   Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(aEdge1,aFirst1,aLast1);
381   gp_Pnt p11;
382   gp_Pnt p12;
383   Standard_Boolean isFirst1 = theVert.IsSame(aVert11);
384   Standard_Boolean isSame1 = aVert11.IsSame(aVert12);
385   if( !aCurve1.IsNull()) {
386     if(isFirst1)
387       p11 = aCurve1->Value(aFirst1);
388     else if(!isSame1)
389       p11 = aCurve1->Value(aLast1);
390     if(isSame1)
391       p12 = aCurve1->Value(aLast1);
392   }
393   else return Standard_False;
394   alIter.Next();
395   TopTools_SequenceOfShape aseqreject;
396   TopTools_SequenceOfShape aseqsuit;
397   
398   Standard_Integer anumLoop =0;
399   for( ; alIter.More(); ) {
400     TopoDS_Edge aEdge = TopoDS::Edge(alIter.Value());
401     if( aMapEdges.Contains(aEdge)) {
402       atempList.Remove(alIter);
403       continue;
404     }
405     
406     TopoDS_Vertex aVert1,aVert2;
407     TopExp::Vertices(aEdge, aVert1,aVert2 );
408     Standard_Real isFirst = theVert.IsSame(aVert1);
409     Standard_Boolean isSame = aVert1.IsSame(aVert2);
410     
411     Standard_Boolean isLoop = ((aVert1.IsSame(aVert11) && aVert2.IsSame(aVert12)) ||
412                                (aVert1.IsSame(aVert12) && aVert2.IsSame(aVert11)));
413     if(isLoop /*&& !aseqsuit.Length()*/ && (atempList.Extent() >anumLoop)) {
414       atempList.Append(aEdge);
415       atempList.Remove(alIter);
416       anumLoop++;
417       continue;
418     }
419     aMapEdges.Add(aEdge);
420     Standard_Real aFirst,aLast;
421     Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge,aFirst,aLast);
422     if( !aCurve.IsNull()) {
423       gp_Pnt p1;
424       gp_Pnt p2;
425       if(isFirst)
426         p1 = aCurve->Value(aFirst);
427       else
428         p1 = aCurve->Value(aLast);
429       if(isSame)
430         p2 = aCurve->Value(aLast);
431       Standard_Real aMinDist = RealLast();
432       gp_XYZ acent;
433       if(!isSame && ! isSame1) {
434         aMinDist =  p1.Distance(p11);
435         acent = (p1.XYZ() + p11.XYZ())/2.0;
436       }
437       else {
438         TColgp_SequenceOfPnt aSeq1;
439         TColgp_SequenceOfPnt aSeq2;
440         aSeq1.Append(p11);
441         if(isSame1)
442           aSeq1.Append(p12);
443         aSeq2.Append(p1);
444         if(isSame)
445           aSeq2.Append(p2);
446         aMinDist = getNearPoint(aSeq1,aSeq2,acent);
447       }
448       
449       if(aMinDist > theTolerance) {
450         if(!aseqreject.Length()) 
451           thecenterreject = acent;
452         aseqreject.Append(aEdge);
453       }
454       else {
455         if(!aseqsuit.Length()) {
456           thecentersuit = acent;
457           aseqsuit.Append(aEdge);
458         }
459         else if(!isSame1)
460           aseqsuit.Append(aEdge);
461         else if((thecentersuit - acent).Modulus() < theTolerance)
462           aseqsuit.Append(aEdge);
463         else
464           aseqreject.Append(aEdge);
465       }
466       
467     }
468     atempList.Remove(alIter);
469   }
470
471   Standard_Boolean isDone = (!aseqsuit.IsEmpty() || !aseqreject.IsEmpty());
472   if(isDone) {
473     if(aseqsuit.IsEmpty()) {
474       theRejectEdges.Append(aEdge1);
475       theLEdges.RemoveFirst();
476       
477       getNearestEdges(theLEdges,theVert,theSuitEdges,theRejectEdges,
478                       theTolerance,thecentersuit,thecenterreject);
479     }
480     else {
481       theSuitEdges.Append(aEdge1);
482       theSuitEdges.Append(aseqsuit);
483       theRejectEdges.Append(aseqreject);
484     }
485   }
486   else
487     theRejectEdges.Append(aEdge1);
488   
489   return isDone;
490 }
491
492
493 //=======================================================================
494 //function : FixVertexPosition
495 //purpose  : 
496 //=======================================================================
497
498 Standard_Boolean ShapeFix::FixVertexPosition(TopoDS_Shape& theshape, 
499                                              const Standard_Real theTolerance,
500                                              const Handle(ShapeBuild_ReShape)& thecontext)
501 {
502   TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdges;
503   TopExp_Explorer aExp1(theshape,TopAbs_EDGE);
504   for( ; aExp1.More(); aExp1.Next()) {
505     TopoDS_Shape aVert1;
506     Standard_Integer nV =1;
507     TopoDS_Iterator aExp3(aExp1.Current());
508     for( ; aExp3.More(); aExp3.Next(),nV++) {
509       TopoDS_Shape aVert =  aExp3.Value();
510       if(nV ==1)
511         aVert1 = aVert;
512       else if(aVert1.IsSame(aVert))
513         continue;
514       if(aMapVertEdges.Contains(aVert))
515         aMapVertEdges.ChangeFromKey(aVert).Append(aExp1.Current());
516       else {
517         TopTools_ListOfShape alEdges;
518         alEdges.Append(aExp1.Current());
519         aMapVertEdges.Add(aVert,alEdges);
520       }
521     }
522   }
523   Standard_Boolean isDone = Standard_False;
524   Standard_Integer i=1;
525   for( ; i <= aMapVertEdges.Extent(); i++) {
526     TopoDS_Vertex aVert = TopoDS::Vertex(aMapVertEdges.FindKey(i));
527     Standard_Real aTolVert = BRep_Tool::Tolerance(aVert);
528     if(aTolVert <= theTolerance)
529       continue;
530     
531     BRep_Builder aB1;
532     aB1.UpdateVertex(aVert,theTolerance);
533     gp_Pnt aPvert = BRep_Tool::Pnt(aVert);
534     gp_XYZ acenter(aPvert.XYZ()), acenterreject(aPvert.XYZ());
535     
536     TopTools_SequenceOfShape aSuitEdges;
537     TopTools_SequenceOfShape aRejectEdges;
538     TopTools_ListOfShape aledges;
539     aledges= aMapVertEdges.FindFromIndex(i);
540     if(aledges.Extent() ==1)
541       continue;
542     //if tolerance of vertex is more than specified tolerance 
543     // check distance between curves and vertex
544     
545     if(!getNearestEdges(aledges,aVert,aSuitEdges,aRejectEdges,theTolerance,acenter,acenterreject))
546       continue;
547
548     //update vertex by nearest point
549     Standard_Boolean isAdd = Standard_False;
550     Standard_Integer k =1;
551     for( ; k <= aSuitEdges.Length(); k++) {
552     
553       TopoDS_Edge aEdgeOld = TopoDS::Edge(aSuitEdges.Value(k));
554       TopoDS_Vertex aVert1,aVert2;
555       TopExp::Vertices(aEdgeOld, aVert1,aVert2 );
556     
557       Standard_Boolean isFirst = (aVert1.IsSame(aVert));
558       Standard_Boolean isLast = (aVert2.IsSame(aVert));
559       if(!isFirst && !isLast)
560         continue;
561       Standard_Real aFirst,aLast;
562       Handle(Geom_Curve) aCurve;
563       TopoDS_Edge aEdge = TopoDS::Edge(thecontext->Apply(aEdgeOld));
564
565       TopoDS_Vertex aVert1n,aVert2n;
566       TopExp::Vertices(aEdge, aVert1n,aVert2n );
567       aCurve = BRep_Tool::Curve(aEdge,aFirst,aLast);
568       if( !aCurve.IsNull()) {
569         gp_Pnt p1 = aCurve->Value(aFirst);
570         gp_Pnt p2 = aCurve->Value(aLast);
571         
572         //if distance between ends of curve more than specified tolerance
573         //but vertices are the same that one of the vertex will be replaced.
574
575         Standard_Boolean isReplace = (aVert1n.IsSame(aVert2n) && p1.Distance(p2) >theTolerance);
576         
577         //Standard_Real dd1 = (acenter - p1.XYZ()).Modulus();
578         //Standard_Real dd2 = (acenter - p2.XYZ()).Modulus();
579          if(isFirst) {
580            if( k>2) {
581              acenter += p1.XYZ();
582              acenter /= 2.0;
583            }
584            if(isReplace) {
585              TopoDS_Edge enew;
586              if(p1.Distance(acenter) < p2.Distance(acenter))
587                enew = ReplaceVertex(aEdge,p2,Standard_False);
588              else
589                enew = ReplaceVertex(aEdge,p1,Standard_True);
590               thecontext->Replace(aEdge,enew);
591               isDone = Standard_True;
592             }
593           }
594           else {
595             if( k>2) {
596               acenter += p2.XYZ();
597               acenter /= 2.0;
598             }
599             if(isReplace) {
600               TopoDS_Edge enew;
601              if(p1.Distance(acenter) < p2.Distance(acenter))
602                enew = ReplaceVertex(aEdge,p2,Standard_False);
603              else
604                enew = ReplaceVertex(aEdge,p1,Standard_True);
605               thecontext->Replace(aEdge,enew);
606               isDone = Standard_True;
607             }
608           }
609           
610       
611           
612         isAdd = Standard_True;
613        
614       }
615     }
616     
617   
618     if(isAdd && aPvert.Distance(acenter) > theTolerance)
619     {
620       
621       BRep_Builder aB;
622      
623       //  aB.UpdateVertex(aVert,Precision::Confusion());
624       //else {
625         isDone = Standard_True;
626         TopoDS_Vertex aNewVertex;
627         aB.MakeVertex(aNewVertex,acenter,Precision::Confusion());
628         aNewVertex.Orientation(aVert.Orientation());
629         thecontext->Replace(aVert,aNewVertex);
630       
631     }
632     
633     for( k =1; k <= aRejectEdges.Length(); k++) {
634       TopoDS_Edge aEdgeOld = TopoDS::Edge( aRejectEdges.Value(k));
635       TopoDS_Vertex aVert1,aVert2;
636       TopExp::Vertices(aEdgeOld, aVert1,aVert2 );
637     
638       Standard_Boolean isFirst = (aVert1.IsSame(aVert));
639       Standard_Boolean isLast = (aVert2.IsSame(aVert));
640       if(!isFirst && !isLast)
641         continue;
642       Standard_Boolean isSame = aVert1.IsSame(aVert2);
643       Handle(Geom_Curve) aCurve;
644       TopoDS_Edge aEdge = TopoDS::Edge(thecontext->Apply(aEdgeOld));
645
646       TopoDS_Vertex aVert1n,aVert2n;
647       TopExp::Vertices(aEdge, aVert1n,aVert2n );
648       
649       Standard_Real aFirst,aLast;
650       aCurve = BRep_Tool::Curve(aEdge,aFirst,aLast);
651       if( !aCurve.IsNull()) {
652         gp_Pnt p1 = aCurve->Value(aFirst);
653         gp_Pnt p2 = aCurve->Value(aLast);
654         TopoDS_Edge enew;
655         if(isFirst) {
656           enew = ReplaceVertex(aEdge,p1,Standard_True);
657           if(isSame)
658             enew = ReplaceVertex(enew,p2,Standard_False);
659         }
660         else {
661           enew = ReplaceVertex(aEdge,p2,Standard_False);
662           if(isSame)
663             enew = ReplaceVertex(enew ,p1,Standard_True);
664         }
665         
666         thecontext->Replace(aEdge,enew);
667         isDone = Standard_True;
668         
669         
670       }
671       
672     }
673   }
674   if(isDone)
675     theshape = thecontext->Apply(theshape);
676   return isDone;
677 }
678
679
680 //=======================================================================
681 //function : LeastEdgeSize
682 //purpose  : 
683 //=======================================================================
684
685 Standard_Real ShapeFix::LeastEdgeSize(TopoDS_Shape& theShape)
686 {
687   Standard_Real aRes = RealLast();
688   for(TopExp_Explorer exp(theShape,TopAbs_EDGE); exp.More(); exp.Next()) { 
689     TopoDS_Edge edge = TopoDS::Edge ( exp.Current() );
690     Standard_Real first,last;
691     Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge, first, last);
692     if(!c3d.IsNull()) {
693       Bnd_Box bb;
694       bb.Add(c3d->Value(first));
695       bb.Add(c3d->Value(last));
696       bb.Add(c3d->Value((last+first)/2.));
697       Standard_Real x1,x2,y1,y2,z1,z2,size;
698       bb.Get(x1,y1,z1,x2,y2,z2);
699       size = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1);
700       if(size<aRes) aRes = size;
701     }
702   }
703   aRes = sqrt(aRes);
704   return aRes;
705 }