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