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