0022048: Visualization, AIS_InteractiveContext - single object selection should alway...
[occt.git] / src / ShapeFix / ShapeFix_Wireframe.cxx
1 // Created on: 1999-08-24
2 // Created by: Sergei ZERTCHANINOV
3 // Copyright (c) 1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <BRep_Builder.hxx>
19 #include <BRep_Tool.hxx>
20 #include <Geom2d_BSplineCurve.hxx>
21 #include <Geom2d_Curve.hxx>
22 #include <Geom_BSplineCurve.hxx>
23 #include <Geom_Curve.hxx>
24 #include <GeomAPI.hxx>
25 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
26 #include <gp_Pln.hxx>
27 #include <gp_Pnt.hxx>
28 #include <Message_Msg.hxx>
29 #include <ShapeAnalysis_Edge.hxx>
30 #include <ShapeAnalysis_TransferParametersProj.hxx>
31 #include <ShapeBuild_Edge.hxx>
32 #include <ShapeBuild_ReShape.hxx>
33 #include <ShapeConstruct.hxx>
34 #include <ShapeConstruct_Curve.hxx>
35 #include <ShapeFix.hxx>
36 #include <ShapeFix_Edge.hxx>
37 #include <ShapeFix_Wire.hxx>
38 #include <ShapeFix_Wireframe.hxx>
39 #include <Standard_ErrorHandler.hxx>
40 #include <Standard_Failure.hxx>
41 #include <Standard_Type.hxx>
42 #include <TopExp_Explorer.hxx>
43 #include <TopoDS.hxx>
44 #include <TopoDS_Compound.hxx>
45 #include <TopoDS_Edge.hxx>
46 #include <TopoDS_Face.hxx>
47 #include <TopoDS_Iterator.hxx>
48 #include <TopoDS_Shape.hxx>
49 #include <TopoDS_Vertex.hxx>
50 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
51 #include <TopTools_DataMapOfShapeInteger.hxx>
52 #include <TopTools_DataMapOfShapeListOfShape.hxx>
53 #include <TopTools_DataMapOfShapeShape.hxx>
54 #include <TopTools_ListIteratorOfListOfShape.hxx>
55 #include <TopTools_ListOfShape.hxx>
56 #include <TopTools_MapOfShape.hxx>
57
58 IMPLEMENT_STANDARD_RTTIEXT(ShapeFix_Wireframe,ShapeFix_Root)
59
60 //#include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
61 //=======================================================================
62 //function : ShapeFix_Wireframe
63 //purpose  : 
64 //=======================================================================
65 ShapeFix_Wireframe::ShapeFix_Wireframe()
66 {
67   ClearStatuses();
68   myModeDrop = Standard_False;
69   myLimitAngle = -1;
70 }
71
72 //=======================================================================
73 //function : ShapeFix_Wireframe
74 //purpose  : 
75 //=======================================================================
76
77 ShapeFix_Wireframe::ShapeFix_Wireframe(const TopoDS_Shape& shape)
78 {
79   ClearStatuses();
80   myShape = shape;
81   myModeDrop = Standard_False;
82   myLimitAngle = -1;
83 }
84
85 //=======================================================================
86 //function : ClearStatuses
87 //purpose  : 
88 //=======================================================================
89
90  void ShapeFix_Wireframe::ClearStatuses()
91 {
92   Standard_Integer emptyStatus = ShapeExtend::EncodeStatus( ShapeExtend_OK );
93
94   myStatusWireGaps   = emptyStatus;
95   myStatusSmallEdges = emptyStatus;
96 }
97
98 //=======================================================================
99 //function : Load
100 //purpose  : 
101 //=======================================================================
102
103  void ShapeFix_Wireframe::Load(const TopoDS_Shape& shape)
104 {
105   ClearStatuses();
106   myShape = shape;
107 }
108
109 //=======================================================================
110 //function : FixWireGaps
111 //purpose  : 
112 //=======================================================================
113
114  Standard_Boolean ShapeFix_Wireframe::FixWireGaps()
115 {
116   myStatusWireGaps = ShapeExtend::EncodeStatus( ShapeExtend_OK );
117   if (myShape.IsNull()) return Standard_False;
118
119   if (Context().IsNull()) SetContext(new ShapeBuild_ReShape);
120   else 
121   {
122     TopoDS_Shape shape = myShape;
123     myShape.Nullify();
124     myShape = Context()->Apply(shape);
125   }
126   
127   Standard_Real prec = (Precision()>0.)? Precision() : Precision::Confusion();
128   TopTools_DataMapOfShapeShape cont;
129   if ( myShape.ShapeType() == TopAbs_COMPOUND ) 
130   {
131     Standard_Boolean locModified = Standard_False;
132     TopoDS_Compound C;
133     BRep_Builder B;
134     B.MakeCompound ( C );
135     TopoDS_Shape savShape = myShape;
136     for ( TopoDS_Iterator it(savShape); it.More(); it.Next() ) 
137     {
138       TopoDS_Shape shape1 = it.Value();
139       TopLoc_Location L = shape1.Location(),nullLoc;
140       shape1.Location ( nullLoc );
141       TopoDS_Shape res;
142       if ( cont.IsBound ( shape1 ) )
143       {
144         res = cont.Find ( shape1 ).Oriented ( shape1.Orientation() );
145       }
146       else 
147       {
148         myShape = shape1;
149         FixWireGaps();
150         res = Shape();
151         cont.Bind(myShape,res);
152       }
153       if ( ! res.IsSame ( shape1 ) ) locModified = Standard_True;
154       res.Location ( L );
155       B.Add ( C, res );
156       
157     }
158     if (locModified ) 
159     {
160       C.Orientation(savShape.Orientation());
161       Context()->Replace(savShape,C);
162     }
163     myShape = Context()->Apply(savShape);
164     return StatusWireGaps(ShapeExtend_DONE);
165   }
166   Handle(ShapeFix_Wire) sfw = new ShapeFix_Wire;
167   sfw->SetContext(Context());
168   sfw->SetPrecision(prec);
169
170   TopoDS_Face face;
171   for (TopExp_Explorer anExpf1(myShape,TopAbs_FACE); anExpf1.More(); anExpf1.Next()) 
172   {
173 //smh#8
174     TopoDS_Shape tmpF = Context()->Apply(anExpf1.Current());
175     face = TopoDS::Face(tmpF);
176     if (face.Orientation()==TopAbs_REVERSED) face.Orientation(TopAbs_FORWARD);
177     for (TopoDS_Iterator itw(face); itw.More(); itw.Next()) 
178     {
179       if(itw.Value().ShapeType() != TopAbs_WIRE)
180         continue;
181 //smh#8
182       TopoDS_Shape tmpW = Context()->Apply(itw.Value());
183       sfw->Init(TopoDS::Wire(tmpW), face, prec);
184       sfw->FixReorder();
185       sfw->FixGaps3d();
186       if (sfw->StatusGaps3d(ShapeExtend_DONE))
187         myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
188       if (sfw->StatusGaps3d(ShapeExtend_FAIL))
189         myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
190       sfw->FixGaps2d();
191       if (sfw->StatusGaps2d(ShapeExtend_DONE))
192         myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
193       if (sfw->StatusGaps2d(ShapeExtend_FAIL))
194         myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL2 );
195       if (sfw->StatusGaps3d(ShapeExtend_DONE) || sfw->StatusGaps2d(ShapeExtend_DONE))
196         SendWarning( itw.Value(), Message_Msg( "FixWireframe.FixFixWireGaps.MSG0" ));
197     }
198   }
199
200   //============================================================
201   //Author :  enk 
202   //Purpose:  This block fixing a 3d wire which not lie on plane
203   // Part 1
204   //============================================================
205   for (TopExp_Explorer expw(myShape,TopAbs_WIRE,TopAbs_FACE); expw.More(); expw.Next())
206   {
207     TopoDS_Shape tmpW = Context()->Apply(expw.Current());
208     sfw->Load(TopoDS::Wire(tmpW));
209     sfw->SetPrecision(prec);
210     sfw->FixReorder();
211     sfw->FixGaps3d();
212     if (sfw->StatusGaps3d(ShapeExtend_DONE))
213       myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
214     if (sfw->StatusGaps3d(ShapeExtend_FAIL))
215       myStatusWireGaps |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
216     if (sfw->StatusGaps3d(ShapeExtend_DONE))
217       SendWarning( expw.Current(), Message_Msg( "FixWireframe.FixFixWireGaps.MSG0" ));
218   }
219   //End Part1========================================================
220
221   if (StatusWireGaps(ShapeExtend_DONE)) 
222   {
223
224     myShape = Context()->Apply(myShape);
225
226     ShapeFix::SameParameter(myShape,Standard_False);
227
228     TopoDS_Wire wire;
229     Handle(ShapeFix_Edge) sfe = new ShapeFix_Edge;
230     for (TopExp_Explorer anExpf2(myShape,TopAbs_FACE); anExpf2.More(); anExpf2.Next()) 
231     {
232       face = TopoDS::Face(anExpf2.Current());
233       if (face.Orientation()==TopAbs_REVERSED) face.Orientation(TopAbs_FORWARD);
234       for (TopoDS_Iterator itw(face); itw.More(); itw.Next()) 
235       {
236         if(itw.Value().ShapeType() != TopAbs_WIRE)
237           continue;
238         wire = TopoDS::Wire(itw.Value());
239         sfw->Init(wire, face, prec);
240         sfw->FixReorder();
241         sfw->FixSelfIntersection();
242         for (TopoDS_Iterator ite(wire); ite.More(); ite.Next())
243           sfe->FixVertexTolerance(TopoDS::Edge(ite.Value()));
244       }
245     }
246     
247     // enk Part 2
248     for (TopExp_Explorer expw2(myShape,TopAbs_WIRE,TopAbs_FACE); expw2.More(); expw2.Next()) 
249     {
250         wire = TopoDS::Wire(expw2.Current());
251         sfw->Load(wire);
252         sfw->SetPrecision(prec);
253         sfw->FixReorder();
254         sfw->FixSelfIntersection();
255         for (TopoDS_Iterator ite(wire); ite.More(); ite.Next())
256           sfe->FixVertexTolerance(TopoDS::Edge(ite.Value()));
257       
258     }
259     // End Part 2
260     
261     return Standard_True;
262   }
263
264   return Standard_False;
265 }
266
267 //=======================================================================
268 //function : JoinEdges (static)
269 //purpose  : used in FixSmallEdges
270 //=======================================================================
271
272  static Standard_Boolean JoinEdges(const TopoDS_Edge& E1,
273                               const TopoDS_Edge& E2,
274                               TopoDS_Edge& E3,
275                               const TopTools_ListOfShape& faces)
276 {
277   Standard_Boolean ReplaceFirst = Standard_True;
278   ShapeAnalysis_Edge sae;
279   Handle(Geom_Curve) c3d1,c3d2;
280   Handle(Geom2d_Curve) c2d1,c2d2; //TopTools
281   TopoDS_Edge newedge,newedge1;
282   E3 = newedge1;
283   TopoDS_Vertex V11 = sae.FirstVertex(E1);
284   TopoDS_Vertex V12 = sae.LastVertex(E1);
285   TopoDS_Vertex V21 = sae.FirstVertex(E2);
286   TopoDS_Vertex V22 = sae.LastVertex(E2);
287   
288   
289   Standard_Boolean isSame = (V11.IsSame(V12) || V22.IsSame(V21));
290   BRep_Builder B;
291   B.MakeEdge(newedge);
292   Standard_Real cf1,cf2,cl1,cl2,first1,first2,last1,last2;
293   newedge.Orientation(TopAbs_FORWARD);
294   try 
295   {
296     OCC_CATCH_SIGNALS
297     if(!sae.Curve3d(E1,c3d1,cf1,cl1,Standard_False )) return ReplaceFirst;
298     if(!sae.Curve3d(E2,c3d2,cf2,cl2,Standard_False )) return ReplaceFirst;
299     
300     
301     B.Add(newedge,V11.Oriented(TopAbs_FORWARD));
302     B.Add(newedge,V22.Oriented(TopAbs_REVERSED));
303     
304     Handle(Geom_Curve) CRes;
305     Standard_Boolean isRev1,isRev2;
306 //     Standard_Real newf,newl;
307     if(!ShapeConstruct::JoinCurves(c3d1,c3d2,E1.Orientation(),E2.Orientation(),cf1, cl1,cf2, cl2,CRes,isRev1,isRev2))
308       return  ReplaceFirst;
309 //    if(isRev1 || isRev2)
310     if(!isSame && (isRev1 || isRev2))
311       return  ReplaceFirst;
312     ReplaceFirst = (!isRev1);
313     
314     Standard_Real newf = cf1;
315     Standard_Real newl = cl1 + cl2 - cf2;
316     TopAbs_Orientation OrEdge1 = E1.Orientation();
317     TopAbs_Orientation OrEdge2 = E2.Orientation();
318     Standard_Boolean ismanifold =(OrEdge1 == TopAbs_FORWARD || OrEdge1 == TopAbs_REVERSED);
319     Standard_Boolean ismanifold2 = (OrEdge2 == TopAbs_FORWARD || OrEdge2 == TopAbs_REVERSED);
320     if(ismanifold != ismanifold2)
321       return ReplaceFirst;
322     
323     if(ismanifold) {
324       
325       OrEdge1 = ( (!isRev1 &&  E1.Orientation() == TopAbs_FORWARD) || 
326                                   (isRev1 &&  E1.Orientation() == TopAbs_REVERSED) ? TopAbs_FORWARD :TopAbs_REVERSED);
327       OrEdge2 = ( (!isRev2 &&  E2.Orientation() == TopAbs_FORWARD) ||
328                                   (isRev2 &&  E2.Orientation() == TopAbs_REVERSED) ? TopAbs_FORWARD :TopAbs_REVERSED);
329     }
330     B.UpdateEdge(newedge,CRes,Max(BRep_Tool::Tolerance(E1),BRep_Tool::Tolerance(E2)));
331     Standard_Real fp= CRes->FirstParameter();
332     Standard_Real lp= CRes->LastParameter();
333     if(fp > newf) newf = fp;
334     if(lp < newl) newl = lp;
335     B.Range(newedge,newf,newl);
336     
337     //merging pcurves
338     for(TopTools_ListIteratorOfListOfShape iter(faces); iter.More(); iter.Next()) 
339     {
340       TopoDS_Face face = TopoDS::Face(iter.Value());
341       if(!sae.PCurve ( E1, face, c2d1, first1, last1, Standard_False )) return ReplaceFirst;  
342       if(!sae.PCurve ( E2, face, c2d2, first2, last2, Standard_False )) return ReplaceFirst;
343       
344       Handle(Geom2d_Curve) C2dRes;
345       Standard_Boolean isRev12,isRev22;
346       if(!ShapeConstruct::JoinCurves(c2d1,c2d2,OrEdge1,OrEdge2,first1, last1,first2, last2,C2dRes,isRev12,isRev22,isSame))
347       return  ReplaceFirst;
348       
349       if(ismanifold && (!isSame && (isRev12 || isRev22)))
350         return  ReplaceFirst;
351       
352       if(isRev12)
353         ReplaceFirst = Standard_False;
354       Standard_Real fp2d = C2dRes->FirstParameter();
355       Standard_Real lp2d = C2dRes->LastParameter();
356       //B.UpdateEdge(newedge,C2dRes,face,0);
357       Standard_Real newf1 = first1;
358       Standard_Real newl1 = last1 + (last2 - first2);
359       if(fp2d > newf1) newf1 = fp2d;
360       if(lp2d < newl1) newl1 = lp2d;
361       
362       // dealing with seams: the same again
363       if(sae.IsSeam(E1,face) && sae.IsSeam(E2,face)) 
364       {
365         Handle(Geom2d_Curve) c2d12,c2d22;
366 //smh#8
367         TopoDS_Shape tmpE1 = E1.Reversed(),
368                      tmpE2 = E2.Reversed();
369         TopoDS_Edge E1t = TopoDS::Edge(tmpE1);
370         TopoDS_Edge E2t = TopoDS::Edge(tmpE2);
371         sae.PCurve ( E1t, face, c2d12, first1, last1, Standard_False );  
372         sae.PCurve ( E2t, face, c2d22, first2, last2, Standard_False );
373         
374         Handle(Geom2d_Curve) C2dRes2;
375         if(!ShapeConstruct::JoinCurves(c2d12,c2d22,OrEdge1,OrEdge2,first1, last1,first2, last2,C2dRes2,isRev12,isRev22,isSame))
376           return ReplaceFirst;
377         if(!isSame && (isRev1 || isRev2))
378           return  ReplaceFirst; 
379         B.UpdateEdge(newedge,C2dRes,C2dRes2,face,0);
380       }
381       else if(sae.IsSeam(E1,face) || sae.IsSeam(E2,face)) return ReplaceFirst;
382       else if(!sae.IsSeam(E1,face) && !sae.IsSeam(E2,face))
383         B.UpdateEdge(newedge,C2dRes,face,0);
384       B.Range(newedge,face,newf1,newl1);
385       if(!ismanifold)
386         newedge.Orientation(ReplaceFirst ? OrEdge1 :OrEdge2 );
387     }
388     B.SameRange(newedge,Standard_False);
389     
390     E3 = newedge;
391     return ReplaceFirst;
392   }
393   catch ( Standard_Failure const& anException) {
394 #ifdef OCCT_DEBUG
395     cout<<"Error: ShapeFix_Wireframe::FixSmallEdges: JoinEdges: Exception in GeomConvert_CompCurveToBSplineCurve: ";
396     anException.Print(cout); cout<<endl;
397 #endif
398     (void)anException;
399     return ReplaceFirst;
400   }
401 }
402
403 //=======================================================================
404 //function : FixSmallEdges
405 //purpose  : 
406 //=======================================================================
407
408  Standard_Boolean ShapeFix_Wireframe::FixSmallEdges() 
409 {
410   myStatusSmallEdges = ShapeExtend::EncodeStatus( ShapeExtend_OK );
411   if (myShape.IsNull()) return Standard_False;
412
413   if (Context().IsNull()) SetContext(new ShapeBuild_ReShape);
414   else 
415   {
416     TopoDS_Shape shape = myShape;
417     myShape.Nullify();
418     myShape = Context()->Apply(shape);
419   }
420  TopTools_DataMapOfShapeShape cont;
421   if ( myShape.ShapeType() == TopAbs_COMPOUND ) 
422   {
423     Standard_Boolean locModified = Standard_False;
424     TopoDS_Compound C;
425     BRep_Builder B;
426     B.MakeCompound ( C );
427     TopoDS_Shape savShape = myShape;
428     for ( TopoDS_Iterator it(savShape); it.More(); it.Next() ) 
429     {
430       TopoDS_Shape shape1 = it.Value();
431       TopLoc_Location L = shape1.Location(),nullLoc;
432       shape1.Location ( nullLoc );
433       TopoDS_Shape res;
434       if ( cont.IsBound ( shape1 ) )
435       {
436         res = cont.Find ( shape1 ).Oriented ( shape1.Orientation() );
437       }
438       else 
439       {
440         myShape = shape1;
441         FixSmallEdges();
442         res = Shape();
443         cont.Bind(myShape,res);
444       }
445       if ( ! res.IsSame ( shape1 ) ) locModified = Standard_True;
446
447       //check if resulting shape if not empty
448       if( res.IsNull())
449         continue;
450
451       res.Location ( L );
452       B.Add ( C, res );
453       
454     }
455     if (locModified ) 
456     {
457       C.Orientation(savShape.Orientation());
458       Context()->Replace(savShape,C);
459     }
460     myShape = Context()->Apply(savShape);
461     return StatusSmallEdges( ShapeExtend_DONE );
462   }
463   TopTools_MapOfShape theSmallEdges, theMultyEdges;
464   TopTools_DataMapOfShapeListOfShape theEdgeToFaces,theFaceWithSmall;
465   CheckSmallEdges ( theSmallEdges,theEdgeToFaces,theFaceWithSmall, theMultyEdges);
466   MergeSmallEdges ( theSmallEdges,theEdgeToFaces,theFaceWithSmall, theMultyEdges);
467   return StatusSmallEdges( ShapeExtend_DONE );
468 }
469
470 //=======================================================================
471 //function : CheckSmallEdges
472 //purpose  : 
473 //=======================================================================
474 #include <BRepBuilderAPI_MakeFace.hxx>
475 #include <TopExp.hxx>
476 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
477 Standard_Boolean ShapeFix_Wireframe::CheckSmallEdges(TopTools_MapOfShape& theSmallEdges,
478                                                      TopTools_DataMapOfShapeListOfShape& theEdgeToFaces,
479                                                      TopTools_DataMapOfShapeListOfShape& theFaceWithSmall,
480                                                      TopTools_MapOfShape& theMultyEdges) 
481 {
482   TopoDS_Face face;
483   TopoDS_Edge edge;
484   ShapeAnalysis_Wire SAW;
485   
486   for (TopExp_Explorer anExpf1(myShape,TopAbs_FACE); anExpf1.More(); anExpf1.Next()) 
487   {
488     TopTools_ListOfShape theEdgeList;
489     TopoDS_Face facet = TopoDS::Face(anExpf1.Current());
490     face = facet;
491     if (facet.Orientation()==TopAbs_REVERSED) face = TopoDS::Face(facet.Oriented(TopAbs_FORWARD));
492     for (TopoDS_Iterator itw(face); itw.More(); itw.Next()) 
493     {
494       if(itw.Value().ShapeType() != TopAbs_WIRE)
495         continue;
496       TopoDS_Wire aW = TopoDS::Wire(itw.Value());
497       Handle(ShapeExtend_WireData) aswd = new ShapeExtend_WireData(aW,Standard_True,Standard_False);
498       SAW.Init(aswd,face,Precision());
499       // pnd protection on seam edges
500       TopTools_DataMapOfShapeInteger EdgeMap;
501       Standard_Integer i;
502       for (i=1; i<=SAW.NbEdges(); i++) 
503       {
504         edge = SAW.WireData()->Edge(i);
505         if (EdgeMap.IsBound(edge))
506           EdgeMap.ChangeFind(edge)++;
507         else
508           EdgeMap.Bind(edge,1);
509       }
510             
511       for ( i=1; i<=SAW.NbEdges(); i++) 
512       {
513         edge = SAW.WireData()->Edge(i);
514         if(EdgeMap.Find(edge)!=1) 
515         {
516           if(!SAW.WireData()->IsSeam(i))
517             theMultyEdges.Add(edge);
518           continue;
519         }
520         // Append current face to the list
521         if (theEdgeToFaces.IsBound(edge)) 
522         {
523           theEdgeToFaces(edge).Append(facet);
524         }
525         else 
526         {
527           TopTools_ListOfShape theFaceList;
528           theFaceList.Append(facet);
529           theEdgeToFaces.Bind(edge,theFaceList);
530         }
531         // Check if current edge is small
532         if (theSmallEdges.Contains(edge)) theEdgeList.Append(edge);
533         else if (SAW.CheckSmall(i,Precision())) 
534         {
535           theSmallEdges.Add(edge);
536           theEdgeList.Append(edge);
537         }
538       }
539     }
540     // Add current face to the map if has small edges
541     if (theEdgeList.Extent()) theFaceWithSmall.Bind(facet,theEdgeList);
542   }
543   
544   //========================================================================
545   // Author : enk 
546   // Purpose: Analizing of shape for small edges , if edge don't lie on face
547   //========================================================================
548   for (TopExp_Explorer expw1(myShape,TopAbs_WIRE,TopAbs_FACE); expw1.More(); expw1.Next()) 
549   {
550     SAW.SetPrecision(Precision());
551     TopTools_DataMapOfShapeInteger EdgeMap;
552     Standard_Integer i;
553     TopoDS_Wire theWire=TopoDS::Wire(expw1.Current());
554     TopTools_ListOfShape theEdgeList;
555     SAW.Load(theWire);
556     if (!SAW.IsLoaded()) 
557     {
558       return Standard_False;
559     }
560     for (i=1; i<=SAW.NbEdges(); i++) 
561     {
562       edge = SAW.WireData()->Edge(i);
563       if (EdgeMap.IsBound(edge))
564         EdgeMap.ChangeFind(edge)++;
565       else
566         EdgeMap.Bind(edge,1);
567     }
568     
569     for ( i=1; i<=SAW.NbEdges(); i++) 
570     {
571       edge = SAW.WireData()->Edge(i);
572       if(EdgeMap.Find(edge)!=1) 
573       {
574         if(!SAW.WireData()->IsSeam(i))
575           theMultyEdges.Add(edge);
576         continue;
577       }
578       
579       // Check if current edge is small
580       if (theSmallEdges.Contains(edge)) theEdgeList.Append(edge);
581       else if (SAW.CheckSmall(i,Precision())) 
582       {
583         theSmallEdges.Add(edge);
584         theEdgeList.Append(edge);
585       }
586     }
587     
588   }
589   return (!theSmallEdges.IsEmpty());
590   
591 }
592
593 //=======================================================================
594 //function : MergeSmallEdges
595 //purpose  : 
596 //=======================================================================
597
598 Standard_Boolean ShapeFix_Wireframe::MergeSmallEdges(TopTools_MapOfShape& theSmallEdges,
599                                                      TopTools_DataMapOfShapeListOfShape& theEdgeToFaces,
600                                                      TopTools_DataMapOfShapeListOfShape& theFaceWithSmall,
601                                                      TopTools_MapOfShape& theMultyEdges,
602                                                      const Standard_Boolean theModeDrop,
603                                                      const Standard_Real theLimitAngle) 
604 {
605   Standard_Boolean aModLimitAngle = (theLimitAngle >-1.0 || myLimitAngle > -1.0);
606   Standard_Real aLimitAngle = Max(theLimitAngle,myLimitAngle);
607   
608   Standard_Boolean aModeDrop = theModeDrop || myModeDrop;
609   TopTools_DataMapOfShapeShape theNewVertices;
610   if (!theSmallEdges.IsEmpty()) 
611   {
612     
613     Handle(ShapeFix_Wire) SFW = new ShapeFix_Wire;
614     SFW->SetContext(Context());
615     ShapeAnalysis_Edge SAE;
616     TopoDS_Edge edge1, edge2, edge3;
617     // Iterate on map of faces with small edges
618     TopExp_Explorer anExpf2(myShape,TopAbs_FACE);
619     for (; anExpf2.More(); anExpf2.Next()) 
620     {
621       if (theFaceWithSmall.IsBound(anExpf2.Current())) 
622       {
623         if (theFaceWithSmall(anExpf2.Current()).Extent()) 
624         {
625           //smh#8
626           TopoDS_Shape tmpShape = Context()->Apply(anExpf2.Current());
627           TopoDS_Face facet = TopoDS::Face(tmpShape);
628           if(!facet.IsSame(anExpf2.Current())) 
629           {  //gka
630             TopExp_Explorer aExpEdge(anExpf2.Current(),TopAbs_EDGE);
631             for( ; aExpEdge.More(); aExpEdge.Next()) 
632             {
633               TopoDS_Shape newEdge;
634               Standard_Integer stat = Context()->Status(aExpEdge.Current(),newEdge,Standard_True);
635               if(stat > 0 ) 
636               {
637                 if(theSmallEdges.Contains(aExpEdge.Current())) 
638                 {
639                   theSmallEdges.Remove(aExpEdge.Current());
640                   theSmallEdges.Add(newEdge);
641                 }
642                 if(theEdgeToFaces.IsBound(aExpEdge.Current())) 
643                 {
644                   TopTools_ListOfShape aListFaces;
645                   aListFaces = theEdgeToFaces.Find(aExpEdge.Current());
646                   theEdgeToFaces.UnBind(aExpEdge.Current());
647                   theEdgeToFaces.Bind(newEdge,aListFaces);
648                   
649                 }
650               }
651             }
652           }
653           TopoDS_Face face = facet;
654           //if (face.Orientation()==TopAbs_REVERSED) 
655           //  face = TopoDS::Face(facet.Oriented(TopAbs_FORWARD));
656           for (TopoDS_Iterator itw(face); itw.More(); itw.Next()) 
657           {
658             if(itw.Value().ShapeType() != TopAbs_WIRE) continue;
659             TopoDS_Wire aWire = TopoDS::Wire(itw.Value());
660             if (face.Orientation()==TopAbs_REVERSED) 
661               face = TopoDS::Face(facet.Oriented(TopAbs_FORWARD));
662             Handle(ShapeExtend_WireData) aswd = new ShapeExtend_WireData(aWire,Standard_True,Standard_False);
663             //SFW->Load(aWire);
664             SFW->Load(aswd);
665             SFW->FixReorder();
666             Standard_Integer prev, next, index = 1;
667             
668             while (index <= SFW->WireData()->NbEdges() && SFW->NbEdges()>1) 
669             {
670               prev = (index==1)? SFW->WireData()->NbEdges() : index-1;
671               next = (index==SFW->WireData()->NbEdges())? 1 : index+1;
672               edge1 = SFW->WireData()->Edge(prev);
673               edge2 = SFW->WireData()->Edge(index);
674               edge3 = SFW->WireData()->Edge(next);
675               
676               //gka protection against joining seem edge 
677               if(edge2.IsSame(edge1) || edge2.IsSame(edge3)) 
678               {
679               //if(BRep_Tool::IsClosed(edge2,face)) { 
680                 index++;
681                 continue;
682               }
683                
684               Standard_Boolean isSeam = SFW->WireData()->IsSeam(index);
685               Standard_Boolean isSeam1 = SFW->WireData()->IsSeam(prev);
686               Standard_Boolean isSeam2 = SFW->WireData()->IsSeam(next);
687               if (theSmallEdges.Contains(edge2)) 
688               {
689                 // Middle edge is small - choose a pair of edges to join
690                 Standard_Boolean IsAnyJoin = (edge1.IsSame(edge3));
691                 Standard_Boolean take_next = IsAnyJoin; //Standard_False;
692                 Standard_Boolean isLimAngle = Standard_False;
693                 Handle(Geom_Curve) C1, C2, C3;
694                 Standard_Real aux, last1, first2, last2, first3;
695                 Standard_Real Ang1 = 0., Ang2 =0.;
696                 if (SAE.Curve3d(edge1,C1,aux,last1) &&
697                     SAE.Curve3d(edge2,C2,first2,last2) &&
698                     SAE.Curve3d(edge3,C3,first3,aux)) 
699                 {
700                   // Compare angles between edges
701                   //Standard_Real Ang1, Ang2;
702                   gp_Vec Vec1, Vec2; gp_Pnt P;
703                   C1->D1(last1,P,Vec1);
704                   C2->D1(first2,P,Vec2);
705                   if ( edge1.Orientation() == TopAbs_REVERSED ) Vec1.Reverse();
706                   if ( edge2.Orientation() == TopAbs_REVERSED ) Vec2.Reverse();
707           Standard_Real tol2 = Precision::SquareConfusion();
708                   if ( Vec1.SquareMagnitude() < tol2 ||
709                        Vec2.SquareMagnitude() < tol2 ) Ang1 = M_PI/2.;
710                   else Ang1 = Abs(Vec1.Angle(Vec2));
711                   C2->D1(last2,P,Vec1);
712                   C3->D1(first3,P,Vec2);
713                   if ( edge2.Orientation() == TopAbs_REVERSED ) Vec1.Reverse();
714                   if ( edge3.Orientation() == TopAbs_REVERSED ) Vec2.Reverse();
715                   if ( Vec1.SquareMagnitude() < tol2 ||
716                        Vec2.SquareMagnitude() < tol2 ) Ang2 = M_PI/2.;
717                   else Ang2 = Abs(Vec1.Angle(Vec2));
718                   //isLimAngle = (theLimitAngle != -1 && Min(Ang1,Ang2) > theLimitAngle);  
719                   //take_next = (Ang2<Ang1);
720                   //if (take_next) { edge1 = edge2; edge2 = edge3; }
721                 }
722                 //if(theLimitAngle != -1 && Ang1 > theLimitAngle && Ang2 >theLimitAngle) {
723                 //  index++; continue;
724                 //}
725                 
726                 // Check if edges lay on the same faces
727                 if(theMultyEdges.Contains(edge1) || theMultyEdges.Contains(edge2)) 
728                 { //??????
729                   index++;
730                   continue;
731                 }
732                 TopTools_ListOfShape theList1,theList2,theList3;
733                 if(theEdgeToFaces.IsBound(edge1))
734                   theList1 = theEdgeToFaces(edge1);
735                 if(theEdgeToFaces.IsBound(edge2))
736                   theList2 = theEdgeToFaces(edge2);
737                 if(theEdgeToFaces.IsBound(edge3))
738                   theList3 = theEdgeToFaces(edge3);
739                 Standard_Boolean same_set = Standard_False;
740                 
741                 //gka protection against joining seem edges with other edges
742                 Standard_Boolean same_set1 = (theList1.Extent()==theList2.Extent() && 
743                                               ((!isSeam && !isSeam1)|| (isSeam && isSeam1))); //gka
744                 Standard_Boolean same_set2 = (theList3.Extent()==theList2.Extent() && 
745                                               ((!isSeam && !isSeam2)|| (isSeam && isSeam2)));
746                 TopTools_MapOfShape theSetOfFaces;
747                 for (TopTools_ListIteratorOfListOfShape itf1(theList2);
748                      itf1.More(); itf1.Next())
749                   theSetOfFaces.Add(itf1.Value());
750                 if (same_set1) 
751                 {
752                   // Add all faces of the first edge to the current set
753                   for (TopTools_ListIteratorOfListOfShape itf2(theList1);
754                        (itf2.More() && same_set1); itf2.Next())
755                     same_set1 = theSetOfFaces.Contains(itf2.Value());
756                 }
757                 if (same_set2) 
758                 {
759                   // Add all faces of the first edge to the current set
760                   for (TopTools_ListIteratorOfListOfShape itf2(theList3);
761                        (itf2.More() && same_set2); itf2.Next())
762                     same_set2 = theSetOfFaces.Contains(itf2.Value());
763                 }
764                 if(same_set1 && same_set2) 
765                 {
766                   same_set = Standard_True;
767                   if(fabs(Ang2-Ang1) >Precision::Angular())
768                     take_next = (Ang2<Ang1);
769                   if (take_next) 
770                   { 
771                     edge1 = edge2; edge2 = edge3;
772                   }
773                   isLimAngle = (aModLimitAngle && Min(Ang1,Ang2) > aLimitAngle);
774                 }
775                 else if(same_set1 && !same_set2) 
776                 {
777                   isLimAngle = (aModLimitAngle && Ang1 > aLimitAngle);
778                   same_set = Standard_True;
779                 }
780                 else if(!same_set1 && same_set2) 
781                 {
782                   same_set = Standard_True;
783                   isLimAngle = (aModLimitAngle && Ang2 > aLimitAngle);
784                   edge1 = edge2; edge2 = edge3;
785                   take_next = Standard_True;
786                 }
787                 if (same_set && !isLimAngle ) 
788                 {
789                   // Merge current pair of edges
790                    //gka protection against crossing seem on second face
791                   Standard_Boolean isNeedJoin = Standard_True;//Standard_False;
792                   for(TopTools_ListIteratorOfListOfShape aItF(theList2); aItF.More() && isNeedJoin; aItF.Next()) 
793                   { 
794                     if(aItF.Value().IsSame(anExpf2.Current())) continue;
795                     TopoDS_Shape aF = Context()->Apply(aItF.Value());
796                     //aF = aF.Oriented(TopAbs_FORWARD);
797                     for(TopoDS_Iterator aIw(aF); aIw.More(); aIw.Next()) 
798                     {
799                       if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
800                       TopoDS_Wire wt = TopoDS::Wire(aIw.Value());
801                       Handle(ShapeFix_Wire) SFW1 = new ShapeFix_Wire;
802                       SFW1->Load(wt);
803                       SFW1->FixReorder();
804                       Handle(ShapeExtend_WireData) atmpswd = SFW1->WireData();
805                       Standard_Integer ind1 = atmpswd->Index(edge1);
806                       Standard_Integer ind2 = atmpswd->Index(edge2);
807                       if(ind1 && ind2) 
808                       {
809                         isNeedJoin = ((ind1 -ind2) ==1 || (ind2 == atmpswd->NbEdges() && ind1 ==1));
810                         break;
811                       }
812                     }
813                   }
814                   Standard_Boolean ReplaceFirst = Standard_True;
815                   if(isNeedJoin) 
816                   {
817                     
818                     TopTools_ListOfShape aListF;
819                     for(TopTools_ListIteratorOfListOfShape aItlF(theList2); aItlF.More(); aItlF.Next()) 
820                     {
821                       TopoDS_Shape tmpF = Context()->Apply(aItlF.Value());
822                       aListF.Append(tmpF);
823                     }
824                     ReplaceFirst = JoinEdges(edge1,edge2,edge3,aListF);
825                   }
826                   else edge3 = TopoDS_Edge();
827                   if (edge3.IsNull()) 
828                   {
829                     index++;
830                     myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
831                   }
832                   else 
833                   {
834                     // Record vertex replacements in the map
835                     TopoDS_Vertex oldV1 = SAE.FirstVertex(edge3),
836                                   oldV2 = SAE.LastVertex(edge3);
837                     if (!theNewVertices.IsBound(oldV1))
838 //smh#8
839                     {
840                       TopoDS_Shape emptyCopiedV1 = oldV1.EmptyCopied();
841                       theNewVertices.Bind(oldV1,TopoDS::Vertex(emptyCopiedV1));
842                     }
843                     if (!oldV1.IsSame(oldV2))
844                       if (!theNewVertices.IsBound(oldV2))
845 //smh#8
846                       {
847                         TopoDS_Shape emptyCopiedV2 = oldV2.EmptyCopied();
848                         theNewVertices.Bind(oldV2,TopoDS::Vertex(emptyCopiedV2));
849                       }
850                     
851                     //To keep NM vertices belonging initial edges
852                     TopoDS_Iterator aItv(edge1,Standard_False);
853                     for( ; aItv.More(); aItv.Next()) {
854                       if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
855                          aItv.Value().Orientation() == TopAbs_EXTERNAL) {
856                         TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
857                         TopoDS_Vertex anewV =  ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge1);
858                         BRep_Builder aB;
859                         aB.Add(edge3,anewV);
860                         Context()->Replace(aOldV,anewV);
861                       }
862                     }
863                       
864                     for(aItv.Initialize(edge2,Standard_False) ; aItv.More(); aItv.Next()) {
865                       if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
866                          aItv.Value().Orientation() == TopAbs_EXTERNAL){
867                         BRep_Builder aB;
868                         TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
869                         TopoDS_Vertex anewV =  ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge2);
870                         aB.Add(edge3,anewV);
871                         Context()->Replace(aOldV,anewV);
872                       }
873                     }
874                   
875                     // Check for small resulting edge
876                     Standard_Boolean newsmall = Standard_False;
877                     ShapeAnalysis_Wire SAW;
878                     SAW.Init(SFW->WireData(),face,Precision());
879                     // Make changes in WireData and Context
880                     if(ReplaceFirst) 
881                     {
882                       Context()->Replace(edge1,edge3);
883                       Context()->Remove(edge2);
884                       SendWarning( edge2, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
885                     }
886                     else 
887                     {
888                       Context()->Replace(edge2,edge3);
889                       Context()->Remove(edge1);
890                       SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
891                     }
892                     if (take_next) 
893                     {
894                       SFW->WireData()->Set(edge3,next);
895                       newsmall = SAW.CheckSmall(next,Precision());
896                     }
897                     else 
898                     {
899                       SFW->WireData()->Set(edge3,prev);
900                       newsmall = SAW.CheckSmall(prev,Precision());
901                     }
902                     SFW->WireData()->Remove(index);
903                     // Process changes in maps
904                     TopTools_ListOfShape theList;
905                     theList.Append(theList2);
906                     theEdgeToFaces.UnBind(edge1);
907                     theEdgeToFaces.UnBind(edge2);
908                     theEdgeToFaces.Bind(edge3,theList);
909                     if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
910                     if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
911                     if (newsmall) theSmallEdges.Add(edge3);
912                     for (TopTools_ListIteratorOfListOfShape itlf(theList);
913                          itlf.More(); itlf.Next()) 
914                     {
915                       TopoDS_Shape curface = itlf.Value();
916                       if (theFaceWithSmall.IsBound(curface)) 
917                       {
918                         TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
919                         if (newsmall) theEdges.Append(edge3);
920                         TopTools_ListIteratorOfListOfShape ite(theEdges);
921                         while (ite.More()) 
922                         {
923                           TopoDS_Shape iedge = ite.Value();
924                           if (iedge.IsSame(edge1) || iedge.IsSame(edge2))
925                             theEdges.Remove(ite);
926                           else ite.Next();
927                         }
928                         // Remove face without small edges from the map
929                         if (!theEdges.Extent()) theFaceWithSmall.UnBind(curface);
930                       }
931                     }
932                     myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
933                   }
934                 }
935                 else if(aModeDrop) 
936                 { //gka
937                   Handle(ShapeExtend_WireData) tempWire = new ShapeExtend_WireData();
938                   ShapeAnalysis_Wire tempSaw;
939                   tempWire->Add(SFW->Wire());
940                   TopoDS_Edge remedge;
941                   if (take_next) 
942                     remedge = edge1;
943                   else  remedge = edge2;
944                   tempWire->Remove (index );
945                   tempSaw.Load(tempWire);
946                   Standard_Integer newindex = (index <= tempSaw.NbEdges() ? index : 1);
947                   tempSaw.CheckConnected(newindex,Precision());
948                   if(!tempSaw.LastCheckStatus(ShapeExtend_FAIL)) 
949                   {
950                     SFW->WireData()->Remove (index );
951                     TopoDS_Edge tmpedge1 = tempWire->Edge(newindex);
952                     TopoDS_Edge tmpedge2 = tempWire->Edge(newindex == 1 ? tempSaw.NbEdges() : (newindex- 1));
953                     TopTools_ListOfShape aL1;
954                     if(theEdgeToFaces.IsBound(tmpedge1))
955                        aL1 = theEdgeToFaces.Find(tmpedge1);
956                     TopTools_ListOfShape aL2;
957                     if(theEdgeToFaces.IsBound(tmpedge2))  
958                       aL2= theEdgeToFaces.Find(tmpedge2);                                             
959                     SFW->FixConnected(newindex <= SFW->NbEdges() ? newindex : 1,Precision());
960                     SFW->FixDegenerated(newindex <= SFW->NbEdges() ? newindex : 1);
961                     TopoDS_Shape aTmpShape = Context()->Apply(tmpedge1); //for porting
962                     TopoDS_Edge anewedge1 = TopoDS::Edge(aTmpShape);
963                     aTmpShape = Context()->Apply(tmpedge2);
964                     TopoDS_Edge anewedge2 = TopoDS::Edge(aTmpShape); 
965                     Context()->Remove(remedge);
966                     SendWarning( remedge, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
967                     if (theSmallEdges.Contains(remedge)) 
968                       theSmallEdges.Remove(remedge);
969                     theEdgeToFaces.UnBind(remedge);
970                     theEdgeToFaces.UnBind(tmpedge1);
971                     theEdgeToFaces.UnBind(tmpedge2);
972                     theEdgeToFaces.Bind(anewedge1,aL1);
973                     theEdgeToFaces.Bind(anewedge2,aL2);
974                     if (theSmallEdges.Contains(tmpedge1)) 
975                     {
976                       theSmallEdges.Remove(tmpedge1);
977                       theSmallEdges.Add(anewedge1);
978                       for (TopTools_ListIteratorOfListOfShape itlf(aL1);
979                          itlf.More(); itlf.Next()) 
980                       {
981                         TopoDS_Shape curface = itlf.Value();
982                         TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
983                         TopTools_ListIteratorOfListOfShape ite(theEdges);
984                         while (ite.More()) 
985                         {
986                           TopoDS_Shape iedge = ite.Value();
987                           if (iedge.IsSame(tmpedge1)) 
988                           {
989                             theEdges.Remove(ite);
990                             theEdges.Append(anewedge1);
991                           }
992                           else ite.Next();
993                         }
994                       }
995                     }
996                     if (theSmallEdges.Contains(tmpedge2)) 
997                     {
998                       theSmallEdges.Remove(tmpedge2);
999                       theSmallEdges.Add(anewedge2);
1000                       for (TopTools_ListIteratorOfListOfShape itlf(aL2);
1001                          itlf.More(); itlf.Next()) 
1002                       {
1003                         TopoDS_Shape curface = itlf.Value();
1004                         TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
1005                         TopTools_ListIteratorOfListOfShape ite(theEdges);
1006                         while (ite.More()) 
1007                         {
1008                           TopoDS_Shape iedge = ite.Value();
1009                           if (iedge.IsSame(tmpedge2)) 
1010                           {
1011                             theEdges.Remove(ite);
1012                             theEdges.Append(anewedge2);
1013                           }
1014                           else ite.Next();
1015                         }
1016                       }
1017                     }
1018                     myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE3 );
1019                   }
1020                   else index++;
1021                 }
1022                 else 
1023                 {
1024                   //gka protection aginst removing circles
1025                   TopoDS_Edge ed = (take_next ? edge1 : edge2);
1026                   ShapeAnalysis_Edge sae;
1027                   Handle(Geom_Curve) c3d;
1028                   Standard_Real f1,l1;
1029                   if(sae.Curve3d(ed,c3d,f1,l1,Standard_False)) 
1030                   {
1031                     gp_Pnt p1,p2,p3;
1032                     c3d->D0(f1,p1);
1033                     c3d->D0(l1,p2);
1034                     c3d->D0((f1 +l1)*0.5,p3);
1035                     
1036                     if(p1.Distance(p3) > p1.Distance(p2)) 
1037                     {
1038                       index++;
1039                       continue;
1040                     }
1041                   }
1042                   if (take_next && theList2.Extent()== 1)  
1043                   { //gka
1044                       TopoDS_Vertex V1 = SAE.FirstVertex(edge1),
1045                                  V2 = SAE.LastVertex(edge1);
1046                       if(V1.IsSame(V2)) 
1047                       {
1048                         SFW->WireData()->Remove (index );
1049                         Context()->Remove(edge1);
1050                         SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1051                         if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
1052                         theEdgeToFaces.UnBind(edge1);
1053                         myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1054                       }
1055                       else index++;
1056                     }
1057                     else if( !take_next && theList2.Extent()== 1) 
1058                     {
1059                       TopoDS_Vertex V1 = SAE.FirstVertex(edge2),
1060                       V2 = SAE.LastVertex(edge2);
1061                       if(V1.IsSame(V2)) 
1062                       {
1063                         SFW->WireData()->Remove (index );
1064                         Context()->Remove(edge2);
1065                         SendWarning( edge2, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1066                         if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
1067                         theEdgeToFaces.UnBind(edge2);
1068                         myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1069                       }
1070                       else index++;
1071                     }
1072                     else index++; 
1073                 }
1074               }
1075               else index++;
1076             }
1077             if (SFW->NbEdges() == 1 && aModeDrop) 
1078             {
1079               edge1 = SFW->WireData()->Edge(1);
1080               if (theSmallEdges.Contains(edge1)) 
1081               {
1082                 SFW->WireData()->Remove(1);
1083                 Context()->Remove(edge1);
1084                 SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1085                 theSmallEdges.Remove(edge1);
1086                 theEdgeToFaces.UnBind(edge1);
1087                 Context()->Remove(aWire);
1088                 SendWarning( aWire, Message_Msg("FixWireframe.FixSmallEdges.MSG1"));
1089                 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1090               }
1091             }
1092             else 
1093             {
1094               SFW->FixConnected();
1095               Context()->Replace(aWire,SFW->Wire());    
1096             }
1097           }
1098           face.Orientation(facet.Orientation());
1099           TopoDS_Shape anewShape = Context()->Apply(face);
1100           TopoDS_Iterator aIter(anewShape);
1101           if(!aIter.More()) {
1102             Context()->Remove(anewShape);
1103             SendWarning( face, Message_Msg("FixWireframe.FixSmallEdges.MSG2"));
1104           }
1105         }
1106       }
1107     }
1108
1109 // enk block
1110 // Iterate on map of wires which not lie on faces 
1111     for (TopExp_Explorer expw1( myShape, TopAbs_WIRE, TopAbs_FACE); expw1.More(); expw1.Next()) 
1112     {
1113             TopoDS_Wire aWire = TopoDS::Wire(expw1.Current());
1114             SFW->Load(aWire);
1115             SFW->FixReorder();
1116             Standard_Integer prev, next, index = 1;
1117             while (index <= SFW->NbEdges() && SFW->NbEdges()>1) 
1118             {
1119               prev = (index==1)? SFW->NbEdges() : index-1;
1120               next = (index==SFW->NbEdges())? 1 : index+1;
1121               edge1 = SFW->WireData()->Edge(prev);
1122               edge2 = SFW->WireData()->Edge(index);
1123               edge3 = SFW->WireData()->Edge(next);
1124               
1125               //gka protection against joining seem edge 
1126               if(edge2.IsSame(edge1) || edge2.IsSame(edge3)) 
1127               {
1128               //if(BRep_Tool::IsClosed(edge2,face)) { 
1129                 index++;
1130                 continue;
1131               }
1132                
1133               Standard_Boolean isSeam = SFW->WireData()->IsSeam(index);
1134               Standard_Boolean isSeam1 = SFW->WireData()->IsSeam(prev);
1135               Standard_Boolean isSeam2 = SFW->WireData()->IsSeam(next);
1136               if (theSmallEdges.Contains(edge2)) 
1137               {
1138                 // Middle edge is small - choose a pair of edges to join
1139                 Standard_Boolean IsAnyJoin = (edge1.IsSame(edge3));
1140                 Standard_Boolean take_next = IsAnyJoin; //Standard_False;
1141                 Standard_Boolean isLimAngle = Standard_False;
1142                 Handle(Geom_Curve) C1, C2, C3;
1143                 Standard_Real aux, last1, first2, last2, first3;
1144                 Standard_Real Ang1 = 0., Ang2 =0.;
1145                 if (SAE.Curve3d(edge1,C1,aux,last1) &&
1146                     SAE.Curve3d(edge2,C2,first2,last2) &&
1147                     SAE.Curve3d(edge3,C3,first3,aux)) 
1148                 {
1149                   // Compare angles between edges
1150                   //Standard_Real Ang1, Ang2;
1151                   gp_Vec Vec1, Vec2; gp_Pnt P;
1152                   C1->D1(last1,P,Vec1);
1153                   C2->D1(first2,P,Vec2);
1154                   if ( edge1.Orientation() == TopAbs_REVERSED ) Vec1.Reverse();
1155                   if ( edge2.Orientation() == TopAbs_REVERSED ) Vec2.Reverse();
1156           Standard_Real tol2 = Precision::SquareConfusion();
1157                   if ( Vec1.SquareMagnitude() < tol2 ||
1158                        Vec2.SquareMagnitude() < tol2 ) Ang1 = M_PI/2.;
1159                   else Ang1 = Abs(Vec1.Angle(Vec2));
1160                   C2->D1(last2,P,Vec1);
1161                   C3->D1(first3,P,Vec2);
1162                   if ( edge2.Orientation() == TopAbs_REVERSED ) Vec1.Reverse();
1163                   if ( edge3.Orientation() == TopAbs_REVERSED ) Vec2.Reverse();
1164                   if ( Vec1.SquareMagnitude() < tol2 ||
1165                        Vec2.SquareMagnitude() < tol2 ) Ang2 = M_PI/2.;
1166                   else Ang2 = Abs(Vec1.Angle(Vec2));
1167                   //isLimAngle = (theLimitAngle != -1 && Min(Ang1,Ang2) > theLimitAngle);  
1168                   //take_next = (Ang2<Ang1);
1169                   //if (take_next) { edge1 = edge2; edge2 = edge3; }
1170                 }
1171                 //if(theLimitAngle != -1 && Ang1 > theLimitAngle && Ang2 >theLimitAngle) {
1172                 //  index++; continue;
1173                 //}
1174                 
1175                 // Check if edges lay on the same faces
1176                 if(theMultyEdges.Contains(edge1) || theMultyEdges.Contains(edge2)) 
1177                 { //??????
1178                   index++;
1179                   continue;
1180                 }
1181                 TopTools_ListOfShape theList1,theList2,theList3;
1182                 if(theEdgeToFaces.IsBound(edge1))
1183                   theList1 = theEdgeToFaces(edge1);
1184                 if(theEdgeToFaces.IsBound(edge2))
1185                   theList2 = theEdgeToFaces(edge2);
1186                 if(theEdgeToFaces.IsBound(edge3))
1187                   theList3 = theEdgeToFaces(edge3);
1188                 Standard_Boolean same_set = Standard_False;
1189                 
1190                 //gka protection against joining seem edges with other edges
1191                 Standard_Boolean same_set1 = (theList1.Extent()==theList2.Extent() && 
1192                                               ((!isSeam && !isSeam1)|| (isSeam && isSeam1))); //gka
1193                 Standard_Boolean same_set2 = (theList3.Extent()==theList2.Extent() && 
1194                                               ((!isSeam && !isSeam2)|| (isSeam && isSeam2)));
1195                 TopTools_MapOfShape theSetOfFaces;
1196                 for (TopTools_ListIteratorOfListOfShape itf1(theList2);
1197                      itf1.More(); itf1.Next())
1198                   theSetOfFaces.Add(itf1.Value());
1199                 if (same_set1) 
1200                 {
1201                   // Add all faces of the first edge to the current set
1202                   for (TopTools_ListIteratorOfListOfShape itf2(theList1);
1203                        (itf2.More() && same_set1); itf2.Next())
1204                     same_set1 = theSetOfFaces.Contains(itf2.Value());
1205                 }
1206                 if (same_set2) 
1207                 {
1208                   // Add all faces of the first edge to the current set
1209                   for (TopTools_ListIteratorOfListOfShape itf2(theList3);
1210                        (itf2.More() && same_set2); itf2.Next())
1211                     same_set2 = theSetOfFaces.Contains(itf2.Value());
1212                 }
1213                 if(same_set1 && same_set2) 
1214                 {
1215                   same_set = Standard_True;
1216                   if(fabs(Ang2-Ang1) >Precision::Angular())
1217                     take_next = (Ang2<Ang1);
1218                   if (take_next) 
1219                   { 
1220                     edge1 = edge2; edge2 = edge3;
1221                   }
1222                   isLimAngle = (aModLimitAngle && Min(Ang1,Ang2) > aLimitAngle);
1223                 }
1224                 else if(same_set1 && !same_set2) 
1225                 {
1226                   isLimAngle = (aModLimitAngle && Ang1 > aLimitAngle);
1227                   same_set = Standard_True;
1228                 }
1229                 else if(!same_set1 && same_set2) 
1230                 {
1231                   same_set = Standard_True;
1232                   isLimAngle = (aModLimitAngle && Ang2 > aLimitAngle);
1233                   edge1 = edge2; edge2 = edge3;
1234                   take_next = Standard_True;
1235                 }
1236                 if (same_set && !isLimAngle ) 
1237                 {
1238                   // Merge current pair of edges
1239                    //gka protection against crossing seem on second face
1240                   Standard_Boolean isNeedJoin = Standard_True;//Standard_False;
1241                   for(TopTools_ListIteratorOfListOfShape aItF(theList2); aItF.More() && isNeedJoin; aItF.Next()) 
1242                   { 
1243                     if(aItF.Value().IsSame(anExpf2.Current())) continue;
1244                     TopoDS_Shape aF = Context()->Apply(aItF.Value());
1245                     //aF = aF.Oriented(TopAbs_FORWARD);
1246                     for(TopoDS_Iterator aIw(aF); aIw.More(); aIw.Next()) 
1247                     {
1248                       if(aIw.Value().ShapeType() != TopAbs_WIRE) continue;
1249                       TopoDS_Wire wt = TopoDS::Wire(aIw.Value());
1250                       Handle(ShapeFix_Wire) SFW1 = new ShapeFix_Wire;
1251                       SFW1->Load(wt);
1252                       SFW1->FixReorder();
1253                       Handle(ShapeExtend_WireData) atmpswd = SFW1->WireData();
1254                       Standard_Integer ind1 = atmpswd->Index(edge1);
1255                       Standard_Integer ind2 = atmpswd->Index(edge2);
1256                       if(ind1 && ind2) 
1257                       {
1258                         isNeedJoin = ((ind1 -ind2) ==1 || (ind2 == atmpswd->NbEdges() && ind1 ==1));
1259                         break;
1260                       }
1261                     }
1262                   }
1263                   Standard_Boolean ReplaceFirst = Standard_True;
1264                   if(isNeedJoin) 
1265                   {
1266                     
1267                     TopTools_ListOfShape aListF;
1268                     for(TopTools_ListIteratorOfListOfShape aItlF(theList2); aItlF.More(); aItlF.Next()) 
1269                     {
1270                       TopoDS_Shape tmpF = Context()->Apply(aItlF.Value());
1271                       aListF.Append(tmpF);
1272                     }
1273                     ReplaceFirst = JoinEdges(edge1,edge2,edge3,aListF);
1274                   }
1275                   else edge3 = TopoDS_Edge();
1276                   if (edge3.IsNull()) 
1277                   {
1278                     index++;
1279                     myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_FAIL1 );
1280                   }
1281                   else 
1282                   {
1283                     // Record vertex replacements in the map
1284                     TopoDS_Vertex oldV1 = SAE.FirstVertex(edge3),
1285                                   oldV2 = SAE.LastVertex(edge3);
1286                     if (!theNewVertices.IsBound(oldV1))
1287 //smh#8
1288                     {
1289                       TopoDS_Shape emptyCopiedV1 = oldV1.EmptyCopied();
1290                       theNewVertices.Bind(oldV1,TopoDS::Vertex(emptyCopiedV1));
1291                     }
1292                     if (!oldV1.IsSame(oldV2))
1293                       if (!theNewVertices.IsBound(oldV2))
1294 //smh#8
1295                       {
1296                         TopoDS_Shape emptyCopiedV2 = oldV2.EmptyCopied();
1297                         theNewVertices.Bind(oldV2,TopoDS::Vertex(emptyCopiedV2));
1298                       }
1299                     //To keep NM vertices belonging initial edges
1300                     TopoDS_Iterator aItv(edge1,Standard_False);
1301                     for( ; aItv.More(); aItv.Next()) {
1302                       if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
1303                          aItv.Value().Orientation() == TopAbs_EXTERNAL) {
1304                         BRep_Builder aB;
1305                         TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
1306                         TopoDS_Vertex anewV =  ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge1);
1307                         aB.Add(edge3,anewV);
1308                         Context()->Replace(aOldV,anewV);
1309                       }
1310                     }
1311                       
1312                     for(aItv.Initialize(edge2,Standard_False) ; aItv.More(); aItv.Next()) {
1313                       if(aItv.Value().Orientation() == TopAbs_INTERNAL ||
1314                          aItv.Value().Orientation() == TopAbs_EXTERNAL){
1315                         BRep_Builder aB;
1316                         TopoDS_Vertex aOldV = TopoDS::Vertex(aItv.Value());
1317                         TopoDS_Vertex anewV =  ShapeAnalysis_TransferParametersProj::CopyNMVertex(aOldV,edge3,edge2);
1318                         aB.Add(edge3,anewV);
1319                         Context()->Replace(aOldV,anewV);
1320                       }
1321                     }
1322                     // Check for small resulting edge
1323                     Standard_Boolean newsmall = Standard_False;
1324                     ShapeAnalysis_Wire SAW;
1325                     SAW.Load(SFW->WireData());
1326                     SAW.SetPrecision(Precision());
1327                     // Make changes in WireData and Context
1328                     if(ReplaceFirst) 
1329                     {
1330                       Context()->Replace(edge1,edge3);
1331                       Context()->Remove(edge2);
1332                       SendWarning( edge2, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1333                     }
1334                     else 
1335                     {
1336                       Context()->Replace(edge2,edge3);
1337                       Context()->Remove(edge1);
1338                       SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1339                     }
1340                     if (take_next) 
1341                     {
1342                       SFW->WireData()->Set(edge3,next);
1343                       newsmall = SAW.CheckSmall(next,Precision());
1344                     }
1345                     else 
1346                     {
1347                       SFW->WireData()->Set(edge3,prev);
1348                       newsmall = SAW.CheckSmall(prev,Precision());
1349                     }
1350                     SFW->WireData()->Remove(index);
1351                     // Process changes in maps
1352                     TopTools_ListOfShape theList;
1353                     theList.Append(theList2);
1354                     theEdgeToFaces.UnBind(edge1);
1355                     theEdgeToFaces.UnBind(edge2);
1356                     theEdgeToFaces.Bind(edge3,theList);
1357                     if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
1358                     if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
1359                     if (newsmall) theSmallEdges.Add(edge3);
1360                     for (TopTools_ListIteratorOfListOfShape itlf(theList);
1361                          itlf.More(); itlf.Next()) 
1362                     {
1363                       TopoDS_Shape curface = itlf.Value();
1364                       if (theFaceWithSmall.IsBound(curface)) 
1365                       {
1366                         TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
1367                         if (newsmall) theEdges.Append(edge3);
1368                         TopTools_ListIteratorOfListOfShape ite(theEdges);
1369                         while (ite.More()) 
1370                         {
1371                           TopoDS_Shape iedge = ite.Value();
1372                           if (iedge.IsSame(edge1) || iedge.IsSame(edge2))
1373                             theEdges.Remove(ite);
1374                           else ite.Next();
1375                         }
1376                         // Remove face without small edges from the map
1377                         if (!theEdges.Extent()) theFaceWithSmall.UnBind(curface);
1378                       }
1379                     }
1380                     myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE1 );
1381                   }
1382                 }
1383                 else if(aModeDrop) 
1384                 { //gka
1385                   Handle(ShapeExtend_WireData) tempWire = new ShapeExtend_WireData();
1386                   ShapeAnalysis_Wire tempSaw;
1387                   tempWire->Add(SFW->Wire());
1388                   TopoDS_Edge remedge;
1389                   if (take_next) 
1390                     remedge = edge1;
1391                   else  remedge = edge2;
1392                   tempWire->Remove (index );
1393                   tempSaw.Load(tempWire);
1394                   Standard_Integer newindex = (index <= tempSaw.NbEdges() ? index : 1);
1395                   tempSaw.CheckConnected(newindex,Precision());
1396                   if(!tempSaw.LastCheckStatus(ShapeExtend_FAIL)) 
1397                   {
1398                     SFW->WireData()->Remove (index );
1399                     TopoDS_Edge tmpedge1 = tempWire->Edge(newindex);
1400                     TopoDS_Edge tmpedge2 = tempWire->Edge(newindex == 1 ? tempSaw.NbEdges() : (newindex- 1));
1401                     TopTools_ListOfShape aL1;
1402                     if(theEdgeToFaces.IsBound(tmpedge1))
1403                        aL1 = theEdgeToFaces.Find(tmpedge1);
1404                     TopTools_ListOfShape aL2;
1405                     if(theEdgeToFaces.IsBound(tmpedge2))  
1406                       aL2= theEdgeToFaces.Find(tmpedge2);                                             
1407                     SFW->FixConnected(newindex <= SFW->NbEdges() ? newindex : 1,Precision());
1408                     SFW->FixDegenerated(newindex <= SFW->NbEdges() ? newindex : 1);
1409                     TopoDS_Shape aTmpShape = Context()->Apply(tmpedge1); //for porting
1410                     TopoDS_Edge anewedge1 = TopoDS::Edge(aTmpShape);
1411                     aTmpShape = Context()->Apply(tmpedge2);
1412                     TopoDS_Edge anewedge2 = TopoDS::Edge(aTmpShape); 
1413                     Context()->Remove(remedge);
1414                     SendWarning( remedge, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1415                     if (theSmallEdges.Contains(remedge)) 
1416                       theSmallEdges.Remove(remedge);
1417                     theEdgeToFaces.UnBind(remedge);
1418                     theEdgeToFaces.UnBind(tmpedge1);
1419                     theEdgeToFaces.UnBind(tmpedge2);
1420                     theEdgeToFaces.Bind(anewedge1,aL1);
1421                     theEdgeToFaces.Bind(anewedge2,aL2);
1422                     if (theSmallEdges.Contains(tmpedge1)) 
1423                     {
1424                       theSmallEdges.Remove(tmpedge1);
1425                       theSmallEdges.Add(anewedge1);
1426                       for (TopTools_ListIteratorOfListOfShape itlf(aL1);
1427                          itlf.More(); itlf.Next()) 
1428                       {
1429                         TopoDS_Shape curface = itlf.Value();
1430                         TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
1431                         TopTools_ListIteratorOfListOfShape ite(theEdges);
1432                         while (ite.More()) 
1433                         {
1434                           TopoDS_Shape iedge = ite.Value();
1435                           if (iedge.IsSame(tmpedge1)) 
1436                           {
1437                             theEdges.Remove(ite);
1438                             theEdges.Append(anewedge1);
1439                           }
1440                           else ite.Next();
1441                         }
1442                       }
1443                     }
1444                     if (theSmallEdges.Contains(tmpedge2)) 
1445                     {
1446                       theSmallEdges.Remove(tmpedge2);
1447                       theSmallEdges.Add(anewedge2);
1448                       for (TopTools_ListIteratorOfListOfShape itlf(aL2);
1449                          itlf.More(); itlf.Next()) 
1450                       {
1451                         TopoDS_Shape curface = itlf.Value();
1452                         TopTools_ListOfShape& theEdges = theFaceWithSmall(curface);
1453                         TopTools_ListIteratorOfListOfShape ite(theEdges);
1454                         while (ite.More()) 
1455                         {
1456                           TopoDS_Shape iedge = ite.Value();
1457                           if (iedge.IsSame(tmpedge2)) 
1458                           {
1459                             theEdges.Remove(ite);
1460                             theEdges.Append(anewedge2);
1461                           }
1462                           else ite.Next();
1463                         }
1464                       }
1465                     }
1466                     myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE3 );
1467                   }
1468                   else index++;
1469                 }
1470                 else 
1471                 {
1472                   //gka protection aginst removing circles
1473                   TopoDS_Edge ed = (take_next ? edge1 : edge2);
1474                   ShapeAnalysis_Edge sae;
1475                   Handle(Geom_Curve) c3d;
1476                   Standard_Real f1,l1;
1477                   if(sae.Curve3d(ed,c3d,f1,l1,Standard_False)) 
1478                   {
1479                     gp_Pnt p1,p2,p3;
1480                     c3d->D0(f1,p1);
1481                     c3d->D0(l1,p2);
1482                     c3d->D0((f1 +l1)*0.5,p3);
1483                     
1484                     if(p1.Distance(p3) > p1.Distance(p2)) 
1485                     {
1486                       index++;
1487                       continue;
1488                     }
1489                   }
1490                   if (take_next && theList2.Extent()== 1)  
1491                   { //gka
1492                       TopoDS_Vertex V1 = SAE.FirstVertex(edge1),
1493                                  V2 = SAE.LastVertex(edge1);
1494                       if(V1.IsSame(V2)) 
1495                       {
1496                         SFW->WireData()->Remove (index );
1497                         Context()->Remove(edge1);
1498                         SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1499                         if (theSmallEdges.Contains(edge1)) theSmallEdges.Remove(edge1);
1500                         theEdgeToFaces.UnBind(edge1);
1501                         myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1502                       }
1503                       else index++;
1504                     }
1505                     else if( !take_next && theList2.Extent()== 1) 
1506                     {
1507                       TopoDS_Vertex V1 = SAE.FirstVertex(edge2),
1508                       V2 = SAE.LastVertex(edge2);
1509                       if(V1.IsSame(V2)) 
1510                       {
1511                         SFW->WireData()->Remove (index );
1512                         Context()->Remove(edge2);
1513                         SendWarning( edge2, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1514                         if (theSmallEdges.Contains(edge2)) theSmallEdges.Remove(edge2);
1515                         theEdgeToFaces.UnBind(edge2);
1516                         myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1517                       }
1518                       else index++;
1519                     }
1520                     else index++; 
1521                 }
1522               }
1523               else index++;
1524             }
1525             if (SFW->NbEdges() == 1 && aModeDrop) 
1526             {
1527               edge1 = SFW->WireData()->Edge(1);
1528               if (theSmallEdges.Contains(edge1)) 
1529               {
1530                 SFW->WireData()->Remove(1);
1531                 Context()->Remove(edge1);
1532                 SendWarning( edge1, Message_Msg("FixWireframe.FixSmallEdges.MSG0"));
1533                 theSmallEdges.Remove(edge1);
1534                 theEdgeToFaces.UnBind(edge1);
1535                 Context()->Remove(aWire);
1536                 SendWarning( aWire, Message_Msg("FixWireframe.FixSmallEdges.MSG1"));
1537                 myStatusSmallEdges |= ShapeExtend::EncodeStatus( ShapeExtend_DONE2 );
1538               }
1539             }
1540             else 
1541             {
1542               SFW->FixConnected();
1543               Context()->Replace(aWire,SFW->Wire());    
1544             }
1545           }
1546 // end enk block      
1547     // Record vertex replacements in context
1548     for (TopTools_DataMapIteratorOfDataMapOfShapeShape itv(theNewVertices);
1549          itv.More(); itv.Next())  Context()->Replace(itv.Key(),itv.Value());
1550   
1551     TopoDS_Shape shape = myShape;
1552     myShape.Nullify();
1553     myShape = Context()->Apply(shape);
1554   
1555     ShapeFix::SameParameter(myShape,Standard_False);
1556     
1557     return StatusSmallEdges( ShapeExtend_DONE );
1558   }
1559
1560   return Standard_False;
1561 }