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 
IMPLEMENT_STANDARD_RTTIEXT(ShapeFix_Wireframe,ShapeFix_Root)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 
ShapeFix_Wireframe(const TopoDS_Shape & shape)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 
ClearStatuses()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 
Load(const TopoDS_Shape & shape)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 
FixWireGaps()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 
JoinEdges(const TopoDS_Edge & E1,const TopoDS_Edge & E2,TopoDS_Edge & E3,const TopTools_ListOfShape & faces)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     std::cout<<"Error: ShapeFix_Wireframe::FixSmallEdges: JoinEdges: Exception in GeomConvert_CompCurveToBSplineCurve: ";
396     anException.Print(std::cout); std::cout<<std::endl;
397 #endif
398     (void)anException;
399     return ReplaceFirst;
400   }
401 }
402 
403 //=======================================================================
404 //function : FixSmallEdges
405 //purpose  :
406 //=======================================================================
407 
FixSmallEdges()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>
CheckSmallEdges(TopTools_MapOfShape & theSmallEdges,TopTools_DataMapOfShapeListOfShape & theEdgeToFaces,TopTools_DataMapOfShapeListOfShape & theFaceWithSmall,TopTools_MapOfShape & theMultyEdges)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: Analyzing of shape for small edges, if edge doesn'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 
MergeSmallEdges(TopTools_MapOfShape & theSmallEdges,TopTools_DataMapOfShapeListOfShape & theEdgeToFaces,TopTools_DataMapOfShapeListOfShape & theFaceWithSmall,TopTools_MapOfShape & theMultyEdges,const Standard_Boolean theModeDrop,const Standard_Real theLimitAngle)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 against 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 against 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 }
1562