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