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