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