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