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