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