0027961: Visualization - remove unused and no more working OpenGl_AVIWriter
[occt.git] / src / ShapeFix / ShapeFix_IntersectionTool.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14
15 #include <Bnd_Box2d.hxx>
16 #include <BndLib_Add2dCurve.hxx>
17 #include <BRep_Builder.hxx>
18 #include <BRep_Tool.hxx>
19 #include <BRepTools.hxx>
20 #include <Geom2d_BSplineCurve.hxx>
21 #include <Geom2d_Curve.hxx>
22 #include <Geom2d_Line.hxx>
23 #include <Geom2d_TrimmedCurve.hxx>
24 #include <Geom2dAdaptor_Curve.hxx>
25 #include <Geom2dInt_GInter.hxx>
26 #include <Geom_Curve.hxx>
27 #include <Geom_Surface.hxx>
28 #include <GeomAdaptor_Curve.hxx>
29 #include <GeomAdaptor_HSurface.hxx>
30 #include <gp_Pnt.hxx>
31 #include <IntRes2d_Domain.hxx>
32 #include <IntRes2d_IntersectionPoint.hxx>
33 #include <IntRes2d_IntersectionSegment.hxx>
34 #include <IntRes2d_Position.hxx>
35 #include <NCollection_Sequence.hxx>
36 #include <ShapeAnalysis.hxx>
37 #include <ShapeAnalysis_Edge.hxx>
38 #include <ShapeAnalysis_Surface.hxx>
39 #include <ShapeAnalysis_TransferParametersProj.hxx>
40 #include <ShapeBuild_Edge.hxx>
41 #include <ShapeBuild_ReShape.hxx>
42 #include <ShapeExtend_WireData.hxx>
43 #include <ShapeFix_DataMapOfShapeBox2d.hxx>
44 #include <ShapeFix_IntersectionTool.hxx>
45 #include <TopExp_Explorer.hxx>
46 #include <TopoDS.hxx>
47 #include <TopoDS_Edge.hxx>
48 #include <TopoDS_Face.hxx>
49 #include <TopoDS_Iterator.hxx>
50 #include <TopoDS_Vertex.hxx>
51 #include <TopoDS_Wire.hxx>
52 #include <TopTools_SequenceOfShape.hxx>
53
54 //gka 06.09.04 BUG 6555 shape is modified always independently either intersection was fixed or not 
55 //=======================================================================
56 //function : ShapeFix_IntersectionTool
57 //purpose  : 
58 //=======================================================================
59 ShapeFix_IntersectionTool::ShapeFix_IntersectionTool(const Handle(ShapeBuild_ReShape)& context,
60                                                      const Standard_Real preci,
61                                                      const Standard_Real maxtol)
62 {
63   myContext = context;
64   myPreci = preci;
65   myMaxTol = maxtol;
66 }
67
68
69 //=======================================================================
70 //function : GetPointOnEdge
71 //purpose  : auxiliary
72 //:h0 abv 29 May 98: PRO10105 1949: like in BRepCheck, point is to be taken 
73 // from 3d curve (but only if edge is SameParameter)
74 //=======================================================================
75 static gp_Pnt GetPointOnEdge(const TopoDS_Edge &edge, 
76                              const Handle(ShapeAnalysis_Surface) &surf,
77                              const Geom2dAdaptor_Curve &Crv2d, 
78                              const Standard_Real param )
79 {
80   if( BRep_Tool::SameParameter(edge) ) {
81     Standard_Real f,l;
82     TopLoc_Location L;
83     const Handle(Geom_Curve) ConS = BRep_Tool::Curve ( edge, L, f, l );
84     if( !ConS.IsNull() )
85       return ConS->Value(param).Transformed(L.Transformation());
86   }
87   gp_Pnt2d aP2d = Crv2d.Value(param);
88   return surf->Adaptor3d()->Value(aP2d.X(), aP2d.Y());
89 }
90
91
92 //=======================================================================
93 //function : SplitEdge
94 //purpose  : 
95 //=======================================================================
96
97 Standard_Boolean ShapeFix_IntersectionTool::SplitEdge(const TopoDS_Edge& edge,
98                                                       const Standard_Real param,
99                                                       const TopoDS_Vertex& vert,
100                                                       const TopoDS_Face& face,
101                                                       TopoDS_Edge& newE1,
102                                                       TopoDS_Edge& newE2,
103                                                       const Standard_Real preci) const
104 {
105   Standard_Real a, b;
106   ShapeAnalysis_Edge sae;
107
108   TopoDS_Vertex V1 = sae.FirstVertex(edge);
109   TopoDS_Vertex V2 = sae.LastVertex(edge);
110   if( V1.IsSame(vert) || V2.IsSame(vert) )
111     return Standard_False;
112
113   Handle(Geom2d_Curve) c2d;
114   sae.PCurve(edge,face,c2d,a,b,Standard_True );
115   if( Abs(a-param)<0.01*preci || Abs(b-param)<0.01*preci )
116     return Standard_False;
117   // check distanse between edge and new vertex
118   gp_Pnt P1;
119   TopLoc_Location L;
120   if(BRep_Tool::SameParameter(edge) && !BRep_Tool::Degenerated(edge)) {
121     Standard_Real f,l;
122     const Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,L,f,l);
123     if(c3d.IsNull())
124       return Standard_False;
125     P1 = c3d->Value(param);
126     if(!L.IsIdentity()) P1 = P1.Transformed(L.Transformation());
127   }
128   else {
129     Handle(Geom_Surface) surf = BRep_Tool::Surface(face,L);
130     Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface(surf);
131     P1 = sas->Value(c2d->Value(param));
132     if(!L.IsIdentity()) P1 = P1.Transformed(L.Transformation());
133   }
134   gp_Pnt P2 = BRep_Tool::Pnt(vert);
135   if(P1.Distance(P2)>preci) {
136     //return Standard_False;
137     BRep_Builder B;
138     B.UpdateVertex(vert,P1.Distance(P2));
139   }
140   
141   Handle(ShapeAnalysis_TransferParametersProj) transferParameters =
142     new ShapeAnalysis_TransferParametersProj;
143   transferParameters->SetMaxTolerance(preci);
144   transferParameters->Init(edge,face);
145   Standard_Real first, last;
146   if (a < b ) {
147     first = a; 
148     last = b;
149   }
150   else {
151     first = b; 
152     last = a;
153   }
154   
155   ShapeBuild_Edge sbe;
156   TopAbs_Orientation orient = edge.Orientation();
157   BRep_Builder B;
158   TopoDS_Edge wE = edge;
159   wE.Orientation ( TopAbs_FORWARD );
160   TopoDS_Shape aTmpShape = vert.Oriented(TopAbs_REVERSED); //for porting
161   newE1 = sbe.CopyReplaceVertices ( wE, sae.FirstVertex(wE), TopoDS::Vertex(aTmpShape) );
162   sbe.CopyPCurves ( newE1, wE  );
163   transferParameters->TransferRange(newE1,first,param,Standard_True);
164   B.SameRange(newE1,Standard_False);
165   B.SameParameter(newE1,Standard_False);
166   aTmpShape = vert.Oriented(TopAbs_FORWARD);
167   newE2 = sbe.CopyReplaceVertices ( wE, TopoDS::Vertex(aTmpShape),sae.LastVertex(wE) );
168   sbe.CopyPCurves ( newE2, wE  );
169   transferParameters->TransferRange(newE2,param,last,Standard_True);
170   B.SameRange(newE2,Standard_False);
171   B.SameParameter(newE2,Standard_False);
172
173   newE1.Orientation(orient);
174   newE2.Orientation(orient);
175   if (orient==TopAbs_REVERSED) { 
176     TopoDS_Edge tmp = newE2; newE2 = newE1; newE1=tmp;
177   }
178
179   return Standard_True;
180 }
181
182
183 //=======================================================================
184 //function : CutEdge
185 //purpose  : 
186 //=======================================================================
187
188 Standard_Boolean ShapeFix_IntersectionTool::CutEdge(const TopoDS_Edge &edge,
189                                                     const Standard_Real pend,
190                                                     const Standard_Real cut,
191                                                     const TopoDS_Face &face,
192                                                     Standard_Boolean &iscutline) const
193 {
194   if( Abs(cut-pend)<10.*Precision::PConfusion() ) return Standard_False;
195   Standard_Real aRange = Abs(cut-pend);
196   Standard_Real a, b;
197   BRep_Tool::Range(edge, a, b);
198   
199   if( aRange<10.*Precision::PConfusion() ) return Standard_False;
200
201   // case pcurve is trimm of line
202   if( !BRep_Tool::SameParameter(edge) ) {
203     ShapeAnalysis_Edge sae;
204     Handle(Geom2d_Curve) Crv;
205     Standard_Real fp,lp;
206     if ( sae.PCurve(edge,face,Crv,fp,lp,Standard_False) ) {
207       if(Crv->IsKind(STANDARD_TYPE(Geom2d_TrimmedCurve))) {
208         Handle(Geom2d_TrimmedCurve) tc = Handle(Geom2d_TrimmedCurve)::DownCast(Crv);
209         if(tc->BasisCurve()->IsKind(STANDARD_TYPE(Geom2d_Line))) {
210           BRep_Builder B;
211           B.Range(edge,Min(pend,cut),Max(pend,cut));
212           if( Abs(pend-lp)<Precision::PConfusion() ) { // cut from the begining
213             Standard_Real cut3d = (cut-fp)*(b-a)/(lp-fp);
214             B.Range(edge, a+cut3d, b, Standard_True);
215             iscutline = Standard_True;
216           }
217           else if( Abs(pend-fp)<Precision::PConfusion() ) { // cut from the end
218             Standard_Real cut3d = (lp-cut)*(b-a)/(lp-fp);
219             B.Range(edge, a, b-cut3d, Standard_True);
220             iscutline = Standard_True;
221           }
222         }
223
224         return Standard_True;
225       }
226      
227     }
228     return Standard_False;
229   }
230
231   // det-study on 03/12/01 checking the old and new ranges
232   if( Abs(Abs(a-b)-aRange) < Precision::PConfusion() ) return Standard_False;
233   if( aRange<10.*Precision::PConfusion() ) return Standard_False;
234
235   BRep_Builder B;
236   B.Range( edge, Min(pend,cut), Max(pend,cut) );
237
238   return Standard_True;
239 }
240
241
242 //=======================================================================
243 //function : SplitEdge1
244 //purpose  : split edge[a,b] om two part e1[a,param]
245 //           and e2[param,b] using vertex vert
246 //=======================================================================
247
248 Standard_Boolean ShapeFix_IntersectionTool::SplitEdge1(const Handle(ShapeExtend_WireData)& sewd,
249                                                        const TopoDS_Face& face,
250                                                        const Standard_Integer num,
251                                                        const Standard_Real param,
252                                                        const TopoDS_Vertex& vert,
253                                                        const Standard_Real preci,
254                                                        ShapeFix_DataMapOfShapeBox2d& boxes) const
255 {
256   TopoDS_Edge edge = sewd->Edge(num);
257   TopoDS_Edge newE1, newE2;
258   if(!SplitEdge(edge,param,vert,face,newE1,newE2,preci)) return Standard_False;
259
260   // change context
261   Handle(ShapeExtend_WireData) wd = new ShapeExtend_WireData;
262   wd->Add(newE1);
263   wd->Add(newE2);
264   if(!myContext.IsNull()) myContext->Replace( edge, wd->Wire() );
265   for (TopExp_Explorer exp ( wd->Wire(), TopAbs_EDGE ); exp.More(); exp.Next() ) {
266     TopoDS_Edge E = TopoDS::Edge ( exp.Current() );
267     BRepTools::Update(E);
268   }
269   
270   // change sewd
271   sewd->Set(newE1,num);
272   if(num==sewd->NbEdges())
273     sewd->Add(newE2);
274   else
275     sewd->Add(newE2,num+1);
276
277   // change boxes
278   boxes.UnBind(edge);
279   TopLoc_Location L;
280   const Handle(Geom_Surface)& S = BRep_Tool::Surface(face,L);
281   Handle(Geom2d_Curve) c2d;
282   Standard_Real cf,cl;
283   ShapeAnalysis_Edge sae;
284   if(sae.PCurve(newE1,S,L,c2d,cf,cl,Standard_False)) {
285     Bnd_Box2d box;
286     Geom2dAdaptor_Curve gac;
287     Standard_Real aFirst = c2d->FirstParameter();
288     Standard_Real aLast = c2d->LastParameter();
289     if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) 
290        && (cf < aFirst || cl > aLast)) {
291       //pdn avoiding problems with segment in Bnd_Box
292       gac.Load(c2d);
293     }
294     else
295       gac.Load(c2d,cf,cl);
296     BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
297     boxes.Bind(newE1,box);
298   }
299   if(sae.PCurve(newE2,S,L,c2d,cf,cl,Standard_False)) {
300     Bnd_Box2d box;
301     Geom2dAdaptor_Curve gac;
302     Standard_Real aFirst = c2d->FirstParameter();
303     Standard_Real aLast = c2d->LastParameter();
304     if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) 
305        && (cf < aFirst || cl > aLast)) {
306       //pdn avoiding problems with segment in Bnd_Box
307       gac.Load(c2d);
308     }
309     else
310       gac.Load(c2d,cf,cl);
311     BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
312     boxes.Bind(newE2,box);
313   }
314
315   return Standard_True;
316 }
317
318
319 //=======================================================================
320 //function : SplitEdge2
321 //purpose  : auxilary: split edge[a,b] om two part e1[a,param1]
322 //                     and e2[param2,b] using vertex vert
323 //                     (remove segment (param1,param2) from edge)
324 //=======================================================================
325
326 Standard_Boolean ShapeFix_IntersectionTool::SplitEdge2(const Handle(ShapeExtend_WireData)& sewd,
327                                                        const TopoDS_Face& face,
328                                                        const Standard_Integer num,
329                                                        const Standard_Real param1,
330                                                        const Standard_Real param2,
331                                                        const TopoDS_Vertex& vert,
332                                                        const Standard_Real preci,
333                                                        ShapeFix_DataMapOfShapeBox2d& boxes) const
334 {
335   TopoDS_Edge edge = sewd->Edge(num);
336   TopoDS_Edge newE1, newE2;
337   Standard_Real param = (param1+param2)/2;
338   if(!SplitEdge(edge,param,vert,face,newE1,newE2,preci)) return Standard_False;
339   // cut new edges by param1 and param2
340   Standard_Boolean IsCutLine;
341   Handle(Geom2d_Curve) Crv1, Crv2;
342   Standard_Real fp1,lp1,fp2,lp2;
343   ShapeAnalysis_Edge sae;
344   if(sae.PCurve ( newE1, face, Crv1, fp1, lp1, Standard_False )) {
345     if(sae.PCurve ( newE2, face, Crv2, fp2, lp2, Standard_False )) {
346       if(lp1==param) {
347         if( (lp1-fp1)*(lp1-param1)>0 ) {
348           CutEdge(newE1, fp1, param1, face, IsCutLine);
349           CutEdge(newE2, lp2, param2, face, IsCutLine);
350         }
351         else {
352           CutEdge(newE1, fp1, param2, face, IsCutLine);
353           CutEdge(newE2, lp2, param1, face, IsCutLine);
354         }
355       }
356       else {
357         if( (fp1-lp1)*(fp1-param1)>0 ) {
358           CutEdge(newE1, lp1, param1, face, IsCutLine);
359           CutEdge(newE2, fp2, param2, face, IsCutLine);
360         }
361         else {
362           CutEdge(newE1, lp1, param2, face, IsCutLine);
363           CutEdge(newE2, fp2, param1, face, IsCutLine);
364         }
365       }
366     }
367   }
368     
369   // change context
370   Handle(ShapeExtend_WireData) wd = new ShapeExtend_WireData;
371   wd->Add(newE1);
372   wd->Add(newE2);
373   if(!myContext.IsNull()) myContext->Replace( edge, wd->Wire() );
374   for (TopExp_Explorer exp ( wd->Wire(), TopAbs_EDGE ); exp.More(); exp.Next() ) {
375       TopoDS_Edge E = TopoDS::Edge ( exp.Current() );
376       BRepTools::Update(E);
377     }
378   
379   // change sewd
380   sewd->Set(newE1,num);
381   if(num==sewd->NbEdges())
382     sewd->Add(newE2);
383   else
384     sewd->Add(newE2,num+1);
385
386   // change boxes
387   boxes.UnBind(edge);
388   TopLoc_Location L;
389   const Handle(Geom_Surface)& S = BRep_Tool::Surface(face,L);
390   Handle(Geom2d_Curve) c2d;
391   Standard_Real cf,cl;
392   if(sae.PCurve(newE1,S,L,c2d,cf,cl,Standard_False)) {
393     Bnd_Box2d box;
394     Geom2dAdaptor_Curve gac;
395     Standard_Real aFirst = c2d->FirstParameter();
396     Standard_Real aLast = c2d->LastParameter();
397     if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) 
398        && (cf < aFirst || cl > aLast)) {
399       //pdn avoiding problems with segment in Bnd_Box
400       gac.Load(c2d);
401     }
402     else
403       gac.Load(c2d,cf,cl);
404     BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
405     boxes.Bind(newE1,box);
406   }
407   if(sae.PCurve(newE2,S,L,c2d,cf,cl,Standard_False)) {
408     Bnd_Box2d box;
409     Geom2dAdaptor_Curve gac;
410     Standard_Real aFirst = c2d->FirstParameter();
411     Standard_Real aLast = c2d->LastParameter();
412     if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) 
413        && (cf < aFirst || cl > aLast)) {
414       //pdn avoiding problems with segment in Bnd_Box
415       gac.Load(c2d);
416     }
417     else
418       gac.Load(c2d,cf,cl);
419     BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
420     boxes.Bind(newE2,box);
421   }
422
423   return Standard_True;
424 }
425
426
427 //=======================================================================
428 //function : UnionVertexes
429 //purpose  : 
430 //=======================================================================
431
432 Standard_Boolean ShapeFix_IntersectionTool::UnionVertexes(const Handle(ShapeExtend_WireData)& sewd,
433                                                           TopoDS_Edge& edge1,
434                                                           TopoDS_Edge& edge2,
435                                                           const Standard_Integer num2,
436                                                           ShapeFix_DataMapOfShapeBox2d& boxes,
437                                                           const Bnd_Box2d& B2) const
438 {
439   // union vertexes
440   Standard_Boolean res = Standard_False;
441   ShapeBuild_Edge sbe;
442   ShapeAnalysis_Edge sae;
443   BRep_Builder B;
444   TopoDS_Vertex V;
445   TopoDS_Vertex V1F = sae.FirstVertex(edge1);
446   gp_Pnt PV1F = BRep_Tool::Pnt(V1F);
447   TopoDS_Vertex V1L = sae.LastVertex(edge1);
448   gp_Pnt PV1L = BRep_Tool::Pnt(V1L);
449   TopoDS_Vertex V2F = sae.FirstVertex(edge2);
450   gp_Pnt PV2F = BRep_Tool::Pnt(V2F);
451   TopoDS_Vertex V2L = sae.LastVertex(edge2);
452   gp_Pnt PV2L = BRep_Tool::Pnt(V2L);
453   Standard_Real d11 = PV1F.Distance(PV2F);
454   Standard_Real d12 = PV1F.Distance(PV2L);
455   Standard_Real d21 = PV1L.Distance(PV2F);
456   Standard_Real d22 = PV1L.Distance(PV2L);
457   if(d11<d12 && d11<d21 && d11<d22) {
458     Standard_Real tolv = Max(BRep_Tool::Tolerance(V1F),BRep_Tool::Tolerance(V2F));
459     if( !V2F.IsSame(V1F) && d11<tolv ) {
460       // union vertexes V1F and V2F
461       B.UpdateVertex(V1F,tolv);
462       TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V1F,V2L);
463 //      cout<<"union vertexes V1F and V2F"<<endl;
464 //      gp_Pnt Ptmp = BRep_Tool::Pnt(V1F);
465 //      B.MakeVertex(V,Ptmp,tolv);
466 //      myContext->Replace(V1F,V);
467 //      myContext->Replace(V2F,V);
468 //      TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V,V2L);
469       myContext->Replace(edge2,NewE);
470       sewd->Set(NewE,num2);
471       edge2 = NewE;
472       boxes.Bind(NewE,B2); // update boxes
473       // replace vertex in other edge
474       Standard_Integer num21,num22;
475       if(num2>1) num21=num2-1;
476       else num21=sewd->NbEdges();
477       if(num2<sewd->NbEdges()) num22=num2+1;
478       else num22=1;
479       TopoDS_Edge edge21 = sewd->Edge(num21);
480       TopoDS_Edge edge22 = sewd->Edge(num22);
481       TopoDS_Vertex V21F = sae.FirstVertex(edge21);
482       TopoDS_Vertex V21L = sae.LastVertex(edge21);
483       TopoDS_Vertex V22F = sae.FirstVertex(edge22);
484       TopoDS_Vertex V22L = sae.LastVertex(edge22);
485       if(V21F.IsSame(V2F)) {
486         NewE = sbe.CopyReplaceVertices(edge21,V1F,V21L);
487         //NewE = sbe.CopyReplaceVertices(edge21,V,V21L);
488         if (boxes.IsBound(edge21))
489           boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
490         myContext->Replace(edge21,NewE);
491         sewd->Set(NewE,num21);
492       }
493       if(V21L.IsSame(V2F)) {
494         NewE = sbe.CopyReplaceVertices(edge21,V21F,V1F);
495         //NewE = sbe.CopyReplaceVertices(edge21,V21F,V);
496         if (boxes.IsBound(edge21))
497           boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
498         myContext->Replace(edge21,NewE);
499         sewd->Set(NewE,num21);
500       }
501       if(V22F.IsSame(V2F)) {
502         NewE = sbe.CopyReplaceVertices(edge22,V1F,V22L);
503         //NewE = sbe.CopyReplaceVertices(edge22,V,V22L);
504         if (boxes.IsBound(edge22))
505           boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
506         myContext->Replace(edge22,NewE);
507         sewd->Set(NewE,num22);
508       }
509       if(V22L.IsSame(V2F)) {
510         NewE = sbe.CopyReplaceVertices(edge22,V22F,V1F);
511         //NewE = sbe.CopyReplaceVertices(edge22,V22F,V);
512         if (boxes.IsBound(edge22))
513           boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
514         myContext->Replace(edge22,NewE);
515         sewd->Set(NewE,num22);
516       }
517       res = Standard_True;
518     }
519   }
520   else if(d12<d21 && d12<d22) {
521     Standard_Real tolv = Max(BRep_Tool::Tolerance(V1F),BRep_Tool::Tolerance(V2L));
522     if( !V2L.IsSame(V1F) && d12<tolv ) {
523       // union vertexes V1F and V2L
524       B.UpdateVertex(V1F,tolv);
525       TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V2F,V1F);
526 //      cout<<"union vertexes V1F and V2L"<<endl;
527 //      gp_Pnt Ptmp = BRep_Tool::Pnt(V1F);
528 //      B.MakeVertex(V,Ptmp,tolv);
529 //      myContext->Replace(V1F,V);
530 //      myContext->Replace(V2L,V);
531 //      TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V2F,V);
532       myContext->Replace(edge2,NewE);
533       sewd->Set(NewE,num2);
534       edge2 = NewE;
535       //boxes.Bind(NewE,boxes.Find(edge2)); // update boxes
536       boxes.Bind(NewE,B2); // update boxes
537       // replace vertex in other edge
538       Standard_Integer num21,num22;
539       if(num2>1) num21=num2-1;
540       else num21=sewd->NbEdges();
541       if(num2<sewd->NbEdges()) num22=num2+1;
542       else num22=1;
543       TopoDS_Edge edge21 = sewd->Edge(num21);
544       TopoDS_Edge edge22 = sewd->Edge(num22);
545       TopoDS_Vertex V21F = sae.FirstVertex(edge21);
546       TopoDS_Vertex V21L = sae.LastVertex(edge21);
547       TopoDS_Vertex V22F = sae.FirstVertex(edge22);
548       TopoDS_Vertex V22L = sae.LastVertex(edge22);
549       if(V21F.IsSame(V2L)) {
550         NewE = sbe.CopyReplaceVertices(edge21,V1F,V21L);
551         //NewE = sbe.CopyReplaceVertices(edge21,V,V21L);
552         if (boxes.IsBound(edge21))
553           boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
554         myContext->Replace(edge21,NewE);
555         sewd->Set(NewE,num21);
556       }
557       if(V21L.IsSame(V2L)) {
558         NewE = sbe.CopyReplaceVertices(edge21,V21F,V1F);
559         //NewE = sbe.CopyReplaceVertices(edge21,V21F,V);
560         if (boxes.IsBound(edge21))
561           boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
562         myContext->Replace(edge21,NewE);
563         sewd->Set(NewE,num21);
564       }
565       if(V22F.IsSame(V2L)) {
566         NewE = sbe.CopyReplaceVertices(edge22,V1F,V22L);
567         //NewE = sbe.CopyReplaceVertices(edge22,V,V22L);
568         if (boxes.IsBound(edge22))
569           boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
570         myContext->Replace(edge22,NewE);
571         sewd->Set(NewE,num22);
572       }
573       if(V22L.IsSame(V2L)) {
574         NewE = sbe.CopyReplaceVertices(edge22,V22F,V1F);
575         //NewE = sbe.CopyReplaceVertices(edge22,V22F,V);
576         if (boxes.IsBound(edge22))
577           boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
578         myContext->Replace(edge22,NewE);
579         sewd->Set(NewE,num22);
580       }
581       res = Standard_True;
582     }
583   }
584   else if(d21<d22) {
585     Standard_Real tolv = Max(BRep_Tool::Tolerance(V1L),BRep_Tool::Tolerance(V2F));
586     if( !V2F.IsSame(V1L) && d21<tolv ) {
587       // union vertexes V1L and V2F
588       B.UpdateVertex(V1L,tolv);
589       TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V1L,V2L);
590 //      cout<<"union vertexes V1L and V2F"<<endl;
591 //      gp_Pnt Ptmp = BRep_Tool::Pnt(V1L);
592 //      B.MakeVertex(V,Ptmp,tolv);
593 //      myContext->Replace(V1L,V);
594 //      myContext->Replace(V2F,V);
595 //      TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V,V2L);
596       myContext->Replace(edge2,NewE);
597       sewd->Set(NewE,num2);
598       edge2 = NewE;
599       boxes.Bind(NewE,B2); // update boxes
600       // replace vertex in other edge
601       Standard_Integer num21,num22;
602       if(num2>1) num21=num2-1;
603       else num21=sewd->NbEdges();
604       if(num2<sewd->NbEdges()) num22=num2+1;
605       else num22=1;
606       TopoDS_Edge edge21 = sewd->Edge(num21);
607       TopoDS_Edge edge22 = sewd->Edge(num22);
608       TopoDS_Vertex V21F = sae.FirstVertex(edge21);
609       TopoDS_Vertex V21L = sae.LastVertex(edge21);
610       TopoDS_Vertex V22F = sae.FirstVertex(edge22);
611       TopoDS_Vertex V22L = sae.LastVertex(edge22);
612       if(V21F.IsSame(V2F)) {
613         NewE = sbe.CopyReplaceVertices(edge21,V1L,V21L);
614         //NewE = sbe.CopyReplaceVertices(edge21,V,V21L);
615         if (boxes.IsBound(edge21))
616           boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
617         myContext->Replace(edge21,NewE);
618         sewd->Set(NewE,num21);
619       }
620       if(V21L.IsSame(V2F)) {
621         NewE = sbe.CopyReplaceVertices(edge21,V21F,V1L);
622         //NewE = sbe.CopyReplaceVertices(edge21,V21F,V);
623         if (boxes.IsBound(edge21))
624           boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
625         myContext->Replace(edge21,NewE);
626         sewd->Set(NewE,num21);
627       }
628       if(V22F.IsSame(V2F)) {
629         NewE = sbe.CopyReplaceVertices(edge22,V1L,V22L);
630         //NewE = sbe.CopyReplaceVertices(edge22,V,V22L);
631         if (boxes.IsBound(edge22))
632           boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
633         myContext->Replace(edge22,NewE);
634         sewd->Set(NewE,num22);
635       }
636       if(V22L.IsSame(V2F)) {
637         NewE = sbe.CopyReplaceVertices(edge22,V22F,V1L);
638         //NewE = sbe.CopyReplaceVertices(edge22,V22F,V);
639         if (boxes.IsBound(edge22))
640           boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
641         myContext->Replace(edge22,NewE);
642         sewd->Set(NewE,num22);
643       }
644       res = Standard_True;
645     }
646   }
647   else {
648     Standard_Real tolv = Max(BRep_Tool::Tolerance(V1L),BRep_Tool::Tolerance(V2L));
649     if( !V2L.IsSame(V1L) && d22<tolv ) {
650       // union vertexes V1L and V2L
651       B.UpdateVertex(V1L,tolv);
652       TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V2F,V1L);
653 //      cout<<"union vertexes V1L and V2L"<<endl;
654 //      gp_Pnt Ptmp = BRep_Tool::Pnt(V1L);
655 //      B.MakeVertex(V,Ptmp,tolv);
656 //      myContext->Replace(V1L,V);
657 //      myContext->Replace(V2L,V);
658 //      TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V2F,V);
659       myContext->Replace(edge2,NewE);
660       sewd->Set(NewE,num2);
661       edge2 = NewE;
662       boxes.Bind(NewE,B2); // update boxes
663       // replace vertex in other edge
664       Standard_Integer num21,num22;
665       if(num2>1) num21=num2-1;
666       else num21=sewd->NbEdges();
667       if(num2<sewd->NbEdges()) num22=num2+1;
668       else num22=1;
669       TopoDS_Edge edge21 = sewd->Edge(num21);
670       TopoDS_Edge edge22 = sewd->Edge(num22);
671       TopoDS_Vertex V21F = sae.FirstVertex(edge21);
672       TopoDS_Vertex V21L = sae.LastVertex(edge21);
673       TopoDS_Vertex V22F = sae.FirstVertex(edge22);
674       TopoDS_Vertex V22L = sae.LastVertex(edge22);
675       if(V21F.IsSame(V2L)) {
676         NewE = sbe.CopyReplaceVertices(edge21,V1L,V21L);
677         //NewE = sbe.CopyReplaceVertices(edge21,V,V21L);
678         if (boxes.IsBound(edge21))
679           boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
680         myContext->Replace(edge21,NewE);
681         sewd->Set(NewE,num21);
682       }
683       if(V21L.IsSame(V2L)) {
684         NewE = sbe.CopyReplaceVertices(edge21,V21F,V1L);
685         //NewE = sbe.CopyReplaceVertices(edge21,V21F,V);
686         if (boxes.IsBound(edge21))
687           boxes.Bind(NewE,boxes.Find(edge21)); // update boxes
688         myContext->Replace(edge21,NewE);
689         sewd->Set(NewE,num21);
690       }
691       if(V22F.IsSame(V2L)) {
692         NewE = sbe.CopyReplaceVertices(edge22,V1L,V22L);
693         //NewE = sbe.CopyReplaceVertices(edge22,V,V22L);
694         if (boxes.IsBound(edge22))
695           boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
696         myContext->Replace(edge22,NewE);
697         sewd->Set(NewE,num22);
698       }
699       if(V22L.IsSame(V2L)) {
700         NewE = sbe.CopyReplaceVertices(edge22,V22F,V1L);
701         //NewE = sbe.CopyReplaceVertices(edge22,V22F,V);
702         if (boxes.IsBound(edge22))
703           boxes.Bind(NewE,boxes.Find(edge22)); // update boxes
704         myContext->Replace(edge22,NewE);
705         sewd->Set(NewE,num22);
706       }
707       res = Standard_True;
708     }
709   }
710
711   return res;
712 }
713
714
715 //=======================================================================
716 //function : CreateBoxes2d
717 //purpose  : auxilary
718 //=======================================================================
719 static Bnd_Box2d CreateBoxes2d(const Handle(ShapeExtend_WireData)& sewd, 
720                                       const TopoDS_Face& face,
721                                       ShapeFix_DataMapOfShapeBox2d& boxes) 
722 {
723   // create box2d for edges from wire
724   Bnd_Box2d aTotalBox;
725   TopLoc_Location L;
726   const Handle(Geom_Surface)& S = BRep_Tool::Surface(face,L);
727   Handle(Geom2d_Curve) c2d;
728   Standard_Real cf,cl;
729   ShapeAnalysis_Edge sae;
730   for(Standard_Integer i=1; i<=sewd->NbEdges(); i++){
731     TopoDS_Edge E = sewd->Edge(i);
732     if(sae.PCurve(E,S,L,c2d,cf,cl,Standard_False)) {
733       Bnd_Box2d box;
734       Geom2dAdaptor_Curve gac;
735       Standard_Real aFirst = c2d->FirstParameter();
736       Standard_Real aLast = c2d->LastParameter();
737       if(c2d->IsKind(STANDARD_TYPE(Geom2d_BSplineCurve)) 
738          && (cf < aFirst || cl > aLast)) {
739         //pdn avoiding problems with segment in Bnd_Box
740         gac.Load(c2d);
741       }
742       else
743         gac.Load(c2d,cf,cl);
744       BndLib_Add2dCurve::Add(gac,::Precision::Confusion(),box);
745       boxes.Bind(E,box);
746       aTotalBox.Add (box);
747     }
748   }
749   return aTotalBox;
750 }
751
752
753 //=======================================================================
754 //function : SelectIntPnt
755 //purpose  : auxilary
756 //=======================================================================
757 static void SelectIntPnt(const Geom2dInt_GInter& Inter,
758                          IntRes2d_IntersectionPoint& IP,
759                          IntRes2d_Transition& Tr1,
760                          IntRes2d_Transition& Tr2)
761 {
762   IP = Inter.Point(1);
763   Tr1 = IP.TransitionOfFirst();
764   Tr2 = IP.TransitionOfSecond();
765   if(Inter.NbPoints()==2) {
766     // possible second point is better?
767     Standard_Integer status1=0,status2=0;
768     if(Tr1.PositionOnCurve()==IntRes2d_Middle) status1+=1;
769     if(Tr2.PositionOnCurve()==IntRes2d_Middle) status1+=2;
770     IntRes2d_IntersectionPoint IP2;
771     IntRes2d_Transition Tr12, Tr22;
772     IP2 = Inter.Point(2);
773     Tr12 = IP2.TransitionOfFirst();
774     Tr22 = IP2.TransitionOfSecond();
775     if(Tr12.PositionOnCurve()==IntRes2d_Middle) status2+=1;
776     if(Tr22.PositionOnCurve()==IntRes2d_Middle) status2+=2;
777     if(status2>status1) {
778       IP=IP2; Tr1=Tr12; Tr2=Tr22;
779     }
780   }
781 }
782
783
784 //=======================================================================
785 //function : FindVertAndSplitEdge
786 //purpose  : auxilary
787 //=======================================================================
788 Standard_Boolean ShapeFix_IntersectionTool::FindVertAndSplitEdge
789            (const Standard_Real param1,
790             const TopoDS_Edge& edge1, const TopoDS_Edge& edge2,
791             const Handle(Geom2d_Curve)& Crv1,
792             Standard_Real& MaxTolVert,
793             Standard_Integer& num1,
794             const Handle(ShapeExtend_WireData)& sewd, 
795             const TopoDS_Face& face,
796             ShapeFix_DataMapOfShapeBox2d& boxes,
797             const Standard_Boolean aTmpKey) const
798 {
799   // find needed vertex from edge2 and split edge1 using it
800   ShapeAnalysis_Edge sae;
801   Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface(BRep_Tool::Surface(face));
802   gp_Pnt pi1 = GetPointOnEdge(edge1,sas,Crv1,param1);
803   BRep_Builder B;
804   TopoDS_Vertex V;
805   Standard_Real tolV;
806   TopoDS_Vertex V1 = sae.FirstVertex(edge2);
807   gp_Pnt PV1 = BRep_Tool::Pnt(V1);
808   TopoDS_Vertex V2 = sae.LastVertex(edge2);
809   gp_Pnt PV2 = BRep_Tool::Pnt(V2);
810   TopoDS_Vertex V11 = sae.FirstVertex(edge1);
811   TopoDS_Vertex V12 = sae.LastVertex(edge1);
812   Standard_Boolean NeedSplit = Standard_True;
813   if(pi1.Distance(PV1)<pi1.Distance(PV2)) {
814     if( V1.IsSame(V11) || V1.IsSame(V12) ) {
815       NeedSplit = Standard_False;
816     }
817     V = V1;
818     tolV = Max( (pi1.Distance(PV1)/2)*1.00001, BRep_Tool::Tolerance(V1) );
819   }
820   else {
821     if( V2.IsSame(V11) || V2.IsSame(V12) ) {
822       NeedSplit = Standard_False;
823     }
824     V = V2;
825     tolV = Max( (pi1.Distance(PV2)/2)*1.00001, BRep_Tool::Tolerance(V2) );
826   }
827   if( NeedSplit || aTmpKey ) {
828     if(SplitEdge1(sewd, face, num1, param1, V, tolV, boxes)) {
829       B.UpdateVertex(V,tolV);
830       MaxTolVert = Max(MaxTolVert,tolV);
831 //      NbSplit++;
832       num1--;
833       return Standard_True;
834       //break;
835     }
836   }
837   return Standard_False;
838 }
839
840
841 //=======================================================================
842 //function : FixSelfIntersectWire
843 //purpose  : 
844 //=======================================================================
845
846 Standard_Boolean ShapeFix_IntersectionTool::FixSelfIntersectWire
847   (Handle(ShapeExtend_WireData)& sewd, const TopoDS_Face& face,
848    Standard_Integer& NbSplit, Standard_Integer& NbCut,
849    Standard_Integer& NbRemoved) const
850 {
851   if(myContext.IsNull() || face.IsNull()) return Standard_False;
852
853   //Standard_Real area2d = ShapeAnalysis::TotCross2D(sewd,face);
854   //if(area2d<Precision::PConfusion()*Precision::PConfusion()) return Standard_False; //gka 06.09.04 BUG 6555
855
856   TopoDS_Shape SF = Context()->Apply(face);
857   Standard_Real MaxTolVert=0.0;
858   for(TopExp_Explorer exp(SF,TopAbs_VERTEX); exp.More(); exp.Next()) { 
859     Standard_Real tolV = BRep_Tool::Tolerance(TopoDS::Vertex(exp.Current()));
860     MaxTolVert = Max(MaxTolVert,tolV);
861   }
862   MaxTolVert = Min(MaxTolVert,myMaxTol);
863   ShapeAnalysis_Edge sae;
864
865   // step 1 : intersection of adjacent edges
866
867   // step 2 : intersection of non-adjacent edges
868   ShapeFix_DataMapOfShapeBox2d boxes;
869   (void)CreateBoxes2d(sewd,face,boxes);
870   Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface(BRep_Tool::Surface(face));
871
872   NbSplit=0;
873   NbCut=0;
874   Standard_Integer nbReplaced =0;
875   Standard_Boolean isDone = Standard_False;
876   for(Standard_Integer num1=1; num1<sewd->NbEdges() && NbSplit<30; num1++) {
877     // for each edge from first wire
878     for(Standard_Integer num2=num1+2; num2<=sewd->NbEdges() && NbSplit<30; num2++) {
879       // for each edge from second wire
880       if( num1==1 && num2==sewd->NbEdges() ) continue;
881       TopoDS_Edge edge1 = sewd->Edge(num1);
882       TopoDS_Edge edge2 = sewd->Edge(num2);
883       if(edge1.IsSame(edge2)) continue;
884       if( BRep_Tool::Degenerated(edge1) || BRep_Tool::Degenerated(edge2) ) continue;
885       if( !boxes.IsBound(edge1) || !boxes.IsBound(edge2) ) continue;
886       Bnd_Box2d B1 = boxes.Find(edge1);
887       Bnd_Box2d B2 = boxes.Find(edge2);
888       if(!B1.IsOut(B2)) {
889         // intersection is possible...
890         Standard_Real a1, b1, a2, b2;
891         Handle(Geom2d_Curve) Crv1, Crv2;
892         if( !sae.PCurve(edge1, face, Crv1, a1, b1, Standard_False) ) return Standard_False;
893         if( !sae.PCurve(edge2, face, Crv2, a2, b2, Standard_False) ) return Standard_False;
894         Standard_Real tolint = 1.0e-10; 
895         Geom2dAdaptor_Curve C1(Crv1), C2(Crv2);
896         IntRes2d_Domain d1(C1.Value(a1),a1,tolint,C1.Value(b1),b1,tolint);
897         IntRes2d_Domain d2(C2.Value(a2),a2,tolint,C2.Value(b2),b2,tolint);
898         Geom2dInt_GInter Inter;
899         Inter.Perform( C1, d1, C2, d2, tolint, tolint );
900         if(!Inter.IsDone()) continue;
901         // intersection is point
902         if( Inter.NbPoints()>0 && Inter.NbPoints()<3 ) {
903           IntRes2d_IntersectionPoint IP;
904           IntRes2d_Transition Tr1, Tr2;
905           SelectIntPnt(Inter,IP,Tr1,Tr2);
906           if( Tr1.PositionOnCurve() == IntRes2d_Middle &&
907              Tr2.PositionOnCurve() == IntRes2d_Middle ) {
908             Standard_Real param1 = IP.ParamOnFirst(); 
909             Standard_Real param2 = IP.ParamOnSecond();
910             gp_Pnt pi1 = GetPointOnEdge(edge1,sas,C1,param1);
911             gp_Pnt pi2 = GetPointOnEdge(edge2,sas,C2,param2);
912             BRep_Builder B;
913             TopoDS_Vertex V;
914             Standard_Real tolV=0;
915             // analysis for edge1
916             Standard_Boolean ModifE1 = Standard_False;
917             TopoDS_Vertex VF1 = sae.FirstVertex(edge1);
918             gp_Pnt PVF1 = BRep_Tool::Pnt(VF1);
919             TopoDS_Vertex VL1 = sae.LastVertex(edge1);
920             gp_Pnt PVL1 = BRep_Tool::Pnt(VL1);
921             Standard_Real dist1 = pi1.Distance(PVF1);
922             Standard_Real dist2 = pi1.Distance(PVL1);
923             Standard_Real distmin = Min(dist1, dist2);
924             if( dist1 != dist2 && distmin < MaxTolVert ) {
925               if (dist1 < dist2) {
926                 tolV = Max( dist1*1.00001, BRep_Tool::Tolerance(VF1) );
927                 B.UpdateVertex(VF1,tolV);
928                 V = VF1;
929               } else {
930                 tolV = Max( dist2*1.00001, BRep_Tool::Tolerance(VL1) );
931                 B.UpdateVertex(VL1,tolV);
932                 V = VL1;
933               }
934               
935               Standard_Real dista = Abs(a1-param1);
936               Standard_Real distb = Abs(b1-param1);
937               Standard_Boolean IsCutLine;
938               ModifE1 = CutEdge(edge1, (( dista > distb ) ? a1 : b1 ), param1, face, IsCutLine);
939               if (ModifE1)
940                 NbCut++;
941               //not needed split edge, if one of parts is too small
942               ModifE1 = ModifE1 || distmin < Precision::Confusion();
943             }
944             // analysis for edge2
945             Standard_Boolean ModifE2 = Standard_False;
946             TopoDS_Vertex VF2 = sae.FirstVertex(edge2);
947             gp_Pnt PVF2 = BRep_Tool::Pnt(VF2);
948             TopoDS_Vertex VL2 = sae.LastVertex(edge2);
949             gp_Pnt PVL2 = BRep_Tool::Pnt(VL2);
950             dist1 = pi2.Distance(PVF2);
951             dist2 = pi2.Distance(PVL2);
952             distmin = Min(dist1, dist2);
953             if( dist1 != dist2 && distmin < MaxTolVert ) {
954               if (dist1 < dist2) {
955                 tolV = Max( dist1*1.00001, BRep_Tool::Tolerance(VF2) );
956                 B.UpdateVertex(VF2,tolV);
957                 V = VF2;
958               } else {
959                 tolV = Max( dist2*1.00001, BRep_Tool::Tolerance(VL2) );
960                 B.UpdateVertex(VL2,tolV);
961                 V = VL2;
962               }
963
964               Standard_Real dista = Abs(a2-param2);
965               Standard_Real distb = Abs(b2-param2);
966               Standard_Boolean IsCutLine;
967               ModifE2 = CutEdge(edge2, (( dista > distb ) ? a2 : b2 ), param2, face, IsCutLine);
968               if (ModifE2)
969                 NbCut++;
970               //not needed split edge, if one of parts is too small
971               ModifE2 = ModifE2 || distmin < Precision::Confusion();
972             }
973             if( ModifE1 && !ModifE2 ) {
974               if(SplitEdge1(sewd, face, num2, param2, V, tolV, boxes)) {
975                 NbSplit++;
976                 num2--; 
977                 continue;
978                 
979               }
980             }
981             if( !ModifE1 && ModifE2 ) {
982               if(SplitEdge1(sewd, face, num1, param1, V, tolV, boxes)) {
983                 NbSplit++;
984                 num1--;
985                 break;
986               }
987             }
988             if( !ModifE1 && !ModifE2 ) {
989               gp_Pnt P0( (pi1.X()+pi2.X())/2, (pi1.Y()+pi2.Y())/2, (pi1.Z()+pi2.Z())/2 );
990               tolV = Max( (pi1.Distance(pi2)/2)*1.00001, Precision::Confusion() );
991               B.MakeVertex(V,P0,tolV);
992               MaxTolVert = Max(MaxTolVert,tolV);
993               Standard_Boolean isEdgeSplit2 = SplitEdge1(sewd, face, num2, param2,
994                                                          V, tolV, boxes);
995               if(isEdgeSplit2) {
996                 NbSplit++;
997                 num2--;
998               }
999               if(SplitEdge1(sewd, face, num1, param1, V, tolV, boxes)) {
1000                 NbSplit++;
1001                 num1--;
1002                 break;
1003               }
1004               if(isEdgeSplit2)
1005                 continue;
1006             }
1007           }
1008           if( Tr1.PositionOnCurve() == IntRes2d_Middle &&
1009              Tr2.PositionOnCurve() != IntRes2d_Middle ) {
1010             // find needed vertex from edge2 and split edge1 using it
1011             Standard_Real param1 = IP.ParamOnFirst(); 
1012             if(FindVertAndSplitEdge(param1, edge1, edge2, Crv1, MaxTolVert,
1013                                     num1, sewd, face, boxes, Standard_False) ) {
1014               NbSplit++;
1015               break;
1016             }
1017           }
1018           if( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1019              Tr2.PositionOnCurve() == IntRes2d_Middle ) {
1020             // find needed vertex from edge1 and split edge2 using it
1021             Standard_Real param2 = IP.ParamOnSecond(); 
1022             if(FindVertAndSplitEdge(param2, edge2, edge1, Crv2, MaxTolVert,
1023                                     num2, sewd, face, boxes, Standard_False) ) {
1024               NbSplit++;
1025               continue;
1026             }
1027           }
1028           if( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1029              Tr2.PositionOnCurve() != IntRes2d_Middle ) {
1030             // union vertexes
1031             if( UnionVertexes(sewd, edge1, edge2, num2, boxes, B2) )
1032               nbReplaced ++; //gka 06.09.04
1033           }
1034         }
1035         // intersection is segment
1036         if( Inter.NbSegments()==1 ) {
1037           IntRes2d_IntersectionSegment IS = Inter.Segment(1);
1038           if ( IS.HasFirstPoint() && IS.HasLastPoint() ) {
1039             Standard_Boolean IsModified1 = Standard_False;
1040             Standard_Boolean IsModified2 = Standard_False;
1041             TopoDS_Vertex NewV;
1042             BRep_Builder B;
1043             Standard_Real newtol=0.0;
1044             IntRes2d_IntersectionPoint IPF = IS.FirstPoint();
1045             Standard_Real p11 = IPF.ParamOnFirst();
1046             Standard_Real p21 = IPF.ParamOnSecond();
1047             IntRes2d_IntersectionPoint IPL = IS.LastPoint();
1048             Standard_Real p12 = IPL.ParamOnFirst();
1049             Standard_Real p22 = IPL.ParamOnSecond();
1050             gp_Pnt Pnt11 = GetPointOnEdge(edge1,sas,C1,p11);
1051             gp_Pnt Pnt12 = GetPointOnEdge(edge1,sas,C1,p12);
1052             gp_Pnt Pnt21 = GetPointOnEdge(edge2,sas,C2,p21);
1053             gp_Pnt Pnt22 = GetPointOnEdge(edge2,sas,C2,p22);
1054             // next string commented by skl 29.12.2004 for OCC7624
1055             //if( Pnt11.Distance(Pnt21)>myPreci || Pnt12.Distance(Pnt22)>myPreci ) continue;
1056             if( Pnt11.Distance(Pnt21)>MaxTolVert || Pnt12.Distance(Pnt22)>MaxTolVert ) continue;
1057             // analysis for edge1
1058             TopoDS_Vertex V1 = sae.FirstVertex(edge1);
1059             gp_Pnt PV1 = BRep_Tool::Pnt(V1);
1060             TopoDS_Vertex V2 = sae.LastVertex(edge1);
1061             gp_Pnt PV2 = BRep_Tool::Pnt(V2);
1062             //Standard_Real tol1 = BRep_Tool::Tolerance(V1);
1063             //Standard_Real tol2 = BRep_Tool::Tolerance(V2);
1064             //Standard_Real maxtol = Max(tol1,tol2);
1065             Standard_Real dist1 = Pnt11.Distance(PV1);
1066             Standard_Real dist2 = Pnt12.Distance(PV1);
1067             Standard_Real maxdist = Max(dist1,dist2);
1068             Standard_Real pdist;
1069             if(edge1.Orientation()==TopAbs_REVERSED)
1070               pdist = Max(Abs(b1-p11),Abs(b1-p12));
1071             else
1072               pdist = Max(Abs(a1-p11),Abs(a1-p12));
1073             if(maxdist<MaxTolVert || pdist<Abs(b1-a1)*0.01) {
1074             //if(maxdist<maxtol || pdist<Abs(b1-a1)*0.01) {
1075               newtol = maxdist;
1076               NewV = V1;
1077               IsModified1 = Standard_True;
1078             }
1079             dist1 = Pnt11.Distance(PV2);
1080             dist2 = Pnt12.Distance(PV2);
1081             maxdist = Max(dist1,dist2);
1082             if(edge1.Orientation()==TopAbs_REVERSED)
1083               pdist = Max(Abs(a1-p11),Abs(a1-p12));
1084             else
1085               pdist = Max(Abs(b1-p11),Abs(b1-p12));
1086             //if(maxdist<maxtol || pdist<Abs(b1-a1)*0.01) {
1087             if(maxdist<MaxTolVert || pdist<Abs(b1-a1)*0.01) {
1088               if( ( IsModified1 && maxdist<newtol ) || !IsModified1 ) {
1089                 newtol = maxdist;
1090                 NewV = V2;
1091                 IsModified1 = Standard_True;
1092               }
1093             }
1094             if(IsModified1) {
1095               // cut edge1 and update tolerance NewV
1096               Standard_Real dista = Abs(a1-p11)+Abs(a1-p12);
1097               Standard_Real distb = Abs(b1-p11)+Abs(b1-p12);
1098               Standard_Real pend,cut;
1099               if(dista>distb) pend=a1;
1100               else pend=b1;
1101               if(Abs(pend-p11)>Abs(pend-p12)) cut=p12;
1102               else cut=p11;
1103               Standard_Boolean IsCutLine;
1104               if (CutEdge(edge1, pend, cut, face, IsCutLine))
1105                 NbCut++;
1106               if(newtol>BRep_Tool::Tolerance(NewV)) {
1107                 B.UpdateVertex(NewV,newtol);
1108               }
1109               else newtol = BRep_Tool::Tolerance(NewV);
1110             }
1111             // analysis for edge2
1112             TopoDS_Vertex V12 = sae.FirstVertex(edge2);
1113             gp_Pnt PV12 = BRep_Tool::Pnt(V12);
1114             TopoDS_Vertex V22 = sae.LastVertex(edge2);
1115             gp_Pnt PV22 = BRep_Tool::Pnt(V22);
1116             //tol1 = BRep_Tool::Tolerance(V1);
1117             //tol2 = BRep_Tool::Tolerance(V2);
1118             //maxtol = Max(tol1,tol2);
1119             dist1 = Pnt21.Distance(PV12);
1120             dist2 = Pnt22.Distance(PV12);
1121             maxdist = Max(dist1,dist2);
1122             if(edge2.Orientation()==TopAbs_REVERSED)
1123               pdist = Max(Abs(b2-p21),Abs(b2-p22));
1124             else
1125               pdist = Max(Abs(a2-p21),Abs(a2-p22));
1126             //if(maxdist<maxtol || pdist<Abs(b2-a2)*0.01) {
1127             if(maxdist<MaxTolVert || pdist<Abs(b2-a2)*0.01) {
1128               newtol = maxdist;
1129               NewV = V12;
1130               IsModified2 = Standard_True;
1131             }
1132             dist1 = Pnt21.Distance(PV22);
1133             dist2 = Pnt22.Distance(PV22);
1134             maxdist = Max(dist1,dist2);
1135             if(edge2.Orientation()==TopAbs_REVERSED)
1136               pdist = Max(Abs(a2-p21),Abs(a2-p22));
1137             else
1138               pdist = Max(Abs(b2-p21),Abs(b2-p22));
1139             //if(maxdist<maxtol || pdist<Abs(b2-a2)*0.01) {
1140             if(maxdist<MaxTolVert || pdist<Abs(b2-a2)*0.01) {
1141               if( ( IsModified2 && maxdist<newtol ) || !IsModified2 ) {
1142                 newtol = maxdist;
1143                 NewV = V22;
1144                 IsModified2 = Standard_True;
1145               }
1146             }
1147             if(IsModified2) {
1148               // cut edge1 and update tolerance NewV
1149               Standard_Real dista = Abs(a2-p21)+Abs(a2-p22);
1150               Standard_Real distb = Abs(b2-p21)+Abs(b2-p22);
1151               Standard_Real pend,cut;
1152               if(dista>distb) pend=a2;
1153               else pend=b2;
1154               if(Abs(pend-p21)>Abs(pend-p22)) cut=p22;
1155               else cut=p21;
1156               Standard_Boolean IsCutLine;
1157               if (CutEdge(edge2, pend, cut, face, IsCutLine))
1158                 NbCut++;
1159               if(newtol>BRep_Tool::Tolerance(NewV)) {
1160                 B.UpdateVertex(NewV,newtol);
1161               }
1162               else newtol = BRep_Tool::Tolerance(NewV);
1163             }
1164
1165             if( IsModified1 && !IsModified2 ) {
1166               if(SplitEdge2(sewd, face, num2, p21, p22, NewV, newtol, boxes)) {
1167                 NbSplit++;
1168                 num2--;
1169                 continue;
1170               }
1171             }
1172             if( !IsModified1 && IsModified2 ) {
1173               if(SplitEdge2(sewd, face, num1, p11, p12, NewV, newtol, boxes)) {
1174                 NbSplit++;
1175                 num1--;
1176                 break;
1177               }
1178             }
1179             if( !IsModified1 && !IsModified2 ) {
1180               Standard_Real param1 = (p11+p12)/2;
1181               Standard_Real param2 = (p21+p22)/2;
1182               gp_Pnt Pnt10 = GetPointOnEdge(edge1,sas,C1,param1);
1183               gp_Pnt Pnt20 = GetPointOnEdge(edge2,sas,C2,param2);
1184               gp_Pnt P0( (Pnt10.X()+Pnt20.X())/2, (Pnt10.Y()+Pnt20.Y())/2,
1185                          (Pnt10.Z()+Pnt20.Z())/2 );
1186               dist1 = Max(Pnt11.Distance(P0),Pnt12.Distance(P0));
1187               dist2 = Max(Pnt21.Distance(P0),Pnt22.Distance(P0));
1188               Standard_Real tolV = Max(dist1,dist2);
1189               tolV = Max(tolV,Pnt10.Distance(Pnt20))*1.00001;
1190               Standard_Boolean FixSegment = Standard_True;
1191               if(tolV<MaxTolVert) {
1192                 // create new vertex and split each intersecting edge on two edges
1193                 B.MakeVertex(NewV,Pnt10,tolV);
1194                 if(SplitEdge2(sewd, face, num2, p21, p22, NewV, tolV, boxes)) {
1195                   NbSplit++;
1196                   num2--;
1197                 }
1198                 if(SplitEdge2(sewd, face, num1, p11, p12, NewV, tolV, boxes)) {
1199                   NbSplit++;
1200                   num1--;
1201                   break;
1202                 }
1203               }
1204               else if(FixSegment) {
1205                 //if( Abs(p12-p11)>Abs(b1-a1)/2 || Abs(p22-p21)>Abs(b2-a2)/2 ) {
1206                 // segment is big and we have to split each intersecting edge
1207                 // on 3 edges --> middle edge - edge based on segment
1208                 // after we can remove edges maked from segment
1209                 gp_Pnt P01( (Pnt11.X()+Pnt21.X())/2, (Pnt11.Y()+Pnt21.Y())/2,
1210                             (Pnt11.Z()+Pnt21.Z())/2 );
1211                 gp_Pnt P02( (Pnt12.X()+Pnt22.X())/2, (Pnt12.Y()+Pnt22.Y())/2,
1212                             (Pnt12.Z()+Pnt22.Z())/2 );
1213                 Standard_Real tolV1 = Max(Pnt11.Distance(P01),Pnt21.Distance(P01));
1214                 tolV1 = Max(tolV1,Precision::Confusion())*1.00001;
1215                 Standard_Real tolV2 = Max(Pnt12.Distance(P02),Pnt22.Distance(P02));
1216                 tolV2 = Max(tolV2,Precision::Confusion())*1.00001;
1217                 if( tolV1>MaxTolVert || tolV2>MaxTolVert ) continue; 
1218                 TopoDS_Vertex NewV1,NewV2;
1219 /*
1220                 // parameters for splitting: a1..p11..p12..b1 and a2..p21..p22..b2 ???
1221                 Standard_Integer nbseg1=3, nbseg2=3, kv1=0, kv2=0;
1222                 if(P01.Distance(PV1)<Max(tolV1,BRep_Tool::Tolerance(V1))) {
1223                   NewV1 = V1;
1224                   if(tolV1>BRep_Tool::Tolerance(V1))
1225                     B.UpdateVertex(NewV1,tolV1);
1226                   //akey1++;
1227                   nbseg1--;
1228                   kv1 = 1;
1229                 }
1230                 else if(P01.Distance(PV2)<Max(tolV1,BRep_Tool::Tolerance(V2))) {
1231                   NewV1 = V2;
1232                   if(tolV1>BRep_Tool::Tolerance(V2))
1233                     B.UpdateVertex(NewV1,tolV1);
1234                   //akey1++;
1235                   nbseg1--;
1236                   kv1 = 1;
1237                 }
1238 */
1239                 TopoDS_Edge tmpE,SegE;
1240                 // split edge1
1241                 Standard_Integer akey1=0, akey2=0;
1242                 Standard_Real newTolerance;
1243                 // analysis fo P01
1244                 newTolerance = Max(tolV1,BRep_Tool::Tolerance(V1));
1245                 if(P01.Distance(PV1)<newTolerance) {
1246                   B.MakeVertex(NewV1,BRep_Tool::Pnt(V1),newTolerance);
1247                   NewV1.Orientation(V1.Orientation());
1248                   akey1++;
1249                 }
1250                 newTolerance = Max(tolV1,BRep_Tool::Tolerance(V2));
1251                 if(P01.Distance(PV2)<newTolerance) {
1252                   B.MakeVertex(NewV1,BRep_Tool::Pnt(V2),newTolerance);
1253                   NewV1.Orientation(V2.Orientation());
1254                   akey1++;
1255                 }
1256                 // analysis fo P02
1257                 newTolerance = Max(tolV2,BRep_Tool::Tolerance(V1));
1258                 if(P02.Distance(PV1)<newTolerance) {
1259                   B.MakeVertex(NewV2,BRep_Tool::Pnt(V1),newTolerance);
1260                   NewV2.Orientation(V1.Orientation());
1261                   akey2++;
1262                 }
1263                 newTolerance = Max(tolV2,BRep_Tool::Tolerance(V2));
1264                 if(P02.Distance(PV2)<newTolerance) {
1265                   B.MakeVertex(NewV2,BRep_Tool::Pnt(V2),newTolerance);
1266                   NewV2.Orientation(V2.Orientation());
1267                   akey2++;
1268                 }
1269                 if( akey1>1 || akey2>1 ) continue;
1270                 Standard_Integer dnum1=0, numseg1=num1;
1271                 // prepare vertices
1272                 if(akey1==0) B.MakeVertex(NewV1,P01,tolV1);
1273                 if(akey2==0) B.MakeVertex(NewV2,P02,tolV2);
1274                 // split
1275                 if( akey1==0 && akey2>0 ) {
1276                   if(SplitEdge1(sewd, face, num1, p11, NewV1, tolV1, boxes)) {
1277                     NbSplit++;
1278                     dnum1=1;
1279                     numseg1=num1+1;
1280                   }
1281                 }
1282                 if( akey1>0 && akey2==0 ) {
1283                   if(SplitEdge1(sewd, face, num1, p12, NewV2, tolV2, boxes) ) {
1284                     NbSplit++;
1285                     dnum1=1;
1286                     numseg1=num1;
1287                   }
1288                 }
1289                 if( akey1==0 && akey2==0 ) {
1290                   if(SplitEdge1(sewd, face, num1, p11, NewV1, tolV1, boxes)) {
1291                     NbSplit++;
1292                     dnum1=1;
1293                   }
1294                   tmpE = sewd->Edge(num1);
1295                   Standard_Real a,b;
1296                   Handle(Geom2d_Curve) c2d;
1297                   sae.PCurve(tmpE,face,c2d,a,b,Standard_False);
1298                   if( (a-p12)*(b-p12)>0 ) { // p12 - external for [a,b] => split next edge
1299                     if(SplitEdge1(sewd, face, num1+1, p12, NewV2, tolV2, boxes) ) {
1300                       NbSplit++;
1301                       dnum1++;
1302                       numseg1=num1+1;
1303                     }
1304                   }
1305                   else {
1306                     if(SplitEdge1(sewd, face, num1, p12, NewV2, tolV2, boxes) ) {
1307                       NbSplit++;
1308                       dnum1++;
1309                       numseg1=num1+1;
1310                     }
1311                   }
1312                 }
1313                 //SegE = sewd->Edge(numseg1); // get edge from segment
1314                 // split edge2
1315                 // replace vertices if it is necessary
1316                 ShapeBuild_Edge sbe;
1317                 akey1=0, akey2=0;
1318
1319                 if(P01.Distance(PV12)<tolV1) {
1320                   tolV1 += P01.Distance(PV12);
1321                   B.UpdateVertex(NewV1,tolV1);
1322                   if(V12.Orientation()==NewV1.Orientation()) {
1323                     myContext->Replace(V12,NewV1);
1324                     V12 = NewV1;
1325                   }
1326                   else {
1327                     myContext->Replace(V12,NewV1.Reversed());
1328                     V12 = TopoDS::Vertex(NewV1.Reversed());
1329                   }
1330                   nbReplaced++; //gka 06.09.04
1331                   TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,NewV1,V22);
1332                   myContext->Replace(edge2,NewE);
1333                   sewd->Set(NewE,num2+dnum1);
1334                   boxes.Bind(NewE,B2); // update boxes
1335                   edge2 = NewE;
1336                   akey1 = 1;
1337                 }
1338                 if(P01.Distance(PV22)<tolV1) {
1339                   tolV1 += P01.Distance(PV22);
1340                   B.UpdateVertex(NewV1,tolV1);
1341                   if(V22.Orientation()==NewV1.Orientation()) {
1342                     myContext->Replace(V22,NewV1);
1343                     V22 = NewV1;
1344                   }
1345                   else {
1346                     myContext->Replace(V22,NewV1.Reversed());
1347                     V22 = TopoDS::Vertex(NewV1.Reversed());
1348                   }
1349                   nbReplaced++; //gka 06.09.04
1350                   TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V12,NewV1);
1351                   myContext->Replace(edge2,NewE);
1352                   sewd->Set(NewE,num2+dnum1);
1353                   boxes.Bind(NewE,B2); // update boxes
1354                   edge2 = NewE;
1355                   akey1 = 2;
1356                 }
1357                 if(P02.Distance(PV12)<tolV2) {
1358                   tolV2 += P02.Distance(PV12);
1359                   B.UpdateVertex(NewV2,tolV2);
1360                   if(V12.Orientation()==NewV2.Orientation()) {
1361                     myContext->Replace(V12,NewV2);
1362                     V12 = NewV2;
1363                   }
1364                   else {
1365                     myContext->Replace(V12,NewV2.Reversed());
1366                     V12 = TopoDS::Vertex(NewV2.Reversed());
1367                   }
1368                   nbReplaced++; //gka 06.09.04
1369                   TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,NewV2,V22);
1370                   myContext->Replace(edge2,NewE);
1371                   sewd->Set(NewE,num2+dnum1);
1372                   boxes.Bind(NewE,B2); // update boxes
1373                   edge2 = NewE;
1374                   akey2 = 1;
1375                 }
1376                 if(P02.Distance(PV22)<tolV2) {
1377                   tolV2 += P02.Distance(PV22);
1378                   B.UpdateVertex(NewV2,tolV2);
1379                   if(V22.Orientation()==NewV2.Orientation()) {
1380                     myContext->Replace(V22,NewV2);
1381                     V22 = NewV2;
1382                   }
1383                   else {
1384                     myContext->Replace(V22,NewV2.Reversed());
1385                     V22 = TopoDS::Vertex(NewV2.Reversed());
1386                   }
1387                   nbReplaced++; //gka 06.09.04
1388                   TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V12,NewV2);
1389                   myContext->Replace(edge2,NewE);
1390                   sewd->Set(NewE,num2+dnum1);
1391                   boxes.Bind(NewE,B2); // update boxes
1392                   edge2 = NewE;
1393                   akey2 = 2;
1394                 }
1395                 Standard_Integer dnum2=0, numseg2=num2+dnum1;
1396                 // split
1397                 if( akey1==0 && akey2>0 ) {
1398                   if(SplitEdge1(sewd, face, num2+dnum1, p21, NewV1, tolV1, boxes)) {
1399                     NbSplit++;
1400                     dnum2=1;
1401                     //numseg2=num2+dnum1+1;
1402                     numseg2=num2+dnum1;
1403                   }
1404                 }
1405                 if( akey1>0 && akey2==0 ) {
1406                   if(SplitEdge1(sewd, face, num2+dnum1, p22, NewV2, tolV2, boxes)) {
1407                     NbSplit++;
1408                     dnum2=1;
1409                     //numseg2=num2+dnum1;
1410                     numseg2=num2+dnum1+1;
1411                   }
1412                 }
1413                 if( akey1==0 && akey2==0 ) {
1414                   if(SplitEdge1(sewd, face, num2+dnum1, p21, NewV1, tolV1, boxes)) {
1415                     NbSplit++;
1416                     dnum2=1;
1417                   }
1418                   tmpE = sewd->Edge(num2+dnum1);
1419                   Standard_Real a,b;
1420                   Handle(Geom2d_Curve) c2d;
1421                   sae.PCurve(tmpE,face,c2d,a,b,Standard_False);
1422                   if( (a-p22)*(b-p22)>0 ) { // p22 - external for [a,b] => split next edge
1423                     if(SplitEdge1(sewd, face, num2+dnum1+dnum2, p22, NewV2, tolV2, boxes) ) {
1424                       NbSplit++;
1425                       numseg2=num2+dnum1+dnum2;
1426                       dnum2++;
1427                     }
1428                   }
1429                   else {
1430                     if(SplitEdge1(sewd, face, num2+dnum1, p22, NewV2, tolV2, boxes) ) {
1431                       NbSplit++;
1432                       dnum2++;
1433                       numseg2=num2+dnum1+1;
1434                     }
1435                   }
1436                 }
1437                 // remove segment
1438                 sewd->Remove(numseg2);
1439                 sewd->Remove(numseg1);
1440                 NbRemoved = NbRemoved+2;
1441                 //num1--;
1442                 //break;
1443               }
1444             }
1445           }
1446         }
1447       }
1448     }
1449   }
1450   isDone = (NbSplit || NbCut || nbReplaced || NbRemoved);
1451   return isDone;
1452 }
1453
1454
1455 //=======================================================================
1456 //function : FixIntersectingWires
1457 //purpose  : 
1458 //=======================================================================
1459
1460 Standard_Boolean ShapeFix_IntersectionTool::FixIntersectingWires
1461   (TopoDS_Face& face) const
1462 {
1463   if(myContext.IsNull() || face.IsNull()) return Standard_False;
1464   //TopoDS_Shape S = context->Apply(face);
1465   //TopoDS_Shape SF = TopoDS::Face(S);
1466   TopoDS_Shape SF = face;
1467   TopAbs_Orientation ori = face.Orientation();
1468   TopTools_SequenceOfShape SeqWir;
1469   TopTools_SequenceOfShape SeqNMShapes;
1470   for( TopoDS_Iterator iter(SF,Standard_False); iter.More(); iter.Next() ) { 
1471     if(iter.Value().ShapeType() != TopAbs_WIRE ||
1472        (iter.Value().Orientation() != TopAbs_FORWARD && 
1473         iter.Value().Orientation() != TopAbs_REVERSED)) {
1474       SeqNMShapes.Append(iter.Value());
1475       continue;
1476     }
1477     TopoDS_Wire wire = TopoDS::Wire(iter.Value());
1478     SeqWir.Append(wire);
1479   }
1480   if(SeqWir.Length()<2) return Standard_False;//gka 06.09.04
1481
1482   Standard_Real MaxTolVert=0.0;
1483   for(TopExp_Explorer exp(SF,TopAbs_VERTEX); exp.More(); exp.Next()) { 
1484     Standard_Real tolV = BRep_Tool::Tolerance(TopoDS::Vertex(exp.Current()));
1485     MaxTolVert = Max(MaxTolVert,tolV);
1486   }
1487   Standard_Boolean isDone = Standard_False; //gka 06.09.04
1488   ShapeAnalysis_Edge sae;
1489   Handle(ShapeAnalysis_Surface) sas = new ShapeAnalysis_Surface (BRep_Tool::Surface (face));
1490
1491   // precompute edge boxes for all wires
1492   NCollection_Sequence<ShapeFix_DataMapOfShapeBox2d> aSeqWirEdgeBoxes;
1493   NCollection_Sequence<Bnd_Box2d> aSeqWirBoxes;
1494   for (Standard_Integer n = 1; n <= SeqWir.Length(); n++)
1495   {
1496     const TopoDS_Wire& aWire = TopoDS::Wire (SeqWir.Value (n));
1497     Handle(ShapeExtend_WireData) aSewd = new ShapeExtend_WireData (aWire);
1498     ShapeFix_DataMapOfShapeBox2d aBoxes;
1499     Bnd_Box2d aTotalBox = CreateBoxes2d (aSewd, face, aBoxes);
1500     aSeqWirEdgeBoxes.Append (aBoxes);
1501     aSeqWirBoxes.Append (aTotalBox);
1502   }
1503
1504   for(Standard_Integer n1=1; n1<=SeqWir.Length()-1; n1++) { 
1505     TopoDS_Wire wire1 = TopoDS::Wire(SeqWir.Value(n1));
1506     Handle(ShapeExtend_WireData) sewd1 = new ShapeExtend_WireData(wire1);
1507     ShapeFix_DataMapOfShapeBox2d& boxes1 = aSeqWirEdgeBoxes.ChangeValue (n1);
1508     Bnd_Box2d aBox1 = aSeqWirBoxes (n1);
1509     for(Standard_Integer n2=n1+1; n2<=SeqWir.Length(); n2++) { 
1510       TopoDS_Wire wire2 = TopoDS::Wire(SeqWir.Value(n2));
1511       Handle(ShapeExtend_WireData) sewd2 = new ShapeExtend_WireData(wire2);
1512       ShapeFix_DataMapOfShapeBox2d& boxes2 = aSeqWirEdgeBoxes.ChangeValue (n2);
1513       Bnd_Box2d aBox2 = aSeqWirBoxes (n2);
1514       if (!aBox1.IsVoid() && !aBox2.IsVoid() && aBox1.IsOut (aBox2))
1515       {
1516         continue;
1517       }
1518       // detect possible intersections:
1519       Standard_Integer NbModif=0;
1520       Standard_Integer nbReplaced =0;//gka 06.09.04
1521       Standard_Boolean hasModifWire = Standard_False; //gka 06.09.04
1522       for(Standard_Integer num1 = 1; num1<=sewd1->NbEdges() && NbModif<30; num1++) {
1523         // for each edge from first wire
1524         TopoDS_Edge edge1 = sewd1->Edge(num1); //gka 06.09.04
1525
1526         for(Standard_Integer num2 = 1; num2<=sewd2->NbEdges() && NbModif<30; num2++) {
1527           // for each edge from second wire
1528           TopoDS_Edge edge2 = sewd2->Edge(num2);
1529           if(edge1.IsSame(edge2)) continue;
1530           if( BRep_Tool::Degenerated(edge1) || BRep_Tool::Degenerated(edge2) ) continue;
1531           if( !boxes1.IsBound(edge1) || !boxes2.IsBound(edge2) ) continue;
1532           Bnd_Box2d B1 = boxes1.Find(edge1);
1533           Bnd_Box2d B2 = boxes2.Find(edge2);
1534           if(!B1.IsOut(B2)) {
1535             // intersection is possible...
1536             Standard_Real a1, b1, a2, b2;
1537             Handle(Geom2d_Curve) Crv1, Crv2;
1538             if( !sae.PCurve(edge1, face, Crv1, a1, b1, Standard_False) ) 
1539               continue; //return Standard_False; gka 06.09.04
1540             if( !sae.PCurve(edge2, face, Crv2, a2, b2, Standard_False) ) 
1541               continue; //return Standard_False;gka 06.09.04
1542             Standard_Real tolint = 1.0e-10; 
1543             Geom2dAdaptor_Curve C1(Crv1), C2(Crv2);
1544             IntRes2d_Domain d1(C1.Value(a1),a1,tolint,C1.Value(b1),b1,tolint);
1545             IntRes2d_Domain d2(C2.Value(a2),a2,tolint,C2.Value(b2),b2,tolint);
1546             Geom2dInt_GInter Inter;
1547             Inter.Perform( C1, d1, C2, d2, tolint, tolint );
1548             if(!Inter.IsDone()) continue;
1549             // intersection is point
1550             if( Inter.NbPoints()>0 && Inter.NbPoints()<3 ) {
1551               IntRes2d_IntersectionPoint IP;
1552               IntRes2d_Transition Tr1, Tr2;
1553               SelectIntPnt(Inter,IP,Tr1,Tr2);
1554               if( Tr1.PositionOnCurve() == IntRes2d_Middle &&
1555                  Tr2.PositionOnCurve() == IntRes2d_Middle ) {
1556                 // create new vertex and split both edges
1557                 Standard_Real param1 = IP.ParamOnFirst(); 
1558                 Standard_Real param2 = IP.ParamOnSecond();
1559                 gp_Pnt pi1 = GetPointOnEdge(edge1,sas,C1,param1);
1560                 gp_Pnt pi2 = GetPointOnEdge(edge2,sas,C2,param2);
1561                 gp_Pnt P0( (pi1.X()+pi2.X())/2, (pi1.Y()+pi2.Y())/2, (pi1.Z()+pi2.Z())/2 );
1562                 BRep_Builder B;
1563                 TopoDS_Vertex V;
1564                 Standard_Real tolV = Max( (pi1.Distance(pi2)/2)*1.00001, Precision::Confusion() );
1565                 B.MakeVertex(V,P0,tolV);
1566                 MaxTolVert = Max(MaxTolVert,tolV);
1567                 Standard_Boolean isSplitEdge2 = SplitEdge1(sewd2, face, num2, param2,
1568                                                            V, tolV, boxes2);
1569                 if(isSplitEdge2) {
1570                   NbModif++;
1571                   num2--;
1572                 }
1573                 if(SplitEdge1(sewd1, face, num1, param1, V, tolV, boxes1)) {
1574                   NbModif++;
1575                   num1--;
1576                   break;
1577                 }
1578                 if(isSplitEdge2)
1579                   continue;
1580               }
1581               if( Tr1.PositionOnCurve() == IntRes2d_Middle &&
1582                  Tr2.PositionOnCurve() != IntRes2d_Middle ) {
1583                 // find needed vertex from edge2 and split edge1 using it
1584                 Standard_Real param1 = IP.ParamOnFirst(); 
1585                 if(FindVertAndSplitEdge(param1, edge1, edge2, Crv1, MaxTolVert,
1586                                         num1, sewd1, face, boxes1, Standard_True) ) {
1587                   NbModif++;
1588                   break;
1589                 }
1590               }
1591               if( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1592                  Tr2.PositionOnCurve() == IntRes2d_Middle ) {
1593                 // find needed vertex from edge1 and split edge2 using it
1594                 Standard_Real param2 = IP.ParamOnSecond(); 
1595                 if(FindVertAndSplitEdge(param2, edge2, edge1, Crv2, MaxTolVert,
1596                                         num2, sewd2, face, boxes2, Standard_True) ) {
1597                   NbModif++;
1598                   continue;
1599                 }
1600               }
1601               if( Tr1.PositionOnCurve() != IntRes2d_Middle &&
1602                  Tr2.PositionOnCurve() != IntRes2d_Middle ) {
1603                 // union vertexes
1604                 if( UnionVertexes(sewd2, edge1, edge2, num2, boxes2, B2) )
1605                   nbReplaced ++; //gka 06.09.04
1606               }
1607             }
1608             hasModifWire = (hasModifWire || NbModif || nbReplaced);
1609             // intersection is segment
1610             if( Inter.NbSegments()==1 ) {
1611               IntRes2d_IntersectionSegment IS = Inter.Segment(1);
1612               if ( IS.HasFirstPoint() && IS.HasLastPoint() ) {
1613                 Standard_Boolean IsModified1 = Standard_False;
1614                 Standard_Boolean IsModified2 = Standard_False;
1615                 TopoDS_Vertex NewV;
1616                 BRep_Builder B;
1617                 Standard_Real newtol=0.0;
1618                 IntRes2d_IntersectionPoint IPF = IS.FirstPoint();
1619                 Standard_Real p11 = IPF.ParamOnFirst();
1620                 Standard_Real p21 = IPF.ParamOnSecond();
1621                 IntRes2d_IntersectionPoint IPL = IS.LastPoint();
1622                 Standard_Real p12 = IPL.ParamOnFirst();
1623                 Standard_Real p22 = IPL.ParamOnSecond();
1624                 gp_Pnt Pnt11 = GetPointOnEdge(edge1,sas,C1,p11);
1625                 gp_Pnt Pnt12 = GetPointOnEdge(edge1,sas,C1,p12);
1626                 gp_Pnt Pnt21 = GetPointOnEdge(edge2,sas,C2,p21);
1627                 gp_Pnt Pnt22 = GetPointOnEdge(edge2,sas,C2,p22);
1628
1629                 // analysis for edge1
1630                 TopoDS_Vertex V1 = sae.FirstVertex(edge1);
1631                 gp_Pnt PV1 = BRep_Tool::Pnt(V1);
1632                 TopoDS_Vertex V2 = sae.LastVertex(edge1);
1633                 gp_Pnt PV2 = BRep_Tool::Pnt(V2);
1634                 Standard_Real dist1 = Pnt11.Distance(PV1);
1635                 Standard_Real dist2 = Pnt12.Distance(PV1);
1636                 Standard_Real maxdist = Max(dist1,dist2);
1637                 Standard_Real pdist;
1638                 if(edge1.Orientation()==TopAbs_REVERSED)
1639                   pdist = Max(Abs(b1-p11),Abs(b1-p12));
1640                 else
1641                   pdist = Max(Abs(a1-p11),Abs(a1-p12));
1642                 if(maxdist<MaxTolVert || pdist<Abs(b1-a1)*0.01) {
1643                   newtol = maxdist;
1644                   NewV = V1;
1645                   IsModified1 = Standard_True;
1646                 }
1647                 dist1 = Pnt11.Distance(PV2);
1648                 dist2 = Pnt12.Distance(PV2);
1649                 maxdist = Max(dist1,dist2);
1650                 if(edge1.Orientation()==TopAbs_REVERSED)
1651                   pdist = Max(Abs(a1-p11),Abs(a1-p12));
1652                 else
1653                   pdist = Max(Abs(b1-p11),Abs(b1-p12));
1654                 if(maxdist<MaxTolVert || pdist<Abs(b1-a1)*0.01) {
1655                   if( ( IsModified1 && maxdist<newtol ) || !IsModified1 ) {
1656                     newtol = maxdist;
1657                     NewV = V2;
1658                     IsModified1 = Standard_True;
1659                   }
1660                 }
1661                 if(IsModified1) {
1662                   // cut edge1 and update tolerance NewV
1663                   Standard_Real dista = Abs(a1-p11)+Abs(a1-p12);
1664                   Standard_Real distb = Abs(b1-p11)+Abs(b1-p12);
1665                   Standard_Real pend,cut;
1666                   if(dista>distb) pend=a1;
1667                   else pend=b1;
1668                   if(Abs(pend-p11)>Abs(pend-p12)) cut=p12;
1669                     else cut=p11;
1670                   Standard_Boolean IsCutLine;
1671                   if(!CutEdge(edge1, pend, cut, face, IsCutLine))
1672                   {
1673                     IsModified1 = Standard_False;
1674                     continue;
1675                   }
1676                   if(newtol>BRep_Tool::Tolerance(NewV)) {
1677                     B.UpdateVertex(NewV,newtol*1.00001);
1678                   }
1679                 }
1680
1681                 // analysis for edge2
1682                 TopoDS_Vertex V12 = sae.FirstVertex(edge2);
1683                 gp_Pnt PV12 = BRep_Tool::Pnt(V12);
1684                 TopoDS_Vertex V22 = sae.LastVertex(edge2);
1685                 gp_Pnt PV22 = BRep_Tool::Pnt(V22);
1686                 dist1 = Pnt21.Distance(PV12);
1687                 dist2 = Pnt22.Distance(PV12);
1688                 maxdist = Max(dist1,dist2);
1689                 if(edge2.Orientation()==TopAbs_REVERSED)
1690                   pdist = Max(Abs(b2-p21),Abs(b2-p22));
1691                 else
1692                   pdist = Max(Abs(a2-p21),Abs(a2-p22));
1693                 if(maxdist<MaxTolVert || pdist<Abs(b2-a2)*0.01) {
1694                   newtol = maxdist;
1695                   NewV = V12;
1696                   IsModified2 = Standard_True;
1697                 }
1698                 dist1 = Pnt21.Distance(PV22);
1699                 dist2 = Pnt22.Distance(PV22);
1700                 maxdist = Max(dist1,dist2);
1701                 if(edge2.Orientation()==TopAbs_REVERSED)
1702                   pdist = Max(Abs(a2-p21),Abs(a2-p22));
1703                 else
1704                   pdist = Max(Abs(b2-p21),Abs(b2-p22));
1705                 if(maxdist<MaxTolVert || pdist<Abs(b2-a2)*0.01) {
1706                   if( ( IsModified2 && maxdist<newtol ) || !IsModified2 ) {
1707                     newtol = maxdist;
1708                     NewV = V22;
1709                     IsModified2 = Standard_True;
1710                   }
1711                 }
1712                 if(IsModified2) {
1713                   // cut edge1 and update tolerance NewV
1714                   Standard_Real dista = Abs(a2-p21)+Abs(a2-p22);
1715                   Standard_Real distb = Abs(b2-p21)+Abs(b2-p22);
1716                   Standard_Real pend,cut;
1717                   if(dista>distb) pend=a2;
1718                   else pend=b2;
1719                   if(Abs(pend-p21)>Abs(pend-p22)) cut=p22;
1720                   else cut=p21;
1721                   Standard_Boolean IsCutLine;
1722                   if(!CutEdge(edge2, pend, cut, face, IsCutLine))
1723                   {
1724                     IsModified2 = Standard_False;
1725                     continue;
1726
1727                   }
1728                   if(newtol>BRep_Tool::Tolerance(NewV)) {
1729                     B.UpdateVertex(NewV,newtol*1.00001);
1730                   }
1731                 }
1732
1733                 if( IsModified1 || IsModified2 ) {
1734                   //necessary to make intersect with the same pair of the edges once again with modified ranges
1735                   num2--;
1736                   hasModifWire = Standard_True; //gka 06.09.04
1737                   continue;
1738                 }
1739                 else {
1740                   // create new vertex and split edge1 and edge2 using it
1741                   if( Abs(p12-p11)>Abs(b1-a1)/2 || Abs(p22-p21)>Abs(b2-a2)/2 ) {
1742                     // segment is big and we have to split each intersecting edge
1743                     // on 3 edges --> middle edge - edge based on segment
1744                     gp_Pnt P01( (Pnt11.X()+Pnt21.X())/2, (Pnt11.Y()+Pnt21.Y())/2,
1745                                 (Pnt11.Z()+Pnt21.Z())/2 );
1746                     gp_Pnt P02( (Pnt12.X()+Pnt22.X())/2, (Pnt12.Y()+Pnt22.Y())/2,
1747                                 (Pnt12.Z()+Pnt22.Z())/2 );
1748                     Standard_Real tolV1 = Max(Pnt11.Distance(P01),Pnt21.Distance(P01));
1749                     tolV1 = Max(tolV1,Precision::Confusion())*1.00001;
1750                     Standard_Real tolV2 = Max(Pnt12.Distance(P02),Pnt22.Distance(P02));
1751                     tolV2 = Max(tolV2,Precision::Confusion())*1.00001;
1752                     if( tolV1>MaxTolVert || tolV2>MaxTolVert ) continue; 
1753                     
1754                     hasModifWire = Standard_True; //gka 06.09.04
1755                     TopoDS_Vertex NewV1,NewV2;
1756                     TopoDS_Edge tmpE,SegE;
1757                     // split edge1
1758                     Standard_Integer akey1=0, akey2=0;
1759                     // analysis fo P01
1760                     if(P01.Distance(PV1)<Max(tolV1,BRep_Tool::Tolerance(V1))) {
1761                       NewV1 = V1;
1762                       if(tolV1>BRep_Tool::Tolerance(V1))
1763                         B.UpdateVertex(NewV1,tolV1);
1764                       akey1++;
1765                     }
1766                     if(P01.Distance(PV2)<Max(tolV1,BRep_Tool::Tolerance(V2))) {
1767                       NewV1 = V2;
1768                       if(tolV1>BRep_Tool::Tolerance(V2))
1769                         B.UpdateVertex(NewV1,tolV1);
1770                       akey1++;
1771                     }
1772                     // analysis fo P02
1773                     if(P02.Distance(PV1)<Max(tolV2,BRep_Tool::Tolerance(V1))) {
1774                       NewV2 = V1;
1775                       if(tolV2>BRep_Tool::Tolerance(V1))
1776                         B.UpdateVertex(NewV2,tolV2);
1777                       akey2++;
1778                     }
1779                     if(P02.Distance(PV2)<Max(tolV2,BRep_Tool::Tolerance(V2))) {
1780                       NewV2 = V2;
1781                       if(tolV2>BRep_Tool::Tolerance(V2))
1782                         B.UpdateVertex(NewV2,tolV2);
1783                       akey2++;
1784                     }
1785                     if( akey1>1 || akey2>1 ) continue;
1786                     // prepare vertices
1787                     if(akey1==0) B.MakeVertex(NewV1,P01,tolV1);
1788                     if(akey2==0) B.MakeVertex(NewV2,P02,tolV2);
1789                     // split
1790                     Standard_Integer numseg1=num1;
1791                     if( akey1==0 && akey2>0 ) {
1792                       if(SplitEdge1(sewd1, face, num1, p11, NewV1, tolV1, boxes1)) {
1793                         NbModif++;
1794                         numseg1=num1+1;
1795                       }
1796                     }
1797                     if( akey1>0 && akey2==0 ) {
1798                       if(SplitEdge1(sewd1, face, num1, p12, NewV2, tolV2, boxes1) ) {
1799                         NbModif++;
1800                         numseg1=num1;
1801                       }
1802                     }
1803                     if( akey1==0 && akey2==0 ) {
1804                       if(SplitEdge1(sewd1, face, num1, p11, NewV1, tolV1, boxes1)) {
1805                         NbModif++;
1806                       }
1807                       tmpE = sewd1->Edge(num1);
1808                       Standard_Real a,b;
1809                       Handle(Geom2d_Curve) c2d;
1810                       sae.PCurve(tmpE,face,c2d,a,b,Standard_False);
1811                       if( (a-p12)*(b-p12)>0 ) { // p12 - external for [a,b] => split next edge
1812                         if(SplitEdge1(sewd1, face, num1+1, p12, NewV2, tolV2, boxes1) ) {
1813                           NbModif++;
1814                           numseg1=num1+1;
1815                         }
1816                       }
1817                       else {
1818                         if(SplitEdge1(sewd1, face, num1, p12, NewV2, tolV2, boxes1) ) {
1819                           NbModif++;
1820                           numseg1=num1+1;
1821                         }
1822                       }
1823                     }
1824                     SegE = sewd1->Edge(numseg1); // get edge from segment
1825                     // split edge2
1826                     // replace vertices if it is necessary
1827                     ShapeBuild_Edge sbe;
1828                     akey1=0, akey2=0;
1829                     if(P01.Distance(PV12)<tolV1) {
1830                       tolV1 += P01.Distance(PV12);
1831                       B.UpdateVertex(NewV1,tolV1);
1832                       V12 = NewV1;
1833                       TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,NewV1,V22);
1834                       myContext->Replace(edge2,NewE);
1835                       sewd2->Set(NewE,num2);
1836                       boxes2.Bind(NewE,B2); // update boxes2
1837                       edge2 = NewE;
1838                       akey1 = 1;
1839                     }
1840                     if(P01.Distance(PV22)<tolV1) {
1841                       tolV1 += P01.Distance(PV22);
1842                       B.UpdateVertex(NewV1,tolV1);
1843                       V22 = NewV1;
1844                       TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V12,NewV1);
1845                       myContext->Replace(edge2,NewE);
1846                       sewd2->Set(NewE,num2);
1847                       boxes2.Bind(NewE,B2); // update boxes2
1848                       edge2 = NewE;
1849                       akey1 = 2;
1850                     }
1851                     if(P02.Distance(PV12)<tolV2) {
1852                       tolV2 += P02.Distance(PV12);
1853                       B.UpdateVertex(NewV2,tolV2);
1854                       V12 = NewV2;
1855                       TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,NewV2,V22);
1856                       myContext->Replace(edge2,NewE);
1857                       sewd2->Set(NewE,num2);
1858                       boxes2.Bind(NewE,B2); // update boxes2
1859                       edge2 = NewE;
1860                       akey2 = 1;
1861                     }
1862                     if(P02.Distance(PV22)<tolV2) {
1863                       tolV2 += P02.Distance(PV22);
1864                       B.UpdateVertex(NewV2,tolV2);
1865                       V22 = NewV2;
1866                       TopoDS_Edge NewE = sbe.CopyReplaceVertices(edge2,V12,NewV2);
1867                       myContext->Replace(edge2,NewE);
1868                       sewd2->Set(NewE,num2);
1869                       boxes2.Bind(NewE,B2); // update boxes2
1870                       edge2 = NewE;
1871                       akey2 = 2;
1872                     }
1873                     // split
1874                     Standard_Integer numseg2=num2;
1875                     if( akey1==0 && akey2>0 ) {
1876                       if(SplitEdge1(sewd2, face, num2, p21, NewV1, tolV1, boxes2)) {
1877                         NbModif++;
1878                         numseg2=num2+1;
1879                       }
1880                     }
1881                     if( akey1>0 && akey2==0 ) {
1882                       if(SplitEdge1(sewd2, face, num2, p22, NewV2, tolV2, boxes2)) {
1883                         NbModif++;
1884                         numseg2=num2;
1885                       }
1886                     }
1887                     if( akey1==0 && akey2==0 ) {
1888                       if(SplitEdge1(sewd2, face, num2, p21, NewV1, tolV1, boxes2)) {
1889                         NbModif++;
1890                         numseg2=num2+1;
1891                       }
1892                       tmpE = sewd2->Edge(num2);
1893                       Standard_Real a,b;
1894                       Handle(Geom2d_Curve) c2d;
1895                       sae.PCurve(tmpE,face,c2d,a,b,Standard_False);
1896                       if( (a-p22)*(b-p22)>0 ) { // p22 - external for [a,b] => split next edge
1897                         if(SplitEdge1(sewd2, face, num2+1, p22, NewV2, tolV2, boxes2) ) {
1898                           NbModif++;
1899                           numseg2=num2+1;
1900                         }
1901                       }
1902                       else {
1903                         if(SplitEdge1(sewd2, face, num2, p22, NewV2, tolV2, boxes2) ) {
1904                           NbModif++;
1905                           numseg2=num2+1;
1906                         }
1907                       }
1908                     }
1909                     tmpE = sewd2->Edge(numseg2);
1910                     boxes2.Bind(tmpE,boxes1.Find(SegE)); // update boxes2
1911                     if(!sae.FirstVertex(SegE).IsSame(sae.FirstVertex(tmpE))) {
1912                       SegE.Reverse();
1913                     }
1914                     myContext->Replace(tmpE,SegE);
1915                     sewd2->Set(SegE,numseg2);
1916                     num1--;
1917                     break;
1918                   }
1919                   else {
1920                     // split each intersecting edge on two edges
1921                     gp_Pnt P0( (Pnt11.X()+Pnt12.X())/2, (Pnt11.Y()+Pnt12.Y())/2,
1922                                (Pnt11.Z()+Pnt12.Z())/2 );
1923                     Standard_Real param1 = (p11+p12)/2;
1924                     Standard_Real param2 = (p21+p22)/2;
1925                     gp_Pnt Pnt10 = GetPointOnEdge(edge1,sas,C1,param1);
1926                     gp_Pnt Pnt20 = GetPointOnEdge(edge2,sas,C2,param2);
1927                     dist1 = Max(Pnt11.Distance(P0),Pnt12.Distance(Pnt10));
1928                     dist2 = Max(Pnt21.Distance(P0),Pnt22.Distance(Pnt10));
1929                     Standard_Real tolV = Max(dist1,dist2);
1930                     tolV = Max(tolV,Pnt10.Distance(Pnt20))*1.00001;
1931                     B.MakeVertex(NewV,Pnt10,tolV);
1932                     MaxTolVert = Max(MaxTolVert,tolV);
1933                     hasModifWire = Standard_True;
1934                     if(SplitEdge2(sewd2, face, num2, p21, p22, NewV, tolV, boxes2)) {
1935                       NbModif++;
1936                       num2--;
1937                     }
1938                     if(SplitEdge2(sewd1, face, num1, p11, p12, NewV, tolV, boxes1)) {
1939                       NbModif++;
1940                       num1--;
1941                       break;
1942                     }
1943                   }
1944                 }
1945               }
1946             } // end if(Inter.NbSegments()==1)
1947
1948           }
1949         }
1950       }
1951       if(hasModifWire) {
1952         isDone = Standard_True;
1953         SeqWir.SetValue(n1,sewd1->Wire());
1954         myContext->Replace( wire1, sewd1->Wire() );
1955         wire1 = sewd1->Wire();
1956         //recompute boxes for wire1
1957         boxes1.Clear();
1958         Bnd_Box2d aNewBox1 = CreateBoxes2d (sewd1, face, boxes1);
1959         aSeqWirBoxes.SetValue (n1, aNewBox1);
1960         SeqWir.SetValue(n2,sewd2->Wire());
1961         myContext->Replace( wire2, sewd2->Wire() );
1962         wire2 = sewd2->Wire();
1963         //recompute boxes for wire2
1964         boxes2.Clear();
1965         Bnd_Box2d aNewBox2 = CreateBoxes2d (sewd2, face, boxes2);
1966         aSeqWirBoxes.SetValue (n2, aNewBox2);
1967       }
1968
1969     }
1970   }
1971
1972   if(isDone) {
1973     // update face
1974     TopoDS_Shape emptyCopied = face.EmptyCopied();
1975     TopoDS_Face newface = TopoDS::Face (emptyCopied);
1976     newface.Orientation(TopAbs_FORWARD);
1977     BRep_Builder B;
1978     Standard_Integer i=1;
1979     for(i=1  ; i<=SeqWir.Length(); i++) { 
1980       TopoDS_Wire wire = TopoDS::Wire(SeqWir.Value(i));
1981       B.Add(newface,wire);
1982     }
1983     for(i=1 ; i<=SeqNMShapes.Length(); i++) { 
1984       TopoDS_Shape aNMS = SeqNMShapes.Value(i);
1985       B.Add(newface,aNMS);
1986     }
1987     newface.Orientation(ori);
1988     myContext->Replace(face,newface);
1989     face = newface;
1990   }
1991   return isDone;
1992 }
1993