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