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