0028577: Get rid of the TopOpeBRep* algorithms in TKOffset toolkit
[occt.git] / src / BRepOffset / BRepOffset_Tool.cxx
1 // Created on: 1995-10-23
2 // Created by: Yves FRICAUD
3 // Copyright (c) 1995-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
18 #include <Bnd_Box2d.hxx>
19 #include <BndLib_Add3dCurve.hxx>
20 #include <BOPAlgo_PaveFiller.hxx>
21 #include <BOPDS_DS.hxx>
22 #include <BOPTools_AlgoTools2D.hxx>
23 #include <BRep_CurveRepresentation.hxx>
24 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
25 #include <BRep_TEdge.hxx>
26 #include <BRep_Tool.hxx>
27 #include <BRep_Builder.hxx>
28 #include <BRepAdaptor_Curve.hxx>
29 #include <BRepAdaptor_Curve2d.hxx>
30 #include <BRepAdaptor_HCurve.hxx>
31 #include <BRepAdaptor_HSurface.hxx>
32 #include <BRepAdaptor_Surface.hxx>
33 #include <BRepAlgo_AsDes.hxx>
34 #include <BRepAlgo_Image.hxx>
35 #include <BRepAlgo_Tool.hxx>
36 #include <BRepBndLib.hxx>
37 #include <BRepLib.hxx>
38 #include <BRepLib_MakeEdge.hxx>
39 #include <BRepLib_MakeFace.hxx>
40 #include <BRepLib_MakePolygon.hxx>
41 #include <BRepLib_MakeVertex.hxx>
42 #include <BRepLib_MakeWire.hxx>
43 #include <BRepOffset_Analyse.hxx>
44 #include <BRepOffset_Interval.hxx>
45 #include <BRepOffset_ListOfInterval.hxx>
46 #include <BRepOffset_Tool.hxx>
47 #include <BRepTools.hxx>
48 #include <BRepTools_Modifier.hxx>
49 #include <BRepTools_TrsfModification.hxx>
50 #include <BRepTools_WireExplorer.hxx>
51 #include <BRepTopAdaptor_FClass2d.hxx>
52 #include <ElCLib.hxx>
53 #include <ElSLib.hxx>
54 #include <Extrema_ExtPC.hxx>
55 #include <Extrema_ExtPC2d.hxx>
56 #include <GCPnts_AbscissaPoint.hxx>
57 #include <GCPnts_QuasiUniformDeflection.hxx>
58 #include <GCPnts_UniformAbscissa.hxx>
59 #include <Geom2d_BezierCurve.hxx>
60 #include <Geom2d_BSplineCurve.hxx>
61 #include <Geom2d_Circle.hxx>
62 #include <Geom2d_Curve.hxx>
63 #include <Geom2d_Ellipse.hxx>
64 #include <Geom2d_Hyperbola.hxx>
65 #include <Geom2d_Line.hxx>
66 #include <Geom2d_Parabola.hxx>
67 #include <Geom2d_TrimmedCurve.hxx>
68 #include <Geom2dAdaptor_Curve.hxx>
69 #include <Geom2dConvert_ApproxCurve.hxx>
70 #include <Geom2dConvert_CompCurveToBSplineCurve.hxx>
71 #include <Geom2dInt_GInter.hxx>
72 #include <Geom_BezierSurface.hxx>
73 #include <Geom_BSplineCurve.hxx>
74 #include <Geom_BSplineSurface.hxx>
75 #include <Geom_Conic.hxx>
76 #include <Geom_ConicalSurface.hxx>
77 #include <Geom_Curve.hxx>
78 #include <Geom_Line.hxx>
79 #include <Geom_OffsetSurface.hxx>
80 #include <Geom_Plane.hxx>
81 #include <Geom_RectangularTrimmedSurface.hxx>
82 #include <Geom_Surface.hxx>
83 #include <Geom_SurfaceOfLinearExtrusion.hxx>
84 #include <Geom_SurfaceOfRevolution.hxx>
85 #include <Geom_TrimmedCurve.hxx>
86 #include <GeomAdaptor_Surface.hxx>
87 #include <GeomAPI.hxx>
88 #include <GeomAPI_ExtremaCurveCurve.hxx>
89 #include <GeomAPI_ProjectPointOnCurve.hxx>
90 #include <GeomConvert_ApproxCurve.hxx>
91 #include <GeomConvert_CompCurveToBSplineCurve.hxx>
92 #include <GeomInt_IntSS.hxx>
93 #include <GeomLib.hxx>
94 #include <GeomProjLib.hxx>
95 #include <gp.hxx>
96 #include <gp_Pnt.hxx>
97 #include <gp_Vec.hxx>
98 #include <IntRes2d_IntersectionPoint.hxx>
99 #include <IntRes2d_IntersectionSegment.hxx>
100 #include <Precision.hxx>
101 #include <ProjLib_HProjectedCurve.hxx>
102 #include <ProjLib_ProjectedCurve.hxx>
103 #include <ShapeCustom_Curve2d.hxx>
104 #include <Standard_ConstructionError.hxx>
105 #include <TColgp_Array1OfPnt2d.hxx>
106 #include <TopAbs.hxx>
107 #include <TopExp.hxx>
108 #include <TopExp_Explorer.hxx>
109 #include <TopoDS.hxx>
110 #include <TopoDS_Compound.hxx>
111 #include <TopoDS_Edge.hxx>
112 #include <TopoDS_Face.hxx>
113 #include <TopoDS_Iterator.hxx>
114 #include <TopoDS_Shape.hxx>
115 #include <TopoDS_Vertex.hxx>
116 #include <TopoDS_Wire.hxx>
117 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
118 #include <TopTools_ListIteratorOfListOfShape.hxx>
119 #include <TopTools_SequenceOfShape.hxx>
120
121 #include <stdio.h>
122 //tma: for new boolean operation
123 #ifdef DRAW
124 #include <DBRep.hxx>
125 #include <Geom2d_Conic.hxx>
126 #include <Geom_ElementarySurface.hxx>
127 #include <Geom_BoundedCurve.hxx>
128 Standard_Boolean AffichInter  = Standard_False;
129 static Standard_Integer NbNewEdges  = 1;
130 static Standard_Integer NbFaces     = 1;
131 static Standard_Integer NbFOB       = 1;
132 static Standard_Integer NbFTE       = 1;
133 static Standard_Integer NbExtE      = 1;
134 #endif
135
136 #ifdef OCCT_DEBUG
137 static Standard_Boolean AffichExtent = Standard_False;
138 #endif
139
140 //=======================================================================
141 //function : EdgeVertices
142 //purpose  : 
143 //=======================================================================
144
145 void BRepOffset_Tool::EdgeVertices (const TopoDS_Edge&   E,
146                                     TopoDS_Vertex& V1, 
147                                     TopoDS_Vertex& V2)
148 {
149   if (E.Orientation() == TopAbs_REVERSED) {
150     TopExp::Vertices(E,V2,V1);
151   }
152   else {
153     TopExp::Vertices(E,V1,V2);
154   }
155 }
156
157 //=======================================================================
158 //function : OriEdgeInFace
159 //purpose  : 
160 //=======================================================================
161
162 TopAbs_Orientation BRepOffset_Tool::OriEdgeInFace (const TopoDS_Edge& E,
163                                                    const TopoDS_Face& F )
164
165 {
166   TopExp_Explorer Exp;
167   Exp.Init(F.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
168
169   for (; Exp.More() ;Exp.Next()) {
170     if (Exp.Current().IsSame(E)) {
171       return Exp.Current().Orientation();
172     }
173   }
174   throw Standard_ConstructionError("BRepOffset_Tool::OriEdgeInFace");
175 }
176
177
178 //=======================================================================
179 //function : FindPeriod
180 //purpose  : 
181 //=======================================================================
182
183 static void FindPeriod (const TopoDS_Face& F,
184                         Standard_Real&     umin,
185                         Standard_Real&     umax,
186                         Standard_Real&     vmin,
187                         Standard_Real&     vmax)
188 {
189
190   Bnd_Box2d B;
191   TopExp_Explorer exp;
192   for (exp.Init(F,TopAbs_EDGE); exp.More(); exp.Next()) {
193     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
194     
195     Standard_Real pf,pl;
196     const Handle(Geom2d_Curve) C = BRep_Tool::CurveOnSurface(E,F,pf,pl);
197     if (C.IsNull()) return;
198     Geom2dAdaptor_Curve PC(C,pf,pl);
199     Standard_Real i, nbp = 20;
200     if (PC.GetType() == GeomAbs_Line) nbp = 2;
201     Standard_Real step = (pl - pf) / nbp;
202     gp_Pnt2d P;
203     PC.D0(pf,P);
204     B.Add(P);
205     for (i = 2; i < nbp; i++) {
206       pf += step;
207       PC.D0(pf,P);
208       B.Add(P);
209     }
210     PC.D0(pl,P);
211     B.Add(P);
212     B.Get(umin,vmin,umax,vmax);
213   }
214 }
215
216 //=======================================================================
217 //function : PutInBounds
218 //purpose  : Recadre la courbe 2d dans les bounds de la face
219 //=======================================================================
220
221 static void PutInBounds (const TopoDS_Face&          F,
222                          const TopoDS_Edge&          E,
223                          Handle(Geom2d_Curve)&       C2d)
224 {
225   Standard_Real   umin,umax,vmin,vmax;
226   Standard_Real   f,l;
227   BRep_Tool::Range(E,f,l);  
228
229   TopLoc_Location L; // Recup S avec la location pour eviter la copie.
230   Handle (Geom_Surface) S   = BRep_Tool::Surface(F,L);
231
232   if (S->IsInstance(STANDARD_TYPE(Geom_RectangularTrimmedSurface))) {
233     S = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
234   }
235   //---------------
236   // Recadre en U.
237   //---------------
238   if (!S->IsUPeriodic() && !S->IsVPeriodic()) return;
239
240   FindPeriod (F,umin,umax,vmin,vmax);
241
242   if (S->IsUPeriodic()) {
243     Standard_Real period  = S->UPeriod();
244     Standard_Real eps     = period*1.e-6;
245     gp_Pnt2d      Pf      = C2d->Value(f);
246     gp_Pnt2d      Pl      = C2d->Value(l);
247     gp_Pnt2d      Pm      = C2d->Value(0.34*f + 0.66*l);
248     Standard_Real minC    = Min(Pf.X(),Pl.X()); minC = Min(minC,Pm.X());
249     Standard_Real maxC    = Max(Pf.X(),Pl.X()); maxC = Max(maxC,Pm.X());
250     Standard_Real du = 0.;
251     if (minC< umin - eps) {
252       du = (int((umin - minC)/period) + 1)*period;
253     }
254     if (minC > umax + eps) {
255       du = -(int((minC - umax)/period) + 1)*period;
256     }
257     if (du != 0) {
258       gp_Vec2d T1(du,0.);
259       C2d->Translate(T1);
260       minC += du; maxC += du;
261     }
262     // Ajuste au mieux la courbe dans le domaine.
263     if (maxC > umax +100*eps) {
264       Standard_Real d1 = maxC - umax;
265       Standard_Real d2 = umin - minC + period;
266       if (d2 < d1) du =-period;
267       if ( du != 0.) {
268         gp_Vec2d T2(du,0.);
269         C2d->Translate(T2);
270       }
271     }
272   }
273   //------------------
274   // Recadre en V.
275   //------------------
276   if (S->IsVPeriodic()) {
277     Standard_Real period  = S->VPeriod();
278     Standard_Real eps     = period*1.e-6;
279     gp_Pnt2d      Pf      = C2d->Value(f);
280     gp_Pnt2d      Pl      = C2d->Value(l);
281     gp_Pnt2d      Pm      = C2d->Value(0.34*f + 0.66*l);
282     Standard_Real minC    = Min(Pf.Y(),Pl.Y()); minC = Min(minC,Pm.Y());
283     Standard_Real maxC    = Max(Pf.Y(),Pl.Y()); maxC = Max(maxC,Pm.Y());
284     Standard_Real dv = 0.;
285     if (minC< vmin - eps) {
286       dv = (int((vmin - minC)/period) + 1)*period;
287     }
288     if (minC > vmax + eps) {
289       dv = -(int((minC - vmax)/period) + 1)*period;
290     }
291     if (dv != 0) {
292       gp_Vec2d T1(0.,dv);
293       C2d->Translate(T1);
294       minC += dv; maxC += dv;
295     }
296     // Ajuste au mieux la courbe dans le domaine.
297     if (maxC > vmax +100*eps) {
298       Standard_Real d1 = maxC - vmax;
299       Standard_Real d2 = vmin - minC + period;
300       if (d2 < d1) dv =-period;
301       if ( dv != 0.) {
302         gp_Vec2d T2(0.,dv);
303         C2d->Translate(T2);
304       }
305     }
306   }
307 }
308
309 //=======================================================================
310 //function : Gabarit
311 //purpose  : 
312 //=======================================================================
313
314 Standard_Real BRepOffset_Tool::Gabarit(const Handle(Geom_Curve)& aCurve)
315 {
316   GeomAdaptor_Curve GC( aCurve );
317   Bnd_Box aBox;
318   BndLib_Add3dCurve::Add( GC, Precision::Confusion(), aBox );
319   Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, dist;
320   aBox.Get( aXmin, aYmin, aZmin, aXmax, aYmax, aZmax );
321   dist = Max( (aXmax-aXmin), (aYmax-aYmin) );
322   dist = Max( dist, (aZmax-aZmin) );
323   return dist;
324 }
325
326 //=======================================================================
327 //function : BuildPCurves
328 //purpose  : 
329 //=======================================================================
330
331 static void BuildPCurves (const TopoDS_Edge&  E,
332                           const TopoDS_Face&  F)
333
334   Standard_Real   ff,ll;
335   Handle (Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface (E,F,ff,ll);
336   if (!C2d.IsNull()) return;
337
338   //Standard_Real Tolerance = Max(Precision::Confusion(),BRep_Tool::Tolerance(E));
339   Standard_Real Tolerance = Precision::Confusion();
340
341   BRepAdaptor_Surface AS(F,0);
342   BRepAdaptor_Curve   AC(E);
343
344   //Try to find pcurve on a bound of BSpline or Bezier surface
345   Handle( Geom_Surface ) theSurf = BRep_Tool::Surface( F );
346   Handle( Standard_Type ) typS = theSurf->DynamicType();
347   if (typS == STANDARD_TYPE(Geom_OffsetSurface))
348     typS = Handle(Geom_OffsetSurface)::DownCast (theSurf)->BasisSurface()->DynamicType();
349   if (typS == STANDARD_TYPE(Geom_BezierSurface) || typS == STANDARD_TYPE(Geom_BSplineSurface))
350     {
351       gp_Pnt fpoint = AC.Value( AC.FirstParameter() );
352       gp_Pnt lpoint = AC.Value( AC.LastParameter() );
353       TopoDS_Face theFace = BRepLib_MakeFace( theSurf, Precision::Confusion() );
354       Standard_Real U1 = 0., U2 = 0., TolProj = 1.e-4; //1.e-5;
355       TopoDS_Edge theEdge;
356       TopExp_Explorer Explo;
357       Explo.Init( theFace, TopAbs_EDGE );
358       for (; Explo.More(); Explo.Next())
359         {
360           TopoDS_Edge anEdge = TopoDS::Edge( Explo.Current() );
361           BRepAdaptor_Curve aCurve( anEdge );
362           Extrema_ExtPC fextr( fpoint, aCurve );
363           if (!fextr.IsDone() || fextr.NbExt() < 1)
364             continue;
365           Standard_Real dist2, dist2min = RealLast();
366           Standard_Integer i;
367           for (i = 1; i <= fextr.NbExt(); i++)
368             {
369               dist2 = fextr.SquareDistance(i);
370               if (dist2 < dist2min)
371                 {
372                   dist2min = dist2;
373                   U1 = fextr.Point(i).Parameter();
374                 }
375             }
376           if (dist2min > TolProj * TolProj)
377             continue;
378           Extrema_ExtPC lextr( lpoint, aCurve );
379           if (!lextr.IsDone() || lextr.NbExt() <1)
380             continue;
381           dist2min = RealLast();
382           for (i = 1; i <= lextr.NbExt(); i++)
383             {
384               dist2 = lextr.SquareDistance(i);
385               if (dist2 < dist2min)
386                 {
387                   dist2min = dist2;
388                   U2 = lextr.Point(i).Parameter();
389                 }
390             }
391           if (dist2min <= TolProj * TolProj)
392             {
393               theEdge = anEdge;
394               break;
395             }
396         } // for (; Explo.More(); Explo.Current())
397       
398       if (! theEdge.IsNull())
399         {
400           //Construction of pcurve
401           if (U2 < U1)
402             {
403               Standard_Real temp = U1;
404               U1 = U2;
405               U2 = temp;
406             }
407           Standard_Real f, l;
408           C2d = BRep_Tool::CurveOnSurface( theEdge, theFace, f, l );
409           C2d = new Geom2d_TrimmedCurve( C2d, U1, U2 );
410
411           if (theSurf->IsUPeriodic() || theSurf->IsVPeriodic())
412             PutInBounds( F, E, C2d );
413
414           BRep_Builder B;
415           B.UpdateEdge( E, C2d, F, BRep_Tool::Tolerance(E) );
416           BRepLib::SameRange( E );
417
418           return;
419         }
420     } // if (typS == ...
421
422   Handle(BRepAdaptor_HSurface) HS = new BRepAdaptor_HSurface(AS);
423   Handle(BRepAdaptor_HCurve)   HC = new BRepAdaptor_HCurve(AC);
424
425   ProjLib_ProjectedCurve Proj(HS,HC,Tolerance);
426   
427   switch ( Proj.GetType()) {
428
429   case GeomAbs_Line:
430     C2d = new Geom2d_Line(Proj.Line());
431     break;
432
433   case GeomAbs_Circle:
434     C2d = new Geom2d_Circle(Proj.Circle());
435     break;
436
437   case GeomAbs_Ellipse:
438     C2d = new Geom2d_Ellipse(Proj.Ellipse());
439     break;
440
441   case GeomAbs_Parabola:
442     C2d = new Geom2d_Parabola(Proj.Parabola());
443     break;
444
445   case GeomAbs_Hyperbola:
446     C2d = new Geom2d_Hyperbola(Proj.Hyperbola());
447     break;
448
449   case GeomAbs_BezierCurve:
450     C2d = Proj.Bezier();
451     break;
452
453   case GeomAbs_BSplineCurve:
454     C2d = Proj.BSpline();
455     break;
456   default:
457     break;
458   }
459
460   if (AS.IsUPeriodic() || AS.IsVPeriodic()) {
461     PutInBounds(F,E,C2d);
462   }
463   if (!C2d.IsNull()) {
464     BRep_Builder    B;
465     B.UpdateEdge (E,C2d,F,BRep_Tool::Tolerance(E));
466   }
467   else {
468     throw Standard_ConstructionError("BRepOffset_Tool::BuildPCurves");
469   }
470 }
471
472 //=======================================================================
473 //function : OriSect
474 //purpose  : 
475 //=======================================================================
476
477 void BRepOffset_Tool::OrientSection (const TopoDS_Edge&  E,
478                                      const TopoDS_Face&  F1,
479                                      const TopoDS_Face&  F2,
480                                      TopAbs_Orientation& O1,
481                                      TopAbs_Orientation& O2) 
482 {
483   TopLoc_Location L;
484   Standard_Real   f,l;
485   
486   
487   Handle (Geom_Surface) S1 = BRep_Tool::Surface(F1);
488   Handle (Geom_Surface) S2 = BRep_Tool::Surface(F2);    
489   Handle (Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(E,F1,f,l);
490   Handle (Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(E,F2,f,l); 
491   Handle (Geom_Curve)   C  = BRep_Tool::Curve(E,L,f,l);
492
493   BRepAdaptor_Curve BAcurve( E );
494   
495   GCPnts_AbscissaPoint AP(BAcurve,GCPnts_AbscissaPoint::Length(BAcurve)/2.0,f);
496   Standard_Real ParOnC;
497
498   if(AP.IsDone())
499     ParOnC = AP.Parameter();
500   else
501     ParOnC = BOPTools_AlgoTools2D::IntermediatePoint(f, l);
502
503   gp_Vec T1 = C->DN(ParOnC,1).Transformed(L.Transformation());
504   if (T1.SquareMagnitude() > gp::Resolution()) {
505     T1.Normalize();
506   }
507
508   gp_Pnt2d P  = C1->Value(ParOnC);
509   gp_Pnt   P3;
510   gp_Vec   D1U,D1V;
511   
512   S1->D1(P.X(),P.Y(),P3,D1U,D1V);
513   gp_Vec DN1(D1U^D1V);
514   if (F1.Orientation() == TopAbs_REVERSED) DN1.Reverse();
515   
516   P = C2->Value(ParOnC);
517   S2->D1(P.X(),P.Y(),P3,D1U,D1V);
518   gp_Vec DN2(D1U^D1V);
519   if (F2.Orientation() == TopAbs_REVERSED) DN2.Reverse();
520   
521   gp_Vec        ProVec = DN2^T1;
522   Standard_Real Prod  =  DN1.Dot(ProVec);
523   if (Prod < 0.0) {
524     O1 = TopAbs_FORWARD;
525   }
526   else {
527     O1 = TopAbs_REVERSED;
528   }
529   ProVec = DN1^T1;
530   Prod  =  DN2.Dot(ProVec);
531   if (Prod < 0.0) {
532     O2 = TopAbs_FORWARD;
533   }
534   else {
535     O2 = TopAbs_REVERSED;
536   }
537   if (F1.Orientation() == TopAbs_REVERSED) O1 = TopAbs::Reverse(O1);
538   if (F2.Orientation() == TopAbs_REVERSED) O2 = TopAbs::Reverse(O2);
539 }
540
541 //=======================================================================
542 //function : FindCommonShapes
543 //purpose  : 
544 //=======================================================================
545 Standard_Boolean BRepOffset_Tool::FindCommonShapes(const TopoDS_Face& theF1,
546                                                    const TopoDS_Face& theF2,
547                                                    TopTools_ListOfShape& theLE,
548                                                    TopTools_ListOfShape& theLV)
549 {
550   Standard_Boolean bFoundEdges =
551     FindCommonShapes(theF1, theF2, TopAbs_EDGE,   theLE);
552   Standard_Boolean bFoundVerts =
553     FindCommonShapes(theF1, theF2, TopAbs_VERTEX, theLV);
554   return bFoundEdges || bFoundVerts;
555 }
556
557 //=======================================================================
558 //function : FindCommonShapes
559 //purpose  : 
560 //=======================================================================
561 Standard_Boolean BRepOffset_Tool::FindCommonShapes(const TopoDS_Shape& theS1,
562                                                    const TopoDS_Shape& theS2,
563                                                    const TopAbs_ShapeEnum theType,
564                                                    TopTools_ListOfShape& theLSC)
565 {
566   theLSC.Clear();
567   //
568   TopTools_MapOfShape aMS;
569   TopExp_Explorer aExp(theS1, theType);
570   for (; aExp.More(); aExp.Next()) {
571     aMS.Add(aExp.Current());
572   }
573   //
574   if (aMS.IsEmpty()) {
575     return Standard_False;
576   }
577   //
578   TopTools_MapOfShape aMFence;
579   aExp.Init(theS2, theType);
580   for (; aExp.More(); aExp.Next()) {
581     const TopoDS_Shape& aS2 = aExp.Current();
582     if (aMS.Contains(aS2)) {
583       if (aMFence.Add(aS2)) {
584         theLSC.Append(aS2);
585       }
586     }
587   }
588   //
589   return !theLSC.IsEmpty();
590 }
591
592 //=======================================================================
593 //function : ToSmall
594 //purpose  : 
595 //=======================================================================
596
597 static Standard_Boolean ToSmall (const Handle(Geom_Curve)& C)
598 {
599   Standard_Real Tol = 10*Precision::Confusion();
600   Standard_Real m   = (C->FirstParameter()*0.668 + C->LastParameter()*0.332); 
601   gp_Pnt P1 = C->Value(C->FirstParameter());
602   gp_Pnt P2 = C->Value(C->LastParameter());
603   gp_Pnt P3 = C->Value(m);
604   if (P1.Distance(P2) > Tol) return Standard_False;
605   if (P2.Distance(P3) > Tol) return Standard_False;
606   return Standard_True;
607 }
608
609
610 //=======================================================================
611 //function : IsOnSurface
612 //purpose  : 
613 //=======================================================================
614
615 static Standard_Boolean IsOnSurface(const Handle(Geom_Curve)&   C,
616                                     const Handle(Geom_Surface)& S,
617                                     Standard_Real               TolConf,
618                                     Standard_Real&              TolReached) 
619 {
620   Standard_Real    f = C->FirstParameter();
621   Standard_Real    l = C->LastParameter();
622   Standard_Integer n = 5;
623   Standard_Real du = (f-l)/(n-1);
624   TolReached = 0.;
625
626   gp_Pnt P;
627   Standard_Real U,V;
628
629   GeomAdaptor_Surface AS(S);
630
631   switch ( AS.GetType()) {
632   case GeomAbs_Plane:
633     {
634       gp_Ax3 Ax = AS.Plane().Position();
635       for ( Standard_Integer i = 0; i < n; i++) {
636         P = C->Value(f+i*du);
637         ElSLib::PlaneParameters(Ax,P,U,V); 
638         TolReached = P.Distance(ElSLib::PlaneValue(U,V,Ax));
639         if ( TolReached  > TolConf)
640           return Standard_False;
641       }
642       break;
643     }
644   case GeomAbs_Cylinder:
645     {
646       gp_Ax3        Ax  = AS.Cylinder().Position();
647       Standard_Real Rad = AS.Cylinder().Radius();
648       for ( Standard_Integer i = 0; i < n; i++) {
649         P = C->Value(f+i*du);
650         ElSLib::CylinderParameters(Ax,Rad,P,U,V); 
651         TolReached = P.Distance(ElSLib::CylinderValue(U,V,Ax,Rad));
652         if ( TolReached > TolConf)
653           return Standard_False;
654       }
655       break;
656     }
657   case GeomAbs_Cone:
658     {
659       gp_Ax3        Ax  = AS.Cone().Position();
660       Standard_Real Rad = AS.Cone().RefRadius();
661       Standard_Real Alp = AS.Cone().SemiAngle();
662       for ( Standard_Integer i = 0; i < n; i++) {
663         P = C->Value(f+i*du);
664         ElSLib::ConeParameters(Ax,Rad,Alp,P,U,V); 
665         TolReached = P.Distance(ElSLib::ConeValue(U,V,Ax,Rad,Alp));
666         if ( TolReached > TolConf)
667           return Standard_False;
668       }
669       break;
670     }
671   case GeomAbs_Sphere:
672     {
673       gp_Ax3        Ax  = AS.Sphere().Position();
674       Standard_Real Rad = AS.Sphere().Radius();
675       for ( Standard_Integer i = 0; i < n; i++) {
676         P = C->Value(f+i*du);
677         ElSLib::SphereParameters(Ax,Rad,P,U,V); 
678         TolReached = P.Distance(ElSLib::SphereValue(U,V,Ax,Rad));
679         if ( TolReached > TolConf)
680           return Standard_False;
681       }
682       break;
683     }
684   case GeomAbs_Torus:
685     {
686       gp_Ax3        Ax  = AS.Torus().Position();
687       Standard_Real R1  = AS.Torus().MajorRadius();
688       Standard_Real R2  = AS.Torus().MinorRadius();
689       for ( Standard_Integer i = 0; i < n; i++) {
690         P = C->Value(f+i*du);
691         ElSLib::TorusParameters(Ax,R1,R2,P,U,V); 
692         TolReached =  P.Distance(ElSLib::TorusValue(U,V,Ax,R1,R2));
693         if ( TolReached > TolConf)
694           return Standard_False;
695       }
696       break;
697     }
698     
699   default:
700     {
701       return Standard_False;
702     }
703   }
704   
705   return Standard_True;
706
707
708
709 //=======================================================================
710 //function : PipeInter
711 //purpose  : 
712 //=======================================================================
713
714 void BRepOffset_Tool::PipeInter(const TopoDS_Face& F1,
715                                 const TopoDS_Face& F2,
716                                 TopTools_ListOfShape& L1,
717                                 TopTools_ListOfShape& L2,
718                                 const TopAbs_State    Side)
719
720 #ifdef DRAW
721   if (AffichInter) {
722     char name[256];
723     sprintf(name,"FF_%d",NbFaces++);
724     DBRep::Set(name,F1);
725     sprintf(name,"FF_%d",NbFaces++);
726     DBRep::Set(name,F2);
727   }
728 #endif
729
730   Handle (Geom_Curve) CI;
731   TopAbs_Orientation O1,O2;
732   L1.Clear(); L2.Clear();
733   BRep_Builder B;
734   Handle (Geom_Surface) S1 = BRep_Tool::Surface(F1);
735   Handle (Geom_Surface) S2 = BRep_Tool::Surface(F2);  
736
737   GeomInt_IntSS Inter (S1,S2, Precision::Confusion(),1,1,1);
738   
739   if (Inter.IsDone()) {
740     for (Standard_Integer i = 1; i <= Inter.NbLines(); i++) {
741       CI = Inter.Line(i);
742       if (ToSmall(CI)) continue;
743       TopoDS_Edge E = BRepLib_MakeEdge(CI);
744       if (Inter.HasLineOnS1(i)) {
745         Handle(Geom2d_Curve) C2 = Inter.LineOnS1(i);
746         PutInBounds  (F1,E,C2);
747         B.UpdateEdge (E,C2,F1,BRep_Tool::Tolerance(E));
748       }
749       else {
750         BuildPCurves (E,F1);
751       }
752       if (Inter.HasLineOnS2(i)) {
753         Handle(Geom2d_Curve) C2 = Inter.LineOnS2(i);
754         PutInBounds  (F2,E,C2);
755         B.UpdateEdge (E,C2,F2,BRep_Tool::Tolerance(E));
756       }
757       else {
758         BuildPCurves (E,F2);
759       }
760       OrientSection (E,F1,F2,O1,O2);
761       if (Side == TopAbs_OUT) {
762         O1 = TopAbs::Reverse(O1);
763         O2 = TopAbs::Reverse(O2);
764       }
765       L1.Append (E.Oriented(O1));
766       L2.Append (E.Oriented(O2));
767 #ifdef DRAW
768       if (AffichInter) {
769         char name[256];
770         sprintf(name,"EI_%d",NbNewEdges++);     
771         DBRep::Set(name,E.Oriented(O1));
772       }
773 #endif      
774     }
775   }
776 }
777
778
779 //=======================================================================
780 //function : IsAutonomVertex
781 //purpose  : Checks wether a vertex is "autonom" or not
782 //=======================================================================
783
784 static Standard_Boolean IsAutonomVertex(const TopoDS_Shape& aVertex,
785                                         const BOPDS_PDS& pDS)
786 {
787   Standard_Integer index;
788   Standard_Integer aNbVVs, aNbEEs, aNbEFs, aInt;
789   //
790   index = pDS->Index(aVertex);
791   if (index == -1) {
792     Standard_Integer i, i1, i2;
793     i1=pDS->NbSourceShapes();
794     i2=pDS->NbShapes();
795     for (i=i1; i<i2; ++i) {
796       const TopoDS_Shape& aSx=pDS->Shape(i);
797       if(aSx.IsSame(aVertex)) {
798                   index = i;
799                   break;
800                 }
801             }
802         }
803   //
804   if (!pDS->IsNewShape(index)) {
805     return Standard_False;
806     }
807   //check if vertex with index "index" is not created in VV or EE or EF interference
808   //VV
809   BOPDS_VectorOfInterfVV& aVVs=pDS->InterfVV();
810   aNbVVs = aVVs.Extent();
811   for(aInt = 0; aInt < aNbVVs; aInt++) {
812     const BOPDS_InterfVV& aVV = aVVs(aInt);
813     if (aVV.HasIndexNew()) {
814       if (aVV.IndexNew() == index) {
815                 return Standard_False;
816             }
817         }
818     }
819   //EE
820   BOPDS_VectorOfInterfEE& aEEs=pDS->InterfEE();
821   aNbEEs = aEEs.Extent();
822   for(aInt = 0; aInt < aNbEEs; aInt++) {
823     const BOPDS_InterfEE& aEE = aEEs(aInt);
824     IntTools_CommonPrt aCP = aEE.CommonPart();
825     if(aCP.Type() == TopAbs_VERTEX) {
826       if (aEE.IndexNew() == index) {
827                     return Standard_False;
828                 }
829             }
830         }
831   //EF
832   BOPDS_VectorOfInterfEF& aEFs=pDS->InterfEF();
833   aNbEFs = aEFs.Extent();
834   for(aInt = 0; aInt < aNbEFs; aInt++) {
835     const BOPDS_InterfEF& aEF = aEFs(aInt);
836     IntTools_CommonPrt aCP = aEF.CommonPart();
837     if(aCP.Type() == TopAbs_VERTEX) {
838       if (aEF.IndexNew() == index) {
839         return Standard_False;
840     }
841     }
842   }
843   return Standard_True;
844 }
845
846
847 //=======================================================================
848 //function : AreConnex
849 //purpose  : define if two shapes are connex by a vertex (vertices)
850 //=======================================================================
851
852 static Standard_Boolean AreConnex(const TopoDS_Wire& W1,
853                                   const TopoDS_Wire& W2,
854                                   const BOPDS_PDS& pDS)
855 {
856   TopoDS_Vertex V11, V12, V21, V22;
857   TopExp::Vertices( W1, V11, V12 );
858   TopExp::Vertices( W2, V21, V22 );
859
860   if (V11.IsSame(V21) || V11.IsSame(V22) ||
861       V12.IsSame(V21) || V12.IsSame(V22))
862     {
863       Standard_Boolean isCV1 = V11.IsSame(V21) || V11.IsSame(V22);
864       Standard_Boolean isCV2 = V12.IsSame(V21) || V12.IsSame(V22);
865       if (isCV1 && !IsAutonomVertex(V11, pDS))
866         {
867           if (!isCV2)
868             return Standard_False;
869           if (!IsAutonomVertex(V12, pDS))
870             return Standard_False;
871         }
872       if (!isCV1 && !IsAutonomVertex(V12, pDS))
873         return Standard_False;
874
875       TopoDS_Vertex CV = (V11.IsSame(V21) || V11.IsSame(V22))? V11 : V12;
876       TopoDS_Edge E1, E2;
877       TopoDS_Iterator itw( W1 );
878       for (; itw.More(); itw.Next())
879         {
880           E1 = TopoDS::Edge(itw.Value());
881           TopoDS_Vertex V1, V2;
882           TopExp::Vertices( E1, V1, V2 );
883           if (V1.IsSame(CV) || V2.IsSame(CV))
884             break;
885         }
886       itw.Initialize( W2 );
887       E2 = TopoDS::Edge(itw.Value());
888
889       Standard_Real f, l;
890       Handle(Geom_Curve) C1 = BRep_Tool::Curve( E1, f, l ); 
891       if (C1->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
892         C1 = Handle(Geom_TrimmedCurve)::DownCast (C1)->BasisCurve();
893       
894       Handle(Geom_Curve) C2 = BRep_Tool::Curve( E2, f, l );
895       if (C2->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
896         C2 = Handle(Geom_TrimmedCurve)::DownCast (C2)->BasisCurve();
897
898       if (C1->IsInstance(STANDARD_TYPE(Geom_Line)) &&
899           C2->IsInstance(STANDARD_TYPE(Geom_Line)))
900         {
901           Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast (C1);
902           gp_Ax1 Axis1 = L1->Position();
903           Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast (C2);
904           gp_Ax1 Axis2 = L2->Position();
905           if (! Axis1.IsParallel( Axis2, Precision::Angular() ))
906             return Standard_False;
907         }
908
909       return Standard_True;
910     }
911
912   return Standard_False;
913 }
914
915 //=======================================================================
916 //function : AreClosed
917 //purpose  : define if two edges are connex by two vertices
918 //=======================================================================
919
920 static Standard_Boolean AreClosed(const TopoDS_Edge& E1,
921                                   const TopoDS_Edge& E2)
922 {
923   TopoDS_Vertex V11, V12, V21, V22;
924   TopExp::Vertices( E1, V11, V12 );
925   TopExp::Vertices( E2, V21, V22 );
926
927   if ((V11.IsSame(V21) && V12.IsSame(V22)) ||
928       (V11.IsSame(V22) && V12.IsSame(V21)))
929     return Standard_True;
930
931   return Standard_False;
932 }
933
934 //=======================================================================
935 //function : BSplineEdges
936 //purpose  : 
937 //=======================================================================
938
939 static Standard_Boolean BSplineEdges(const TopoDS_Edge& E1,
940                                      const TopoDS_Edge& E2,
941                                      const Standard_Integer par1,
942                                      const Standard_Integer par2,
943                                      Standard_Real& angle)
944 {
945   Standard_Real first1, last1, first2, last2, Param1, Param2;
946
947   Handle(Geom_Curve) C1 = BRep_Tool::Curve( E1, first1, last1 ); 
948   if (C1->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
949     C1 = Handle(Geom_TrimmedCurve)::DownCast (C1)->BasisCurve();
950
951   Handle(Geom_Curve) C2 = BRep_Tool::Curve( E2, first2, last2 );
952   if (C2->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
953     C2 = Handle(Geom_TrimmedCurve)::DownCast (C2)->BasisCurve();
954
955   if (!C1->IsInstance(STANDARD_TYPE(Geom_BSplineCurve)) ||
956       !C2->IsInstance(STANDARD_TYPE(Geom_BSplineCurve)))
957     return Standard_False;
958
959   Param1 = (par1 == 0)? first1 : last1;
960   Param2 = (par2 == 0)? first2 : last2;
961
962   gp_Pnt Pnt1, Pnt2;
963   gp_Vec Der1, Der2;
964   C1->D1( Param1, Pnt1, Der1 );
965   C2->D1( Param2, Pnt2, Der2 );
966
967   if (Der1.Magnitude() <= gp::Resolution() ||
968       Der2.Magnitude() <= gp::Resolution())
969     angle = M_PI/2.;
970   else
971     angle = Der1.Angle(Der2);
972
973   return Standard_True;
974 }
975
976 //=======================================================================
977 //function : AngleWireEdge
978 //purpose  : 
979 //=======================================================================
980
981 static Standard_Real AngleWireEdge(const TopoDS_Wire& aWire,
982                                    const TopoDS_Edge& anEdge)
983 {
984   TopoDS_Vertex V11, V12, V21, V22, CV;
985   TopExp::Vertices( aWire,  V11, V12 );
986   TopExp::Vertices( anEdge, V21, V22 );
987   CV = (V11.IsSame(V21) || V11.IsSame(V22))? V11 : V12;
988   TopoDS_Edge FirstEdge;
989   TopoDS_Iterator itw(aWire);
990   for (; itw.More(); itw.Next())
991     {
992       FirstEdge = TopoDS::Edge(itw.Value());
993       TopoDS_Vertex v1, v2;
994       TopExp::Vertices( FirstEdge, v1, v2 );
995       if (v1.IsSame(CV) || v2.IsSame(CV))
996         {
997           V11 = v1;
998           V12 = v2;
999           break;
1000         }
1001     }
1002   Standard_Real Angle;
1003   if (V11.IsSame(CV) && V21.IsSame(CV))
1004     {
1005       BSplineEdges( FirstEdge, anEdge, 0, 0, Angle );
1006       Angle = M_PI - Angle;
1007     }
1008   else if (V11.IsSame(CV) && V22.IsSame(CV))
1009     BSplineEdges( FirstEdge, anEdge, 0, 1, Angle );
1010   else if (V12.IsSame(CV) && V21.IsSame(CV))
1011     BSplineEdges( FirstEdge, anEdge, 1, 0, Angle );
1012   else
1013     {
1014       BSplineEdges( FirstEdge, anEdge, 1, 1, Angle );
1015       Angle = M_PI - Angle;
1016     }
1017   return Angle;
1018 }
1019
1020
1021 //=======================================================================
1022 //function : ReconstructPCurves
1023 //purpose  : 
1024 //=======================================================================
1025
1026 static void ReconstructPCurves(const TopoDS_Edge& anEdge)
1027 {
1028   Standard_Real f, l;
1029   Handle(Geom_Curve) C3d = BRep_Tool::Curve(anEdge, f, l);
1030
1031   BRep_ListIteratorOfListOfCurveRepresentation
1032     itcr( (Handle(BRep_TEdge)::DownCast(anEdge.TShape()))->ChangeCurves() );
1033   for (; itcr.More(); itcr.Next())
1034     {
1035       Handle( BRep_CurveRepresentation ) CurveRep = itcr.Value();
1036       if (CurveRep->IsCurveOnSurface())
1037         {
1038           Handle(Geom_Surface) theSurf  = CurveRep->Surface();
1039           TopLoc_Location      theLoc   = CurveRep->Location();
1040           theLoc = anEdge.Location() * theLoc;
1041           theSurf = Handle(Geom_Surface)::DownCast
1042             (theSurf->Transformed(theLoc.Transformation()));
1043           Handle(Geom2d_Curve) ProjPCurve =
1044             GeomProjLib::Curve2d( C3d, f, l, theSurf );
1045           if(!ProjPCurve.IsNull())
1046           {
1047             CurveRep->PCurve( ProjPCurve );
1048           }
1049         }
1050     }
1051 }
1052
1053 //=======================================================================
1054 //function : ConcatPCurves
1055 //purpose  : 
1056 //=======================================================================
1057
1058 static Handle(Geom2d_Curve) ConcatPCurves(const TopoDS_Edge& E1,
1059                                           const TopoDS_Edge& E2,
1060                                           const TopoDS_Face& F,
1061                                           const Standard_Boolean After,
1062                                           Standard_Real& newFirst,
1063                                           Standard_Real& newLast)
1064 {
1065   Standard_Real Tol = 1.e-7;
1066   GeomAbs_Shape Continuity = GeomAbs_C1;
1067   Standard_Integer MaxDeg = 14;
1068   Standard_Integer MaxSeg = 16;
1069
1070   Standard_Real first1, last1, first2, last2;
1071   Handle(Geom2d_Curve) PCurve1, PCurve2, newPCurve;
1072
1073   PCurve1 = BRep_Tool::CurveOnSurface( E1, F, first1, last1 );
1074   if (PCurve1->IsInstance(STANDARD_TYPE(Geom2d_TrimmedCurve)))
1075     PCurve1 = Handle(Geom2d_TrimmedCurve)::DownCast (PCurve1)->BasisCurve();
1076
1077   PCurve2 = BRep_Tool::CurveOnSurface( E2, F, first2, last2 );
1078   if (PCurve2->IsInstance(STANDARD_TYPE(Geom2d_TrimmedCurve)))
1079     PCurve2 = Handle(Geom2d_TrimmedCurve)::DownCast (PCurve2)->BasisCurve();
1080       
1081   if (PCurve1 == PCurve2)
1082     {
1083       newPCurve = PCurve1;
1084       newFirst  = Min( first1, first2 );
1085       newLast   = Max( last1, last2 );
1086     }
1087   else if (PCurve1->DynamicType() == PCurve2->DynamicType() &&
1088            (PCurve1->IsInstance(STANDARD_TYPE(Geom2d_Line)) ||
1089             PCurve1->IsKind(STANDARD_TYPE(Geom2d_Conic))))
1090     {
1091       newPCurve = PCurve1;
1092       gp_Pnt2d P1, P2;
1093       P1 = PCurve2->Value( first2 );
1094       P2 = PCurve2->Value( last2 );
1095       if (PCurve1->IsInstance(STANDARD_TYPE(Geom2d_Line)))
1096         {
1097           Handle(Geom2d_Line) Lin1 = Handle(Geom2d_Line)::DownCast (PCurve1);
1098           gp_Lin2d theLin = Lin1->Lin2d();
1099           first2 = ElCLib::Parameter( theLin, P1 );
1100           last2  = ElCLib::Parameter( theLin, P2 );
1101         }
1102       else if (PCurve1->IsInstance(STANDARD_TYPE(Geom2d_Circle)))
1103         {
1104           Handle(Geom2d_Circle) Circ1 = Handle(Geom2d_Circle)::DownCast (PCurve1);
1105           gp_Circ2d theCirc = Circ1->Circ2d();
1106           first2 = ElCLib::Parameter( theCirc, P1 );
1107           last2  = ElCLib::Parameter( theCirc, P2 );
1108         }
1109       else if (PCurve1->IsInstance(STANDARD_TYPE(Geom2d_Ellipse)))
1110         {
1111           Handle(Geom2d_Ellipse) Ell1 = Handle(Geom2d_Ellipse)::DownCast (PCurve1);
1112           gp_Elips2d theElips = Ell1->Elips2d();
1113           first2 = ElCLib::Parameter( theElips, P1 );
1114           last2  = ElCLib::Parameter( theElips, P2 );
1115         }
1116       else if (PCurve1->IsInstance(STANDARD_TYPE(Geom2d_Parabola)))
1117         {
1118           Handle(Geom2d_Parabola) Parab1 = Handle(Geom2d_Parabola)::DownCast (PCurve1);
1119           gp_Parab2d theParab = Parab1->Parab2d();
1120           first2 = ElCLib::Parameter( theParab, P1 );
1121           last2  = ElCLib::Parameter( theParab, P2 );
1122         }
1123       else if (PCurve1->IsInstance(STANDARD_TYPE(Geom2d_Hyperbola)))
1124         {
1125           Handle(Geom2d_Hyperbola) Hypr1 = Handle(Geom2d_Hyperbola)::DownCast (PCurve1);
1126           gp_Hypr2d theHypr = Hypr1->Hypr2d();
1127           first2 = ElCLib::Parameter( theHypr, P1 );
1128           last2  = ElCLib::Parameter( theHypr, P2 );
1129         }
1130       newFirst  = Min( first1, first2 );
1131       newLast   = Max( last1, last2 );
1132     }
1133   else
1134     {
1135       Handle(Geom2d_TrimmedCurve) TC1 = new Geom2d_TrimmedCurve( PCurve1, first1, last1 );
1136       Handle(Geom2d_TrimmedCurve) TC2 = new Geom2d_TrimmedCurve( PCurve2, first2, last2 );
1137       Geom2dConvert_CompCurveToBSplineCurve Concat2d( TC1 );
1138       Concat2d.Add( TC2, Precision::Confusion(), After );
1139       newPCurve = Concat2d.BSplineCurve();
1140       if (newPCurve->Continuity() < GeomAbs_C1)
1141         {
1142           Geom2dConvert_ApproxCurve Approx2d( newPCurve, Tol, Continuity, MaxSeg, MaxDeg );
1143           if (Approx2d.HasResult())
1144             newPCurve = Approx2d.Curve();
1145         }
1146       newFirst = newPCurve->FirstParameter();
1147       newLast  = newPCurve->LastParameter();
1148     }
1149
1150   return newPCurve;
1151 }
1152
1153 //=======================================================================
1154 //function : Glue
1155 //purpose  : glue two edges.
1156 //=======================================================================
1157
1158 static TopoDS_Edge Glue(const TopoDS_Edge& E1,
1159                         const TopoDS_Edge& E2,
1160                         const TopoDS_Vertex& Vfirst,
1161                         const TopoDS_Vertex& Vlast,
1162                         const Standard_Boolean After,
1163                         const TopoDS_Face& F1,
1164                         const Standard_Boolean addPCurve1,
1165                         const TopoDS_Face& F2,
1166                         const Standard_Boolean addPCurve2,
1167                         const Standard_Real theGlueTol)
1168 {
1169   Standard_Real Tol = 1.e-7;
1170   GeomAbs_Shape Continuity = GeomAbs_C1;
1171   Standard_Integer MaxDeg = 14;
1172   Standard_Integer MaxSeg = 16;
1173
1174   Handle(Geom_Curve) C1, C2, newCurve;
1175   Handle(Geom2d_Curve) PCurve1, PCurve2, newPCurve;
1176   Standard_Real first1, last1, first2, last2, fparam=0., lparam=0.;
1177   Standard_Boolean IsCanonic = Standard_False;
1178
1179   C1 = BRep_Tool::Curve( E1, first1, last1 ); 
1180   if (C1->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
1181     C1 = Handle(Geom_TrimmedCurve)::DownCast (C1)->BasisCurve();
1182
1183   C2 = BRep_Tool::Curve( E2, first2, last2 );
1184   if (C2->IsInstance(STANDARD_TYPE(Geom_TrimmedCurve)))
1185     C2 = Handle(Geom_TrimmedCurve)::DownCast (C2)->BasisCurve();
1186
1187   if (C1 == C2)
1188     {
1189       newCurve = C1;
1190       fparam = Min( first1, first2 );
1191       lparam = Max( last1, last2 );
1192     }
1193   else if (C1->DynamicType() == C2->DynamicType() &&
1194            (C1->IsInstance(STANDARD_TYPE(Geom_Line)) ||
1195             C1->IsKind(STANDARD_TYPE(Geom_Conic))))
1196     {
1197       IsCanonic = Standard_True;
1198       newCurve  = C1;
1199     }
1200   else
1201     {
1202       Handle(Geom_TrimmedCurve) TC1 = new Geom_TrimmedCurve( C1, first1, last1 );
1203       Handle(Geom_TrimmedCurve) TC2 = new Geom_TrimmedCurve( C2, first2, last2 );
1204       GeomConvert_CompCurveToBSplineCurve Concat( TC1 );
1205       Concat.Add( TC2, theGlueTol, After );
1206       newCurve = Concat.BSplineCurve();
1207       if (newCurve->Continuity() < GeomAbs_C1)
1208         {
1209           GeomConvert_ApproxCurve Approx3d( newCurve, Tol, Continuity, MaxSeg, MaxDeg );
1210           if (Approx3d.HasResult())
1211             newCurve = Approx3d.Curve();
1212         }
1213       fparam = newCurve->FirstParameter();
1214       lparam = newCurve->LastParameter();
1215     }
1216
1217   TopoDS_Edge newEdge;
1218   BRep_Builder BB;
1219
1220   if (IsCanonic)
1221     newEdge = BRepLib_MakeEdge( newCurve, Vfirst, Vlast );
1222   else
1223     newEdge = BRepLib_MakeEdge( newCurve, Vfirst, Vlast, fparam, lparam );
1224
1225   Standard_Real newFirst, newLast;
1226   if (addPCurve1)
1227     {
1228       newPCurve = ConcatPCurves( E1, E2, F1, After, newFirst, newLast );
1229       BB.UpdateEdge( newEdge, newPCurve, F1, 0. );
1230       BB.Range( newEdge, F1, newFirst, newLast );
1231     }
1232   if (addPCurve2)
1233     {
1234       newPCurve = ConcatPCurves( E1, E2, F2, After, newFirst, newLast );
1235       BB.UpdateEdge( newEdge, newPCurve, F2, 0. );
1236       BB.Range( newEdge, F2, newFirst, newLast );
1237     }
1238
1239   return newEdge;
1240 }
1241
1242
1243 //=======================================================================
1244 //function : FindNewVerticesOnBoundsOfFace
1245 //purpose  : 
1246 //=======================================================================
1247
1248 static void FindNewVerticesOnBoundsOfFace(const BOPDS_PDS& pDS,
1249                                           const TopoDS_Face& aFace,
1250                                           TopTools_DataMapOfShapeShape& VEmap)
1251 {
1252   TopTools_IndexedMapOfShape OldVertices;
1253   TopExp::MapShapes( aFace, TopAbs_VERTEX, OldVertices );
1254   BOPDS_ListIteratorOfListOfPaveBlock aItLPB;
1255   TopoDS_Vertex V1, V2;
1256
1257   TopExp_Explorer Explo( aFace, TopAbs_EDGE );
1258   for (; Explo.More(); Explo.Next()) {
1259     const TopoDS_Shape& aE = Explo.Current();
1260     Standard_Integer nE = pDS->Index(aE);
1261     //
1262     const BOPDS_ListOfPaveBlock& aLPB = pDS->PaveBlocks(nE);
1263     aItLPB.Initialize(aLPB);
1264     for (; aItLPB.More(); aItLPB.Next()) {
1265       const Handle(BOPDS_PaveBlock)& aPB = aItLPB.Value();
1266       const TopoDS_Edge& aESp = *(TopoDS_Edge*)&pDS->Shape(aPB->Edge());
1267       //
1268       TopExp::Vertices( aESp, V1, V2 );
1269       if (!OldVertices.Contains( V1 )) {
1270         VEmap.Bind( V1, aE );
1271         }
1272       //
1273       if (!OldVertices.Contains( V2 )) {
1274         VEmap.Bind( V2, aE );
1275     }
1276 }
1277   }
1278 }
1279                                    
1280 //=======================================================================
1281 //function : CheckIntersFF
1282 //purpose  : 
1283 //=======================================================================
1284
1285 static Standard_Boolean CheckIntersFF(const BOPDS_PDS& pDS,
1286                                       const TopoDS_Edge& RefEdge,
1287                                       const TopoDS_Face& F1,
1288                                       const TopoDS_Face& F2,
1289                                       TopTools_IndexedMapOfShape& TrueEdges)
1290 {
1291   Standard_Boolean isEl1 = Standard_False, isEl2 = Standard_False;
1292   Standard_Boolean isPlane1 = Standard_False, isPlane2 = Standard_False;
1293
1294   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(F1);
1295   if (aSurf->IsInstance(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
1296     aSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast (aSurf)->BasisSurface();
1297   if (aSurf->IsInstance(STANDARD_TYPE(Geom_Plane)))
1298     isPlane1 = Standard_True;
1299   else if (aSurf->IsKind(STANDARD_TYPE(Geom_ElementarySurface)))
1300     isEl1 = Standard_True;
1301
1302   aSurf = BRep_Tool::Surface(F2);
1303   if (aSurf->IsInstance(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
1304     aSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast (aSurf)->BasisSurface();
1305   if (aSurf->IsInstance(STANDARD_TYPE(Geom_Plane)))
1306     isPlane2 = Standard_True;
1307   else if (aSurf->IsKind(STANDARD_TYPE(Geom_ElementarySurface)))
1308     isEl2 = Standard_True;
1309
1310   if (isPlane1 || isPlane2)
1311     return Standard_True;
1312
1313   if (isEl1 && isEl2)
1314     return Standard_True;
1315
1316   BOPDS_VectorOfInterfFF& aFFs = pDS->InterfFF();
1317   Standard_Integer aNb = aFFs.Extent();
1318   Standard_Integer i, j, nbe = 0;
1319
1320   TopTools_SequenceOfShape Edges;
1321   
1322   for (i = 0; i < aNb; ++i) 
1323     {
1324       BOPDS_InterfFF& aFFi=aFFs(i);
1325       const BOPDS_VectorOfCurve& aBCurves=aFFi.Curves();
1326       Standard_Integer aNbCurves = aBCurves.Extent();
1327       
1328       for (j = 0; j < aNbCurves; ++j) 
1329         {
1330           const BOPDS_Curve& aBC=aBCurves(j);
1331           const BOPDS_ListOfPaveBlock& aSectEdges = aBC.PaveBlocks();
1332           
1333           BOPDS_ListIteratorOfListOfPaveBlock aPBIt;
1334           aPBIt.Initialize(aSectEdges);
1335           
1336           for (; aPBIt.More(); aPBIt.Next())
1337             {
1338               const Handle(BOPDS_PaveBlock)& aPB = aPBIt.Value();
1339               Standard_Integer nSect = aPB->Edge();
1340               const TopoDS_Edge& anEdge = *(TopoDS_Edge*)&pDS->Shape(nSect);
1341               Edges.Append( anEdge );
1342               nbe++;
1343             }
1344         }
1345     }
1346
1347   if (nbe <= 1)
1348     return Standard_True;
1349
1350   //define tangents of RefEdge on start and on end
1351   BRepAdaptor_Curve cref(RefEdge);
1352   gp_Vec RefTangFirst = cref.DN(cref.FirstParameter(), 1);
1353   gp_Vec RefTangLast  = cref.DN(cref.LastParameter(), 1);
1354
1355   //find the start edge and take it from Edges
1356   TopoDS_Edge StartEdge; //, StartEonF1, StartEonF2, EndEonF1, EndEonF2;
1357
1358   TopTools_DataMapOfShapeShape VEmapF1, VEmapF2;
1359   FindNewVerticesOnBoundsOfFace( pDS, F1, VEmapF1 );
1360   FindNewVerticesOnBoundsOfFace( pDS, F2, VEmapF2 );
1361
1362   Standard_Real AngTol = 0.1;
1363   Standard_Boolean V1onBound = Standard_False;
1364   Standard_Boolean V2onBound = Standard_False;
1365   TopoDS_Vertex V1, V2, Vcur;
1366   gp_Vec TangFirst, TangLast, TangCur;
1367   for (i = 1; i <= Edges.Length(); i++)
1368     {
1369       StartEdge = TopoDS::Edge(Edges(i));
1370       TopExp::Vertices( StartEdge, V1, V2 );
1371       V1onBound = VEmapF1.IsBound(V1) || VEmapF2.IsBound(V1); // && ?
1372       V2onBound = VEmapF1.IsBound(V2) || VEmapF2.IsBound(V2); // && ?
1373       if (V1onBound || V2onBound)
1374         {
1375           BRepAdaptor_Curve CE(StartEdge);
1376           TangFirst = CE.DN( CE.FirstParameter(), 1 );
1377           TangLast = CE.DN( CE.LastParameter(), 1 );
1378           if (V1onBound)
1379             {
1380               if (TangFirst.IsParallel( RefTangFirst, AngTol ) ||
1381                   TangFirst.IsParallel( RefTangLast,  AngTol ))
1382                 break; //start edged found
1383             }
1384           else if (V2onBound)
1385             {
1386               if (TangLast.IsParallel( RefTangLast,  AngTol ) ||
1387                   TangLast.IsParallel( RefTangFirst, AngTol ))
1388                 break; //start edged found
1389             }
1390         }
1391     }
1392
1393   if (i > Edges.Length()) //start edged not found
1394     return Standard_False;
1395
1396   if (V1onBound && V2onBound)
1397     {
1398       if ((TangFirst.IsParallel(RefTangFirst,AngTol) && TangLast.IsParallel(RefTangLast,AngTol)) ||
1399           (TangFirst.IsParallel(RefTangLast,AngTol)  && TangLast.IsParallel(RefTangFirst,AngTol)))
1400       {
1401         TrueEdges.Add( Edges(i) );
1402         return Standard_True;
1403       }
1404       else
1405         return Standard_False;
1406     }
1407
1408   //StartEonF1 = (V1onBound)? VEmapF1( V1 ) : VEmapF1( V2 );
1409   //StartEonF2 = (V1onBound)? VEmapF2( V1 ) : VEmapF2( V2 );
1410
1411   TrueEdges.Add( Edges(i) );
1412   Edges.Remove(i);
1413   Vcur    = (V1onBound)? V2 : V1;
1414   TangCur = (V1onBound)? TangLast : TangFirst;
1415   if (V2onBound)
1416     TangCur.Reverse();
1417   
1418   //build the chain from StartEdge till the opposite bound of face
1419   for (;;)
1420     {
1421       TColStd_SequenceOfInteger Candidates;
1422       for (i = 1; i <= Edges.Length(); i++)
1423         {
1424           TopoDS_Edge anEdge = TopoDS::Edge(Edges(i));
1425           TopExp::Vertices( anEdge, V1, V2 );
1426           if (V1.IsSame(Vcur) || V2.IsSame(Vcur))
1427             Candidates.Append(i);
1428         }
1429       if (Candidates.IsEmpty())
1430         {
1431           TrueEdges.Clear();
1432           return Standard_False;
1433         }
1434
1435       Standard_Integer minind = 1;
1436       if (Candidates.Length() > 1)
1437         {
1438           Standard_Real MinAngle = RealLast();
1439           for (i = 1; i <= Candidates.Length(); i++)
1440             {
1441               TopoDS_Edge anEdge = TopoDS::Edge(Edges(Candidates(i)));
1442               TopExp::Vertices( anEdge, V1, V2 );
1443               Standard_Boolean ConnectByFirst = (Vcur.IsSame(V1))? Standard_True : Standard_False;
1444               BRepAdaptor_Curve CE(anEdge);
1445               gp_Vec aTang = (ConnectByFirst)?
1446                 CE.DN( CE.FirstParameter(), 1 ) : CE.DN( CE.LastParameter(), 1 );
1447               if (!ConnectByFirst)
1448                 aTang.Reverse();
1449               Standard_Real anAngle = TangCur.Angle(aTang);
1450               if (anAngle < MinAngle)
1451                 {
1452                   MinAngle = anAngle;
1453                   minind = i;
1454                 }
1455             }
1456         }
1457       TopoDS_Edge CurEdge = TopoDS::Edge(Edges(Candidates(minind)));
1458       TrueEdges.Add( CurEdge );
1459       Edges.Remove(Candidates(minind));
1460       TopExp::Vertices( CurEdge, V1, V2 );
1461       Standard_Boolean ConnectByFirst = (Vcur.IsSame(V1))? Standard_True : Standard_False;
1462       Vcur = (ConnectByFirst)? V2 : V1;
1463       BRepAdaptor_Curve CE(CurEdge);
1464       TangCur = (ConnectByFirst)? CE.DN( CE.LastParameter(), 1 ) : CE.DN( CE.FirstParameter(), 1 );
1465       if (!ConnectByFirst)
1466         TangCur.Reverse();
1467       //check if Vcur is on bounds of faces
1468       if (VEmapF1.IsBound(Vcur) || VEmapF2.IsBound(Vcur))
1469         break;
1470     } //end of for (;;)
1471   
1472   if (TangCur.IsParallel( RefTangFirst, AngTol ) ||
1473       TangCur.IsParallel( RefTangLast,  AngTol ))
1474     return Standard_True;
1475
1476   TrueEdges.Clear();
1477   return Standard_False;
1478 }
1479
1480 //=======================================================================
1481 //function : AssembleEdge
1482 //purpose  : 
1483 //=======================================================================
1484
1485 static TopoDS_Edge AssembleEdge(const BOPDS_PDS& pDS,
1486                                 const TopoDS_Face& F1,
1487                                 const TopoDS_Face& F2,
1488                                 const Standard_Boolean addPCurve1,
1489                                 const Standard_Boolean addPCurve2,
1490                                 const TopTools_SequenceOfShape& EdgesForConcat)
1491 {
1492   TopoDS_Edge CurEdge = TopoDS::Edge( EdgesForConcat(1) );
1493   Standard_Real aGlueTol = Precision::Confusion();
1494   for (Standard_Integer j = 2; j <= EdgesForConcat.Length(); j++)
1495     {
1496       TopoDS_Edge anEdge = TopoDS::Edge( EdgesForConcat(j) );
1497       Standard_Boolean After = Standard_False;
1498       TopoDS_Vertex Vfirst, Vlast;
1499       if (AreClosed( CurEdge, anEdge ))
1500         {
1501           TopoDS_Vertex V1, V2;
1502           TopExp::Vertices( CurEdge, V1, V2 );
1503           if (IsAutonomVertex( V1, pDS ))
1504             {
1505               After = Standard_False;
1506               Vfirst = Vlast = V2;
1507             }
1508           else
1509             {
1510               After = Standard_True;
1511               Vfirst = Vlast = V1;
1512             }
1513         }
1514       else
1515         {
1516           TopoDS_Vertex CV, V11, V12, V21, V22;
1517           TopExp::CommonVertex( CurEdge, anEdge, CV );
1518           aGlueTol = BRep_Tool::Tolerance(CV);
1519           TopExp::Vertices( CurEdge, V11, V12 );
1520           TopExp::Vertices( anEdge,  V21, V22 );
1521           if (V11.IsSame(CV) && V21.IsSame(CV))
1522             {
1523               Vfirst = V22;
1524               Vlast  = V12;
1525             }
1526           else if (V11.IsSame(CV) && V22.IsSame(CV))
1527             {
1528               Vfirst = V21;
1529               Vlast  = V12;
1530             }
1531           else if (V12.IsSame(CV) && V21.IsSame(CV))
1532             {
1533               Vfirst = V11;
1534               Vlast  = V22;
1535             }
1536           else
1537             {
1538               Vfirst = V11;
1539               Vlast  = V21;
1540             }
1541         } //end of else (open wire)
1542       
1543       TopoDS_Edge NewEdge = Glue(CurEdge, anEdge, Vfirst, Vlast, After,
1544                                  F1, addPCurve1, F2, addPCurve2, aGlueTol);
1545       CurEdge = NewEdge;
1546     } //end of for (Standard_Integer j = 2; j <= EdgesForConcat.Length(); j++)
1547   
1548   return CurEdge;
1549 }
1550
1551 //=======================================================================
1552 //function : Inter3D
1553 //purpose  : 
1554 //=======================================================================
1555
1556 void BRepOffset_Tool::Inter3D(const TopoDS_Face& F1,
1557                               const TopoDS_Face& F2,
1558                               TopTools_ListOfShape& L1,
1559                               TopTools_ListOfShape& L2,
1560                               const TopAbs_State    Side,
1561                               const TopoDS_Edge&     RefEdge,
1562                               const Standard_Boolean IsRefEdgeDefined)
1563 {
1564 #ifdef DRAW
1565   if (AffichInter) {
1566     char name[256];
1567     sprintf(name,"FF_%d",NbFaces++);
1568     DBRep::Set(name,F1);
1569     sprintf(name,"FF_%d",NbFaces++);
1570     DBRep::Set(name,F2);
1571   }
1572 #endif
1573
1574   TopoDS_Face cpF1=F1; 
1575   TopoDS_Face cpF2=F2;
1576   // create 3D curves on faces
1577   BRepLib::BuildCurves3d(cpF1);
1578   BRepLib::BuildCurves3d(cpF2);
1579  
1580   BOPAlgo_PaveFiller aPF1, aPF2;
1581   BOPCol_ListOfShape aLS;
1582   aLS.Append(cpF1);
1583   aLS.Append(cpF2);
1584   aPF1.SetArguments(aLS);
1585   //
1586   aPF1.Perform();
1587   
1588   BOPAlgo_PaveFiller *pPF = &aPF1;
1589
1590   aLS.Clear();
1591   TopTools_IndexedMapOfShape TrueEdges;
1592   if (IsRefEdgeDefined && !CheckIntersFF( pPF->PDS(), RefEdge, cpF1, cpF2, TrueEdges ))
1593     {
1594       cpF1 = F2;
1595       cpF2 = F1;
1596       aLS.Append(cpF1);
1597       aLS.Append(cpF2);
1598       aPF2.SetArguments(aLS);
1599       aPF2.Perform();
1600       pPF = &aPF2;
1601       CheckIntersFF( pPF->PDS(), RefEdge, cpF1, cpF2, TrueEdges );
1602    }
1603
1604   Standard_Boolean addPCurve1 = 1;
1605   Standard_Boolean addPCurve2 = 1;
1606   
1607   const BOPDS_PDS& pDS = pPF->PDS();
1608   BOPDS_VectorOfInterfFF& aFFs=pDS->InterfFF();
1609   Standard_Integer aNb = aFFs.Extent();
1610   Standard_Integer i = 0, j = 0, k;
1611   // Store Result
1612   L1.Clear(); L2.Clear();
1613   TopAbs_Orientation O1,O2;
1614   //
1615   const Handle(IntTools_Context)& aContext = pPF->Context();
1616   //
1617   for (i = 0; i < aNb; i++) {
1618     BOPDS_InterfFF& aFFi=aFFs(i);
1619     const BOPDS_VectorOfCurve& aBCurves=aFFi.Curves();
1620         
1621     Standard_Integer aNbCurves = aBCurves.Extent();
1622       
1623     for (j = 0; j < aNbCurves; j++) {
1624       const BOPDS_Curve& aBC=aBCurves(j);
1625       const BOPDS_ListOfPaveBlock& aSectEdges = aBC.PaveBlocks();
1626       
1627       BOPDS_ListIteratorOfListOfPaveBlock aPBIt;
1628       aPBIt.Initialize(aSectEdges);
1629       
1630       for (; aPBIt.More(); aPBIt.Next()) {
1631         const Handle(BOPDS_PaveBlock)& aPB = aPBIt.Value();
1632         Standard_Integer nSect = aPB->Edge();
1633         const TopoDS_Edge& anEdge = *(TopoDS_Edge*)&pDS->Shape(nSect);
1634         if (!TrueEdges.IsEmpty() && !TrueEdges.Contains(anEdge))
1635           continue;
1636         
1637         Standard_Real f, l;
1638         const Handle(Geom_Curve)& aC3DE = BRep_Tool::Curve(anEdge, f, l);
1639         Handle(Geom_TrimmedCurve) aC3DETrim;
1640             
1641         if(!aC3DE.IsNull()) 
1642             aC3DETrim = new Geom_TrimmedCurve(aC3DE, f, l);
1643         
1644         BRep_Builder aBB;
1645         Standard_Real aTolEdge = BRep_Tool::Tolerance(anEdge);
1646                 
1647         if (!BOPTools_AlgoTools2D::HasCurveOnSurface(anEdge, cpF1)) {
1648           Handle(Geom2d_Curve) aC2d = aBC.Curve().FirstCurve2d();
1649           if(!aC3DETrim.IsNull()) {
1650                 Handle(Geom2d_Curve) aC2dNew;
1651                 
1652                 if(aC3DE->IsPeriodic()) {
1653                   BOPTools_AlgoTools2D::AdjustPCurveOnFace(cpF1, f, l,  aC2d, aC2dNew, aContext);
1654                   }
1655                 else {
1656                   BOPTools_AlgoTools2D::AdjustPCurveOnFace(cpF1, aC3DETrim, aC2d, aC2dNew, aContext); 
1657                   }
1658                 aC2d = aC2dNew;
1659               }
1660               aBB.UpdateEdge(anEdge, aC2d, cpF1, aTolEdge);
1661         }
1662         
1663         if (!BOPTools_AlgoTools2D::HasCurveOnSurface(anEdge, cpF2)) {
1664           Handle(Geom2d_Curve) aC2d = aBC.Curve().SecondCurve2d();
1665           if(!aC3DETrim.IsNull()) {
1666                 Handle(Geom2d_Curve) aC2dNew;
1667                 
1668                 if(aC3DE->IsPeriodic()) {
1669                   BOPTools_AlgoTools2D::AdjustPCurveOnFace(cpF2, f, l,  aC2d, aC2dNew, aContext);
1670                   }
1671                 else {
1672                   BOPTools_AlgoTools2D::AdjustPCurveOnFace(cpF2, aC3DETrim, aC2d, aC2dNew, aContext); 
1673                   }
1674                 aC2d = aC2dNew;
1675               }
1676               aBB.UpdateEdge(anEdge, aC2d, cpF2, aTolEdge);
1677         }
1678          
1679         OrientSection (anEdge, F1, F2, O1, O2);
1680         if (Side == TopAbs_OUT) {
1681           O1 = TopAbs::Reverse(O1);
1682           O2 = TopAbs::Reverse(O2);
1683         }
1684         
1685         L1.Append (anEdge.Oriented(O1));
1686         L2.Append (anEdge.Oriented(O2));
1687         
1688 #ifdef DRAW
1689         if (AffichInter) {
1690           char name[256];
1691           sprintf(name,"EI_%d",NbNewEdges++);   
1692           DBRep::Set(name,anEdge.Oriented(O1));
1693          
1694         }
1695 #endif       
1696       }
1697     }
1698   }
1699
1700   Standard_Real aSameParTol = Precision::Confusion();
1701   Standard_Boolean isEl1 = Standard_False, isEl2 = Standard_False;
1702
1703   Handle(Geom_Surface) aSurf = BRep_Tool::Surface(cpF1);
1704   if (aSurf->IsInstance(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
1705     aSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast (aSurf)->BasisSurface();
1706   if (aSurf->IsInstance(STANDARD_TYPE(Geom_Plane)))
1707     addPCurve1 = Standard_False;
1708   else if (aSurf->IsKind(STANDARD_TYPE(Geom_ElementarySurface)))
1709     isEl1 = Standard_True;
1710
1711   aSurf = BRep_Tool::Surface(cpF2);
1712   if (aSurf->IsInstance(STANDARD_TYPE(Geom_RectangularTrimmedSurface)))
1713     aSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast (aSurf)->BasisSurface();
1714   if (aSurf->IsInstance(STANDARD_TYPE(Geom_Plane)))
1715     addPCurve2 = Standard_False;
1716   else if (aSurf->IsKind(STANDARD_TYPE(Geom_ElementarySurface)))
1717     isEl2 = Standard_True;
1718
1719   if (L1.Extent() > 1 && (!isEl1 || !isEl2)) {
1720     TopTools_SequenceOfShape eseq;
1721     TopTools_SequenceOfShape EdgesForConcat;
1722
1723     if (!TrueEdges.IsEmpty())
1724       {
1725         for (i = TrueEdges.Extent(); i >= 1; i--)
1726           EdgesForConcat.Append( TrueEdges(i) );
1727         TopoDS_Edge theEdge =
1728           AssembleEdge( pDS, cpF1, cpF2, addPCurve1, addPCurve2, EdgesForConcat );
1729         eseq.Append(theEdge);
1730       }
1731     else
1732       {
1733         
1734         TopTools_SequenceOfShape wseq;
1735         TopTools_SequenceOfShape edges;
1736         TopTools_ListIteratorOfListOfShape itl(L1);
1737         for (; itl.More(); itl.Next())
1738           edges.Append( itl.Value() );
1739         while (!edges.IsEmpty())
1740           {
1741             TopoDS_Edge anEdge = TopoDS::Edge( edges.First() );
1742             TopoDS_Wire aWire = BRepLib_MakeWire( anEdge ), resWire;
1743             TColStd_SequenceOfInteger Candidates;
1744             for (k = 1; k <= wseq.Length(); k++)
1745               {
1746                 resWire = TopoDS::Wire(wseq(k));
1747                 if (AreConnex( resWire, aWire, pDS ))
1748                   {
1749                     Candidates.Append( 1 );
1750                     break;
1751                   }
1752               }
1753             if (Candidates.IsEmpty())
1754               {
1755                 wseq.Append( aWire );
1756                 edges.Remove(1);
1757               }
1758             else
1759               {
1760                 for (j = 2; j <= edges.Length(); j++)
1761                   {
1762                     anEdge = TopoDS::Edge( edges(j) );
1763                     //if (anEdge.IsSame(edges(Candidates.First())))
1764                     //continue;
1765                     aWire = BRepLib_MakeWire( anEdge );
1766                     if (AreConnex( resWire, aWire, pDS ))
1767                       Candidates.Append( j );
1768                   }
1769                 Standard_Integer minind = 1;
1770                 if (Candidates.Length() > 1)
1771                   {
1772                     Standard_Real MinAngle = RealLast();
1773                     for (j = 1; j <= Candidates.Length(); j++)
1774                       {
1775                         anEdge = TopoDS::Edge( edges(Candidates(j)) );
1776                         Standard_Real anAngle = AngleWireEdge( resWire, anEdge );
1777                         if (anAngle < MinAngle)
1778                           {
1779                             MinAngle = anAngle;
1780                             minind = j;
1781                           }
1782                       }
1783                   }
1784                 TopoDS_Wire NewWire = BRepLib_MakeWire( resWire, TopoDS::Edge(edges(Candidates(minind))) );
1785                 wseq(k) = NewWire;
1786                 edges.Remove(Candidates(minind));
1787               }
1788           } //end of while (!edges.IsEmpty())
1789         
1790         for (i = 1; i <= wseq.Length(); i++)
1791           {
1792             TopoDS_Wire aWire = TopoDS::Wire(wseq(i));
1793             TopTools_SequenceOfShape aLocalEdgesForConcat;
1794             if (aWire.Closed())
1795               {
1796                 TopoDS_Vertex StartVertex;
1797                 TopoDS_Edge StartEdge;
1798                 Standard_Boolean StartFound = Standard_False;
1799                 TopTools_ListOfShape Elist;
1800                 
1801                 TopoDS_Iterator itw(aWire);
1802                 for (; itw.More(); itw.Next())
1803                   {
1804                     TopoDS_Edge anEdge = TopoDS::Edge(itw.Value());
1805                     if (StartFound)
1806                       Elist.Append(anEdge);
1807                     else
1808                       {
1809                         TopoDS_Vertex V1, V2;
1810                         TopExp::Vertices( anEdge, V1, V2 );
1811                         if (!IsAutonomVertex( V1, pDS ))
1812                           {
1813                             StartVertex = V2;
1814                             StartEdge = anEdge;
1815                             StartFound = Standard_True;
1816                           }
1817                         else if (!IsAutonomVertex( V2, pDS ))
1818                           {
1819                             StartVertex = V1;
1820                             StartEdge = anEdge;
1821                             StartFound = Standard_True;
1822                           }
1823                         else
1824                           Elist.Append(anEdge);
1825                       }
1826                   } //end of for (; itw.More(); itw.Next())
1827                 if (!StartFound)
1828                   {
1829                     itl.Initialize(Elist);
1830                     StartEdge = TopoDS::Edge(itl.Value());
1831                     Elist.Remove(itl);
1832                     TopoDS_Vertex V1, V2;
1833                     TopExp::Vertices( StartEdge, V1, V2 );
1834                     StartVertex = V1;
1835                   }
1836                 aLocalEdgesForConcat.Append( StartEdge );
1837                 while (!Elist.IsEmpty())
1838                   {
1839                     for (itl.Initialize(Elist); itl.More(); itl.Next())
1840                       {
1841                         TopoDS_Edge anEdge = TopoDS::Edge(itl.Value());
1842                         TopoDS_Vertex V1, V2;
1843                         TopExp::Vertices( anEdge, V1, V2 );
1844                         if (V1.IsSame(StartVertex))
1845                           {
1846                             StartVertex = V2;
1847                             aLocalEdgesForConcat.Append( anEdge );
1848                             Elist.Remove(itl);
1849                             break;
1850                           }
1851                         else if (V2.IsSame(StartVertex))
1852                           {
1853                             StartVertex = V1;
1854                             aLocalEdgesForConcat.Append( anEdge );
1855                             Elist.Remove(itl);
1856                             break;
1857                           }
1858                       }
1859                   } //end of while (!Elist.IsEmpty())
1860               } //end of if (aWire.Closed())
1861               else
1862               {
1863                 BRepTools_WireExplorer Wexp( aWire );
1864                 for (; Wexp.More(); Wexp.Next())
1865                   aLocalEdgesForConcat.Append( Wexp.Current() );
1866               }
1867             
1868             TopoDS_Edge theEdge =
1869               AssembleEdge( pDS, cpF1, cpF2, addPCurve1, addPCurve2, aLocalEdgesForConcat );
1870             eseq.Append( theEdge );
1871           }
1872       } //end of else (when TrueEdges is empty)
1873     
1874     if (eseq.Length() < L1.Extent())
1875       {
1876         L1.Clear();
1877         L2.Clear();
1878         for (i = 1; i <= eseq.Length(); i++)
1879           {
1880             TopoDS_Edge anEdge = TopoDS::Edge(eseq(i));
1881             BRepLib::SameParameter(anEdge, aSameParTol, Standard_True);
1882             Standard_Real EdgeTol = BRep_Tool::Tolerance(anEdge);
1883 #ifdef OCCT_DEBUG
1884             cout<<"Tolerance of glued E =      "<<EdgeTol<<endl;
1885 #endif
1886             if (EdgeTol > 1.e-2)
1887               continue;
1888
1889             if (EdgeTol >= 1.e-4)
1890               {
1891                 ReconstructPCurves(anEdge);
1892                 BRepLib::SameParameter(anEdge, aSameParTol, Standard_True);
1893 #ifdef OCCT_DEBUG
1894                 cout<<"After projection tol of E = "<<BRep_Tool::Tolerance(anEdge)<<endl;
1895 #endif
1896               }
1897
1898             OrientSection( anEdge, F1, F2, O1, O2 );
1899             if (Side == TopAbs_OUT)
1900               {
1901                 O1 = TopAbs::Reverse(O1);
1902                 O2 = TopAbs::Reverse(O2);
1903               }
1904             
1905             L1.Append( anEdge.Oriented(O1) );
1906             L2.Append( anEdge.Oriented(O2) );
1907           }
1908       }
1909   } //end of if (L1.Extent() > 1)
1910
1911   else
1912     {
1913       TopTools_ListIteratorOfListOfShape itl(L1);
1914       for (; itl.More(); itl.Next())
1915         {
1916           const TopoDS_Edge& anEdge = TopoDS::Edge( itl.Value() );
1917           BRepLib::SameParameter(anEdge, aSameParTol, Standard_True);
1918         }
1919     }
1920 }
1921
1922 //=======================================================================
1923 //function : TryProject
1924 //purpose  : 
1925 //=======================================================================
1926
1927 Standard_Boolean BRepOffset_Tool::TryProject
1928 (const TopoDS_Face&          F1,
1929  const TopoDS_Face&          F2,
1930  const TopTools_ListOfShape& Edges,
1931        TopTools_ListOfShape& LInt1,
1932        TopTools_ListOfShape& LInt2,
1933  const TopAbs_State          Side,
1934  const Standard_Real         TolConf)
1935 {
1936 #ifdef DRAW
1937   if (AffichInter) {
1938     char name[256];
1939     sprintf(name,"FF_%d",NbFaces++);
1940     DBRep::Set(name,F1);
1941     sprintf(name,"FF_%d",NbFaces++);
1942     DBRep::Set(name,F2);
1943   }
1944 #endif
1945
1946   // try to find if the edges <Edges> are laying on the face F1.
1947   LInt1.Clear(); LInt2.Clear();
1948   TopTools_ListIteratorOfListOfShape it(Edges);
1949   Standard_Boolean     isOk = Standard_True;
1950   Standard_Boolean     Ok   = Standard_True;
1951   TopAbs_Orientation   O1,O2;
1952   Handle(Geom_Surface) Bouchon = BRep_Tool::Surface(F1);
1953   BRep_Builder B;
1954
1955   for ( ; it.More(); it.Next()) {
1956     TopLoc_Location L;
1957     Standard_Real f,l;
1958     TopoDS_Edge CurE     = TopoDS::Edge(it.Value());
1959     Handle(Geom_Curve) C = BRep_Tool::Curve(CurE,L,f,l);
1960     if (C.IsNull()) {
1961       BRepLib::BuildCurve3d(CurE,BRep_Tool::Tolerance(CurE));
1962       C  = BRep_Tool::Curve(CurE,L,f,l);
1963     }
1964     C = new Geom_TrimmedCurve(C,f,l);
1965     if ( !L.IsIdentity()) C->Transform(L);
1966     Standard_Real TolReached;
1967     isOk = IsOnSurface(C,Bouchon,TolConf,TolReached);
1968     
1969     if ( isOk) {
1970       B.UpdateEdge(CurE,TolReached);
1971       BuildPCurves(CurE,F1);
1972       OrientSection (CurE,F1,F2,O1,O2);
1973       if (Side == TopAbs_OUT) {
1974         O1 = TopAbs::Reverse(O1);
1975         O2 = TopAbs::Reverse(O2);
1976       }
1977       LInt1.Append (CurE.Oriented(O1));
1978       LInt2.Append (CurE.Oriented(O2));
1979 #ifdef DRAW
1980       if (AffichInter) {
1981         char name[256];
1982         sprintf(name,"EI_%d",NbNewEdges++);     
1983         DBRep::Set(name,CurE.Oriented(O1));
1984       }
1985 #endif      
1986     }
1987     else 
1988       Ok = Standard_False;
1989   }
1990   return Ok;
1991 }
1992
1993
1994 //=======================================================================
1995 //function : InterOrExtent
1996 //purpose  : 
1997 //=======================================================================
1998
1999 void BRepOffset_Tool::InterOrExtent(const TopoDS_Face& F1,
2000                                     const TopoDS_Face& F2,
2001                                     TopTools_ListOfShape& L1,
2002                                     TopTools_ListOfShape& L2,
2003                                     const TopAbs_State    Side)
2004 {
2005 #ifdef DRAW
2006   if (AffichInter) {
2007     char name[256];
2008     sprintf(name,"FF_%d",NbFaces++);
2009     DBRep::Set(name,F1);
2010     sprintf(name,"FF_%d",NbFaces++);
2011     DBRep::Set(name,F2);
2012   }
2013 #endif
2014
2015   Handle (Geom_Curve) CI;
2016   TopAbs_Orientation O1,O2;
2017   L1.Clear(); L2.Clear();
2018   Handle (Geom_Surface) S1 = BRep_Tool::Surface(F1);
2019   Handle (Geom_Surface) S2 = BRep_Tool::Surface(F2);  
2020
2021   if (S1->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
2022     Handle(Geom_RectangularTrimmedSurface) RTS ;
2023     RTS = Handle(Geom_RectangularTrimmedSurface)::DownCast (S1);
2024     if (RTS->BasisSurface()->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
2025       S1 = RTS->BasisSurface();
2026     }
2027   }
2028   if (S2->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
2029     Handle(Geom_RectangularTrimmedSurface) RTS ;
2030     RTS = Handle(Geom_RectangularTrimmedSurface)::DownCast (S2);
2031     if (RTS->BasisSurface()->DynamicType() == STANDARD_TYPE(Geom_Plane)) {
2032       S2 = RTS->BasisSurface();
2033     }
2034   }
2035
2036   GeomInt_IntSS Inter  (S1,S2, Precision::Confusion());
2037
2038   if (Inter.IsDone()) {
2039     for (Standard_Integer i = 1; i <= Inter.NbLines(); i++) {
2040       CI = Inter.Line(i);
2041       
2042       if (ToSmall(CI)) continue;
2043       TopoDS_Edge E = BRepLib_MakeEdge(CI);
2044       BuildPCurves (E,F1);
2045       BuildPCurves (E,F2);
2046       OrientSection (E,F1,F2,O1,O2);
2047       if (Side == TopAbs_OUT) {
2048         O1 = TopAbs::Reverse(O1);
2049         O2 = TopAbs::Reverse(O2);
2050       }
2051       L1.Append (E.Oriented(O1));
2052       L2.Append (E.Oriented(O2));
2053 #ifdef DRAW
2054       if (AffichInter) {
2055         char name[256];
2056         sprintf(name,"EI_%d",NbNewEdges++);     
2057         DBRep::Set(name,E.Oriented(O1));
2058       }
2059 #endif      
2060     }
2061   }
2062 }
2063
2064 //=======================================================================
2065 //function : ExtentEdge
2066 //purpose  : 
2067 //=======================================================================
2068
2069 static void ExtentEdge(const TopoDS_Face& F,
2070                        const TopoDS_Face& EF,
2071                        const TopoDS_Edge& E,
2072                        TopoDS_Edge&       NE)
2073 {
2074   BRepAdaptor_Curve CE(E);
2075   GeomAbs_CurveType Type = CE.GetType();
2076   TopoDS_Shape aLocalEdge = E.EmptyCopied();
2077   NE = TopoDS::Edge(aLocalEdge); 
2078 //  NE = TopoDS::Edge(E.EmptyCopied()); 
2079
2080   if (Type == GeomAbs_Line || Type == GeomAbs_Circle || Type == GeomAbs_Ellipse || 
2081       Type == GeomAbs_Hyperbola || Type == GeomAbs_Parabola) {
2082     return;
2083   }
2084   // Extension en tangence jusqu'au bord de la surface.
2085   Standard_Real   PMax = 1.e2;
2086   TopLoc_Location L;
2087   Handle(Geom_Surface) S = BRep_Tool::Surface(F,L);
2088   Standard_Real umin,umax,vmin,vmax;
2089
2090   S->Bounds(umin,umax,vmin,vmax);
2091   umin = Max(umin,-PMax);vmin = Max(vmin,-PMax);
2092   umax = Min(umax, PMax);vmax = Min(vmax, PMax);
2093
2094  
2095   Standard_Real f,l;
2096   Handle(Geom2d_Curve) C2d = BRep_Tool::CurveOnSurface(E,F,f,l);
2097
2098   //calcul point cible . ie point d'intersection du prolongement tangent et des bords.
2099   gp_Pnt2d P;
2100   gp_Vec2d Tang;
2101   C2d->D1(CE.FirstParameter(),P,Tang);
2102   Standard_Real tx,ty,tmin;
2103   tx = ty = Precision::Infinite();
2104   if (Abs(Tang.X()) > Precision::Confusion())
2105     tx = Min (Abs((umax - P.X())/Tang.X()), Abs((umin - P.X())/Tang.X()));
2106   if (Abs(Tang.Y()) > Precision::Confusion())
2107     ty = Min (Abs((vmax - P.Y())/Tang.Y()), Abs((vmin - P.Y())/Tang.Y()));
2108   tmin = Min (tx,ty);
2109   Tang = tmin*Tang;
2110   gp_Pnt2d  PF2d (P.X() - Tang.X(),P.Y() - Tang.Y());
2111
2112   C2d->D1(CE.LastParameter(),P,Tang);
2113   tx = ty = Precision::Infinite();
2114   if (Abs(Tang.X()) > Precision::Confusion())
2115     tx = Min (Abs((umax - P.X())/Tang.X()), Abs((umin - P.X())/Tang.X()));
2116   if (Abs(Tang.Y()) > Precision::Confusion())
2117     ty = Min (Abs((vmax - P.Y())/Tang.Y()), Abs((vmin - P.Y())/Tang.Y()));
2118   tmin = Min (tx,ty);
2119   Tang = tmin*Tang;
2120   gp_Pnt2d  PL2d (P.X() + Tang.X(),P.Y() + Tang.Y());
2121
2122   Handle(Geom_Curve) CC = GeomAPI::To3d(C2d,gp_Pln(gp::XOY()));
2123   gp_Pnt PF(PF2d.X(),PF2d.Y(),0.);
2124   gp_Pnt PL(PL2d.X(),PL2d.Y(),0.);
2125
2126   Handle(Geom_BoundedCurve) ExtC = Handle(Geom_BoundedCurve)::DownCast(CC);
2127   if (ExtC.IsNull()) return;
2128
2129   GeomLib::ExtendCurveToPoint(ExtC,PF,1,0);
2130   GeomLib::ExtendCurveToPoint(ExtC,PL,1,1); 
2131
2132   Handle(Geom2d_Curve) CNE2d = GeomAPI::To2d(ExtC,gp_Pln(gp::XOY()));
2133
2134   //Construction de la nouvelle arrete;
2135   BRep_Builder B;
2136   B.MakeEdge(NE);
2137 //  B.UpdateEdge (NE,CNE2d,F,BRep_Tool::Tolerance(E));
2138   B.UpdateEdge (NE,CNE2d,EF,BRep_Tool::Tolerance(E));
2139   B.Range (NE,CNE2d->FirstParameter(), CNE2d->LastParameter());
2140   NE.Orientation(E.Orientation());
2141 #ifdef DRAW
2142   if (AffichExtent) {
2143     char name[256];
2144     sprintf (name,"F_%d",NbExtE);
2145     DBRep::Set(name,EF);
2146     sprintf (name,"OE_%d",NbExtE);
2147     DBRep::Set (name,E);
2148     sprintf (name,"ExtE_%d",NbExtE++);
2149     DBRep::Set(name,NE);
2150   }
2151 #endif
2152 }
2153
2154 //=======================================================================
2155 //function : ProjectVertexOnEdge
2156 //purpose  : 
2157 //=======================================================================
2158
2159 static Standard_Boolean  ProjectVertexOnEdge(TopoDS_Vertex&     V,
2160                                              const TopoDS_Edge& E,
2161                                              Standard_Real      TolConf)
2162
2163 #ifdef DRAW
2164   if (AffichExtent) {
2165     DBRep::Set("V",V); 
2166     DBRep::Set("E",E);
2167   }
2168 #endif
2169   BRep_Builder    B;
2170   Standard_Real   f,l;
2171   Standard_Real U = 0.;
2172   TopLoc_Location L;
2173   Standard_Boolean found = Standard_False;
2174
2175   gp_Pnt            P = BRep_Tool::Pnt  (V);  
2176   BRepAdaptor_Curve C = BRepAdaptor_Curve(E);
2177   f = C.FirstParameter(); l = C.LastParameter();
2178
2179   if (V.Orientation() == TopAbs_FORWARD) {
2180     if (Abs(f) < Precision::Infinite()) { 
2181       gp_Pnt PF = C.Value (f);
2182       if (PF.IsEqual(P,TolConf)) {
2183         U = f;
2184         found = Standard_True;
2185       }
2186     }
2187   }
2188   if (V.Orientation() == TopAbs_REVERSED) {
2189     if (!found && Abs(l) < Precision::Infinite()) {
2190       gp_Pnt PL = C.Value (l);
2191       if (PL.IsEqual(P,TolConf)) {
2192         U = l;
2193         found = Standard_True;
2194       }
2195     }
2196   }
2197   if (!found) {
2198     Extrema_ExtPC Proj(P,C);
2199     if (Proj.IsDone() && Proj.NbExt() > 0) {
2200       Standard_Real Dist2,Dist2Min = Proj.SquareDistance(1);
2201       U = Proj.Point(1).Parameter();
2202       for (Standard_Integer i = 2; i <= Proj.NbExt(); i++) {
2203         Dist2 = Proj.SquareDistance(i);
2204         if (Dist2 < Dist2Min) {
2205           Dist2Min = Dist2;
2206           U = Proj.Point(i).Parameter();
2207         }
2208       }
2209       found = Standard_True;
2210     }
2211   }
2212
2213 #ifdef OCCT_DEBUG
2214   if (AffichExtent) {
2215     Standard_Real Dist = P.Distance(C.Value(U));
2216     if (Dist > TolConf) {
2217       cout << " ProjectVertexOnEdge :distance vertex edge :"<<Dist<<endl;
2218     }
2219     if (U < f - Precision::Confusion() || 
2220         U > l + Precision::Confusion()) {
2221       cout << " ProjectVertexOnEdge : hors borne :"<<endl;
2222       cout << " f = "<<f<<" l ="<<l<< " U ="<<U<<endl;
2223     }
2224   }
2225   if (!found) {
2226     cout <<"BRepOffset_Tool::ProjectVertexOnEdge Parameter no found"<<endl;
2227     if (Abs(f) < Precision::Infinite() && 
2228         Abs(l) < Precision::Infinite()) {
2229 #ifdef DRAW
2230       DBRep::Set("E",E);
2231 #endif
2232     }
2233   }    
2234 #endif 
2235   if (found) {
2236     TopoDS_Shape aLocalShape = E.Oriented(TopAbs_FORWARD);
2237     TopoDS_Edge EE = TopoDS::Edge(aLocalShape);
2238     aLocalShape = V.Oriented(TopAbs_INTERNAL);
2239 //    TopoDS_Edge EE = TopoDS::Edge(E.Oriented(TopAbs_FORWARD));
2240     B.UpdateVertex(TopoDS::Vertex(aLocalShape),
2241                    U,EE,BRep_Tool::Tolerance(E));
2242     
2243   }
2244   return found;
2245 }
2246
2247 //=======================================================================
2248 //function : Inter2d                                    
2249 //purpose  : 
2250 //=======================================================================
2251
2252 void BRepOffset_Tool::Inter2d (const TopoDS_Face&    F,
2253                                const TopoDS_Edge&    E1,
2254                                const TopoDS_Edge&    E2,
2255                                TopTools_ListOfShape& LV,
2256                                const Standard_Real   TolConf) 
2257 {
2258 #ifdef DRAW
2259   if (AffichExtent) {
2260     DBRep::Set("E1",E1); 
2261     DBRep::Set("E2",E2);
2262     DBRep::Set("F",F);
2263   }
2264 #endif
2265   BRep_Builder  B;
2266   Standard_Real fl1[2],fl2[2];
2267   LV.Clear();
2268   
2269   // Si l edge a ete etendu les pcurves ne sont pas forcement 
2270   // a jour.
2271   BuildPCurves(E1,F);
2272   BuildPCurves(E2,F);
2273   
2274
2275   // Construction des curves 3d si elles n existent pas 
2276   // utile pour coder correctement les parametres des vertex 
2277   // d intersection sur les edges.
2278   //TopLoc_Location L;
2279   //Standard_Real   f,l;
2280   //Handle(Geom_Curve) C3d1 = BRep_Tool::Curve(E1,L,f,l);
2281   //if (C3d1.IsNull()) {
2282   //  BRepLib::BuildCurve3d(E1,BRep_Tool::Tolerance(E1));
2283   //}
2284   //Handle(Geom_Curve) C3d2 = BRep_Tool::Curve(E2,L,f,l);
2285   //if (C3d2.IsNull()) {
2286   //  BRepLib::BuildCurve3d(E2,BRep_Tool::Tolerance(E2));
2287   //}
2288   
2289   Standard_Integer NbPC1 = 1, NbPC2 = 1;
2290   if (BRep_Tool::IsClosed(E1,F)) NbPC1++;
2291   if (BRep_Tool::IsClosed(E2,F)) NbPC2++;
2292   
2293   Handle(Geom_Surface) S  = BRep_Tool::Surface(F);
2294   Handle(Geom2d_Curve) C1, C2;
2295   Standard_Boolean YaSol = Standard_False;
2296   Standard_Integer itry  = 0;
2297
2298   while (!YaSol && itry < 2) {
2299     for ( Standard_Integer i = 1; i <= NbPC1 ; i++) {
2300         TopoDS_Shape aLocalEdgeReversedE1 = E1.Reversed();
2301       if (i == 1)  C1 = BRep_Tool::CurveOnSurface(E1,F,fl1[0],fl1[1]);
2302       else         C1 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalEdgeReversedE1),
2303                                                   F,fl1[0],fl1[1]);
2304 //      if (i == 1)  C1 = BRep_Tool::CurveOnSurface(E1,F,fl1[0],fl1[1]);
2305 //     else         C1 = BRep_Tool::CurveOnSurface(TopoDS::Edge(E1.Reversed()),
2306 //                                                F,fl1[0],fl1[1]);
2307       for ( Standard_Integer j = 1; j <= NbPC2; j++ ) {
2308         TopoDS_Shape aLocalEdge = E2.Reversed();
2309         if (j == 1)  C2 = BRep_Tool::CurveOnSurface(E2,F,fl2[0],fl2[1]);
2310         else         C2 = BRep_Tool::CurveOnSurface(TopoDS::Edge(aLocalEdge),
2311                                                     F,fl2[0],fl2[1]);
2312 //      if (j == 1)  C2 = BRep_Tool::CurveOnSurface(E2,F,fl2[0],fl2[1]);
2313 //      else         C2 = BRep_Tool::CurveOnSurface(TopoDS::Edge(E2.Reversed()),
2314 //                                                  F,fl2[0],fl2[1]);
2315 #ifdef OCCT_DEBUG
2316         if (C1.IsNull() || C2.IsNull()) {
2317           cout <<"Inter2d : Pas de pcurve"<<endl;
2318 #ifdef DRAW
2319           DBRep::Set("E1",E1); 
2320           DBRep::Set("E2",E2);
2321           DBRep::Set("F",F);
2322 #endif
2323           return;
2324         }
2325 #endif
2326         Standard_Real    U1 = 0.,U2 = 0.;
2327         gp_Pnt2d         P2d;   
2328         if (itry == 1) {
2329           fl1[0] = C1->FirstParameter(); fl1[1] = C1->LastParameter();
2330           fl2[0] = C2->FirstParameter(); fl2[1] = C2->LastParameter();
2331         }
2332         Geom2dAdaptor_Curve   AC1(C1,fl1[0],fl1[1]);
2333         Geom2dAdaptor_Curve   AC2(C2,fl2[0],fl2[1]);
2334
2335         if (itry == 0) {
2336           gp_Pnt2d P1[2],P2[2];
2337           P1[0] = C1->Value(fl1[0]); P1[1] = C1->Value(fl1[1]);
2338           P2[0] = C2->Value(fl2[0]); P2[1] = C2->Value(fl2[1]);
2339
2340           Standard_Integer i1 ;
2341           for ( i1 = 0; i1 < 2; i1++) {
2342             for (Standard_Integer i2 = 0; i2 < 2; i2++) {
2343               if (Abs(fl1[i1]) < Precision::Infinite() &&
2344                   Abs(fl2[i2]) < Precision::Infinite()   ) {
2345                 if (P1[i1].IsEqual(P2[i2],TolConf)) {
2346                   YaSol = Standard_True;
2347                   U1  = fl1[i1]; U2 = fl2[i2];
2348                   P2d = C1->Value(U1);
2349                 }
2350               }
2351             }
2352           }
2353           if (!YaSol)
2354             for (i1 = 0; i1 < 2; i1++)
2355               {
2356                 Extrema_ExtPC2d extr( P1[i1], AC2 );
2357                 if (extr.IsDone() && extr.NbExt() > 0)
2358                   {
2359                     Standard_Real Dist2, Dist2Min = extr.SquareDistance(1);
2360                     Standard_Integer IndexMin = 1;
2361                     for (Standard_Integer ind = 2; ind <= extr.NbExt(); ind++)
2362                       {
2363                         Dist2 = extr.SquareDistance(ind);
2364                         if (Dist2 < Dist2Min)
2365                           {
2366                             Dist2Min = Dist2;
2367                             IndexMin = ind;
2368                           }
2369                       }
2370             if (Dist2Min <= Precision::SquareConfusion())
2371                       {
2372                         YaSol = Standard_True;
2373                         P2d = P1[i1];
2374                         U1 = fl1[i1];
2375                         U2 = (extr.Point(IndexMin)).Parameter();
2376                         break;
2377                       }
2378                   }
2379               }
2380           if (!YaSol)
2381             for (Standard_Integer i2 = 0; i2 < 2; i2++)
2382               {
2383                 Extrema_ExtPC2d extr( P2[i2], AC1 );
2384                 if (extr.IsDone() && extr.NbExt() > 0)
2385                   {
2386                     Standard_Real Dist2, Dist2Min = extr.SquareDistance(1);
2387                     Standard_Integer IndexMin = 1;
2388                     for (Standard_Integer ind = 2; ind <= extr.NbExt(); ind++)
2389                       {
2390                         Dist2 = extr.SquareDistance(ind);
2391                         if (Dist2 < Dist2Min)
2392                           {
2393                             Dist2Min = Dist2;
2394                             IndexMin = ind;
2395                           }
2396                       }
2397             if (Dist2Min <= Precision::SquareConfusion())
2398                       {
2399                         YaSol = Standard_True;
2400                         P2d = P2[i2];
2401                         U2 = fl2[i2];
2402                         U1 = (extr.Point(IndexMin)).Parameter();
2403                         break;
2404                       }
2405                   }
2406               }
2407         }
2408         
2409         if (!YaSol) {
2410           Geom2dInt_GInter Inter (AC1,AC2,TolConf,TolConf);
2411           
2412           if (!Inter.IsEmpty() && Inter.NbPoints() > 0) {
2413             YaSol = Standard_True;
2414             U1  = Inter.Point(1).ParamOnFirst();
2415             U2  = Inter.Point(1).ParamOnSecond();
2416             P2d = Inter.Point(1).Value();
2417           }
2418           else if (!Inter.IsEmpty() && Inter.NbSegments() > 0) {
2419             YaSol = Standard_True;
2420             IntRes2d_IntersectionSegment Seg = Inter.Segment(1);
2421             IntRes2d_IntersectionPoint IntP1 = Seg.FirstPoint();
2422             IntRes2d_IntersectionPoint IntP2 = Seg.LastPoint();
2423             Standard_Real U1on1 = IntP1.ParamOnFirst();
2424             Standard_Real U1on2 = IntP2.ParamOnFirst();
2425             Standard_Real U2on1 = IntP1.ParamOnSecond();
2426             Standard_Real U2on2 = IntP2.ParamOnSecond();
2427 #ifdef OCCT_DEBUG
2428             cout << " BRepOffset_Tool::Inter2d SEGMENT d intersection" << endl;
2429             cout << "     ===> Parametres sur Curve1 : ";
2430             cout << U1on1 << " " << U1on2 << endl;
2431             cout << "     ===> Parametres sur Curve2 : ";
2432             cout << U2on1 << " " << U2on2 << endl;
2433 #endif
2434             U1 = (U1on1 + U1on2)/2.;
2435             U2 = (U2on1 + U2on2)/2.;
2436             gp_Pnt2d P2d1 = C1->Value(U1);
2437             gp_Pnt2d P2d2 = C2->Value(U2);
2438             P2d.SetX( (P2d1.X() + P2d2.X()) / 2.);
2439             P2d.SetY( (P2d1.Y() + P2d2.Y()) / 2.);
2440           }
2441         }
2442         if (YaSol) {
2443           gp_Pnt        P   = S->Value(P2d.X(),P2d.Y());
2444           TopoDS_Vertex V = BRepLib_MakeVertex(P);
2445           V.Orientation(TopAbs_INTERNAL);
2446           TopoDS_Shape aLocalEdgeOrientedE1 = E1.Oriented(TopAbs_FORWARD);
2447           B.UpdateVertex(V,U1,TopoDS::Edge(aLocalEdgeOrientedE1),TolConf);
2448           aLocalEdgeOrientedE1 = E2.Oriented(TopAbs_FORWARD);
2449           B.UpdateVertex(V,U2,TopoDS::Edge(aLocalEdgeOrientedE1),TolConf);
2450 //        B.UpdateVertex(V,U1,TopoDS::Edge(E1.Oriented(TopAbs_FORWARD)),TolConf);
2451 //        B.UpdateVertex(V,U2,TopoDS::Edge(E2.Oriented(TopAbs_FORWARD)),TolConf);
2452           LV.Append(V);
2453         }
2454       }
2455     }
2456     itry++;
2457   }
2458
2459   if (LV.Extent() > 1) {
2460     //------------------------------------------------
2461     // garde seulement les vertex les plus proches du 
2462     //debut et de la fin. 
2463     //------------------------------------------------
2464     TopTools_ListIteratorOfListOfShape it(LV);
2465     TopoDS_Vertex         VF,VL;
2466     Standard_Real         UMin =  Precision::Infinite();
2467     Standard_Real         UMax = -Precision::Infinite();
2468     Standard_Real         U;
2469
2470     for ( ; it.More(); it.Next()) {
2471       TopoDS_Vertex CV = TopoDS::Vertex(it.Value());
2472       TopoDS_Shape aLocalEdge = E1.Oriented(TopAbs_FORWARD);
2473       U = BRep_Tool::Parameter(CV,TopoDS::Edge(aLocalEdge));
2474 //      U = BRep_Tool::Parameter(CV,TopoDS::Edge(E1.Oriented(TopAbs_FORWARD)));
2475       if ( U < UMin) {
2476         VF = CV; UMin = U;
2477       }
2478       if ( U > UMax) {
2479         VL = CV; UMax = U;
2480       }
2481     }
2482     LV.Clear();LV.Append(VF); LV.Append(VL);
2483   }
2484
2485 #ifdef OCCT_DEBUG
2486   if (!YaSol) {
2487     cout <<"Inter2d : Pas de solution"<<endl;
2488 #ifdef DRAW
2489     DBRep::Set("E1",E1); 
2490     DBRep::Set("E2",E2);
2491     DBRep::Set("F",F);
2492 #endif
2493   }
2494 #endif    
2495 }
2496
2497 //=======================================================================
2498 //function : SelectEdge
2499 //purpose  : 
2500 //=======================================================================
2501
2502 static void SelectEdge (const TopoDS_Face& /*F*/,
2503                         const TopoDS_Face& /*EF*/,
2504                         const TopoDS_Edge& E,
2505                         TopTools_ListOfShape& LInt)
2506 {
2507  //------------------------------------------------------------
2508   // detrompeur sur les intersections sur les faces periodiques
2509   //------------------------------------------------------------
2510    TopTools_ListIteratorOfListOfShape it(LInt);
2511   Standard_Real dU = 1.0e100;
2512   TopoDS_Edge   GE;
2513
2514   Standard_Real Fst, Lst, tmp;
2515   BRep_Tool::Range(E, Fst, Lst);
2516   BRepAdaptor_Curve  Ad1(E);
2517  
2518   gp_Pnt PFirst = Ad1.Value( Fst );  
2519   gp_Pnt PLast  = Ad1.Value( Lst );  
2520
2521   //----------------------------------------------------------------------
2522   // Selection de l edge qui couvre le plus le domaine de l edge initiale.
2523   //---------------------------------------------------------------------- 
2524   for (; it.More(); it.Next()) {
2525     const TopoDS_Edge& EI = TopoDS::Edge(it.Value());
2526
2527     BRep_Tool::Range(EI, Fst, Lst);
2528     BRepAdaptor_Curve  Ad2(EI);
2529     gp_Pnt P1 = Ad2.Value(Fst);
2530     gp_Pnt P2 = Ad2.Value(Lst);
2531        
2532     tmp = P1.Distance(PFirst) + P2.Distance(PLast);
2533     if( tmp <= dU ) {
2534       dU = tmp;
2535       GE = EI;
2536     } 
2537
2538   }
2539   LInt.Clear(); 
2540   LInt.Append(GE);
2541 }
2542
2543
2544 //=======================================================================
2545 //function : Init
2546 //purpose  : 
2547 //=======================================================================
2548
2549 static void MakeFace(const Handle(Geom_Surface)& S,
2550                      const Standard_Real Um,
2551                      const Standard_Real UM,
2552                      const Standard_Real Vm,
2553                      const Standard_Real VM,
2554                      const Standard_Boolean isVminDegen,
2555                      const Standard_Boolean isVmaxDegen,
2556                      TopoDS_Face&        F)
2557 {
2558   Standard_Real UMin = Um;
2559   Standard_Real UMax = UM;
2560   Standard_Real VMin = Vm;
2561   Standard_Real VMax = VM;
2562   Standard_Real epsilon = Precision::Confusion();
2563
2564   Standard_Real umin,umax,vmin,vmax;
2565   S->Bounds(umin,umax,vmin,vmax);
2566
2567
2568   // compute infinite flags
2569   Standard_Boolean umininf = Precision::IsNegativeInfinite(UMin);
2570   Standard_Boolean umaxinf = Precision::IsPositiveInfinite(UMax);
2571   Standard_Boolean vmininf = Precision::IsNegativeInfinite(VMin);
2572   Standard_Boolean vmaxinf = Precision::IsPositiveInfinite(VMax);
2573   
2574   // closed flag
2575   Standard_Boolean IsSuclosed = S->IsUClosed(), IsSvclosed = S->IsVClosed();
2576   if (S->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface))
2577     {
2578       Handle(Geom_Surface) BasisSurf = Handle(Geom_OffsetSurface)::DownCast (S)->BasisSurface();
2579       IsSuclosed = BasisSurf->IsUClosed();
2580       IsSvclosed = BasisSurf->IsVClosed();
2581     }
2582
2583   Standard_Boolean uclosed = 
2584     IsSuclosed && 
2585       Abs(UMin - umin) < epsilon && 
2586         Abs(UMax - umax) < epsilon;
2587   
2588   Standard_Boolean vclosed = 
2589     IsSvclosed && 
2590       Abs(VMin - vmin) < epsilon && 
2591         Abs(VMax - vmax) < epsilon;
2592   
2593   // degenerated flags (for cones)
2594   Standard_Boolean vmindegen = isVminDegen, vmaxdegen = isVmaxDegen;
2595   Handle(Geom_Surface) theSurf = S;
2596   if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
2597     theSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
2598   if (theSurf->DynamicType() == STANDARD_TYPE(Geom_ConicalSurface))
2599     {
2600       Handle(Geom_ConicalSurface) ConicalS = Handle(Geom_ConicalSurface)::DownCast (theSurf);
2601       gp_Cone theCone = ConicalS->Cone();
2602       gp_Pnt theApex = theCone.Apex();
2603       Standard_Real Uapex, Vapex;
2604       ElSLib::Parameters( theCone, theApex, Uapex, Vapex );
2605       if (Abs(VMin - Vapex) <= Precision::Confusion())
2606         vmindegen = Standard_True;
2607       if (Abs(VMax - Vapex) <= Precision::Confusion())
2608         vmaxdegen = Standard_True;
2609     }
2610   
2611   // compute vertices
2612   BRep_Builder B;
2613   Standard_Real tol = Precision::Confusion();
2614   
2615   TopoDS_Vertex V00,V10,V11,V01;
2616   
2617   if (!umininf) {
2618     if (!vmininf) B.MakeVertex(V00,S->Value(UMin,VMin),tol);
2619     if (!vmaxinf) B.MakeVertex(V01,S->Value(UMin,VMax),tol);
2620   }
2621   if (!umaxinf) {
2622     if (!vmininf) B.MakeVertex(V10,S->Value(UMax,VMin),tol);
2623     if (!vmaxinf) B.MakeVertex(V11,S->Value(UMax,VMax),tol);
2624   }
2625
2626   if (uclosed) {
2627     V10 = V00;
2628     V11 = V01;
2629   }
2630
2631   if (vclosed) {
2632     V01 = V00;
2633     V11 = V10;
2634   }
2635
2636   if (vmindegen)
2637     V10 = V00;
2638   if (vmaxdegen)
2639     V11 = V01;
2640
2641   // make the lines
2642   Handle(Geom2d_Line) Lumin,Lumax,Lvmin,Lvmax;
2643   if (!umininf)
2644     Lumin = new Geom2d_Line(gp_Pnt2d(UMin,0),gp_Dir2d(0,1));
2645   if (!umaxinf)
2646     Lumax = new Geom2d_Line(gp_Pnt2d(UMax,0),gp_Dir2d(0,1));
2647   if (!vmininf)
2648     Lvmin = new Geom2d_Line(gp_Pnt2d(0,VMin),gp_Dir2d(1,0));
2649   if (!vmaxinf)
2650     Lvmax = new Geom2d_Line(gp_Pnt2d(0,VMax),gp_Dir2d(1,0));
2651   
2652   Handle(Geom_Curve) Cumin,Cumax,Cvmin,Cvmax;
2653   Standard_Real TolApex = 1.e-5;
2654   //Standard_Boolean hasiso = ! S->IsKind(STANDARD_TYPE(Geom_OffsetSurface));
2655   Standard_Boolean hasiso = S->IsKind(STANDARD_TYPE(Geom_ElementarySurface));
2656   if (hasiso) {
2657     if (!umininf)
2658       Cumin = S->UIso(UMin);
2659     if (!umaxinf)
2660       Cumax = S->UIso(UMax);
2661     if (!vmininf)
2662       {
2663         Cvmin = S->VIso(VMin);
2664         if (BRepOffset_Tool::Gabarit( Cvmin ) <= TolApex)
2665           vmindegen = Standard_True;
2666       }
2667     if (!vmaxinf)
2668       {
2669         Cvmax = S->VIso(VMax);
2670         if (BRepOffset_Tool::Gabarit( Cvmax ) <= TolApex)
2671           vmaxdegen = Standard_True;
2672       }
2673   }
2674
2675   // make the face
2676   B.MakeFace(F,S,tol);
2677
2678   // make the edges
2679   TopoDS_Edge eumin,eumax,evmin,evmax;
2680
2681   if (!umininf) {
2682     if (hasiso)
2683       B.MakeEdge(eumin,Cumin,tol);
2684     else
2685       B.MakeEdge(eumin);
2686     if (uclosed) 
2687       B.UpdateEdge(eumin,Lumax,Lumin,F,tol);
2688     else
2689       B.UpdateEdge(eumin,Lumin,F,tol);
2690     if (!vmininf) {
2691       V00.Orientation(TopAbs_FORWARD);
2692       B.Add(eumin,V00);
2693     }
2694     if (!vmaxinf) {
2695       V01.Orientation(TopAbs_REVERSED);
2696       B.Add(eumin,V01);
2697     }
2698     B.Range(eumin,VMin,VMax);
2699   }
2700
2701   if (!umaxinf) {
2702     if (uclosed)
2703       eumax = eumin;
2704     else {
2705       if (hasiso)
2706         B.MakeEdge(eumax,Cumax,tol);
2707       else
2708         B.MakeEdge(eumax);
2709       B.UpdateEdge(eumax,Lumax,F,tol);
2710       if (!vmininf) {
2711         V10.Orientation(TopAbs_FORWARD);
2712         B.Add(eumax,V10);
2713       }
2714       if (!vmaxinf) {
2715         V11.Orientation(TopAbs_REVERSED);
2716         B.Add(eumax,V11);
2717       }
2718       B.Range(eumax,VMin,VMax);
2719     }
2720   }
2721
2722   if (!vmininf) {
2723     if (hasiso && !vmindegen)
2724       B.MakeEdge(evmin,Cvmin,tol);
2725     else
2726       B.MakeEdge(evmin);
2727     if (vclosed)
2728       B.UpdateEdge(evmin,Lvmin,Lvmax,F,tol);
2729     else
2730       B.UpdateEdge(evmin,Lvmin,F,tol);
2731     if (!umininf) {
2732       V00.Orientation(TopAbs_FORWARD);
2733       B.Add(evmin,V00);
2734     }
2735     if (!umaxinf) {
2736       V10.Orientation(TopAbs_REVERSED);
2737       B.Add(evmin,V10);
2738     }
2739     B.Range(evmin,UMin,UMax);
2740     if (vmindegen)
2741       B.Degenerated(evmin, Standard_True);
2742   }
2743
2744   if (!vmaxinf) {
2745     if (vclosed)
2746       evmax = evmin;
2747     else {
2748       if (hasiso && !vmaxdegen)
2749         B.MakeEdge(evmax,Cvmax,tol);
2750       else
2751         B.MakeEdge(evmax);
2752       B.UpdateEdge(evmax,Lvmax,F,tol);
2753       if (!umininf) {
2754         V01.Orientation(TopAbs_FORWARD);
2755         B.Add(evmax,V01);
2756       }
2757       if (!umaxinf) {
2758         V11.Orientation(TopAbs_REVERSED);
2759         B.Add(evmax,V11);
2760       }
2761       B.Range(evmax,UMin,UMax);
2762       if (vmaxdegen)
2763         B.Degenerated(evmax, Standard_True);
2764     }
2765   }
2766
2767   // make the wires and add them to the face
2768   eumin.Orientation(TopAbs_REVERSED);
2769   evmax.Orientation(TopAbs_REVERSED);
2770   
2771   TopoDS_Wire W;
2772
2773   if (!umininf && !umaxinf && vmininf && vmaxinf) {
2774     // two wires in u
2775     B.MakeWire(W);
2776     B.Add(W,eumin);
2777     B.Add(F,W);
2778     B.MakeWire(W);
2779     B.Add(W,eumax);
2780     B.Add(F,W);
2781     F.Closed(uclosed);
2782   }
2783     
2784   else if (umininf && umaxinf && !vmininf && !vmaxinf) {
2785     // two wires in v
2786     B.MakeWire(W);
2787     B.Add(W,evmin);
2788     B.Add(F,W);
2789     B.MakeWire(W);
2790     B.Add(W,evmax);
2791     B.Add(F,W);
2792     F.Closed(vclosed);
2793   }
2794     
2795   else if (!umininf || !umaxinf || !vmininf || !vmaxinf) {
2796     // one wire
2797     B.MakeWire(W);
2798     if (!umininf) B.Add(W,eumin);
2799     if (!vmininf) B.Add(W,evmin);
2800     if (!umaxinf) B.Add(W,eumax);
2801     if (!vmaxinf) B.Add(W,evmax);
2802     B.Add(F,W);
2803     W.Closed(!umininf && !umaxinf && !vmininf && !vmaxinf);
2804     F.Closed(uclosed && vclosed);
2805   }
2806 }
2807
2808 //=======================================================================
2809 //function : EnLargeGeometry
2810 //purpose  : 
2811 //=======================================================================
2812
2813 static Standard_Boolean EnlargeGeometry(Handle(Geom_Surface)& S,
2814                                         Standard_Real&        U1,
2815                                         Standard_Real&        U2,
2816                                         Standard_Real&        V1,
2817                                         Standard_Real&        V2,
2818                                         Standard_Boolean&     IsV1degen,
2819                                         Standard_Boolean&     IsV2degen,
2820                                         const Standard_Real   uf1,
2821                                         const Standard_Real   uf2,
2822                                         const Standard_Real   vf1,
2823                                         const Standard_Real   vf2,
2824                                         const Standard_Boolean GlobalEnlargeU,
2825                                         const Standard_Boolean GlobalEnlargeVfirst,
2826                                         const Standard_Boolean GlobalEnlargeVlast)
2827 {
2828   const Standard_Real coeff = 4.;
2829   const Standard_Real TolApex = 1.e-5;
2830
2831   Standard_Boolean SurfaceChange = Standard_False;
2832   if ( S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
2833     Handle(Geom_Surface) BS = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
2834     EnlargeGeometry(BS,U1,U2,V1,V2,IsV1degen,IsV2degen,
2835                     uf1,uf2,vf1,vf2,GlobalEnlargeU,GlobalEnlargeVfirst,GlobalEnlargeVlast);
2836     if (!GlobalEnlargeVfirst)
2837       V1 = vf1;
2838     if (!GlobalEnlargeVlast)
2839       V2 = vf2;
2840     if (!GlobalEnlargeVfirst || !GlobalEnlargeVlast)
2841       //Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->SetTrim( U1, U2, V1, V2 );
2842       S = new Geom_RectangularTrimmedSurface( BS, U1, U2, V1, V2 );
2843     else
2844       S = BS;
2845     SurfaceChange = Standard_True;
2846   }
2847   else if (S->DynamicType() == STANDARD_TYPE(Geom_OffsetSurface)) {
2848     Handle(Geom_Surface) Surf = Handle(Geom_OffsetSurface)::DownCast (S)->BasisSurface();
2849     SurfaceChange = EnlargeGeometry(Surf,U1,U2,V1,V2,IsV1degen,IsV2degen,
2850                                     uf1,uf2,vf1,vf2,GlobalEnlargeU,GlobalEnlargeVfirst,GlobalEnlargeVlast);
2851     Handle(Geom_OffsetSurface)::DownCast(S)->SetBasisSurface(Surf);
2852   }
2853   else if (S->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion) ||
2854            S->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfRevolution))
2855     {
2856       Standard_Real du=0., dv=0.;
2857       Handle( Geom_Curve ) uiso, viso, uiso1, uiso2, viso1, viso2;
2858       Standard_Real u1, u2, v1, v2;
2859       Standard_Boolean enlargeU = GlobalEnlargeU, enlargeV = Standard_True;
2860       Standard_Boolean enlargeUfirst = enlargeU, enlargeUlast = enlargeU;
2861       Standard_Boolean enlargeVfirst = GlobalEnlargeVfirst, enlargeVlast = GlobalEnlargeVlast;
2862       S->Bounds( u1, u2, v1, v2 );
2863       if (Precision::IsInfinite(u1) || Precision::IsInfinite(u2))
2864         {
2865           du = uf2-uf1;
2866           u1 = uf1-du;
2867           u2 = uf2+du;
2868           enlargeU = Standard_False;
2869         }
2870       else if (S->IsUClosed())
2871         enlargeU = Standard_False;
2872       else
2873         {
2874           viso = S->VIso( vf1 );
2875           GeomAdaptor_Curve gac( viso );
2876           du = GCPnts_AbscissaPoint::Length( gac ) / coeff;
2877           uiso1 = S->UIso( uf1 );
2878           uiso2 = S->UIso( uf2 );
2879           if (BRepOffset_Tool::Gabarit( uiso1 ) <= TolApex)
2880             enlargeUfirst = Standard_False;
2881           if (BRepOffset_Tool::Gabarit( uiso2 ) <= TolApex)
2882             enlargeUlast = Standard_False;
2883         }
2884       if (Precision::IsInfinite(v1) || Precision::IsInfinite(v2))
2885         {
2886           dv = vf2-vf1;
2887           v1 = vf1-dv;
2888           v2 = vf2+dv;
2889           enlargeV = Standard_False;
2890         }
2891       else if (S->IsVClosed())
2892         enlargeV = Standard_False;
2893       else
2894         {
2895           uiso = S->UIso( uf1 );
2896           GeomAdaptor_Curve gac( uiso );
2897           dv = GCPnts_AbscissaPoint::Length( gac ) / coeff;
2898           viso1 = S->VIso( vf1 );
2899           viso2 = S->VIso( vf2 );
2900           if (BRepOffset_Tool::Gabarit( viso1 ) <= TolApex)
2901             {
2902               enlargeVfirst = Standard_False;
2903               IsV1degen = Standard_True;
2904             }
2905           if (BRepOffset_Tool::Gabarit( viso2 ) <= TolApex)
2906             {
2907               enlargeVlast = Standard_False;
2908               IsV2degen = Standard_True;
2909             }
2910         }
2911       Handle(Geom_BoundedSurface) aSurf = new Geom_RectangularTrimmedSurface( S, u1, u2, v1, v2 );
2912       if (enlargeU)
2913         {
2914           if (enlargeUfirst)
2915             GeomLib::ExtendSurfByLength (aSurf, du, 1, Standard_True, Standard_False);
2916           if (enlargeUlast)
2917             GeomLib::ExtendSurfByLength (aSurf, du, 1, Standard_True, Standard_True);
2918         }
2919       if (enlargeV)
2920         {
2921           if (enlargeVfirst)
2922             GeomLib::ExtendSurfByLength (aSurf, dv, 1, Standard_False, Standard_False);
2923           if (enlargeVlast)
2924             GeomLib::ExtendSurfByLength (aSurf, dv, 1, Standard_False, Standard_True);
2925         }
2926       S = aSurf;
2927       S->Bounds( U1, U2, V1, V2 );
2928       SurfaceChange = Standard_True;
2929     }
2930   else if (S->DynamicType() == STANDARD_TYPE(Geom_BezierSurface) ||
2931            S->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface))
2932     {
2933       Standard_Boolean enlargeU = GlobalEnlargeU, enlargeV = Standard_True;
2934       Standard_Boolean enlargeUfirst = enlargeU, enlargeUlast = enlargeU;
2935       Standard_Boolean enlargeVfirst = GlobalEnlargeVfirst, enlargeVlast = GlobalEnlargeVlast;
2936       if (S->IsUClosed())
2937         enlargeU = Standard_False;
2938       if (S->IsVClosed())
2939         enlargeV = Standard_False;
2940
2941       Standard_Real duf = uf2-uf1, dvf = vf2-vf1;
2942       Standard_Real u1, u2, v1, v2;
2943       S->Bounds( u1, u2, v1, v2 );
2944
2945       Standard_Real du=0., dv=0.;
2946       Handle( Geom_Curve ) uiso, viso, uiso1, uiso2, viso1, viso2;
2947       GeomAdaptor_Curve gac;
2948       if (enlargeU)
2949         {
2950           viso = S->VIso( v1 );
2951           gac.Load( viso );
2952           du = GCPnts_AbscissaPoint::Length( gac ) / coeff;
2953           uiso1 = S->UIso( u1 );
2954           uiso2 = S->UIso( u2 );
2955           if (BRepOffset_Tool::Gabarit( uiso1 ) <= TolApex)
2956             enlargeUfirst = Standard_False;
2957           if (BRepOffset_Tool::Gabarit( uiso2 ) <= TolApex)
2958             enlargeUlast = Standard_False;
2959         }
2960       if (enlargeV)
2961         {
2962           uiso = S->UIso( u1 );
2963           gac.Load( uiso );
2964           dv = GCPnts_AbscissaPoint::Length( gac ) / coeff;
2965           viso1 = S->VIso( v1 );
2966           viso2 = S->VIso( v2 );
2967           if (BRepOffset_Tool::Gabarit( viso1 ) <= TolApex)
2968             {
2969               enlargeVfirst = Standard_False;
2970               IsV1degen = Standard_True;
2971             }
2972           if (BRepOffset_Tool::Gabarit( viso2 ) <= TolApex)
2973             {
2974               enlargeVlast = Standard_False;
2975               IsV2degen = Standard_True;
2976             }
2977         }
2978
2979       Handle(Geom_BoundedSurface) aSurf = Handle(Geom_BoundedSurface)::DownCast (S);
2980       if (enlargeU)
2981         {
2982           if (enlargeUfirst && uf1-u1 < duf)
2983             GeomLib::ExtendSurfByLength (aSurf, du, 1, Standard_True, Standard_False);
2984           if (enlargeUlast && u2-uf2 < duf)
2985             GeomLib::ExtendSurfByLength (aSurf, du, 1, Standard_True, Standard_True);
2986         }
2987       if (enlargeV)
2988         {
2989           if (enlargeVfirst && vf1-v1 < dvf)
2990             GeomLib::ExtendSurfByLength (aSurf, dv, 1, Standard_False, Standard_False);
2991           if (enlargeVlast && v2-vf2 < dvf)
2992             GeomLib::ExtendSurfByLength (aSurf, dv, 1, Standard_False, Standard_True);
2993         }
2994       S = aSurf;
2995
2996       S->Bounds( U1, U2, V1, V2 );
2997       SurfaceChange = Standard_True;
2998     }
2999 //  else if (S->DynamicType() == STANDARD_TYPE(Geom_BezierSurface) ||
3000 //         S->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface)) {
3001 //    S->Bounds(U1,U2,V1,V2);
3002 //  }
3003   else { 
3004     Standard_Real UU1,UU2,VV1,VV2;
3005     S->Bounds(UU1,UU2,VV1,VV2);
3006     // Pas d extension au dela des bornes de la surface.
3007     U1 = Max(UU1,U1);    
3008     V1 = Max(VV1,V1);
3009     U2 = Min(UU2,U2);    
3010     V2 = Min(VV2,V2);
3011   }
3012   return SurfaceChange;
3013 }
3014
3015 //=======================================================================
3016 //function : UpDatePCurve
3017 //purpose  :  Mise a jour des pcurves de F sur la surface de de BF.
3018 //            F and BF has to be FORWARD,
3019 //=======================================================================
3020
3021 static void UpdatePCurves (const TopoDS_Face& F,
3022                                  TopoDS_Face& BF)
3023 {
3024   Standard_Real   f,l;
3025   Standard_Integer i;
3026   BRep_Builder    B;
3027   TopTools_IndexedMapOfShape Emap;
3028   Handle(Geom2d_Curve) NullPCurve;
3029
3030   TopExp::MapShapes( F, TopAbs_EDGE, Emap );
3031   
3032   for (i = 1; i <= Emap.Extent(); i++)
3033     {
3034       TopoDS_Edge CE = TopoDS::Edge( Emap(i) );
3035       CE.Orientation( TopAbs_FORWARD );
3036       Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface( CE, F, f, l );
3037       if (!C2.IsNull())
3038         {
3039           if (BRep_Tool::IsClosed( CE, F ))
3040             {
3041               CE.Reverse();
3042               Handle(Geom2d_Curve) C2R = BRep_Tool::CurveOnSurface( CE, F, f, l );
3043               B.UpdateEdge( CE, NullPCurve, NullPCurve, F, BRep_Tool::Tolerance(CE) );
3044               B.UpdateEdge( CE, C2, C2R, BF, BRep_Tool::Tolerance(CE) );
3045             }
3046           else
3047             {
3048               B.UpdateEdge( CE, NullPCurve, F, BRep_Tool::Tolerance(CE) );
3049               B.UpdateEdge( CE, C2, BF, BRep_Tool::Tolerance(CE) );
3050             }
3051
3052           B.Range(CE,f,l);
3053         }
3054     }
3055 }
3056
3057 //=======================================================================
3058 //function :CompactUVBounds
3059 //purpose  : 
3060 //=======================================================================
3061
3062 static void CompactUVBounds (const TopoDS_Face& F,
3063                                  Standard_Real& UMin,
3064                                  Standard_Real& UMax,
3065                                  Standard_Real& VMin,
3066                                  Standard_Real& VMax)
3067 {
3068   // Calcul serre pour que les bornes ne couvrent pas plus d une periode
3069   Standard_Real U1,U2;
3070   Standard_Real N = 33;
3071   Bnd_Box2d B;
3072   
3073   TopExp_Explorer exp;  
3074   for (exp.Init(F, TopAbs_EDGE); exp.More(); exp.Next()) {
3075     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
3076     BRepAdaptor_Curve2d C(E,F);
3077     BRep_Tool::Range(E,U1,U2);
3078     gp_Pnt2d P;
3079     Standard_Real U  = U1;
3080     Standard_Real DU = (U2-U1)/(N-1);
3081     for (Standard_Integer j=1;j<N;j++) {
3082       C.D0(U,P);
3083       U+=DU;
3084       B.Add(P);
3085     }
3086     C.D0(U2,P);
3087     B.Add(P);
3088   }
3089   B.Get(UMin,VMin,UMax,VMax);
3090 }
3091
3092 //=======================================================================
3093 //function : CheckBounds
3094 //purpose  : 
3095 //=======================================================================
3096
3097 void BRepOffset_Tool::CheckBounds(const TopoDS_Face& F,
3098                                   const BRepOffset_Analyse& Analyse,
3099                                   Standard_Boolean& enlargeU,
3100                                   Standard_Boolean& enlargeVfirst,
3101                                   Standard_Boolean& enlargeVlast)
3102 {
3103   enlargeU = Standard_True;
3104   enlargeVfirst = Standard_True; enlargeVlast = Standard_True;
3105
3106   Standard_Integer Ubound = 0, Vbound = 0;
3107   Standard_Real Ufirst = RealLast(), Ulast = RealFirst();
3108   Standard_Real Vfirst = RealLast(), Vlast = RealFirst();
3109
3110   Standard_Real UF1,UF2,VF1,VF2;
3111   CompactUVBounds(F,UF1,UF2,VF1,VF2);
3112
3113   Handle(Geom_Surface) theSurf = BRep_Tool::Surface(F);
3114   if (theSurf->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
3115     theSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast (theSurf)->BasisSurface();
3116
3117   if (theSurf->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfLinearExtrusion) ||
3118       theSurf->DynamicType() == STANDARD_TYPE(Geom_SurfaceOfRevolution) ||
3119       theSurf->DynamicType() == STANDARD_TYPE(Geom_BezierSurface) ||
3120       theSurf->DynamicType() == STANDARD_TYPE(Geom_BSplineSurface))
3121     {
3122       TopExp_Explorer Explo(F, TopAbs_EDGE);
3123       for (; Explo.More(); Explo.Next())
3124         {
3125           const TopoDS_Edge& anEdge = TopoDS::Edge(Explo.Current());
3126           const BRepOffset_ListOfInterval& L = Analyse.Type(anEdge);
3127           if (!L.IsEmpty() || BRep_Tool::Degenerated(anEdge))
3128             {
3129               BRepOffset_Type OT = L.First().Type();
3130               if (OT == BRepOffset_Tangent || BRep_Tool::Degenerated(anEdge))
3131                 {
3132                   Standard_Real fpar, lpar;
3133                   Handle(Geom2d_Curve) aCurve = BRep_Tool::CurveOnSurface(anEdge, F, fpar, lpar);
3134                   if (aCurve->DynamicType() == STANDARD_TYPE(Geom2d_TrimmedCurve))
3135                     aCurve = Handle(Geom2d_TrimmedCurve)::DownCast (aCurve)->BasisCurve();
3136                   
3137                   Handle(Geom2d_Line) theLine;
3138                   if (aCurve->DynamicType() == STANDARD_TYPE(Geom2d_Line))
3139                     theLine = Handle(Geom2d_Line)::DownCast (aCurve);
3140                   else if (aCurve->DynamicType() == STANDARD_TYPE(Geom2d_BezierCurve) ||
3141                            aCurve->DynamicType() == STANDARD_TYPE(Geom2d_BSplineCurve))
3142                     {
3143                       Standard_Real newFpar, newLpar, deviation;
3144                       theLine = ShapeCustom_Curve2d::ConvertToLine2d(aCurve, fpar, lpar, Precision::Confusion(),
3145                                                                      newFpar, newLpar, deviation);
3146                     }
3147
3148                   if (!theLine.IsNull())
3149                     {
3150                       gp_Dir2d theDir = theLine->Direction();
3151                       if (theDir.IsParallel( gp::DX2d(), Precision::Angular() ))
3152                         {
3153                           Vbound++;
3154                           if (BRep_Tool::Degenerated(anEdge))
3155                             {
3156                               if (Abs(theLine->Location().Y() - VF1) <= Precision::Confusion())
3157                                 enlargeVfirst = Standard_False;
3158                               else //theLine->Location().Y() is near VF2
3159                                 enlargeVlast  = Standard_False;
3160                             }
3161                           else
3162                             {
3163                               if (theLine->Location().Y() < Vfirst)
3164                                 Vfirst = theLine->Location().Y();
3165                               if (theLine->Location().Y() > Vlast)
3166                                 Vlast  = theLine->Location().Y();
3167                             }
3168                         }
3169                       else if (theDir.IsParallel( gp::DY2d(), Precision::Angular() ))
3170                         {
3171                           Ubound++;
3172                           if (theLine->Location().X() < Ufirst)
3173                             Ufirst = theLine->Location().X();
3174                           if (theLine->Location().X() > Ulast)
3175                             Ulast  = theLine->Location().X();
3176                         }
3177                     }
3178                 }
3179             }
3180         }
3181     }
3182
3183   if (Ubound >= 2 || Vbound >= 2)
3184     {
3185       if (Ubound >= 2 &&
3186           Abs(UF1-Ufirst) <= Precision::Confusion() &&
3187           Abs(UF2-Ulast)  <= Precision::Confusion())
3188         enlargeU = Standard_False;
3189       if (Vbound >= 2 &&
3190           Abs(VF1-Vfirst) <= Precision::Confusion() &&
3191           Abs(VF2-Vlast)  <= Precision::Confusion())
3192         {
3193           enlargeVfirst = Standard_False;
3194           enlargeVlast  = Standard_False;
3195         }
3196     }
3197 }
3198
3199 //=======================================================================
3200 //function : EnLargeFace
3201 //purpose  : 
3202 //=======================================================================
3203
3204 Standard_Boolean BRepOffset_Tool::EnLargeFace 
3205 (const TopoDS_Face&       F,
3206  TopoDS_Face&             BF,
3207  const Standard_Boolean   CanExtentSurface,
3208  const Standard_Boolean   UpdatePCurve,
3209  const Standard_Boolean   enlargeU,
3210  const Standard_Boolean   enlargeVfirst,
3211  const Standard_Boolean   enlargeVlast)
3212 {
3213   //---------------------------
3214   // extension de la geometrie.
3215   //---------------------------
3216   TopLoc_Location       L;
3217   Handle (Geom_Surface) S = BRep_Tool::Surface(F,L);
3218   Standard_Real         UU1,VV1,UU2,VV2;
3219   Standard_Boolean      isVV1degen = Standard_False, isVV2degen = Standard_False;
3220   Standard_Real         US1,VS1,US2,VS2;
3221   Standard_Real         UF1,VF1,UF2,VF2;
3222   // The maximal value to enlarge surfaces is decreased to 1.e+7.
3223   // It is justified by the floating point format. As we can have only 15
3224   // valuable decimal numbers, then during intersection of surfaces with
3225   // bounds of 1.e+8 the possible inaccuracy might appear already in seventh
3226   // decimal place which will be more than Precision::Confusion value -
3227   // 1.e-7, default tolerance value for the section curves.
3228   // By decreasing the max enlarge value to 1.e+7 the inaccuracy will be
3229   // shifted to eighth decimal place, i.e. the inaccuracy will be
3230   // decreased to values less than 1.e-7.
3231   Standard_Real         infini = 1.e7;//1.e8;
3232   Standard_Boolean      SurfaceChange = Standard_False;
3233
3234   if (S->IsUPeriodic() || S->IsVPeriodic()) {
3235     // Calcul serre pour que les bornes ne couvre pas plus d une periode
3236     CompactUVBounds(F,UF1,UF2,VF1,VF2);                                        
3237   }
3238   else {
3239     BRepTools::UVBounds(F,UF1,UF2,VF1,VF2);
3240   }
3241
3242   S->Bounds            (US1,US2,VS1,VS2);
3243   UU1 = VV1 = - infini;
3244   UU2 = VV2 =   infini;
3245   
3246   if (CanExtentSurface) {
3247     SurfaceChange = EnlargeGeometry( S, UU1, UU2, VV1, VV2, isVV1degen, isVV2degen, UF1, UF2, VF1, VF2,
3248                                      enlargeU, enlargeVfirst, enlargeVlast );
3249   }
3250   else {
3251     UU1 = Max(US1,UU1); UU2 = Min(UU2,US2); 
3252     VV1 = Max(VS1,VV1); VV2 = Min(VS2,VV2);
3253   }
3254
3255   if (S->IsUPeriodic()) {
3256     Standard_Real    Period = S->UPeriod(); 
3257     Standard_Real    Delta  = Period - (UF2 - UF1);
3258     Standard_Real    alpha  = 0.1;
3259     UU1 = UF1 - alpha*Delta; UU2 = UF2 + alpha*Delta;
3260     if ((UU2 - UU1) > Period) {
3261       UU2 = UU1 + Period;
3262     }
3263   }
3264   if (S->IsVPeriodic()) {
3265     Standard_Real    Period = S->VPeriod(); 
3266     Standard_Real    Delta  = Period - (VF2 - VF1);
3267     Standard_Real    alpha  = 0.1;
3268     VV1 = VF1 - alpha*Delta; VV2 = VF2 + alpha*Delta;
3269     if ((VV2 - VV1) > Period) {
3270       VV2 = VV1 + Period;
3271     }
3272   }
3273
3274   //Special treatment for conical surfaces
3275   Handle(Geom_Surface) theSurf = S;
3276   if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface))
3277     theSurf = Handle(Geom_RectangularTrimmedSurface)::DownCast (S)->BasisSurface();
3278   if (theSurf->DynamicType() == STANDARD_TYPE(Geom_ConicalSurface))
3279     {
3280       Handle(Geom_ConicalSurface) ConicalS = Handle(Geom_ConicalSurface)::DownCast (theSurf);
3281       gp_Cone theCone = ConicalS->Cone();
3282       gp_Pnt theApex = theCone.Apex();
3283       Standard_Real Uapex, Vapex;
3284       ElSLib::Parameters( theCone, theApex, Uapex, Vapex );
3285       if (VV1 < Vapex && Vapex < VV2)
3286         {
3287           //consider that VF1 and VF2 are on the same side from apex
3288           Standard_Real TolApex = 1.e-5;
3289           if (Vapex - VF1 >= TolApex ||
3290               Vapex - VF2 >= TolApex)   //if (VF1 < Vapex || VF2 < Vapex)
3291             VV2 = Vapex;
3292           else
3293             VV1 = Vapex;
3294         }
3295     }
3296
3297   if (!enlargeU)
3298     {
3299       UU1 = UF1; UU2 = UF2;
3300     }
3301   if (!enlargeVfirst)
3302     VV1 = VF1;
3303   if (!enlargeVlast)
3304     VV2 = VF2;
3305
3306   MakeFace(S,UU1,UU2,VV1,VV2,isVV1degen,isVV2degen,BF);
3307   BF.Location(L);
3308 /*
3309   if (S->DynamicType() == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
3310     BRep_Builder B;
3311     //----------------------------------------------------------------
3312     // utile pour les bouchons on ne doit pas changer leur geometrie.
3313     // (Ce que fait BRepLib_MakeFace si S est restreinte).
3314     // On remet S et on update les pcurves.
3315     //----------------------------------------------------------------
3316     TopExp_Explorer exp;
3317     exp.Init(BF,TopAbs_EDGE);
3318     Standard_Real f=0.,l=0.;
3319     for (; exp.More(); exp.Next()) {
3320       TopoDS_Edge   CE  = TopoDS::Edge(exp.Current());
3321       Handle(Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(CE,BF,f,l); 
3322       B.UpdateEdge (CE,C2,S,L,BRep_Tool::Tolerance(CE));
3323     }    
3324     B.UpdateFace(BF,S,L,BRep_Tool::Tolerance(F)); 
3325   }
3326 */  
3327   if (SurfaceChange && UpdatePCurve) {
3328     TopoDS_Shape aLocalFace = F.Oriented(TopAbs_FORWARD);
3329     UpdatePCurves(TopoDS::Face(aLocalFace),BF);
3330     //UpdatePCurves(TopoDS::Face(F.Oriented(TopAbs_FORWARD)),BF);
3331     BRep_Builder BB;
3332     BB.UpdateFace( F, S, L, BRep_Tool::Tolerance(F) );
3333   }
3334
3335   BF.Orientation(F.Orientation());
3336   return SurfaceChange;
3337 }
3338
3339 //=======================================================================
3340 //function : TryParameter
3341 //purpose  : 
3342 //=======================================================================
3343
3344 static Standard_Boolean TryParameter (const TopoDS_Edge& OE,
3345                                       TopoDS_Vertex&     V,
3346                                       const TopoDS_Edge& NE,
3347                                       Standard_Real      TolConf)
3348 {
3349   BRepAdaptor_Curve OC(OE);
3350   BRepAdaptor_Curve NC(NE);
3351   Standard_Real Of = OC.FirstParameter(); Standard_Real Ol = OC.LastParameter();
3352   Standard_Real Nf = NC.FirstParameter(); Standard_Real Nl = NC.LastParameter();
3353   Standard_Real U = 0.;
3354   gp_Pnt           P  = BRep_Tool::Pnt(V);
3355   Standard_Boolean OK = Standard_False;
3356
3357   if (P.Distance(OC.Value(Of)) < TolConf) {
3358     if (Of > Nf && Of < Nl  && P.Distance(NC.Value(Of)) < TolConf) {
3359       OK = Standard_True;
3360       U    = Of;
3361     }
3362   }
3363   if (P.Distance(OC.Value(Ol)) < TolConf) {
3364     if (Ol > Nf && Ol < Nl  && P.Distance(NC.Value(Ol)) < TolConf) {
3365       OK = Standard_True;
3366       U    = Ol;
3367     }
3368   }
3369   if (OK) {
3370     BRep_Builder B;
3371     TopoDS_Shape aLocalShape = NE.Oriented(TopAbs_FORWARD);
3372     TopoDS_Edge EE = TopoDS::Edge(aLocalShape);
3373 //    TopoDS_Edge EE = TopoDS::Edge(NE.Oriented(TopAbs_FORWARD));
3374     aLocalShape = V.Oriented(TopAbs_INTERNAL);
3375     B.UpdateVertex(TopoDS::Vertex(aLocalShape),
3376                    U,NE,BRep_Tool::Tolerance(NE));
3377 //    B.UpdateVertex(TopoDS::Vertex(V.Oriented(TopAbs_INTERNAL)),
3378 //                 U,NE,BRep_Tool::Tolerance(NE));
3379   }
3380   return OK;  
3381 }
3382
3383 //=======================================================================
3384 //function : 
3385 //purpose  : 
3386 //=======================================================================
3387
3388 void BRepOffset_Tool::MapVertexEdges (const TopoDS_Shape& S,
3389                                       TopTools_DataMapOfShapeListOfShape& MEV)
3390 {
3391   TopExp_Explorer      exp;
3392   exp.Init(S.Oriented(TopAbs_FORWARD),TopAbs_EDGE);
3393   TopTools_MapOfShape  DejaVu;
3394   for ( ; exp.More(); exp.Next()) {
3395     const TopoDS_Edge& E = TopoDS::Edge(exp.Current());
3396     if (DejaVu.Add(E)) {
3397       TopoDS_Vertex     V1,V2;
3398       TopExp::Vertices (E,V1,V2);
3399       if (!MEV.IsBound(V1)) {
3400         TopTools_ListOfShape empty;
3401         MEV.Bind(V1,empty);
3402       }
3403       MEV(V1).Append(E);
3404       if (!V1.IsSame(V2)) {
3405         if (!MEV.IsBound(V2)) {
3406           TopTools_ListOfShape empty;
3407           MEV.Bind(V2,empty);
3408         }
3409         MEV(V2).Append(E);
3410       }
3411     }
3412   }
3413 }
3414
3415 //=======================================================================
3416 //function : 
3417 //purpose  : 
3418 //=======================================================================
3419
3420 void BRepOffset_Tool::BuildNeighbour (const TopoDS_Wire& W,
3421                                       const TopoDS_Face& F,
3422                                       TopTools_DataMapOfShapeShape& NOnV1,
3423                                       TopTools_DataMapOfShapeShape& NOnV2)
3424 {
3425   TopoDS_Vertex V1,V2,VP1,VP2,FV1,FV2;
3426   TopoDS_Edge   CurE,FirstE,PrecE;
3427   BRepTools_WireExplorer         wexp;
3428   
3429   TopoDS_Shape aLocalFace = F.Oriented(TopAbs_FORWARD);
3430   TopoDS_Shape aLocalWire = W.Oriented(TopAbs_FORWARD);
3431   wexp.Init(TopoDS::Wire(aLocalWire),TopoDS::Face(aLocalFace));
3432 //  wexp.Init(TopoDS::Wire(W.Oriented(TopAbs_FORWARD)),
3433 //          TopoDS::Face(F.Oriented(TopAbs_FORWARD)));
3434   CurE = FirstE = PrecE = wexp.Current();
3435   TopExp::Vertices(CurE,V1,V2);
3436   FV1 = VP1 = V1; FV2 = VP2 = V2;
3437   wexp.Next();
3438   while (wexp.More()) {
3439     CurE = wexp.Current();
3440     TopExp::Vertices(CurE,V1,V2);