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