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_Curve.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_Surface.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_ProgressScope.hxx>
71 #include <Message_Msg.hxx>
72 #include <ShapeExtend_BasicMsgRegistrator.hxx>
73 
74 //=======================================================================
75 //function : SameParameter
76 //purpose  :
77 //=======================================================================
78 
SameParameter(const TopoDS_Shape & shape,const Standard_Boolean enforce,const Standard_Real preci,const Message_ProgressRange & theProgress,const Handle (ShapeExtend_BasicMsgRegistrator)& theMsgReg)79 Standard_Boolean ShapeFix::SameParameter(const TopoDS_Shape& shape,
80                                          const Standard_Boolean enforce,
81                                          const Standard_Real preci,
82                                          const Message_ProgressRange& 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_ProgressScope aPSForSameParam(theProgress, "Fixing same parameter problem", 2);
110 
111   {
112     // Start progress scope (no need to check if progress exists -- it is safe)
113     Message_ProgressScope aPS (aPSForSameParam.Next(), "Fixing edge", aNbEdges);
114 
115     while ( ex.More() )
116     {
117       TopoDS_Edge E;
118       while ( ex.More() && aPS.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         aPS.Next();
165       } // -- end while
166 
167       // Halt algorithm in case of user's abort
168       if ( !aPS.More() )
169         return Standard_False;
170     }
171 
172   }
173 
174   {
175     // Start progress scope (no need to check if progress exists -- it is safe)
176     Message_ProgressScope aPS (aPSForSameParam.Next(), "Update tolerances", aNbFaces);
177 
178     //:i2 abv 21 Aug 98: ProSTEP TR8 Motor.rle face 710:
179     // Update tolerance of edges on planes (no pcurves are stored)
180     for ( TopExp_Explorer exp ( shape, TopAbs_FACE ); exp.More() && aPS.More(); exp.Next(), aPS.Next() )
181     {
182       TopoDS_Face face = TopoDS::Face ( exp.Current() );
183       Handle(Geom_Surface) Surf = BRep_Tool::Surface ( face );
184 
185       Handle(Geom_Plane) plane = Handle(Geom_Plane)::DownCast ( Surf );
186       if ( plane.IsNull() ) {
187         Handle(Geom_RectangularTrimmedSurface) GRTS =
188           Handle(Geom_RectangularTrimmedSurface)::DownCast ( Surf );
189         if ( ! GRTS.IsNull() )
190           plane = Handle(Geom_Plane)::DownCast ( GRTS->BasisSurface() );
191         if ( plane.IsNull() )
192            continue;
193       }
194 
195       Handle(GeomAdaptor_Surface) AS = new GeomAdaptor_Surface ( plane );
196       for ( TopExp_Explorer ed ( face, TopAbs_EDGE ); ed.More(); ed.Next() ) {
197         TopoDS_Edge edge = TopoDS::Edge ( ed.Current() );
198         Standard_Real f, l;
199         Handle(Geom_Curve) crv = BRep_Tool::Curve ( edge, f, l );
200         if ( crv.IsNull() )
201           continue;
202 
203         Handle(Geom2d_Curve) c2d = BRep_Tool::CurveOnSurface ( edge, face, f, l );
204         if ( c2d.IsNull() ) continue;
205         Handle(Geom2dAdaptor_Curve) GHPC = new Geom2dAdaptor_Curve ( c2d, f, l );
206         Adaptor3d_CurveOnSurface ACS(GHPC,AS);
207 
208         Standard_Real tol0 = BRep_Tool::Tolerance(edge);
209         tol = tol0;
210         Standard_Real tol2 = tol*tol;
211         Standard_Boolean isChanged = Standard_False;
212         const Standard_Integer NCONTROL = 23;
213         for ( Standard_Integer i = 0; i < NCONTROL; i++ )
214         {
215           Standard_Real par = ( f * ( NCONTROL - 1 - i ) + l * i ) / ( NCONTROL - 1 );
216           gp_Pnt pnt = crv->Value ( par );
217           gp_Pnt prj = ACS.Value( par );
218           Standard_Real dist = pnt.SquareDistance(prj);
219           if ( tol2 < dist )
220           {
221             tol2 = dist;
222             isChanged = Standard_True;
223           }
224         }
225         if ( isChanged )
226         {
227           tol = 1.00005 * sqrt(tol2); // coeff: see trj3_pm1-ct-203.stp #19681, edge 10
228           if ( tol >= tol0 )
229           {
230             B.UpdateEdge ( edge, tol );
231             for ( TopoDS_Iterator itV(edge); itV.More(); itV.Next() )
232             {
233               TopoDS_Shape S = itV.Value();
234               B.UpdateVertex ( TopoDS::Vertex ( S ), tol );
235             }
236           }
237         }
238       }
239     }
240     // Halt algorithm in case of user's abort
241     if (!aPS.More())
242       return Standard_False;
243   }
244 
245   if (!status) {
246 #ifdef OCCT_DEBUG
247     std::cout<<"** SameParameter not complete. On "<<numedge<<" Edges:";
248     if (nbfail > 0) std::cout<<"  "<<nbfail<<" Failed";
249     std::cout<<std::endl;
250 #endif
251   }
252   return status;
253 }
254 
255 
256 //=======================================================================
257 //function : EncodeRegularity
258 //purpose  :
259 //=======================================================================
260 
EncodeRegularity(const TopoDS_Shape & shape,const Standard_Real tolang)261 void ShapeFix::EncodeRegularity (const TopoDS_Shape& shape,
262                                  const Standard_Real tolang)
263 {
264   BRepLib::EncodeRegularity(shape, tolang);
265 }
266 
267 
268 //=======================================================================
269 //function : RemoveSmallEdges
270 //purpose  :
271 //=======================================================================
272 
RemoveSmallEdges(TopoDS_Shape & Shape,const Standard_Real Tolerance,Handle (ShapeBuild_ReShape)& context)273 TopoDS_Shape ShapeFix::RemoveSmallEdges (TopoDS_Shape& Shape,
274 					 const Standard_Real Tolerance,
275 					 Handle(ShapeBuild_ReShape)& context)
276 {
277   Handle(ShapeFix_Shape) sfs = new ShapeFix_Shape;
278   sfs->Init(Shape);
279   sfs->SetPrecision(Tolerance);
280   sfs->FixFaceTool()->FixMissingSeamMode() = Standard_False;
281   sfs->FixFaceTool()->FixOrientationMode() = Standard_False;
282   sfs->FixFaceTool()->FixSmallAreaWireMode() = Standard_False;
283   sfs->FixWireTool()->ModifyTopologyMode() = Standard_True;
284   //sfs.FixWireTool().FixReorderMode() = Standard_False;
285   sfs->FixWireTool()->FixConnectedMode() = Standard_False;
286   sfs->FixWireTool()->FixEdgeCurvesMode() = Standard_False;
287   sfs->FixWireTool()->FixDegeneratedMode() = Standard_False;
288   sfs->FixWireTool()->FixSelfIntersectionMode() = Standard_False;
289   sfs->FixWireTool()->FixLackingMode() = Standard_False;
290   sfs->FixWireTool()->FixSmallMode() = Standard_True;
291   sfs->Perform();
292   TopoDS_Shape result = sfs->Shape();
293   context = sfs->Context();
294   return result;
295 }
296 
297 
298 //=======================================================================
299 //function : ReplaceVertex
300 //purpose  : auxiliary for FixVertexPosition
301 //=======================================================================
ReplaceVertex(const TopoDS_Edge & theEdge,const gp_Pnt theP,const Standard_Boolean theFwd)302 static TopoDS_Edge ReplaceVertex(const TopoDS_Edge& theEdge,
303                                  const gp_Pnt theP,
304                                  const Standard_Boolean theFwd)
305 {
306   TopoDS_Vertex aNewVertex;
307   BRep_Builder aB;
308   aB.MakeVertex(aNewVertex,theP,Precision::Confusion());
309   TopoDS_Vertex aV1,aV2;
310   if(theFwd) {
311     aV1 = aNewVertex;
312     aV1.Orientation( TopAbs_FORWARD);
313   }
314   else {
315     aV2 = aNewVertex;
316     aV2.Orientation( TopAbs_REVERSED);
317   }
318   ShapeBuild_Edge aSbe;
319   TopoDS_Edge e1 = theEdge;
320   TopAbs_Orientation Ori = e1.Orientation();
321   e1.Orientation(TopAbs_FORWARD);
322   TopoDS_Edge aNewEdge = aSbe.CopyReplaceVertices(e1,aV1,aV2);
323   aNewEdge.Orientation(Ori);
324   return aNewEdge;
325 }
326 
327 
328 //=======================================================================
329 //function : getNearPoint
330 //purpose  : auxiliary for FixVertexPosition
331 //=======================================================================
getNearPoint(const TColgp_SequenceOfPnt & aSeq1,const TColgp_SequenceOfPnt & aSeq2,gp_XYZ & acent)332 static Standard_Real getNearPoint(const TColgp_SequenceOfPnt& aSeq1,
333                                   const TColgp_SequenceOfPnt& aSeq2,
334                                   gp_XYZ& acent)
335 {
336   Standard_Integer i =1;
337   Standard_Integer ind1 =0,ind2 =0;
338   Standard_Real mindist =RealLast();
339   for( ; i <= aSeq1.Length(); i++) {
340     gp_Pnt p1 = aSeq1.Value(i);
341     Standard_Integer j=1;
342     for( ; j <= aSeq2.Length(); j++) {
343       gp_Pnt p2 = aSeq2.Value(j);
344       Standard_Real d = p1.Distance(p2);
345       if(fabs(d -mindist ) <= Precision::Confusion())
346         continue;
347       if(d < mindist) {
348         mindist = d;
349         ind1 =i;
350         ind2 = j;
351       }
352 
353     }
354   }
355   if(ind1 && ind2)
356     acent = (aSeq1.Value(ind1).XYZ() + aSeq2.Value(ind2).XYZ())/2.0;
357   return mindist;
358 }
359 
360 
361 //=======================================================================
362 //function : getNearestEdges
363 //purpose  : auxiliary for FixVertexPosition
364 //=======================================================================
getNearestEdges(TopTools_ListOfShape & theLEdges,const TopoDS_Vertex theVert,TopTools_SequenceOfShape & theSuitEdges,TopTools_SequenceOfShape & theRejectEdges,const Standard_Real theTolerance,gp_XYZ & thecentersuit,gp_XYZ & thecenterreject)365 static Standard_Boolean getNearestEdges(TopTools_ListOfShape& theLEdges,
366                                         const TopoDS_Vertex theVert,
367                                         TopTools_SequenceOfShape& theSuitEdges,
368                                         TopTools_SequenceOfShape& theRejectEdges,
369                                         const Standard_Real theTolerance,
370                                         gp_XYZ& thecentersuit,
371                                         gp_XYZ& thecenterreject)
372 {
373   if(theLEdges.IsEmpty())
374     return Standard_False;
375   TopTools_MapOfShape aMapEdges;
376 
377   TopTools_ListOfShape atempList;
378   atempList= theLEdges;
379   TopTools_ListIteratorOfListOfShape alIter(atempList);
380 
381   TopoDS_Edge aEdge1 = TopoDS::Edge(alIter.Value());
382   TopoDS_Vertex aVert11,aVert12;
383   TopExp::Vertices(aEdge1, aVert11,aVert12 );
384   aMapEdges.Add(aEdge1);
385   Standard_Real aFirst1,aLast1;
386   Handle(Geom_Curve) aCurve1 = BRep_Tool::Curve(aEdge1,aFirst1,aLast1);
387   gp_Pnt p11;
388   gp_Pnt p12;
389   Standard_Boolean isFirst1 = theVert.IsSame(aVert11);
390   Standard_Boolean isSame1 = aVert11.IsSame(aVert12);
391   if( !aCurve1.IsNull()) {
392     if(isFirst1)
393       p11 = aCurve1->Value(aFirst1);
394     else if(!isSame1)
395       p11 = aCurve1->Value(aLast1);
396     if(isSame1)
397       p12 = aCurve1->Value(aLast1);
398   }
399   else return Standard_False;
400   alIter.Next();
401   TopTools_SequenceOfShape aseqreject;
402   TopTools_SequenceOfShape aseqsuit;
403 
404   Standard_Integer anumLoop =0;
405   for( ; alIter.More(); ) {
406     TopoDS_Edge aEdge = TopoDS::Edge(alIter.Value());
407     if( aMapEdges.Contains(aEdge)) {
408       atempList.Remove(alIter);
409       continue;
410     }
411 
412     TopoDS_Vertex aVert1,aVert2;
413     TopExp::Vertices(aEdge, aVert1,aVert2 );
414     Standard_Real isFirst = theVert.IsSame(aVert1);
415     Standard_Boolean isSame = aVert1.IsSame(aVert2);
416 
417     Standard_Boolean isLoop = ((aVert1.IsSame(aVert11) && aVert2.IsSame(aVert12)) ||
418                                (aVert1.IsSame(aVert12) && aVert2.IsSame(aVert11)));
419     if(isLoop /*&& !aseqsuit.Length()*/ && (atempList.Extent() >anumLoop)) {
420       atempList.Append(aEdge);
421       atempList.Remove(alIter);
422       anumLoop++;
423       continue;
424     }
425     aMapEdges.Add(aEdge);
426     Standard_Real aFirst,aLast;
427     Handle(Geom_Curve) aCurve = BRep_Tool::Curve(aEdge,aFirst,aLast);
428     if( !aCurve.IsNull()) {
429       gp_Pnt p1;
430       gp_Pnt p2;
431       if(isFirst)
432         p1 = aCurve->Value(aFirst);
433       else
434         p1 = aCurve->Value(aLast);
435       if(isSame)
436         p2 = aCurve->Value(aLast);
437       Standard_Real aMinDist = RealLast();
438       gp_XYZ acent;
439       if(!isSame && ! isSame1) {
440         aMinDist =  p1.Distance(p11);
441         acent = (p1.XYZ() + p11.XYZ())/2.0;
442       }
443       else {
444         TColgp_SequenceOfPnt aSeq1;
445         TColgp_SequenceOfPnt aSeq2;
446         aSeq1.Append(p11);
447         if(isSame1)
448           aSeq1.Append(p12);
449         aSeq2.Append(p1);
450         if(isSame)
451           aSeq2.Append(p2);
452         aMinDist = getNearPoint(aSeq1,aSeq2,acent);
453       }
454 
455       if(aMinDist > theTolerance) {
456         if(!aseqreject.Length())
457           thecenterreject = acent;
458         aseqreject.Append(aEdge);
459       }
460       else {
461         if(!aseqsuit.Length()) {
462           thecentersuit = acent;
463           aseqsuit.Append(aEdge);
464         }
465         else if(!isSame1)
466           aseqsuit.Append(aEdge);
467         else if((thecentersuit - acent).Modulus() < theTolerance)
468           aseqsuit.Append(aEdge);
469         else
470           aseqreject.Append(aEdge);
471       }
472 
473     }
474     atempList.Remove(alIter);
475   }
476 
477   Standard_Boolean isDone = (!aseqsuit.IsEmpty() || !aseqreject.IsEmpty());
478   if(isDone) {
479     if(aseqsuit.IsEmpty()) {
480       theRejectEdges.Append(aEdge1);
481       theLEdges.RemoveFirst();
482 
483       getNearestEdges(theLEdges,theVert,theSuitEdges,theRejectEdges,
484                       theTolerance,thecentersuit,thecenterreject);
485     }
486     else {
487       theSuitEdges.Append(aEdge1);
488       theSuitEdges.Append(aseqsuit);
489       theRejectEdges.Append(aseqreject);
490     }
491   }
492   else
493     theRejectEdges.Append(aEdge1);
494 
495   return isDone;
496 }
497 
498 
499 //=======================================================================
500 //function : FixVertexPosition
501 //purpose  :
502 //=======================================================================
503 
FixVertexPosition(TopoDS_Shape & theshape,const Standard_Real theTolerance,const Handle (ShapeBuild_ReShape)& thecontext)504 Standard_Boolean ShapeFix::FixVertexPosition(TopoDS_Shape& theshape,
505                                              const Standard_Real theTolerance,
506                                              const Handle(ShapeBuild_ReShape)& thecontext)
507 {
508   TopTools_IndexedDataMapOfShapeListOfShape aMapVertEdges;
509   TopExp_Explorer aExp1(theshape,TopAbs_EDGE);
510   for( ; aExp1.More(); aExp1.Next()) {
511     TopoDS_Shape aVert1;
512     Standard_Integer nV =1;
513     TopoDS_Iterator aExp3(aExp1.Current());
514     for( ; aExp3.More(); aExp3.Next(),nV++) {
515       TopoDS_Shape aVert =  aExp3.Value();
516       if(nV ==1)
517         aVert1 = aVert;
518       else if(aVert1.IsSame(aVert))
519         continue;
520       if(aMapVertEdges.Contains(aVert))
521         aMapVertEdges.ChangeFromKey(aVert).Append(aExp1.Current());
522       else {
523         TopTools_ListOfShape alEdges;
524         alEdges.Append(aExp1.Current());
525         aMapVertEdges.Add(aVert,alEdges);
526       }
527     }
528   }
529   Standard_Boolean isDone = Standard_False;
530   Standard_Integer i=1;
531   for( ; i <= aMapVertEdges.Extent(); i++) {
532     TopoDS_Vertex aVert = TopoDS::Vertex(aMapVertEdges.FindKey(i));
533     Standard_Real aTolVert = BRep_Tool::Tolerance(aVert);
534     if(aTolVert <= theTolerance)
535       continue;
536 
537     BRep_Builder aB1;
538     aB1.UpdateVertex(aVert,theTolerance);
539     gp_Pnt aPvert = BRep_Tool::Pnt(aVert);
540     gp_XYZ acenter(aPvert.XYZ()), acenterreject(aPvert.XYZ());
541 
542     TopTools_SequenceOfShape aSuitEdges;
543     TopTools_SequenceOfShape aRejectEdges;
544     TopTools_ListOfShape aledges;
545     aledges= aMapVertEdges.FindFromIndex(i);
546     if(aledges.Extent() ==1)
547       continue;
548     //if tolerance of vertex is more than specified tolerance
549     // check distance between curves and vertex
550 
551     if(!getNearestEdges(aledges,aVert,aSuitEdges,aRejectEdges,theTolerance,acenter,acenterreject))
552       continue;
553 
554     //update vertex by nearest point
555     Standard_Boolean isAdd = Standard_False;
556     Standard_Integer k =1;
557     for( ; k <= aSuitEdges.Length(); k++) {
558 
559       TopoDS_Edge aEdgeOld = TopoDS::Edge(aSuitEdges.Value(k));
560       TopoDS_Vertex aVert1,aVert2;
561       TopExp::Vertices(aEdgeOld, aVert1,aVert2 );
562 
563       Standard_Boolean isFirst = (aVert1.IsSame(aVert));
564       Standard_Boolean isLast = (aVert2.IsSame(aVert));
565       if(!isFirst && !isLast)
566         continue;
567       Standard_Real aFirst,aLast;
568       Handle(Geom_Curve) aCurve;
569       TopoDS_Edge aEdge = TopoDS::Edge(thecontext->Apply(aEdgeOld));
570 
571       TopoDS_Vertex aVert1n,aVert2n;
572       TopExp::Vertices(aEdge, aVert1n,aVert2n );
573       aCurve = BRep_Tool::Curve(aEdge,aFirst,aLast);
574       if( !aCurve.IsNull()) {
575         gp_Pnt p1 = aCurve->Value(aFirst);
576         gp_Pnt p2 = aCurve->Value(aLast);
577 
578         //if distance between ends of curve more than specified tolerance
579         //but vertices are the same that one of the vertex will be replaced.
580 
581         Standard_Boolean isReplace = (aVert1n.IsSame(aVert2n) && p1.Distance(p2) >theTolerance);
582 
583         //Standard_Real dd1 = (acenter - p1.XYZ()).Modulus();
584         //Standard_Real dd2 = (acenter - p2.XYZ()).Modulus();
585          if(isFirst) {
586            if( k>2) {
587              acenter += p1.XYZ();
588              acenter /= 2.0;
589            }
590            if(isReplace) {
591              TopoDS_Edge enew;
592              if(p1.Distance(acenter) < p2.Distance(acenter))
593                enew = ReplaceVertex(aEdge,p2,Standard_False);
594              else
595                enew = ReplaceVertex(aEdge,p1,Standard_True);
596               thecontext->Replace(aEdge,enew);
597               isDone = Standard_True;
598             }
599           }
600           else {
601             if( k>2) {
602               acenter += p2.XYZ();
603               acenter /= 2.0;
604             }
605             if(isReplace) {
606               TopoDS_Edge enew;
607              if(p1.Distance(acenter) < p2.Distance(acenter))
608                enew = ReplaceVertex(aEdge,p2,Standard_False);
609              else
610                enew = ReplaceVertex(aEdge,p1,Standard_True);
611               thecontext->Replace(aEdge,enew);
612               isDone = Standard_True;
613             }
614           }
615 
616 
617 
618         isAdd = Standard_True;
619 
620       }
621     }
622 
623 
624     if(isAdd && aPvert.Distance(acenter) > theTolerance)
625     {
626 
627       BRep_Builder aB;
628 
629       //  aB.UpdateVertex(aVert,Precision::Confusion());
630       //else {
631         isDone = Standard_True;
632         TopoDS_Vertex aNewVertex;
633         aB.MakeVertex(aNewVertex,acenter,Precision::Confusion());
634         aNewVertex.Orientation(aVert.Orientation());
635         thecontext->Replace(aVert,aNewVertex);
636 
637     }
638 
639     for( k =1; k <= aRejectEdges.Length(); k++) {
640       TopoDS_Edge aEdgeOld = TopoDS::Edge( aRejectEdges.Value(k));
641       TopoDS_Vertex aVert1,aVert2;
642       TopExp::Vertices(aEdgeOld, aVert1,aVert2 );
643 
644       Standard_Boolean isFirst = (aVert1.IsSame(aVert));
645       Standard_Boolean isLast = (aVert2.IsSame(aVert));
646       if(!isFirst && !isLast)
647         continue;
648       Standard_Boolean isSame = aVert1.IsSame(aVert2);
649       Handle(Geom_Curve) aCurve;
650       TopoDS_Edge aEdge = TopoDS::Edge(thecontext->Apply(aEdgeOld));
651 
652       TopoDS_Vertex aVert1n,aVert2n;
653       TopExp::Vertices(aEdge, aVert1n,aVert2n );
654 
655       Standard_Real aFirst,aLast;
656       aCurve = BRep_Tool::Curve(aEdge,aFirst,aLast);
657       if( !aCurve.IsNull()) {
658         gp_Pnt p1 = aCurve->Value(aFirst);
659         gp_Pnt p2 = aCurve->Value(aLast);
660         TopoDS_Edge enew;
661         if(isFirst) {
662           enew = ReplaceVertex(aEdge,p1,Standard_True);
663           if(isSame)
664             enew = ReplaceVertex(enew,p2,Standard_False);
665         }
666         else {
667           enew = ReplaceVertex(aEdge,p2,Standard_False);
668           if(isSame)
669             enew = ReplaceVertex(enew ,p1,Standard_True);
670         }
671 
672         thecontext->Replace(aEdge,enew);
673         isDone = Standard_True;
674 
675 
676       }
677 
678     }
679   }
680   if(isDone)
681     theshape = thecontext->Apply(theshape);
682   return isDone;
683 }
684 
685 
686 //=======================================================================
687 //function : LeastEdgeSize
688 //purpose  :
689 //=======================================================================
690 
LeastEdgeSize(TopoDS_Shape & theShape)691 Standard_Real ShapeFix::LeastEdgeSize(TopoDS_Shape& theShape)
692 {
693   Standard_Real aRes = RealLast();
694   for(TopExp_Explorer exp(theShape,TopAbs_EDGE); exp.More(); exp.Next()) {
695     TopoDS_Edge edge = TopoDS::Edge ( exp.Current() );
696     Standard_Real first,last;
697     Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge, first, last);
698     if(!c3d.IsNull()) {
699       Bnd_Box bb;
700       bb.Add(c3d->Value(first));
701       bb.Add(c3d->Value(last));
702       bb.Add(c3d->Value((last+first)/2.));
703       Standard_Real x1,x2,y1,y2,z1,z2,size;
704       bb.Get(x1,y1,z1,x2,y2,z2);
705       size = (x2-x1)*(x2-x1) + (y2-y1)*(y2-y1) + (z2-z1)*(z2-z1);
706       if(size<aRes) aRes = size;
707     }
708   }
709   aRes = sqrt(aRes);
710   return aRes;
711 }
712