588cc13c8c9d44e3f88302ed11a2d1e85ac2cc7b
[occt.git] / src / BRepOffset / BRepOffset_Inter2d.cxx
1 // Created on: 1996-09-03
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 //  Modified by skv - Wed Dec 24 18:08:39 2003 OCC4455
18
19 #include <stdio.h>
20
21 #include <BRepOffset_Inter2d.ixx>
22 #include <BRepAlgo_AsDes.hxx>
23 #include <BRepOffset_Offset.hxx>
24 #include <BRepOffset_Tool.hxx>
25
26 #include <BRep_Builder.hxx>
27 #include <BRep_Tool.hxx>
28 #include <BRepLib_MakeVertex.hxx>
29 #include <BRepAdaptor_Curve.hxx>
30 #include <BRepAdaptor_Surface.hxx>
31 #include <BRepTools_WireExplorer.hxx>
32 #include <TopExp.hxx>
33 #include <TopExp_Explorer.hxx>
34 #include <TopoDS_Iterator.hxx>
35
36 #include <TopoDS.hxx>
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Vertex.hxx>
39 #include <TopoDS_Wire.hxx>
40 #include <TopTools_ListOfShape.hxx>
41 #include <TopTools_ListIteratorOfListOfShape.hxx>
42 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
43 #include <gp_Pnt.hxx>
44 #include <BRep_TEdge.hxx>
45 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
46 #include <BRep_CurveRepresentation.hxx>
47 #include <BRep_GCurve.hxx>
48
49 #include <Geom_Line.hxx>
50 #include <Geom_Plane.hxx>
51 #include <Geom_TrimmedCurve.hxx>
52 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
53 #include <Precision.hxx>
54 #include <Geom2d_TrimmedCurve.hxx>
55 #include <Geom2d_BezierCurve.hxx>
56 #include <Geom2d_BSplineCurve.hxx>
57 #include <Geom2d_Line.hxx>
58 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
59
60 #include <BRepLib.hxx>
61 #include <BRepAdaptor_Curve2d.hxx>
62 #include <Adaptor3d_HSurface.hxx>
63 #include <Adaptor3d_CurveOnSurface.hxx>
64 #include <Geom_BSplineSurface.hxx>
65 #include <Geom_CylindricalSurface.hxx>
66 #include <Geom_ConicalSurface.hxx>
67 #include <Adaptor2d_HCurve2d.hxx>
68 #include <TColGeom2d_SequenceOfCurve.hxx>
69 #include <Geom2dInt_GInter.hxx>
70 #include <IntRes2d_IntersectionPoint.hxx>
71 #include <IntRes2d_IntersectionSegment.hxx>
72 #include <GeomAPI_ProjectPointOnCurve.hxx>
73 #include <GeomAdaptor_Surface.hxx>
74 #include <Geom2dAdaptor_HCurve.hxx>
75 #include <GeomAdaptor_HSurface.hxx>
76 #include <GeomLib.hxx>
77 #include <GeomProjLib.hxx>
78 #include <TColgp_SequenceOfPnt.hxx>
79 #include <TColgp_Array1OfPnt2d.hxx>
80 #include <Bnd_Box.hxx>
81 #include <BndLib_Add3dCurve.hxx>
82 #include <BRepTools.hxx>
83
84 #ifdef DRAW 
85 #include <DBRep.hxx>
86 Standard_IMPORT extern Standard_Boolean AffichInt2d;
87 static Standard_Integer NbF2d = 0;
88 static Standard_Integer NbE2d = 0;
89 static Standard_Integer NbNewVertices  = 0;
90 #endif
91
92 //=======================================================================
93 //function : CommonVertex
94 //purpose  : 
95 //=======================================================================
96
97 static TopoDS_Vertex CommonVertex(TopoDS_Edge& E1,
98                                   TopoDS_Edge& E2)
99 {
100   TopoDS_Vertex V1[2],V2[2],V;
101   //  Modified by skv - Wed Dec 24 18:08:39 2003 OCC4455 Begin
102 //  TopExp::Vertices(E1,V1[0],V1[1]);
103 //  TopExp::Vertices(E2,V2[0],V2[1]);
104
105   TopExp::Vertices(E1,V1[0],V1[1], Standard_True);
106   TopExp::Vertices(E2,V2[0],V2[1], Standard_True);
107   // The first edge is the current one, the second edge is the next one.
108   // We check last vertex of the first edge first.
109 //  if (V1[0].IsSame(V2[0]) || V1[0].IsSame(V2[1])) return V1[0];
110 //  if (V1[1].IsSame(V2[0]) || V1[1].IsSame(V2[1])) return V1[1];
111   if (V1[1].IsSame(V2[0]) || V1[1].IsSame(V2[1])) return V1[1];
112   if (V1[0].IsSame(V2[0]) || V1[0].IsSame(V2[1])) return V1[0];
113   //  Modified by skv - Wed Dec 24 18:08:40 2003 OCC4455 End
114   return V;
115 }
116
117 //=======================================================================
118 //function : Store
119 //purpose  : 
120 //=======================================================================
121
122 static void  Store (const TopoDS_Edge&       E1,
123                     const TopoDS_Edge&       E2,
124                     TopTools_ListOfShape&    LV1,
125                     TopTools_ListOfShape&    LV2,
126                     Handle(BRepAlgo_AsDes)   AsDes,
127                     Standard_Real            Tol)
128 {
129   //-------------------------------------------------------------
130   // Test if the points of intersection correspond to existing 
131   // vertices. Otherwise add edges in the descendants.
132   // Note: at this stage only vertices of intersection are in the descendants.
133   //-------------------------------------------------------------
134   const TopTools_ListOfShape& VOnE1 = AsDes->Descendant(E1);
135   const TopTools_ListOfShape& VOnE2 = AsDes->Descendant(E2);
136   TopTools_ListOfShape        NewVOnE1;   
137   TopTools_ListOfShape        NewVOnE2; 
138   gp_Pnt                      P,P1,P2;
139   TopoDS_Vertex               V1,V2;
140   TopTools_ListIteratorOfListOfShape it, itLV1, itLV2;
141   BRep_Builder                       B;
142   TopAbs_Orientation                 O1,O2;
143   Standard_Real                      U1,U2;
144   Standard_Boolean                   OnE1,OnE2;
145
146   for (itLV1.Initialize(LV1),itLV2.Initialize(LV2); 
147        itLV1.More(); 
148        itLV1.Next()  ,itLV2.Next()) {
149
150     TopoDS_Vertex V    = TopoDS::Vertex(itLV1.Value());
151
152     U1 = (BRep_Tool::Degenerated(E1))?
153       BRep_Tool::Parameter(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)), E1) :
154       BRep_Tool::Parameter(V, E1);
155     U2 = (BRep_Tool::Degenerated(E2))?
156       BRep_Tool::Parameter(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)), E2) :
157       BRep_Tool::Parameter(V, E2);
158     O1 = V.Orientation();
159     O2 = itLV2.Value().Orientation();
160     P  = BRep_Tool::Pnt(V);
161     OnE1 = OnE2 = Standard_False;
162     
163     if (!VOnE1.IsEmpty()) {
164       //-----------------------------------------------------------------
165       // Find if the point of intersection corresponds to a vertex of E1.
166       //-----------------------------------------------------------------
167       for (it.Initialize(VOnE1); it.More(); it.Next()) {
168         P1 = BRep_Tool::Pnt(TopoDS::Vertex(it.Value()));
169         if (P.IsEqual(P1,Tol)) {
170           V    = TopoDS::Vertex(it.Value());
171           V1   = V;
172           OnE1 = Standard_True;
173           break;
174         }
175       }
176     }
177     if (!VOnE2.IsEmpty()) {
178       if (OnE1) {
179         //-----------------------------------------------------------------
180         // Find if the vertex found on E1 is not already on E2.
181         //-----------------------------------------------------------------
182         for (it.Initialize(VOnE2); it.More(); it.Next()) {
183           if (it.Value().IsSame(V)) {
184             OnE2 = Standard_True;
185             V2   = V;
186             break;
187           }
188         }
189       }
190       for (it.Initialize(VOnE2); it.More(); it.Next()) {
191         //-----------------------------------------------------------------
192         // Find if the point of intersection corresponds to a vertex of E2.
193         //-----------------------------------------------------------------
194         P2 = BRep_Tool::Pnt(TopoDS::Vertex(it.Value()));
195         if (P.IsEqual(P2,Tol)) {
196           V  = TopoDS::Vertex(it.Value());
197           V2 = V;
198           OnE2 = Standard_True;
199           break;
200         }
201       }      
202     }  
203     if (OnE1 && OnE2) {
204       if (!V1.IsSame(V2)) {
205         //---------------------------------------------------------------
206         // Two vertices are actually the same.
207         // V2 will be replaced by V1. 
208         // update the parameters of vertex on edges.
209         //---------------------------------------------------------------
210         Standard_Real UV2;
211         TopoDS_Edge   EWE2;
212         const TopTools_ListOfShape& EdgeWithV2 = AsDes->Ascendant(V2);
213
214         for (it.Initialize(EdgeWithV2); it.More(); it.Next()) {
215           EWE2  = TopoDS::Edge(it.Value());
216           TopoDS_Shape aLocalShape =V2.Oriented(TopAbs_INTERNAL);
217           UV2   = BRep_Tool::Parameter(TopoDS::Vertex(aLocalShape),EWE2);
218 //        UV2   = 
219 //          BRep_Tool::Parameter(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),EWE2);
220           aLocalShape = V1.Oriented(TopAbs_INTERNAL);
221           B.UpdateVertex(TopoDS::Vertex(aLocalShape),UV2,EWE2,Tol);
222 //        B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),
223 //                       UV2,EWE2,Tol);
224         }
225         AsDes->Replace(V2,V1);
226       }
227     }
228     if (!OnE1) {
229       if (OnE2) {
230         TopoDS_Shape aLocalShape = V.Oriented(TopAbs_INTERNAL);
231         B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,E1,Tol);
232 //      B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
233 //                     U1,E1,Tol);
234       }
235       NewVOnE1.Append(V.Oriented(O1));
236     }
237     if (!OnE2) {
238       if (OnE1) {
239         TopoDS_Shape aLocalShape = V.Oriented(TopAbs_INTERNAL);
240         B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,E2,Tol);
241 //      B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
242 //                     U2,E2,Tol);
243       }
244       NewVOnE2.Append(V.Oriented(O2));
245     }
246     
247 #ifdef DRAW
248    if (AffichInt2d) {     
249      if (!OnE1 && !OnE2) {
250        char name[256];
251        sprintf(name,"VV_%d",NbNewVertices++);   
252        DBRep::Set(name,V);
253      }
254    }  
255 #endif    
256   }
257   if (!NewVOnE1.IsEmpty()) AsDes->Add(E1,NewVOnE1);
258   if (!NewVOnE2.IsEmpty()) AsDes->Add(E2,NewVOnE2);
259 }
260
261
262 //=======================================================================
263 //function : EdgeInter
264 //purpose  : 
265 //=======================================================================
266
267 static void EdgeInter(const TopoDS_Face&              F,
268                       const TopoDS_Edge&              E1,
269                       const TopoDS_Edge&              E2,
270                       const Handle(BRepAlgo_AsDes)&   AsDes,
271                       Standard_Real                   Tol,
272                       Standard_Boolean                WithOri)
273 {
274 #ifdef DRAW
275   if (AffichInt2d) {
276     char name[256];
277     sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++);
278     DBRep::Set(name,E1);
279     sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++);
280     DBRep::Set(name,E2);
281   }
282 #endif
283
284   if (E1.IsSame(E2))
285     return;
286
287   Standard_Real f[3],l[3];
288   Standard_Real TolDub = 1.e-7;
289   Standard_Integer i;
290
291   BRep_Tool::Range(E1, f[1], l[1]);
292   BRep_Tool::Range(E2, f[2], l[2]);
293
294   BRepAdaptor_Curve CE1(E1,F);
295   BRepAdaptor_Curve CE2(E2,F);
296
297   TopoDS_Edge                 EI[3]; EI[1] = E1; EI[2] = E2;
298   TopTools_ListOfShape        LV1;   
299   TopTools_ListOfShape        LV2; 
300   BRep_Builder                B;
301
302   TopoDS_Vertex CV;
303   if (!TopExp::CommonVertex( E1, E2, CV ))
304     {
305       BRepLib::BuildCurve3d(E1);
306       BRepLib::BuildCurve3d(E2);
307       
308       Standard_Real TolSum = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2);
309       TolSum = Max( TolSum, 1.e-5 );
310
311       TColgp_SequenceOfPnt   ResPoints;
312       TColStd_SequenceOfReal ResParamsOnE1, ResParamsOnE2;
313       gp_Pnt DegPoint;
314       Standard_Boolean WithDegen = BRep_Tool::Degenerated(E1) || BRep_Tool::Degenerated(E2);
315       
316       if (WithDegen)
317         {
318           Standard_Integer ideg = (BRep_Tool::Degenerated(E1))? 1 : 2;
319           TopoDS_Iterator iter( EI[ideg] );
320           if (iter.More())
321             {
322               const TopoDS_Vertex& vdeg = TopoDS::Vertex(iter.Value());
323               DegPoint = BRep_Tool::Pnt(vdeg);
324             }
325           else
326             {
327               BRepAdaptor_Curve CEdeg( EI[ideg], F );
328               DegPoint = CEdeg.Value( CEdeg.FirstParameter() );
329             }
330         }
331       BRepAdaptor_Surface BAsurf(F);
332       Handle(Geom2d_Curve) pcurve1 = BRep_Tool::CurveOnSurface(E1, F, f[1], l[1]);
333       Handle(Geom2d_Curve) pcurve2 = BRep_Tool::CurveOnSurface(E2, F, f[2], l[2]);
334       Geom2dAdaptor_Curve GAC1(pcurve1, f[1], l[1]);
335       Geom2dAdaptor_Curve GAC2(pcurve2, f[2], l[2]);
336       Geom2dInt_GInter Inter2d( GAC1, GAC2, TolDub, TolDub );
337       for (i = 1; i <= Inter2d.NbPoints(); i++)
338         {
339           gp_Pnt P3d;
340           if (WithDegen)
341             P3d = DegPoint;
342           else
343             {
344               gp_Pnt2d P2d = Inter2d.Point(i).Value();
345               P3d = BAsurf.Value( P2d.X(), P2d.Y() );
346             }
347           ResPoints.Append( P3d );
348           ResParamsOnE1.Append( Inter2d.Point(i).ParamOnFirst() );
349           ResParamsOnE2.Append( Inter2d.Point(i).ParamOnSecond() );
350         }
351
352       for (i = 1; i <= ResPoints.Length(); i++)
353         {
354           Standard_Real aT1 = ResParamsOnE1(i); //ponc1.Parameter();
355           Standard_Real aT2 = ResParamsOnE2(i); //ponc2.Parameter();
356           if (Precision::IsInfinite(aT1) || Precision::IsInfinite(aT2))
357             {
358 #ifdef OCCT_DEBUG
359               cout << "Inter2d : Solution rejected due to infinite parameter"<<endl;
360 #endif
361               continue;
362             }
363           
364           gp_Pnt P = ResPoints(i); //ponc1.Value();
365           TopoDS_Vertex aNewVertex = BRepLib_MakeVertex(P);
366           aNewVertex.Orientation(TopAbs_INTERNAL);
367           B.UpdateVertex( aNewVertex, aT1, E1, Tol );
368           B.UpdateVertex( aNewVertex, aT2, E2, Tol );
369           gp_Pnt P1 = CE1.Value(aT1);
370           gp_Pnt P2 = CE2.Value(aT2);
371           Standard_Real dist1, dist2, dist3;
372           dist1 = P1.Distance(P);
373           dist2 = P2.Distance(P);
374           dist3 = P1.Distance(P2);
375           dist1 = Max( dist1, dist2 );
376           dist1 = Max( dist1, dist3 );
377           B.UpdateVertex( aNewVertex, dist1 );
378           
379 #ifdef OCCT_DEBUG
380           if (aT1 < f[1]-Tol  || aT1 > l[1]+Tol)
381             {
382               cout << "out of limit"<<endl;
383               cout<<"aT1 = "<<aT1<<", f[1] = "<<f[1]<<", l[1] = "<<l[1]<<endl;
384             }
385           if (aT2 < f[2]-Tol  || aT2 > l[2]+Tol)
386             {
387               cout << "out of limit"<<endl;
388               cout<<"aT2 = "<<aT2<<", f[2] = "<<f[2]<<", l[2] = "<<l[2]<<endl;
389             }
390           Standard_Real MilTol2 = 1000*Tol*Tol;
391           if (P1.SquareDistance(P) >  MilTol2 || P2.SquareDistance(P) > MilTol2 || P1.Distance(P2) > 2.*Tol)
392             {
393               cout << "Inter2d : Solution rejected "<<endl;
394               cout<<"P  = "<<P.X()<<" "<<P.Y()<<" "<<P.Z()<<endl;
395               cout<<"P1 = "<<P1.X()<<" "<<P1.Y()<<" "<<P1.Z()<<endl;
396               cout<<"P2 = "<<P2.X()<<" "<<P2.Y()<<" "<<P2.Z()<<endl;
397               cout<<"MaxDist = "<<dist1<<endl;
398             }
399 #endif
400           //define the orientation of a new vertex
401           TopAbs_Orientation OO1 = TopAbs_REVERSED;
402           TopAbs_Orientation OO2 = TopAbs_REVERSED;
403           if (WithOri)
404             {
405               BRepAdaptor_Curve2d PCE1( E1, F );
406               BRepAdaptor_Curve2d PCE2( E2, F );
407               gp_Pnt2d P2d1, P2d2;
408               gp_Vec2d V1, V2, V1or, V2or;
409               PCE1.D1( aT1, P2d1, V1 );
410               PCE2.D1( aT2, P2d2, V2 );
411               V1or = V1; V2or = V2;
412               if (E1.Orientation() == TopAbs_REVERSED) V1or.Reverse();
413               if (E2.Orientation() == TopAbs_REVERSED) V2or.Reverse();
414               Standard_Real CrossProd = V2or ^ V1;
415 #ifdef OCCT_DEBUG
416               if (Abs(CrossProd) <= gp::Resolution())
417                 cout<<endl<<"CrossProd = "<<CrossProd<<endl;
418 #endif
419               if (CrossProd > 0.)
420                 OO1 = TopAbs_FORWARD;
421               CrossProd = V1or ^ V2;
422               if (CrossProd > 0.)
423                 OO2 = TopAbs_FORWARD;
424             }
425           LV1.Append( aNewVertex.Oriented(OO1) );
426           LV2.Append( aNewVertex.Oriented(OO2) );
427         }
428     }
429   
430   //----------------------------------
431   // Test at end.
432   //---------------------------------
433   Standard_Real U1,U2;
434   Standard_Real TolConf = Tol;
435   TopoDS_Vertex V1[2],V2[2];
436   TopExp::Vertices(E1,V1[0],V1[1]);
437   TopExp::Vertices(E2,V2[0],V2[1]);
438
439   Standard_Integer j;
440   for (j = 0; j < 2; j++) {
441     if (V1[j].IsNull()) continue;
442     for (Standard_Integer k = 0; k < 2; k++) {
443       if (V2[k].IsNull()) continue;
444       gp_Pnt P1 = BRep_Tool::Pnt(V1[j]);
445       gp_Pnt P2 = BRep_Tool::Pnt(V2[k]);
446       Standard_Real Dist = P1.Distance(P2); 
447       if (Dist < TolConf) {
448         TopoDS_Vertex V = BRepLib_MakeVertex(P1);
449         U1 = (j == 0) ? f[1] : l[1];
450         U2 = (k == 0) ? f[2] : l[2];
451         TopoDS_Shape aLocalShape = V.Oriented(TopAbs_INTERNAL);
452 //  Modified by skv - Thu Jan 22 18:16:01 2004 OCC4455 Begin
453         Standard_Real aTol = BRep_Tool::Tolerance(V1[j]);
454
455         if (!V1[j].IsSame(V2[k])) {
456           Standard_Real aTol2 = BRep_Tool::Tolerance(V2[k]);
457
458           aTol = Max(aTol, aTol2);
459         }
460
461         B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,E1,aTol);
462         B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,E2,aTol);
463 //      B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,E1,Tol);
464 //      B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,E2,Tol);
465 //      B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
466 //                     U1,E1,Tol);
467 //      B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
468 //                     U2,E2,Tol);
469 //  Modified by skv - Thu Jan 22 18:16:01 2004 OCC4455 End
470         LV1.Prepend(V.Oriented(V1[j].Orientation()));
471         LV2.Prepend(V.Oriented(V2[k].Orientation()));
472       }
473     }
474   }
475
476   Standard_Boolean AffichPurge = Standard_False;
477
478   if ( !LV1.IsEmpty()) {
479     //----------------------------------
480     // Remove all vertices.
481     // There can be doubles
482     //----------------------------------
483     TopTools_ListIteratorOfListOfShape it1LV1,it1LV2,it2LV1;
484     gp_Pnt P1,P2;
485     Standard_Boolean Purge = Standard_True;
486
487     while (Purge) {
488       i = 1;
489       Purge = Standard_False;
490       for (it1LV1.Initialize(LV1),it1LV2.Initialize(LV2); 
491            it1LV1.More(); it1LV1.Next(),it1LV2.Next()) {
492         j = 1;
493         it2LV1.Initialize(LV1);
494         while (j < i) {      
495           P1 = BRep_Tool::Pnt(TopoDS::Vertex(it1LV1.Value()));
496           P2 = BRep_Tool::Pnt(TopoDS::Vertex(it2LV1.Value()));
497 //  Modified by skv - Thu Jan 22 18:19:04 2004 OCC4455 Begin
498 //        if (P1.IsEqual(P2,10*Tol)) {
499           Standard_Real aTol;
500
501           aTol = Max(BRep_Tool::Tolerance(TopoDS::Vertex(it1LV1.Value())),
502                      BRep_Tool::Tolerance(TopoDS::Vertex(it2LV1.Value())));
503           if (P1.IsEqual(P2,aTol)) {
504 //  Modified by skv - Thu Jan 22 18:19:05 2004 OCC4455 End
505             LV1.Remove(it1LV1);
506             LV2.Remove(it1LV2);
507             if (AffichPurge) cout <<"Doubles removed in EdgeInter."<<endl;
508             Purge = Standard_True;
509             break;
510           }
511           j++;
512           it2LV1.Next();
513         }
514         if (Purge) break;
515         i++;
516       }
517     }
518     //---------------------------------
519     // Vertex storage in DS.
520     //---------------------------------
521 //  Modified by skv - Tue Jan 13 15:14:30 2004 Begin
522     Standard_Real TolStore = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2);
523
524     TolStore = Max(TolStore, 10.*Tol);
525
526     Store (E1,E2,LV1,LV2,AsDes,TolStore);
527 //    Store (E1,E2,LV1,LV2,AsDes,10.*Tol);
528 //    Store (E1,E2,LV1,LV2,AsDes,Tol);
529 //  Modified by skv - Tue Jan 13 15:14:30 2004 End
530   }
531 }
532 //=======================================================================
533 //function : EdgeInter
534 //purpose  : 
535 //=======================================================================
536
537 static void RefEdgeInter(const TopoDS_Face&              F,
538                          const TopoDS_Edge&              E1,
539                          const TopoDS_Edge&              E2,
540                          const Handle(BRepAlgo_AsDes)&   AsDes,
541                          Standard_Real                   Tol,
542                          Standard_Boolean                WithOri,
543                          gp_Pnt&                         Pref)
544 {
545 #ifdef DRAW
546   if (AffichInt2d) {
547     char name[256];
548     sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++);
549     DBRep::Set(name,E1);
550     sprintf(name,"E2d_%d_%d",NbF2d,NbE2d++);
551     DBRep::Set(name,E2);
552   }
553 #endif
554
555   if (E1.IsSame(E2))
556     return;
557
558   Standard_Real f[3],l[3];
559   Standard_Real TolDub = 1.e-7;
560   Standard_Integer i;
561
562   //BRep_Tool::Range(E1, f[1], l[1]);
563   //BRep_Tool::Range(E2, f[2], l[2]);
564
565   BRepAdaptor_Curve CE1(E1,F);
566   BRepAdaptor_Curve CE2(E2,F);
567
568   TopoDS_Edge                 EI[3]; EI[1] = E1; EI[2] = E2;
569   TopTools_ListOfShape        LV1;   
570   TopTools_ListOfShape        LV2; 
571   BRep_Builder                B;
572
573   BRepLib::BuildCurve3d(E1);
574   BRepLib::BuildCurve3d(E2);
575
576   Standard_Real TolSum = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2);
577   TolSum = Max( TolSum, 1.e-5 );
578
579   TColgp_SequenceOfPnt   ResPoints;
580   TColStd_SequenceOfReal ResParamsOnE1, ResParamsOnE2;
581   gp_Pnt DegPoint;
582   Standard_Boolean WithDegen = BRep_Tool::Degenerated(E1) || BRep_Tool::Degenerated(E2);
583   
584   if (WithDegen)
585     {
586       Standard_Integer ideg = (BRep_Tool::Degenerated(E1))? 1 : 2;
587       TopoDS_Iterator iter( EI[ideg] );
588       if (iter.More())
589         {
590           const TopoDS_Vertex& vdeg = TopoDS::Vertex(iter.Value());
591           DegPoint = BRep_Tool::Pnt(vdeg);
592         }
593       else
594         {
595           BRepAdaptor_Curve CEdeg( EI[ideg], F );
596           DegPoint = CEdeg.Value( CEdeg.FirstParameter() );
597         }
598     }
599   BRepAdaptor_Surface BAsurf(F);
600   Handle(Geom2d_Curve) pcurve1 = BRep_Tool::CurveOnSurface(E1, F, f[1], l[1]);
601   Handle(Geom2d_Curve) pcurve2 = BRep_Tool::CurveOnSurface(E2, F, f[2], l[2]);
602   Geom2dAdaptor_Curve GAC1(pcurve1, f[1], l[1]);
603   Geom2dAdaptor_Curve GAC2(pcurve2, f[2], l[2]);
604   Geom2dInt_GInter Inter2d( GAC1, GAC2, TolDub, TolDub );
605   for (i = 1; i <= Inter2d.NbPoints(); i++)
606     {
607       gp_Pnt P3d;
608       if (WithDegen)
609         P3d = DegPoint;
610       else
611         {
612           gp_Pnt2d P2d = Inter2d.Point(i).Value();
613           P3d = BAsurf.Value( P2d.X(), P2d.Y() );
614         }
615       ResPoints.Append( P3d );
616       ResParamsOnE1.Append( Inter2d.Point(i).ParamOnFirst() );
617       ResParamsOnE2.Append( Inter2d.Point(i).ParamOnSecond() );
618     }
619   
620   for (i = 1; i <= ResPoints.Length(); i++)
621     {
622       Standard_Real aT1 = ResParamsOnE1(i); //ponc1.Parameter();
623       Standard_Real aT2 = ResParamsOnE2(i); //ponc2.Parameter();
624       if (Precision::IsInfinite(aT1) || Precision::IsInfinite(aT2))
625         {
626 #ifdef OCCT_DEBUG
627           cout << "Inter2d : Solution rejected due to infinite parameter"<<endl;
628 #endif
629           continue;
630         }
631       
632       gp_Pnt P = ResPoints(i); //ponc1.Value();
633       TopoDS_Vertex aNewVertex = BRepLib_MakeVertex(P);
634       aNewVertex.Orientation(TopAbs_INTERNAL);
635       B.UpdateVertex( aNewVertex, aT1, E1, Tol );
636       B.UpdateVertex( aNewVertex, aT2, E2, Tol );
637       gp_Pnt P1 = CE1.Value(aT1);
638       gp_Pnt P2 = CE2.Value(aT2);
639       Standard_Real dist1, dist2, dist3;
640       dist1 = P1.Distance(P);
641       dist2 = P2.Distance(P);
642       dist3 = P1.Distance(P2);
643       dist1 = Max( dist1, dist2 );
644       dist1 = Max( dist1, dist3 );
645       B.UpdateVertex( aNewVertex, dist1 );
646       
647 #ifdef OCCT_DEBUG
648       if (aT1 < f[1]-Tol  || aT1 > l[1]+Tol)
649         {
650           cout << "out of limit"<<endl;
651           cout<<"aT1 = "<<aT1<<", f[1] = "<<f[1]<<", l[1] = "<<l[1]<<endl;
652         }
653       if (aT2 < f[2]-Tol  || aT2 > l[2]+Tol)
654         {
655           cout << "out of limit"<<endl;
656           cout<<"aT2 = "<<aT2<<", f[2] = "<<f[2]<<", l[2] = "<<l[2]<<endl;
657         }
658       Standard_Real MilTol2 = 1000*Tol*Tol;
659       if (P1.SquareDistance(P) >  MilTol2 || P2.SquareDistance(P) > MilTol2 || P1.Distance(P2) > 2.*Tol)
660         {
661           cout << "Inter2d : Solution rejected"<<endl;
662           cout<<"P  = "<<P.X()<<" "<<P.Y()<<" "<<P.Z()<<endl;
663           cout<<"P1 = "<<P1.X()<<" "<<P1.Y()<<" "<<P1.Z()<<endl;
664           cout<<"P2 = "<<P2.X()<<" "<<P2.Y()<<" "<<P2.Z()<<endl;
665           cout<<"MaxDist = "<<dist1<<endl;
666         }
667 #endif
668       //define the orientation of a new vertex
669       TopAbs_Orientation OO1 = TopAbs_REVERSED;
670       TopAbs_Orientation OO2 = TopAbs_REVERSED;
671       if (WithOri)
672         {
673           BRepAdaptor_Curve2d PCE1( E1, F );
674           BRepAdaptor_Curve2d PCE2( E2, F );
675           gp_Pnt2d P2d1, P2d2;
676           gp_Vec2d V1, V2, V1or, V2or;
677           PCE1.D1( aT1, P2d1, V1 );
678           PCE2.D1( aT2, P2d2, V2 );
679           V1or = V1; V2or = V2;
680           if (E1.Orientation() == TopAbs_REVERSED) V1or.Reverse();
681           if (E2.Orientation() == TopAbs_REVERSED) V2or.Reverse();
682           Standard_Real CrossProd = V2or ^ V1;
683 #ifdef OCCT_DEBUG
684           if (Abs(CrossProd) <= gp::Resolution())
685             cout<<endl<<"CrossProd = "<<CrossProd<<endl;
686 #endif
687           if (CrossProd > 0.)
688             OO1 = TopAbs_FORWARD;
689           CrossProd = V1or ^ V2;
690           if (CrossProd > 0.)
691             OO2 = TopAbs_FORWARD;
692         }
693       LV1.Append( aNewVertex.Oriented(OO1) );
694       LV2.Append( aNewVertex.Oriented(OO2) );
695     }
696   
697   //----------------------------------
698   // Test at end.
699   //---------------------------------
700   Standard_Real U1,U2;
701   Standard_Real TolConf = Tol;
702   TopoDS_Vertex V1[2],V2[2];
703   TopExp::Vertices(E1,V1[0],V1[1]);
704   TopExp::Vertices(E2,V2[0],V2[1]);
705
706   Standard_Integer j;
707   for (j = 0; j < 2; j++) {
708     if (V1[j].IsNull()) continue;
709     for (Standard_Integer k = 0; k < 2; k++) {
710       if (V2[k].IsNull()) continue;
711       gp_Pnt P1 = BRep_Tool::Pnt(V1[j]);
712       gp_Pnt P2 = BRep_Tool::Pnt(V2[k]);
713       Standard_Real Dist = P1.Distance(P2); 
714       if (Dist < TolConf) {
715         TopoDS_Vertex V = BRepLib_MakeVertex(P1);
716         U1 = (j == 0) ? f[1] : l[1];
717         U2 = (k == 0) ? f[2] : l[2];
718         TopoDS_Shape aLocalShape = V.Oriented(TopAbs_INTERNAL);
719         B.UpdateVertex(TopoDS::Vertex(aLocalShape),U1,E1,Tol);
720         B.UpdateVertex(TopoDS::Vertex(aLocalShape),U2,E2,Tol);
721 //      B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
722 //                     U1,E1,Tol);
723 //      B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
724 //                     U2,E2,Tol);
725         LV1.Prepend(V.Oriented(V1[j].Orientation()));
726         LV2.Prepend(V.Oriented(V2[k].Orientation()));
727       }
728     }
729   }
730
731   Standard_Boolean AffichPurge = Standard_False;
732
733   if ( !LV1.IsEmpty()) {
734     //----------------------------------
735     // Remove all vertices.
736     // there can be doubles
737     //----------------------------------
738     TopTools_ListIteratorOfListOfShape it1LV1,it1LV2,it2LV1;
739     gp_Pnt P1,P2;
740     Standard_Boolean Purge = Standard_True;
741
742     while (Purge) {
743       i = 1;
744       Purge = Standard_False;
745       for (it1LV1.Initialize(LV1),it1LV2.Initialize(LV2); 
746            it1LV1.More(); it1LV1.Next(),it1LV2.Next()) {
747         j = 1;
748         it2LV1.Initialize(LV1);
749         while (j < i) {      
750           P1 = BRep_Tool::Pnt(TopoDS::Vertex(it1LV1.Value()));
751           P2 = BRep_Tool::Pnt(TopoDS::Vertex(it2LV1.Value()));
752           if (P1.IsEqual(P2,10*Tol)) {
753             LV1.Remove(it1LV1);
754             LV2.Remove(it1LV2);
755             if (AffichPurge) cout <<"Doubles removed in EdgeInter."<<endl;
756             Purge = Standard_True;
757             break;
758           }
759           j++;
760           it2LV1.Next();
761         }
762         if (Purge) break;
763         i++;
764       }
765     }
766     //---------------------------------
767     // Vertex storage in SD.
768     //---------------------------------
769 ////-----------------------------------------------------
770     if(LV1.Extent() > 1) {
771       //cout << "IFV - RefEdgeInter: remove vertex" << endl;
772       Standard_Real dmin = RealLast();
773       TopoDS_Vertex Vmin;
774       for (it1LV1.Initialize(LV1); it1LV1.More(); it1LV1.Next()) {
775         gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(it1LV1.Value()));
776         Standard_Real d = P.SquareDistance(Pref);
777         if(d < dmin) {
778           dmin = d;
779           Vmin = TopoDS::Vertex(it1LV1.Value());
780         }
781       }
782       for (it1LV1.Initialize(LV1),it1LV2.Initialize(LV2); 
783            it1LV1.More(); it1LV1.Next(),it1LV2.Next()) {
784         if(!Vmin.IsSame(it1LV1.Value())) {
785           LV1.Remove(it1LV1);
786           LV2.Remove(it1LV2);
787           if(!it1LV1.More()) break;
788         }
789       }
790     }
791       
792 ////-----------------------------------------------------
793
794 //  Modified by skv - Tue Jan 13 15:14:30 2004 Begin
795     Standard_Real TolStore = BRep_Tool::Tolerance(E1) + BRep_Tool::Tolerance(E2);
796
797     TolStore = Max(TolStore, 10.*Tol);
798
799     Store (E1,E2,LV1,LV2,AsDes,TolStore);
800 //    Store (E1,E2,LV1,LV2,AsDes,10.*Tol);
801 //    Store (E1,E2,LV1,LV2,AsDes,Tol);
802 //  Modified by skv - Tue Jan 13 15:14:30 2004 End
803   }
804 }
805
806
807 //======================================================================
808 //function : EvaluateMaxSegment
809 //purpose  : return MaxSegment to pass in approximation
810 //======================================================================
811
812 static Standard_Integer evaluateMaxSegment(const Adaptor3d_CurveOnSurface& aCurveOnSurface)
813 {
814   Handle(Adaptor3d_HSurface) aSurf   = aCurveOnSurface.GetSurface();
815   Handle(Adaptor2d_HCurve2d) aCurv2d = aCurveOnSurface.GetCurve();
816
817   Standard_Real aNbSKnots = 0, aNbC2dKnots = 0;
818   
819   if (aSurf->GetType() == GeomAbs_BSplineSurface) {
820     Handle(Geom_BSplineSurface) aBSpline = aSurf->BSpline();
821     aNbSKnots = Max(aBSpline->NbUKnots(), aBSpline->NbVKnots());
822   }
823   if (aCurv2d->GetType() == GeomAbs_BSplineCurve) {
824     aNbC2dKnots = aCurv2d->NbKnots();
825   }
826   Standard_Integer aReturn = (Standard_Integer) (  30 + Max(aNbSKnots, aNbC2dKnots) ) ;
827   return aReturn;
828 }
829
830
831 //=======================================================================
832 //function : ExtendPCurve
833 //purpose  : 
834 //=======================================================================
835
836 static Standard_Boolean ExtendPCurve(const Handle(Geom2d_Curve)& aPCurve,
837                                      const Standard_Real anEf,
838                                      const Standard_Real anEl,
839                                      const Standard_Real a2Offset,
840                                      Handle(Geom2d_Curve)& NewPCurve)
841 {
842   NewPCurve = aPCurve;
843   if (NewPCurve->IsInstance(STANDARD_TYPE(Geom2d_TrimmedCurve)))
844     NewPCurve = (*((Handle(Geom2d_TrimmedCurve)*)&NewPCurve))->BasisCurve();
845   
846   Standard_Real FirstPar = NewPCurve->FirstParameter();
847   Standard_Real LastPar  = NewPCurve->LastParameter();
848
849   if (NewPCurve->IsKind(STANDARD_TYPE(Geom2d_BoundedCurve)) &&
850       (FirstPar > anEf - a2Offset || LastPar < anEl + a2Offset))
851     {
852       if (NewPCurve->IsInstance(STANDARD_TYPE(Geom2d_BezierCurve)))
853         {
854           Handle(Geom2d_BezierCurve) aBezier = *((Handle(Geom2d_BezierCurve)*)&NewPCurve);
855           if (aBezier->NbPoles() == 2)
856             {
857               TColgp_Array1OfPnt2d thePoles(1,2);
858               aBezier->Poles(thePoles);
859               gp_Vec2d aVec(thePoles(1), thePoles(2));
860               NewPCurve = new Geom2d_Line(thePoles(1), aVec);
861               return Standard_True;
862             }
863         }
864       else if (NewPCurve->IsInstance(STANDARD_TYPE(Geom2d_BSplineCurve)))
865         {
866           Handle(Geom2d_BSplineCurve) aBSpline = *((Handle(Geom2d_BSplineCurve)*)&NewPCurve);
867           if (aBSpline->NbKnots() == 2 && aBSpline->NbPoles() == 2)
868             {
869               TColgp_Array1OfPnt2d thePoles(1,2);
870               aBSpline->Poles(thePoles);
871               gp_Vec2d aVec(thePoles(1), thePoles(2));
872               NewPCurve = new Geom2d_Line(thePoles(1), aVec);
873               return Standard_True;
874             }
875         }
876     }
877
878   FirstPar = aPCurve->FirstParameter();
879   LastPar  = aPCurve->LastParameter();
880   Handle(Geom2d_TrimmedCurve) aTrCurve = 
881     new Geom2d_TrimmedCurve(aPCurve, FirstPar, LastPar);
882   
883   // The curve is not prolonged on begin or end.
884   // Trying to prolong it adding a segment to its bound.
885   gp_Pnt2d                              aPBnd;
886   gp_Vec2d                              aVBnd;
887   gp_Pnt2d                              aPBeg;
888   gp_Dir2d                              aDBnd;
889   Handle(Geom2d_Line)                   aLin;
890   Handle(Geom2d_TrimmedCurve)           aSegment;
891   Geom2dConvert_CompCurveToBSplineCurve aCompCurve(aTrCurve, Convert_RationalC1);
892   Standard_Real                         aTol = Precision::Confusion();
893   Standard_Real                         aDelta = Max(a2Offset, 1.);
894   
895   if (FirstPar > anEf - a2Offset) {
896     aPCurve->D1(FirstPar, aPBnd, aVBnd);
897     aDBnd.SetXY(aVBnd.XY());
898     aPBeg    = aPBnd.Translated(gp_Vec2d(-aDelta*aDBnd.XY()));
899     aLin     = new Geom2d_Line(aPBeg, aDBnd);
900     aSegment = new Geom2d_TrimmedCurve(aLin, 0, aDelta);
901     
902     if (!aCompCurve.Add(aSegment, aTol))
903       return Standard_False;
904   }
905   
906   if (LastPar < anEl + a2Offset) {
907     aPCurve->D1(LastPar, aPBeg, aVBnd);
908     aDBnd.SetXY(aVBnd.XY());
909     aLin     = new Geom2d_Line(aPBeg, aDBnd);
910     aSegment = new Geom2d_TrimmedCurve(aLin, 0, aDelta);
911     
912     if (!aCompCurve.Add(aSegment, aTol))
913       return Standard_False;
914   }
915   
916   NewPCurve  = aCompCurve.BSplineCurve();
917   return Standard_True;
918 }
919
920 //=======================================================================
921 //function : ExtentEdge
922 //purpose  : 
923 //=======================================================================
924
925 //  Modified by skv - Fri Dec 26 17:00:55 2003 OCC4455 Begin
926 //static void ExtentEdge(const TopoDS_Edge& E,TopoDS_Edge& NE) 
927 static void ExtentEdge(const TopoDS_Edge& E,TopoDS_Edge& NE, const Standard_Real theOffset)
928 {
929   //BRepLib::BuildCurve3d(E);
930
931   TopoDS_Shape  aLocalShape = E.EmptyCopied();
932   Standard_Real anEf;
933   Standard_Real anEl;
934   Standard_Real a2Offset = 2.*Abs(theOffset);
935   BRep_Builder BB;
936   Standard_Integer i, j;
937
938   BRep_Tool::Range(E, anEf, anEl);
939   NE = TopoDS::Edge(aLocalShape); 
940 //  NE = TopoDS::Edge(E.EmptyCopied()); 
941   // Enough for analytic edges, for general case reconstruct the
942   // geometry of the edge recalculating the intersection of surfaces.
943
944   //BRepLib::BuildCurve3d(E);
945
946   Standard_Integer NbPCurves = 0;
947   Standard_Real FirstParOnPC = RealFirst(), LastParOnPC = RealLast();
948   Handle(Geom2d_Curve) MinPC;
949   Handle(Geom_Surface) MinSurf;
950   TopLoc_Location      MinLoc;
951
952   BRep_ListIteratorOfListOfCurveRepresentation itr( (Handle(BRep_TEdge)::DownCast(NE.TShape()))->ChangeCurves() );
953   for (; itr.More(); itr.Next())
954     {
955       Handle( BRep_CurveRepresentation ) CurveRep = itr.Value();
956       Standard_Real FirstPar, LastPar;
957       if (CurveRep->IsCurveOnSurface())
958         {
959           NbPCurves++;
960           Handle(Geom2d_Curve) theCurve = CurveRep->PCurve();
961           FirstPar = theCurve->FirstParameter();
962           LastPar  = theCurve->LastParameter();
963
964           if (theCurve->IsKind(STANDARD_TYPE(Geom2d_BoundedCurve)) &&
965               (FirstPar > anEf - a2Offset || LastPar < anEl + a2Offset))
966             {
967               Handle(Geom2d_Curve) NewPCurve;
968               if (ExtendPCurve(theCurve, anEf, anEl, a2Offset, NewPCurve))
969                 {
970                   CurveRep->PCurve(NewPCurve);
971                   FirstPar = NewPCurve->FirstParameter();
972                   LastPar  = NewPCurve->LastParameter();
973                   if (CurveRep->IsCurveOnClosedSurface())
974                     {
975                       Handle(Geom2d_Curve) PCurve2 = CurveRep->PCurve2();
976                       if (ExtendPCurve(PCurve2, anEf, anEl, a2Offset, NewPCurve))
977                         CurveRep->PCurve2(NewPCurve);
978                     }
979                 }
980             }
981           else if (theCurve->IsPeriodic())
982             {
983               Standard_Real delta = (theCurve->Period() - (anEl - anEf))*0.5;
984               delta *= 0.95;
985               FirstPar = anEf - delta;
986               LastPar  = anEl + delta;
987             }
988           else if (theCurve->IsClosed())
989             LastPar -= 0.05*(LastPar - FirstPar);
990
991           //check FirstPar and LastPar: the pcurve should be in its surface
992           theCurve = CurveRep->PCurve();
993           Handle(Geom_Surface) theSurf = CurveRep->Surface();
994           Standard_Real Umin, Umax, Vmin, Vmax;
995           theSurf->Bounds(Umin, Umax, Vmin, Vmax);
996           TColGeom2d_SequenceOfCurve BoundLines;
997           if (!Precision::IsInfinite(Vmin))
998             {
999               Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( 0., Vmin ),
1000                                                           gp_Dir2d( 1., 0. ));
1001               BoundLines.Append(aLine);
1002             }
1003           if (!Precision::IsInfinite(Umin))
1004             {
1005               Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( Umin, 0. ),
1006                                                           gp_Dir2d( 0., 1. ));
1007               BoundLines.Append(aLine);
1008             }
1009           if (!Precision::IsInfinite(Vmax))
1010             {
1011               Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( 0., Vmax ),
1012                                                           gp_Dir2d( 1., 0. ));
1013               BoundLines.Append(aLine);
1014             }
1015           if (!Precision::IsInfinite(Umax))
1016             {
1017               Handle(Geom2d_Line) aLine = new Geom2d_Line(gp_Pnt2d( Umax, 0. ),
1018                                                           gp_Dir2d( 0., 1. ));
1019               BoundLines.Append(aLine);
1020             }
1021
1022           TColStd_SequenceOfReal params;
1023           Geom2dInt_GInter IntCC;
1024           Geom2dAdaptor_Curve GAcurve(theCurve);
1025           for (i = 1; i <= BoundLines.Length(); i++)
1026             {
1027               Geom2dAdaptor_Curve GAline( BoundLines(i) );
1028               IntCC.Perform( GAcurve, GAline, Precision::PConfusion(), Precision::PConfusion());
1029               if (IntCC.IsDone())
1030                 {
1031                   for (j = 1; j <= IntCC.NbPoints(); j++)
1032                     {
1033                       const IntRes2d_IntersectionPoint& ip = IntCC.Point(j);
1034                       gp_Pnt2d aPoint = ip.Value();
1035                       if (aPoint.X() >= Umin && aPoint.X() <= Umax &&
1036                           aPoint.Y() >= Vmin && aPoint.Y() <= Vmax)
1037                         params.Append( ip.ParamOnFirst() );
1038                     }
1039                   for (j = 1; j <= IntCC.NbSegments(); j++)
1040                     {
1041                       const IntRes2d_IntersectionSegment& is = IntCC.Segment(j);
1042                       if (is.HasFirstPoint())
1043                         {
1044                           const IntRes2d_IntersectionPoint& ip = is.FirstPoint();
1045                           gp_Pnt2d aPoint = ip.Value();
1046                           if (aPoint.X() >= Umin && aPoint.X() <= Umax &&
1047                               aPoint.Y() >= Vmin && aPoint.Y() <= Vmax)
1048                             params.Append( ip.ParamOnFirst() );
1049                         }
1050                       if (is.HasLastPoint())
1051                         {
1052                           const IntRes2d_IntersectionPoint& ip = is.LastPoint();
1053                           gp_Pnt2d aPoint = ip.Value();
1054                           if (aPoint.X() >= Umin && aPoint.X() <= Umax &&
1055                               aPoint.Y() >= Vmin && aPoint.Y() <= Vmax)
1056                             params.Append( ip.ParamOnFirst() );
1057                         }
1058                     }
1059                 }
1060             }
1061           if (!params.IsEmpty())
1062             {
1063               if (params.Length() == 1)
1064                 {
1065                   gp_Pnt2d PntFirst = theCurve->Value(FirstPar);
1066                   if (PntFirst.X() >= Umin && PntFirst.X() <= Umax &&
1067                       PntFirst.Y() >= Vmin && PntFirst.Y() <= Vmax)
1068                     {
1069                       if (LastPar > params(1))
1070                         LastPar = params(1);
1071                     }
1072                   else if (FirstPar < params(1))
1073                     FirstPar = params(1);
1074                 }
1075               else
1076                 {
1077                   Standard_Real fpar = RealLast(), lpar = RealFirst();
1078                   for (i = 1; i <= params.Length(); i++)
1079                     {
1080                       if (params(i) < fpar)
1081                         fpar = params(i);
1082                       if (params(i) > lpar)
1083                         lpar = params(i);
1084                     }
1085                   if (FirstPar < fpar)
1086                     FirstPar = fpar;
1087                   if (LastPar > lpar)
1088                     LastPar = lpar;
1089                 }
1090             }
1091           //// end of check ////
1092           (Handle(BRep_GCurve)::DownCast(CurveRep))->SetRange( FirstPar, LastPar );
1093           //gp_Pnt2d Pfirst = theCurve->Value(FirstPar);
1094           //gp_Pnt2d Plast  = theCurve->Value(LastPar);
1095           //(Handle(BRep_CurveOnSurface)::DownCast(CurveRep))->SetUVPoints( Pfirst, Plast );
1096
1097           //update FirstParOnPC and LastParOnPC
1098           if (FirstPar > FirstParOnPC)
1099             {
1100               FirstParOnPC = FirstPar;
1101               MinPC   = theCurve;
1102               MinSurf = theSurf;
1103               MinLoc  = CurveRep->Location();
1104             }
1105           if (LastPar  < LastParOnPC)
1106             {
1107               LastParOnPC  = LastPar;
1108               MinPC   = theCurve;
1109               MinSurf = theSurf;
1110               MinLoc  = CurveRep->Location();
1111             }
1112         }
1113     }
1114
1115   Standard_Real f, l;
1116   Handle(Geom_Curve) C3d = BRep_Tool::Curve( NE, f, l );
1117   if (NbPCurves)
1118     {
1119       MinLoc = E.Location() * MinLoc;
1120       if (!C3d.IsNull())
1121         {
1122           if (MinPC->IsClosed())
1123             {
1124               f = FirstParOnPC;
1125               l = LastParOnPC;
1126             }
1127           else if (C3d->IsPeriodic())
1128             {
1129               Standard_Real delta = (C3d->Period() - (l - f))*0.5;
1130               delta *= 0.95;
1131               f -= delta;
1132               l += delta;
1133             }
1134           else if (C3d->IsClosed())
1135             l -= 0.05*(l - f);
1136           else
1137             {
1138               f = FirstParOnPC;
1139               l = LastParOnPC;
1140               GeomAPI_ProjectPointOnCurve Projector;
1141               if (!Precision::IsInfinite(FirstParOnPC))
1142                 {
1143                   gp_Pnt2d P2d1 = MinPC->Value(FirstParOnPC);
1144                   gp_Pnt P1 = MinSurf->Value( P2d1.X(), P2d1.Y() );
1145                   P1.Transform(MinLoc.Transformation());
1146                   Projector.Init( P1, C3d );
1147                   if (Projector.NbPoints() > 0)
1148                     f = Projector.LowerDistanceParameter();
1149 #ifdef OCCT_DEBUG
1150                   else
1151                     cout<<"ProjectPointOnCurve not done"<<endl;
1152 #endif
1153                 }
1154               if (!Precision::IsInfinite(LastParOnPC))
1155                 {
1156                   gp_Pnt2d P2d2 = MinPC->Value(LastParOnPC);
1157                   gp_Pnt P2 = MinSurf->Value( P2d2.X(), P2d2.Y() );
1158                   P2.Transform(MinLoc.Transformation());
1159                   Projector.Init( P2, C3d );
1160                   if (Projector.NbPoints() > 0)
1161                     l = Projector.LowerDistanceParameter();
1162 #ifdef OCCT_DEBUG
1163                   else
1164                     cout<<"ProjectPointOnCurve not done"<<endl;
1165 #endif
1166                 }
1167             }
1168           BB.Range( NE, f, l );
1169           if (!Precision::IsInfinite(f) && !Precision::IsInfinite(l))
1170             BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True );
1171         }
1172       else if (!BRep_Tool::Degenerated(E)) //no 3d curve
1173         {
1174           MinSurf = Handle(Geom_Surface)::DownCast
1175             (MinSurf->Transformed(MinLoc.Transformation()));
1176           Standard_Real max_deviation = 0.;
1177           if (Precision::IsInfinite(FirstParOnPC) || Precision::IsInfinite(LastParOnPC))
1178             {
1179               if (MinPC->IsInstance(STANDARD_TYPE(Geom2d_Line)))
1180                 {
1181                   Standard_Boolean IsLine = Standard_False;
1182                   if (MinSurf->IsInstance(STANDARD_TYPE(Geom_Plane)))
1183                     IsLine = Standard_True;
1184                   else if (MinSurf->IsInstance(STANDARD_TYPE(Geom_CylindricalSurface)) ||
1185                            MinSurf->IsInstance(STANDARD_TYPE(Geom_ConicalSurface)))
1186                     {
1187                       Handle(Geom2d_Line) theLine = *((Handle(Geom2d_Line)*)&MinPC);
1188                       gp_Dir2d LineDir = theLine->Direction();
1189                       if (LineDir.IsParallel( gp::DY2d(), Precision::Angular() ))
1190                         IsLine = Standard_True;
1191                     }
1192                   if (IsLine)
1193                     {
1194                       gp_Pnt2d P2d1 = MinPC->Value(0.), P2d2 = MinPC->Value(1.);
1195                       gp_Pnt P1 = MinSurf->Value(P2d1.X(), P2d1.Y());
1196                       gp_Pnt P2 = MinSurf->Value(P2d2.X(), P2d2.Y());
1197                       gp_Vec aVec(P1, P2);
1198                       C3d = new Geom_Line( P1, aVec );
1199                     }
1200                 }
1201             }
1202           else
1203             {
1204               Geom2dAdaptor_Curve AC2d( MinPC, FirstParOnPC, LastParOnPC );
1205               GeomAdaptor_Surface GAsurf( MinSurf );
1206               Handle(Geom2dAdaptor_HCurve) HC2d  = new Geom2dAdaptor_HCurve( AC2d );
1207               Handle(GeomAdaptor_HSurface) HSurf = new GeomAdaptor_HSurface( GAsurf );
1208               Adaptor3d_CurveOnSurface ConS( HC2d, HSurf );
1209               Standard_Real /*max_deviation,*/ average_deviation;
1210               GeomAbs_Shape Continuity = GeomAbs_C1;
1211               Standard_Integer MaxDegree = 14;
1212               Standard_Integer MaxSegment = evaluateMaxSegment(ConS);
1213               GeomLib::BuildCurve3d(Precision::Confusion(),
1214                                     ConS, FirstParOnPC, LastParOnPC,
1215                                     C3d, max_deviation, average_deviation,
1216                                     Continuity, MaxDegree, MaxSegment);
1217             }
1218           BB.UpdateEdge( NE, C3d, max_deviation );
1219           //BB.Range( NE, FirstParOnPC, LastParOnPC );
1220           Standard_Boolean ProjectionSuccess = Standard_True;
1221           if (NbPCurves > 1)
1222             //BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True );
1223             for (itr.Initialize((Handle(BRep_TEdge)::DownCast(NE.TShape()))->ChangeCurves());
1224                  itr.More();
1225                  itr.Next())
1226               {
1227                 Handle( BRep_CurveRepresentation ) CurveRep = itr.Value();
1228                 Standard_Real FirstPar, LastPar;
1229                 if (CurveRep->IsCurveOnSurface())
1230                   {
1231                     Handle(Geom2d_Curve) theCurve = CurveRep->PCurve();
1232                     Handle(Geom_Surface) theSurf  = CurveRep->Surface();
1233                     TopLoc_Location      theLoc   = CurveRep->Location();
1234                     if (theCurve == MinPC && theSurf == MinSurf && theLoc == MinLoc)
1235                       continue;
1236                     FirstPar = (Handle(BRep_GCurve)::DownCast(CurveRep))->First();
1237                     LastPar  = (Handle(BRep_GCurve)::DownCast(CurveRep))->Last();
1238                     if (Abs(FirstPar - FirstParOnPC) > Precision::PConfusion() ||
1239                         Abs(LastPar  - LastParOnPC)  > Precision::PConfusion())
1240                       {
1241                         theLoc = E.Location() * theLoc;
1242                         theSurf = Handle(Geom_Surface)::DownCast
1243                           (theSurf->Transformed(theLoc.Transformation()));
1244
1245                         if (theCurve->IsInstance(STANDARD_TYPE(Geom2d_Line)) &&
1246                             theSurf->IsKind(STANDARD_TYPE(Geom_BoundedSurface)))
1247                           {
1248                             gp_Dir2d theDir = (*((Handle(Geom2d_Line)*)&theCurve))->Direction();
1249                             if (theDir.IsParallel(gp::DX2d(), Precision::Angular()) ||
1250                                 theDir.IsParallel(gp::DY2d(), Precision::Angular()))
1251                               {
1252                                 Standard_Real U1, U2, V1, V2;
1253                                 theSurf->Bounds(U1, U2, V1, V2);
1254                                 gp_Pnt2d Origin = (*((Handle(Geom2d_Line)*)&theCurve))->Location();
1255                                 if (Abs(Origin.X()-U1) <= Precision::Confusion() ||
1256                                     Abs(Origin.X()-U2) <= Precision::Confusion() ||
1257                                     Abs(Origin.Y()-V1) <= Precision::Confusion() ||
1258                                     Abs(Origin.Y()-V2) <= Precision::Confusion())
1259                                   {
1260                                     BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True );
1261                                     break;
1262                                   }
1263                               }
1264                           }
1265
1266                         Handle(Geom2d_Curve) ProjPCurve =
1267                           GeomProjLib::Curve2d( C3d, FirstParOnPC, LastParOnPC, theSurf );
1268                         if (ProjPCurve.IsNull())
1269                           ProjectionSuccess = Standard_False;
1270                         else
1271                           CurveRep->PCurve( ProjPCurve );
1272                       }
1273                   }
1274               }
1275           if (ProjectionSuccess)
1276             BB.Range( NE, FirstParOnPC, LastParOnPC );
1277           else
1278             {
1279               BB.Range( NE, FirstParOnPC, LastParOnPC, Standard_True );
1280               BRepLib::SameParameter( NE, Precision::Confusion(), Standard_True );
1281             }
1282         }
1283     }
1284   else //no pcurves
1285     {
1286       Standard_Real FirstPar = C3d->FirstParameter();
1287       Standard_Real LastPar  = C3d->LastParameter();
1288       
1289       if (C3d->IsKind(STANDARD_TYPE(Geom_BoundedCurve)) &&
1290           (FirstPar > anEf - a2Offset || LastPar < anEl + a2Offset))
1291         {
1292           Handle(Geom_TrimmedCurve) aTrCurve = 
1293             new Geom_TrimmedCurve(C3d, FirstPar, LastPar);
1294           
1295           // The curve is not prolonged on begin or end.
1296           // Trying to prolong it adding a segment to its bound.
1297           gp_Pnt                              aPBnd;
1298           gp_Vec                              aVBnd;
1299           gp_Pnt                              aPBeg;
1300           gp_Dir                              aDBnd;
1301           Handle(Geom_Line)                   aLin;
1302           Handle(Geom_TrimmedCurve)           aSegment;
1303           GeomConvert_CompCurveToBSplineCurve aCompCurve(aTrCurve, Convert_RationalC1);
1304           Standard_Real                       aTol = Precision::Confusion();
1305           Standard_Real                       aDelta = Max(a2Offset, 1.);
1306           
1307           if (FirstPar > anEf - a2Offset) {
1308             C3d->D1(FirstPar, aPBnd, aVBnd);
1309             aDBnd.SetXYZ(aVBnd.XYZ());
1310             aPBeg    = aPBnd.Translated(gp_Vec(-aDelta*aDBnd.XYZ()));
1311             aLin     = new Geom_Line(aPBeg, aDBnd);
1312             aSegment = new Geom_TrimmedCurve(aLin, 0, aDelta);
1313             
1314             if (!aCompCurve.Add(aSegment, aTol))
1315               return;
1316           }
1317           
1318           if (LastPar < anEl + a2Offset) {
1319             C3d->D1(LastPar, aPBeg, aVBnd);
1320             aDBnd.SetXYZ(aVBnd.XYZ());
1321             aLin     = new Geom_Line(aPBeg, aDBnd);
1322             aSegment = new Geom_TrimmedCurve(aLin, 0, aDelta);
1323             
1324             if (!aCompCurve.Add(aSegment, aTol))
1325               return;
1326           }
1327           
1328           C3d = aCompCurve.BSplineCurve();
1329           FirstPar = C3d->FirstParameter();
1330           LastPar  = C3d->LastParameter();
1331           BB.UpdateEdge(NE, C3d, Precision::Confusion());
1332         }
1333       else if (C3d->IsPeriodic())
1334         {
1335           Standard_Real delta = (C3d->Period() - (anEl - anEf))*0.5;
1336           delta *= 0.95;
1337           FirstPar = anEf - delta;
1338           LastPar  = anEl + delta;
1339         }
1340       else if (C3d->IsClosed())
1341         LastPar -= 0.05*(LastPar - FirstPar);
1342       
1343       BB.Range( NE, FirstPar, LastPar );
1344     }
1345 }
1346 //  Modified by skv - Fri Dec 26 17:00:57 2003 OCC4455 End
1347
1348
1349 //=======================================================================
1350 //function : UpdateVertex
1351 //purpose  : 
1352 //=======================================================================
1353
1354 static Standard_Boolean  UpdateVertex(TopoDS_Vertex V,
1355                                       TopoDS_Edge&  OE,
1356                                       TopoDS_Edge&  NE,
1357                                       Standard_Real TolConf)
1358 {
1359   BRepAdaptor_Curve OC(OE);
1360   BRepAdaptor_Curve NC(NE);
1361   Standard_Real Of = OC.FirstParameter(); Standard_Real Ol = OC.LastParameter();
1362   Standard_Real Nf = NC.FirstParameter(); Standard_Real Nl = NC.LastParameter();
1363   Standard_Real U = 0.;
1364   Standard_Real ParTol = Precision::PConfusion();
1365   gp_Pnt           P  = BRep_Tool::Pnt(V);
1366   Standard_Boolean OK = Standard_False;
1367
1368   if (P.Distance(OC.Value(Of)) < TolConf) {
1369     if (Of >= Nf + ParTol && Of <= Nl + ParTol  && P.Distance(NC.Value(Of)) < TolConf) {
1370       OK = Standard_True;
1371       U    = Of;
1372     }
1373   }
1374   if (P.Distance(OC.Value(Ol)) < TolConf) {
1375     if (Ol >= Nf + ParTol && Ol <= Nl + ParTol  && P.Distance(NC.Value(Ol)) < TolConf) {
1376       OK = Standard_True;
1377       U    = Ol;
1378     }
1379   }
1380   if (OK) {
1381     BRep_Builder B;
1382     TopoDS_Shape aLocalShape = NE.Oriented(TopAbs_FORWARD);
1383     TopoDS_Edge EE = TopoDS::Edge(aLocalShape);
1384 //    TopoDS_Edge EE = TopoDS::Edge(NE.Oriented(TopAbs_FORWARD));
1385     aLocalShape = V.Oriented(TopAbs_INTERNAL);
1386     B.UpdateVertex(TopoDS::Vertex(aLocalShape),
1387                    U,NE,BRep_Tool::Tolerance(NE));
1388 //    B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
1389 //                 U,NE,BRep_Tool::Tolerance(NE));
1390   }
1391   return OK;  
1392 }
1393
1394 //=======================================================================
1395 //function : Compute
1396 //purpose  : 
1397 //=======================================================================
1398
1399 void BRepOffset_Inter2d::Compute (const Handle(BRepAlgo_AsDes)&     AsDes,
1400                                   const TopoDS_Face&                F,
1401                                   const TopTools_IndexedMapOfShape& NewEdges,
1402                                   const Standard_Real               Tol)
1403 {
1404 #ifdef DRAW
1405   NbF2d++;
1406   NbE2d = 0;
1407 #endif 
1408
1409   //Do not intersect the edges of face
1410   TopTools_MapOfShape EdgesOfFace;
1411   TopExp_Explorer Explo( F, TopAbs_EDGE );
1412   for (; Explo.More(); Explo.Next())
1413     EdgesOfFace.Add( Explo.Current() );
1414
1415   //-----------------------------------------------------------
1416   // calculate intersections2d on faces touched by  
1417   // intersection3d
1418   //---------------------------------------------------------
1419   TopTools_ListIteratorOfListOfShape it1LE ;    
1420   TopTools_ListIteratorOfListOfShape it2LE ;  
1421
1422   //-----------------------------------------------
1423   // Intersection of edges 2*2.
1424   //-----------------------------------------------
1425   const TopTools_ListOfShape&        LE = AsDes->Descendant(F);
1426   TopoDS_Vertex                      V1,V2;
1427   Standard_Integer                   j, i = 1;
1428
1429   for ( it1LE.Initialize(LE) ; it1LE.More(); it1LE.Next()) {
1430     const TopoDS_Edge& E1 = TopoDS::Edge(it1LE.Value());        
1431     j = 1;
1432     it2LE.Initialize(LE);
1433     
1434     while (j < i && it2LE.More()) {
1435       const TopoDS_Edge& E2 = TopoDS::Edge(it2LE.Value());
1436       //--------------------------------------------------------------
1437       // Intersections of New edges obtained by intersection
1438       // between them and with edges of restrictions
1439       //------------------------------------------------------
1440       if ( (!EdgesOfFace.Contains(E1) || !EdgesOfFace.Contains(E2)) &&
1441            (NewEdges.Contains(E1) || NewEdges.Contains(E2)) ) {
1442         TopoDS_Shape aLocalShape = F.Oriented(TopAbs_FORWARD);
1443         EdgeInter(TopoDS::Face(aLocalShape),E1,E2,AsDes,Tol,Standard_True);
1444 //        EdgeInter(TopoDS::Face(F.Oriented(TopAbs_FORWARD)),E1,E2,AsDes,Tol,Standard_True);
1445       }
1446       it2LE.Next();
1447       j++;
1448     }
1449     i++;
1450   }
1451 }
1452
1453 //=======================================================================
1454 //function : ConnexIntByInt
1455 //purpose  : 
1456 //=======================================================================
1457
1458 //  Modified by skv - Fri Dec 26 16:53:16 2003 OCC4455 Begin
1459 //  Add another parameter: offset value.
1460 void BRepOffset_Inter2d::ConnexIntByInt
1461 (const TopoDS_Face&            FI,
1462  BRepOffset_Offset&            OFI,
1463  TopTools_DataMapOfShapeShape& MES,
1464  const TopTools_DataMapOfShapeShape& Build,
1465  const Handle(BRepAlgo_AsDes)&     AsDes,
1466  const Standard_Real           Offset,
1467  const Standard_Real           Tol)
1468 //  Modified by skv - Fri Dec 26 16:53:18 2003 OCC4455 End
1469 {  
1470
1471   TopTools_DataMapOfShapeListOfShape MVE;
1472   BRepOffset_Tool::MapVertexEdges(FI,MVE);
1473
1474   //---------------------
1475   // Extension of edges.
1476   //---------------------
1477   TopoDS_Edge  NE;
1478   TopTools_DataMapIteratorOfDataMapOfShapeListOfShape it(MVE);
1479   for  ( ; it.More(); it.Next()) {
1480     const TopTools_ListOfShape&  L = it.Value();
1481     Standard_Boolean   YaBuild = 0;
1482     TopTools_ListIteratorOfListOfShape itL(L);
1483     for (; itL.More(); itL.Next()) {
1484       YaBuild = Build.IsBound(itL.Value());
1485       if (YaBuild) break;
1486     }
1487     if (YaBuild) {
1488       for (itL.Initialize(L); itL.More(); itL.Next()) {
1489         const TopoDS_Edge& EI = TopoDS::Edge(itL.Value());
1490         TopoDS_Shape aLocalShape = OFI.Generated(EI);
1491         const TopoDS_Edge& OE = TopoDS::Edge(aLocalShape);
1492 //      const TopoDS_Edge& OE = TopoDS::Edge(OFI.Generated(EI));
1493         if (!MES.IsBound(OE) && !Build.IsBound(EI)) {
1494 //  Modified by skv - Fri Dec 26 16:59:52 2003 OCC4455 Begin
1495 //        ExtentEdge(OE,NE);
1496           ExtentEdge(OE,NE, Offset);
1497 //  Modified by skv - Fri Dec 26 16:59:54 2003 OCC4455 End
1498           MES.Bind  (OE,NE);
1499         }
1500       }
1501     } 
1502   }
1503   
1504   TopoDS_Face           FIO = TopoDS::Face(OFI.Face());
1505   if (MES.IsBound(FIO)) FIO = TopoDS::Face(MES(FIO));
1506
1507   TopExp_Explorer exp(FI.Oriented(TopAbs_FORWARD),TopAbs_WIRE);
1508   for (; exp.More(); exp.Next()) {
1509     const TopoDS_Wire&     W = TopoDS::Wire(exp.Current());
1510     BRepTools_WireExplorer wexp;
1511     Standard_Boolean       end = Standard_False ;
1512     TopoDS_Edge            FirstE,CurE,NextE;
1513
1514     TopoDS_Shape aLocalWire = W .Oriented(TopAbs_FORWARD);
1515     TopoDS_Shape aLocalFace = FI.Oriented(TopAbs_FORWARD);
1516     wexp.Init(TopoDS::Wire(aLocalWire),TopoDS::Face(aLocalFace));
1517 //    wexp.Init(TopoDS::Wire(W .Oriented(TopAbs_FORWARD)),
1518 //            TopoDS::Face(FI.Oriented(TopAbs_FORWARD)));
1519     CurE = FirstE  = wexp.Current(); 
1520     while (!end) {
1521       wexp.Next();
1522       if (wexp.More()) {
1523         NextE = wexp.Current();
1524       } 
1525       else {
1526         NextE = FirstE; end = Standard_True;
1527       }
1528       if (CurE.IsSame(NextE)) continue;
1529
1530       //IFV------------
1531       TopoDS_Vertex Vref = CommonVertex(CurE, NextE); 
1532       gp_Pnt Pref = BRep_Tool::Pnt(Vref);
1533       //IFV------------
1534
1535       TopoDS_Shape aLocalShape = OFI.Generated(CurE);
1536       TopoDS_Edge CEO = TopoDS::Edge(aLocalShape);
1537       aLocalShape = OFI.Generated(NextE);
1538       TopoDS_Edge NEO = TopoDS::Edge(aLocalShape);
1539 //      TopoDS_Edge CEO = TopoDS::Edge(OFI.Generated(CurE));
1540 //      TopoDS_Edge NEO = TopoDS::Edge(OFI.Generated(NextE));
1541       //------------------------------------------
1542       // Inter processing of images of CurE NextE.
1543       //------------------------------------------
1544       TopTools_ListOfShape LV1,LV2;
1545       Standard_Boolean     DoInter = 1;
1546       TopoDS_Shape         NE1,NE2;
1547       
1548       if (Build.IsBound(CurE) && Build.IsBound(NextE)) {
1549         NE1 = Build(CurE );
1550         NE2 = Build(NextE);
1551       }
1552       else if (Build.IsBound(CurE) && MES.IsBound(NEO)) {
1553         NE1 = Build(CurE);
1554         NE2 = MES  (NEO);
1555       }
1556       else if (Build.IsBound(NextE) && MES.IsBound(CEO)) {
1557         NE1 = Build(NextE);
1558         NE2 = MES(CEO);
1559       }
1560       else {
1561         DoInter = 0;
1562       }
1563       if (DoInter) {
1564         //------------------------------------
1565         // NE1,NE2 can be a compound of Edges.
1566         //------------------------------------
1567         TopExp_Explorer Exp1,Exp2;
1568         for (Exp1.Init(NE1,TopAbs_EDGE) ; Exp1.More(); Exp1.Next()) {
1569           for (Exp2.Init(NE2,TopAbs_EDGE) ; Exp2.More(); Exp2.Next()) {
1570             RefEdgeInter(FIO,TopoDS::Edge(Exp1.Current()),TopoDS::Edge(Exp2.Current()),
1571                       AsDes,Tol,Standard_True/*Standard_False*/, Pref);
1572           }
1573         }
1574       }
1575       else {
1576         if (MES.IsBound(CEO)) {
1577           TopoDS_Vertex  V = CommonVertex(CEO,NEO); 
1578           UpdateVertex  (V,CEO,TopoDS::Edge(MES(CEO)),Tol);
1579           AsDes->Add     (MES(CEO),V);
1580         }
1581         else if (MES.IsBound(NEO)) {
1582           TopoDS_Vertex V = CommonVertex(CEO,NEO); 
1583           UpdateVertex (V,NEO,TopoDS::Edge(MES(NEO)),Tol);
1584           AsDes->Add    (MES(NEO),V);
1585         }
1586       }
1587       CurE = NextE;
1588     }
1589   }
1590 }
1591
1592
1593