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