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